]> gitweb.michael.orlitzky.com - sage.d.git/blobdiff - mjo/cone/cone.py
Don't check the cones constructed in motzkin_decomposition().
[sage.d.git] / mjo / cone / cone.py
index eac86b374c131f4cad05dc27c7ec0eb7060deca2..68fd1931e9d7a4a7fdf3a00a5636011c963e58dd 100644 (file)
@@ -135,6 +135,14 @@ def motzkin_decomposition(K):
         sage: S.lineality() == S.dim()
         True
 
+    A strictly convex cone should be equal to its strictly convex component::
+
+        sage: set_random_seed()
+        sage: K = random_cone(max_ambient_dim=8, strictly_convex=True)
+        sage: (P,_) = motzkin_decomposition(K)
+        sage: K.is_equivalent(P)
+        True
+
     The generators of the components are obtained from orthogonal
     projections of the original generators [Stoer-Witzgall]_::
 
@@ -155,11 +163,11 @@ def motzkin_decomposition(K):
     # The lines() method only returns one generator per line. For a true
     # line, we also need a generator pointing in the opposite direction.
     S_gens = [ direction*gen for direction in [1,-1] for gen in K.lines() ]
-    S = Cone(S_gens, K.lattice())
+    S = Cone(S_gens, K.lattice(), check=False)
 
     # Since ``S`` is a subspace, the rays of its dual generate its
     # orthogonal complement.
-    S_perp = Cone(S.dual(), K.lattice())
+    S_perp = Cone(S.dual(), K.lattice(), check=False)
     P = K.intersection(S_perp)
 
     return (P,S)
@@ -446,18 +454,27 @@ def positive_operator_gens(K):
     W = VectorSpace(F, n**2)
     vectors = [ W(tp.list()) for tp in tensor_products ]
 
-    # Create the *dual* cone of the positive operators, expressed as
-    # long vectors. WARNING: check=True is necessary even though it
-    # makes Cone() take forever. For an example take
-    # K = Cone([(1,0,0),(0,0,1),(0,0,-1)]).
-    pi_dual = Cone(vectors, ToricLattice(W.dimension()))
+    check = True
+    if K.is_solid() or K.is_strictly_convex():
+        # The lineality space of either ``K`` or ``K.dual()`` is
+        # trivial and it's easy to show that our generating set is
+        # minimal. I would love a proof that this works when ``K`` is
+        # neither pointed nor solid.
+        #
+        # Note that in that case we can get *duplicates*, since the
+        # tensor product of (x,s) is the same as that of (-x,-s).
+        check = False
+
+    # Create the dual cone of the positive operators, expressed as
+    # long vectors.
+    pi_dual = Cone(vectors, ToricLattice(W.dimension()), check=check)
 
     # Now compute the desired cone from its dual...
     pi_cone = pi_dual.dual()
 
     # And finally convert its rays back to matrix representations.
     M = MatrixSpace(F, n)
-    return [ M(v.list()) for v in pi_cone.rays() ]
+    return [ M(v.list()) for v in pi_cone ]
 
 
 def Z_transformation_gens(K):
@@ -576,11 +593,20 @@ def Z_transformation_gens(K):
     W = VectorSpace(F, n**2)
     vectors = [ W(m.list()) for m in tensor_products ]
 
-    # Create the *dual* cone of the cross-positive operators,
-    # expressed as long vectors. WARNING: check=True is necessary
-    # even though it makes Cone() take forever. For an example take
-    # K = Cone([(1,0,0),(0,0,1),(0,0,-1)]).
-    Sigma_dual = Cone(vectors, lattice=ToricLattice(W.dimension()))
+    check = True
+    if K.is_solid() or K.is_strictly_convex():
+        # The lineality space of either ``K`` or ``K.dual()`` is
+        # trivial and it's easy to show that our generating set is
+        # minimal. I would love a proof that this works when ``K`` is
+        # neither pointed nor solid.
+        #
+        # Note that in that case we can get *duplicates*, since the
+        # tensor product of (x,s) is the same as that of (-x,-s).
+        check = False
+
+    # Create the dual cone of the cross-positive operators,
+    # expressed as long vectors.
+    Sigma_dual = Cone(vectors, lattice=ToricLattice(W.dimension()), check=check)
 
     # Now compute the desired cone from its dual...
     Sigma_cone = Sigma_dual.dual()
@@ -589,7 +615,7 @@ def Z_transformation_gens(K):
     # But first, make them negative, so we get Z-transformations and
     # not cross-positive ones.
     M = MatrixSpace(F, n)
-    return [ -M(v.list()) for v in Sigma_cone.rays() ]
+    return [ -M(v.list()) for v in Sigma_cone ]
 
 
 def Z_cone(K):