+ if K1.nrays() != K2.nrays():
+ return False
+
+ if K1.dim() != K2.dim():
+ return False
+
+ if lineality(K1) != lineality(K2):
+ return False
+
+ if K1.is_solid() != K2.is_solid():
+ return False
+
+ if K1.is_strictly_convex() != K2.is_strictly_convex():
+ return False
+
+ if len(LL(K1)) != len(LL(K2)):
+ return False
+
+ C_of_K1 = discrete_complementarity_set(K1)
+ C_of_K2 = discrete_complementarity_set(K2)
+ if len(C_of_K1) != len(C_of_K2):
+ return False
+
+ if len(K1.facets()) != len(K2.facets()):
+ return False
+
+ return True
+
+
+
+def iso_space(K):
+ r"""
+ Construct the space `W \times W^{\perp}` isomorphic to the ambient space
+ of ``K`` where `W` is equal to the span of ``K``.
+ """
+ V = K.lattice().vector_space()
+
+ # Create the space W \times W^{\perp} isomorphic to V.
+ # First we get an orthogonal (but not normal) basis...
+ M = matrix(V.base_field(), K.rays())
+ W_basis = drop_dependent(K.rays())
+
+ W = V.subspace_with_basis(W_basis)
+ W_perp = W.complement()
+
+ return W.cartesian_product(W_perp)
+
+
+def ips_iso(K):
+ r"""
+ Construct the IPS isomorphism and its inverse from our paper.
+
+ Given a cone ``K``, the returned isomorphism will split its ambient
+ vector space `V` into a cartesian product `W \times W^{\perp}` where
+ `W` equals the span of ``K``.
+ """
+ V = K.lattice().vector_space()
+ V_iso = iso_space(K)
+ (W, W_perp) = V_iso.cartesian_factors()
+
+ # A space equivalent to V, but using our basis.
+ V_user = V.subspace_with_basis( W.basis() + W_perp.basis() )
+
+ def phi(v):
+ # Write v in terms of our custom basis, where the first dim(W)
+ # coordinates are for the W-part of the basis.
+ cs = V_user.coordinates(v)
+
+ w1 = sum([ V_user.basis()[idx]*cs[idx]
+ for idx in range(0, W.dimension()) ])
+ w2 = sum([ V_user.basis()[idx]*cs[idx]
+ for idx in range(W.dimension(), V.dimension()) ])
+
+ return V_iso( (w1, w2) )
+
+
+ def phi_inv( pair ):
+ # Crash if the arguments are in the wrong spaces.
+ V_iso(pair)
+
+ #w = sum([ sub_w[idx]*W.basis()[idx] for idx in range(0,m) ])
+ #w_prime = sum([ sub_w_prime[idx]*W_perp.basis()[idx]
+ # for idx in range(0,n-m) ])
+
+ return sum( pair.cartesian_factors() )
+
+
+ return (phi,phi_inv)
+
+
+
+def unrestrict_span(K, K2=None):
+ if K2 is None:
+ K2 = K
+
+ _,phi_inv = ips_iso(K2)
+ V_iso = iso_space(K2)
+ (W, W_perp) = V_iso.cartesian_factors()
+
+ rays = []
+ for r in K.rays():
+ w = sum([ r[idx]*W.basis()[idx] for idx in range(0,len(r)) ])
+ pair = V_iso( (w, W_perp.zero()) )
+ rays.append( phi_inv(pair) )
+
+ L = ToricLattice(W.dimension() + W_perp.dimension())