Exemple #1
0
    def has_IP_property(self):
        """
        Whether the lattice polytope has the IP property.

        That is, the polytope is full-dimensional and the origin is a
        interior point not on the boundary.

        OUTPUT:

        Boolean.

        EXAMPLES::

            sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
            sage: LatticePolytope_PPL((-1,-1),(0,1),(1,0)).has_IP_property()
            True
            sage: LatticePolytope_PPL((-1,-1),(1,1)).has_IP_property()
            False
        """
        origin = C_Polyhedron(point(0*Variable(self.space_dimension())))
        is_included = Poly_Con_Relation.is_included()
        saturates = Poly_Con_Relation.saturates()
        for c in self.constraints():
            rel = origin.relation_with(c)
            if (not rel.implies(is_included)) or rel.implies(saturates):
                return False
        return True
    def vertices_saturating(self, constraint):
        """
        Return the vertices saturating the constraint

        INPUT:

        - ``constraint`` -- a constraint (inequality or equation) of
          the polytope.

        OUTPUT:

        The tuple of vertices saturating the constraint. The vertices
        are returned as `\ZZ`-vectors, as in :meth:`vertices`.

        EXAMPLES::

            sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
            sage: p = LatticePolytope_PPL((0,0),(0,1),(1,0))
            sage: ieq = next(iter(p.constraints()));  ieq
            x0>=0
            sage: p.vertices_saturating(ieq)
            ((0, 0), (0, 1))
        """
        from sage.libs.ppl import C_Polyhedron, Poly_Con_Relation
        result = []
        for i,v in enumerate(self.minimized_generators()):
            v = C_Polyhedron(v)
            if v.relation_with(constraint).implies(Poly_Con_Relation.saturates()):
                result.append(self.vertices()[i])
        return tuple(result)
Exemple #3
0
    def contains(self, point_coordinates):
        r"""
        Test whether point is contained in the polytope.

        INPUT:

        - ``point_coordinates`` -- a list/tuple/iterable of rational
          numbers. The coordinates of the point.

        OUTPUT:

        Boolean.

        EXAMPLES::

            sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
            sage: line = LatticePolytope_PPL((1,2,3), (-1,-2,-3))
            sage: line.contains([0,0,0])
            True
            sage: line.contains([1,0,0])
            False
        """
        p = C_Polyhedron(point(Linear_Expression(list(point_coordinates), 1)))
        is_included = Poly_Con_Relation.is_included()
        for c in self.constraints():
            if not p.relation_with(c).implies(is_included):
                return False
        return True
Exemple #4
0
    def vertices_saturating(self, constraint):
        """
        Return the vertices saturating the constraint

        INPUT:

        - ``constraint`` -- a constraint (inequality or equation) of
          the polytope.

        OUTPUT:

        The tuple of vertices saturating the constraint. The vertices
        are returned as `\ZZ`-vectors, as in :meth:`vertices`.

        EXAMPLES::

            sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
            sage: p = LatticePolytope_PPL((0,0),(0,1),(1,0))
            sage: ieq = iter(p.constraints()).next();  ieq
            x0>=0
            sage: p.vertices_saturating(ieq)
            ((0, 0), (0, 1))
        """
        from sage.libs.ppl import C_Polyhedron, Poly_Con_Relation
        result = []
        for i,v in enumerate(self.minimized_generators()):
            v = C_Polyhedron(v)
            if v.relation_with(constraint).implies(Poly_Con_Relation.saturates()):
                result.append(self.vertices()[i])
        return tuple(result)
    def contains(self, point_coordinates):
        r"""
        Test whether point is contained in the polytope.

        INPUT:

        - ``point_coordinates`` -- a list/tuple/iterable of rational
          numbers. The coordinates of the point.

        OUTPUT:

        Boolean.

        EXAMPLES::

            sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
            sage: line = LatticePolytope_PPL((1,2,3), (-1,-2,-3))
            sage: line.contains([0,0,0])
            True
            sage: line.contains([1,0,0])
            False
        """
        p = C_Polyhedron(point(Linear_Expression(list(point_coordinates), 1)))
        is_included = Poly_Con_Relation.is_included()
        for c in self.constraints():
            if not p.relation_with(c).implies(is_included):
                return False
        return True
    def has_IP_property(self):
        """
        Whether the lattice polytope has the IP property.

        That is, the polytope is full-dimensional and the origin is a
        interior point not on the boundary.

        OUTPUT:

        Boolean.

        EXAMPLES::

            sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
            sage: LatticePolytope_PPL((-1,-1),(0,1),(1,0)).has_IP_property()
            True
            sage: LatticePolytope_PPL((-1,-1),(1,1)).has_IP_property()
            False
        """
        origin = C_Polyhedron(point(0*Variable(self.space_dimension())))
        is_included = Poly_Con_Relation.is_included()
        saturates = Poly_Con_Relation.saturates()
        for c in self.constraints():
            rel = origin.relation_with(c)
            if (not rel.implies(is_included)) or rel.implies(saturates):
                return False
        return True
