Example #1
0
def LatticePolytope_PPL(*args):
    """
    Construct a new instance of the PPL-based lattice polytope class.

    EXAMPLES::

        sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
        sage: LatticePolytope_PPL((0,0),(1,0),(0,1))
        A 2-dimensional lattice polytope in ZZ^2 with 3 vertices

        sage: from sage.libs.ppl import point, Generator_System, C_Polyhedron, Linear_Expression, Variable
        sage: p = point(Linear_Expression([2,3],0));  p
        point(2/1, 3/1)
        sage: LatticePolytope_PPL(p)
        A 0-dimensional lattice polytope in ZZ^2 with 1 vertex

        sage: P = C_Polyhedron(Generator_System(p));  P
        A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point
        sage: LatticePolytope_PPL(P)
        A 0-dimensional lattice polytope in ZZ^2 with 1 vertex

    A ``TypeError`` is raised if the arguments do not specify a lattice polytope::

        sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL
        sage: LatticePolytope_PPL((0,0),(1/2,1))
        Traceback (most recent call last):
        ...
        TypeError: no conversion of this rational to integer

        sage: from sage.libs.ppl import point, Generator_System, C_Polyhedron, Linear_Expression, Variable
        sage: p = point(Linear_Expression([2,3],0), 5);  p
        point(2/5, 3/5)
        sage: LatticePolytope_PPL(p)
        Traceback (most recent call last):
         ...
        TypeError: generator is not a lattice polytope generator

        sage: P = C_Polyhedron(Generator_System(p));  P
        A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point
        sage: LatticePolytope_PPL(P)
        Traceback (most recent call last):
        ...
        TypeError: polyhedron has non-integral generators
    """
    polytope_class = LatticePolytope_PPL_class
    if len(args) == 1 and isinstance(args[0], C_Polyhedron):
        polyhedron = args[0]
        polytope_class = _class_for_LatticePolytope(
            polyhedron.space_dimension())
        if not all(p.is_point() and p.divisor().is_one()
                   for p in polyhedron.generators()):
            raise TypeError('polyhedron has non-integral generators')
        return polytope_class(polyhedron)
    if len(args)==1 \
            and isinstance(args[0], (list, tuple)) \
            and isinstance(args[0][0], (list,tuple)):
        vertices = args[0]
    else:
        vertices = args
    gs = Generator_System()
    for v in vertices:
        if isinstance(v, Generator):
            if (not v.is_point()) or (not v.divisor().is_one()):
                raise TypeError(
                    'generator is not a lattice polytope generator')
            gs.insert(v)
        else:
            gs.insert(point(Linear_Expression(v, 0)))
    if not gs.empty():
        dim = next(Generator_System_iterator(gs)).space_dimension()
        polytope_class = _class_for_LatticePolytope(dim)
    return polytope_class(gs)
Example #2
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)
Example #3
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])
Example #4
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.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)