Skip to content

Commit 6dbc0d0

Browse files
authored
New tests for enumpure_solve in pure strategies and behaviors (#609)
This adds tests for `enumpure_solve` and `enumpure_agent_solve` which confirm that the profiles returned are in fact the expected equilibria, including cases in which there are pure-strategy agent-form equilibria which are not Nash.
1 parent da2ab3c commit 6dbc0d0

File tree

2 files changed

+124
-11
lines changed

2 files changed

+124
-11
lines changed

pyproject.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,14 @@ max-line-length = 99
7575
[tool.pytest.ini_options]
7676
addopts = "--strict-markers"
7777
markers = [
78+
"nash_enumpure_strategy: tests of enumpure_solve in pure strategies",
79+
"nash_enumpure_agent: tests of enumpure_solve in pure behaviors",
7880
"nash_enummixed_strategy: tests of enummixed_solve in mixed strategies",
79-
"nash_enumpoly_behavior: tests of enumpoly_solve in behavior strategies",
81+
"nash_enumpoly_behavior: tests of enumpoly_solve in mixed behaviors",
8082
"nash_lcp_strategy: tests of lcp_solve in mixed strategies",
81-
"nash_lcp_behavior: tests of lcp_solve in behavior strategies",
83+
"nash_lcp_behavior: tests of lcp_solve in mixed behaviors",
8284
"nash_lp_strategy: tests of lp_solve in mixed strategies",
83-
"nash_lp_behavior: tests of lp_solve in behavior strategies",
85+
"nash_lp_behavior: tests of lp_solve in mixed behaviors",
8486
"nash: all tests of Nash equilibrium solvers",
8587
"slow: all time-consuming tests",
8688
]

tests/test_nash.py

Lines changed: 119 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,127 @@
1616
TOL = 1e-13 # tolerance for floating point assertions
1717

1818

19-
def test_enumpure_strategy():
20-
"""Test calls of enumeration of pure strategies."""
21-
game = games.read_from_file("stripped_down_poker.efg")
22-
assert len(gbt.nash.enumpure_solve(game).equilibria) == 0
19+
@pytest.mark.nash
20+
@pytest.mark.nash_enumpure_strategy
21+
@pytest.mark.parametrize(
22+
"game,pure_strategy_prof_data",
23+
[
24+
# Zero-sum games
25+
(
26+
games.create_two_player_perfect_info_win_lose_efg(),
27+
[
28+
[[0, 0, 1, 0], [1, 0, 0]],
29+
[[0, 0, 1, 0], [0, 1, 0]],
30+
[[0, 0, 1, 0], [0, 0, 1]],
31+
]
32+
),
33+
(games.create_stripped_down_poker_efg(), []),
34+
# Non-zero-sum 2-player games
35+
(games.create_one_shot_trust_efg(), [[[0, 1], [0, 1]]]),
36+
(
37+
games.create_EFG_for_nxn_bimatrix_coordination_game(3),
38+
[
39+
[[1, 0, 0], [1, 0, 0]],
40+
[[0, 1, 0], [0, 1, 0]],
41+
[[0, 0, 1], [0, 0, 1]],
42+
],
43+
),
44+
(games.create_EFG_for_6x6_bimatrix_with_long_LH_paths_and_unique_eq(), []),
45+
# 3-player game
46+
(
47+
games.create_mixed_behav_game_efg(),
48+
[
49+
[[1, 0], [1, 0], [1, 0]],
50+
[[0, 1], [0, 1], [1, 0]],
51+
[[0, 1], [1, 0], [0, 1]],
52+
[[1, 0], [0, 1], [0, 1]],
53+
],
54+
),
55+
]
56+
)
57+
def test_enumpure_strategy(game: gbt.Game, pure_strategy_prof_data: list):
58+
"""Test calls of enumeration of pure strategy equilibria
59+
60+
Tests max regret being zero (internal consistency) and compares the computed sequence of
61+
pure strategy equilibria to a previosuly computed sequence (regression test)
62+
"""
63+
result = gbt.nash.enumpure_solve(game)
64+
assert len(result.equilibria) == len(pure_strategy_prof_data)
65+
for eq, exp in zip(result.equilibria, pure_strategy_prof_data, strict=True):
66+
assert eq.max_regret() == 0
67+
expected = game.mixed_strategy_profile(rational=True, data=exp)
68+
assert eq == expected
2369

2470

25-
def test_enumpure_agent():
26-
"""Test calls of enumeration of pure agent strategies."""
27-
game = games.read_from_file("stripped_down_poker.efg")
28-
assert len(gbt.nash.enumpure_agent_solve(game).equilibria) == 0
71+
@pytest.mark.nash
72+
@pytest.mark.nash_enumpure_agent
73+
@pytest.mark.parametrize(
74+
"game,pure_behav_prof_data",
75+
[
76+
#############################################################
77+
# Examples where Nash pure behaviors and agent-form pure equillibrium behaviors coincide
78+
#############################################################
79+
# Zero-sum games
80+
(
81+
games.create_two_player_perfect_info_win_lose_efg(),
82+
[
83+
[[[1, 0], [1, 0]], [[0, 1], [1, 0]]],
84+
[[[0, 1], [1, 0]], [[1, 0], [1, 0]]],
85+
[[[0, 1], [1, 0]], [[1, 0], [0, 1]]],
86+
[[[0, 1], [1, 0]], [[0, 1], [1, 0]]],
87+
[[[0, 1], [1, 0]], [[0, 1], [0, 1]]]
88+
]
89+
),
90+
(games.create_stripped_down_poker_efg(), []),
91+
# Non-zero-sum 2-player games
92+
(games.create_one_shot_trust_efg(), [[[[0, 1]], [[0, 1]]]]),
93+
(
94+
games.create_EFG_for_nxn_bimatrix_coordination_game(3),
95+
[
96+
[[[1, 0, 0]], [[1, 0, 0]]],
97+
[[[0, 1, 0]], [[0, 1, 0]]],
98+
[[[0, 0, 1]], [[0, 0, 1]]],
99+
],
100+
),
101+
(games.create_EFG_for_6x6_bimatrix_with_long_LH_paths_and_unique_eq(), []),
102+
# 3-player game
103+
(
104+
games.create_mixed_behav_game_efg(),
105+
[
106+
[[[1, 0]], [[1, 0]], [[1, 0]]],
107+
[[[1, 0]], [[0, 1]], [[0, 1]]],
108+
[[[0, 1]], [[1, 0]], [[0, 1]]],
109+
[[[0, 1]], [[0, 1]], [[1, 0]]],
110+
],
111+
),
112+
#############################################################
113+
# Examples where the are agent-form pure equillibrium behaviors that are not Nash eq
114+
#############################################################
115+
(
116+
games.read_from_file("myerson_fig_4_2.efg"),
117+
[
118+
[[[1, 0], [0, 1]], [[0, 1]]],
119+
[[[0, 1], [0, 1]], [[1, 0]]]
120+
]
121+
),
122+
]
123+
)
124+
def test_enumpure_agent(game: gbt.Game, pure_behav_prof_data: list):
125+
"""Test calls of enumeration of pure agent (behavior) equilibria
126+
127+
Tests agent max regret being zero (internal consistency) and compares the computed
128+
sequence of pure agent equilibria to a previosuly computed sequence (regression test)
129+
130+
This should include all Nash equilibria in pure behaviors, but may include further
131+
profiles that are not Nash equilibria
132+
133+
"""
134+
result = gbt.nash.enumpure_agent_solve(game)
135+
assert len(result.equilibria) == len(pure_behav_prof_data)
136+
for eq, exp in zip(result.equilibria, pure_behav_prof_data, strict=True):
137+
assert eq.agent_max_regret() == 0
138+
expected = game.mixed_behavior_profile(rational=True, data=exp)
139+
assert eq == expected
29140

30141

31142
def test_enummixed_double():

0 commit comments

Comments
 (0)