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:
ExceptionAn 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.779496368228267e-10, ... '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.986246886102996e-09} >>> 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 2-space, e1 = [1.0000000] [0.1000000], e2 = [3.0000000] [0.1000000] CVXOPT returned: dual infeasibility: None dual objective: 1.0 dual slack: 8.779496368228267e-10 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.986246886102996e-09 s: None status: primal infeasible x: None y: [ 1] [ 1] z: [ 1] [ 1] [ 0] [ 0]
- exception PoorScalingException(game)[source]¶
Bases:
ExceptionAn 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,
- 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 2-space, 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 side-by-side.
- 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
rightappended 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 top-to-bottom.
- 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
bottomappended 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 2-norm 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-by-domain_dimdense 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
vec2you want.vec2 (matrix) – The second vector, whose inner product with
vec1you want.
- Returns:
The inner product of
vec1andvec2.- Return type:
float
- Raises:
TypeError – If the lengths of
vec1andvec2differ.
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
- norm(matrix_or_vector)[source]¶
Return the Frobenius norm of a matrix or vector.
When the input is a vector, its matrix-Frobenius norm is the same thing as its vector-Euclidean 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 column-major order from
mat.- Parameters:
mat (matrix) – Any sort of real matrix that you want written as a long vector.
- Returns:
An
len(mat)-by-1long column vector containign the entries ofmatin 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
matis a vector, this function is a no-op:>>> 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 = 1e-06¶
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
1e-7, 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:
TestCaseTests for the
append_col()function.
- class AppendRowTest(methodName='runTest')[source]¶
Bases:
TestCaseTests for the
dunshire.matrices.append_row()function.
- class ConditionNumberTest(methodName='runTest')[source]¶
Bases:
TestCaseTests for the
dunshire.matrices.condition_number()function.
- class EigenvaluesRealPartTest(methodName='runTest')[source]¶
Bases:
TestCaseTests 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
deepcopyhere in case thecopyused in thedunshire.matrices.eigenvalues_re()function is insufficient. Ifcopydidn’t work and this test used it too, then this test would pass when it shouldn’t.
- class EigenvaluesTest(methodName='runTest')[source]¶
Bases:
TestCaseTests 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
deepcopyhere in case thecopyused in theeigenvalues()function is insufficient. Ifcopydidn’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:
TestCaseTests 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:
TestCaseTests 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 randomly-generated game. When the condition number of the games gets too high, we start to see
PoorScalingExceptionbeing thrown. There’s no science to choosing the upper bound – it got lowered until those exceptions stopped popping up. It’s at125because129doesn’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 off-diagonal entries.
These matrices are Lyapunov-like 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 off-diagonal 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_game()[source]¶
Return a random game.
One of the functions,
is chosen at random and used to generate a random game.
- Returns:
A random game.
- Return type:
Examples
>>> random_game() <dunshire.games.SymmetricLinearGame object at 0x...>
- random_icecream_game()[source]¶
Generate a random game over the ice-cream cone.
We generate each of
L,K,e1, ande2randomly within the constraints of the ice-cream 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 ice-cream cone.
- Return type:
Examples
>>> random_icecream_game() <dunshire.games.SymmetricLinearGame object at 0x...>
- random_ll_game()[source]¶
Return a random Lyapunov-like game.
One of the functions,
is chosen at random and used to generate a random game.
- Returns:
A random Lyapunov-like game.
- Return type:
Examples
>>> random_ll_game() <dunshire.games.SymmetricLinearGame object at 0x...>
- random_ll_icecream_game()[source]¶
Return a random Lyapunov game over some ice-cream 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 ice-cream cone whose
dunshire.games.SymmetricLinearGame.payoff()method is based on a Lyapunov-likedunshire.games.SymmetricLinearGame.L()operator.- Return type:
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 Lyapunov-like 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 Lyapunov-likedunshire.games.SymmetricLinearGame.L()operator.- Return type:
Examples
>>> random_ll_orthant_game() <dunshire.games.SymmetricLinearGame object at 0x...>
- random_lyapunov_like_icecream(dims)[source]¶
Generate a random matrix Lyapunov-like on the ice-cream cone.
The form of these matrices is cited in Gowda and Tao [GowdaTao]. The scalar
aand the vectorb(using their notation) are easy to generate. The submatrixDis a little trickier, but it can be found noticing that \(C + C^{T} = 0\) for a skew-symmetric 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 ice-cream cone (not of the matrix you want!) on which the returned matrix should be Lyapunov-like.
- Returns:
A new matrix, Lyapunov-like on the ice-cream cone in
dimsdimensions, 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 Lyapunov-like transformations. Mathematical Programming, 147:155-170, 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
1andRANDOM_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 re-attempt 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, ande2randomly 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:
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:
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 skew-symmetrix matrix.
- Parameters:
dims (int) – The number of rows/columns you want in the returned matrix.
- Returns:
A new skew-matrix whose strictly above-diagonal 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 re-attempt 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:
TestCaseTests 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
Lby a nonnegative number scales the value of the game by the same number.
- assert_translation_works(G)[source]¶
Check that translating
Lby alpha*(e1*e2.trans()) increases the value of the associated game by alpha.
- assert_within_tol(first, second, modifier=1)[source]¶
Test that
firstandsecondare 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 ice-cream 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 ice-cream 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 ice-cream 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 ice-cream 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 ice-cream 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
Lby 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 ice-cream 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.