Exemple #7
0
    def _init_from_Vrepresentation(self, vertices, rays, lines, minimize=True, verbose=False):
        """
        Construct polyhedron from V-representation data.

        INPUT:

        - ``vertices`` -- list of point. Each point can be specified
           as any iterable container of
           :meth:`~sage.geometry.polyhedron.base.base_ring` elements.

        - ``rays`` -- list of rays. Each ray can be specified as any
          iterable container of
          :meth:`~sage.geometry.polyhedron.base.base_ring` elements.

        - ``lines`` -- list of lines. 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_Vrepresentation(p, [], [], [])
        """
        gs = Generator_System()
        if vertices is None: vertices = []
        for v in vertices:
            d = LCM_list([denominator(v_i) for v_i in v])
            if d.is_one():
                gs.insert(point(Linear_Expression(v, 0)))
            else:
                dv = [ d*v_i for v_i in v ]
                gs.insert(point(Linear_Expression(dv, 0), d))
        if rays is None: rays = []
        for r in rays:
            d = LCM_list([denominator(r_i) for r_i in r])
            if d.is_one():
                gs.insert(ray(Linear_Expression(r, 0)))
            else:
                dr = [ d*r_i for r_i in r ]
                gs.insert(ray(Linear_Expression(dr, 0)))
        if lines is None: lines = []
        for l in lines:
            d = LCM_list([denominator(l_i) for l_i in l])
            if d.is_one():
                gs.insert(line(Linear_Expression(l, 0)))
            else:
                dl = [ d*l_i for l_i in l ]
                gs.insert(line(Linear_Expression(dl, 0)))
        if gs.empty():
            self._ppl_polyhedron = C_Polyhedron(self.ambient_dim(), 'empty')
        else:
            self._ppl_polyhedron = C_Polyhedron(gs)
        self._init_Vrepresentation_from_ppl(minimize)
        self._init_Hrepresentation_from_ppl(minimize)
Exemple #8
0
    def _init_from_Vrepresentation(self, vertices, rays, lines, minimize=True):
        """
        Construct polyhedron from V-representation data.

        INPUT:

        - ``vertices`` -- list of point. Each point can be specified
           as any iterable container of
           :meth:`~sage.geometry.polyhedron.base.base_ring` elements.

        - ``rays`` -- list of rays. Each ray can be specified as any
          iterable container of
          :meth:`~sage.geometry.polyhedron.base.base_ring` elements.

        - ``lines`` -- list of lines. 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_ppl
            sage: Polyhedron_ppl._init_from_Vrepresentation(p, [], [], [])
        """
        gs = Generator_System()
        if vertices is None: vertices = []
        for v in vertices:
            d = LCM_list([denominator(v_i) for v_i in v])
            if d.is_one():
                gs.insert(point(Linear_Expression(v, 0)))
            else:
                dv = [d * v_i for v_i in v]
                gs.insert(point(Linear_Expression(dv, 0), d))
        if rays is None: rays = []
        for r in rays:
            d = LCM_list([denominator(r_i) for r_i in r])
            if d.is_one():
                gs.insert(ray(Linear_Expression(r, 0)))
            else:
                dr = [d * r_i for r_i in r]
                gs.insert(ray(Linear_Expression(dr, 0)))
        if lines is None: lines = []
        for l in lines:
            d = LCM_list([denominator(l_i) for l_i in l])
            if d.is_one():
                gs.insert(line(Linear_Expression(l, 0)))
            else:
                dl = [d * l_i for l_i in l]
                gs.insert(line(Linear_Expression(dl, 0)))
        if gs.empty():
            self._ppl_polyhedron = C_Polyhedron(self.ambient_dim(), 'empty')
        else:
            self._ppl_polyhedron = C_Polyhedron(gs)
        self._init_Vrepresentation_from_ppl(minimize)
        self._init_Hrepresentation_from_ppl(minimize)
Exemple #9
0
    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 __call__(self, x):
        """
        Return the image of ``x``

        INPUT:

        - ``x`` -- a vector or lattice polytope.

        EXAMPLES::

            sage: from sage.geometry.polyhedron.ppl_lattice_polytope \
            ....:     import LatticePolytope_PPL, C_Polyhedron
            sage: from sage.geometry.polyhedron.lattice_euclidean_group_element \
            ....:     import LatticeEuclideanGroupElement
            sage: M = LatticeEuclideanGroupElement([[1,2],[2,3],[-1,2]], [1,2,3])
            sage: M(vector(ZZ, [11,13]))
            (38, 63, 18)
            sage: M(LatticePolytope_PPL((0,0),(1,0),(0,1)))
            A 2-dimensional lattice polytope in ZZ^3 with 3 vertices
        """
        from sage.geometry.polyhedron.ppl_lattice_polytope import (
            LatticePolytope_PPL, LatticePolytope_PPL_class)
        if isinstance(x, LatticePolytope_PPL_class):
            if x.is_empty():
                from sage.libs.ppl import C_Polyhedron
                return LatticePolytope_PPL(C_Polyhedron(self._b.degree(),
                                                        'empty'))
            return LatticePolytope_PPL(*[self(v) for v in x.vertices()])
            pass
        v = self._A*x+self._b
        v.set_immutable()

        return v
