From 92c9e3f2e7d685477cf8227d85faf8642059fd98 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Thu, 6 Oct 2016 17:10:40 -0400 Subject: [PATCH] Add doctests for the solution of some easy games. --- TODO | 3 - src/dunshire/symmetric_linear_game.py | 114 +++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 7 deletions(-) diff --git a/TODO b/TODO index aaf796f..b38d65a 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,3 @@ -1. Add doctests for simple examples like the ones in Dr. Gowda's paper - and the identity operator. - 2. Add unit testing for crazier things like random invertible matrices. 6. Add real docstrings everywhere. diff --git a/src/dunshire/symmetric_linear_game.py b/src/dunshire/symmetric_linear_game.py index 07385d7..968d9ca 100644 --- a/src/dunshire/symmetric_linear_game.py +++ b/src/dunshire/symmetric_linear_game.py @@ -39,11 +39,21 @@ class Solution: * The optimal strategy of player one. * The optimal strategy of player two. - """ + EXAMPLES: + + >>> print(Solution(10, matrix([1,2]), matrix([3,4]))) + Game value: 10.0000000 + Player 1 optimal: + [ 1] + [ 2] + Player 2 optimal: + [ 3] + [ 4] + """ tpl = 'Game value: {:.7f}\n' \ 'Player 1 optimal:{:s}\n' \ - 'Player 2 optimal:{:s}\n' + 'Player 2 optimal:{:s}' p1_str = '\n{!s}'.format(self.player1_optimal()) p1_str = '\n '.join(p1_str.splitlines()) @@ -122,8 +132,39 @@ class SymmetricLinearGame: def __str__(self): """ Return a string representatoin of this game. + + EXAMPLES: + + >>> from cones import NonnegativeOrthant + >>> K = NonnegativeOrthant(3) + >>> L = [[1,-1,-12],[-5,2,-15],[-15,-3,1]] + >>> e1 = [1,1,1] + >>> e2 = [1,2,3] + >>> SLG = SymmetricLinearGame(L, K, e1, e2) + >>> print(SLG) + The linear game (L, K, e1, e2) where + L = [ 1 -5 -15] + [ -1 2 -3] + [-12 -15 1], + K = Nonnegative orthant in the real 3-space, + e1 = [ 1] + [ 1] + [ 1], + e2 = [ 1] + [ 2] + [ 3]. + """ - return "a game" + tpl = 'The linear game (L, K, e1, e2) where\n' \ + ' L = {:s},\n' \ + ' 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) + def solution(self): """ @@ -137,6 +178,49 @@ class SymmetricLinearGame: could *not* be solved -- which should never happen -- then a GameUnsolvableException is raised. It can be printed to get the raw output from CVXOPT. + + EXAMPLES: + + This example is computed in Gowda and Ravindran in the section + "The value of a Z-transformation": + + >>> from cones import NonnegativeOrthant + >>> K = NonnegativeOrthant(3) + >>> L = [[1,-1,-12],[-5,2,-15],[-15,-3,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.5517241] + [-0.0000000] + [ 0.4482759] + Player 2 optimal: + [0.4482759] + [0.0000000] + [0.5517241] + + The value of the following game can be computed using the fact + that the identity is invertible: + + >>> from cones import NonnegativeOrthant + >>> 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.0312500] + [0.0625000] + [0.0937500] + Player 2 optimal: + [0.1250000] + [0.1562500] + [0.1875000] + """ # The cone "C" that appears in the statement of the CVXOPT # conelp program. @@ -164,7 +248,7 @@ class SymmetricLinearGame: # The matrix "A" that appears on the right-hand side of Ax = b # in the statement of the CVXOPT conelp program. - A = matrix([0, self._e1], (1, self._K.dimension() + 1), 'd') + A = matrix([0, self._e2], (1, self._K.dimension() + 1), 'd') # Actually solve the thing and obtain a dictionary describing # what happened. @@ -188,6 +272,28 @@ class SymmetricLinearGame: def dual(self): """ Return the dual game to this game. + + EXAMPLES: + + >>> from cones import NonnegativeOrthant + >>> K = NonnegativeOrthant(3) + >>> L = [[1,-1,-12],[-5,2,-15],[-15,-3,1]] + >>> e1 = [1,1,1] + >>> e2 = [1,2,3] + >>> SLG = SymmetricLinearGame(L, K, e1, e2) + >>> print(SLG.dual()) + The linear game (L, K, e1, e2) where + L = [ 1 -1 -12] + [ -5 2 -15] + [-15 -3 1], + K = Nonnegative orthant in the real 3-space, + e1 = [ 1] + [ 2] + [ 3], + e2 = [ 1] + [ 1] + [ 1]. + """ return SymmetricLinearGame(self._L.trans(), self._K, # Since "K" is symmetric. -- 2.44.2