def _init_from_Hrepresentation(self, ambient_dim, ieqs, eqns, minimize=True): """ Construct polyhedron from H-representation data. INPUT: - ``ambient_dim`` -- integer. The dimension of the ambient space. - ``ieqs`` -- list of inequalities. Each line can be specified as any iterable container of :meth:`~sage.geometry.polyhedron.base.base_ring` elements. - ``eqns`` -- list of equalities. Each line can be specified as any iterable container of :meth:`~sage.geometry.polyhedron.base.base_ring` elements. EXAMPLES:: sage: p = Polyhedron(backend='ppl') sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_QQ_ppl sage: Polyhedron_QQ_ppl._init_from_Hrepresentation(p, 2, [], []) """ cs = Constraint_System() if ieqs is None: ieqs = [] for ieq in ieqs: d = lcm([denominator(ieq_i) for ieq_i in ieq]) dieq = [ ZZ(d*ieq_i) for ieq_i in ieq ] b = dieq[0] A = dieq[1:] cs.insert(Linear_Expression(A, b) >= 0) if eqns is None: eqns = [] for eqn in eqns: d = lcm([denominator(eqn_i) for eqn_i in eqn]) deqn = [ ZZ(d*eqn_i) for eqn_i in eqn ] b = deqn[0] A = deqn[1:] cs.insert(Linear_Expression(A, b) == 0) self._ppl_polyhedron = C_Polyhedron(cs) self._init_Vrepresentation_from_ppl(minimize) self._init_Hrepresentation_from_ppl(minimize)
def _init_from_Hrepresentation(self, ieqs, eqns, minimize=True, verbose=False): """ Construct polyhedron from H-representation data. INPUT: - ``ieqs`` -- list of inequalities. Each line can be specified as any iterable container of :meth:`~sage.geometry.polyhedron.base.base_ring` elements. - ``eqns`` -- list of equalities. Each line can be specified as any iterable container of :meth:`~sage.geometry.polyhedron.base.base_ring` elements. - ``verbose`` -- boolean (default: ``False``). Whether to print verbose output for debugging purposes. EXAMPLES:: sage: p = Polyhedron(backend='ppl') sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_ppl sage: Polyhedron_ppl._init_from_Hrepresentation(p, [], []) """ cs = Constraint_System() if ieqs is None: ieqs = [] for ieq in ieqs: d = LCM_list([denominator(ieq_i) for ieq_i in ieq]) dieq = [ZZ(d * ieq_i) for ieq_i in ieq] b = dieq[0] A = dieq[1:] cs.insert(Linear_Expression(A, b) >= 0) if eqns is None: eqns = [] for eqn in eqns: d = LCM_list([denominator(eqn_i) for eqn_i in eqn]) deqn = [ZZ(d * eqn_i) for eqn_i in eqn] b = deqn[0] A = deqn[1:] cs.insert(Linear_Expression(A, b) == 0) if cs.empty(): self._ppl_polyhedron = C_Polyhedron(self.ambient_dim(), 'universe') else: self._ppl_polyhedron = C_Polyhedron(cs) self._init_Vrepresentation_from_ppl(minimize) self._init_Hrepresentation_from_ppl(minimize)
def _init_from_Hrepresentation(self, ieqs, eqns, minimize=True, verbose=False): """ Construct polyhedron from H-representation data. INPUT: - ``ieqs`` -- list of inequalities. Each line can be specified as any iterable container of :meth:`~sage.geometry.polyhedron.base.base_ring` elements. - ``eqns`` -- list of equalities. Each line can be specified as any iterable container of :meth:`~sage.geometry.polyhedron.base.base_ring` elements. - ``verbose`` -- boolean (default: ``False``). Whether to print verbose output for debugging purposes. EXAMPLES:: sage: p = Polyhedron(backend='ppl') sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_ppl sage: Polyhedron_ppl._init_from_Hrepresentation(p, [], []) """ cs = Constraint_System() if ieqs is None: ieqs = [] for ieq in ieqs: d = LCM_list([denominator(ieq_i) for ieq_i in ieq]) dieq = [ ZZ(d*ieq_i) for ieq_i in ieq ] b = dieq[0] A = dieq[1:] cs.insert(Linear_Expression(A, b) >= 0) if eqns is None: eqns = [] for eqn in eqns: d = LCM_list([denominator(eqn_i) for eqn_i in eqn]) deqn = [ ZZ(d*eqn_i) for eqn_i in eqn ] b = deqn[0] A = deqn[1:] cs.insert(Linear_Expression(A, b) == 0) if cs.empty(): self._ppl_polyhedron = C_Polyhedron(self.ambient_dim(), 'universe') else: self._ppl_polyhedron = C_Polyhedron(cs) self._init_Vrepresentation_from_ppl(minimize) self._init_Hrepresentation_from_ppl(minimize)
def _init_from_Hrepresentation(self, ambient_dim, ieqs, eqns, minimize=True): """ Construct polyhedron from H-representation data. INPUT: - ``ambient_dim`` -- integer. The dimension of the ambient space. - ``ieqs`` -- list of inequalities. Each line can be specified as any iterable container of :meth:`~sage.geometry.polyhedron.base.base_ring` elements. - ``eqns`` -- list of equalities. Each line can be specified as any iterable container of :meth:`~sage.geometry.polyhedron.base.base_ring` elements. EXAMPLES:: sage: p = Polyhedron(backend='ppl') sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_QQ_ppl sage: Polyhedron_QQ_ppl._init_from_Hrepresentation(p, 2, [], []) """ cs = Constraint_System() if ieqs is None: ieqs = [] for ieq in ieqs: d = lcm([denominator(ieq_i) for ieq_i in ieq]) dieq = [ZZ(d * ieq_i) for ieq_i in ieq] b = dieq[0] A = dieq[1:] cs.insert(Linear_Expression(A, b) >= 0) if eqns is None: eqns = [] for eqn in eqns: d = lcm([denominator(eqn_i) for eqn_i in eqn]) deqn = [ZZ(d * eqn_i) for eqn_i in eqn] b = deqn[0] A = deqn[1:] cs.insert(Linear_Expression(A, b) == 0) self._ppl_polyhedron = C_Polyhedron(cs) self._init_Vrepresentation_from_ppl(minimize) self._init_Hrepresentation_from_ppl(minimize)
def normal_cone(self): r""" Return the (closure of the) normal cone of the triangulation. Recall that a regular triangulation is one that equals the "crease lines" of a convex piecewise-linear function. This support function is not unique, for example, you can scale it by a positive constant. The set of all piecewise-linear functions with fixed creases forms an open cone. This cone can be interpreted as the cone of normal vectors at a point of the secondary polytope, which is why we call it normal cone. See [GKZ]_ Section 7.1 for details. OUTPUT: The closure of the normal cone. The `i`-th entry equals the value of the piecewise-linear function at the `i`-th point of the configuration. For an irregular triangulation, the normal cone is empty. In this case, a single point (the origin) is returned. EXAMPLES:: sage: triangulation = polytopes.n_cube(2).triangulate(engine='internal') sage: triangulation (<0,1,3>, <0,2,3>) sage: N = triangulation.normal_cone(); N 4-d cone in 4-d lattice sage: N.rays() (-1, 0, 0, 0), ( 1, 0, 1, 0), (-1, 0, -1, 0), ( 1, 0, 0, -1), (-1, 0, 0, 1), ( 1, 1, 0, 0), (-1, -1, 0, 0) in Ambient free module of rank 4 over the principal ideal domain Integer Ring sage: N.dual().rays() (-1, 1, 1, -1) in Ambient free module of rank 4 over the principal ideal domain Integer Ring TESTS:: sage: polytopes.n_simplex(2).triangulate().normal_cone() 3-d cone in 3-d lattice sage: _.dual().is_trivial() True """ if not self.point_configuration().base_ring().is_subring(QQ): raise NotImplementedError("Only base rings ZZ and QQ are supported") from sage.libs.ppl import Variable, Constraint, Constraint_System, Linear_Expression, C_Polyhedron from sage.matrix.constructor import matrix from sage.misc.misc import uniq from sage.rings.arith import lcm pc = self.point_configuration() cs = Constraint_System() for facet in self.interior_facets(): s0, s1 = self._boundary_simplex_dictionary()[facet] p = set(s0).difference(facet).pop() q = set(s1).difference(facet).pop() origin = pc.point(p).reduced_affine_vector() base_indices = [i for i in s0 if i != p] base = matrix([pc.point(i).reduced_affine_vector() - origin for i in base_indices]) sol = base.solve_left(pc.point(q).reduced_affine_vector() - origin) relation = [0] * pc.n_points() relation[p] = sum(sol) - 1 relation[q] = 1 for i, base_i in enumerate(base_indices): relation[base_i] = -sol[i] rel_denom = lcm([QQ(r).denominator() for r in relation]) relation = [ZZ(r * rel_denom) for r in relation] ex = Linear_Expression(relation, 0) cs.insert(ex >= 0) from sage.modules.free_module import FreeModule ambient = FreeModule(ZZ, self.point_configuration().n_points()) if cs.empty(): cone = C_Polyhedron(ambient.dimension(), "universe") else: cone = C_Polyhedron(cs) from sage.geometry.cone import _Cone_from_PPL return _Cone_from_PPL(cone, lattice=ambient)
def normal_cone(self): r""" Return the (closure of the) normal cone of the triangulation. Recall that a regular triangulation is one that equals the "crease lines" of a convex piecewise-linear function. This support function is not unique, for example, you can scale it by a positive constant. The set of all piecewise-linear functions with fixed creases forms an open cone. This cone can be interpreted as the cone of normal vectors at a point of the secondary polytope, which is why we call it normal cone. See [GKZ]_ Section 7.1 for details. OUTPUT: The closure of the normal cone. The `i`-th entry equals the value of the piecewise-linear function at the `i`-th point of the configuration. For an irregular triangulation, the normal cone is empty. In this case, a single point (the origin) is returned. EXAMPLES:: sage: triangulation = polytopes.hypercube(2).triangulate(engine='internal') sage: triangulation (<0,1,3>, <0,2,3>) sage: N = triangulation.normal_cone(); N 4-d cone in 4-d lattice sage: N.rays() (-1, 0, 0, 0), ( 1, 0, 1, 0), (-1, 0, -1, 0), ( 1, 0, 0, -1), (-1, 0, 0, 1), ( 1, 1, 0, 0), (-1, -1, 0, 0) in Ambient free module of rank 4 over the principal ideal domain Integer Ring sage: N.dual().rays() (-1, 1, 1, -1) in Ambient free module of rank 4 over the principal ideal domain Integer Ring TESTS:: sage: polytopes.simplex(2).triangulate().normal_cone() 3-d cone in 3-d lattice sage: _.dual().is_trivial() True """ if not self.point_configuration().base_ring().is_subring(QQ): raise NotImplementedError( 'Only base rings ZZ and QQ are supported') from sage.libs.ppl import Variable, Constraint, Constraint_System, Linear_Expression, C_Polyhedron from sage.matrix.constructor import matrix from sage.misc.misc import uniq from sage.rings.arith import lcm pc = self.point_configuration() cs = Constraint_System() for facet in self.interior_facets(): s0, s1 = self._boundary_simplex_dictionary()[facet] p = set(s0).difference(facet).pop() q = set(s1).difference(facet).pop() origin = pc.point(p).reduced_affine_vector() base_indices = [i for i in s0 if i != p] base = matrix([ pc.point(i).reduced_affine_vector() - origin for i in base_indices ]) sol = base.solve_left(pc.point(q).reduced_affine_vector() - origin) relation = [0] * pc.n_points() relation[p] = sum(sol) - 1 relation[q] = 1 for i, base_i in enumerate(base_indices): relation[base_i] = -sol[i] rel_denom = lcm([QQ(r).denominator() for r in relation]) relation = [ZZ(r * rel_denom) for r in relation] ex = Linear_Expression(relation, 0) cs.insert(ex >= 0) from sage.modules.free_module import FreeModule ambient = FreeModule(ZZ, self.point_configuration().n_points()) if cs.empty(): cone = C_Polyhedron(ambient.dimension(), 'universe') else: cone = C_Polyhedron(cs) from sage.geometry.cone import _Cone_from_PPL return _Cone_from_PPL(cone, lattice=ambient)