Developer API Documentation¶
This section contains API documentation that is of interest to developers, but not so much to end users. It documents our internal modules, exceptions, the test suite, and supporting code.
dunshire.errors module¶
Errors that can occur when solving a linear game.

exception
GameUnsolvableException
(game, solution_dict)[source]¶ Bases:
Exception
An exception raised when a game cannot be solved.
Every linear game has a solution. If we can’t solve the conic program associated with a linear game, then something is wrong with either the model or the input, and this exception should be raised.
Parameters:  game (SymmetricLinearGame) – A copy of the game whose solution failed.
 solution_dict (dict) – The solution dictionary returned from the failed cone program.
Examples
>>> from dunshire import * >>> K = IceCream(2) >>> L = [[1,2],[3,4]] >>> e1 = [1, 0.1] >>> e2 = [3, 0.1] >>> G = SymmetricLinearGame(L,K,e1,e2) >>> d = {'residual as dual infeasibility certificate': None, ... 'y': matrix([1,1]), ... 'dual slack': 8.779496368228267e10, ... 'z': matrix([1,1,0,0]), ... 's': None, ... 'primal infeasibility': None, ... 'status': 'primal infeasible', ... 'dual infeasibility': None, ... 'relative gap': None, ... 'iterations': 5, ... 'primal slack': None, ... 'x': None, ... 'dual objective': 1.0, ... 'primal objective': None, ... 'gap': None, ... 'residual as primal infeasibility certificate': ... 3.986246886102996e09} >>> print(GameUnsolvableException(G,d)) Solution failed with result "primal infeasible." The linear game (L, K, e1, e2) where L = [ 1 2] [ 3 4], K = Lorentz "ice cream" cone in the real 2space, e1 = [1.0000000] [0.1000000], e2 = [3.0000000] [0.1000000] CVXOPT returned: dual infeasibility: None dual objective: 1.0 dual slack: 8.779496368228267e10 gap: None iterations: 5 primal infeasibility: None primal objective: None primal slack: None relative gap: None residual as dual infeasibility certificate: None residual as primal infeasibility certificate: 3.986246886102996e09 s: None status: primal infeasible x: None y: [ 1] [ 1] z: [ 1] [ 1] [ 0] [ 0]

exception
PoorScalingException
(game)[source]¶ Bases:
Exception
An exception raised when poor scaling leads to solution errors.
Under certain circumstances, a problem that should be solvable can trigger errors in CVXOPT. The end result is the following
ValueError
:Traceback (most recent call last): ... return math.sqrt(x[offset]  a) * math.sqrt(x[offset] + a) ValueError: math domain error
This happens when one of the arguments to
math.sqrt()
is negative, but the underlying cause is elusive. We’re blaming it on “poor scaling,” whatever that means.Similar issues have been discussed a few times on the CVXOPT mailing list; for example,
 https://groups.google.com/forum/#!msg/cvxopt/TeQGdc2b4Xc/j5_mQME_rvUJ
 https://groups.google.com/forum/#!topic/cvxopt/HZrRfaoM0pk
 https://groups.google.com/forum/#!topic/cvxopt/riFSxB31zU4
Parameters: game (SymmetricLinearGame) – A copy of the game whose solution failed. Examples
>>> from dunshire import * >>> K = IceCream(2) >>> L = [[1,2],[3,4]] >>> e1 = [1, 0.1] >>> e2 = [3, 0.1] >>> G = SymmetricLinearGame(L,K,e1,e2) >>> print(PoorScalingException(G)) Solution failed due to poor scaling. The linear game (L, K, e1, e2) where L = [ 1 2] [ 3 4], K = Lorentz "ice cream" cone in the real 2space, e1 = [1.0000000] [0.1000000], e2 = [3.0000000] [0.1000000]
dunshire.matrices module¶
Utility functions for working with CVXOPT matrices (instances of the class:cvxopt.base.matrix class).

append_col
(left, right)[source]¶ Append two matrices sidebyside.
Parameters:  left (matrix) – The “original” matrix, the one that will wind up on the left.
 right (matrix) – The matrix to be appended on the right of
left
.
Returns: A new matrix consisting of
right
appended to the right ofleft
.Return type: matrix
Examples
>>> A = matrix([1,2,3,4], (2,2)) >>> B = matrix([5,6,7,8,9,10], (2,3)) >>> print(A) [ 1 3] [ 2 4] >>> print(B) [ 5 7 9] [ 6 8 10] >>> print(append_col(A,B)) [ 1 3 5 7 9] [ 2 4 6 8 10]