Exemple #11
0
    def _init_empty_polyhedron(self):
        """
        Initializes an empty polyhedron.

        TESTS::

            sage: empty = Polyhedron(backend='ppl'); empty
            The empty polyhedron in ZZ^0
            sage: empty.Vrepresentation()
            ()
            sage: empty.Hrepresentation()
            (An equation -1 == 0,)
            sage: Polyhedron(vertices = [], backend='ppl')
            The empty polyhedron in ZZ^0
            sage: Polyhedron(backend='ppl')._init_empty_polyhedron()
        """
        super(Polyhedron_ppl, self)._init_empty_polyhedron()
        self._ppl_polyhedron = C_Polyhedron(self.ambient_dim(), 'empty')
Exemple #12
0
    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)
Exemple #13
0
    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)
Exemple #14
0
    def _init_empty_polyhedron(self, ambient_dim):
        """
        Initializes an empty polyhedron.

        INPUT:

        - ``ambient_dim`` -- integer. The dimension of the ambient space.

        TESTS::

            sage: empty = Polyhedron(backend='ppl'); empty
            The empty polyhedron in QQ^0
            sage: empty.Vrepresentation()
            ()
            sage: empty.Hrepresentation()
            (An equation -1 == 0,)
            sage: Polyhedron(vertices = [], backend='ppl')
            The empty polyhedron in QQ^0
            sage: Polyhedron(backend='ppl')._init_empty_polyhedron(0)
        """
        super(Polyhedron_QQ_ppl, self)._init_empty_polyhedron(ambient_dim)
        self._ppl_polyhedron = C_Polyhedron(ambient_dim, 'empty')
Exemple #15
0
    def _init_from_Vrepresentation(self, ambient_dim, vertices, rays, lines, minimize=True):
        """
        Construct polyhedron from V-representation data.

        INPUT:

        - ``ambient_dim`` -- integer. The dimension of the ambient space.
        
        - ``vertices`` -- list of point. Each point can be specified
           as any iterable container of
           :meth:`~sage.geometry.polyhedron.base.base_ring` elements.
        
        - ``rays`` -- list of rays. Each ray can be specified as any
          iterable container of
          :meth:`~sage.geometry.polyhedron.base.base_ring` elements.
        
        - ``lines`` -- list of lines. 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_Vrepresentation(p, 2, [], [], [])
        """
        gs = Generator_System()
        if vertices is None: vertices = []
        for v in vertices:
            d = lcm([denominator(v_i) for v_i in v])
            dv = [ ZZ(d*v_i) for v_i in v ]
            gs.insert(point(Linear_Expression(dv, 0), d))
        if rays is None: rays = []
        for r in rays:
            d = lcm([denominator(r_i) for r_i in r])
            dr = [ ZZ(d*r_i) for r_i in r ]
            gs.insert(ray(Linear_Expression(dr, 0)))
        if lines is None: lines = []
        for l in lines:
            d = lcm([denominator(l_i) for l_i in l])
            dl = [ ZZ(d*l_i) for l_i in l ]
            gs.insert(line(Linear_Expression(dl, 0)))
        self._ppl_polyhedron = C_Polyhedron(gs)
        self._init_Vrepresentation_from_ppl(minimize)
        self._init_Hrepresentation_from_ppl(minimize)
Exemple #16
0
    def _init_empty_polyhedron(self):
        """
        Initializes an empty polyhedron.

        TESTS::

            sage: empty = Polyhedron(backend='ppl'); empty
            The empty polyhedron in ZZ^0
            sage: empty.Vrepresentation()
            ()
            sage: empty.Hrepresentation()
            (An equation -1 == 0,)
            sage: Polyhedron(vertices = [], backend='ppl')
            The empty polyhedron in ZZ^0
            sage: Polyhedron(backend='ppl')._init_empty_polyhedron()
        """
        super(Polyhedron_ppl, self)._init_empty_polyhedron()
        self._ppl_polyhedron = C_Polyhedron(self.ambient_dim(), 'empty')
Exemple #17
0
    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)
Exemple #18
0
    def _init_empty_polyhedron(self, ambient_dim):
        """
        Initializes an empty polyhedron.

        INPUT:

        - ``ambient_dim`` -- integer. The dimension of the ambient space.

        TESTS::

            sage: empty = Polyhedron(backend='ppl'); empty
            The empty polyhedron in QQ^0
            sage: empty.Vrepresentation()
            ()
            sage: empty.Hrepresentation()
            (An equation -1 == 0,)
            sage: Polyhedron(vertices = [], backend='ppl')
            The empty polyhedron in QQ^0
            sage: Polyhedron(backend='ppl')._init_empty_polyhedron(0)
        """
        super(Polyhedron_QQ_ppl, self)._init_empty_polyhedron(ambient_dim)
        self._ppl_polyhedron = C_Polyhedron(ambient_dim, 'empty')
