Skip to content

Commit

Permalink
Trac #20289: pep8 cleanup in game_theory
Browse files Browse the repository at this point in the history
just to correct a typo and a few pep8 details in game_theory

URL: http://trac.sagemath.org/20289
Reported by: chapoton
Ticket author(s): Frédéric Chapoton
Reviewer(s): Travis Scrimshaw
  • Loading branch information
Release Manager authored and vbraun committed Mar 27, 2016
2 parents e481501 + 6a5df50 commit 94685aa
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 39 deletions.
1 change: 0 additions & 1 deletion src/sage/game_theory/all.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@
lazy_import('sage.game_theory.cooperative_game', 'CooperativeGame')
lazy_import('sage.game_theory.normal_form_game', 'NormalFormGame')
lazy_import('sage.game_theory.matching_game', 'MatchingGame')

1 change: 0 additions & 1 deletion src/sage/game_theory/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@
"""

import catalog_normal_form_games as normal_form_games

15 changes: 9 additions & 6 deletions src/sage/game_theory/catalog_normal_form_games.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ def CoordinationGame(A=10, a=5, B=0, b=0, C=0, c=0, D=5, d=10):
TypeError: the input values for a Coordination game must
be of the form A > B, D > C, a > c and d > b
"""
if not (A > B and D > C and a > c and d > b):
if not (A > B and D > C and a > c and d > b):
raise TypeError("the input values for a Coordination game must be of the form A > B, D > C, a > c and d > b")
from sage.matrix.constructor import matrix
A = matrix([[A, C], [B, D]])
Expand Down Expand Up @@ -414,7 +414,7 @@ def AntiCoordinationGame(A=3, a=3, B=5, b=1, C=1, c=5, D=0, d=0):
...
TypeError: the input values for an Anti coordination game must be of the form A < B, D < C, a < c and d < b
"""
if not (A < B and D < C and a < c and d < b):
if not (A < B and D < C and a < c and d < b):
raise TypeError("the input values for an Anti coordination game must be of the form A < B, D < C, a < c and d < b")
from sage.matrix.constructor import matrix
A = matrix([[A, C], [B, D]])
Expand Down Expand Up @@ -506,9 +506,10 @@ def HawkDove(v=2, c=3):
...
TypeError: the input values for a Hawk Dove game must be of the form c > v
"""
if not (c>v):
if not (c > v):
raise TypeError("the input values for a Hawk Dove game must be of the form c > v")
g = AntiCoordinationGame(A=v/2-c, a=v/2-c, B=0, b=v, C=v, c=0, D=v/2, d=v/2)
g = AntiCoordinationGame(A=v/2-c, a=v/2-c, B=0, b=v,
C=v, c=0, D=v/2, d=v/2)
g.rename('Hawk-Dove - ' + repr(g))
return g

Expand Down Expand Up @@ -656,6 +657,7 @@ def RPS():
g.rename('Rock-Paper-Scissors - ' + repr(g))
return g


def RPSLS():
r"""
Return a Rock-Paper-Scissors-Lizard-Spock game.
Expand Down Expand Up @@ -716,7 +718,7 @@ def RPSLS():
from sage.matrix.constructor import matrix
A = matrix([[0, -1, 1, 1, -1],
[1, 0, -1, -1, 1],
[-1, 1, 0, 1 , -1],
[-1, 1, 0, 1, -1],
[-1, 1, -1, 0, 1],
[1, -1, 1, -1, 0]])
g = NormalFormGame([A])
Expand Down Expand Up @@ -814,6 +816,7 @@ def Chicken(A=0, a=0, B=1, b=-1, C=-1, c=1, D=-10, d=-10):
g.rename('Chicken - ' + repr(g))
return g


def TravellersDilemma(max_value=10):
r"""
Return a Travellers dilemma game.
Expand Down Expand Up @@ -929,7 +932,7 @@ def TravellersDilemma(max_value=10):
from sage.matrix.constructor import matrix
from sage.functions.generalized import sign
A = matrix([[min(i, j) + 2 * sign(j - i) for j in range(max_value, 1, -1)]
for i in range(max_value, 1, -1)])
for i in range(max_value, 1, -1)])
g = NormalFormGame([A, A.transpose()])
g.rename('Travellers dilemma - ' + repr(g))
return g
5 changes: 2 additions & 3 deletions src/sage/game_theory/cooperative_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ def shapley_value(self):
for player in self.player_list:
weighted_contribution = 0
for coalition in powerset(self.player_list):
if coalition: # If non-empty
if coalition: # If non-empty
k = Integer(len(coalition))
weight = 1 / (n.binomial(k) * k)
t = tuple(p for p in coalition if p != player)
Expand Down Expand Up @@ -617,7 +617,7 @@ def _latex_(self):
cf = self.ch_f
output = "v(c) = \\begin{cases}\n"
for key in sorted(cf.keys(), key=lambda key: len(key)):
if not key: # == ()
if not key: # == ()
coalition = "\\emptyset"
else:
coalition = "\\{" + ", ".join(str(player) for player in key) + "\\}"
Expand Down Expand Up @@ -860,4 +860,3 @@ def is_symmetric(self, payoff_vector):
if all(results) and payoff_vector[c1[0]] != payoff_vector[c2[0]]:
return False
return True

