Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
- Max regret is calculated correctly for strategy and behavior profiles on games with zero player
strategies or actions (is defined to be 0 trivially) (#904)
- Corrected calculation of total number of actions for a player in `pygambit` (#938)
- Corrected a regression in action graph games that left the internal data structure not fully initialised,
leading to segmentation faults.

### Changed
- Added a new welcome/landing window on launching the GUI without a game. This has the effect of
Expand Down
1 change: 1 addition & 0 deletions src/games/gameagg.cc
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ GameAGGRep::GameAGGRep(std::shared_ptr<agg::AGG> p_aggPtr) : aggPtr(p_aggPtr)
s->m_label = std::to_string(st++);
});
}
IndexStrategies();
}

Game GameAGGRep::Copy() const
Expand Down
1 change: 1 addition & 0 deletions src/games/gamebagg.cc
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ GameBAGGRep::GameBAGGRep(std::shared_ptr<agg::BAGG> _baggPtr)
});
}
}
IndexStrategies();
}

Game GameBAGGRep::Copy() const
Expand Down
3 changes: 2 additions & 1 deletion src/pygambit/gambit.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,8 @@ cdef extern from "games/game.h":
iterator begin() except +
iterator end() except +

int IsTree() except +
bool IsTree() except +
bool IsAgg() except +

string GetTitle() except +
void SetTitle(string) except +
Expand Down
4 changes: 2 additions & 2 deletions src/pygambit/game.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -972,8 +972,8 @@ class Game:
self.game.deref().GetPlayer(pl+1).deref().GetStrategy(st+1)
)

if self.is_tree:
return TreeGameOutcome.wrap(self.game, psp)
if self.is_tree or self.game.deref().IsAgg():
return DerivedGameOutcome.wrap(self.game, psp)
else:
outcome = Outcome.wrap(deref(deref(psp).deref()).GetOutcome())
if outcome.outcome != cython.cast(c_GameOutcome, NULL):
Expand Down
14 changes: 8 additions & 6 deletions src/pygambit/outcome.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,10 @@ class Outcome:


@cython.cclass
class TreeGameOutcome:
"""Represents an outcome in a strategic game derived from an extensive game."""
class DerivedGameOutcome:
"""Represents an outcome in a strategic game derived from a game in another representation.
Such outcomes are one-to-one with the set of pure strategy profiles.
"""
c_game = cython.declare(c_Game)
psp = cython.declare(shared_ptr[c_PureStrategyProfile])

Expand All @@ -136,8 +138,8 @@ class TreeGameOutcome:

@staticmethod
@cython.cfunc
def wrap(game: c_Game, psp: shared_ptr[c_PureStrategyProfile]) -> TreeGameOutcome:
obj: TreeGameOutcome = TreeGameOutcome.__new__(TreeGameOutcome)
def wrap(game: c_Game, psp: shared_ptr[c_PureStrategyProfile]) -> DerivedGameOutcome:
obj: DerivedGameOutcome = DerivedGameOutcome.__new__(DerivedGameOutcome)
obj.c_game = game
obj.psp = psp
return obj
Expand All @@ -152,8 +154,8 @@ class TreeGameOutcome:

def __eq__(self, other: typing.Any) -> bool:
return (
isinstance(other, TreeGameOutcome) and
deref(self.psp).deref() == deref(cython.cast(TreeGameOutcome, other).psp).deref()
isinstance(other, DerivedGameOutcome) and
deref(self.psp).deref() == deref(cython.cast(DerivedGameOutcome, other).psp).deref()
)

def __getitem__(self, player: Player | str) -> Rational:
Expand Down
4 changes: 4 additions & 0 deletions tests/games.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ def read_from_file(fn: str) -> gbt.Game:
return gbt.read_efg(pathlib.Path("tests/test_games") / fn)
elif fn.endswith(".nfg"):
return gbt.read_nfg(pathlib.Path("tests/test_games") / fn)
elif fn.endswith(".agg"):
return gbt.read_agg(pathlib.Path("tests/test_games") / fn)
elif fn.endswith(".bagg"):
return gbt.read_bagg(pathlib.Path("tests/test_games") / fn)
else:
raise ValueError(f"Unknown file extension in {fn}")

Expand Down
20 changes: 2 additions & 18 deletions tests/test_games/2x2.agg
Original file line number Diff line number Diff line change
@@ -1,20 +1,4 @@
#AGG
# Generated by GAMUT v1.0.1
# Random Symmetric Action Graph Game
# Game Parameter Values:
# Random seed: 1306765487422
# Cmd Line: -players 2 -actions 2 -g RandomSymmetricAGG -output SpecialOutput -random_params -f 2x2.agg
# Players: 2
# Actions: 2 2
# players: 2
# actions: [2]
# graph: RandomGraph
# graph_params: null
# Graph Params:
# { nodes: 2, edges: 4, sym_edges: false, reflex_ok: true }
# Players: 2
# Actions: [ 2 2 ]

#number of players:
2
#number of action nodes:
Expand Down Expand Up @@ -45,5 +29,5 @@
#now the payoff values: one row per action node.
#For each row: first, the type of the payoff format
#Then payoffs are given in lexicographical order of the input configurations
0 35.622809717175556 -3.7188980070375948
0 -10.180526107272556 95.1203958671928
0 35 -4
0 -10 95
34 changes: 34 additions & 0 deletions tests/test_games/2x2_small_payoffs.agg
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#AGG

