+ 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...]
+
+ """
+ try:
+ # First try with a stricter tolerance. Who knows, it might
+ # work. If it does, we prefer that solution.
+ return self._try_solution(options.ABS_TOL / 10)
+
+ except (PoorScalingException, GameUnsolvableException):
+ # Ok, that didn't work. Let's try it with the default
+ # tolerance, and whatever happens, happens.
+ return self._try_solution(tolerance = options.ABS_TOL)
+
+
+ def condition(self):
+ r"""
+ Return the condition number of this game.
+
+ In the CVXOPT construction of this game, two matrices ``G`` and
+ ``A`` appear. When those matrices are nasty, numerical problems
+ can show up. We define the condition number of this game to be
+ the average of the condition numbers of ``G`` and ``A`` in the
+ CVXOPT construction. If the condition number of this game is
+ high, then you can expect numerical difficulty (such as
+ :class:`PoorScalingException`).
+
+ Returns
+ -------
+
+ float
+ A real number greater than or equal to one that measures how
+ bad this game is numerically.
+
+ Examples
+ --------
+
+ >>> from dunshire import *
+ >>> K = NonnegativeOrthant(1)
+ >>> L = [[1]]
+ >>> e1 = [1]
+ >>> e2 = e1
+ >>> SLG = SymmetricLinearGame(L, K, e1, e2)
+ >>> actual = SLG.condition()
+ >>> expected = 1.8090169943749477
+ >>> abs(actual - expected) < options.ABS_TOL
+ True
+
+ """
+ return (condition_number(self._G()) + condition_number(self._A()))/2
+
+