-
-def random_matrix(dims):
- """
- Generate a random square matrix.
-
- Parameters
- ----------
-
- dims : int
- The number of rows/columns you want in the returned matrix.
-
- Returns
- -------
-
- matrix
- A new matrix whose entries are random floats chosen uniformly from
- the interval [-RANDOM_MAX, RANDOM_MAX].
-
- Examples
- --------
-
- >>> A = random_matrix(3)
- >>> A.size
- (3, 3)
-
- """
- return matrix([[uniform(-RANDOM_MAX, RANDOM_MAX) for _ in range(dims)]
- for _ in range(dims)])
-
-
-def random_nonnegative_matrix(dims):
- """
- Generate a random square matrix with nonnegative entries.
-
- Parameters
- ----------
-
- dims : int
- The number of rows/columns you want in the returned matrix.
-
- Returns
- -------
-
- matrix
- A new matrix whose entries are random floats chosen uniformly from
- the interval [0, RANDOM_MAX].
-
- Examples
- --------
-
- >>> A = random_nonnegative_matrix(3)
- >>> A.size
- (3, 3)
- >>> all([entry >= 0 for entry in A])
- True
-
- """
- L = random_matrix(dims)
- return matrix([abs(entry) for entry in L], (dims, dims))
-
-
-def random_diagonal_matrix(dims):
- """
- 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
- -------
-
- matrix
- A new matrix whose diagonal entries are random floats chosen
- uniformly from the interval [-RANDOM_MAX, RANDOM_MAX] and whose
- off-diagonal entries are zero.
-
- 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
-
- """
- return matrix([[uniform(-RANDOM_MAX, RANDOM_MAX)*int(i == j)
- for i in range(dims)]
- for j in range(dims)])
-
-
-def random_skew_symmetric_matrix(dims):
- """
- Generate a random skew-symmetrix matrix.
-
- Parameters
- ----------
-
- dims : int
- The number of rows/columns you want in the returned matrix.
-
- Returns
- -------
-
- matrix
- A new skew-matrix whose strictly above-diagonal entries are
- random floats chosen uniformly from the interval
- [-RANDOM_MAX, RANDOM_MAX].
-
- Examples
- --------
-
- >>> A = random_skew_symmetric_matrix(3)
- >>> A.size
- (3, 3)
-
- >>> from dunshire.matrices import norm
- >>> A = random_skew_symmetric_matrix(randint(1, 10))
- >>> norm(A + A.trans()) < options.ABS_TOL
- True
-
- """
- strict_ut = [[uniform(-10, 10)*int(i < j) for i in range(dims)]
- for j in range(dims)]
-
- strict_ut = matrix(strict_ut, (dims, dims))
- return strict_ut - strict_ut.trans()
-
-
-def random_lyapunov_like_icecream(dims):
- r"""
- 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 vector ``b`` (using their
- notation) are easy to generate. The submatrix ``D`` is a little
- trickier, but it can be found noticing that :math:`C + C^{T} = 0`
- for a skew-symmetric matrix :math:`C` implying that :math:`C + C^{T}
- + \left(2a\right)I = \left(2a\right)I`. Thus we can stick an
- :math:`aI` with each of :math:`C,C^{T}` and let those be our
- :math:`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
- -------
-
- matrix
- A new matrix, Lyapunov-like on the ice-cream cone in ``dims``
- dimensions, whose free entries are random floats chosen uniformly
- from the interval [-10, 10].
-
- 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)
- >>> x = matrix([1,1,0])
- >>> s = matrix([1,-1,0])
- >>> abs(inner_product(L*x, s)) < options.ABS_TOL
- True
-
- """
- a = matrix([uniform(-10, 10)], (1, 1))
- b = matrix([uniform(-10, 10) for _ in range(dims-1)], (dims-1, 1))
- D = random_skew_symmetric_matrix(dims-1) + a*identity(dims-1)
- row1 = append_col(a, b.trans())
- row2 = append_col(b, D)
- return append_row(row1, row2)
-
-
-def random_orthant_game():
- """
- Generate the ``L``, ``K``, ``e1``, and ``e2`` parameters for a
- random game over the nonnegative orthant, and return the
- corresponding :class:`SymmetricLinearGame`.
-
- We keep going until we generate a game with a condition number under
- 5000.
- """
- ambient_dim = randint(1, 10)
- K = NonnegativeOrthant(ambient_dim)
- e1 = [uniform(0.5, 10) for _ in range(K.dimension())]
- e2 = [uniform(0.5, 10) for _ in range(K.dimension())]
- L = random_matrix(K.dimension())
- G = SymmetricLinearGame(L, K, e1, e2)
-
- if G._condition() <= MAX_COND:
- return G
- else:
- return random_orthant_game()
-
-
-def random_icecream_game():
- """
- Generate the ``L``, ``K``, ``e1``, and ``e2`` parameters for a
- random game over the ice-cream cone, and return the corresponding
- :class:`SymmetricLinearGame`.
- """
- # Use a minimum dimension of two to avoid divide-by-zero in
- # the fudge factor we make up later.
- ambient_dim = randint(2, 10)
- K = IceCream(ambient_dim)
- e1 = [1] # Set the "height" of e1 to one
- e2 = [1] # And the same for e2
-
- # If we choose the rest of the components of e1,e2 randomly
- # between 0 and 1, then the largest the squared norm of the
- # non-height part of e1,e2 could be is the 1*(dim(K) - 1). We
- # need to make it less than one (the height of the cone) so
- # that the whole thing is in the cone. The norm of the
- # non-height part is sqrt(dim(K) - 1), and we can divide by
- # twice that.
- fudge_factor = 1.0 / (2.0*sqrt(K.dimension() - 1.0))
- e1 += [fudge_factor*uniform(0, 1) for _ in range(K.dimension() - 1)]
- e2 += [fudge_factor*uniform(0, 1) for _ in range(K.dimension() - 1)]
- L = random_matrix(K.dimension())
- G = SymmetricLinearGame(L, K, e1, e2)
-
- if G._condition() <= MAX_COND:
- return G
- else:
- return random_icecream_game()
-