#number of players:
2
#number of action nodes:
2
#number of func nodes:
0

#sizes of action sets:
2 2

#action sets:
0 1
0 1


#the action graph:
2 0 1
2 1 0

#the types of func nodes:
#0: sum
#1: existence
#2: highest
#3: lowest


#the payoffs:
#now the payoff values: one row per action node.
#For each row: first, the type of the payoff format
#Then payoffs are given in lexicographical order of the input configurations
0 4 -1
0 -2 5
211 changes: 211 additions & 0 deletions tests/test_games/Bayesian-Coffee-3-2-2-3.bagg
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
#BAGG
3
13
18
2 2 2
0.5 0.5
0.5 0.5
0.5 0.5
7 7
7 7
7 7
0 1 2 3 4 5 6
0 7 8 9 10 11 12
0 1 2 3 4 5 6
0 7 8 9 10 11 12
0 1 2 3 4 5 6
0 7 8 9 10 11 12
0
3 13 19 25
3 14 20 26
3 15 21 27
3 16 22 28
3 17 23 29
3 18 24 30
3 13 19 25
3 14 20 26
3 15 21 27
3 16 22 28
3 17 23 29
3 18 24 30
2 1 7
2 2 8
2 3 9
2 4 10
2 5 11
2 6 12
3 14 16 17
5 13 15 16 17 18
3 14 17 18
3 13 14 17
5 13 14 15 16 18
3 14 15 17
2 15 18
0
2 13 16
2 15 18
0
2 13 16

0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0

1
1
[ ] 89

1
10
[ 1 0 0 ] 94
[ 3 0 0 ] 61
[ 2 0 0 ] 35
[ 1 2 0 ] 29
[ 2 1 0 ] 58
[ 1 1 0 ] 98
[ 1 0 2 ] 38
[ 1 1 1 ] 43
[ 2 0 1 ] 35
[ 1 0 1 ] 58

1
6
[ 3 0 0 ] 68
[ 1 2 0 ] 65
[ 2 1 0 ] 31
[ 1 0 0 ] 11
[ 1 1 0 ] 34
[ 2 0 0 ] 58

1
10
[ 3 0 0 ] 96
[ 1 2 0 ] 79
[ 2 1 0 ] 86
[ 1 0 2 ] 55
[ 1 1 1 ] 79
[ 2 0 1 ] 24
[ 1 0 0 ] 37
[ 1 0 1 ] 36
[ 1 1 0 ] 99
[ 2 0 0 ] 90

1
10
[ 1 0 0 ] 9
[ 1 2 0 ] 38
[ 1 1 0 ] 27
[ 1 0 2 ] 50
[ 1 1 1 ] 41
[ 1 0 1 ] 96
[ 3 0 0 ] 74
[ 2 0 1 ] 82
[ 2 1 0 ] 75
[ 2 0 0 ] 99

1
6
[ 1 0 0 ] 55
[ 1 2 0 ] 70
[ 1 1 0 ] 46
[ 3 0 0 ] 15
[ 2 1 0 ] 60
[ 2 0 0 ] 29

1
10
[ 1 0 0 ] 81
[ 1 0 2 ] 23
[ 1 0 1 ] 63
[ 1 2 0 ] 54
[ 1 1 1 ] 60
[ 1 1 0 ] 0
[ 3 0 0 ] 71
[ 2 1 0 ] 14
[ 2 0 1 ] 78
[ 2 0 0 ] 37

1
10
[ 1 0 0 ] 3
[ 3 0 0 ] 30
[ 2 0 0 ] 7
[ 1 2 0 ] 85
[ 2 1 0 ] 35
[ 1 1 0 ] 26
[ 1 0 2 ] 41
[ 1 1 1 ] 52
[ 2 0 1 ] 79
[ 1 0 1 ] 48

1
6
[ 3 0 0 ] 48
[ 1 2 0 ] 58
[ 2 1 0 ] 58
[ 1 0 0 ] 79
[ 1 1 0 ] 5
[ 2 0 0 ] 3

1
10
[ 3 0 0 ] 53
[ 1 2 0 ] 81
[ 2 1 0 ] 1
[ 1 0 2 ] 79
[ 1 1 1 ] 34
[ 2 0 1 ] 90
[ 1 0 0 ] 21
[ 1 0 1 ] 86
[ 1 1 0 ] 38
[ 2 0 0 ] 70

1
10
[ 3 0 0 ] 82
[ 1 0 2 ] 72
[ 2 0 1 ] 77
[ 1 2 0 ] 16
[ 1 1 1 ] 64
[ 2 1 0 ] 33
[ 1 0 0 ] 83
[ 1 1 0 ] 75
[ 1 0 1 ] 51
[ 2 0 0 ] 16

1
6
[ 3 0 0 ] 43
[ 1 2 0 ] 84
[ 2 1 0 ] 0
[ 1 0 0 ] 20
[ 1 1 0 ] 87
[ 2 0 0 ] 73

1
10
[ 3 0 0 ] 7
[ 1 2 0 ] 46
[ 2 1 0 ] 13
[ 1 0 2 ] 46
[ 1 1 1 ] 59
[ 2 0 1 ] 26
[ 1 0 0 ] 68
[ 1 0 1 ] 67
[ 1 1 0 ] 87
[ 2 0 0 ] 78
Loading
Loading