]> gitweb.michael.orlitzky.com - dunshire.git/commitdiff
Play with the error/solution formatting some more.
authorMichael Orlitzky <michael@orlitzky.com>
Thu, 6 Oct 2016 13:11:49 +0000 (09:11 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Thu, 6 Oct 2016 13:11:49 +0000 (09:11 -0400)
errors.py
symmetric_linear_game.py

index 028f5e72ca5a8f223fe1766a95c9de5cf25e3ec9..f46c4a46b6cdf46d7e1ba37e29246163bb78a692 100644 (file)
--- a/errors.py
+++ b/errors.py
@@ -4,53 +4,48 @@ Errors that can occur when solving a linear game.
 
 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
index 8c37c66c4cbe7c21aa85bdd37fa4cf7c2aabdd5a..694e09f6a9f21930ee028d732f96ddda9cdbb553 100644 (file)
@@ -7,14 +7,14 @@ from matrices import append_col, append_row, identity
 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
 
@@ -29,27 +29,27 @@ class Solution:
           * 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
 
@@ -113,13 +113,12 @@ class SymmetricLinearGame:
         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)