+ In fact [Orlitzky/Gowda]_, no closed convex polyhedral cone can have
+ Lyapunov rank `n-1` in `n` dimensions::
+
+ sage: K = random_cone(max_dim=10)
+ sage: b = lyapunov_rank(K)
+ sage: n = K.lattice_dim()
+ sage: b == n-1
+ False
+
+ The calculation of the Lyapunov rank of an improper cone can be
+ reduced to that of a proper cone [Orlitzky/Gowda]_::
+
+ sage: K = random_cone(max_dim=15, solid=False, strictly_convex=False)
+ sage: actual = lyapunov_rank(K)
+ sage: (phi1, _) = span_iso(K)
+ sage: K_S = phi1(K)
+ sage: (phi2, _) = span_iso(K_S.dual())
+ sage: J_T = phi2(K_S.dual()).dual()
+ sage: l = K.linear_subspace().dimension()
+ sage: codim = K.lattice_dim() - K.dim()
+ sage: expected = lyapunov_rank(J_T) + K.dim()*(l + codim) + codim**2
+ sage: actual == expected
+ True
+
+ Repeat the previous test with different ``random_cone()`` params::
+
+ sage: K = random_cone(max_dim=15, solid=False, strictly_convex=True)
+ sage: actual = lyapunov_rank(K)
+ sage: (phi1, _) = span_iso(K)
+ sage: K_S = phi1(K)
+ sage: (phi2, _) = span_iso(K_S.dual())
+ sage: J_T = phi2(K_S.dual()).dual()
+ sage: l = K.linear_subspace().dimension()
+ sage: codim = K.lattice_dim() - K.dim()
+ sage: expected = lyapunov_rank(J_T) + K.dim()*(l + codim) + codim**2
+ sage: actual == expected
+ True
+
+ sage: K = random_cone(max_dim=15, solid=True, strictly_convex=False)
+ sage: actual = lyapunov_rank(K)
+ sage: (phi1, _) = span_iso(K)
+ sage: K_S = phi1(K)
+ sage: (phi2, _) = span_iso(K_S.dual())
+ sage: J_T = phi2(K_S.dual()).dual()
+ sage: l = K.linear_subspace().dimension()
+ sage: codim = K.lattice_dim() - K.dim()
+ sage: expected = lyapunov_rank(J_T) + K.dim()*(l + codim) + codim**2
+ sage: actual == expected
+ True
+
+ sage: K = random_cone(max_dim=15, solid=True, strictly_convex=True)
+ sage: actual = lyapunov_rank(K)
+ sage: (phi1, _) = span_iso(K)
+ sage: K_S = phi1(K)
+ sage: (phi2, _) = span_iso(K_S.dual())
+ sage: J_T = phi2(K_S.dual()).dual()
+ sage: l = K.linear_subspace().dimension()
+ sage: codim = K.lattice_dim() - K.dim()
+ sage: expected = lyapunov_rank(J_T) + K.dim()*(l + codim) + codim**2
+ sage: actual == expected
+ True
+
+ sage: K = random_cone(max_dim=15)
+ sage: actual = lyapunov_rank(K)
+ sage: (phi1, _) = span_iso(K)
+ sage: K_S = phi1(K)
+ sage: (phi2, _) = span_iso(K_S.dual())
+ sage: J_T = phi2(K_S.dual()).dual()
+ sage: l = K.linear_subspace().dimension()
+ sage: codim = K.lattice_dim() - K.dim()
+ sage: expected = lyapunov_rank(J_T) + K.dim()*(l + codim) + codim**2
+ sage: actual == expected
+ True
+
+ And test with the project_span function::
+
+ sage: K = random_cone(max_dim=15)
+ sage: actual = lyapunov_rank(K)
+ sage: K_S = project_span(K)
+ sage: P = project_span(K_S.dual()).dual()
+ sage: l = K.linear_subspace().dimension()
+ sage: codim = K.lattice_dim() - K.dim()
+ sage: expected = lyapunov_rank(P) + K.dim()*(l + codim) + codim**2
+ sage: actual == expected
+ True
+