Exemple #19
0
class Polyhedron_ppl(Polyhedron_base):
    """
    Polyhedra with ppl

    INPUT:

    - ``Vrep`` -- a list ``[vertices, rays, lines]`` or ``None``.

    - ``Hrep`` -- a list ``[ieqs, eqns]`` or ``None``.

    EXAMPLES::

        sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)], rays=[(1,1)], lines=[], backend='ppl')
        sage: TestSuite(p).run()
    """
    def _init_from_Vrepresentation(self,
                                   vertices,
                                   rays,
                                   lines,
                                   minimize=True,
                                   verbose=False):
        """
        Construct polyhedron from V-representation data.

        INPUT:

        - ``vertices`` -- list of point. Each point can be specified
           as any iterable container of
           :meth:`~sage.geometry.polyhedron.base.base_ring` elements.

        - ``rays`` -- list of rays. Each ray can be specified as any
          iterable container of
          :meth:`~sage.geometry.polyhedron.base.base_ring` elements.

        - ``lines`` -- list of lines. 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_Vrepresentation(p, [], [], [])
        """
        gs = Generator_System()
        if vertices is None: vertices = []
        for v in vertices:
            d = LCM_list([denominator(v_i) for v_i in v])
            if d.is_one():
                gs.insert(point(Linear_Expression(v, 0)))
            else:
                dv = [d * v_i for v_i in v]
                gs.insert(point(Linear_Expression(dv, 0), d))
        if rays is None: rays = []
        for r in rays:
            d = LCM_list([denominator(r_i) for r_i in r])
            if d.is_one():
                gs.insert(ray(Linear_Expression(r, 0)))
            else:
                dr = [d * r_i for r_i in r]
                gs.insert(ray(Linear_Expression(dr, 0)))
        if lines is None: lines = []
        for l in lines:
            d = LCM_list([denominator(l_i) for l_i in l])
            if d.is_one():
                gs.insert(line(Linear_Expression(l, 0)))
            else:
                dl = [d * l_i for l_i in l]
                gs.insert(line(Linear_Expression(dl, 0)))
        if gs.empty():
            self._ppl_polyhedron = C_Polyhedron(self.ambient_dim(), 'empty')
        else:
            self._ppl_polyhedron = C_Polyhedron(gs)
        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_Vrepresentation_from_ppl(self, minimize):
        """
        Create the Vrepresentation objects from the ppl polyhedron.

        EXAMPLES::

            sage: p = Polyhedron(vertices=[(0,1/2),(2,0),(4,5/6)],
            ...                  backend='ppl')  # indirect doctest
            sage: p.Hrepresentation()
            (An inequality (1, 4) x - 2 >= 0,
             An inequality (1, -12) x + 6 >= 0,
             An inequality (-5, 12) x + 10 >= 0)
            sage: p._ppl_polyhedron.minimized_constraints()
            Constraint_System {x0+4*x1-2>=0, x0-12*x1+6>=0, -5*x0+12*x1+10>=0}
            sage: p.Vrepresentation()
            (A vertex at (0, 1/2), A vertex at (2, 0), A vertex at (4, 5/6))
            sage: p._ppl_polyhedron.minimized_generators()
            Generator_System {point(0/2, 1/2), point(2/1, 0/1), point(24/6, 5/6)}
        """
        self._Vrepresentation = []
        gs = self._ppl_polyhedron.minimized_generators()
        parent = self.parent()
        for g in gs:
            if g.is_point():
                d = g.divisor()
                if d.is_one():
                    parent._make_Vertex(self, g.coefficients())
                else:
                    parent._make_Vertex(self,
                                        [x / d for x in g.coefficients()])
            elif g.is_ray():
                parent._make_Ray(self, g.coefficients())
            elif g.is_line():
                parent._make_Line(self, g.coefficients())
            else:
                assert False
        self._Vrepresentation = tuple(self._Vrepresentation)

    def _init_Hrepresentation_from_ppl(self, minimize):
        """
        Create the Hrepresentation objects from the ppl polyhedron.

        EXAMPLES::

            sage: p = Polyhedron(vertices=[(0,1/2),(2,0),(4,5/6)],
            ...                  backend='ppl')  # indirect doctest
            sage: p.Hrepresentation()
            (An inequality (1, 4) x - 2 >= 0,
             An inequality (1, -12) x + 6 >= 0,
             An inequality (-5, 12) x + 10 >= 0)
            sage: p._ppl_polyhedron.minimized_constraints()
            Constraint_System {x0+4*x1-2>=0, x0-12*x1+6>=0, -5*x0+12*x1+10>=0}
            sage: p.Vrepresentation()
            (A vertex at (0, 1/2), A vertex at (2, 0), A vertex at (4, 5/6))
            sage: p._ppl_polyhedron.minimized_generators()
            Generator_System {point(0/2, 1/2), point(2/1, 0/1), point(24/6, 5/6)}
        """
        self._Hrepresentation = []
        cs = self._ppl_polyhedron.minimized_constraints()
        parent = self.parent()
        for c in cs:
            if c.is_inequality():
                parent._make_Inequality(self, (c.inhomogeneous_term(), ) +
                                        c.coefficients())
            elif c.is_equality():
                parent._make_Equation(self, (c.inhomogeneous_term(), ) +
                                      c.coefficients())
        self._Hrepresentation = tuple(self._Hrepresentation)

    def _init_empty_polyhedron(self):
        """
        Initializes an empty polyhedron.

        TESTS::

            sage: empty = Polyhedron(backend='ppl'); empty
            The empty polyhedron in ZZ^0
            sage: empty.Vrepresentation()
            ()
            sage: empty.Hrepresentation()
            (An equation -1 == 0,)
            sage: Polyhedron(vertices = [], backend='ppl')
            The empty polyhedron in ZZ^0
            sage: Polyhedron(backend='ppl')._init_empty_polyhedron()
        """
        super(Polyhedron_ppl, self)._init_empty_polyhedron()
        self._ppl_polyhedron = C_Polyhedron(self.ambient_dim(), 'empty')
    def fibration_generator(self, dim):
        """
        Generate the lattice polytope fibrations.

        For the purposes of this function, a lattice polytope fiber is
        a sub-lattice polytope. Projecting the plane spanned by the
        subpolytope to a point yields another lattice polytope, the
        base of the fibration.

        INPUT:

        - ``dim`` -- integer. The dimension of the lattice polytope
          fiber.

        OUTPUT:

        A generator yielding the distinct lattice polytope fibers of
        given dimension.

        EXAMPLES::

            sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
            sage: p = LatticePolytope_PPL((-9,-6,-1,-1),(0,0,0,1),(0,0,1,0),(0,1,0,0),(1,0,0,0))
            sage: list( p.fibration_generator(2) )
            [A 2-dimensional lattice polytope in ZZ^4 with 3 vertices]
        """
        assert self.is_full_dimensional()
        codim = self.space_dimension() - dim
        # "points" are the potential vertices of the fiber. They are
        # in the $codim$-skeleton of the polytope, which is contained
        # in the points that saturate at least $dim$ equations.
        points = [ p for p in self._integral_points_saturating() if len(p[1])>=dim ]
        points = sorted(points, key=lambda x:len(x[1]))

        # iterate over point combinations subject to all points being on one facet.
        def point_combinations_iterator(n, i0=0, saturated=None):
            for i in range(i0, len(points)):
                p, ieqs = points[i]
                if saturated is None:
                    saturated_ieqs = ieqs
                else:
                    saturated_ieqs = saturated.intersection(ieqs)
                if len(saturated_ieqs)==0:
                    continue
                if n == 1:
                    yield [i]
                else:
                    for c in point_combinations_iterator(n-1, i+1, saturated_ieqs):
                        yield [i] + c

        point_lines = [ line(Linear_Expression(p[0].list(),0)) for p in points ]
        origin = point()
        fibers = set()
        gs = Generator_System()
        for indices in point_combinations_iterator(dim):
            gs.clear()
            gs.insert(origin)
            for i in indices:
                gs.insert(point_lines[i])
            plane = C_Polyhedron(gs)
            if plane.affine_dimension() != dim:
                continue
            plane.intersection_assign(self)
            if (not self.is_full_dimensional()) and (plane.affine_dimension() != dim):
                continue
            try:
                fiber = LatticePolytope_PPL(plane)
            except TypeError:   # not a lattice polytope
                continue
            fiber_vertices = tuple(sorted(fiber.vertices()))
            if fiber_vertices not in fibers:
                yield fiber
                fibers.update([fiber_vertices])
    def find_isomorphism(self, polytope):
        """
        Return a lattice isomorphism with ``polytope``.

        INPUT:

        - ``polytope`` -- a polytope, potentially higher-dimensional.

        OUTPUT:

        A
        :class:`~sage.geometry.polyhedron.lattice_euclidean_group_element.LatticeEuclideanGroupElement`. It
        is not necessarily invertible if the affine dimension of
        ``self`` or ``polytope`` is not two. A
        :class:`~sage.geometry.polyhedron.lattice_euclidean_group_element.LatticePolytopesNotIsomorphicError`
        is raised if no such isomorphism exists.

        EXAMPLES::

            sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
            sage: L1 = LatticePolytope_PPL((1,0),(0,1),(0,0))
            sage: L2 = LatticePolytope_PPL((1,0,3),(0,1,0),(0,0,1))
            sage: iso = L1.find_isomorphism(L2)
            sage: iso(L1) == L2
            True

            sage: L1 = LatticePolytope_PPL((0, 1), (3, 0), (0, 3), (1, 0))
            sage: L2 = LatticePolytope_PPL((0,0,2,1),(0,1,2,0),(2,0,0,3),(2,3,0,0))
            sage: iso = L1.find_isomorphism(L2)
            sage: iso(L1) == L2
            True

        The following polygons are isomorphic over `\QQ`, but not as
        lattice polytopes::

            sage: L1 = LatticePolytope_PPL((1,0),(0,1),(-1,-1))
            sage: L2 = LatticePolytope_PPL((0, 0), (0, 1), (1, 0))
            sage: L1.find_isomorphism(L2)
            Traceback (most recent call last):
            ...
            LatticePolytopesNotIsomorphicError: different number of integral points
            sage: L2.find_isomorphism(L1)
            Traceback (most recent call last):
            ...
            LatticePolytopesNotIsomorphicError: different number of integral points
        """
        from sage.geometry.polyhedron.lattice_euclidean_group_element import \
            LatticePolytopesNotIsomorphicError
        if polytope.affine_dimension() != self.affine_dimension():
            raise LatticePolytopesNotIsomorphicError('different dimension')
        polytope_vertices = polytope.vertices()
        if len(polytope_vertices) != self.n_vertices():
            raise LatticePolytopesNotIsomorphicError('different number of vertices')
        self_vertices = self.ordered_vertices()
        if len(polytope.integral_points()) != len(self.integral_points()):
            raise LatticePolytopesNotIsomorphicError('different number of integral points')

        if len(self_vertices) < 3:
            return self._find_isomorphism_degenerate(polytope)

        polytope_origin = polytope_vertices[0]
        origin_P = C_Polyhedron(next(Generator_System_iterator(
            polytope.minimized_generators())))

        neighbors = []
        for c in polytope.minimized_constraints():
            if not c.is_inequality():
                continue
            if origin_P.relation_with(c).implies(Poly_Con_Relation.saturates()):
                for i, g in enumerate(polytope.minimized_generators()):
                    if i == 0:
                        continue
                    g = C_Polyhedron(g)
                    if g.relation_with(c).implies(Poly_Con_Relation.saturates()):
                        neighbors.append(polytope_vertices[i])
                        break

        p_ray_left = neighbors[0] - polytope_origin
        p_ray_right = neighbors[1] - polytope_origin
        try:
            return self._find_cyclic_isomorphism_matching_edge(polytope, polytope_origin,
                                                               p_ray_left, p_ray_right)
        except LatticePolytopesNotIsomorphicError:
            pass
        try:
            return self._find_cyclic_isomorphism_matching_edge(polytope, polytope_origin,
                                                               p_ray_right, p_ray_left)
        except LatticePolytopesNotIsomorphicError:
            pass
        raise LatticePolytopesNotIsomorphicError('different polygons')
