Skip to content

Commit 9995912

Browse files
Make sequence form a private implementation detail of behaviour support (#595)
This moves the sequence form implementation as an implementation detail of the behaviour support. This is the first step in a refactoring of the sequence form to integrate it within the game representation classes.
1 parent b00d64e commit 9995912

File tree

7 files changed

+151
-23
lines changed

7 files changed

+151
-23
lines changed

Makefile.am

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,9 @@ agg_SOURCES = \
285285

286286
game_SOURCES = \
287287
src/gambit.h \
288+
src/games/gameseq.cc \
289+
src/games/gameseq.h \
290+
src/games/ndarray.h \
288291
src/games/number.h \
289292
src/games/gameobject.h \
290293
src/games/game.cc \
@@ -398,9 +401,6 @@ gambit_nashsupport_SOURCES = \
398401

399402
gambit_enumpoly_SOURCES = \
400403
${core_SOURCES} ${game_SOURCES} ${gambit_nashsupport_SOURCES} \
401-
src/solvers/enumpoly/ndarray.h \
402-
src/solvers/enumpoly/gameseq.cc \
403-
src/solvers/enumpoly/gameseq.h \
404404
src/solvers/enumpoly/indexproduct.h \
405405
src/solvers/enumpoly/rectangle.h \
406406
src/solvers/enumpoly/poly.cc \

src/games/behavspt.cc

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
//
2222

2323
#include "gambit.h"
24+
#include "gameseq.h"
2425

2526
namespace Gambit {
2627

@@ -259,4 +260,55 @@ std::list<GameNode> BehaviorSupportProfile::GetMembers(const GameInfoset &p_info
259260
return answer;
260261
}
261262

263+
//========================================================================
264+
// BehaviorSupportProfile: Sequence form
265+
//========================================================================
266+
267+
std::shared_ptr<GameSequenceForm> BehaviorSupportProfile::GetSequenceForm() const
268+
{
269+
if (!m_sequenceForm) {
270+
m_sequenceForm = std::make_shared<GameSequenceForm>(*this);
271+
}
272+
return m_sequenceForm;
273+
}
274+
275+
SequencesWrapper BehaviorSupportProfile::GetSequences() const
276+
{
277+
return SequencesWrapper(GetSequenceForm()->GetSequences());
278+
}
279+
280+
PlayerSequencesWrapper BehaviorSupportProfile::GetSequences(GamePlayer &p_player) const
281+
{
282+
return PlayerSequencesWrapper(GetSequenceForm()->GetSequences(p_player));
283+
}
284+
285+
int BehaviorSupportProfile::GetConstraintEntry(const GameInfoset &p_infoset,
286+
const GameAction &p_action) const
287+
{
288+
return GetSequenceForm()->GetConstraintEntry(p_infoset, p_action);
289+
}
290+
291+
const Rational &BehaviorSupportProfile::GetPayoff(
292+
const std::map<GamePlayer, std::shared_ptr<GameSequenceRep>> &p_profile,
293+
const GamePlayer &p_player) const
294+
{
295+
return GetSequenceForm()->GetPayoff(p_profile, p_player);
296+
}
297+
298+
MixedBehaviorProfile<double> BehaviorSupportProfile::ToMixedBehaviorProfile(
299+
const std::map<std::shared_ptr<GameSequenceRep>, double> &p_profile) const
300+
{
301+
return GetSequenceForm()->ToMixedBehaviorProfile(p_profile);
302+
}
303+
304+
InfosetsWrapper BehaviorSupportProfile::GetInfosets() const
305+
{
306+
return InfosetsWrapper(GetSequenceForm()->GetInfosets());
307+
}
308+
309+
ContingenciesWrapper BehaviorSupportProfile::GetContingencies() const
310+
{
311+
return ContingenciesWrapper(GetSequenceForm()->GetContingencies());
312+
}
313+
262314
} // end namespace Gambit

src/games/behavspt.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@
2929

3030
namespace Gambit {
3131

32+
class GameSequenceForm;
33+
class GameSequenceRep;
34+
class SequencesWrapper;
35+
class PlayerSequencesWrapper;
36+
class InfosetsWrapper;
37+
class ContingenciesWrapper;
38+
3239
/// This class represents a subset of the actions in an extensive game.
3340
/// It is enforced that each player has at least one action at each
3441
/// information set; thus, the actions in a support can be viewed as
@@ -139,6 +146,20 @@ class BehaviorSupportProfile {
139146
/// Returns a copy of the support with dominated actions eliminated
140147
BehaviorSupportProfile Undominated(bool p_strict) const;
141148
//@}
149+
150+
mutable std::shared_ptr<GameSequenceForm> m_sequenceForm;
151+
std::shared_ptr<GameSequenceForm> GetSequenceForm() const;
152+
SequencesWrapper GetSequences() const;
153+
PlayerSequencesWrapper GetSequences(GamePlayer &p_player) const;
154+
int GetConstraintEntry(const GameInfoset &p_infoset, const GameAction &p_action) const;
155+
const Rational &
156+
GetPayoff(const std::map<GamePlayer, std::shared_ptr<GameSequenceRep>> &p_profile,
157+
const GamePlayer &p_player) const;
158+
GameRep::Players GetPlayers() const { return GetGame()->GetPlayers(); }
159+
MixedBehaviorProfile<double>
160+
ToMixedBehaviorProfile(const std::map<std::shared_ptr<GameSequenceRep>, double> &) const;
161+
InfosetsWrapper GetInfosets() const;
162+
ContingenciesWrapper GetContingencies() const;
142163
};
143164

144165
} // end namespace Gambit
Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
namespace Gambit {
3030

31-
struct GameSequenceRep {
31+
class GameSequenceRep {
3232
public:
3333
GamePlayer player;
3434
GameAction action;
@@ -293,6 +293,61 @@ class GameSequenceForm {
293293
ToMixedBehaviorProfile(const std::map<GameSequence, double> &) const;
294294
};
295295

296+
class SequencesWrapper {
297+
public:
298+
explicit SequencesWrapper(const GameSequenceForm::Sequences &sequences) : m_sequences(sequences)
299+
{
300+
}
301+
302+
auto begin() const { return m_sequences.begin(); }
303+
auto end() const { return m_sequences.end(); }
304+
305+
std::size_t size() const { return m_sequences.size(); }
306+
307+
private:
308+
GameSequenceForm::Sequences m_sequences;
309+
};
310+
311+
class PlayerSequencesWrapper {
312+
public:
313+
explicit PlayerSequencesWrapper(const GameSequenceForm::PlayerSequences &sequences)
314+
: m_sequences(sequences)
315+
{
316+
}
317+
318+
auto begin() const { return m_sequences.begin(); }
319+
auto end() const { return m_sequences.end(); }
320+
321+
std::size_t size() const { return m_sequences.size(); }
322+
323+
private:
324+
GameSequenceForm::PlayerSequences m_sequences;
325+
};
326+
327+
class InfosetsWrapper {
328+
public:
329+
explicit InfosetsWrapper(const GameSequenceForm::Infosets &infosets) : m_infosets(infosets) {}
330+
331+
std::size_t size() const { return m_infosets.size(); }
332+
333+
private:
334+
GameSequenceForm::Infosets m_infosets;
335+
};
336+
337+
class ContingenciesWrapper {
338+
public:
339+
explicit ContingenciesWrapper(const GameSequenceForm::Contingencies &contingencies)
340+
: m_contingencies(contingencies)
341+
{
342+
}
343+
344+
auto begin() { return m_contingencies.begin(); }
345+
auto end() { return m_contingencies.end(); }
346+
347+
private:
348+
GameSequenceForm::Contingencies m_contingencies;
349+
};
350+
296351
} // end namespace Gambit
297352

298353
#endif // GAMESEQ_H

src/solvers/enumpoly/efgpoly.cc

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
#include "enumpoly.h"
2424
#include "solvers/nashsupport/nashsupport.h"
25-
#include "gameseq.h"
25+
#include "games/gameseq.h"
2626
#include "polysystem.h"
2727
#include "polysolver.h"
2828
#include "behavextend.h"
@@ -48,7 +48,7 @@ namespace {
4848

4949
class ProblemData {
5050
public:
51-
GameSequenceForm sfg;
51+
BehaviorSupportProfile m_support;
5252
std::shared_ptr<VariableSpace> space;
5353
std::map<GameSequence, int> var;
5454
std::map<GameSequence, Polynomial<double>> variables;
@@ -62,36 +62,36 @@ Polynomial<double> BuildSequenceVariable(ProblemData &p_data, const GameSequence
6262
if (!p_sequence->action) {
6363
return {p_data.space, 1};
6464
}
65-
if (p_sequence->action != p_data.sfg.GetSupport().GetActions(p_sequence->GetInfoset()).back()) {
65+
if (p_sequence->action != p_data.m_support.GetActions(p_sequence->GetInfoset()).back()) {
6666
return {p_data.space, var.at(p_sequence), 1};
6767
}
6868

6969
Polynomial<double> equation(p_data.space);
70-
for (auto seq : p_data.sfg.GetSequences(p_sequence->player)) {
70+
for (auto seq : p_data.m_support.GetSequences(p_sequence->player)) {
7171
if (seq == p_sequence) {
7272
continue;
7373
}
7474
if (const int constraint_coef =
75-
p_data.sfg.GetConstraintEntry(p_sequence->GetInfoset(), seq->action)) {
75+
p_data.m_support.GetConstraintEntry(p_sequence->GetInfoset(), seq->action)) {
7676
equation += BuildSequenceVariable(p_data, seq, var) * double(constraint_coef);
7777
}
7878
}
7979
return equation;
8080
}
8181

8282
ProblemData::ProblemData(const BehaviorSupportProfile &p_support)
83-
: sfg(p_support),
84-
space(std::make_shared<VariableSpace>(sfg.GetSequences().size() - sfg.GetInfosets().size() -
85-
sfg.GetPlayers().size()))
83+
: m_support(p_support), space(std::make_shared<VariableSpace>(m_support.GetSequences().size() -
84+
m_support.GetInfosets().size() -
85+
m_support.GetPlayers().size()))
8686
{
87-
for (auto sequence : sfg.GetSequences()) {
87+
for (auto sequence : m_support.GetSequences()) {
8888
if (sequence->action &&
8989
(sequence->action != p_support.GetActions(sequence->GetInfoset()).back())) {
9090
var[sequence] = var.size() + 1;
9191
}
9292
}
9393

94-
for (auto sequence : sfg.GetSequences()) {
94+
for (auto sequence : m_support.GetSequences()) {
9595
variables.emplace(sequence, BuildSequenceVariable(*this, sequence, var));
9696
}
9797
}
@@ -100,11 +100,11 @@ Polynomial<double> GetPayoff(ProblemData &p_data, const GamePlayer &p_player)
100100
{
101101
Polynomial<double> equation(p_data.space);
102102

103-
for (auto profile : p_data.sfg.GetContingencies()) {
104-
auto pay = p_data.sfg.GetPayoff(profile, p_player);
103+
for (auto profile : p_data.m_support.GetContingencies()) {
104+
auto pay = p_data.m_support.GetPayoff(profile, p_player);
105105
if (pay != Rational(0)) {
106106
Polynomial<double> term(p_data.space, double(pay));
107-
for (auto player : p_data.sfg.GetPlayers()) {
107+
for (auto player : p_data.m_support.GetPlayers()) {
108108
term *= p_data.variables.at(profile[player]);
109109
}
110110
equation += term;
@@ -115,9 +115,9 @@ Polynomial<double> GetPayoff(ProblemData &p_data, const GamePlayer &p_player)
115115

116116
void IndifferenceEquations(ProblemData &p_data, PolynomialSystem<double> &p_equations)
117117
{
118-
for (auto player : p_data.sfg.GetPlayers()) {
118+
for (auto player : p_data.m_support.GetPlayers()) {
119119
const Polynomial<double> payoff = GetPayoff(p_data, player);
120-
for (auto sequence : p_data.sfg.GetSequences(player)) {
120+
for (auto sequence : p_data.m_support.GetSequences(player)) {
121121
try {
122122
p_equations.push_back(payoff.PartialDerivative(p_data.var.at(sequence)));
123123
}
@@ -131,11 +131,11 @@ void IndifferenceEquations(ProblemData &p_data, PolynomialSystem<double> &p_equa
131131

132132
void LastActionProbPositiveInequalities(ProblemData &p_data, PolynomialSystem<double> &p_equations)
133133
{
134-
for (auto sequence : p_data.sfg.GetSequences()) {
134+
for (auto sequence : p_data.m_support.GetSequences()) {
135135
if (!sequence->action) {
136136
continue;
137137
}
138-
const auto &actions = p_data.sfg.GetSupport().GetActions(sequence->action->GetInfoset());
138+
const auto &actions = p_data.m_support.GetActions(sequence->action->GetInfoset());
139139
if (actions.size() > 1 && sequence->action == actions.back()) {
140140
p_equations.push_back(p_data.variables.at(sequence));
141141
}
@@ -145,7 +145,7 @@ void LastActionProbPositiveInequalities(ProblemData &p_data, PolynomialSystem<do
145145
std::map<GameSequence, double> ToSequenceProbs(const ProblemData &p_data, const Vector<double> &v)
146146
{
147147
std::map<GameSequence, double> x;
148-
for (auto sequence : p_data.sfg.GetSequences()) {
148+
for (auto sequence : p_data.m_support.GetSequences()) {
149149
x[sequence] = p_data.variables.at(sequence).Evaluate(v);
150150
}
151151
return x;
@@ -181,7 +181,7 @@ std::list<MixedBehaviorProfile<double>> SolveSupport(const BehaviorSupportProfil
181181
std::list<MixedBehaviorProfile<double>> solutions;
182182
for (auto root : roots) {
183183
const MixedBehaviorProfile<double> sol(
184-
data.sfg.ToMixedBehaviorProfile(ToSequenceProbs(data, root)));
184+
data.m_support.ToMixedBehaviorProfile(ToSequenceProbs(data, root)));
185185
if (ExtendsToNash(sol, BehaviorSupportProfile(sol.GetGame()),
186186
BehaviorSupportProfile(sol.GetGame()))) {
187187
solutions.push_back(sol);

0 commit comments

Comments
 (0)