@@ -106,14 +106,20 @@ def test_enummixed_rational():
106106 # ),
107107 ],
108108)
109- def test_enumpoly_behavior_rational (
109+ def test_enumpoly_ordered_behavior_rational (
110110 game : gbt .Game , mixed_behav_prof_data : list , stop_after : typing .Union [None , int ]
111111):
112112 """Test calls of enumpoly for mixed behavior equilibria, rational precision,
113113 using max_regret (internal consistency); and comparison to a set of previously
114114 computed equilibria using this function (regression test).
115115 This set will be the full set of all computed equilibria if stop_after is None,
116116 else the first stop_after-many equilibria.
117+
118+ This is the "ordered" version where we test for the outputs coming in a specific
119+ order; this is also an "unordered" version that includes examples where the order
120+ could not be relied on even for repeated runs on the same system when on Windows
121+ (vis github actions)
122+
117123 """
118124 if stop_after :
119125 result = gbt .nash .enumpoly_solve (
@@ -133,6 +139,76 @@ def test_enumpoly_behavior_rational(
133139 assert abs (eq [p ][i ][a ] - expected [p ][i ][a ]) <= TOL
134140
135141
142+ @pytest .mark .nash
143+ @pytest .mark .nash_enumpoly_behavior
144+ @pytest .mark .parametrize (
145+ "game,mixed_behav_prof_data,stop_after" ,
146+ [
147+ # 3-player game
148+ (
149+ games .create_mixed_behav_game_efg (),
150+ [
151+ [[["2/5" , "3/5" ]], [["1/2" , "1/2" ]], [["1/3" , "2/3" ]]],
152+ [[["1/2" , "1/2" ]], [["2/5" , "3/5" ]], [["1/4" , "3/4" ]]],
153+ [[["1/2" , "1/2" ]], [["1/2" , "1/2" ]], [[1 , 0 ]]],
154+ [[["1/3" , "2/3" ]], [[1 , 0 ]], [["1/4" , "3/4" ]]],
155+ [[[1 , 0 ]], [[1 , 0 ]], [[1 , 0 ]]],
156+ [[[1 , 0 ]], [[0 , 1 ]], [[0 , 1 ]]],
157+ [[[0 , 1 ]], [["1/4" , "3/4" ]], [["1/3" , "2/3" ]]],
158+ [[[0 , 1 ]], [[1 , 0 ]], [[0 , 1 ]]],
159+ [[[0 , 1 ]], [[0 , 1 ]], [[1 , 0 ]]],
160+ ],
161+ 9 ,
162+ ),
163+ ],
164+ )
165+ def test_enumpoly_unordered_behavior_rational (
166+ game : gbt .Game , mixed_behav_prof_data : list , stop_after : typing .Union [None , int ]
167+ ):
168+ """Test calls of enumpoly for mixed behavior equilibria, rational precision,
169+ using max_regret (internal consistency); and comparison to a set of previously
170+ computed equilibria using this function (regression test).
171+
172+ This set will be the full set of all computed equilibria if stop_after is None,
173+ else the first stop_after-many equilibria.
174+
175+ This is the "unordered" version where we test for the outputs belong to a set
176+ of expected output; there is also an "unordered" that expects the outputs in a specific order.
177+
178+ In this unordered version, once something from the expected set is found it is removed,
179+ so we are checking for no duplicate outputs.
180+ """
181+ if stop_after :
182+ result = gbt .nash .enumpoly_solve (
183+ game , use_strategic = False , stop_after = stop_after , maxregret = 0.00001
184+ )
185+ assert len (result .equilibria ) == stop_after
186+ else :
187+ # compute all
188+ result = gbt .nash .enumpoly_solve (game , use_strategic = False )
189+
190+ assert len (result .equilibria ) == len (mixed_behav_prof_data )
191+
192+ def are_the_same (game , found , candidate ):
193+ for p in game .players :
194+ for i in p .infosets :
195+ for a in i .actions :
196+ if not abs (found [p ][i ][a ] - candidate [p ][i ][a ]) <= TOL :
197+ return False
198+ return True
199+
200+ for eq in result .equilibria :
201+ assert abs (eq .max_regret ()) <= TOL
202+ found = False
203+ for exp in mixed_behav_prof_data [:]:
204+ expected = game .mixed_behavior_profile (rational = True , data = exp )
205+ if are_the_same (game , eq , expected ):
206+ mixed_behav_prof_data .remove (exp )
207+ found = True
208+ break
209+ assert found
210+
211+
136212def test_lcp_strategy_double ():
137213 """Test calls of LCP for mixed strategy equilibria, floating-point."""
138214 game = games .read_from_file ("poker.efg" )
0 commit comments