Exemple #22
0
class Polyhedron_QQ_ppl(Polyhedron_QQ):
    """
    Polyhedra over `\QQ` with ppl

    INPUT:

    - ``ambient_dim`` -- integer. The dimension of the ambient space.

    - ``Vrep`` -- a list ``[vertices, rays, lines]``.
        
    - ``Hrep`` -- a list ``[ieqs, eqns]``.

    EXAMPLES::

        sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)], rays=[(1,1)], lines=[], backend='ppl')
        sage: TestSuite(p).run()
    """

    def _init_from_Vrepresentation(self, ambient_dim, vertices, rays, lines, minimize=True):
        """
        Construct polyhedron from V-representation data.

        INPUT:

        - ``ambient_dim`` -- integer. The dimension of the ambient space.
        
        - ``vertices`` -- list of point. Each point can be specified
           as any iterable container of
           :meth:`~sage.geometry.polyhedron.base.base_ring` elements.
        
        - ``rays`` -- list of rays. Each ray can be specified as any
          iterable container of
          :meth:`~sage.geometry.polyhedron.base.base_ring` elements.
        
        - ``lines`` -- list of lines. 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_Vrepresentation(p, 2, [], [], [])
        """
        gs = Generator_System()
        if vertices is None: vertices = []
        for v in vertices:
            d = lcm([denominator(v_i) for v_i in v])
            dv = [ ZZ(d*v_i) for v_i in v ]
            gs.insert(point(Linear_Expression(dv, 0), d))
        if rays is None: rays = []
        for r in rays:
            d = lcm([denominator(r_i) for r_i in r])
            dr = [ ZZ(d*r_i) for r_i in r ]
            gs.insert(ray(Linear_Expression(dr, 0)))
        if lines is None: lines = []
        for l in lines:
            d = lcm([denominator(l_i) for l_i in l])
            dl = [ ZZ(d*l_i) for l_i in l ]
            gs.insert(line(Linear_Expression(dl, 0)))
        self._ppl_polyhedron = C_Polyhedron(gs)
        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 _init_Vrepresentation_from_ppl(self, minimize):
        """
        Create the Vrepresentation objects from the ppl polyhedron.
        
        EXAMPLES::

            sage: p = Polyhedron(vertices=[(0,1/2),(2,0),(4,5/6)],
            ...                  backend='ppl')  # indirect doctest
            sage: p.Hrepresentation()
            (An inequality (1, 4) x - 2 >= 0,
             An inequality (1, -12) x + 6 >= 0,
             An inequality (-5, 12) x + 10 >= 0)
            sage: p._ppl_polyhedron.minimized_constraints()
            Constraint_System {x0+4*x1-2>=0, x0-12*x1+6>=0, -5*x0+12*x1+10>=0}
            sage: p.Vrepresentation()
            (A vertex at (0, 1/2), A vertex at (2, 0), A vertex at (4, 5/6))
            sage: p._ppl_polyhedron.minimized_generators()
            Generator_System {point(0/2, 1/2), point(2/1, 0/1), point(24/6, 5/6)}
        """
        self._Vrepresentation = []
        gs = self._ppl_polyhedron.minimized_generators()
        for g in gs:
            if g.is_point():
                d = g.divisor()
                Vertex(self, [x/d for x in g.coefficients()])
            elif g.is_ray():
                Ray(self, g.coefficients())
            elif g.is_line():
                Line(self, g.coefficients())
            else:
                assert False
        self._Vrepresentation = tuple(self._Vrepresentation)
        

    def _init_Hrepresentation_from_ppl(self, minimize):
        """
        Create the Vrepresentation objects from the ppl polyhedron.
        
        EXAMPLES::

            sage: p = Polyhedron(vertices=[(0,1/2),(2,0),(4,5/6)],
            ...                  backend='ppl')  # indirect doctest
            sage: p.Hrepresentation()
            (An inequality (1, 4) x - 2 >= 0,
             An inequality (1, -12) x + 6 >= 0,
             An inequality (-5, 12) x + 10 >= 0)
            sage: p._ppl_polyhedron.minimized_constraints()
            Constraint_System {x0+4*x1-2>=0, x0-12*x1+6>=0, -5*x0+12*x1+10>=0}
            sage: p.Vrepresentation()
            (A vertex at (0, 1/2), A vertex at (2, 0), A vertex at (4, 5/6))
            sage: p._ppl_polyhedron.minimized_generators()
            Generator_System {point(0/2, 1/2), point(2/1, 0/1), point(24/6, 5/6)}
        """
        self._Hrepresentation = []
        cs = self._ppl_polyhedron.minimized_constraints()
        for c in cs:
            if c.is_inequality():
                Inequality(self, (c.inhomogeneous_term(),) + c.coefficients())
            elif c.is_equality():
                Equation(self, (c.inhomogeneous_term(),) + c.coefficients())
        self._Hrepresentation = tuple(self._Hrepresentation)
        

    def _init_empty_polyhedron(self, ambient_dim):
        """
        Initializes an empty polyhedron.

        INPUT:

        - ``ambient_dim`` -- integer. The dimension of the ambient space.

        TESTS::

            sage: empty = Polyhedron(backend='ppl'); empty
            The empty polyhedron in QQ^0
            sage: empty.Vrepresentation()
            ()
            sage: empty.Hrepresentation()
            (An equation -1 == 0,)
            sage: Polyhedron(vertices = [], backend='ppl')
            The empty polyhedron in QQ^0
            sage: Polyhedron(backend='ppl')._init_empty_polyhedron(0)
        """
        super(Polyhedron_QQ_ppl, self)._init_empty_polyhedron(ambient_dim)
        self._ppl_polyhedron = C_Polyhedron(ambient_dim, 'empty')
    def find_isomorphism(self, polytope):
        """
        Return a lattice isomorphism with ``polytope``.

        INPUT:

        - ``polytope`` -- a polytope, potentially higher-dimensional.

        OUTPUT:

        A
        :class:`~sage.geometry.polyhedron.lattice_euclidean_group_element.LatticeEuclideanGroupElement`. It
        is not necessarily invertible if the affine dimension of
        ``self`` or ``polytope`` is not two. A
        :class:`~sage.geometry.polyhedron.lattice_euclidean_group_element.LatticePolytopesNotIsomorphicError`
        is raised if no such isomorphism exists.

        EXAMPLES::

            sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
            sage: L1 = LatticePolytope_PPL((1,0),(0,1),(0,0))
            sage: L2 = LatticePolytope_PPL((1,0,3),(0,1,0),(0,0,1))
            sage: iso = L1.find_isomorphism(L2)
            sage: iso(L1) == L2
            True

            sage: L1 = LatticePolytope_PPL((0, 1), (3, 0), (0, 3), (1, 0))
            sage: L2 = LatticePolytope_PPL((0,0,2,1),(0,1,2,0),(2,0,0,3),(2,3,0,0))
            sage: iso = L1.find_isomorphism(L2)
            sage: iso(L1) == L2
            True

        The following polygons are isomorphic over `\QQ`, but not as
        lattice polytopes::

            sage: L1 = LatticePolytope_PPL((1,0),(0,1),(-1,-1))
            sage: L2 = LatticePolytope_PPL((0, 0), (0, 1), (1, 0))
            sage: L1.find_isomorphism(L2)
            Traceback (most recent call last):
            ...
            LatticePolytopesNotIsomorphicError: different number of integral points
            sage: L2.find_isomorphism(L1)
            Traceback (most recent call last):
            ...
            LatticePolytopesNotIsomorphicError: different number of integral points
        """
        from sage.geometry.polyhedron.lattice_euclidean_group_element import \
            LatticePolytopesNotIsomorphicError
        if polytope.affine_dimension() != self.affine_dimension():
            raise LatticePolytopesNotIsomorphicError('different dimension')
        polytope_vertices = polytope.vertices()
        if len(polytope_vertices) != self.n_vertices():
            raise LatticePolytopesNotIsomorphicError(
                'different number of vertices')
        self_vertices = self.ordered_vertices()
        if len(polytope.integral_points()) != len(self.integral_points()):
            raise LatticePolytopesNotIsomorphicError(
                'different number of integral points')

        if len(self_vertices) < 3:
            return self._find_isomorphism_degenerate(polytope)

        polytope_origin = polytope_vertices[0]
        origin_P = C_Polyhedron(
            next(Generator_System_iterator(polytope.minimized_generators())))

        neighbors = []
        for c in polytope.minimized_constraints():
            if not c.is_inequality():
                continue
            if origin_P.relation_with(c).implies(
                    Poly_Con_Relation.saturates()):
                for i, g in enumerate(polytope.minimized_generators()):
                    if i == 0:
                        continue
                    g = C_Polyhedron(g)
                    if g.relation_with(c).implies(
                            Poly_Con_Relation.saturates()):
                        neighbors.append(polytope_vertices[i])
                        break

        p_ray_left = neighbors[0] - polytope_origin
        p_ray_right = neighbors[1] - polytope_origin
        try:
            return self._find_cyclic_isomorphism_matching_edge(
                polytope, polytope_origin, p_ray_left, p_ray_right)
        except LatticePolytopesNotIsomorphicError:
            pass
        try:
            return self._find_cyclic_isomorphism_matching_edge(
                polytope, polytope_origin, p_ray_right, p_ray_left)
        except LatticePolytopesNotIsomorphicError:
            pass
        raise LatticePolytopesNotIsomorphicError('different polygons')
