+ >>> from dunshire import *
+ >>> K = NonnegativeOrthant(3)
+ >>> L = [[4,5,6],[7,8,9],[10,11,12]]
+ >>> e1 = [1,2,3]
+ >>> e2 = [1,1,1]
+ >>> SLG = SymmetricLinearGame(L, K, e1, e2)
+ >>> print(SLG._h())
+ [0.0000000]
+ [0.0000000]
+ [0.0000000]
+ [0.0000000]
+ [0.0000000]
+ [0.0000000]
+ <BLANKLINE>
+
+ """
+
+ return matrix([self._zero(), self._zero()])
+
+ def _b(self):
+ """
+ Return the ``b`` vector used in our CVXOPT construction.
+
+ The vector ``b`` appears on the right-hand side of :math:`Ax =
+ b` in the statement of the CVXOPT conelp program.
+
+ .. warning::
+
+ It is not safe to cache any of the matrices passed to
+ CVXOPT, because it can clobber them.
+
+ Returns
+ -------
+
+ matrix
+ A ``1``-by-``1`` matrix containing a single entry ``1``.
+
+ Examples
+ --------
+
+ >>> from dunshire import *
+ >>> K = NonnegativeOrthant(3)
+ >>> L = [[4,5,6],[7,8,9],[10,11,12]]
+ >>> e1 = [1,2,3]
+ >>> e2 = [1,1,1]
+ >>> SLG = SymmetricLinearGame(L, K, e1, e2)
+ >>> print(SLG._b())
+ [1.0000000]
+ <BLANKLINE>
+
+ """
+ return matrix([1], tc='d')
+
+
+ def _try_solution(self, tolerance):
+ """
+ Solve this linear game within ``tolerance``, if possible.
+
+ This private function is the one that does all of the actual
+ work for :meth:`solution`. This method accepts a ``tolerance``,
+ and what :meth:`solution` does is call this method twice with
+ two different tolerances. First it tries a strict tolerance, and
+ then it tries a looser one.
+
+ .. warning::
+
+ If you try to be smart and precompute the matrices used by
+ this function (the ones passed to ``conelp``), then you're
+ going to shoot yourself in the foot. CVXOPT can and will
+ clobber some (but not all) of its input matrices. This isn't
+ performance sensitive, so play it safe.
+
+ Parameters
+ ----------
+
+ tolerance : float
+ The absolute tolerance to pass to the CVXOPT solver.
+
+ 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 game can be solved easily, so the first attempt in
+ :meth:`solution` should succeed::
+
+ >>> from dunshire import *
+ >>> from dunshire.matrices import norm
+ >>> from dunshire.options import ABS_TOL
+ >>> 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)
+ >>> s1 = SLG.solution()
+ >>> s2 = SLG._try_solution(options.ABS_TOL)
+ >>> abs(s1.game_value() - s2.game_value()) < ABS_TOL
+ True
+ >>> norm(s1.player1_optimal() - s2.player1_optimal()) < ABS_TOL
+ True
+ >>> norm(s1.player2_optimal() - s2.player2_optimal()) < ABS_TOL
+ True
+
+ """
+ try:
+ solvers.options['show_progress'] = options.VERBOSE
+ solvers.options['abs_tol'] = tolerance
+ soln_dict = solvers.conelp(self._c(),
+ self._G(),
+ self._h(),
+ self._C().cvxopt_dims(),
+ self._A(),
+ self._b())
+ except ValueError as e:
+ if str(e) == 'math domain error':
+ # Oops, CVXOPT tried to take the square root of a
+ # negative number. Report some details about the game
+ # rather than just the underlying CVXOPT crash.
+ raise PoorScalingException(self)
+ else:
+ raise e