append_row
(top, bottom)[source]¶ Append two matrices toptobottom.
Parameters:  top (matrix) – The “original” matrix, the one that will wind up on top.
 bottom (matrix) – The matrix to be appended below
top
.
Returns: A new matrix consisting of
bottom
appended belowtop
.Return type: matrix
Examples
>>> A = matrix([1,2,3,4], (2,2)) >>> B = matrix([5,6,7,8,9,10], (3,2)) >>> print(A) [ 1 3] [ 2 4] >>> print(B) [ 5 8] [ 6 9] [ 7 10] >>> print(append_row(A,B)) [ 1 3] [ 2 4] [ 5 8] [ 6 9] [ 7 10]

condition_number
(mat)[source]¶ Return the condition number of the given matrix.
The condition number of a matrix quantifies how hard it is to do numerical computation with that matrix. It is usually defined as the ratio of the norm of the matrix to the norm of its inverse, and therefore depends on the norm used. One way to compute the condition number with respect to the 2norm is as the ratio of the matrix’s largest and smallest singular values. Since we have easy access to those singular values, that is the algorithm we use.
The larger the condition number is, the worse the matrix is.
Parameters: mat (matrix) – The matrix whose condition number you want. Returns: The nonnegative condition number of mat
.Return type: float Examples
>>> condition_number(identity(3)) 1.0
>>> A = matrix([[2,1],[1,2]]) >>> abs(condition_number(A)  3.0) < options.ABS_TOL True
>>> A = matrix([[2,1j],[1j,2]]) >>> abs(condition_number(A)  3.0) < options.ABS_TOL True

eigenvalues
(symmat)[source]¶ Return the eigenvalues of the given symmetric real matrix.
On the surface, this appears redundant to the
eigenvalues_re()
function. However, if we know in advance that our input is symmetric, a better algorithm can be used.Parameters: symmat (matrix) – The real symmetric matrix whose eigenvalues you want. Returns: A list of the eigenvalues (in no particular order) of symmat
.Return type: list of float Raises: TypeError
– If the input matrix is not symmetric.Examples
>>> A = matrix([[2,1],[1,2]], tc='d') >>> eigenvalues(A) [1.0, 3.0]
If the input matrix is not symmetric, it may not have real eigenvalues, and we don’t know what to do:
>>> A = matrix([[1,2],[3,4]]) >>> eigenvalues(A) Traceback (most recent call last): ... TypeError: input must be a symmetric real matrix

eigenvalues_re
(anymat)[source]¶ Return the real parts of the eigenvalues of the given square matrix.
Parameters: anymat (matrix) – The square matrix whose eigenvalues you want. Returns: A list of the real parts (in no particular order) of the eigenvalues of anymat
.Return type: list of float Raises: TypeError
– If the input matrix is not square.Examples
This is symmetric and has two real eigenvalues:
>>> A = matrix([[2,1],[1,2]], tc='d') >>> sorted(eigenvalues_re(A)) [1.0, 3.0]
But this rotation matrix has eigenvalues i and i, both of whose real parts are zero:
>>> A = matrix([[0,1],[1,0]]) >>> eigenvalues_re(A) [0.0, 0.0]
If the input matrix is not square, it doesn’t have eigenvalues:
>>> A = matrix([[1,2],[3,4],[5,6]]) >>> eigenvalues_re(A) Traceback (most recent call last): ... TypeError: input matrix must be square

identity
(domain_dim, typecode='i')[source]¶ Create an identity matrix of the given dimensions.
Parameters:  domain_dim (int) – The dimension of the vector space on which the identity will act.
 typecode ({‘i’, ‘d’, ‘z’}, optional) – The type code for the returned matrix, defaults to ‘i’ for integers. Can also be ‘d’ for real double, or ‘z’ for complex double.
Returns: A
domain_dim
bydomain_dim
dense integer identity matrix.Return type: matrix
Raises: ValueError
– If you ask for the identity on zero or fewer dimensions.Examples
>>> print(identity(3)) [ 1 0 0] [ 0 1 0] [ 0 0 1]

