diff --git a/src/sage/game_theory/gambit_docs.py b/src/sage/game_theory/gambit_docs.py index fae37766c96..b2d8af991e9 100644 --- a/src/sage/game_theory/gambit_docs.py +++ b/src/sage/game_theory/gambit_docs.py @@ -115,18 +115,19 @@ converted to Python integers (due to the preparser). Here is an example showing the Battle of the Sexes:: - sage: import gambit # optional - gambit - sage: g = gambit.Game.new_table([2,2]) # optional - gambit - sage: g[int(0), int(0)][int(0)] = int(2) # optional - gambit - sage: g[int(0), int(0)][int(1)] = int(1) # optional - gambit - sage: g[int(0), int(1)][int(0)] = int(0) # optional - gambit - sage: g[int(0), int(1)][int(1)] = int(0) # optional - gambit - sage: g[int(1), int(0)][int(0)] = int(0) # optional - gambit - sage: g[int(1), int(0)][int(1)] = int(0) # optional - gambit - sage: g[int(1), int(1)][int(0)] = int(1) # optional - gambit - sage: g[int(1), int(1)][int(1)] = int(2) # optional - gambit - sage: solver = gambit.nash.ExternalLCPSolver() # optional - gambit - sage: solver.solve(g) # optional - gambit + sage: # optional - gambit + sage: import gambit + sage: g = gambit.Game.new_table([2,2]) + sage: g[int(0), int(0)][int(0)] = int(2) + sage: g[int(0), int(0)][int(1)] = int(1) + sage: g[int(0), int(1)][int(0)] = int(0) + sage: g[int(0), int(1)][int(1)] = int(0) + sage: g[int(1), int(0)][int(0)] = int(0) + sage: g[int(1), int(0)][int(1)] = int(0) + sage: g[int(1), int(1)][int(0)] = int(1) + sage: g[int(1), int(1)][int(1)] = int(2) + sage: solver = gambit.nash.ExternalLCPSolver() + sage: solver.solve(g) [, , ] diff --git a/src/sage/game_theory/normal_form_game.py b/src/sage/game_theory/normal_form_game.py index 811e00aec62..275907d7276 100644 --- a/src/sage/game_theory/normal_form_game.py +++ b/src/sage/game_theory/normal_form_game.py @@ -72,7 +72,8 @@ sage: B = matrix([[2, 1], [0, 3]]) sage: battle_of_the_sexes = NormalFormGame([A, B]) sage: battle_of_the_sexes - Normal Form Game with the following utilities: {(0, 0): [3, 2], (0, 1): [1, 1], (1, 0): [0, 0], (1, 1): [2, 3]} + Normal Form Game with the following utilities: {(0, 0): [3, 2], + (0, 1): [1, 1], (1, 0): [0, 0], (1, 1): [2, 3]} To obtain the Nash equilibria we run the ``obtain_nash()`` method. In the first few examples, we will use the 'support enumeration' algorithm. @@ -159,8 +160,10 @@ sage: y = var('y') sage: A = matrix([[1, -1], [-1, 1]]) - sage: p = plot((A * vector([y, 1 - y]))[0], y, 0, 1, color='blue', legend_label='$u_1(r_1, (y, 1-y))$', axes_labels=['$y$', '']) - sage: p += plot((A * vector([y, 1 - y]))[1], y, 0, 1, color='red', legend_label='$u_1(r_2, (y, 1-y))$'); p + sage: p = plot((A * vector([y, 1 - y]))[0], y, 0, 1, color='blue', + ....: legend_label='$u_1(r_1, (y, 1-y))$', axes_labels=['$y$', '']) + sage: p += plot((A * vector([y, 1 - y]))[1], y, 0, 1, color='red', + ....: legend_label='$u_1(r_2, (y, 1-y))$'); p Graphics object consisting of 2 graphics primitives We see that the only point at which player 1 is indifferent amongst @@ -281,7 +284,8 @@ sage: f[1,1][0] = 4 sage: f[1,1][1] = 4 sage: f - Normal Form Game with the following utilities: {(0, 0): [1, 3], (0, 1): [2, 3], (1, 0): [3, 1], (1, 1): [4, 4]} + Normal Form Game with the following utilities: {(0, 0): [1, 3], + (0, 1): [2, 3], (1, 0): [3, 1], (1, 1): [4, 4]} Once this game is constructed we can view the payoff matrices and solve the game:: @@ -401,7 +405,9 @@ sage: threegame.obtain_nash() Traceback (most recent call last): ... - NotImplementedError: Nash equilibrium for games with more than 2 players have not been implemented yet. Please see the gambit website (http://gambit.sourceforge.net/) that has a variety of available algorithms + NotImplementedError: Nash equilibrium for games with more than 2 players + have not been implemented yet. Please see the gambit website + (http://gambit.sourceforge.net/) that has a variety of available algorithms There are however a variety of such algorithms available in gambit, further compatibility between Sage and gambit is actively being developed: @@ -424,18 +430,18 @@ It is also possible to generate a Normal form game from a gambit Game:: - sage: from gambit import Game # optional - gambit - sage: gambitgame= Game.new_table([2, 2]) # optional - gambit - sage: gambitgame[int(0), int(0)][int(0)] = int(8) # optional - gambit - sage: gambitgame[int(0), int(0)][int(1)] = int(8) # optional - gambit - sage: gambitgame[int(0), int(1)][int(0)] = int(2) # optional - gambit - sage: gambitgame[int(0), int(1)][int(1)] = int(10) # optional - gambit - sage: gambitgame[int(1), int(0)][int(0)] = int(10) # optional - gambit - sage: gambitgame[int(1), int(0)][int(1)] = int(2) # optional - gambit - sage: gambitgame[int(1), int(1)][int(0)] = int(5) # optional - gambit - sage: gambitgame[int(1), int(1)][int(1)] = int(5) # optional - gambit - sage: g = NormalFormGame(gambitgame) # optional - gambit - sage: g # optional - gambit + sage: # optional - gambit + sage: from gambit import Game + sage: gambitgame= Game.new_table([2, 2]) + sage: gambitgame[int(0), int(0)][int(0)] = int(8) + sage: gambitgame[int(0), int(0)][int(1)] = int(8) + sage: gambitgame[int(0), int(1)][int(0)] = int(2) + sage: gambitgame[int(0), int(1)][int(1)] = int(10) + sage: gambitgame[int(1), int(0)][int(0)] = int(10) + sage: gambitgame[int(1), int(0)][int(1)] = int(2) + sage: gambitgame[int(1), int(1)][int(0)] = int(5) + sage: gambitgame[int(1), int(1)][int(1)] = int(5) + sage: g = NormalFormGame(gambitgame); g Normal Form Game with the following utilities: {(0, 0): [8.0, 8.0], (0, 1): [2.0, 10.0], (1, 0): [10.0, 2.0], @@ -476,9 +482,9 @@ sage: B = matrix([[min(i,j) + 2 * sign(i-j) for j in range(K, 1, -1)] ....: for i in range(K, 1, -1)]) sage: g = NormalFormGame([A, B]) - sage: g.obtain_nash(algorithm='lrs') # optional - lrslib + sage: g.obtain_nash(algorithm='lrs') # optional - lrslib [[(0, 0, 0, 0, 0, 0, 0, 0, 1), (0, 0, 0, 0, 0, 0, 0, 0, 1)]] - sage: g.obtain_nash(algorithm='LCP') # optional - gambit + sage: g.obtain_nash(algorithm='LCP') # optional - gambit [[(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0), (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0)]] @@ -564,9 +570,9 @@ sage: A = matrix([[3,3],[2,5],[0,6]]) sage: B = matrix([[3,3],[2,6],[3,1]]) sage: degenerate_game = NormalFormGame([A,B]) - sage: degenerate_game.obtain_nash(algorithm='lrs') # random, optional - lrslib + sage: degenerate_game.obtain_nash(algorithm='lrs') # random, optional - lrslib [[(0, 1/3, 2/3), (1/3, 2/3)], [(1, 0, 0), (1/2, 3)], [(1, 0, 0), (1, 3)]] - sage: degenerate_game.obtain_nash(algorithm='LCP') # optional - gambit + sage: degenerate_game.obtain_nash(algorithm='LCP') # optional - gambit [[(0.0, 0.3333333333, 0.6666666667), (0.3333333333, 0.6666666667)], [(1.0, -0.0, 0.0), (0.6666666667, 0.3333333333)], [(1.0, 0.0, 0.0), (1.0, 0.0)]] @@ -705,22 +711,25 @@ def __init__(self, generator=None): sage: threegame.obtain_nash() Traceback (most recent call last): ... - NotImplementedError: Nash equilibrium for games with more than 2 players have not been implemented yet. Please see the gambit website (http://gambit.sourceforge.net/) that has a variety of available algorithms + NotImplementedError: Nash equilibrium for games with more than + 2 players have not been implemented yet. Please see the gambit + website (http://gambit.sourceforge.net/) that has a variety of + available algorithms Can initialise a game from a gambit game object:: - sage: from gambit import Game # optional - gambit - sage: gambitgame= Game.new_table([2, 2]) # optional - gambit - sage: gambitgame[int(0), int(0)][int(0)] = int(5) # optional - gambit - sage: gambitgame[int(0), int(0)][int(1)] = int(8) # optional - gambit - sage: gambitgame[int(0), int(1)][int(0)] = int(2) # optional - gambit - sage: gambitgame[int(0), int(1)][int(1)] = int(11) # optional - gambit - sage: gambitgame[int(1), int(0)][int(0)] = int(10) # optional - gambit - sage: gambitgame[int(1), int(0)][int(1)] = int(7) # optional - gambit - sage: gambitgame[int(1), int(1)][int(0)] = int(5) # optional - gambit - sage: gambitgame[int(1), int(1)][int(1)] = int(5) # optional - gambit - sage: g = NormalFormGame(gambitgame) # optional - gambit - sage: g # optional - gambit + sage: # optional - gambit + sage: from gambit import Game + sage: gambitgame= Game.new_table([2, 2]) + sage: gambitgame[int(0), int(0)][int(0)] = int(5) + sage: gambitgame[int(0), int(0)][int(1)] = int(8) + sage: gambitgame[int(0), int(1)][int(0)] = int(2) + sage: gambitgame[int(0), int(1)][int(1)] = int(11) + sage: gambitgame[int(1), int(0)][int(0)] = int(10) + sage: gambitgame[int(1), int(0)][int(1)] = int(7) + sage: gambitgame[int(1), int(1)][int(0)] = int(5) + sage: gambitgame[int(1), int(1)][int(1)] = int(5) + sage: g = NormalFormGame(gambitgame); g Normal Form Game with the following utilities: {(0, 0): [5.0, 8.0], (0, 1): [2.0, 11.0], (1, 0): [10.0, 7.0], @@ -790,10 +799,12 @@ def __delitem__(self, key): sage: B = matrix([[2, 0], [5, 4]]) sage: prisoners_dilemma = NormalFormGame([A, B]) sage: prisoners_dilemma - Normal Form Game with the following utilities: {(0, 0): [2, 2], (0, 1): [5, 0], (1, 0): [0, 5], (1, 1): [4, 4]} + Normal Form Game with the following utilities: {(0, 0): [2, 2], + (0, 1): [5, 0], (1, 0): [0, 5], (1, 1): [4, 4]} sage: del(prisoners_dilemma[(0,1)]) sage: prisoners_dilemma - Normal Form Game with the following utilities: {(0, 0): [2, 2], (1, 0): [0, 5], (1, 1): [4, 4]} + Normal Form Game with the following utilities: {(0, 0): [2, 2], + (1, 0): [0, 5], (1, 1): [4, 4]} """ self.utilities.pop(key, None) @@ -897,7 +908,8 @@ def _repr_(self): sage: p2 = matrix([[3, 3], [1, 4]]) sage: g = NormalFormGame([p1, p2]) sage: g - Normal Form Game with the following utilities: {(0, 0): [1, 3], (0, 1): [2, 3], (1, 0): [3, 1], (1, 1): [4, 4]} + Normal Form Game with the following utilities: {(0, 0): [1, 3], + (0, 1): [2, 3], (1, 0): [3, 1], (1, 1): [4, 4]} """ from pprint import pformat base_str = "Normal Form Game with the following utilities: {}" @@ -967,19 +979,19 @@ def _gambit_game(self, game): TESTS:: - sage: from gambit import Game # optional - gambit - sage: testgame = Game.new_table([2, 2]) # optional - gambit - sage: testgame[int(0), int(0)][int(0)] = int(8) # optional - gambit - sage: testgame[int(0), int(0)][int(1)] = int(8) # optional - gambit - sage: testgame[int(0), int(1)][int(0)] = int(2) # optional - gambit - sage: testgame[int(0), int(1)][int(1)] = int(10) # optional - gambit - sage: testgame[int(1), int(0)][int(0)] = int(10) # optional - gambit - sage: testgame[int(1), int(0)][int(1)] = int(2) # optional - gambit - sage: testgame[int(1), int(1)][int(0)] = int(5) # optional - gambit - sage: testgame[int(1), int(1)][int(1)] = int(5) # optional - gambit - sage: g = NormalFormGame() # optional - gambit - sage: g._gambit_game(testgame) # optional - gambit - sage: g # optional - gambit + sage: # optional - gambit + sage: from gambit import Game + sage: testgame = Game.new_table([2, 2]) + sage: testgame[int(0), int(0)][int(0)] = int(8) + sage: testgame[int(0), int(0)][int(1)] = int(8) + sage: testgame[int(0), int(1)][int(0)] = int(2) + sage: testgame[int(0), int(1)][int(1)] = int(10) + sage: testgame[int(1), int(0)][int(0)] = int(10) + sage: testgame[int(1), int(0)][int(1)] = int(2) + sage: testgame[int(1), int(1)][int(0)] = int(5) + sage: testgame[int(1), int(1)][int(1)] = int(5) + sage: g = NormalFormGame() + sage: g._gambit_game(testgame); g Normal Form Game with the following utilities: {(0, 0): [8.0, 8.0], (0, 1): [2.0, 10.0], (1, 0): [10.0, 2.0], @@ -1008,11 +1020,11 @@ def _gambit_(self, as_integer=False, maximization=True): TESTS:: - sage: from gambit import Game # optional - gambit + sage: # optional - gambit + sage: from gambit import Game sage: A = matrix([[2, 1], [1, 2.5]]) sage: g = NormalFormGame([A]) - sage: gg = g._gambit_() # optional - gambit - sage: gg # optional - gambit + sage: gg = g._gambit_(); gg NFG 1 R "" { "1" "2" } { { "1" "2" } @@ -1028,9 +1040,7 @@ def _gambit_(self, as_integer=False, maximization=True): } 1 2 3 4 - - sage: gg = g._gambit_(as_integer=True) # optional - gambit - sage: gg # optional - gambit + sage: gg = g._gambit_(as_integer=True); gg NFG 1 R "" { "1" "2" } { { "1" "2" } @@ -1049,11 +1059,11 @@ def _gambit_(self, as_integer=False, maximization=True): :: + sage: # optional - gambit sage: A = matrix([[2, 1], [1, 2.5]]) sage: B = matrix([[3, 2], [5.5, 4]]) sage: g = NormalFormGame([A, B]) - sage: gg = g._gambit_() # optional - gambit - sage: gg # optional - gambit + sage: gg = g._gambit_(); gg NFG 1 R "" { "1" "2" } { { "1" "2" } @@ -1069,9 +1079,7 @@ def _gambit_(self, as_integer=False, maximization=True): } 1 2 3 4 - - sage: gg = g._gambit_(as_integer = True) # optional - gambit - sage: gg # optional - gambit + sage: gg = g._gambit_(as_integer = True); gg NFG 1 R "" { "1" "2" } { { "1" "2" } @@ -1090,35 +1098,36 @@ def _gambit_(self, as_integer=False, maximization=True): :: - sage: threegame = NormalFormGame() # optional - gambit - sage: threegame.add_player(2) # optional - gambit - sage: threegame.add_player(2) # optional - gambit - sage: threegame.add_player(2) # optional - gambit - sage: threegame[0, 0, 0][0] = 3 # optional - gambit - sage: threegame[0, 0, 0][1] = 1 # optional - gambit - sage: threegame[0, 0, 0][2] = 4 # optional - gambit - sage: threegame[0, 0, 1][0] = 1 # optional - gambit - sage: threegame[0, 0, 1][1] = 5 # optional - gambit - sage: threegame[0, 0, 1][2] = 9 # optional - gambit - sage: threegame[0, 1, 0][0] = 2 # optional - gambit - sage: threegame[0, 1, 0][1] = 6 # optional - gambit - sage: threegame[0, 1, 0][2] = 5 # optional - gambit - sage: threegame[0, 1, 1][0] = 3 # optional - gambit - sage: threegame[0, 1, 1][1] = 5 # optional - gambit - sage: threegame[0, 1, 1][2] = 8 # optional - gambit - sage: threegame[1, 0, 0][0] = 9 # optional - gambit - sage: threegame[1, 0, 0][1] = 7 # optional - gambit - sage: threegame[1, 0, 0][2] = 9 # optional - gambit - sage: threegame[1, 0, 1][0] = 3 # optional - gambit - sage: threegame[1, 0, 1][1] = 2 # optional - gambit - sage: threegame[1, 0, 1][2] = 3 # optional - gambit - sage: threegame[1, 1, 0][0] = 8 # optional - gambit - sage: threegame[1, 1, 0][1] = 4 # optional - gambit - sage: threegame[1, 1, 0][2] = 6 # optional - gambit - sage: threegame[1, 1, 1][0] = 2 # optional - gambit - sage: threegame[1, 1, 1][1] = 6 # optional - gambit - sage: threegame[1, 1, 1][2] = 4 # optional - gambit - sage: threegame._gambit_(as_integer = True) # optional - gambit + sage: # optional - gambit + sage: threegame = NormalFormGame() + sage: threegame.add_player(2) + sage: threegame.add_player(2) + sage: threegame.add_player(2) + sage: threegame[0, 0, 0][0] = 3 + sage: threegame[0, 0, 0][1] = 1 + sage: threegame[0, 0, 0][2] = 4 + sage: threegame[0, 0, 1][0] = 1 + sage: threegame[0, 0, 1][1] = 5 + sage: threegame[0, 0, 1][2] = 9 + sage: threegame[0, 1, 0][0] = 2 + sage: threegame[0, 1, 0][1] = 6 + sage: threegame[0, 1, 0][2] = 5 + sage: threegame[0, 1, 1][0] = 3 + sage: threegame[0, 1, 1][1] = 5 + sage: threegame[0, 1, 1][2] = 8 + sage: threegame[1, 0, 0][0] = 9 + sage: threegame[1, 0, 0][1] = 7 + sage: threegame[1, 0, 0][2] = 9 + sage: threegame[1, 0, 1][0] = 3 + sage: threegame[1, 0, 1][1] = 2 + sage: threegame[1, 0, 1][2] = 3 + sage: threegame[1, 1, 0][0] = 8 + sage: threegame[1, 1, 0][1] = 4 + sage: threegame[1, 1, 0][2] = 6 + sage: threegame[1, 1, 1][0] = 2 + sage: threegame[1, 1, 1][1] = 6 + sage: threegame[1, 1, 1][2] = 4 + sage: threegame._gambit_(as_integer = True) NFG 1 R "" { "1" "2" "3" } { { "1" "2" } @@ -1274,7 +1283,9 @@ def add_player(self, num_strategies): sage: g.add_player(1) # Adding second player with 1 strategy sage: g.add_player(1) # Adding third player with 1 strategy sage: g - Normal Form Game with the following utilities: {(0, 0, 0): [False, False, False], (1, 0, 0): [False, False, False]} + Normal Form Game with the following utilities: + {(0, 0, 0): [False, False, False], + (1, 0, 0): [False, False, False]} """ self.players.append(_Player(num_strategies)) self._generate_utilities(True) @@ -1350,7 +1361,8 @@ def add_strategy(self, player): sage: t = matrix([[3, 2], [-1, 0]]) sage: example = NormalFormGame([s, t]) sage: example - Normal Form Game with the following utilities: {(0, 0): [1, 3], (0, 1): [0, 2], (1, 0): [-2, -1], (1, 1): [3, 0]} + Normal Form Game with the following utilities: {(0, 0): [1, 3], + (0, 1): [0, 2], (1, 0): [-2, -1], (1, 1): [3, 0]} sage: example.add_strategy(0) sage: example Normal Form Game with the following utilities: {(0, 0): [1, 3], @@ -1475,10 +1487,12 @@ def obtain_nash(self, algorithm=False, maximization=True, solver=None): ....: [3, 4, 1], ....: [4, 1, 20]]) sage: g=NormalFormGame([A, B]) - sage: g.obtain_nash(algorithm='lrs') # optional - lrslib + sage: g.obtain_nash(algorithm='lrs') # optional - lrslib [[(0, 0, 0, 1), (0, 0, 1)]] - sage: g.obtain_nash(algorithm='lrs', maximization=False) # optional - lrslib - [[(2/3, 1/12, 1/4, 0), (6333/8045, 247/8045, 293/1609)], [(3/4, 0, 1/4, 0), (0, 11/307, 296/307)], [(5/6, 1/6, 0, 0), (98/99, 1/99, 0)]] + sage: g.obtain_nash(algorithm='lrs', maximization=False) # optional - lrslib + [[(2/3, 1/12, 1/4, 0), (6333/8045, 247/8045, 293/1609)], + [(3/4, 0, 1/4, 0), (0, 11/307, 296/307)], + [(5/6, 1/6, 0, 0), (98/99, 1/99, 0)]] This particular game has 3 Nash equilibria:: @@ -1490,7 +1504,9 @@ def obtain_nash(self, algorithm=False, maximization=True, solver=None): ....: [3,1]]) sage: g = NormalFormGame([A, B]) sage: g.obtain_nash(algorithm='enumeration') - [[(0, 1/3, 2/3), (1/3, 2/3)], [(4/5, 1/5, 0), (2/3, 1/3)], [(1, 0, 0), (1, 0)]] + [[(0, 1/3, 2/3), (1/3, 2/3)], + [(4/5, 1/5, 0), (2/3, 1/3)], + [(1, 0, 0), (1, 0)]] Here is a slightly larger game:: @@ -1525,9 +1541,9 @@ def obtain_nash(self, algorithm=False, maximization=True, solver=None): sage: fivegame = NormalFormGame([player1, player2]) sage: fivegame.obtain_nash(algorithm='enumeration') [[(1, 0, 0, 0, 0), (0, 1, 0, 0, 0)]] - sage: fivegame.obtain_nash(algorithm='lrs') # optional - lrslib + sage: fivegame.obtain_nash(algorithm='lrs') # optional - lrslib [[(1, 0, 0, 0, 0), (0, 1, 0, 0, 0)]] - sage: fivegame.obtain_nash(algorithm='LCP') # optional - gambit + sage: fivegame.obtain_nash(algorithm='LCP') # optional - gambit [[(1.0, 0.0, 0.0, 0.0, 0.0), (0.0, 1.0, 0.0, 0.0, 0.0)]] Here are some examples of finding Nash equilibria for constant-sum games:: @@ -1536,24 +1552,24 @@ def obtain_nash(self, algorithm=False, maximization=True, solver=None): sage: cg = NormalFormGame([A]) sage: cg.obtain_nash(algorithm='lp') [[(0.5, 0.5), (0.5, 0.5)]] - sage: cg.obtain_nash(algorithm='lp', solver='Coin') # optional - sage_numerical_backends_coin + sage: cg.obtain_nash(algorithm='lp', solver='Coin') # optional - sage_numerical_backends_coin [[(0.5, 0.5), (0.5, 0.5)]] sage: cg.obtain_nash(algorithm='lp', solver='PPL') [[(1/2, 1/2), (1/2, 1/2)]] - sage: cg.obtain_nash(algorithm='lp', solver='gambit') # optional - gambit + sage: cg.obtain_nash(algorithm='lp', solver='gambit') # optional - gambit [[(0.5, 0.5), (0.5, 0.5)]] sage: A = matrix([[2, 1], [1, 3]]) sage: cg = NormalFormGame([A]) sage: ne = cg.obtain_nash(algorithm='lp', solver='glpk') sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] [[[0.666667, 0.333333], [0.666667, 0.333333]]] - sage: ne = cg.obtain_nash(algorithm='lp', solver='Coin') # optional - sage_numerical_backends_coin - sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - sage_numerical_backends_coin + sage: ne = cg.obtain_nash(algorithm='lp', solver='Coin') # optional - sage_numerical_backends_coin + sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - sage_numerical_backends_coin [[[0.666667, 0.333333], [0.666667, 0.333333]]] sage: cg.obtain_nash(algorithm='lp', solver='PPL') [[(2/3, 1/3), (2/3, 1/3)]] - sage: ne = cg.obtain_nash(algorithm='lp', solver='gambit') # optional - gambit - sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - gambit + sage: ne = cg.obtain_nash(algorithm='lp', solver='gambit') # optional - gambit + sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - gambit [[[0.666667, 0.333333], [0.666667, 0.333333]]] sage: A = matrix([[1, 2, 1], [1, 1, 2], [2, 1, 1]]) sage: B = matrix([[2, 1, 2], [2, 2, 1], [1, 2, 2]]) @@ -1561,13 +1577,13 @@ def obtain_nash(self, algorithm=False, maximization=True, solver=None): sage: ne = cg.obtain_nash(algorithm='lp', solver='glpk') sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] [[[0.333333, 0.333333, 0.333333], [0.333333, 0.333333, 0.333333]]] - sage: ne = cg.obtain_nash(algorithm='lp', solver='Coin') # optional - sage_numerical_backends_coin - sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - sage_numerical_backends_coin + sage: ne = cg.obtain_nash(algorithm='lp', solver='Coin') # optional - sage_numerical_backends_coin + sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - sage_numerical_backends_coin [[[0.333333, 0.333333, 0.333333], [0.333333, 0.333333, 0.333333]]] sage: cg.obtain_nash(algorithm='lp', solver='PPL') [[(1/3, 1/3, 1/3), (1/3, 1/3, 1/3)]] - sage: ne = cg.obtain_nash(algorithm='lp', solver='gambit') # optional - gambit - sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - gambit + sage: ne = cg.obtain_nash(algorithm='lp', solver='gambit') # optional - gambit + sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - gambit [[[0.333333, 0.333333, 0.333333], [0.333333, 0.333333, 0.333333]]] sage: A = matrix([[160, 205, 44], ....: [175, 180, 45], @@ -1609,19 +1625,19 @@ def obtain_nash(self, algorithm=False, maximization=True, solver=None): sage: gg = NormalFormGame([A]) sage: gg.obtain_nash(algorithm='enumeration') [[(0, 1), (0, 1)], [(0, 1), (1, 0)], [(1, 0), (0, 1)], [(1, 0), (1, 0)]] - sage: gg.obtain_nash(algorithm='lrs') # optional - lrs + sage: gg.obtain_nash(algorithm='lrs') # optional - lrs [[(0, 1), (0, 1)], [(0, 1), (1, 0)], [(1, 0), (0, 1)], [(1, 0), (1, 0)]] sage: gg.obtain_nash(algorithm='lp', solver='glpk') [[(1.0, 0.0), (1.0, 0.0)]] - sage: gg.obtain_nash(algorithm='LCP') # optional - gambit + sage: gg.obtain_nash(algorithm='LCP') # optional - gambit [[(1.0, 0.0), (1.0, 0.0)]] sage: gg.obtain_nash(algorithm='enumeration', maximization=False) [[(0, 1), (0, 1)], [(0, 1), (1, 0)], [(1, 0), (0, 1)], [(1, 0), (1, 0)]] - sage: gg.obtain_nash(algorithm='lrs', maximization=False) # optional - lrs + sage: gg.obtain_nash(algorithm='lrs', maximization=False) # optional - lrs [[(0, 1), (0, 1)], [(0, 1), (1, 0)], [(1, 0), (0, 1)], [(1, 0), (1, 0)]] sage: gg.obtain_nash(algorithm='lp', solver='glpk', maximization=False) [[(1.0, 0.0), (1.0, 0.0)]] - sage: gg.obtain_nash(algorithm='LCP', maximization=False) # optional - gambit + sage: gg.obtain_nash(algorithm='LCP', maximization=False) # optional - gambit [[(1.0, 0.0), (1.0, 0.0)]] Note that outputs for all algorithms are as lists of lists of @@ -1709,7 +1725,7 @@ def _solve_lrs(self, maximization=True): sage: A = matrix([[1, 2], [3, 4]]) sage: B = matrix([[3, 3], [1, 4]]) sage: C = NormalFormGame([A, B]) - sage: C._solve_lrs() # optional - lrslib + sage: C._solve_lrs() # optional - lrslib [[(0, 1), (0, 1)]] 2 random matrices:: @@ -1725,7 +1741,7 @@ def _solve_lrs(self, maximization=True): ....: [1, 0, 0, 0, 0,], ....: [1, -3, 1, 21, -2]]) sage: biggame = NormalFormGame([p1, p2]) - sage: biggame._solve_lrs() # optional - lrslib + sage: biggame._solve_lrs() # optional - lrslib [[(0, 0, 0, 20/21, 1/21), (11/12, 0, 0, 1/12, 0)]] Another test:: @@ -1737,7 +1753,7 @@ def _solve_lrs(self, maximization=True): ....: [6, -2, -3], ....: [-4, 6, -10]]) sage: biggame = NormalFormGame([p1, p2]) - sage: biggame._solve_lrs() # optional - lrslib + sage: biggame._solve_lrs() # optional - lrslib [[(0, 1, 0), (1, 0, 0)], [(1/3, 2/3, 0), (0, 1/6, 5/6)], [(1/3, 2/3, 0), (1/7, 0, 6/7)], @@ -1774,7 +1790,7 @@ def _solve_LCP(self, maximization): sage: a = matrix([[1, 0], [1, 4]]) sage: b = matrix([[2, 3], [2, 4]]) sage: c = NormalFormGame([a, b]) - sage: c._solve_LCP(maximization=True) # optional - gambit + sage: c._solve_LCP(maximization=True) # optional - gambit [[(0.0, 1.0), (0.0, 1.0)]] """ g = self._gambit_(maximization) @@ -1791,14 +1807,14 @@ def _solve_gambit_LP(self, maximization=True): sage: A = matrix([[2, 1], [1, 2.5]]) sage: g = NormalFormGame([A]) - sage: g._solve_gambit_LP() # optional - gambit + sage: g._solve_gambit_LP() # optional - gambit [[(0.6, 0.4), (0.6, 0.4)]] sage: A = matrix.identity(2) sage: g = NormalFormGame([A]) - sage: g._solve_gambit_LP() # optional - gambit + sage: g._solve_gambit_LP() # optional - gambit [[(0.5, 0.5), (0.5, 0.5)]] sage: g = NormalFormGame([A,A]) - sage: g._solve_gambit_LP() # optional - gambit + sage: g._solve_gambit_LP() # optional - gambit Traceback (most recent call last): ... RuntimeError: Method only valid for constant-sum games. @@ -1830,9 +1846,9 @@ def _solve_LP(self, solver='glpk', maximization=True): sage: g = NormalFormGame([A]) sage: g._solve_LP() [[(0.5, 0.5), (0.5, 0.5)]] - sage: g._solve_LP('gambit') # optional - gambit + sage: g._solve_LP('gambit') # optional - gambit [[(0.5, 0.5), (0.5, 0.5)]] - sage: g._solve_LP('Coin') # optional - sage_numerical_backends_coin + sage: g._solve_LP('Coin') # optional - sage_numerical_backends_coin [[(0.5, 0.5), (0.5, 0.5)]] sage: g._solve_LP('PPL') [[(1/2, 1/2), (1/2, 1/2)]] @@ -1841,11 +1857,11 @@ def _solve_LP(self, solver='glpk', maximization=True): sage: ne = g._solve_LP() sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] [[[0.666667, 0.333333], [0.666667, 0.333333]]] - sage: ne = g._solve_LP('gambit') # optional - gambit - sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - gambit + sage: ne = g._solve_LP('gambit') # optional - gambit + sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - gambit [[[0.666667, 0.333333], [0.666667, 0.333333]]] - sage: ne = g._solve_LP('Coin') # optional - sage_numerical_backends_coin - sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - sage_numerical_backends_coin + sage: ne = g._solve_LP('Coin') # optional - sage_numerical_backends_coin + sage: [[[round(el, 6) for el in v] for v in eq] for eq in ne] # optional - sage_numerical_backends_coin [[[0.666667, 0.333333], [0.666667, 0.333333]]] sage: g._solve_LP('PPL') [[(2/3, 1/3), (2/3, 1/3)]] @@ -1950,7 +1966,9 @@ def _solve_enumeration(self, maximization=True): ....: [3, 2, 1, 1]]) sage: C = NormalFormGame([A, B]) sage: C._solve_enumeration() - [[(0, 0, 0, 1), (1, 0, 0, 0)], [(2/7, 0, 0, 5/7), (5/11, 0, 6/11, 0)], [(1, 0, 0, 0), (0, 0, 1, 0)]] + [[(0, 0, 0, 1), (1, 0, 0, 0)], + [(2/7, 0, 0, 5/7), (5/11, 0, 6/11, 0)], + [(1, 0, 0, 0), (0, 0, 1, 0)]] Again:: @@ -2485,11 +2503,11 @@ def is_degenerate(self, certificate=False): ....: [-17, 25, -97, -82], ....: [30, 31, -1, 50]]) sage: d_game = NormalFormGame([a, b]) - sage: d_game.obtain_nash(algorithm='lrs') # optional - lrslib + sage: d_game.obtain_nash(algorithm='lrs') # optional - lrslib [[(0, 0, 1, 0), (0, 1, 0, 0)], [(17/29, 0, 0, 12/29), (0, 0, 42/73, 31/73)], [(122/145, 0, 23/145, 0), (0, 1, 0, 0)]] - sage: d_game.obtain_nash(algorithm='LCP') # optional - gambit + sage: d_game.obtain_nash(algorithm='LCP') # optional - gambit [[(0.5862068966, 0.0, 0.0, 0.4137931034), (0.0, 0.0, 0.5753424658, 0.4246575342)]] sage: d_game.obtain_nash(algorithm='enumeration') @@ -2532,7 +2550,8 @@ def is_degenerate(self, certificate=False): sage: g.is_degenerate() Traceback (most recent call last): ... - NotImplementedError: Tests for Degeneracy is not yet implemented for games with more than two players. + NotImplementedError: Tests for Degeneracy is not yet implemented for + games with more than two players. """ if len(self.players) > 2: raise NotImplementedError("Tests for Degeneracy is not yet " @@ -2607,7 +2626,7 @@ def best_responses(self, strategy, player): sage: g.best_responses((3/4, 1/4), player=0) [0] - To get the best responses for Player 2 we pass the argument :code:`player=1` + To get the best responses for Player 2 we pass the argument :code:`player=1`:: sage: g.best_responses((4/5, 1/5, 0), player=1) [0, 1] @@ -2658,7 +2677,7 @@ def best_responses(self, strategy, player): ValueError: Strategy is not of correct dimension If the strategy is not a true probability vector then an error is - passed: + passed:: sage: A = matrix([[3, 0], [0, 3], [1.5, 1.5]]) sage: B = matrix([[4, 3], [2, 6], [3, 1]]) diff --git a/src/sage/game_theory/parser.py b/src/sage/game_theory/parser.py index 0784e4bc184..d528116f244 100644 --- a/src/sage/game_theory/parser.py +++ b/src/sage/game_theory/parser.py @@ -194,18 +194,19 @@ def format_gambit(self, gambit_game): Here we construct a two by two game in gambit:: - sage: import gambit # optional - gambit + sage: # optional - gambit + sage: import gambit sage: from sage.game_theory.parser import Parser - sage: g = gambit.Game.new_table([2,2]) # optional - gambit - sage: g[int(0), int(0)][int(0)] = int(2) # optional - gambit - sage: g[int(0), int(0)][int(1)] = int(1) # optional - gambit - sage: g[int(0), int(1)][int(0)] = int(0) # optional - gambit - sage: g[int(0), int(1)][int(1)] = int(0) # optional - gambit - sage: g[int(1), int(0)][int(0)] = int(0) # optional - gambit - sage: g[int(1), int(0)][int(1)] = int(0) # optional - gambit - sage: g[int(1), int(1)][int(0)] = int(1) # optional - gambit - sage: g[int(1), int(1)][int(1)] = int(2) # optional - gambit - sage: solver = gambit.nash.ExternalLCPSolver() # optional - gambit + sage: g = gambit.Game.new_table([2,2]) + sage: g[int(0), int(0)][int(0)] = int(2) + sage: g[int(0), int(0)][int(1)] = int(1) + sage: g[int(0), int(1)][int(0)] = int(0) + sage: g[int(0), int(1)][int(1)] = int(0) + sage: g[int(1), int(0)][int(0)] = int(0) + sage: g[int(1), int(0)][int(1)] = int(0) + sage: g[int(1), int(1)][int(0)] = int(1) + sage: g[int(1), int(1)][int(1)] = int(2) + sage: solver = gambit.nash.ExternalLCPSolver() Here is the output of the LCP algorithm:: @@ -218,21 +219,24 @@ def format_gambit(self, gambit_game): The Parser class outputs the equilibrium:: sage: nasheq = Parser(LCP_output).format_gambit(g) # optional - gambit - sage: nasheq # optional - gambit - [[(1.0, 0.0), (1.0, 0.0)], [(0.6666666667, 0.3333333333), (0.3333333333, 0.6666666667)], [(0.0, 1.0), (0.0, 1.0)]] + sage: nasheq # optional - gambit + [[(1.0, 0.0), (1.0, 0.0)], + [(0.6666666667, 0.3333333333), (0.3333333333, 0.6666666667)], + [(0.0, 1.0), (0.0, 1.0)]] Here is another game:: - sage: g = gambit.Game.new_table([2,2]) # optional - gambit - sage: g[int(0), int(0)][int(0)] = int(4) # optional - gambit - sage: g[int(0), int(0)][int(1)] = int(8) # optional - gambit - sage: g[int(0), int(1)][int(0)] = int(0) # optional - gambit - sage: g[int(0), int(1)][int(1)] = int(1) # optional - gambit - sage: g[int(1), int(0)][int(0)] = int(1) # optional - gambit - sage: g[int(1), int(0)][int(1)] = int(3) # optional - gambit - sage: g[int(1), int(1)][int(0)] = int(1) # optional - gambit - sage: g[int(1), int(1)][int(1)] = int(0) # optional - gambit - sage: solver = gambit.nash.ExternalLCPSolver() # optional - gambit + sage: # optional - gambit + sage: g = gambit.Game.new_table([2,2]) + sage: g[int(0), int(0)][int(0)] = int(4) + sage: g[int(0), int(0)][int(1)] = int(8) + sage: g[int(0), int(1)][int(0)] = int(0) + sage: g[int(0), int(1)][int(1)] = int(1) + sage: g[int(1), int(0)][int(0)] = int(1) + sage: g[int(1), int(0)][int(1)] = int(3) + sage: g[int(1), int(1)][int(0)] = int(1) + sage: g[int(1), int(1)][int(1)] = int(0) + sage: solver = gambit.nash.ExternalLCPSolver() Here is the LCP output:: @@ -248,26 +252,27 @@ def format_gambit(self, gambit_game): Here is a larger degenerate game:: - sage: g = gambit.Game.new_table([3,3]) # optional - gambit - sage: g[int(0), int(0)][int(0)] = int(-7) # optional - gambit - sage: g[int(0), int(0)][int(1)] = int(-9) # optional - gambit - sage: g[int(0), int(1)][int(0)] = int(-5) # optional - gambit - sage: g[int(0), int(1)][int(1)] = int(7) # optional - gambit - sage: g[int(0), int(2)][int(0)] = int(5) # optional - gambit - sage: g[int(0), int(2)][int(1)] = int(9) # optional - gambit - sage: g[int(1), int(0)][int(0)] = int(5) # optional - gambit - sage: g[int(1), int(0)][int(1)] = int(6) # optional - gambit - sage: g[int(1), int(1)][int(0)] = int(5) # optional - gambit - sage: g[int(1), int(1)][int(1)] = int(-2) # optional - gambit - sage: g[int(1), int(2)][int(0)] = int(3) # optional - gambit - sage: g[int(1), int(2)][int(1)] = int(-3) # optional - gambit - sage: g[int(2), int(0)][int(0)] = int(1) # optional - gambit - sage: g[int(2), int(0)][int(1)] = int(-4) # optional - gambit - sage: g[int(2), int(1)][int(0)] = int(-6) # optional - gambit - sage: g[int(2), int(1)][int(1)] = int(6) # optional - gambit - sage: g[int(2), int(2)][int(0)] = int(1) # optional - gambit - sage: g[int(2), int(2)][int(1)] = int(-10) # optional - gambit - sage: solver = gambit.nash.ExternalLCPSolver() # optional - gambit + sage: # optional - gambit + sage: g = gambit.Game.new_table([3,3]) + sage: g[int(0), int(0)][int(0)] = int(-7) + sage: g[int(0), int(0)][int(1)] = int(-9) + sage: g[int(0), int(1)][int(0)] = int(-5) + sage: g[int(0), int(1)][int(1)] = int(7) + sage: g[int(0), int(2)][int(0)] = int(5) + sage: g[int(0), int(2)][int(1)] = int(9) + sage: g[int(1), int(0)][int(0)] = int(5) + sage: g[int(1), int(0)][int(1)] = int(6) + sage: g[int(1), int(1)][int(0)] = int(5) + sage: g[int(1), int(1)][int(1)] = int(-2) + sage: g[int(1), int(2)][int(0)] = int(3) + sage: g[int(1), int(2)][int(1)] = int(-3) + sage: g[int(2), int(0)][int(0)] = int(1) + sage: g[int(2), int(0)][int(1)] = int(-4) + sage: g[int(2), int(1)][int(0)] = int(-6) + sage: g[int(2), int(1)][int(1)] = int(6) + sage: g[int(2), int(2)][int(0)] = int(1) + sage: g[int(2), int(2)][int(1)] = int(-10) + sage: solver = gambit.nash.ExternalLCPSolver() Here is the LCP output::