2 changes: 1 addition & 1 deletion src/sage/game_theory/gambit_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
Out[14]: [<NashProfile for '': [0.5, 0.5, 0.5, 0.5]>]
Note that the above examples only show how to build and find equilibria for
two player strategic form games. Gambit supports mulitple player games as well
two player strategic form games. Gambit supports multiple player games as well
as extensive form games: for more details see http://www.gambit-project.org/.
If one really wants to use gambit directly in Sage (without using the
Expand Down
17 changes: 9 additions & 8 deletions src/sage/game_theory/matching_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from copy import deepcopy
from sage.graphs.bipartite_graph import BipartiteGraph


class MatchingGame(SageObject):
r"""
A matching game.
Expand Down Expand Up @@ -397,8 +398,8 @@ def _repr_(self):
sage: M
A matching game with 2 suitors and 2 reviewers
"""
return 'A matching game with {} suitors and {} reviewers'.format(
len(self._suitors), len(self._reviewers))
txt = 'A matching game with {} suitors and {} reviewers'
return txt.format(len(self._suitors), len(self._reviewers))

def _latex_(self):
r"""
Expand All @@ -424,10 +425,10 @@ def _latex_(self):
"""
output = "\\text{Suitors:}\n\\begin{aligned}"
for suitor in self._suitors:
output += "\n\\\\ %s & \\to %s"%(suitor, suitor.pref)
output += "\n\\\\ %s & \\to %s" % (suitor, suitor.pref)
output += "\n\\end{aligned}\n\\text{Reviewers:}\n\\begin{aligned}"
for reviewer in self._reviewers:
output += "\n\\\\ %s & \\to %s"%(reviewer, reviewer.pref)
output += "\n\\\\ %s & \\to %s" % (reviewer, reviewer.pref)
return output + "\n\\end{aligned}"

def __eq__(self, other):
Expand Down Expand Up @@ -493,9 +494,9 @@ def __eq__(self, other):
and set(self._suitors) == set(other._suitors)
and set(self._reviewers) == set(other._reviewers)
and all(r1.pref == r2.pref for r1, r2 in
zip(set(self._reviewers), set(other._reviewers)))
zip(set(self._reviewers), set(other._reviewers)))
and all(s1.pref == s2.pref for s1, s2 in
zip(set(self._suitors), set(other._suitors))))
zip(set(self._suitors), set(other._suitors))))

def __hash__(self):
"""
Expand Down Expand Up @@ -950,8 +951,8 @@ def solve(self, invert=False):
self._sol_dict[r] = [r.partner]

if invert:
return {key:self._sol_dict[key][0] for key in self._reviewers}
return {key:self._sol_dict[key][0] for key in self._suitors}
return {key: self._sol_dict[key][0] for key in self._reviewers}
return {key: self._sol_dict[key][0] for key in self._suitors}


class Player(object):
Expand Down
39 changes: 22 additions & 17 deletions src/sage/game_theory/normal_form_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,7 @@
except ImportError:
Game = None


class NormalFormGame(SageObject, MutableMapping):
r"""
An object representing a Normal Form Game. Primarily used to compute the
Expand Down Expand Up @@ -1078,7 +1079,7 @@ def _generate_utilities(self, replacement):
self.utilities = {}
for profile in product(*strategy_sizes):
if profile not in self.utilities.keys():
self.utilities[profile] = [False]*len(self.players)
self.utilities[profile] = [False] * len(self.players)