inner_product
(vec1, vec2)[source]¶ Compute the Euclidean inner product of two vectors.
Parameters:  vec1 (matrix) – The first vector, whose inner product with
vec2
you want.  vec2 (matrix) – The second vector, whose inner product with
vec1
you want.
Returns: The inner product of
vec1
andvec2
.Return type: float
Raises: TypeError
– If the lengths ofvec1
andvec2
differ.Examples
>>> x = [1,2,3] >>> y = [3,4,1] >>> inner_product(x,y) 14
>>> x = matrix([1,1,1]) >>> y = matrix([2,3,4], (1,3)) >>> inner_product(x,y) 9
>>> x = [1,2,3] >>> y = [1,1] >>> inner_product(x,y) Traceback (most recent call last): ... TypeError: the lengths of vec1 and vec2 must match
 vec1 (matrix) – The first vector, whose inner product with

norm
(matrix_or_vector)[source]¶ Return the Frobenius norm of a matrix or vector.
When the input is a vector, its matrixFrobenius norm is the same thing as its vectorEuclidean norm.
Parameters: matrix_or_vector (matrix) – The matrix or vector whose norm you want. Returns: The norm of matrix_or_vector
.Return type: float Examples
>>> v = matrix([1,1]) >>> norm(v) 1.414...
>>> A = matrix([1,1,1,1], (2,2)) >>> norm(A) 2.0...

specnorm
(mat)[source]¶ Return the spectral norm of a matrix.
The spectral norm of a matrix is its largest singular value, and it corresponds to the operator norm induced by the vector Euclidean norm.
Parameters:  mat (matrix) – The matrix whose spectral norm you want.
 Examples –
>>> specnorm(identity(3)) 1.0
>>> specnorm(5*identity(4)) 5.0

vec
(mat)[source]¶ Create a long vector in columnmajor order from
mat
.Parameters: mat (matrix) – Any sort of real matrix that you want written as a long vector. Returns: An len(mat)
by1
long column vector containign the entries ofmat
in column major order.Return type: matrix Examples
>>> A = matrix([[1,2],[3,4]]) >>> print(A) [ 1 3] [ 2 4]
>>> print(vec(A)) [ 1] [ 2] [ 3] [ 4]
Note that if
mat
is a vector, this function is a noop:>>> v = matrix([1,2,3,4], (4,1)) >>> print(v) [ 1] [ 2] [ 3] [ 4] >>> print(vec(v)) [ 1] [ 2] [ 3] [ 4]
dunshire.options module¶
A place to collect the various options that “can be passed to the underlying engine.” Just kidding, they’re constants and you can’t change them. But this makes the user interface real simple.

ABS_TOL
= 1e06¶ The absolute tolerance used in all “are these numbers equal” and “is this number less than (or equal to) that other number” tests. The CVXOPT default is
1e7
, but loosening that a little reduces the number of “unknown” solutions that we get during random testing. Whether or not it improves the solubility of real problems is a question for the philosophers.

DEBUG_FLOAT_FORMAT
= '%.20f'¶ The float output format to use when something goes wrong. If we need to reproduce a random test case, for example, then we need all of the digits of the things involved. If we try to recreate the problem using only, say, the first seven digits of each number, then the resulting game might not reproduce the failure.

FLOAT_FORMAT
= '%.7f'¶ The default output format for floating point numbers.
test module¶
The whole test suite.
This module compiles the doctests and unittests from the rest of the
codebase into one big TestSuite() and the runs it. It also provides a
function build_suite()
that merely builds the suite; the result
can be used by setuptools.
test.matrices_test¶
Unit tests for the functions in the dunshire.matrices
module.

class
AppendColTest
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
Tests for the
append_col()
function.

class
AppendRowTest
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
Tests for the
dunshire.matrices.append_row()
function.

class
ConditionNumberTest
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
Tests for the
dunshire.matrices.condition_number()
function.

class
EigenvaluesRealPartTest
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
Tests for the
dunshire.matrices.eigenvalues_re()
function.
test_eigenvalues_re_input_not_clobbered
()[source]¶ The eigenvalue functions provided by CVXOPT/LAPACK like to overwrite the matrices that you pass into them as arguments. This test makes sure that our
dunshire.matrices.eigenvalues_re()
function does not do the same.We use a
deepcopy
here in case thecopy
used in thedunshire.matrices.eigenvalues_re()
function is insufficient. Ifcopy
didn’t work and this test used it too, then this test would pass when it shouldn’t.


class
EigenvaluesTest
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
Tests for the
dunshire.matrices.eigenvalues()
function.
test_eigenvalues_input_not_clobbered
()[source]¶ The eigenvalue functions provided by CVXOPT/LAPACK like to overwrite the matrices that you pass into them as arguments. This test makes sure that our
eigenvalues()
function does not do the same.We use a
deepcopy
here in case thecopy
used in theeigenvalues()
function is insufficient. Ifcopy
didn’t work and this test used it too, then this test would pass when it shouldn’t.

