- def solution(self):
- """
- Solve this linear game and return a :class:`Solution`.
-
- Returns
- -------
-
- :class:`Solution`
- A :class:`Solution` object describing the game's value and
- the optimal strategies of both players.
-
- Raises
- ------
- GameUnsolvableException
- If the game could not be solved (if an optimal solution to its
- associated cone program was not found).
-
- PoorScalingException
- If the game could not be solved because CVXOPT crashed while
- trying to take the square root of a negative number.
-
- Examples
- --------
-
- This example is computed in Gowda and Ravindran in the section
- "The value of a Z-transformation"::
-
- >>> from dunshire import *
- >>> K = NonnegativeOrthant(3)
- >>> L = [[1,-5,-15],[-1,2,-3],[-12,-15,1]]
- >>> e1 = [1,1,1]
- >>> e2 = [1,1,1]
- >>> SLG = SymmetricLinearGame(L, K, e1, e2)
- >>> print(SLG.solution())
- Game value: -6.1724138
- Player 1 optimal:
- [ 0.551...]
- [-0.000...]
- [ 0.448...]
- Player 2 optimal:
- [0.448...]
- [0.000...]
- [0.551...]
-
- The value of the following game can be computed using the fact
- that the identity is invertible::
-
- >>> from dunshire import *
- >>> K = NonnegativeOrthant(3)
- >>> L = [[1,0,0],[0,1,0],[0,0,1]]
- >>> e1 = [1,2,3]
- >>> e2 = [4,5,6]
- >>> SLG = SymmetricLinearGame(L, K, e1, e2)
- >>> print(SLG.solution())
- Game value: 0.0312500
- Player 1 optimal:
- [0.031...]
- [0.062...]
- [0.093...]
- Player 2 optimal:
- [0.125...]
- [0.156...]
- [0.187...]
+ # The "optimal" and "unknown" results, we actually treat the
+ # same. Even if CVXOPT bails out due to numerical difficulty,
+ # it will have some candidate points in mind. If those
+ # candidates are good enough, we take them. We do the same
+ # check (perhaps pointlessly so) for "optimal" results.
+ #
+ # First we check that the primal/dual objective values are
+ # close enough (one could be low by ABS_TOL, the other high by
+ # it) because otherwise CVXOPT might return "unknown" and give
+ # us two points in the cone that are nowhere near optimal.
+ if abs(p1_value - p2_value) > 2*options.ABS_TOL:
+ printing.options['dformat'] = options.DEBUG_FLOAT_FORMAT
+ raise GameUnsolvableException(self, soln_dict)