If we do this according to our paper, then the result is proper::
sage: set_random_seed()
- sage: K = random_cone(max_ambient_dim = 8,
- ....: strictly_convex=False,
- ....: solid=False)
- sage: K_S = _rho(K)
- sage: K_SP = _rho(K_S.dual()).dual()
- sage: K_SP.is_proper()
- True
- sage: K_SP = _rho(K_S, K_S.dual())
- sage: K_SP.is_proper()
- True
-
- ::
-
- sage: set_random_seed()
- sage: K = random_cone(max_ambient_dim = 8,
- ....: strictly_convex=True,
- ....: solid=False)
- sage: K_S = _rho(K)
- sage: K_SP = _rho(K_S.dual()).dual()
- sage: K_SP.is_proper()
- True
- sage: K_SP = _rho(K_S, K_S.dual())
- sage: K_SP.is_proper()
- True
-
- ::
-
- sage: set_random_seed()
- sage: K = random_cone(max_ambient_dim = 8,
- ....: strictly_convex=False,
- ....: solid=True)
- sage: K_S = _rho(K)
- sage: K_SP = _rho(K_S.dual()).dual()
- sage: K_SP.is_proper()
- True
- sage: K_SP = _rho(K_S, K_S.dual())
- sage: K_SP.is_proper()
- True
-
- ::
-
- sage: set_random_seed()
- sage: K = random_cone(max_ambient_dim = 8,
- ....: strictly_convex=True,
- ....: solid=True)
+ sage: K = random_cone(max_ambient_dim = 8)
sage: K_S = _rho(K)
sage: K_SP = _rho(K_S.dual()).dual()
sage: K_SP.is_proper()
sage: K_SP.is_proper()
True
- Test Proposition 7 in our paper concerning the duals and
+ Test the proposition in our paper concerning the duals and
restrictions. Generate a random cone, then create a subcone of
it. The operation of dual-taking should then commute with rho::
sage: set_random_seed()
- sage: J = random_cone(max_ambient_dim = 8,
- ....: solid=False,
- ....: strictly_convex=False)
- sage: K = Cone(random_sublist(J.rays(), 0.5), lattice=J.lattice())
- sage: K_W_star = _rho(K, J).dual()
- sage: K_star_W = _rho(K.dual(), J)
- sage: _basically_the_same(K_W_star, K_star_W)
- True
-
- ::
-
- sage: set_random_seed()
- sage: J = random_cone(max_ambient_dim = 8,
- ....: solid=True,
- ....: strictly_convex=False)
- sage: K = Cone(random_sublist(J.rays(), 0.5), lattice=J.lattice())
- sage: K_W_star = _rho(K, J).dual()
- sage: K_star_W = _rho(K.dual(), J)
- sage: _basically_the_same(K_W_star, K_star_W)
- True
-
- ::
-
- sage: set_random_seed()
- sage: J = random_cone(max_ambient_dim = 8,
- ....: solid=False,
- ....: strictly_convex=True)
- sage: K = Cone(random_sublist(J.rays(), 0.5), lattice=J.lattice())
- sage: K_W_star = _rho(K, J).dual()
- sage: K_star_W = _rho(K.dual(), J)
- sage: _basically_the_same(K_W_star, K_star_W)
- True
-
- ::
-
- sage: set_random_seed()
- sage: J = random_cone(max_ambient_dim = 8,
- ....: solid=True,
- ....: strictly_convex=True)
+ sage: J = random_cone(max_ambient_dim = 8)
sage: K = Cone(random_sublist(J.rays(), 0.5), lattice=J.lattice())
sage: K_W_star = _rho(K, J).dual()
sage: K_star_W = _rho(K.dual(), J)
sage: lyapunov_rank(K1) == lyapunov_rank(K2)
True
- Just to be sure, test a few more::
-
- sage: K1 = random_cone(max_ambient_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_ambient_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_ambient_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_ambient_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: 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_ambient_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_ambient_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_ambient_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_ambient_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
sage: actual == expected
True
- The Lyapunov rank of a proper cone is just the dimension of ``LL(K)``::
+ The Lyapunov rank of any cone is just the dimension of ``LL(K)``::
sage: set_random_seed()
- sage: K = random_cone(max_ambient_dim=8,
- ....: strictly_convex=True,
- ....: solid=True)
- sage: lyapunov_rank(K) == len(LL(K))
- True
-
- In fact the same can be said of any cone. These additional tests
- just increase our confidence that the reduction scheme works::
-
- sage: set_random_seed()
- sage: K = random_cone(max_ambient_dim=8,
- ....: strictly_convex=True,
- ....: solid=False)
- sage: lyapunov_rank(K) == len(LL(K))
- True
-
- ::
-
- sage: set_random_seed()
- sage: K = random_cone(max_ambient_dim=8,
- ....: strictly_convex=False,
- ....: solid=True)
- sage: lyapunov_rank(K) == len(LL(K))
- True
-
- ::
-
- sage: set_random_seed()
- sage: K = random_cone(max_ambient_dim=8,
- ....: strictly_convex=False,
- ....: solid=False)
+ sage: K = random_cone(max_ambient_dim=8)
sage: lyapunov_rank(K) == len(LL(K))
True
--- /dev/null
+"""
+Additional tests for the mjo.cone.cone module. These are extra
+properties that we'd like to check, but which are overkill for inclusion
+into Sage.
+"""
+
+# Sage doesn't load ~/.sage/init.sage during testing (sage -t), so we
+# have to explicitly mangle our sitedir here so that "mjo.cone"
+# resolves.
+from os.path import abspath
+from site import addsitedir
+addsitedir(abspath('../../'))
+
+from sage.all import *
+
+# The double-import is needed to get the underscore methods.
+from mjo.cone.cone import *
+from mjo.cone.cone import _basically_the_same, _rho
+
+#
+# Tests for _rho.
+#
+"""
+Apply _rho according to our paper (to obtain our main result). Test all
+four parameter combinations::
+
+ sage: set_random_seed()
+ sage: K = random_cone(max_ambient_dim = 8,
+ ....: strictly_convex=False,
+ ....: solid=False)
+ sage: K_S = _rho(K)
+ sage: K_SP = _rho(K_S.dual()).dual()
+ sage: K_SP.is_proper()
+ True
+ sage: K_SP = _rho(K_S, K_S.dual())
+ sage: K_SP.is_proper()
+ True
+
+::
+
+ sage: set_random_seed()
+ sage: K = random_cone(max_ambient_dim = 8,
+ ....: strictly_convex=True,
+ ....: solid=False)
+ sage: K_S = _rho(K)
+ sage: K_SP = _rho(K_S.dual()).dual()
+ sage: K_SP.is_proper()
+ True
+ sage: K_SP = _rho(K_S, K_S.dual())
+ sage: K_SP.is_proper()
+ True
+
+::
+
+ sage: set_random_seed()
+ sage: K = random_cone(max_ambient_dim = 8,
+ ....: strictly_convex=False,
+ ....: solid=True)
+ sage: K_S = _rho(K)
+ sage: K_SP = _rho(K_S.dual()).dual()
+ sage: K_SP.is_proper()
+ True
+ sage: K_SP = _rho(K_S, K_S.dual())
+ sage: K_SP.is_proper()
+ True
+
+::
+
+ sage: set_random_seed()
+ sage: K = random_cone(max_ambient_dim = 8,
+ ....: strictly_convex=True,
+ ....: solid=True)
+ sage: K_S = _rho(K)
+ sage: K_SP = _rho(K_S.dual()).dual()
+ sage: K_SP.is_proper()
+ True
+ sage: K_SP = _rho(K_S, K_S.dual())
+ sage: K_SP.is_proper()
+ True
+
+Test the proposition in our paper concerning the duals and
+restrictions. Generate a random cone, then create a subcone of
+it. The operation of dual-taking should then commute with rho. Test
+all parameter combinations::
+
+
+ sage: set_random_seed()
+ sage: J = random_cone(max_ambient_dim = 8,
+ ....: solid=False,
+ ....: strictly_convex=False)
+ sage: K = Cone(random_sublist(J.rays(), 0.5), lattice=J.lattice())
+ sage: K_W_star = _rho(K, J).dual()
+ sage: K_star_W = _rho(K.dual(), J)
+ sage: _basically_the_same(K_W_star, K_star_W)
+ True
+
+::
+
+ sage: set_random_seed()
+ sage: J = random_cone(max_ambient_dim = 8,
+ ....: solid=True,
+ ....: strictly_convex=False)
+ sage: K = Cone(random_sublist(J.rays(), 0.5), lattice=J.lattice())
+ sage: K_W_star = _rho(K, J).dual()
+ sage: K_star_W = _rho(K.dual(), J)
+ sage: _basically_the_same(K_W_star, K_star_W)
+ True
+
+::
+
+ sage: set_random_seed()
+ sage: J = random_cone(max_ambient_dim = 8,
+ ....: solid=False,
+ ....: strictly_convex=True)
+ sage: K = Cone(random_sublist(J.rays(), 0.5), lattice=J.lattice())
+ sage: K_W_star = _rho(K, J).dual()
+ sage: K_star_W = _rho(K.dual(), J)
+ sage: _basically_the_same(K_W_star, K_star_W)
+ True
+
+::
+
+ sage: set_random_seed()
+ sage: J = random_cone(max_ambient_dim = 8,
+ ....: solid=True,
+ ....: strictly_convex=True)
+ sage: K = Cone(random_sublist(J.rays(), 0.5), lattice=J.lattice())
+ sage: K_W_star = _rho(K, J).dual()
+ sage: K_star_W = _rho(K.dual(), J)
+ sage: _basically_the_same(K_W_star, K_star_W)
+ True
+
+"""
+
+
+#
+# Lyapunov rank tests
+#
+"""
+
+The Lyapunov rank is invariant under a linear isomorphism. Check all
+combinations of parameters::
+
+ sage: K1 = random_cone(max_ambient_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_ambient_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_ambient_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_ambient_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 Lyapunov rank of a dual cone should be the same as the original
+cone. Check all combinations of parameters::
+
+ sage: set_random_seed()
+ sage: K = random_cone(max_ambient_dim=8,
+ ....: strictly_convex=False,
+ ....: solid=False)
+ sage: lyapunov_rank(K) == lyapunov_rank(K.dual())
+ True
+
+::
+
+ sage: set_random_seed()
+ sage: K = random_cone(max_ambient_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_ambient_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_ambient_dim=8,
+ ....: strictly_convex=True,
+ ....: solid=True)
+ sage: lyapunov_rank(K) == lyapunov_rank(K.dual())
+ True
+
+The Lyapunov rank of a cone ``K`` is the dimension of ``LL(K)``. Check
+all combinations of parameters::
+
+ sage: set_random_seed()
+ sage: K = random_cone(max_ambient_dim=8,
+ ....: strictly_convex=True,
+ ....: solid=True)
+ sage: lyapunov_rank(K) == len(LL(K))
+ True
+
+::
+
+ sage: set_random_seed()
+ sage: K = random_cone(max_ambient_dim=8,
+ ....: strictly_convex=True,
+ ....: solid=False)
+ sage: lyapunov_rank(K) == len(LL(K))
+ True
+
+::
+
+ sage: set_random_seed()
+ sage: K = random_cone(max_ambient_dim=8,
+ ....: strictly_convex=False,
+ ....: solid=True)
+ sage: lyapunov_rank(K) == len(LL(K))
+ True
+
+::
+
+ sage: set_random_seed()
+ sage: K = random_cone(max_ambient_dim=8,
+ ....: strictly_convex=False,
+ ....: solid=False)
+ sage: lyapunov_rank(K) == len(LL(K))
+ True
+
+"""