test_eigenvalues_of_symmat_are_real
()[source]¶ A real symmetric matrix has real eigenvalues, so if we start with a symmetric matrix, then the two functions
dunshire.matrices.eigenvalues()
anddunshire.matrices.eigenvalues_re()
should agree on it.


class
InnerProductTest
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
Tests for the
dunshire.matrices.inner_product()
function.
test_inner_product_with_self_is_norm_squared
()[source]¶ Ensure that the func:dunshire.matrices.inner_product and
dunshire.matrices.norm()
functions are compatible by checking that the square of the norm of a vector is its inner product with itself.


class
NormTest
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
Tests for the
dunshire.matrices.norm()
function.
test.randomgen¶
Random thing generators used in the rest of the test suite.

MAX_COND
= 125¶ The maximum condition number of a randomlygenerated game. When the condition number of the games gets too high, we start to see
PoorScalingException
being thrown. There’s no science to choosing the upper bound – it got lowered until those exceptions stopped popping up. It’s at125
because129
doesn’t work.

RANDOM_MAX
= 10¶ When generating random real numbers or integers, this is used as the largest allowed magnitude. It keeps our condition numbers down and other properties within reason.

random_diagonal_matrix
(dims)[source]¶ Generate a random square matrix with zero offdiagonal entries.
These matrices are Lyapunovlike on the nonnegative orthant, as is fairly easy to see.
Parameters: dims (int) – The number of rows/columns you want in the returned matrix. Returns: A new matrix whose diagonal entries are random floats chosen using random_scalar()
and whose offdiagonal entries are zero.Return type: matrix Examples
>>> A = random_diagonal_matrix(3) >>> A.size (3, 3) >>> A[0,1] == A[0,2] == A[1,0] == A[2,0] == A[1,2] == A[2,1] == 0 True

random_icecream_game
()[source]¶ Generate a random game over the icecream cone.
We generate each of
L
,K
,e1
, ande2
randomly within the constraints of the icecream cone, and then construct a game from them. The process is repeated until we generate a game with a condition number underMAX_COND
.Returns: A random game over some icecream cone. Return type: SymmetricLinearGame Examples
>>> random_icecream_game() <dunshire.games.SymmetricLinearGame object at 0x...>

random_ll_icecream_game
()[source]¶ Return a random Lyapunov game over some icecream cone.
We first construct a
random_icecream_game()
and then modify it to have arandom_lyapunov_like_icecream()
operator. That process is repeated until the condition number of the resulting game is withinMAX_COND
.Returns: A random game over some icecream cone whose dunshire.games.SymmetricLinearGame.payoff()
method is based on a Lyapunovlikedunshire.games.SymmetricLinearGame.L()
operator.Return type: SymmetricLinearGame Examples
>>> random_ll_icecream_game() <dunshire.games.SymmetricLinearGame object at 0x...>

random_ll_orthant_game
()[source]¶ Return a random Lyapunov game over some nonnegative orthant.
We first construct a
random_orthant_game()
and then modify it to have arandom_diagonal_matrix()
as its operator. Such things are Lyapunovlike on the nonnegative orthant. That process is repeated until the condition number of the resulting game is withinMAX_COND
.Returns: A random game over some nonnegative orthant whose dunshire.games.SymmetricLinearGame.payoff()
method is based on a Lyapunovlikedunshire.games.SymmetricLinearGame.L()
operator.Return type: SymmetricLinearGame Examples
>>> random_ll_orthant_game() <dunshire.games.SymmetricLinearGame object at 0x...>

random_lyapunov_like_icecream
(dims)[source]¶ Generate a random matrix Lyapunovlike on the icecream cone.
The form of these matrices is cited in Gowda and Tao [GowdaTao]. The scalar
a
and the vectorb
(using their notation) are easy to generate. The submatrixD
is a little trickier, but it can be found noticing that \(C + C^{T} = 0\) for a skewsymmetric matrix \(C\) implying that \(C + C^{T} + \left(2a\right)I = \left(2a\right)I\). Thus we can stick an \(aI\) with each of \(C,C^{T}\) and let those be our \(D,D^{T}\).Parameters: dims (int) – The dimension of the icecream cone (not of the matrix you want!) on which the returned matrix should be Lyapunovlike. Returns: A new matrix, Lyapunovlike on the icecream cone in dims
dimensions, whose free entries are random floats chosen uniformly between negative and positiveRANDOM_MAX
.Return type: matrix References
[GowdaTao] M. S. Gowda and J. Tao. On the bilinearity rank of a proper cone and Lyapunovlike transformations. Mathematical Programming, 147:155170, 2014. Examples
>>> L = random_lyapunov_like_icecream(3) >>> L.size (3, 3)
>>> from dunshire.options import ABS_TOL >>> from dunshire.matrices import inner_product >>> x = matrix([1,1,0]) >>> s = matrix([1,1,0]) >>> abs(inner_product(L*x, s)) < ABS_TOL True

