noregret 0.0.0.dev5__tar.gz → 0.0.0.dev6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/PKG-INFO +2 -2
  2. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/README.rst +1 -1
  3. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/black_box.py +6 -8
  4. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/extensive_form/games.py +2 -2
  5. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/games.py +6 -4
  6. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/multilinear.py +1 -7
  7. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/normal_form/games.py +5 -2
  8. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/utilities.py +1 -0
  9. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/sequence_form_polytopes.py +2 -4
  10. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/solvers/regret_minimization.py +3 -0
  11. noregret-0.0.0.dev6/noregret/tests/test_games.py +182 -0
  12. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret.egg-info/PKG-INFO +2 -2
  13. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/setup.py +1 -1
  14. noregret-0.0.0.dev5/noregret/tests/test_games.py +0 -62
  15. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/LICENSE +0 -0
  16. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/__init__.py +0 -0
  17. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/__init__.py +0 -0
  18. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/extensive_form/__init__.py +0 -0
  19. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/normal_form/__init__.py +0 -0
  20. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/normal_form/assurance-game.json +0 -0
  21. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/normal_form/battle-of-the-sexes.json +0 -0
  22. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/normal_form/chicken.json +0 -0
  23. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/normal_form/gift-exchange-game.json +0 -0
  24. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/normal_form/matching-pennies.json +0 -0
  25. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/normal_form/prisoners-dilemma.json +0 -0
  26. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/normal_form/pure-coordination.json +0 -0
  27. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/normal_form/rock-paper-scissors-plus.json +0 -0
  28. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/normal_form/rock-paper-scissors.json +0 -0
  29. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/normal_form/rock-paper-superscissors.json +0 -0
  30. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/games/normal_form/stag-hunt.json +0 -0
  31. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/kernels.py +0 -0
  32. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/regret_minimizers/__init__.py +0 -0
  33. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/regret_minimizers/probability_simplices.py +0 -0
  34. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/regret_minimizers/regret_minimizers.py +0 -0
  35. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/regret_minimizers/sequence_form_polytopes.py +0 -0
  36. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/solvers/__init__.py +0 -0
  37. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/solvers/linear_programming.py +0 -0
  38. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/tests/__init__.py +0 -0
  39. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/tests/test_linear_programming.py +0 -0
  40. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/tests/test_regret_minimization.py +0 -0
  41. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/tests/test_sequence_form_polytopes.py +0 -0
  42. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret/utilities.py +0 -0
  43. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret.egg-info/SOURCES.txt +0 -0
  44. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret.egg-info/dependency_links.txt +0 -0
  45. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret.egg-info/requires.txt +0 -0
  46. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/noregret.egg-info/top_level.txt +0 -0
  47. {noregret-0.0.0.dev5 → noregret-0.0.0.dev6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: noregret
3
- Version: 0.0.0.dev5
3
+ Version: 0.0.0.dev6
4
4
  Summary: No-regret learning dynamics
5
5
  Home-page: https://github.com/uoftcprg/noregret
6
6
  Author: Universal, Open, Free, and Transparent Computer Poker Research Group
@@ -52,7 +52,7 @@ Dynamic: summary
52
52
  NoRegret
53
53
  ========
54
54
 
55
- NoRegret is an open-source software library for no-regret learning dynamics and computational game solving, developed by the Universal, Open, Free, and Transparent Computer Poker Research Group. NoRegret implements an extensive array of regret minimizers and game solvers, and also supports GPU-acceleration. The library can be used in a variety of use cases, from solving games to conducting research in online convex optimization. NoRegret's reliability has been established through extensive doctests and unit tests, achieving 91% code coverage.
55
+ NoRegret is an open-source software library for no-regret learning dynamics and computational game solving, developed by the Universal, Open, Free, and Transparent Computer Poker Research Group. NoRegret implements an extensive array of regret minimizers and game solvers, and also supports GPU-acceleration. The library can be used in a variety of use cases, from solving games to conducting research in online convex optimization. NoRegret's reliability has been established through extensive doctests and unit tests, achieving 95% code coverage.
56
56
 
57
57
  Features
58
58
  --------
@@ -2,7 +2,7 @@
2
2
  NoRegret
3
3
  ========
4
4
 
5
- NoRegret is an open-source software library for no-regret learning dynamics and computational game solving, developed by the Universal, Open, Free, and Transparent Computer Poker Research Group. NoRegret implements an extensive array of regret minimizers and game solvers, and also supports GPU-acceleration. The library can be used in a variety of use cases, from solving games to conducting research in online convex optimization. NoRegret's reliability has been established through extensive doctests and unit tests, achieving 91% code coverage.
5
+ NoRegret is an open-source software library for no-regret learning dynamics and computational game solving, developed by the Universal, Open, Free, and Transparent Computer Poker Research Group. NoRegret implements an extensive array of regret minimizers and game solvers, and also supports GPU-acceleration. The library can be used in a variety of use cases, from solving games to conducting research in online convex optimization. NoRegret's reliability has been established through extensive doctests and unit tests, achieving 95% code coverage.
6
6
 
7
7
  Features
8
8
  --------
@@ -85,11 +85,11 @@ class BlackBoxGame(ABC):
85
85
  """
86
86
 
87
87
  @abstractmethod
88
- def utility(self, player, node):
88
+ def utility(self, node, player):
89
89
  """Return the utility given a player and a node.
90
90
 
91
- :param player: Player.
92
91
  :param node: Node.
92
+ :param player: Player.
93
93
  :return: Utility.
94
94
  """
95
95
 
@@ -99,9 +99,7 @@ class BlackBoxGame(ABC):
99
99
  :param node: Node.
100
100
  :return: Utilities.
101
101
  """
102
- P = range(self.player_count)
103
-
104
- return list(map(self.utility(i, node) for i in P))
102
+ return list(map(partial(self.utility, node), range(self.player_count)))
105
103
 
106
104
  @abstractmethod
107
105
  def information_set(self, node):
@@ -128,7 +126,7 @@ class BlackBoxGame(ABC):
128
126
  """
129
127
  A = self.actions(node)
130
128
 
131
- return list(map(self.chance_probability(node, a) for a in A))
129
+ return list(map(partial(self.chance_probability, node), A))
132
130
 
133
131
 
134
132
  @dataclass
@@ -168,14 +166,14 @@ class _OpenSpielBlackBoxGame(BlackBoxGame):
168
166
  actions.append(node.action_to_string(a))
169
167
  children.append(node.child(a))
170
168
 
171
- return actions, children
169
+ return OrderedSet(actions), children
172
170
 
173
171
  def player(self, node):
174
172
  i = node.current_player()
175
173
 
176
174
  return None if i == -1 else i
177
175
 
178
- def utility(self, player, node):
176
+ def utility(self, node, player):
179
177
  return node.player_reward(player)
180
178
 
181
179
  def utilities(self, node):
@@ -122,12 +122,12 @@ class TwoPlayerExtensiveFormGame(TwoPlayerMultilinearGame, ExtensiveFormGame):
122
122
  def row_best_response_value(self, column_strategy):
123
123
  u = self.row_utility(column_strategy)
124
124
 
125
- return self.row_sequence_form_polytopes.best_response_value(u)
125
+ return self.row_sequence_form_polytope.best_response_value(u)
126
126
 
127
127
  def column_best_response_value(self, row_strategy):
128
128
  v = self.column_utility(row_strategy)
129
129
 
130
- return self.column_sequence_form_polytopes.best_response_value(v)
130
+ return self.column_sequence_form_polytope.best_response_value(v)
131
131
 
132
132
 
133
133
  @dataclass
@@ -98,12 +98,14 @@ class Game(ABC):
98
98
  :param strategy_profile: Strategy profile.
99
99
  :return: Nash gap.
100
100
  """
101
- expected_utilities = self.expected_utilities(strategy_profile)
102
- best_response_values = self.best_response_values(strategy_profile)
101
+ expected_utilities = self.expected_utilities(*strategy_profile)
102
+ best_response_values = self.best_response_values(*strategy_profile)
103
+ nash_gap = 0
103
104
 
104
- assert (best_response_values >= expected_utilities).all()
105
+ for u, u_prime in zip(best_response_values, expected_utilities):
106
+ assert u >= u_prime
105
107
 
106
- nash_gap = (best_response_values - expected_utilities).sum()
108
+ nash_gap += u - u_prime
107
109
 
108
110
  return nash_gap
109
111
 
@@ -122,12 +122,6 @@ class TwoPlayerMultilinearGame(TwoPlayerGame, MultilinearGame, ABC):
122
122
  def expected_column_utility(self, row_strategy, column_strategy):
123
123
  return row_strategy @ self.column_payoffs @ column_strategy
124
124
 
125
- def expected_utility(self, player, row_strategy, column_strategy):
126
- return row_strategy @ self.payoffs[player] @ column_strategy
127
-
128
- def expected_utilities(self, row_strategy, column_strategy):
129
- return row_strategy @ self.payoffs @ column_strategy
130
-
131
125
 
132
126
  @dataclass
133
127
  class TwoPlayerZeroSumMultilinearGame(
@@ -144,7 +138,7 @@ class TwoPlayerZeroSumMultilinearGame(
144
138
  def __post_init__(self):
145
139
  super(MultilinearGame, self).__post_init__()
146
140
 
147
- if self.payoffs.shape != (self.row_dimension, self.column_dimension):
141
+ if self.payoffs.shape != self.dimensions:
148
142
  raise ValueError('inconsistent dimensions')
149
143
 
150
144
  @property
@@ -90,10 +90,13 @@ class TwoPlayerNormalFormGame(TwoPlayerMultilinearGame, NormalFormGame):
90
90
  """
91
91
  return len(self.column_actions)
92
92
 
93
- def row_best_response_value(self, player, column_strategy):
93
+ def expected_utilities(self, row_strategy, column_strategy):
94
+ return row_strategy @ self.payoffs @ column_strategy
95
+
96
+ def row_best_response_value(self, column_strategy):
94
97
  return self.row_utility(column_strategy).max()
95
98
 
96
- def column_best_response_value(self, player, row_strategy):
99
+ def column_best_response_value(self, row_strategy):
97
100
  return self.column_utility(row_strategy).max()
98
101
 
99
102
 
@@ -1,3 +1,4 @@
1
+ """Module for utilities."""
1
2
  from collections import defaultdict
2
3
  from functools import partial, singledispatch
3
4
  from itertools import starmap
@@ -303,8 +303,7 @@ class SequenceFormPolytope:
303
303
 
304
304
  u = utility.copy()
305
305
 
306
- for L_R, L_A, L_B, L_C_B in zip(
307
- self._L_R[::-1],
306
+ for L_A, L_B, L_C_B in zip(
308
307
  self._L_A[::-1],
309
308
  self._L_B[::-1],
310
309
  self._L_C_B2[::-1],
@@ -328,8 +327,7 @@ class SequenceFormPolytope:
328
327
 
329
328
  u = utility.copy()
330
329
 
331
- for L_R, L_A, L_B, L_C_B in zip(
332
- self._L_R[::-1],
330
+ for L_A, L_B, L_C_B in zip(
333
331
  self._L_A[::-1],
334
332
  self._L_B[::-1],
335
333
  self._L_C_B2[::-1],
@@ -31,6 +31,9 @@ def regret_minimization(
31
31
  """
32
32
  np = game.kernel.numpy
33
33
 
34
+ if len(regret_minimizers) != game.player_count:
35
+ raise ValueError('inconsistent number of regret minimizers')
36
+
34
37
  def average_strategy_profile():
35
38
  average_strategy_profile = []
36
39
 
@@ -0,0 +1,182 @@
1
+ from abc import ABC, abstractmethod
2
+ from unittest import main, TestCase
3
+
4
+ import noregret as nr
5
+
6
+
7
+ class GameTestCaseMixin(ABC):
8
+ @abstractmethod
9
+ def uniform_strategy_profile(self, game):
10
+ pass
11
+
12
+ def test_equivalence(self):
13
+ np = self.KERNEL.numpy
14
+
15
+ for game in self.GAMES:
16
+ x, y = self.uniform_strategy_profile(game)
17
+
18
+ self.assertEqual(
19
+ nr.MultilinearGame.dimensions.fget(game),
20
+ game.dimensions,
21
+ )
22
+ np.testing.assert_allclose(
23
+ nr.Game.utilities(game, x, y),
24
+ game.utilities(x, y),
25
+ )
26
+ np.testing.assert_allclose(
27
+ nr.Game.expected_utilities(game, x, y),
28
+ game.expected_utilities(x, y),
29
+ )
30
+ np.testing.assert_allclose(
31
+ nr.Game.best_response_values(game, x, y),
32
+ game.best_response_values(x, y),
33
+ )
34
+ np.testing.assert_allclose(
35
+ nr.Game.nash_gap(game, x, y),
36
+ game.nash_gap(x, y),
37
+ )
38
+
39
+
40
+ class NormalFormGameTestCase(GameTestCaseMixin, TestCase):
41
+ KERNEL = nr.FloatingPointKernel()
42
+ GAMES = (
43
+ nr.AssuranceGame(KERNEL),
44
+ nr.BattleOfTheSexes(KERNEL),
45
+ nr.Chicken(KERNEL),
46
+ nr.GiftExchangeGame(KERNEL),
47
+ nr.MatchingPennies(KERNEL),
48
+ nr.PrisonersDilemma(KERNEL),
49
+ nr.PureCoordination(KERNEL),
50
+ nr.RockPaperScissors(KERNEL),
51
+ nr.RockPaperScissorsPlus(KERNEL),
52
+ nr.RockPaperSuperscissors(KERNEL),
53
+ nr.StagHunt(KERNEL),
54
+ )
55
+
56
+ def uniform_strategy_profile(self, game):
57
+ np = self.KERNEL.numpy
58
+ dtype = self.KERNEL.data_type
59
+
60
+ for n in game.dimensions:
61
+ yield np.full(n, 1 / n, dtype)
62
+
63
+ def test_best_response_value(self):
64
+ np = self.KERNEL.numpy
65
+
66
+ for game in self.GAMES:
67
+ x, y = self.uniform_strategy_profile(game)
68
+
69
+ np.testing.assert_allclose(
70
+ nr.NFG.best_response_value(game, 0, y),
71
+ game.best_response_value(0, y),
72
+ )
73
+ np.testing.assert_allclose(
74
+ nr.NFG.best_response_value(game, 1, x),
75
+ game.best_response_value(1, x),
76
+ )
77
+
78
+ def test_serialization(self):
79
+ for game in self.GAMES:
80
+ raw_game = game.dumps()
81
+ game2 = type(game).loads(self.KERNEL, raw_game)
82
+ raw_game2 = game2.dumps()
83
+
84
+ self.assertEqual(raw_game, raw_game2)
85
+ self.assertTrue((game.payoffs == game2.payoffs).all())
86
+ self.assertEqual(game.actions, game2.actions)
87
+
88
+
89
+ class ExtensiveFormGameTestCase(GameTestCaseMixin, TestCase):
90
+ KERNEL = nr.FloatingPointKernel()
91
+ GAMES = (
92
+ nr.to_efg(nr.MatchingPennies(KERNEL)),
93
+ nr.to_efg(nr.RockPaperScissors(KERNEL)),
94
+ nr.to_efg(nr.RockPaperScissorsPlus(KERNEL)),
95
+ nr.to_efg(nr.RockPaperSuperscissors(KERNEL)),
96
+ nr.to_efg(KERNEL, nr.from_open_spiel('kuhn_poker')),
97
+ nr.to_efg(KERNEL, nr.from_open_spiel('leduc_poker')),
98
+ )
99
+
100
+ def uniform_strategy_profile(self, game):
101
+ for sfp in game.sequence_form_polytopes:
102
+ yield sfp.to_sequence_form(sfp.behavioral_form_uniform_strategy)
103
+
104
+ def test_best_response_value(self):
105
+ np = self.KERNEL.numpy
106
+
107
+ for game in self.GAMES:
108
+ x, y = self.uniform_strategy_profile(game)
109
+
110
+ np.testing.assert_allclose(
111
+ nr.EFG.best_response_value(game, 0, y),
112
+ game.best_response_value(0, y),
113
+ )
114
+ np.testing.assert_allclose(
115
+ nr.EFG.best_response_value(game, 1, x),
116
+ game.best_response_value(1, x),
117
+ )
118
+
119
+ def test_serialization(self):
120
+ for game in self.GAMES:
121
+ raw_game = game.dumps()
122
+ game2 = type(game).loads(self.KERNEL, raw_game)
123
+ raw_game2 = game2.dumps()
124
+
125
+ self.assertEqual(raw_game, raw_game2)
126
+ self.assertFalse((game.payoffs != game2.payoffs).count_nonzero())
127
+
128
+ for sfp, sfp2 in zip(
129
+ game.sequence_form_polytopes,
130
+ game2.sequence_form_polytopes,
131
+ ):
132
+ self.assertEqual(sfp.actions, sfp2.actions)
133
+ self.assertEqual(sfp.parent_sequences, sfp2.parent_sequences)
134
+
135
+
136
+ class BlackBoxGameTestCase(TestCase):
137
+ GAMES = nr.from_open_spiel('kuhn_poker'), nr.from_open_spiel('leduc_poker')
138
+
139
+ def test_actions_and_children(self):
140
+ for game in self.GAMES:
141
+ h = game.root_node
142
+ A = game.actions(h)
143
+ children = list(map(str, game.children(h)))
144
+ A_children = game.actions_and_children(h)
145
+
146
+ self.assertIsInstance(A_children, tuple)
147
+ self.assertEqual(len(A_children), 2)
148
+
149
+ A_children = A_children[0], list(map(str, A_children[1]))
150
+
151
+ self.assertEqual((A, children), A_children)
152
+
153
+ children2 = list(map(str, nr.BlackBoxGame.children(game, h)))
154
+ A_children2 = nr.BlackBoxGame.actions_and_children(game, h)
155
+
156
+ self.assertIsInstance(A_children, tuple)
157
+ self.assertEqual(len(A_children), 2)
158
+
159
+ A_children2 = A_children2[0], list(map(str, A_children2[1]))
160
+
161
+ self.assertEqual((A, children2), A_children2)
162
+ self.assertEqual(A_children, A_children2)
163
+
164
+ def test_utilities(self):
165
+ for game in self.GAMES:
166
+ h = game.root_node
167
+ us = game.utilities(h)
168
+ us2 = nr.BlackBoxGame.utilities(game, h)
169
+
170
+ self.assertEqual(us, us2)
171
+
172
+ def test_chance_probabilities(self):
173
+ for game in self.GAMES:
174
+ h = game.root_node
175
+ ps = game.chance_probabilities(h)
176
+ ps2 = nr.BlackBoxGame.chance_probabilities(game, h)
177
+
178
+ self.assertEqual(ps, ps2)
179
+
180
+
181
+ if __name__ == '__main__':
182
+ main() # pragma: no cover
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: noregret
3
- Version: 0.0.0.dev5
3
+ Version: 0.0.0.dev6
4
4
  Summary: No-regret learning dynamics
5
5
  Home-page: https://github.com/uoftcprg/noregret
6
6
  Author: Universal, Open, Free, and Transparent Computer Poker Research Group
@@ -52,7 +52,7 @@ Dynamic: summary
52
52
  NoRegret
53
53
  ========
54
54
 
55
- NoRegret is an open-source software library for no-regret learning dynamics and computational game solving, developed by the Universal, Open, Free, and Transparent Computer Poker Research Group. NoRegret implements an extensive array of regret minimizers and game solvers, and also supports GPU-acceleration. The library can be used in a variety of use cases, from solving games to conducting research in online convex optimization. NoRegret's reliability has been established through extensive doctests and unit tests, achieving 91% code coverage.
55
+ NoRegret is an open-source software library for no-regret learning dynamics and computational game solving, developed by the Universal, Open, Free, and Transparent Computer Poker Research Group. NoRegret implements an extensive array of regret minimizers and game solvers, and also supports GPU-acceleration. The library can be used in a variety of use cases, from solving games to conducting research in online convex optimization. NoRegret's reliability has been established through extensive doctests and unit tests, achieving 95% code coverage.
56
56
 
57
57
  Features
58
58
  --------
@@ -4,7 +4,7 @@ from setuptools import find_packages, setup
4
4
 
5
5
  setup(
6
6
  name='noregret',
7
- version='0.0.0.dev5',
7
+ version='0.0.0.dev6',
8
8
  description='No-regret learning dynamics',
9
9
  long_description=open('README.rst').read(),
10
10
  long_description_content_type='text/x-rst',
@@ -1,62 +0,0 @@
1
- from unittest import main, TestCase
2
-
3
- import noregret as nr
4
-
5
-
6
- class NormalFormGameTestCase(TestCase):
7
- KERNEL = nr.FloatingPointKernel()
8
- GAMES = (
9
- nr.AssuranceGame(KERNEL),
10
- nr.BattleOfTheSexes(KERNEL),
11
- nr.Chicken(KERNEL),
12
- nr.GiftExchangeGame(KERNEL),
13
- nr.MatchingPennies(KERNEL),
14
- nr.PrisonersDilemma(KERNEL),
15
- nr.PureCoordination(KERNEL),
16
- nr.RockPaperScissors(KERNEL),
17
- nr.RockPaperScissorsPlus(KERNEL),
18
- nr.RockPaperSuperscissors(KERNEL),
19
- nr.StagHunt(KERNEL),
20
- )
21
-
22
- def test_serialization(self):
23
- for game in self.GAMES:
24
- raw_game = game.dumps()
25
- game2 = type(game).loads(self.KERNEL, raw_game)
26
- raw_game2 = game2.dumps()
27
-
28
- self.assertEqual(raw_game, raw_game2)
29
- self.assertTrue((game.payoffs == game2.payoffs).all())
30
- self.assertEqual(game.actions, game2.actions)
31
-
32
-
33
- class ExtensiveFormGameTestCase(TestCase):
34
- KERNEL = nr.FloatingPointKernel()
35
- GAMES = (
36
- nr.to_efg(nr.MatchingPennies(KERNEL)),
37
- nr.to_efg(nr.RockPaperScissors(KERNEL)),
38
- nr.to_efg(nr.RockPaperScissorsPlus(KERNEL)),
39
- nr.to_efg(nr.RockPaperSuperscissors(KERNEL)),
40
- nr.to_efg(KERNEL, nr.from_open_spiel('kuhn_poker')),
41
- nr.to_efg(KERNEL, nr.from_open_spiel('leduc_poker')),
42
- )
43
-
44
- def test_serialization(self):
45
- for game in self.GAMES:
46
- raw_game = game.dumps()
47
- game2 = type(game).loads(self.KERNEL, raw_game)
48
- raw_game2 = game2.dumps()
49
-
50
- self.assertEqual(raw_game, raw_game2)
51
- self.assertFalse((game.payoffs != game2.payoffs).count_nonzero())
52
-
53
- for sfp, sfp2 in zip(
54
- game.sequence_form_polytopes,
55
- game2.sequence_form_polytopes,
56
- ):
57
- self.assertEqual(sfp.actions, sfp2.actions)
58
- self.assertEqual(sfp.parent_sequences, sfp2.parent_sequences)
59
-
60
-
61
- if __name__ == '__main__':
62
- main() # pragma: no cover
File without changes
File without changes