Exemple #24
0
    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)
Exemple #25
0
    def fibration_generator(self, dim):
        """
        Generate the lattice polytope fibrations.

        For the purposes of this function, a lattice polytope fiber is
        a sub-lattice polytope. Projecting the plane spanned by the
        subpolytope to a point yields another lattice polytope, the
        base of the fibration.

        INPUT:

        - ``dim`` -- integer. The dimension of the lattice polytope
          fiber.

        OUTPUT:

        A generator yielding the distinct lattice polytope fibers of
        given dimension.

        EXAMPLES::

            sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
            sage: p = LatticePolytope_PPL((-9,-6,-1,-1),(0,0,0,1),(0,0,1,0),(0,1,0,0),(1,0,0,0))
            sage: list( p.fibration_generator(2) )
            [A 2-dimensional lattice polytope in ZZ^4 with 3 vertices]
        """
        assert self.is_full_dimensional()
        codim = self.space_dimension() - dim
        # "points" are the potential vertices of the fiber. They are
        # in the $codim$-skeleton of the polytope, which is contained
        # in the points that saturate at least $dim$ equations.
        points = [ p for p in self._integral_points_saturating() if len(p[1])>=dim ]
        points = sorted(points, key=lambda x:len(x[1]))

        # iterate over point combinations subject to all points being on one facet.
        def point_combinations_iterator(n, i0=0, saturated=None):
            for i in range(i0, len(points)):
                p, ieqs = points[i]
                if saturated is None:
                    saturated_ieqs = ieqs
                else:
                    saturated_ieqs = saturated.intersection(ieqs)
                if len(saturated_ieqs)==0:
                    continue
                if n == 1:
                    yield [i]
                else:
                    for c in point_combinations_iterator(n-1, i+1, saturated_ieqs):
                        yield [i] + c

        point_lines = [ line(Linear_Expression(p[0].list(),0)) for p in points ]
        origin = point()
        fibers = set()
        gs = Generator_System()
        for indices in point_combinations_iterator(dim):
            gs.clear()
            gs.insert(origin)
            for i in indices:
                gs.insert(point_lines[i])
            plane = C_Polyhedron(gs)
            if plane.affine_dimension() != dim:
                continue
            plane.intersection_assign(self)
            if (not self.is_full_dimensional()) and (plane.affine_dimension() != dim):
                continue
            try:
                fiber = LatticePolytope_PPL(plane)
            except TypeError:   # not a lattice polytope
                continue
            fiber_vertices = tuple(sorted(fiber.vertices()))
            if fiber_vertices not in fibers:
                yield fiber
                fibers.update([fiber_vertices])