if K1.is_strictly_convex() != K2.is_strictly_convex():
return False
- if len(LL(K1)) != len(LL(K2)):
+ if len(K1.LL()) != len(K2.LL()):
return False
C_of_K1 = K1.discrete_complementarity_set()
return Cone(K_W_rays, lattice=L)
-def LL(K):
- r"""
- Compute a basis of Lyapunov-like transformations on this cone.
-
- OUTPUT:
-
- A list of matrices forming a basis for the space of all
- Lyapunov-like transformations on the given cone.
-
- EXAMPLES:
-
- The trivial cone has no Lyapunov-like transformations::
-
- sage: L = ToricLattice(0)
- sage: K = Cone([], lattice=L)
- sage: LL(K)
- []
-
- The Lyapunov-like transformations on the nonnegative orthant are
- simply diagonal matrices::
-
- sage: K = Cone([(1,)])
- sage: LL(K)
- [[1]]
-
- sage: K = Cone([(1,0),(0,1)])
- sage: LL(K)
- [
- [1 0] [0 0]
- [0 0], [0 1]
- ]
-
- sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)])
- sage: LL(K)
- [
- [1 0 0] [0 0 0] [0 0 0]
- [0 0 0] [0 1 0] [0 0 0]
- [0 0 0], [0 0 0], [0 0 1]
- ]
-
- Only the identity matrix is Lyapunov-like on the `L^{3}_{1}` and
- `L^{3}_{\infty}` cones [Rudolf et al.]_::
-
- sage: L31 = Cone([(1,0,1), (0,-1,1), (-1,0,1), (0,1,1)])
- sage: LL(L31)
- [
- [1 0 0]
- [0 1 0]
- [0 0 1]
- ]
-
- sage: L3infty = Cone([(0,1,1), (1,0,1), (0,-1,1), (-1,0,1)])
- sage: LL(L3infty)
- [
- [1 0 0]
- [0 1 0]
- [0 0 1]
- ]
-
- If our cone is the entire space, then every transformation on it is
- Lyapunov-like::
-
- sage: K = Cone([(1,0), (-1,0), (0,1), (0,-1)])
- sage: M = MatrixSpace(QQ,2)
- sage: M.basis() == LL(K)
- True
-
- TESTS:
-
- The inner product `\left< L\left(x\right), s \right>` is zero for
- every pair `\left( x,s \right)` in the discrete complementarity set
- of the cone::
-
- sage: set_random_seed()
- sage: K = random_cone(max_ambient_dim=8)
- sage: C_of_K = K.discrete_complementarity_set()
- sage: l = [ (L*x).inner_product(s) for (x,s) in C_of_K for L in LL(K) ]
- sage: sum(map(abs, l))
- 0
-
- The Lyapunov-like transformations on a cone and its dual are related
- by transposition, but we're not guaranteed to compute transposed
- elements of `LL\left( K \right)` as our basis for `LL\left( K^{*}
- \right)`
-
- sage: set_random_seed()
- sage: K = random_cone(max_ambient_dim=8)
- sage: LL2 = [ L.transpose() for L in LL(K.dual()) ]
- sage: V = VectorSpace( K.lattice().base_field(), K.lattice_dim()^2)
- sage: LL1_vecs = [ V(m.list()) for m in LL(K) ]
- sage: LL2_vecs = [ V(m.list()) for m in LL2 ]
- sage: V.span(LL1_vecs) == V.span(LL2_vecs)
- True
-
- """
- V = K.lattice().vector_space()
-
- C_of_K = K.discrete_complementarity_set()
-
- tensor_products = [ s.tensor_product(x) for (x,s) in C_of_K ]
-
- # Sage doesn't think matrices are vectors, so we have to convert
- # our matrices to vectors explicitly before we can figure out how
- # many are linearly-indepenedent.
- #
- # The space W has the same base ring as V, but dimension
- # dim(V)^2. So it has the same dimension as the space of linear
- # transformations on V. In other words, it's just the right size
- # to create an isomorphism between it and our matrices.
- W = VectorSpace(V.base_ring(), V.dimension()**2)
-
- # Turn our matrices into long vectors...
- vectors = [ W(m.list()) for m in tensor_products ]
-
- # Vector space representation of Lyapunov-like matrices
- # (i.e. vec(L) where L is Luapunov-like).
- LL_vector = W.span(vectors).complement()
-
- # Now construct an ambient MatrixSpace in which to stick our
- # transformations.
- M = MatrixSpace(V.base_ring(), V.dimension())
-
- matrix_basis = [ M(v.list()) for v in LL_vector.basis() ]
-
- return matrix_basis
-
-
-
def lyapunov_rank(K):
r"""
Compute the Lyapunov rank (or bilinearity rank) of this cone.
sage: actual == expected
True
- The Lyapunov rank of any cone is just the dimension of ``LL(K)``::
+ The Lyapunov rank of any cone is just the dimension of ``K.LL()``::
sage: set_random_seed()
sage: K = random_cone(max_ambient_dim=8)
- sage: lyapunov_rank(K) == len(LL(K))
+ sage: lyapunov_rank(K) == len(K.LL())
True
We can make an imperfect cone perfect by adding a slack variable
# Non-pointed reduction lemma.
beta += l * m
- beta += len(LL(K))
+ beta += len(K.LL())
return beta
sage: is_lyapunov_like(L,K)
True
- Everything in ``LL(K)`` should be Lyapunov-like on ``K``::
+ Everything in ``K.LL()`` should be Lyapunov-like on ``K``::
sage: K = random_cone(min_ambient_dim = 1, max_rays = 5)
- sage: all([is_lyapunov_like(L,K) for L in LL(K)])
+ sage: all([is_lyapunov_like(L,K) for L in K.LL()])
True
"""