random_matrix
(row_count, column_count=None)[source]¶ Generate a random matrix.
Parameters:  row_count (int) – The number of rows you want in the returned matrix.
 column_count (int) – The number of columns you want in the returned matrix (default:
the same as
row_count
).
Returns: A new matrix whose entries are random floats chosen uniformly between negative and positive
RANDOM_MAX
.Return type: matrix
Examples
>>> A = random_matrix(3) >>> A.size (3, 3)
>>> A = random_matrix(3,2) >>> A.size (3, 2)

random_natural
()[source]¶ Generate a random natural number.
Returns: A random natural number between 1
andRANDOM_MAX
, inclusive.Return type: int Examples
>>> 1 <= random_natural() <= RANDOM_MAX True

random_nn_scalar
()[source]¶ Generate a random nonnegative scalar.
Returns: A random nonnegative real number between zero and RANDOM_MAX
, inclusive.Return type: float Examples
>>> 0 <= random_nn_scalar() <= RANDOM_MAX True

random_nn_scaling
(G)[source]¶ Scale the given game by a random nonnegative amount.
We reattempt the scaling with a new random number until the resulting scaled game has an acceptable condition number.
Parameters: G (SymmetricLinearGame) – The game that you would like to scale. Returns: A pair containing the both the scaling factor and the new scaled game. Return type: (float, SymmetricLinearGame) Examples
>>> from dunshire.matrices import norm >>> from dunshire.options import ABS_TOL >>> G = random_orthant_game() >>> (alpha, H) = random_nn_scaling(G) >>> alpha >= 0 True >>> G.K() == H.K() True >>> norm(G.e1()  H.e1()) < ABS_TOL True >>> norm(G.e2()  H.e2()) < ABS_TOL True

random_nonnegative_matrix
(row_count, column_count=None)[source]¶ Generate a random matrix with nonnegative entries.
Parameters:  row_count (int) – The number of rows you want in the returned matrix.
 column_count (int) – The number of columns you want in the returned matrix (default:
the same as
row_count
).
Returns: A new matrix whose entries are chosen by
random_nn_scalar()
.Return type: matrix
Examples
>>> A = random_nonnegative_matrix(3) >>> A.size (3, 3) >>> all([entry >= 0 for entry in A]) True
>>> A = random_nonnegative_matrix(3,2) >>> A.size (3, 2) >>> all([entry >= 0 for entry in A]) True

random_orthant_game
()[source]¶ Generate a random game over the nonnegative orthant.
We generate each of
L
,K
,e1
, ande2
randomly within the constraints of the nonnegative orthant, and then construct a game from them. The process is repeated until we generate a game with a condition number underMAX_COND
.Returns: A random game over some nonnegative orthant. Return type: SymmetricLinearGame Examples
>>> random_orthant_game() <dunshire.games.SymmetricLinearGame object at 0x...>

random_positive_orthant_game
()[source]¶ Return a random game over the nonnegative orthant with a positive operator.
We first construct a
random_orthant_game()
and then modify it to have arandom_nonnegative_matrix()
as its operator. That process is repeated until the condition number of the resulting game is withinMAX_COND
.Returns: A random game over some nonnegative orthant whose dunshire.games.SymmetricLinearGame.payoff()
method is based on a positivedunshire.games.SymmetricLinearGame.L()
operator.Return type: SymmetricLinearGame Examples
>>> random_positive_orthant_game() <dunshire.games.SymmetricLinearGame object at 0x...>

random_scalar
()[source]¶ Generate a random scalar.
Returns: A random real number between negative and positive RANDOM_MAX
, inclusive.Return type: float Examples
>>> abs(random_scalar()) <= RANDOM_MAX True

random_skew_symmetric_matrix
(dims)[source]¶ Generate a random skewsymmetrix matrix.
Parameters: dims (int) – The number of rows/columns you want in the returned matrix. Returns: A new skewmatrix whose strictly abovediagonal entries are random floats chosen with random_scalar()
.Return type: matrix Examples
>>> A = random_skew_symmetric_matrix(3) >>> A.size (3, 3)
>>> from dunshire.options import ABS_TOL >>> from dunshire.matrices import norm >>> A = random_skew_symmetric_matrix(random_natural()) >>> norm(A + A.trans()) < ABS_TOL True

