]> gitweb.michael.orlitzky.com - dunshire.git/blobdiff - dunshire/errors.py
Use "..." for floating point output in doctests.
[dunshire.git] / dunshire / errors.py
index b63344a0311e9c843cdeb189c903902de4a2179b..424f3e62352848c7f673375e401da18c25cdbb98 100644 (file)
@@ -49,6 +49,9 @@ class GameUnsolvableException(Exception):
     Parameters
     ----------
 
     Parameters
     ----------
 
+    game : SymmetricLinearGame
+        A copy of the game whose solution failed.
+
     solution_dict : dict
         The solution dictionary returned from the failed cone program.
 
     solution_dict : dict
         The solution dictionary returned from the failed cone program.
 
@@ -87,7 +90,8 @@ class GameUnsolvableException(Exception):
          e1 = [1.0000000]
               [0.1000000],
          e2 = [3.0000000]
          e1 = [1.0000000]
               [0.1000000],
          e2 = [3.0000000]
-              [0.1000000].
+              [0.1000000],
+         Condition((L, K, e1, e2)) = 4.155...
        CVXOPT returned:
          dual infeasibility: None
          dual objective: 1.0
        CVXOPT returned:
          dual infeasibility: None
          dual objective: 1.0
@@ -114,7 +118,7 @@ class GameUnsolvableException(Exception):
     """
     def __init__(self, game, solution_dict):
         """
     """
     def __init__(self, game, solution_dict):
         """
-        Create a new GameUnsolvableException object.
+        Create a new :class:`GameUnsolvableException` object.
         """
         super().__init__()
         self._game = game
         """
         super().__init__()
         self._game = game
@@ -127,7 +131,7 @@ class GameUnsolvableException(Exception):
 
         The returned representation highlights the "status" field of the
         CVXOPT dictionary, since that should explain what went
 
         The returned representation highlights the "status" field of the
         CVXOPT dictionary, since that should explain what went
-        wrong. The game details and full CVXOPT solution dictionary is
+        wrong. The game details and full CVXOPT solution dictionary are
         included after the status.
         """
         tpl = 'Solution failed with result "{:s}."\n' \
         included after the status.
         """
         tpl = 'Solution failed with result "{:s}."\n' \
@@ -137,3 +141,76 @@ class GameUnsolvableException(Exception):
         # Indent the whole dict by two spaces.
         cvx_str = '\n  '.join(cvx_lines)
         return tpl.format(self._solution_dict['status'], self._game, cvx_str)
         # Indent the whole dict by two spaces.
         cvx_str = '\n  '.join(cvx_lines)
         return tpl.format(self._solution_dict['status'], self._game, cvx_str)
+
+
+class PoorScalingException(Exception):
+    """
+    An exception raised when poor scaling leads to solution errors.
+
+    Under certain circumstances, a problem that should be solvable can
+    trigger errors in CVXOPT. The end result is the following
+    :class:`ValueError`::
+
+        Traceback (most recent call last):
+        ...
+          return math.sqrt(x[offset] - a) * math.sqrt(x[offset] + a)
+        ValueError: math domain error
+
+    This happens when one of the arguments to :func:`math.sqrt` is
+    negative, but the underlying cause is elusive. We're blaming it on
+    "poor scaling," whatever that means.
+
+    Similar issues have been discussed a few times on the CVXOPT mailing
+    list; for example,
+
+    1. https://groups.google.com/forum/#!msg/cvxopt/TeQGdc2b4Xc/j5_mQME_rvUJ
+    2. https://groups.google.com/forum/#!topic/cvxopt/HZrRfaoM0pk
+    3. https://groups.google.com/forum/#!topic/cvxopt/riFSxB31zU4
+
+    Parameters
+    ----------
+
+    game : SymmetricLinearGame
+        A copy of the game whose solution failed.
+
+    Examples
+    --------
+
+       >>> from dunshire import *
+       >>> K = IceCream(2)
+       >>> L = [[1,2],[3,4]]
+       >>> e1 = [1, 0.1]
+       >>> e2 = [3, 0.1]
+       >>> G = SymmetricLinearGame(L,K,e1,e2)
+       >>> print(PoorScalingException(G))
+       Solution failed due to poor scaling.
+       The linear game (L, K, e1, e2) where
+         L = [ 1  2]
+             [ 3  4],
+         K = Lorentz "ice cream" cone in the real 2-space,
+         e1 = [1.0000000]
+              [0.1000000],
+         e2 = [3.0000000]
+              [0.1000000],
+         Condition((L, K, e1, e2)) = 4.155...
+       <BLANKLINE>
+    """
+    def __init__(self, game):
+        """
+        Create a new :class:`PoorScalingException` object.
+        """
+        super().__init__()
+        self._game = game
+
+
+    def __str__(self):
+        """
+        Return a string representation of this exception.
+
+        Pretty much all we can say is that there was poor scaling; that
+        is, that CVXOPT failed. The game details are included after
+        that.
+        """
+        tpl = 'Solution failed due to poor scaling.\n' \
+              '{!s}\n'
+        return tpl.format(self._game)