def add_strategy(self, player):
r"""
Expand Down Expand Up @@ -1420,9 +1421,9 @@ def _solve_LCP(self, maximization):
scalar *= -1
for strategy_profile in self.utilities:
g[strategy_profile][0] = int(scalar *
self.utilities[strategy_profile][0])
self.utilities[strategy_profile][0])
g[strategy_profile][1] = int(scalar *
self.utilities[strategy_profile][1])
self.utilities[strategy_profile][1])
output = ExternalLCPSolver().solve(g)
nasheq = Parser(output).format_gambit(g)
return sorted(nasheq)
Expand Down Expand Up @@ -1660,7 +1661,7 @@ def _solve_indifference(self, support1, support2, M):
sage: g._solve_indifference((0,), (0,), -A.transpose())
(1)
"""
linearsystem = matrix(QQ, len(support2)+1, M.nrows())
linearsystem = matrix(QQ, len(support2) + 1, M.nrows())

# Build linear system for player 1
for strategy1 in support1:
Expand Down Expand Up @@ -1742,23 +1743,27 @@ def _is_NE(self, a, b, p1_support, p2_support, M1, M2):
False
"""
# Check that supports are obeyed
if not (all([a[i] > 0 for i in p1_support]) and
all([b[j] > 0 for j in p2_support]) and
all([a[i] == 0 for i in range(len(a)) if i not in p1_support]) and
all([b[j] == 0 for j in range(len(b)) if j not in p2_support])):
if not(all([a[i] > 0 for i in p1_support]) and
all([b[j] > 0 for j in p2_support]) and
all([a[i] == 0 for i in range(len(a))
if i not in p1_support]) and
all([b[j] == 0 for j in range(len(b))
if j not in p2_support])):
return False

# Check that have pair of best responses

p1_payoffs = [sum(v * row[i] for i, v in enumerate(b)) for row
in M1.rows()]
p2_payoffs = [sum(v * col[j] for j, v in enumerate(a)) for col
in M2.columns()]
p1_payoffs = [sum(v * row[i] for i, v in enumerate(b))
for row in M1.rows()]
p2_payoffs = [sum(v * col[j] for j, v in enumerate(a))
for col in M2.columns()]

#if p1_payoffs.index(max(p1_payoffs)) not in p1_support:
if not any(i in p1_support for i, x in enumerate(p1_payoffs) if x == max(p1_payoffs)):
if not any(i in p1_support for i, x in enumerate(p1_payoffs)
if x == max(p1_payoffs)):
return False
if not any(i in p2_support for i, x in enumerate(p2_payoffs) if x == max(p2_payoffs)):
if not any(i in p2_support for i, x in enumerate(p2_payoffs)
if x == max(p2_payoffs)):
return False

return True
Expand Down Expand Up @@ -2019,11 +2024,11 @@ def is_degenerate(self, certificate=False):
M1, M2 = self.payoff_matrices()
potential_supports = [[tuple(support) for support in
powerset(range(player.num_strategies))]
for player in self.players]
for player in self.players]

# filter out all supports that are pure or empty
potential_supports = [[i for i in k if len(i) > 1] for k in
potential_supports]
potential_supports = [[i for i in k if len(i) > 1]
for k in potential_supports]

potential_support_pairs = [pair for pair in
product(*potential_supports) if
Expand Down
3 changes: 1 addition & 2 deletions src/sage/game_theory/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ def format_lrs(self):
equilibria = []
from sage.misc.sage_eval import sage_eval
from itertools import groupby
for collection in [list(x[1]) for x in groupby(self.raw_string[7:], lambda x: x=='\n')]:
for collection in [list(x[1]) for x in groupby(self.raw_string[7:], lambda x: x == '\n')]:
if collection[0].startswith('2'):
s1 = tuple([sage_eval(k) for k in collection[-1].split()][1:-1])
for s2 in collection[:-1]:
Expand All @@ -201,7 +201,6 @@ def format_lrs(self):

return equilibria


def format_gambit(self, gambit_game):
"""
Parses the output of gambit so as to return vectors
Expand Down

0 comments on commit 94685aa

Please sign in to comment.