random_translation
(G)[source]¶ Translate the given game by a random amount.
We reattempt the translation with new random scalars until the resulting translated game has an acceptable condition number.
Parameters: G (SymmetricLinearGame) – The game that you would like to translate. Returns: A pair containing the both the translation distance and the new scaled game. Return type: (float, SymmetricLinearGame) Examples
>>> from dunshire.matrices import norm >>> from dunshire.options import ABS_TOL >>> G = random_orthant_game() >>> (alpha, H) = random_translation(G) >>> G.K() == H.K() True >>> norm(G.e1()  H.e1()) < ABS_TOL True >>> norm(G.e2()  H.e2()) < ABS_TOL True
test.symmetric_linear_game_test module¶
Unit tests for the SymmetricLinearGame
class.

class
SymmetricLinearGameTest
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
Tests for the SymmetricLinearGame and Solution classes.

assert_opposite_game_works
(G)[source]¶ Check the value of the “opposite” game that gives rise to a value that is the negation of the original game. Comes from some corollary.

assert_orthogonality
(G)[source]¶ Two orthogonality relations hold at an optimal solution, and we check them here.

assert_player1_start_valid
(G)[source]¶ Ensure that player one’s starting point satisfies both the equality and cone inequality in the CVXOPT primal problem.

assert_player2_start_valid
(G)[source]¶ Check that player two’s starting point satisfies both the cone inequality in the CVXOPT dual problem.

assert_scaling_works
(G)[source]¶ Test that scaling
L
by a nonnegative number scales the value of the game by the same number.

assert_translation_works
(G)[source]¶ Check that translating
L
by alpha*(e1*e2.trans()) increases the value of the associated game by alpha.

assert_within_tol
(first, second, modifier=1)[source]¶ Test that
first
andsecond
are equal within a multiple of our default tolerances.Parameters:  first (float) – The first number to compare.
 second (float) – The second number to compare.
 modifier (float) – A scaling factor (default: 1) applied to the default tolerance for this comparison. If you have a poorly conditioned matrix, for example, you may want to set this greater than one.

test_condition_lower_bound
()[source]¶ Ensure that the condition number of a game is greater than or equal to one.
It should be safe to compare these floats directly: we compute the condition number as the ratio of one nonnegative real number to a smaller nonnegative real number.

test_opposite_game_icecream
()[source]¶ Like
test_opposite_game_orthant()
, except over the icecream cone.

test_opposite_game_orthant
()[source]¶ Test the value of the “opposite” game over the nonnegative orthant.

test_orthogonality_icecream
()[source]¶ Check the orthgonality relationships that hold for a solution over the icecream cone.

test_orthogonality_orthant
()[source]¶ Check the orthgonality relationships that hold for a solution over the nonnegative orthant.

test_player1_start_valid_icecream
()[source]¶ Ensure that player one’s starting point is feasible over the icecream cone.

test_player1_start_valid_orthant
()[source]¶ Ensure that player one’s starting point is feasible over the nonnegative orthant.

test_player2_start_valid_icecream
()[source]¶ Ensure that player two’s starting point is feasible over the icecream cone.

test_player2_start_valid_orthant
()[source]¶ Ensure that player two’s starting point is feasible over the nonnegative orthant.

test_positive_operator_value
()[source]¶ Test that a positive operator on the nonnegative orthant gives rise to a a game with a nonnegative value.
This test theoretically applies to the icecream cone as well, but we don’t know how to make positive operators on that cone.

test_scaling_icecream
()[source]¶ The same test as
test_nonnegative_scaling_orthant()
, except over the ice cream cone.

test_scaling_orthant
()[source]¶ Test that scaling
L
by a nonnegative number scales the value of the game by the same number over the nonnegative orthant.

test_solutions_dont_change_icecream
()[source]¶ If we solve the same game twice over the icecream cone, then we should get the same solution both times. The solution to a game is not unique, but the process we use is (as far as we know) deterministic.

test_solutions_dont_change_orthant
()[source]¶ If we solve the same game twice over the nonnegative orthant, then we should get the same solution both times. The solution to a game is not unique, but the process we use is (as far as we know) deterministic.

test_translation_icecream
()[source]¶ The same as
test_translation_orthant()
, except over the ice cream cone.
