From: Michael Orlitzky Date: Mon, 10 Oct 2016 02:05:07 +0000 (-0400) Subject: Transpose the input matrix "L" by default and document that fact. X-Git-Tag: 0.1.0~182 X-Git-Url: https://gitweb.michael.orlitzky.com/?a=commitdiff_plain;h=3184c09e1f747dbd1dc4fadd156d6107dbc89414;p=dunshire.git Transpose the input matrix "L" by default and document that fact. --- diff --git a/src/dunshire/symmetric_linear_game.py b/src/dunshire/symmetric_linear_game.py index 968d9ca..857b064 100644 --- a/src/dunshire/symmetric_linear_game.py +++ b/src/dunshire/symmetric_linear_game.py @@ -106,22 +106,106 @@ class SymmetricLinearGame: """ INPUT: - - ``L`` -- an n-by-b matrix represented as a list of lists - of real numbers. + - ``L`` -- an square matrix represented as a list of lists + of real numbers. ``L`` itself is interpreted as a list of + ROWS, which agrees with (for example) SageMath and NumPy, + but not with CVXOPT (whose matrix constructor accepts a + list of columns). - ``K`` -- a SymmetricCone instance. - - ``e1`` -- the interior point of ``K`` belonging to player one, - as a column vector. + - ``e1`` -- the interior point of ``K`` belonging to player one; + it can be of any enumerable type having the correct length. - - ``e2`` -- the interior point of ``K`` belonging to player two, - as a column vector. + - ``e2`` -- the interior point of ``K`` belonging to player two; + it can be of any enumerable type having the correct length. + EXAMPLES: + + Lists can (and probably should) be used for every argument: + + >>> from cones import NonnegativeOrthant + >>> K = NonnegativeOrthant(2) + >>> L = [[1,0],[0,1]] + >>> e1 = [1,1] + >>> e2 = [1,1] + >>> G = SymmetricLinearGame(L, K, e1, e2) + >>> print(G) + The linear game (L, K, e1, e2) where + L = [ 1 0] + [ 0 1], + K = Nonnegative orthant in the real 2-space, + e1 = [ 1] + [ 1], + e2 = [ 1] + [ 1]. + + The points ``e1`` and ``e2`` can also be passed as some other + enumerable type (of the correct length) without much harm, since + there is no row/column ambiguity: + + >>> import cvxopt + >>> import numpy + >>> from cones import NonnegativeOrthant + >>> K = NonnegativeOrthant(2) + >>> L = [[1,0],[0,1]] + >>> e1 = cvxopt.matrix([1,1]) + >>> e2 = numpy.matrix([1,1]) + >>> G = SymmetricLinearGame(L, K, e1, e2) + >>> print(G) + The linear game (L, K, e1, e2) where + L = [ 1 0] + [ 0 1], + K = Nonnegative orthant in the real 2-space, + e1 = [ 1] + [ 1], + e2 = [ 1] + [ 1]. + + However, ``L`` will always be intepreted as a list of rows, even + if it is passed as a ``cvxopt.base.matrix`` which is otherwise + indexed by columns: + + >>> import cvxopt + >>> from cones import NonnegativeOrthant + >>> K = NonnegativeOrthant(2) + >>> L = [[1,2],[3,4]] + >>> e1 = [1,1] + >>> e2 = e1 + >>> G = SymmetricLinearGame(L, K, e1, e2) + >>> print(G) + The linear game (L, K, e1, e2) where + L = [ 1 2] + [ 3 4], + K = Nonnegative orthant in the real 2-space, + e1 = [ 1] + [ 1], + e2 = [ 1] + [ 1]. + >>> L = cvxopt.matrix(L) + >>> print(L) + [ 1 3] + [ 2 4] + + >>> G = SymmetricLinearGame(L, K, e1, e2) + >>> print(G) + The linear game (L, K, e1, e2) where + L = [ 1 2] + [ 3 4], + K = Nonnegative orthant in the real 2-space, + e1 = [ 1] + [ 1], + e2 = [ 1] + [ 1]. """ self._K = K self._e1 = matrix(e1, (K.dimension(), 1)) self._e2 = matrix(e2, (K.dimension(), 1)) - self._L = matrix(L, (K.dimension(), K.dimension())) + + # Our input ``L`` is indexed by rows but CVXOPT matrices are + # indexed by columns, so we need to transpose the input before + # feeding it to CVXOPT. + self._L = matrix(L, (K.dimension(), K.dimension())).trans() if not K.contains_strict(self._e1): raise ValueError('the point e1 must lie in the interior of K') @@ -137,7 +221,7 @@ class SymmetricLinearGame: >>> from cones import NonnegativeOrthant >>> K = NonnegativeOrthant(3) - >>> L = [[1,-1,-12],[-5,2,-15],[-15,-3,1]] + >>> L = [[1,-5,-15],[-1,2,-3],[-12,-15,1]] >>> e1 = [1,1,1] >>> e2 = [1,2,3] >>> SLG = SymmetricLinearGame(L, K, e1, e2) @@ -160,10 +244,10 @@ class SymmetricLinearGame: ' K = {!s},\n' \ ' e1 = {:s},\n' \ ' e2 = {:s}.' - L_str = '\n '.join(str(self._L).splitlines()) - e1_str = '\n '.join(str(self._e1).splitlines()) - e2_str = '\n '.join(str(self._e2).splitlines()) - return tpl.format(L_str, str(self._K), e1_str, e2_str) + indented_L = '\n '.join(str(self._L).splitlines()) + indented_e1 = '\n '.join(str(self._e1).splitlines()) + indented_e2 = '\n '.join(str(self._e2).splitlines()) + return tpl.format(indented_L, str(self._K), indented_e1, indented_e2) def solution(self): @@ -186,7 +270,7 @@ class SymmetricLinearGame: >>> from cones import NonnegativeOrthant >>> K = NonnegativeOrthant(3) - >>> L = [[1,-1,-12],[-5,2,-15],[-15,-3,1]] + >>> L = [[1,-5,-15],[-1,2,-3],[-12,-15,1]] >>> e1 = [1,1,1] >>> e2 = [1,1,1] >>> SLG = SymmetricLinearGame(L, K, e1, e2) @@ -277,7 +361,7 @@ class SymmetricLinearGame: >>> from cones import NonnegativeOrthant >>> K = NonnegativeOrthant(3) - >>> L = [[1,-1,-12],[-5,2,-15],[-15,-3,1]] + >>> L = [[1,-5,-15],[-1,2,-3],[-12,-15,1]] >>> e1 = [1,1,1] >>> e2 = [1,2,3] >>> SLG = SymmetricLinearGame(L, K, e1, e2) @@ -295,7 +379,7 @@ class SymmetricLinearGame: [ 1]. """ - return SymmetricLinearGame(self._L.trans(), + return SymmetricLinearGame(self._L, # It will be transposed in __init__(). self._K, # Since "K" is symmetric. self._e2, self._e1)