- The nonnegative orthant in `\mathbb{R}^{n}` always has rank `n`
- [Rudolf et al.]_::
-
- sage: positives = Cone([(1,)])
- sage: lyapunov_rank(positives)
- 1
- sage: quadrant = Cone([(1,0), (0,1)])
- sage: lyapunov_rank(quadrant)
- 2
- sage: octant = Cone([(1,0,0), (0,1,0), (0,0,1)])
- sage: lyapunov_rank(octant)
- 3
-
- The full space `\mathbb{R}^{n}` has Lyapunov rank `n^{2}`
- [Orlitzky/Gowda]_::
-
- sage: R5 = VectorSpace(QQ, 5)
- sage: gs = R5.basis() + [ -r for r in R5.basis() ]
- sage: K = Cone(gs)
- sage: lyapunov_rank(K)
- 25
-
- The `L^{3}_{1}` cone is known to have a Lyapunov rank of one
- [Rudolf et al.]_::
-
- sage: L31 = Cone([(1,0,1), (0,-1,1), (-1,0,1), (0,1,1)])
- sage: lyapunov_rank(L31)
- 1
-
- Likewise for the `L^{3}_{\infty}` cone [Rudolf et al.]_::
-
- sage: L3infty = Cone([(0,1,1), (1,0,1), (0,-1,1), (-1,0,1)])
- sage: lyapunov_rank(L3infty)
- 1
-
- A single ray in `n` dimensions should have Lyapunov rank `n^{2} - n
- + 1` [Orlitzky/Gowda]_::
-
- sage: K = Cone([(1,0,0,0,0)])
- sage: lyapunov_rank(K)
- 21
- sage: K.lattice_dim()**2 - K.lattice_dim() + 1
- 21
-
- A subspace (of dimension `m`) in `n` dimensions should have a
- Lyapunov rank of `n^{2} - m\left(n - m)` [Orlitzky/Gowda]_::
-
- sage: e1 = (1,0,0,0,0)
- sage: neg_e1 = (-1,0,0,0,0)
- sage: e2 = (0,1,0,0,0)
- sage: neg_e2 = (0,-1,0,0,0)
- sage: z = (0,0,0,0,0)
- sage: K = Cone([e1, neg_e1, e2, neg_e2, z, z, z])
- sage: lyapunov_rank(K)
- 19
- sage: K.lattice_dim()**2 - K.dim()*K.codim()
- 19
-
- The Lyapunov rank should be additive on a product of proper cones
- [Rudolf et al.]_::
-
- sage: L31 = Cone([(1,0,1), (0,-1,1), (-1,0,1), (0,1,1)])
- sage: octant = Cone([(1,0,0), (0,1,0), (0,0,1)])
- sage: K = L31.cartesian_product(octant)
- sage: lyapunov_rank(K) == lyapunov_rank(L31) + lyapunov_rank(octant)
- True
-
- Two isomorphic cones should have the same Lyapunov rank [Rudolf et al.]_.
- The cone ``K`` in the following example is isomorphic to the nonnegative
- octant in `\mathbb{R}^{3}`::
-
- sage: K = Cone([(1,2,3), (-1,1,0), (1,0,6)])
- sage: lyapunov_rank(K)
- 3
-
- The dual cone `K^{*}` of ``K`` should have the same Lyapunov rank as ``K``
- itself [Rudolf et al.]_::
-
- sage: K = Cone([(2,2,4), (-1,9,0), (2,0,6)])
- sage: lyapunov_rank(K) == lyapunov_rank(K.dual())
- True
-
- TESTS:
-
- The Lyapunov rank should be additive on a product of proper cones
- [Rudolf et al.]_::
-
- sage: set_random_seed()
- sage: K1 = random_cone(max_dim=8, strictly_convex=True, solid=True)
- sage: K2 = random_cone(max_dim=8, strictly_convex=True, solid=True)
- sage: K = K1.cartesian_product(K2)
- sage: lyapunov_rank(K) == lyapunov_rank(K1) + lyapunov_rank(K2)
- True
-
- The Lyapunov rank is invariant under a linear isomorphism
- [Orlitzky/Gowda]_::
-
- sage: K1 = random_cone(max_dim = 8)
- sage: A = random_matrix(QQ, K1.lattice_dim(), algorithm='unimodular')
- sage: K2 = Cone( [ A*r for r in K1.rays() ], lattice=K1.lattice())
- sage: lyapunov_rank(K1) == lyapunov_rank(K2)
- True
-
- Just to be sure, test a few more::
-
- sage: K1 = random_cone(max_dim=8, strictly_convex=True, solid=True)
- sage: A = random_matrix(QQ, K1.lattice_dim(), algorithm='unimodular')
- sage: K2 = Cone( [ A*r for r in K1.rays() ], lattice=K1.lattice())
- sage: lyapunov_rank(K1) == lyapunov_rank(K2)
- True
-
- ::
-
- sage: K1 = random_cone(max_dim=8, strictly_convex=True, solid=False)
- sage: A = random_matrix(QQ, K1.lattice_dim(), algorithm='unimodular')
- sage: K2 = Cone( [ A*r for r in K1.rays() ], lattice=K1.lattice())
- sage: lyapunov_rank(K1) == lyapunov_rank(K2)
- True
-
- ::
-
- sage: K1 = random_cone(max_dim=8, strictly_convex=False, solid=True)
- sage: A = random_matrix(QQ, K1.lattice_dim(), algorithm='unimodular')
- sage: K2 = Cone( [ A*r for r in K1.rays() ], lattice=K1.lattice())
- sage: lyapunov_rank(K1) == lyapunov_rank(K2)
- True
-
- ::
-
- sage: K1 = random_cone(max_dim=8, strictly_convex=False, solid=False)
- sage: A = random_matrix(QQ, K1.lattice_dim(), algorithm='unimodular')
- sage: K2 = Cone( [ A*r for r in K1.rays() ], lattice=K1.lattice())
- sage: lyapunov_rank(K1) == lyapunov_rank(K2)
- True
-
- The dual cone `K^{*}` of ``K`` should have the same Lyapunov rank as ``K``
- itself [Rudolf et al.]_::
-
- sage: set_random_seed()
- sage: K = random_cone(max_dim=8)
- sage: lyapunov_rank(K) == lyapunov_rank(K.dual())
- True
-
- Make sure we exercise the non-strictly-convex/non-solid case::
-
- sage: set_random_seed()
- sage: K = random_cone(max_dim=8, strictly_convex=False, solid=False)
- sage: lyapunov_rank(K) == lyapunov_rank(K.dual())
- True
-
- Let's check the other permutations as well, just to be sure::
-
- sage: set_random_seed()
- sage: K = random_cone(max_dim=8, strictly_convex=False, solid=True)
- sage: lyapunov_rank(K) == lyapunov_rank(K.dual())
- True
-
- ::
-
- sage: set_random_seed()
- sage: K = random_cone(max_dim=8, strictly_convex=True, solid=False)
- sage: lyapunov_rank(K) == lyapunov_rank(K.dual())
- True
-
- ::
-
- sage: set_random_seed()
- sage: K = random_cone(max_dim=8, strictly_convex=True, solid=True)
- sage: lyapunov_rank(K) == lyapunov_rank(K.dual())
- True
-
- The Lyapunov rank of a proper polyhedral cone in `n` dimensions can
- be any number between `1` and `n` inclusive, excluding `n-1`
- [Gowda/Tao]_. By accident, the `n-1` restriction will hold for the
- trivial cone in a trivial space as well. However, in zero dimensions,
- the Lyapunov rank of the trivial cone will be zero::