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.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:
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,
- 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
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 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
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 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_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 of
vec1
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
- 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-1
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 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:
TestCase
Tests for the
append_col()
function.
- class AppendRowTest(methodName='runTest')[source]¶
Bases:
TestCase
Tests for the
dunshire.matrices.append_row()
function.
- class ConditionNumberTest(methodName='runTest')[source]¶
Bases:
TestCase
Tests for the
dunshire.matrices.condition_number()
function.
- class EigenvaluesRealPartTest(methodName='runTest')[source]¶
Bases:
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:
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:
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:
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 randomly-generated 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 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
, ande2
randomly 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
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 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
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 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
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 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
, 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:
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:
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 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
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 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.