from cvxopt import matrix
-class GameException(Exception):
- """
- The base class for all exceptions that can occur during the solution
- of a linear game.
- """
- def pretty_print_dict(self, solution_dict):
- """
- Return a pretty-printed string representation of a CVXOPT
- solution dictionary.
- """
- result = ''
- for (k,v) in solution_dict.items():
- if isinstance(v, matrix):
- # Try to display vectors as rows on one line.
- result += ' {:s}: {!s}'.format(k,v.trans())
- else:
- result += ' {:s}: {!s}\n'.format(k,v)
-
- return result
-
-class GameUnsolvableException(GameException):
+class GameUnsolvableException(Exception):
"""
Every linear game has a solution (this follows from a general
min-max theorem). If we can't solve the conic program associated
with a linear game, then something is wrong with either the model of
the input.
"""
- def __init__(self, status, solution, solution_dict):
+ def __str__(self):
+ tpl = 'Solution failed with result "{:s}."\n' \
+ 'CVXOPT returned:\n{!s}'
+ return tpl.format(self._solution_dict['status'],
+ self._pretty_print_dict(self._solution_dict))
+
+
+ def __init__(self, solution_dict):
"""
Create a new GameUnsolvableException object.
INPUT:
- - ``status`` -- the failure status code returned by CVXOPT.
-
- - ``solution`` -- a Solution object.
-
- ``solution_dict`` -- the solution dictionary returned from the
cone program.
"""
- tpl = 'Solution failed with error "{:s}".\n' \
- '{!s}\n' \
- 'CVXOPT returned:\n{!s}'
- # TODO: dont convert the solution to a string, we need
- # to output the two values as well.
- self.message = tpl.format(status,
- solution,
- self.pretty_print_dict(solution_dict))
+ self._solution_dict = solution_dict
+
+
+ def _pretty_print_dict(self, solution_dict):
+ """
+ Return a pretty-printed string representation of a CVXOPT
+ solution dictionary.
+ """
+ result = ''
+ for (k,v) in solution_dict.items():
+ if isinstance(v, matrix):
+ # Display matrices on their own lines, indented.
+ result += ' {:s}:'.format(k)
+ colvec = '\n{!s}'.format(v)
+ result += '\n '.join(colvec.splitlines())
+ result += '\n'
+ else:
+ result += ' {:s}: {!s}\n'.format(k,v)
+
+ return result
printing.options['dformat'] = '%.7f'
solvers.options['show_progress'] = False
+
class Solution:
"""
A representation of the solution of a linear game. It should contain
the value of the game, and both players' strategies.
"""
- def __init__(self, p1_value, p2_value, p1_optimal, p2_optimal):
- self._player1_value = p1_value
- self._player2_value = p2_value
+ def __init__(self, game_value, p1_optimal, p2_optimal):
+ self._game_value = game_value
self._player1_optimal = p1_optimal
self._player2_optimal = p2_optimal
* The optimal strategy of player two.
"""
- # The string representations of the player strategy matrices
- # already contain trailing newlines.
+
tpl = 'Game value: {:.7f}\n' \
- 'Player 1 optimal: {!s}' \
- 'Player 2 optimal: {!s}'
- return tpl.format(self.game_value(),
- self.player1_optimal().trans(),
- self.player2_optimal().trans())
+ 'Player 1 optimal:{:s}\n' \
+ 'Player 2 optimal:{:s}\n'
+
+ p1 = '\n{!s}'.format(self.player1_optimal())
+ p1 = '\n '.join(p1.splitlines())
+ p2 = '\n{!s}'.format(self.player2_optimal())
+ p2 = '\n '.join(p2.splitlines())
+
+ return tpl.format(self.game_value(), p1, p2)
- def game_value(self):
- return ((self.player1_value() + self.player2_value()) / 2.0)
- def player1_value(self):
- return self._player1_value
+ def game_value(self):
+ return self._game_value
- def player2_value(self):
- return self._player2_value
def player1_optimal(self):
return self._player1_optimal
+
def player2_optimal(self):
return self._player2_optimal
A = matrix([0, self._e1], (1, K.dimension() + 1), 'd')
soln_dict = solvers.conelp(c, G, h, C.cvxopt_dims(), A, b)
+
+ if soln_dict['status'] != 'optimal':
+ raise GameUnsolvableException(soln_dict)
+
p1_value = soln_dict['x'][0]
- p2_value = soln_dict['y'][0]
p1_optimal = soln_dict['x'][1:]
p2_optimal = soln_dict['z'][self._K.dimension():]
- soln = Solution(p1_value, p2_value, p1_optimal, p2_optimal)
-
- #if soln_dict['status'] != 'optimal':
- raise GameUnsolvableException(soln_dict['status'], soln, soln_dict)
- return soln
+ return Solution(p1_value, p1_optimal, p2_optimal)