Ticket #11763: trac_11763-polyhedra_coercion_folded.2.patch

File trac_11763-polyhedra_coercion_folded.2.patch, 247.1 KB (added by vbraun, 7 years ago)

Updated patch

  • doc/en/reference/geometry.rst

    # HG changeset patch
    # User Volker Braun <vbraun@stp.dias.ie>
    # Date 1315501129 14400
    # Node ID 24e5ac38ab4e9df0c622c7e39498ce59d333048a
    # Parent  e3b550be53b3eaf9122bcd1b22205190b54bc28e
    Trac #11763: Add ZZ as allowed base ring for polyhedra
    * * *
    Trac #11763: Parents for polyhedra
    * * *
    Trac #11763: relax typechecks
    
    Some plotting commands needlessly require that the
    input is a Python list. This patch relaxes typechecks
    to allow arbitrary iterables.
    * * *
    Trac #11763: remove trailing whitespace
    
    diff --git a/doc/en/reference/geometry.rst b/doc/en/reference/geometry.rst
    a b  
    2525   sage/geometry/polyhedron/plot
    2626   sage/geometry/polyhedron/base
    2727   sage/geometry/polyhedron/base_QQ
     28   sage/geometry/polyhedron/base_ZZ
    2829   sage/geometry/polyhedron/base_RDF
     30   sage/geometry/polyhedron/face
    2931   sage/geometry/polyhedron/backend_cdd
    3032   sage/geometry/polyhedron/backend_ppl
    3133   sage/geometry/polyhedron/cdd_file_format
  • sage/categories/all.py

    diff --git a/sage/categories/all.py b/sage/categories/all.py
    a b  
    127127from highest_weight_crystals import HighestWeightCrystals
    128128from finite_crystals import FiniteCrystals
    129129from classical_crystals import ClassicalCrystals
     130
     131# polyhedra
     132from polyhedra import PolyhedralSets
  • new file sage/categories/polyhedra.py

    diff --git a/sage/categories/polyhedra.py b/sage/categories/polyhedra.py
    new file mode 100644
    - +  
     1r"""
     2Polyhedral subsets of free ZZ, QQ or RR-modules.
     3"""
     4#*****************************************************************************
     5#       Copyright (C) 2011 Volker Braun <vbraun.name@gmail.com>
     6#
     7#  Distributed under the terms of the GNU General Public License (GPL)
     8#                  http://www.gnu.org/licenses/
     9#******************************************************************************
     10
     11from sage.structure.element_wrapper import ElementWrapper
     12from sage.categories.category_types import Category_over_base_ring
     13from sage.misc.cachefunc import cached_method
     14from sage.categories.category import HomCategory
     15
     16
     17
     18class PolyhedralSets(Category_over_base_ring):
     19    r"""
     20    The category of Polyhedra over a ring.
     21
     22    EXAMPLES:
     23
     24    We create the category of polyhedra over `\QQ`::
     25
     26        sage: PolyhedralSets(QQ)
     27        Category of Polyhedra over Rational Field
     28
     29    TESTS::
     30
     31        sage: TestSuite(PolyhedralSets(RDF)).run()
     32
     33        sage: P = Polyhedron()
     34        sage: P.parent().category().element_class
     35        <class 'sage.categories.category.PolyhedralSets.element_class'>
     36        sage: P.parent().category().element_class.mro()
     37        [<class 'sage.categories.category.PolyhedralSets.element_class'>,
     38         <class 'sage.categories.magmas.Magmas.element_class'>,
     39         <class 'sage.categories.additive_magmas.AdditiveMagmas.element_class'>,
     40         <class 'sage.categories.sets_cat.Sets.element_class'>,
     41         <class 'sage.categories.category.SetsWithPartialMaps.element_class'>,
     42         <class 'sage.categories.objects.Objects.element_class'>,
     43         <type 'object'>]
     44        sage: isinstance(P, P.parent().category().element_class)
     45        True
     46    """
     47
     48    def __init__(self, R):
     49        """
     50        TESTS::
     51
     52            sage: PolyhedralSets((1,2,3))
     53            Traceback (most recent call last):
     54            ...
     55            TypeError: base ring R (=(1, 2, 3)) must be ZZ, QQ, or RDF.
     56        """
     57        from sage.rings.all import ZZ, QQ, RDF
     58        if R not in [ZZ, QQ, RDF]:
     59            raise TypeError, 'base ring R (='+str(R)+') must be ZZ, QQ, or RDF.'
     60        Category_over_base_ring.__init__(self, R, 'Polyhedra')
     61
     62    @cached_method
     63    def super_categories(self):
     64        """
     65        EXAMPLES::
     66
     67            sage: PolyhedralSets(QQ).super_categories()
     68            [Category of magmas, Category of additive magmas]
     69        """
     70        from sage.categories.all import Magmas, AdditiveMagmas
     71        return [Magmas(), AdditiveMagmas()]
     72
     73
     74
     75
  • sage/geometry/cone.py

    diff --git a/sage/geometry/cone.py b/sage/geometry/cone.py
    a b  
    171171    sage: four_rays.lattice_polytope()
    172172    A lattice polytope: 3-dimensional, 5 vertices.
    173173    sage: four_rays.polyhedron()
    174     A 3-dimensional polyhedron in QQ^3 defined as
     174    A 3-dimensional polyhedron in ZZ^3 defined as
    175175    the convex hull of 1 vertex and 4 rays
    176176
    177177And of course you are always welcome to suggest new features that should be
     
    568568        V = lattice.base_extend(QQ)
    569569        for n, ray in enumerate(rays):
    570570            try:
    571                 ray = V(ray)
     571                if isinstance(ray, (list, tuple, V._element_class)):
     572                    ray = V(ray)
     573                else:
     574                    ray = V(list(ray))
    572575            except TypeError:
    573576                raise TypeError("cannot convert %s to %s!" % (ray, V))
    574577            if ray.is_zero():
     
    31063109
    31073110            sage: quadrant = Cone([(1,0), (0,1)])
    31083111            sage: quadrant.polyhedron()
    3109             A 2-dimensional polyhedron in QQ^2 defined as the convex hull
     3112            A 2-dimensional polyhedron in ZZ^2 defined as the convex hull
    31103113            of 1 vertex and 2 rays
    31113114            sage: line = Cone([(1,0), (-1,0)])
    31123115            sage: line.polyhedron()
    3113             A 1-dimensional polyhedron in QQ^2 defined as the convex hull
     3116            A 1-dimensional polyhedron in ZZ^2 defined as the convex hull
    31143117            of 1 vertex and 1 line
    31153118           
    31163119        Here is an example of a trivial cone (see Trac #10237)::
    31173120       
    31183121            sage: origin = Cone([], lattice=ZZ^2)
    31193122            sage: origin.polyhedron()
    3120             A 0-dimensional polyhedron in QQ^2 defined as the convex hull
     3123            A 0-dimensional polyhedron in ZZ^2 defined as the convex hull
    31213124            of 1 vertex
    31223125        """
    31233126        if "_polyhedron" not in self.__dict__:
  • sage/geometry/integral_points.pyx

    diff --git a/sage/geometry/integral_points.pyx b/sage/geometry/integral_points.pyx
    a b  
    266266   
    267267        sage: v = [(1,0,7,-1), (-2,-2,4,-3), (-1,-1,-1,4), (2,9,0,-5), (-2,-1,5,1)]
    268268        sage: simplex = Polyhedron(v); simplex
    269         A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 5 vertices
     269        A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 5 vertices
    270270        sage: pts = simplex_points(simplex.Vrepresentation())
    271271        sage: len(pts)
    272272        49
     
    279279       
    280280        sage: v = [(4,-1,-1,-1), (-1,4,-1,-1), (-1,-1,4,-1), (-1,-1,-1,4), (-1,-1,-1,-1)]
    281281        sage: P4mirror = Polyhedron(v); P4mirror
    282         A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 5 vertices
     282        A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 5 vertices
    283283        sage: len( simplex_points(P4mirror.Vrepresentation()) )
    284284        126
    285285    """
     
    878878        max_abs_coordinates = permutation.action(max_abs_coordinates)
    879879        self.ineqs_int = []
    880880        self.ineqs_generic = []
    881         if not polyhedron:
     881        if polyhedron is None:
    882882            return
    883883        for Hrep_obj in polyhedron.inequality_generator():
    884884            A, b = self._make_A_b(Hrep_obj, permutation)
  • sage/geometry/polyhedron/backend_cdd.py

    diff --git a/sage/geometry/polyhedron/backend_cdd.py b/sage/geometry/polyhedron/backend_cdd.py
    a b  
    1010from base import Polyhedron_base
    1111from base_QQ import Polyhedron_QQ
    1212from base_RDF import Polyhedron_RDF
    13 from representation import (
    14     PolyhedronRepresentation,
    15     Hrepresentation,
    16     Inequality, Equation,
    17     Vrepresentation,
    18     Vertex, Ray, Line )
    1913
    2014
    2115
     
    2519    Base class for the cdd backend.
    2620    """
    2721
    28     def _init_from_Vrepresentation(self, ambient_dim, vertices, rays, lines, verbose=False):
     22    def _init_from_Vrepresentation(self, vertices, rays, lines, verbose=False):
    2923        """
    3024        Construct polyhedron from V-representation data.
    3125
    3226        INPUT:
    3327
    34         - ``ambient_dim`` -- integer. The dimension of the ambient space.
    35        
    3628        - ``vertices`` -- list of point. Each point can be specified
    3729           as any iterable container of
    3830           :meth:`~sage.geometry.polyhedron.base.base_ring` elements.
    39        
     31
    4032        - ``rays`` -- list of rays. Each ray can be specified as any
    4133          iterable container of
    4234          :meth:`~sage.geometry.polyhedron.base.base_ring` elements.
    43        
     35
    4436        - ``lines`` -- list of lines. Each line can be specified as
    4537          any iterable container of
    4638          :meth:`~sage.geometry.polyhedron.base.base_ring` elements.
     
    5143        EXAMPLES::
    5244
    5345            sage: Polyhedron(vertices=[(0,0)], rays=[(1,1)],
    54             ...              lines=[(1,-1)], backend='cddr')  # indirect doctest
     46            ...              lines=[(1,-1)], backend='cdd', base_ring=QQ)  # indirect doctest
    5547            A 2-dimensional polyhedron in QQ^2 defined as the
    5648            convex hull of 1 vertex, 1 ray, 1 line
    5749        """
     
    6052        self._init_from_cdd_input(s, '--reps', verbose)
    6153
    6254
    63     def _init_from_Hrepresentation(self, ambient_dim, ieqs, eqns, verbose=False):
     55    def _init_from_Hrepresentation(self, ieqs, eqns, verbose=False):
    6456        """
    6557        Construct polyhedron from H-representation data.
    6658
    6759        INPUT:
    6860
    69         - ``ambient_dim`` -- integer. The dimension of the ambient space.
    70        
    7161        - ``ieqs`` -- list of inequalities. Each line can be specified
    7262          as any iterable container of
    7363          :meth:`~sage.geometry.polyhedron.base.base_ring` elements.
     
    8272        EXAMPLES::
    8373
    8474            sage: Polyhedron(ieqs=[(0,1,1)], eqns=[(0,1,-1)],
    85             ...              backend='cddr')  # indirect doctest
     75            ...              backend='cdd', base_ring=QQ)  # indirect doctest
    8676            A 1-dimensional polyhedron in QQ^2 defined as the
    8777            convex hull of 1 vertex and 1 ray
    8878        """
     
    9787        computed during initialization.
    9888
    9989        EXAMPLES::
    100        
    101             sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)], backend='cddr')
     90
     91            sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)], backend='cdd', base_ring=QQ)
    10292            sage: '_H_adjacency_matrix' in p.__dict__
    10393            False
    10494            sage: p._init_facet_adjacency_matrix()
     
    117107        computed during initialization.
    118108
    119109        EXAMPLES::
    120        
    121             sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)], backend='cddr')
     110
     111            sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)], backend='cdd', base_ring=QQ)
    122112            sage: '_V_adjacency_matrix' in p.__dict__
    123113            False
    124114            sage: p._init_vertex_adjacency_matrix()
     
    137127        and initialize ourselves with the output.
    138128
    139129        TESTS::
    140        
    141             sage: p = Polyhedron(vertices = [[0,0,0],[1,0,0],[0,1,0],[0,0,1]], backend='cddr')
     130
     131            sage: p = Polyhedron(vertices = [[0,0,0],[1,0,0],[0,1,0],[0,0,1]], backend='cdd', base_ring=QQ)
    142132            sage: from sage.geometry.polyhedron.cdd_file_format import cdd_Vrepresentation
    143133            sage: s = cdd_Vrepresentation('rational', [[0,0,1],[0,1,0],[1,0,0]], [], [])
    144134            sage: p._init_from_cdd_input(s)
     
    162152        Initialize ourselves with the output from cdd.
    163153
    164154        TESTS::
    165  
     155
    166156            sage: from sage.geometry.polyhedron.cdd_file_format import cdd_Vrepresentation
    167157            sage: s = cdd_Vrepresentation('rational',[[0,0],[1,0],[0,1],[1,1]], [], [])
    168158            sage: from subprocess import Popen, PIPE
    169159            sage: cdd_proc = Popen(['cdd_both_reps_gmp', '--all'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
    170160            sage: ans, err = cdd_proc.communicate(input=s)
    171             sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,1],[1,1]], backend='cddr')
     161            sage: p = Polyhedron(vertices = [[0,0],[1,0],[0,1],[1,1]], backend='cdd', base_ring=QQ)
    172162            sage: p._init_from_cdd_output(ans)
    173163            sage: p.vertices()
    174             [[0, 0], [1, 0], [0, 1], [1, 1]]
     164            (A vertex at (0, 0), A vertex at (1, 0), A vertex at (0, 1), A vertex at (1, 1))
    175165        """
    176166        cddout=cdd_output_string.splitlines()
    177167        suppressed_vertex = False   # whether cdd suppressed the vertex in output
     168        parent = self.parent()
    178169
    179170        # nested function
    180171        def expect_in_cddout(expected_string):
     
    219210            lines = cdd_linearities()
    220211            expect_in_cddout('begin')
    221212            l = cddout.pop(0).split()
    222             assert self._ambient_dim == int(l[1])-1,  "Different ambient dimension?"
     213            assert self.ambient_dim() == int(l[1])-1,  "Different ambient dimension?"
    223214            suppressed_vertex = True
    224215            for i in range(int(l[0])):
    225216                l = cddout.pop(0).strip()
    226217                l_type = l[0]
    227218                l = l[1:]
    228219                if i in lines:
    229                     Line(self, cdd_convert(l));
     220                    parent._make_Line(self, cdd_convert(l));
    230221                elif l_type == '0':
    231                     Ray(self, cdd_convert(l));
     222                    parent._make_Ray(self, cdd_convert(l));
    232223                else:
    233                     Vertex(self, cdd_convert(l));
     224                    parent._make_Vertex(self, cdd_convert(l));
    234225                    suppressed_vertex = False
    235226            if suppressed_vertex and self.n_Vrepresentation()>0:
    236227                # cdd does not output the vertex if it is only the origin
    237                 Vertex(self, [0] * self._ambient_dim)
     228                parent._make_Vertex(self, [0] * self.ambient_dim())
    238229            self._Vrepresentation = tuple(self._Vrepresentation)
    239230            expect_in_cddout('end')
    240        
     231
    241232        if find_in_cddout('H-representation'):
    242233            self._Hrepresentation = []
    243234            equations = cdd_linearities()
    244235            expect_in_cddout('begin')
    245236            l = cddout.pop(0).split()
    246             assert self._ambient_dim == int(l[1])-1, "Different ambient dimension?"
     237            assert self.ambient_dim() == int(l[1])-1, "Different ambient dimension?"
    247238            for i in range(int(l[0])):
    248239                l = cddout.pop(0)
    249240                if i in equations:
    250                     Equation(self, cdd_convert(l));
     241                    parent._make_Equation(self, cdd_convert(l));
    251242                else:
    252                     Inequality(self, cdd_convert(l));
     243                    parent._make_Inequality(self, cdd_convert(l));
    253244            self._Hrepresentation = tuple(self._Hrepresentation)
    254245            expect_in_cddout('end')
    255246
     
    258249            l = cddout.pop(0).split()
    259250            assert l[2] == ':', "Not a line of the adjacency data?"
    260251            return [int(i)-1 for i in l[3:]]
    261        
     252
    262253        if find_in_cddout('Vertex graph'):
    263254            n = len(self._Vrepresentation);
    264255            if suppressed_vertex:
     
    285276                    self._V_adjacency_matrix[n-1,i] = 1
    286277            self._V_adjacency_matrix.set_immutable()
    287278            expect_in_cddout('end')
    288    
     279
    289280        if find_in_cddout('Facet graph'):
    290281            n = len(self._Hrepresentation);
    291282            self._H_adjacency_matrix = matrix(ZZ, n, n, 0)
     
    306297
    307298    INPUT:
    308299
    309     - ``ambient_dim`` -- integer. The dimension of the ambient space.
     300    - ``parent`` -- the parent, an instance of
     301      :class:`~sage.geometry.polyhedron.parent.Polyhedra`.
    310302
    311     - ``Vrep`` -- a list ``[vertices, rays, lines]``.
    312        
    313     - ``Hrep`` -- a list ``[ieqs, eqns]``.
     303    - ``Vrep`` -- a list ``[vertices, rays, lines]`` or ``None``.
     304
     305    - ``Hrep`` -- a list ``[ieqs, eqns]`` or ``None``.
    314306
    315307    EXAMPLES::
    316308
     309        sage: from sage.geometry.polyhedron.parent import Polyhedra
     310        sage: parent = Polyhedra(QQ, 2, backend='cdd')
    317311        sage: from sage.geometry.polyhedron.backend_cdd import Polyhedron_QQ_cdd
    318         sage: Polyhedron_QQ_cdd(2, [ [(1,0),(0,1),(0,0)], [], []], None, verbose=False)
     312        sage: Polyhedron_QQ_cdd(parent, [ [(1,0),(0,1),(0,0)], [], []], None, verbose=False)
    319313        A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
    320314    """
    321315
     
    323317
    324318    _cdd_executable = 'cdd_both_reps_gmp'
    325319
    326     def __init__(self, ambient_dim, Vrep, Hrep, **kwds):
     320    def __init__(self, parent, Vrep, Hrep, **kwds):
    327321        """
    328322        The Python constructor.
    329323
     
    331325        data.
    332326
    333327        TESTS::
    334        
    335             sage: p = Polyhedron(backend='cddr')
     328
     329            sage: p = Polyhedron(backend='cdd', base_ring=QQ)
    336330            sage: type(p)
    337             <class 'sage.geometry.polyhedron.backend_cdd.Polyhedron_QQ_cdd'>
     331            <class 'sage.geometry.polyhedron.backend_cdd.Polyhedra_QQ_cdd_with_category.element_class'>
    338332            sage: TestSuite(p).run()
    339333        """
    340         Polyhedron_cdd.__init__(self, ambient_dim, Vrep, Hrep, **kwds)
    341    
     334        Polyhedron_cdd.__init__(self, parent, Vrep, Hrep, **kwds)
     335
    342336
    343337#########################################################################
    344338class Polyhedron_RDF_cdd(Polyhedron_cdd, Polyhedron_RDF):
     
    349343
    350344    - ``ambient_dim`` -- integer. The dimension of the ambient space.
    351345
    352     - ``Vrep`` -- a list ``[vertices, rays, lines]``.
    353        
    354     - ``Hrep`` -- a list ``[ieqs, eqns]``.
     346    - ``Vrep`` -- a list ``[vertices, rays, lines]`` or ``None``.
     347
     348    - ``Hrep`` -- a list ``[ieqs, eqns]`` or ``None``.
    355349
    356350    EXAMPLES::
    357351
     352        sage: from sage.geometry.polyhedron.parent import Polyhedra
     353        sage: parent = Polyhedra(RDF, 2, backend='cdd')
    358354        sage: from sage.geometry.polyhedron.backend_cdd import Polyhedron_RDF_cdd
    359         sage: Polyhedron_RDF_cdd(2, [ [(1,0),(0,1),(0,0)], [], []], None, verbose=False)
     355        sage: Polyhedron_RDF_cdd(parent, [ [(1,0),(0,1),(0,0)], [], []], None, verbose=False)
    360356        A 2-dimensional polyhedron in RDF^2 defined as the convex hull of 3 vertices
    361357    """
    362358    _cdd_type = 'real'
    363    
     359
    364360    _cdd_executable = 'cdd_both_reps'
    365361
    366     def __init__(self, ambient_dim, Vrep, Hrep, **kwds):
     362    def __init__(self, parent, Vrep, Hrep, **kwds):
    367363        """
    368364        The Python constructor.
    369365
     
    371367        data.
    372368
    373369        TESTS::
    374        
    375             sage: p = Polyhedron(backend='cddf')
     370
     371            sage: p = Polyhedron(backend='cdd', base_ring=RDF)
    376372            sage: type(p)
    377             <class 'sage.geometry.polyhedron.backend_cdd.Polyhedron_RDF_cdd'>
     373            <class 'sage.geometry.polyhedron.backend_cdd.Polyhedra_RDF_cdd_with_category.element_class'>
    378374            sage: TestSuite(p).run()
    379375        """
    380         Polyhedron_cdd.__init__(self, ambient_dim, Vrep, Hrep, **kwds)
    381    
     376        Polyhedron_cdd.__init__(self, parent, Vrep, Hrep, **kwds)
     377
  • sage/geometry/polyhedron/backend_ppl.py

    diff --git a/sage/geometry/polyhedron/backend_ppl.py b/sage/geometry/polyhedron/backend_ppl.py
    a b  
    33"""
    44
    55from sage.rings.all import ZZ, QQ
    6 from sage.rings.arith import lcm
     6from sage.rings.integer import LCM_list
    77from sage.misc.functional import denominator
    88from sage.matrix.constructor import matrix
    99from sage.libs.ppl import (
     
    1111    Variable, Linear_Expression,
    1212    line, ray, point )
    1313
     14from base import Polyhedron_base
    1415from base_QQ import Polyhedron_QQ
    15 from representation import (
    16     PolyhedronRepresentation,
    17     Hrepresentation,
    18     Inequality, Equation,
    19     Vrepresentation,
    20     Vertex, Ray, Line )
    21 
     16from base_ZZ import Polyhedron_ZZ
    2217
    2318
    2419#########################################################################
    25 class Polyhedron_QQ_ppl(Polyhedron_QQ):
     20class Polyhedron_ppl(Polyhedron_base):
    2621    """
    27     Polyhedra over `\QQ` with ppl
     22    Polyhedra with ppl
    2823
    2924    INPUT:
    3025
    31     - ``ambient_dim`` -- integer. The dimension of the ambient space.
     26    - ``Vrep`` -- a list ``[vertices, rays, lines]`` or ``None``.
    3227
    33     - ``Vrep`` -- a list ``[vertices, rays, lines]``.
    34        
    35     - ``Hrep`` -- a list ``[ieqs, eqns]``.
     28    - ``Hrep`` -- a list ``[ieqs, eqns]`` or ``None``.
    3629
    3730    EXAMPLES::
    3831
     
    4033        sage: TestSuite(p).run()
    4134    """
    4235
    43     def _init_from_Vrepresentation(self, ambient_dim, vertices, rays, lines, minimize=True):
     36    def _init_from_Vrepresentation(self, vertices, rays, lines, minimize=True):
    4437        """
    4538        Construct polyhedron from V-representation data.
    4639
    4740        INPUT:
    4841
    49         - ``ambient_dim`` -- integer. The dimension of the ambient space.
    50        
    5142        - ``vertices`` -- list of point. Each point can be specified
    5243           as any iterable container of
    5344           :meth:`~sage.geometry.polyhedron.base.base_ring` elements.
    54        
     45
    5546        - ``rays`` -- list of rays. Each ray can be specified as any
    5647          iterable container of
    5748          :meth:`~sage.geometry.polyhedron.base.base_ring` elements.
    58        
     49
    5950        - ``lines`` -- list of lines. Each line can be specified as
    6051          any iterable container of
    6152          :meth:`~sage.geometry.polyhedron.base.base_ring` elements.
     
    6354        EXAMPLES::
    6455
    6556            sage: p = Polyhedron(backend='ppl')
    66             sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_QQ_ppl
    67             sage: Polyhedron_QQ_ppl._init_from_Vrepresentation(p, 2, [], [], [])
     57            sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_ppl
     58            sage: Polyhedron_ppl._init_from_Vrepresentation(p, [], [], [])
    6859        """
    6960        gs = Generator_System()
    7061        if vertices is None: vertices = []
    7162        for v in vertices:
    72             d = lcm([denominator(v_i) for v_i in v])
    73             dv = [ ZZ(d*v_i) for v_i in v ]
    74             gs.insert(point(Linear_Expression(dv, 0), d))
     63            d = LCM_list([denominator(v_i) for v_i in v])
     64            if d.is_one():
     65                gs.insert(point(Linear_Expression(v, 0)))
     66            else:
     67                dv = [ d*v_i for v_i in v ]
     68                gs.insert(point(Linear_Expression(dv, 0), d))
    7569        if rays is None: rays = []
    7670        for r in rays:
    77             d = lcm([denominator(r_i) for r_i in r])
    78             dr = [ ZZ(d*r_i) for r_i in r ]
    79             gs.insert(ray(Linear_Expression(dr, 0)))
     71            d = LCM_list([denominator(r_i) for r_i in r])
     72            if d.is_one():
     73                gs.insert(ray(Linear_Expression(r, 0)))
     74            else:
     75                dr = [ d*r_i for r_i in r ]
     76                gs.insert(ray(Linear_Expression(dr, 0)))
    8077        if lines is None: lines = []
    8178        for l in lines:
    82             d = lcm([denominator(l_i) for l_i in l])
    83             dl = [ ZZ(d*l_i) for l_i in l ]
    84             gs.insert(line(Linear_Expression(dl, 0)))
    85         self._ppl_polyhedron = C_Polyhedron(gs)
     79            d = LCM_list([denominator(l_i) for l_i in l])
     80            if d.is_one():
     81                gs.insert(line(Linear_Expression(l, 0)))
     82            else:
     83                dl = [ d*l_i for l_i in l ]
     84                gs.insert(line(Linear_Expression(dl, 0)))
     85        if gs.empty():
     86            self._ppl_polyhedron = C_Polyhedron(self.ambient_dim(), 'empty')
     87        else:
     88            self._ppl_polyhedron = C_Polyhedron(gs)
    8689        self._init_Vrepresentation_from_ppl(minimize)
    8790        self._init_Hrepresentation_from_ppl(minimize)
    8891
    89 
    90     def _init_from_Hrepresentation(self, ambient_dim, ieqs, eqns, minimize=True):
     92    def _init_from_Hrepresentation(self, ieqs, eqns, minimize=True):
    9193        """
    9294        Construct polyhedron from H-representation data.
    9395
    9496        INPUT:
    9597
    96         - ``ambient_dim`` -- integer. The dimension of the ambient space.
    97        
    9898        - ``ieqs`` -- list of inequalities. Each line can be specified
    9999          as any iterable container of
    100100          :meth:`~sage.geometry.polyhedron.base.base_ring` elements.
     
    106106        EXAMPLES::
    107107
    108108            sage: p = Polyhedron(backend='ppl')
    109             sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_QQ_ppl
    110             sage: Polyhedron_QQ_ppl._init_from_Hrepresentation(p, 2, [], [])
     109            sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_ppl
     110            sage: Polyhedron_ppl._init_from_Hrepresentation(p, [], [])
    111111        """
    112112        cs = Constraint_System()
    113113        if ieqs is None: ieqs = []
    114114        for ieq in ieqs:
    115             d = lcm([denominator(ieq_i) for ieq_i in ieq])
     115            d = LCM_list([denominator(ieq_i) for ieq_i in ieq])
    116116            dieq = [ ZZ(d*ieq_i) for ieq_i in ieq ]
    117117            b = dieq[0]
    118118            A = dieq[1:]
    119119            cs.insert(Linear_Expression(A, b) >= 0)
    120120        if eqns is None: eqns = []
    121121        for eqn in eqns:
    122             d = lcm([denominator(eqn_i) for eqn_i in eqn])
     122            d = LCM_list([denominator(eqn_i) for eqn_i in eqn])
    123123            deqn = [ ZZ(d*eqn_i) for eqn_i in eqn ]
    124124            b = deqn[0]
    125125            A = deqn[1:]
    126126            cs.insert(Linear_Expression(A, b) == 0)
    127         self._ppl_polyhedron = C_Polyhedron(cs)
     127        if cs.empty():
     128            self._ppl_polyhedron = C_Polyhedron(self.ambient_dim(), 'universe')
     129        else:
     130            self._ppl_polyhedron = C_Polyhedron(cs)
    128131        self._init_Vrepresentation_from_ppl(minimize)
    129132        self._init_Hrepresentation_from_ppl(minimize)
    130133
    131        
    132134    def _init_Vrepresentation_from_ppl(self, minimize):
    133135        """
    134136        Create the Vrepresentation objects from the ppl polyhedron.
    135        
     137
    136138        EXAMPLES::
    137139
    138140            sage: p = Polyhedron(vertices=[(0,1/2),(2,0),(4,5/6)],
     
    150152        """
    151153        self._Vrepresentation = []
    152154        gs = self._ppl_polyhedron.minimized_generators()
     155        parent = self.parent()
    153156        for g in gs:
    154157            if g.is_point():
    155158                d = g.divisor()
    156                 Vertex(self, [x/d for x in g.coefficients()])
     159                if d.is_one():
     160                    parent._make_Vertex(self, g.coefficients())
     161                else:
     162                    parent._make_Vertex(self, [x/d for x in g.coefficients()])
    157163            elif g.is_ray():
    158                 Ray(self, g.coefficients())
     164                parent._make_Ray(self, g.coefficients())
    159165            elif g.is_line():
    160                 Line(self, g.coefficients())
     166                parent._make_Line(self, g.coefficients())
    161167            else:
    162168                assert False
    163169        self._Vrepresentation = tuple(self._Vrepresentation)
    164        
    165170
    166171    def _init_Hrepresentation_from_ppl(self, minimize):
    167172        """
    168         Create the Vrepresentation objects from the ppl polyhedron.
    169        
     173        Create the Hrepresentation objects from the ppl polyhedron.
     174
    170175        EXAMPLES::
    171176
    172177            sage: p = Polyhedron(vertices=[(0,1/2),(2,0),(4,5/6)],
     
    184189        """
    185190        self._Hrepresentation = []
    186191        cs = self._ppl_polyhedron.minimized_constraints()
     192        parent = self.parent()
    187193        for c in cs:
    188194            if c.is_inequality():
    189                 Inequality(self, (c.inhomogeneous_term(),) + c.coefficients())
     195                parent._make_Inequality(self, (c.inhomogeneous_term(),) + c.coefficients())
    190196            elif c.is_equality():
    191                 Equation(self, (c.inhomogeneous_term(),) + c.coefficients())
     197                parent._make_Equation(self, (c.inhomogeneous_term(),) + c.coefficients())
    192198        self._Hrepresentation = tuple(self._Hrepresentation)
    193        
    194199
    195     def _init_empty_polyhedron(self, ambient_dim):
     200    def _init_empty_polyhedron(self):
    196201        """
    197202        Initializes an empty polyhedron.
    198203
    199         INPUT:
    200 
    201         - ``ambient_dim`` -- integer. The dimension of the ambient space.
    202 
    203204        TESTS::
    204205
    205206            sage: empty = Polyhedron(backend='ppl'); empty
    206             The empty polyhedron in QQ^0
     207            The empty polyhedron in ZZ^0
    207208            sage: empty.Vrepresentation()
    208209            ()
    209210            sage: empty.Hrepresentation()
    210211            (An equation -1 == 0,)
    211212            sage: Polyhedron(vertices = [], backend='ppl')
    212             The empty polyhedron in QQ^0
    213             sage: Polyhedron(backend='ppl')._init_empty_polyhedron(0)
     213            The empty polyhedron in ZZ^0
     214            sage: Polyhedron(backend='ppl')._init_empty_polyhedron()
    214215        """
    215         super(Polyhedron_QQ_ppl, self)._init_empty_polyhedron(ambient_dim)
    216         self._ppl_polyhedron = C_Polyhedron(ambient_dim, 'empty')
     216        super(Polyhedron_ppl, self)._init_empty_polyhedron()
     217        self._ppl_polyhedron = C_Polyhedron(self.ambient_dim(), 'empty')
    217218
    218219
     220
     221
     222#########################################################################
     223class Polyhedron_QQ_ppl(Polyhedron_ppl, Polyhedron_QQ):
     224    """
     225    Polyhedra over `\QQ` with ppl
     226
     227    INPUT:
     228
     229    - ``Vrep`` -- a list ``[vertices, rays, lines]`` or ``None``.
     230
     231    - ``Hrep`` -- a list ``[ieqs, eqns]`` or ``None``.
     232
     233    EXAMPLES::
     234
     235        sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)], rays=[(1,1)], lines=[],
     236        ...                  backend='ppl', base_ring=QQ)
     237        sage: TestSuite(p).run(skip='_test_pickling')
     238    """
     239    pass
     240
     241
     242#########################################################################
     243class Polyhedron_ZZ_ppl(Polyhedron_ppl, Polyhedron_ZZ):
     244    """
     245    Polyhedra over `\ZZ` with ppl
     246
     247    INPUT:
     248
     249    - ``Vrep`` -- a list ``[vertices, rays, lines]`` or ``None``.
     250
     251    - ``Hrep`` -- a list ``[ieqs, eqns]`` or ``None``.
     252
     253    EXAMPLES::
     254
     255        sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)], rays=[(1,1)], lines=[])
     256        ...                  backend='ppl', base_ring=ZZ)
     257        sage: TestSuite(p).run(skip='_test_pickling')
     258    """
     259    pass
  • sage/geometry/polyhedron/base.py

    diff --git a/sage/geometry/polyhedron/base.py b/sage/geometry/polyhedron/base.py
    a b  
    1313########################################################################
    1414
    1515
    16 from sage.structure.sage_object import SageObject
     16from sage.structure.element import Element, coerce_binop, is_Vector
    1717
    1818from sage.misc.all import union, cached_method, prod
    1919from sage.misc.package import is_package_installed
     
    3333from sage.groups.perm_gps.permgroup_named import AlternatingGroup
    3434
    3535from constructor import Polyhedron
    36 from representation import (
    37     PolyhedronRepresentation,
    38     Hrepresentation,
    39     Inequality, Equation,
    40     Vrepresentation,
    41     Vertex, Ray, Line )
    4236
    4337
    4438#########################################################################
     
    5549#
    5650#  * You can of course also override any other method for which you
    5751#    have a faster implementation.
     52#########################################################################
    5853
    5954
    6055#########################################################################
     
    8378
    8479
    8580#########################################################################
    86 class Polyhedron_base(SageObject):
     81class Polyhedron_base(Element):
    8782    """
    8883    Base class for Polyhedron objects
    8984
    9085    INPUT:
    9186
    92     - ``ambient_dim`` -- integer. The dimension of the ambient space.
     87    - ``parent`` -- the parent, an instance of
     88      :class:`~sage.geometry.polyhedron.parent.Polyhedra`.
    9389
    9490    - ``Vrep`` -- a list `[vertices, rays, lines]`` or ``None``. The
    9591      V-representation of the polyhedron. If ``None``, the polyhedron
    9692      is determined by the H-representation.
    97        
     93
    9894    - ``Hrep`` -- a list `[ieqs, eqns]`` or ``None``. The
    9995      H-representation of the polyhedron. If ``None``, the polyhedron
    10096      is determined by the V-representation.
     
    107103        sage: TestSuite(p).run()
    108104    """
    109105
    110     def __init__(self, ambient_dim, Vrep, Hrep, **kwds):
     106    def __init__(self, parent, Vrep, Hrep, **kwds):
    111107        """
    112108        Initializes the polyhedron.
    113109
     
    118114
    119115            sage: p = Polyhedron()    # indirect doctests
    120116        """
    121         self._ambient_dim = ambient_dim
     117        Element.__init__(self, parent=parent)
    122118        if Vrep is not None:
    123119            vertices, rays, lines = Vrep
    124             if len(vertices)==0:
    125                 vertices = [[0] * ambient_dim]
    126             self._init_from_Vrepresentation(ambient_dim, vertices, rays, lines, **kwds)
     120            self._init_from_Vrepresentation(vertices, rays, lines, **kwds)
    127121        elif Hrep is not None:
    128122            ieqs, eqns = Hrep
    129             self._init_from_Hrepresentation(ambient_dim, ieqs, eqns, **kwds)
     123            self._init_from_Hrepresentation(ieqs, eqns, **kwds)
    130124        else:
    131             self._init_empty_polyhedron(ambient_dim)
    132 
    133 
    134     def _init_from_Vrepresentation(self, ambient_dim, vertices, rays, lines, **kwds):
     125            self._init_empty_polyhedron()
     126
     127
     128    def _init_from_Vrepresentation(self, vertices, rays, lines, **kwds):
    135129        """
    136130        Construct polyhedron from V-representation data.
    137131
    138132        INPUT:
    139133
    140         - ``ambient_dim`` -- integer. The dimension of the ambient space.
    141        
    142134        - ``vertices`` -- list of point. Each point can be specified
    143135           as any iterable container of
    144136           :meth:`~sage.geometry.polyhedron.base.base_ring` elements.
    145        
     137
    146138        - ``rays`` -- list of rays. Each ray can be specified as any
    147139          iterable container of
    148140          :meth:`~sage.geometry.polyhedron.base.base_ring` elements.
    149        
     141
    150142        - ``lines`` -- list of lines. Each line can be specified as
    151143          any iterable container of
    152144          :meth:`~sage.geometry.polyhedron.base.base_ring` elements.
     
    155147
    156148            sage: p = Polyhedron()
    157149            sage: from sage.geometry.polyhedron.base import Polyhedron_base
    158             sage: Polyhedron_base._init_from_Vrepresentation(p, 2, [], [], [])
     150            sage: Polyhedron_base._init_from_Vrepresentation(p, [], [], [])
    159151            Traceback (most recent call last):
    160152            ...
    161153            NotImplementedError: A derived class must implement this method.
     
    163155        raise NotImplementedError('A derived class must implement this method.')
    164156
    165157
    166     def _init_from_Hrepresentation(self, ambient_dim, ieqs, eqns, **kwds):
     158    def _init_from_Hrepresentation(self, ieqs, eqns, **kwds):
    167159        """
    168160        Construct polyhedron from H-representation data.
    169161
    170162        INPUT:
    171163
    172         - ``ambient_dim`` -- integer. The dimension of the ambient space.
    173        
    174164        - ``ieqs`` -- list of inequalities. Each line can be specified
    175165          as any iterable container of
    176166          :meth:`~sage.geometry.polyhedron.base.base_ring` elements.
     
    183173
    184174            sage: p = Polyhedron()
    185175            sage: from sage.geometry.polyhedron.base import Polyhedron_base
    186             sage: Polyhedron_base._init_from_Hrepresentation(p, 2, [], [])
     176            sage: Polyhedron_base._init_from_Hrepresentation(p, [], [])
    187177            Traceback (most recent call last):
    188178            ...
    189179            NotImplementedError: A derived class must implement this method.
    190180        """
    191181        raise NotImplementedError('A derived class must implement this method.')
    192182
    193 
    194     def _init_empty_polyhedron(self, ambient_dim):
     183    def _init_empty_polyhedron(self):
    195184        """
    196185        Initializes an empty polyhedron.
    197186
    198         INPUT:
    199 
    200         - ``ambient_dim`` -- integer. The dimension of the ambient space.
    201 
    202187        TESTS::
    203188
    204189            sage: empty = Polyhedron(); empty
    205             The empty polyhedron in QQ^0
     190            The empty polyhedron in ZZ^0
    206191            sage: empty.Vrepresentation()
    207192            ()
    208193            sage: empty.Hrepresentation()
    209194            (An equation -1 == 0,)
    210195            sage: Polyhedron(vertices = [])
    211             The empty polyhedron in QQ^0
    212             sage: Polyhedron()._init_empty_polyhedron(0)
     196            The empty polyhedron in ZZ^0
     197            sage: Polyhedron(vertices = [])._init_empty_polyhedron()
     198            sage: from sage.geometry.polyhedron.parent import Polyhedra
     199            sage: Polyhedra(QQ,7)()
     200            A 0-dimensional polyhedron in QQ^7 defined as the convex hull of 1 vertex
    213201        """
    214202        self._Vrepresentation = []
    215203        self._Hrepresentation = []
    216         Equation(self, [-1] + [0]*ambient_dim);
     204        self.parent()._make_Equation(self, [-1] + [0]*self.ambient_dim());
    217205        self._Vrepresentation = tuple(self._Vrepresentation)
    218206        self._Hrepresentation = tuple(self._Hrepresentation)
    219207
    220         self._V_adjacency_matrix = matrix(ZZ, 0, 0, 0)
    221         self._V_adjacency_matrix.set_immutable()
    222 
    223         self._H_adjacency_matrix = matrix(ZZ, 1, 1, 0)
    224         self._H_adjacency_matrix.set_immutable()
    225 
    226 
    227     def _init_facet_adjacency_matrix(self):
     208        V_matrix = matrix(ZZ, 0, 0, 0)
     209        V_matrix.set_immutable()
     210        self.vertex_adjacency_matrix.set_cache(V_matrix)
     211
     212        H_matrix = matrix(ZZ, 1, 1, 0)
     213        H_matrix.set_immutable()
     214        self.facet_adjacency_matrix.set_cache(H_matrix)
     215
     216    def _facet_adjacency_matrix(self):
    228217        """
    229218        Compute the facet adjacency matrix in case it has not been
    230219        computed during initialization.
    231220
    232221        EXAMPLES::
    233        
     222
    234223            sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)])
    235             sage: '_H_adjacency_matrix' in p.__dict__
    236             False
    237             sage: p._init_facet_adjacency_matrix()
    238             sage: p._H_adjacency_matrix
     224            sage: p._facet_adjacency_matrix()
    239225            [0 1 1]
    240226            [1 0 1]
    241227            [1 1 0]
     
    256242            Hrep = face.element.ambient_Hrepresentation()
    257243            if len(Hrep) == 2:
    258244                set_adjacent(Hrep[0], Hrep[1])
    259 
    260         self._H_adjacency_matrix = M
    261 
    262 
    263     def _init_vertex_adjacency_matrix(self):
     245        return M
     246
     247    def _vertex_adjacency_matrix(self):
    264248        """
    265249        Compute the vertex adjacency matrix in case it has not been
    266250        computed during initialization.
    267251
    268252        EXAMPLES::
    269        
     253
    270254            sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)])
    271             sage: '_V_adjacency_matrix' in p.__dict__
    272             False
    273             sage: p._init_vertex_adjacency_matrix()
    274             sage: p._V_adjacency_matrix
     255            sage: p._vertex_adjacency_matrix()
    275256            [0 1 1]
    276257            [1 0 1]
    277258            [1 1 0]
     
    299280        for r in self.ray_generator():
    300281            for vrep in self.Vrep_generator():
    301282                set_adjacent(r, vrep)
    302                
    303         self._V_adjacency_matrix = M
    304 
    305 
    306     def __lt__(self, other):
     283        return M
     284
     285    def delete(self):
    307286        """
    308         Test whether ``self`` is a strict sub-polyhedron of ``other``.
     287        Delete this polyhedron.
     288
     289        This speeds up creation of new polyhedra by reusing
     290        objects. After recycling a polyhedron object, it is not in a
     291        consistent state any more and neither the polyhedron nor its
     292        H/V-representation objects may be used any more.
     293
     294        .. seealso:: :meth:`~sage.geometry.polyhedron.parent.Polyhedra_base.recycle`
     295 
     296        EXAMPLES::
     297 
     298            sage: p = Polyhedron([(0,0),(1,0),(0,1)])
     299            sage: p.delete()
     300
     301            sage: vertices = [(0,0,0,0),(1,0,0,0),(0,1,0,0),(1,1,0,0),(0,0,1,0),(0,0,0,1)]
     302            sage: def loop_polyhedra():
     303            ...       for i in range(0,100):
     304            ...           p = Polyhedron(vertices)
     305
     306            sage: timeit('loop_polyhedra()')                   # not tested - random
     307            5 loops, best of 3: 79.5 ms per loop
     308
     309            sage: def loop_polyhedra_with_recycling():
     310            ...       for i in range(0,100):
     311            ...           p = Polyhedron(vertices)
     312            ...           p.delete()
     313
     314            sage: timeit('loop_polyhedra_with_recycling()')    # not tested - random
     315            5 loops, best of 3: 57.3 ms per loop
     316        """
     317        self.parent().recycle(self)
     318
     319    def base_extend(self, base_ring, backend=None):
     320        """
     321        Return a new polyhedron over a larger field.
    309322
    310323        INPUT:
    311324
    312         - ``other`` -- a :class:`Polyhedron`.
     325        - ``base_ring`` -- the new base ring.
     326
     327        - ``backend`` -- the new backend, see
     328          :func:`~sage.geometry.polyhedron.constructor.Polyhedron`.
    313329
    314330        OUTPUT:
    315331
    316         Boolean.
     332        The same polyhedron, but over a larger base ring.
     333
     334        EXAMPLES::
     335
     336            sage: P = Polyhedron(vertices=[(1,0), (0,1)], rays=[(1,1)], base_ring=ZZ);  P
     337            A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices and 1 ray
     338            sage: P.base_extend(QQ)
     339            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 1 ray
     340            sage: P.base_extend(QQ) == P
     341            True
     342        """
     343        new_parent = self.parent().base_extend(base_ring, backend)
     344        return new_parent(self)
     345
     346    def __cmp__(self, other):
     347        """
     348        Compare ``self`` and ``other``.
     349
     350        INPUT:
     351
     352        - ``other`` -- anything.
     353 
     354        OUTPUT:
     355
     356        `-1, 0, +1` depending on how ``self`` and ``other``
     357        compare. If ``other`` is a polyhedron, then the comparison
     358        operator "less or equal than" means "is contained in", and
     359        "less than" means "is strictly contained in".
    317360
    318361        EXAMPLES::
    319362
    320363            sage: P = Polyhedron(vertices=[(1,0), (0,1)], rays=[(1,1)])
    321364            sage: Q = Polyhedron(vertices=[(1,0), (0,1)])
    322             sage: P < Q   # indirect doctest
     365            sage: cmp(P,Q)
     366            1
     367            sage: cmp(Q,P)
     368            -1
     369            sage: cmp(P,P)
     370            0
     371            sage: abs(cmp(P, 'anything'))
     372            1
     373
     374       The polytope ``Q`` is contained in ``P``::
     375
     376            sage: P > Q
     377            True
     378            sage: P < Q
    323379            False
    324             sage: P < P   # indirect doctest
     380            sage: P == Q
    325381            False
    326             sage: Q < P   # indirect doctest
    327             True
    328         """
    329         return self._is_subpolyhedron(other) and not other._is_subpolyhedron(self)
    330 
    331 
    332     def __le__(self, other):
    333         """
    334         Test whether ``self`` is a (not necessarily strict)
    335         sub-polyhedron of ``other``.
    336 
    337         INPUT:
    338 
    339         - ``other`` -- a :class:`Polyhedron`.
    340 
    341         OUTPUT:
    342 
    343         Boolean.
    344 
    345         EXAMPLES::
    346 
    347             sage: P = Polyhedron(vertices=[(1,0), (0,1)], rays=[(1,1)])
    348             sage: Q = Polyhedron(vertices=[(1,0), (0,1)])
    349             sage: P <= Q   # indirect doctest
    350             False
    351             sage: P <= P   # indirect doctest
    352             True
    353             sage: Q <= P   # indirect doctest
    354             True
    355         """
    356         return self._is_subpolyhedron(other)
    357        
    358 
    359     def __eq__(self, other):
    360         """
    361         Test whether ``self`` is a strict sub-polyhedron of ``other``.
    362 
    363         INPUT:
    364 
    365         - ``other`` -- a :class:`Polyhedron`.
    366 
    367         OUTPUT:
    368 
    369         Boolean.
    370 
    371         EXAMPLES::
    372 
    373             sage: P = Polyhedron(vertices=[(1,0), (0,1)], rays=[(1,1)])
    374             sage: Q = Polyhedron(vertices=[(1,0), (0,1)])
    375             sage: P == Q   # indirect doctest
    376             False
    377             sage: P == P   # indirect doctest
    378             True
    379             sage: Q == P   # indirect doctest
    380             False
    381         """
    382         return self._is_subpolyhedron(other) and other._is_subpolyhedron(self)
    383 
    384 
    385     def __ne__(self, other):
    386         """
    387         Test whether ``self`` is not equal to ``other``.
    388 
    389         INPUT:
    390 
    391         - ``other`` -- a :class:`Polyhedron`.
    392 
    393         OUTPUT:
    394 
    395         Boolean.
    396 
    397         EXAMPLES::
    398 
    399             sage: P = Polyhedron(vertices=[(1,0), (0,1)], rays=[(1,1)])
    400             sage: Q = Polyhedron(vertices=[(1,0), (0,1)])
    401             sage: P != Q   # indirect doctest
    402             True
    403             sage: P != P   # indirect doctest
    404             False
    405             sage: Q != P   # indirect doctest
    406             True
    407         """
    408         return not self.__eq__(other)
    409 
    410 
    411     def __gt__(self, other):
    412         """
    413         Test whether ``self`` is a strict super-polyhedron of ``other``.
    414 
    415         INPUT:
    416 
    417         - ``other`` -- a :class:`Polyhedron`.
    418 
    419         OUTPUT:
    420 
    421         Boolean.
    422 
    423         EXAMPLES::
    424 
    425             sage: P = Polyhedron(vertices=[(1,0), (0,1)], rays=[(1,1)])
    426             sage: Q = Polyhedron(vertices=[(1,0), (0,1)])
    427             sage: P > Q   # indirect doctest
    428             True
    429             sage: P > P   # indirect doctest
    430             False
    431             sage: Q > P   # indirect doctest
    432             False
    433         """
    434         return other._is_subpolyhedron(self) and not self._is_subpolyhedron(other)
    435 
    436 
    437     def __ge__(self, other):
    438         """
    439         Test whether ``self`` is a (not necessarily strict)
    440         super-polyhedron of ``other``.
    441 
    442         INPUT:
    443 
    444         - ``other`` -- a :class:`Polyhedron`.
    445 
    446         OUTPUT:
    447 
    448         Boolean.
    449 
    450         EXAMPLES::
    451 
    452             sage: P = Polyhedron(vertices=[(1,0), (0,1)], rays=[(1,1)])
    453             sage: Q = Polyhedron(vertices=[(1,0), (0,1)])
    454             sage: P >= Q   # indirect doctest
    455             True
    456             sage: P >= P   # indirect doctest
    457             True
    458             sage: Q >= P   # indirect doctest
    459             False
    460         """
    461         return other._is_subpolyhedron(self)
    462 
    463 
     382           
     383        TESTS::
     384
     385            sage: abs(cmp(P, 'string'))
     386            1
     387         """
     388        if not isinstance(other, Polyhedron_base):
     389            return -1
     390        if self._Vrepresentation is None or other._Vrepresentation is None:
     391            return -1   # make sure deleted polyhedra are not used in cache
     392        c = cmp(self.ambient_dim(), other.ambient_dim())
     393        if c != 0: return c
     394        c0 = self._is_subpolyhedron(other)
     395        c1 = other._is_subpolyhedron(self)
     396        if c0 and c1:
     397            return 0
     398        if c0:
     399            return -1
     400        else:
     401            return +1
     402
     403    @coerce_binop
    464404    def _is_subpolyhedron(self, other):
    465405        """
    466406        Test whether ``self`` is a (not necessarily strict)
     
    483423            sage: Q._is_subpolyhedron(P)
    484424            True
    485425        """
    486         if not is_Polyhedron(other):
    487             raise ValueError('Can only compare Polyhedron objects.')
    488426        return all( other_H.contains(self_V)
    489427                    for other_H, self_V in
    490428                    CartesianProduct(other.Hrep_generator(), self.Vrep_generator()) )
    491        
    492429
    493430    def plot(self, **kwds):
    494431        """
    495432        Return a graphical representation.
    496433
    497434        INPUT:
    498        
     435
    499436        - ``**kwds`` -- optional keyword parameters.
    500437
    501438        See :func:`render_2d`, :func:`render_3d`, :func:`render_4d`
     
    519456        raise NotImplementedError('Plotting of '+str(self.ambient_dim())+
    520457                                  '-dimensional polyhedra not implemented')
    521458
    522 
    523459    show = plot
    524460
    525 
    526461    def _repr_(self):
    527462        """
    528463        Return a description of the polyhedron.
     
    531466
    532467            sage: poly_test = Polyhedron(vertices = [[1,2,3,4],[2,1,3,4],[4,3,2,1]])
    533468            sage: poly_test._repr_()
    534             'A 2-dimensional polyhedron in QQ^4 defined as the convex hull of 3 vertices'
     469            'A 2-dimensional polyhedron in ZZ^4 defined as the convex hull of 3 vertices'
    535470            sage: grammar_test = Polyhedron(vertices = [[1,1,1,1,1,1]])
    536471            sage: grammar_test._repr_()
    537             'A 0-dimensional polyhedron in QQ^6 defined as the convex hull of 1 vertex'
     472            'A 0-dimensional polyhedron in ZZ^6 defined as the convex hull of 1 vertex'
    538473        """
    539474        desc = ''
    540475        if self.n_vertices()==0:
     
    542477        else:
    543478            desc += 'A ' + repr(self.dim()) + '-dimensional polyhedron'
    544479        desc += ' in '
    545         if self.field()==QQ: desc += 'QQ'
    546         else:                desc += 'RDF'
     480        if   self.base_ring() is QQ:  desc += 'QQ'
     481        elif self.base_ring() is ZZ:  desc += 'ZZ'
     482        elif self.base_ring() is RDF: desc += 'RDF'
     483        else: assert False
    547484        desc += '^' + repr(self.ambient_dim())
    548485
    549486        if self.n_vertices()>0:
     
    551488            desc += repr(self.n_vertices())
    552489            if self.n_vertices()==1: desc += ' vertex'
    553490            else:                    desc += ' vertices'
    554            
     491
    555492            if self.n_rays()>0:
    556493                if self.n_lines()>0: desc += ", "
    557494                else:                desc += " and "
    558495                desc += repr(self.n_rays())
    559496                if self.n_rays()==1: desc += ' ray'
    560497                else:                desc += ' rays'
    561                
     498
    562499            if self.n_lines()>0:
    563500                if self.n_rays()>0: desc += ", "
    564501                else:               desc += " and "
     
    568505
    569506        return desc
    570507
    571 
    572508    def cdd_Hrepresentation(self):
    573509        """
    574510        Write the inequalities/equations data of the polyhedron in
     
    596532        try:
    597533            cdd_type = self._cdd_type
    598534        except AttributeError:
    599             ring_to_cdd = { QQ:'rational', RDF:'real' }
    600             cdd_type = ring_to_cdd[self.base_ring()]
     535            if self.base_ring() is ZZ or self.base_ring() is QQ:
     536                cdd_type = 'rational'
     537            elif self.base_ring() is RDF:
     538                cdd_type = 'real'
     539            else:
     540                raise TypeError('The base ring must be ZZ, QQ, or RDF')
    601541        return cdd_Hrepresentation(cdd_type,
    602542                                   list(self.inequality_generator()),
    603543                                   list(self.equation_generator()) )
    604544
    605 
    606545    def cdd_Vrepresentation(self):
    607546        """
    608547        Write the vertices/rays/lines data of the polyhedron in cdd's
    609548        V-representation format.
    610        
     549
    611550        OUTPUT:
    612551
    613552        A string. If you save the output to filename.ext then you can
     
    630569        try:
    631570            cdd_type = self._cdd_type
    632571        except AttributeError:
    633             ring_to_cdd = { QQ:'rational', RDF:'real' }
    634             cdd_type = ring_to_cdd[self.base_ring()]
     572            if self.base_ring() is ZZ or self.base_ring() is QQ:
     573                cdd_type = 'rational'
     574            elif self.base_ring() is RDF:
     575                cdd_type = 'real'
     576            else:
     577                raise TypeError('The base ring must be ZZ, QQ, or RDF')
    635578        return cdd_Vrepresentation(cdd_type,
    636579                                   list(self.vertex_generator()),
    637580                                   list(self.ray_generator()),
    638581                                   list(self.line_generator()) )
    639582
    640 
     583    @cached_method
    641584    def n_equations(self):
    642585        """
    643586        Return the number of equations. The representation will
     
    650593            sage: p.n_equations()
    651594            1
    652595        """
    653         try:
    654             return self._n_equations
    655         except AttributeError:
    656             self._n_equations = len(self.equations())
    657             return self._n_equations
    658 
    659 
     596        return len(self.equations())
     597
     598    @cached_method
    660599    def n_inequalities(self):
    661600        """
    662601        Return the number of inequalities. The representation will
     
    668607            sage: p = Polyhedron(vertices = [[1,0,0],[0,1,0],[0,0,1]])
    669608            sage: p.n_inequalities()
    670609            3
    671         """
    672         try:
    673             return self._n_inequalities
    674         except AttributeError:
    675             self._n_inequalities = 0
    676             for i in self.inequalities(): self._n_inequalities += 1
    677             return self._n_inequalities
    678 
    679 
    680     def n_facets(self):
    681         """
    682         Return the number of facets in the polyhedron.  This is the
    683         same as the n_inequalities function.
    684 
    685         EXAMPLES::
    686610
    687611            sage: p = Polyhedron(vertices = [[t,t^2,t^3] for t in range(6)])
    688612            sage: p.n_facets()
    689613            8
    690614        """
    691         return self.n_inequalities()
    692 
    693 
     615        return len(self.inequalities())
     616
     617    n_facets = n_inequalities
     618
     619    @cached_method
    694620    def n_vertices(self):
    695621        """
    696622        Return the number of vertices. The representation will
     
    702628            sage: p.n_vertices()
    703629            2
    704630        """
    705         try:
    706             return self._n_vertices
    707         except AttributeError:
    708             self._n_vertices = 0
    709             for v in self.vertex_generator(): self._n_vertices += 1
    710             return self._n_vertices
    711 
    712 
     631        return len(self.vertices())
     632
     633    @cached_method
    713634    def n_rays(self):
    714635        """
    715636        Return the number of rays. The representation will
     
    721642            sage: p.n_rays()
    722643            1
    723644        """
    724         try:
    725             return self._n_rays
    726         except AttributeError:
    727             self._n_rays = 0
    728             for r in self.rays(): self._n_rays += 1
    729             return self._n_rays
    730 
    731 
     645        return len(self.rays())
     646
     647    @cached_method
    732648    def n_lines(self):
    733649        """
    734650        Return the number of lines. The representation will
     
    740656            sage: p.n_lines()
    741657            1
    742658        """
    743         try:
    744             return self._n_lines
    745         except AttributeError:
    746             self._n_lines = len(self.lines())
    747             return self._n_lines
    748 
     659        return len(self.lines())
    749660
    750661    def Hrepresentation(self, index=None):
    751662        """
     
    753664        either an inequality or a equation.
    754665
    755666        INPUT:
    756        
     667
    757668        - ``index`` -- either an integer or ``None``.
    758669
    759670        OUTPUT:
    760        
     671
    761672        The optional argument is an index in
    762673        `0...n_Hrepresentations()`. If present, the H-representation
    763674        object at the given index will be returned. Without an
    764675        argument, returns the list of all H-representation objects.
    765676
    766677        EXAMPLES::
    767        
     678
    768679            sage: p = polytopes.n_cube(3)
    769680            sage: p.Hrepresentation(0)
    770681            An inequality (0, 0, -1) x + 1 >= 0
    771682            sage: p.Hrepresentation(0) == p.Hrepresentation() [0]
    772683            True
    773684        """
    774         if index==None:
     685        if index is None:
    775686            return self._Hrepresentation
    776687        else:
    777688            return self._Hrepresentation[index]
    778            
     689
    779690
    780691    def Hrep_generator(self):
    781692        """
     
    783694        (inequalities or equations).
    784695
    785696        EXAMPLES::
    786        
     697
    787698            sage: p = polytopes.n_cube(3)
    788699            sage: p.Hrep_generator().next()
    789700            An inequality (0, 0, -1) x + 1 >= 0
     
    791702        for H in self.Hrepresentation():
    792703            yield H
    793704
    794 
     705    @cached_method
    795706    def n_Hrepresentation(self):
    796707        """
    797708        Return the number of objects that make up the
     
    811722        """
    812723        return len(self.Hrepresentation())
    813724
    814 
    815725    def Vrepresentation(self, index=None):
    816726        """
    817727        Return the objects of the V-representation. Each entry is
    818728        either a vertex, a ray, or a line.
    819729
    820730        INPUT:
    821        
     731
    822732        - ``index`` -- either an integer or ``None``.
    823733
    824734        OUTPUT:
    825        
     735
    826736        The optional argument is an index in
    827737        `0...n_Vrepresentation()`. If present, the V-representation
    828738        object at the given index will be returned. Without an
     
    836746            sage: p.Vrepresentation(0) == p.Vrepresentation() [0]
    837747            True
    838748        """
    839         if index==None:
     749        if index is None:
    840750            return self._Vrepresentation
    841751        else:
    842752            return self._Vrepresentation[index]
    843753
    844 
     754    @cached_method
    845755    def n_Vrepresentation(self):
    846756        """
    847757        Return the number of objects that make up the
     
    861771        """
    862772        return len(self.Vrepresentation())
    863773
    864 
    865774    def Vrep_generator(self):
    866775        """
    867776        Returns an iterator over the objects of the V-representation
     
    879788        for V in self.Vrepresentation():
    880789            yield V
    881790
    882 
    883791    def facial_adjacencies(self):
    884         """
     792        r"""
    885793        Return the list of face indices (i.e. indices of
    886794        H-representation objects) and the indices of faces adjacent to
    887795        them.
     
    896804
    897805            sage: p = polytopes.permutahedron(4)
    898806            sage: p.facial_adjacencies()[0:3]
     807            doctest:...: DeprecationWarning:
     808            This method is deprecated.
     809            Use self.Hrepresentation(i).neighbors() instead.
     810            See http://trac.sagemath.org/11763 for details.
    899811            [[0, [1, 2, 5, 10, 12, 13]], [1, [0, 2, 5, 7, 9, 11]], [2, [0, 1, 10, 11]]]
    900812            sage: f0 = p.Hrepresentation(0)
    901813            sage: f0.index() == 0
     
    904816            sage: p.facial_adjacencies()[0] == f0_adjacencies
    905817            True
    906818        """
     819        from sage.misc.superseded import deprecation
     820        deprecation(11763, 'This method is deprecated. Use self.Hrepresentation(i).neighbors() instead.')
    907821        try:
    908822            return self._facial_adjacencies
    909823        except AttributeError:
     
    913827                  ] for h in self.Hrepresentation() ]
    914828            return self._facial_adjacencies
    915829
    916 
    917830    def facial_incidences(self):
    918831        """
    919832        Return the face-vertex incidences in the form `[f_i, [v_{i_0}, v_{i_1},\dots ,v_{i_2}]]`.
    920        
     833
    921834        .. NOTE::
    922835
    923836            Instead of working with face/vertex indices, it is
     
    935848
    936849            sage: p = Polyhedron(vertices = [[5,0,0],[0,5,0],[5,5,0],[0,0,0],[2,2,5]])
    937850            sage: p.facial_incidences()
     851            doctest:...: DeprecationWarning:
     852            This method is deprecated. Use self.Hrepresentation(i).incident() instead.
     853            See http://trac.sagemath.org/11763 for details.
    938854            [[0, [0, 1, 3, 4]],
    939855             [1, [0, 1, 2]],
    940856             [2, [0, 2, 3]],
     
    959875            sage: p.incidence_matrix().column(4)
    960876            (0, 1, 1, 0, 1)
    961877        """
     878        from sage.misc.superseded import deprecation
     879        deprecation(11763, 'This method is deprecated. Use self.Hrepresentation(i).incident() instead.')
    962880        try:
    963881            return self._facial_incidences
    964882        except AttributeError:
     
    968886                  ] for h in self.Hrepresentation() ]
    969887            return self._facial_incidences
    970888
    971 
    972889    def vertex_adjacencies(self):
    973890        """
    974891        Return a list of vertex indices and their adjacent vertices.
     
    987904
    988905            sage: permuta3 = Polyhedron(vertices = permutations([1,2,3,4]))
    989906            sage: permuta3.vertex_adjacencies()[0:3]
     907            doctest:...: DeprecationWarning:
     908            This method is deprecated. Use self.Vrepresentation(i).neighbors() instead.
     909            See http://trac.sagemath.org/11763 for details.
    990910            [[0, [1, 2, 6]], [1, [0, 3, 7]], [2, [0, 4, 8]]]
    991911            sage: v0 = permuta3.Vrepresentation(0)
    992912            sage: v0.index() == 0
     
    997917            sage: permuta3.vertex_adjacencies()[0] == v0_adjacencies
    998918            True
    999919        """
     920        from sage.misc.superseded import deprecation
     921        deprecation(11763, 'This method is deprecated. Use self.Vrepresentation(i).neighbors() instead.')
    1000922        try:
    1001923            return self._vertex_adjacencies
    1002924        except AttributeError:
     
    1006928                  ] for v in self.Vrepresentation() ]
    1007929            return self._vertex_adjacencies
    1008930
    1009 
    1010931    def vertex_incidences(self):
    1011932        """
    1012933        Return the vertex-face incidences in the form `[v_i, [f_{i_0}, f_{i_1},\dots ,f_{i_2}]]`.
    1013        
     934
    1014935        .. NOTE::
    1015936
    1016937            Instead of working with face/vertex indices, you can use
     
    1021942
    1022943            sage: p = polytopes.n_simplex(3)
    1023944            sage: p.vertex_incidences()
     945            doctest:...: DeprecationWarning:
     946            This method is deprecated. Use self.Vrepresentation(i).incident() instead.
     947            See http://trac.sagemath.org/11763 for details.
    1024948            [[0, [0, 1, 2]], [1, [0, 1, 3]], [2, [0, 2, 3]], [3, [1, 2, 3]]]
    1025949            sage: v0 = p.Vrepresentation(0)
    1026950            sage: v0.index() == 0
     
    1028952            sage: p.vertex_incidences()[0] == [ v0.index(), [h.index() for h in v0.incident()] ]
    1029953            True
    1030954        """
     955        from sage.misc.superseded import deprecation
     956        deprecation(11763, 'This method is deprecated. Use self.Vrepresentation(i).incident() instead.')
    1031957        try:
    1032958            return self._vertex_incidences
    1033959        except AttributeError:
     
    1037963                  ] for v in self.Vrepresentation() ]
    1038964            return self._vertex_incidences
    1039965
    1040 
    1041966    def inequality_generator(self):
    1042967        """
    1043968        Return  a generator for the defining inequalities of the
    1044969        polyhedron.
    1045970
    1046971        OUTPUT:
    1047        
     972
    1048973        A generator of the inequality Hrepresentation objects.
    1049974
    1050975        EXAMPLES::
     
    1065990            if H.is_inequality():
    1066991                yield H
    1067992
    1068 
     993    @cached_method
    1069994    def inequalities(self):
    1070995        """
    1071         Return a list of inequalities as coefficient lists.
    1072 
    1073         .. NOTE::
    1074        
    1075             It is recommended to use :meth:`inequality_generator`
    1076             instead to iterate over the list of :class:`Inequality`
    1077             objects.
     996        Return all inequalities.
     997
     998        OUTPUT:
     999
     1000        A tuple of inequalities.
    10781001
    10791002        EXAMPLES::
    10801003
    10811004            sage: p = Polyhedron(vertices = [[0,0,0],[0,0,1],[0,1,0],[1,0,0],[2,2,2]])
    10821005            sage: p.inequalities()[0:3]
     1006            (An inequality (1, 0, 0) x + 0 >= 0,
     1007             An inequality (0, 1, 0) x + 0 >= 0,
     1008             An inequality (0, 0, 1) x + 0 >= 0)
     1009            sage: p3 = Polyhedron(vertices = permutations([1,2,3,4]))
     1010            sage: ieqs = p3.inequalities()
     1011            sage: ieqs[0]
     1012            An inequality (0, 1, 1, 1) x - 6 >= 0
     1013            sage: list(_)
     1014            [-6, 0, 1, 1, 1]
     1015        """
     1016        return tuple(self.inequality_generator())
     1017
     1018    def inequalities_list(self):
     1019        """
     1020        Return a list of inequalities as coefficient lists.
     1021
     1022        .. NOTE::
     1023
     1024            It is recommended to use :meth:`inequalities` or
     1025            :meth:`inequality_generator` instead to iterate over the
     1026            list of :class:`Inequality` objects.
     1027
     1028        EXAMPLES::
     1029
     1030            sage: p = Polyhedron(vertices = [[0,0,0],[0,0,1],[0,1,0],[1,0,0],[2,2,2]])
     1031            sage: p.inequalities_list()[0:3]
    10831032            [[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
    10841033            sage: p3 = Polyhedron(vertices = permutations([1,2,3,4]))
    1085             sage: ieqs = p3.inequalities()
     1034            sage: ieqs = p3.inequalities_list()
    10861035            sage: ieqs[0]
    10871036            [-6, 0, 1, 1, 1]
    10881037            sage: ieqs[-1]
     
    10901039            sage: ieqs == [list(x) for x in p3.inequality_generator()]
    10911040            True
    10921041        """
    1093         try:
    1094             return self._inequalities
    1095         except AttributeError:
    1096             self._ieqs = [list(x) for x in self.inequality_generator()]
    1097             return self._ieqs
    1098 
     1042        return [list(x) for x in self.inequality_generator()]
    10991043
    11001044    def ieqs(self):
    11011045        """
    11021046        Deprecated. Alias for inequalities()
    11031047
    11041048        EXAMPLES::
    1105          
     1049
    11061050            sage: p3 = Polyhedron(vertices = permutations([1,2,3,4]))
    11071051            sage: p3.ieqs() == p3.inequalities()
     1052            doctest:...: DeprecationWarning:
     1053            This method is deprecated. Use inequalities() instead.
     1054            See http://trac.sagemath.org/11763 for details.
    11081055            True
    11091056        """
     1057        from sage.misc.superseded import deprecation
     1058        deprecation(11763, 'This method is deprecated. Use inequalities() instead.')
    11101059        return self.inequalities()
    11111060
    1112 
    11131061    def equation_generator(self):
    11141062        """
    11151063        Return a generator for the linear equations satisfied by the
     
    11261074            if H.is_equation():
    11271075                yield H
    11281076
    1129 
     1077    @cached_method
    11301078    def equations(self):
    11311079        """
     1080        Return all linear constraints of the polyhedron.
     1081
     1082        OUTPUT:
     1083
     1084        A tuple of equations.
     1085
     1086        EXAMPLES::
     1087
     1088            sage: test_p = Polyhedron(vertices = [[1,2,3,4],[2,1,3,4],[4,3,2,1],[3,4,1,2]])
     1089            sage: test_p.equations()
     1090            (An equation (1, 1, 1, 1) x - 10 == 0,)
     1091        """
     1092        return tuple(self.equation_generator())
     1093
     1094    def equations_list(self):
     1095        """
    11321096        Return the linear constraints of the polyhedron. As with
    11331097        inequalities, each constraint is given as [b -a1 -a2 ... an]
    11341098        where for variables x1, x2,..., xn, the polyhedron satisfies
    11351099        the equation b = a1*x1 + a2*x2 + ... + an*xn.
    11361100
    11371101        .. NOTE::
    1138        
    1139             It is recommended to use :meth:`equation_generator()` instead
    1140             to iterate over the list of :class:`Equation` objects.
     1102
     1103            It is recommended to use :meth:`equations` or
     1104            :meth:`equation_generator()` instead to iterate over the
     1105            list of
     1106            :class:`~sage.geometry.polyhedron.representation.Equation`
     1107            objects.
    11411108
    11421109        EXAMPLES::
    11431110
    11441111            sage: test_p = Polyhedron(vertices = [[1,2,3,4],[2,1,3,4],[4,3,2,1],[3,4,1,2]])
    1145             sage: test_p.equations()
     1112            sage: test_p.equations_list()
    11461113            [[-10, 1, 1, 1, 1]]
    11471114        """
    1148         try:
    1149             return self._equations
    1150         except AttributeError:
    1151             self._equations = [list(eq) for eq in self.equation_generator()]
    1152             return self._equations
    1153 
     1115        return [list(eq) for eq in self.equation_generator()]
    11541116
    11551117    def linearities(self):
    11561118        """
     
    11641126
    11651127            sage: test_p = Polyhedron(vertices = [[1,2,3,4],[2,1,3,4],[4,3,2,1],[3,4,1,2]])
    11661128            sage: test_p.linearities()
     1129            doctest:...: DeprecationWarning:
     1130            This method is deprecated. Use equations_list() instead.
     1131            See http://trac.sagemath.org/11763 for details.
    11671132            [[-10, 1, 1, 1, 1]]
    1168             sage: test_p.linearities() == test_p.equations()
     1133            sage: test_p.linearities() == test_p.equations_list()
    11691134            True
    11701135        """
    1171         return self.equations()
    1172 
    1173 
    1174     def vertices(self):
     1136        from sage.misc.superseded import deprecation
     1137        deprecation(11763, 'This method is deprecated. Use equations_list() instead.')
     1138        return self.equations_list()
     1139
     1140    def vertices_list(self):
    11751141        """
    11761142        Return a list of vertices of the polyhedron.
    11771143
    11781144        .. NOTE::
    1179        
     1145
    11801146            It is recommended to use :meth:`vertex_generator` instead to
    11811147            iterate over the list of :class:`Vertex` objects.
    11821148
    11831149        EXAMPLES::
    11841150
    11851151            sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[1,1]])
    1186             sage: triangle.vertices()
     1152            sage: triangle.vertices_list()
    11871153            [[0, 1], [1, 0], [1, 1]]
    11881154            sage: a_simplex = Polyhedron(ieqs = [
    11891155            ...            [0,1,0,0,0],[0,0,1,0,0],[0,0,0,1,0],[0,0,0,0,1]
    11901156            ...        ], eqns = [[1,-1,-1,-1,-1]])
    1191             sage: a_simplex.vertices()
     1157            sage: a_simplex.vertices_list()
    11921158            [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]
    1193             sage: a_simplex.vertices() == [list(v) for v in a_simplex.vertex_generator()]
     1159            sage: a_simplex.vertices_list() == [list(v) for v in a_simplex.vertex_generator()]
    11941160            True
    11951161        """
    1196         try:
    1197             return self._vertices
    1198         except AttributeError:
    1199             self._vertices = [list(x) for x in self.vertex_generator()]
    1200             return self._vertices
    1201 
    1202        
     1162        return [list(x) for x in self.vertex_generator()]
     1163
    12031164    def vertex_generator(self):
    12041165        """
    12051166        Return a generator for the vertices of the polyhedron.
     
    12291190        for V in self.Vrepresentation():
    12301191            if V.is_vertex():
    12311192                yield V
    1232        
     1193
     1194    @cached_method
     1195    def vertices(self):
     1196        """
     1197        Return all vertices of the polyhedron.
     1198
     1199        OUTPUT:
     1200
     1201        A tuple of vertices.
     1202
     1203        EXAMPLES::
     1204
     1205            sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[1,1]])
     1206            sage: triangle.vertices()
     1207            (A vertex at (0, 1), A vertex at (1, 0), A vertex at (1, 1))
     1208            sage: a_simplex = Polyhedron(ieqs = [
     1209            ...            [0,1,0,0,0],[0,0,1,0,0],[0,0,0,1,0],[0,0,0,0,1]
     1210            ...        ], eqns = [[1,-1,-1,-1,-1]])
     1211            sage: a_simplex.vertices()
     1212            (A vertex at (1, 0, 0, 0), A vertex at (0, 1, 0, 0),
     1213             A vertex at (0, 0, 1, 0), A vertex at (0, 0, 0, 1))
     1214        """
     1215        return tuple(self.vertex_generator())
     1216
     1217    @cached_method
     1218    def vertices_matrix(self, base_ring=None):
     1219        """
     1220        Return the coordinates of the vertices as the columns of a matrix.
     1221
     1222        INPUT:
     1223
     1224        - ``base_ring`` -- A ring or ``None`` (default). The base ring
     1225          of the returned matrix. If not specified, the base ring of
     1226          the polyhedron is used.
     1227
     1228        OUTPUT:
     1229
     1230        A matrix over ``base_ring`` whose columns are the coordinates
     1231        of the vertices. A ``TypeError`` is raised if the coordinates
     1232        cannot be converted to ``base_ring``.
     1233
     1234        EXAMPLES::
     1235
     1236            sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[1,1]])
     1237            sage: triangle.vertices_matrix()
     1238            [0 1 1]
     1239            [1 0 1]
     1240            sage: (triangle/2).vertices_matrix()
     1241            [  0 1/2 1/2]
     1242            [1/2   0 1/2]
     1243            sage: (triangle/2).vertices_matrix(ZZ)
     1244            Traceback (most recent call last):
     1245            ...
     1246            TypeError: no conversion of this rational to integer
     1247        """
     1248        if base_ring is None:
     1249            base_ring = self.base_ring()
     1250        m = matrix(base_ring, self.ambient_dim(), self.n_vertices())
     1251        for i,v in enumerate(self.vertices()):
     1252            for j in range(0,self.ambient_dim()):
     1253                m[j,i] = v[j]
     1254        return m
    12331255
    12341256    def ray_generator(self):
    12351257        """
     
    12461268            if V.is_ray():
    12471269                yield V
    12481270
    1249 
     1271    @cached_method
    12501272    def rays(self):
    12511273        """
    1252         Return a list of rays as coefficient lists.
    1253 
    1254         .. NOTE::
    1255        
    1256             It is recommended to use :meth:`ray_generator` instead to
    1257             iterate over the list of :class:`Ray` objects.
     1274        Return a list of rays of the polyhedron.
    12581275
    12591276        OUTPUT:
    12601277
    1261         A list of rays as lists of coordinates.
     1278        A tuple of rays.
    12621279
    12631280        EXAMPLES::
    12641281
    12651282            sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0],[1,1,0,0]])
    12661283            sage: p.rays()
     1284            (A ray in the direction (1, 0, 0),
     1285             A ray in the direction (0, 1, 0),
     1286             A ray in the direction (0, 0, 1))
     1287        """
     1288        return tuple(self.ray_generator())
     1289
     1290    def rays_list(self):
     1291        """
     1292        Return a list of rays as coefficient lists.
     1293
     1294        .. NOTE::
     1295
     1296            It is recommended to use :meth:`rays` or
     1297            :meth:`ray_generator` instead to iterate over the list of
     1298            :class:`Ray` objects.
     1299
     1300        OUTPUT:
     1301
     1302        A list of rays as lists of coordinates.
     1303
     1304        EXAMPLES::
     1305
     1306            sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0],[1,1,0,0]])
     1307            sage: p.rays_list()
    12671308            [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
    1268             sage: p.rays() == [list(r) for r in p.ray_generator()]
     1309            sage: p.rays_list() == [list(r) for r in p.ray_generator()]
    12691310            True
    12701311        """
    1271         try:
    1272             return self._rays
    1273         except AttributeError:
    1274             self._rays = [list(x) for x in self.ray_generator()]
    1275             return self._rays
    1276 
     1312        return [list(x) for x in self.ray_generator()]
    12771313
    12781314    def line_generator(self):
    12791315        """
     
    12891325            if V.is_line():
    12901326                yield V
    12911327
    1292 
     1328    @cached_method
    12931329    def lines(self):
    12941330        """
     1331        Return all lines of the polyhedron.
     1332
     1333        OUTPUT:
     1334
     1335        A tuple of lines.
     1336
     1337        EXAMPLES::
     1338
     1339            sage: p = Polyhedron(rays = [[1,0],[-1,0],[0,1],[1,1]], vertices = [[-2,-2],[2,3]])
     1340            sage: p.lines()
     1341            (A line in the direction (1, 0),)
     1342        """
     1343        return tuple(self.line_generator())
     1344
     1345    def lines_list(self):
     1346        """
    12951347        Return a list of lines of the polyhedron.  The line data is given
    12961348        as a list of coordinates rather than as a Hrepresentation object.
    12971349
    12981350        .. NOTE::
    1299        
     1351
    13001352            It is recommended to use :meth:`line_generator` instead to
    13011353            iterate over the list of :class:`Line` objects.
    13021354
    13031355        EXAMPLES::
    13041356
    13051357            sage: p = Polyhedron(rays = [[1,0],[-1,0],[0,1],[1,1]], vertices = [[-2,-2],[2,3]])
    1306             sage: p.lines()
     1358            sage: p.lines_list()
    13071359            [[1, 0]]
    1308             sage: p.lines() == [list(x) for x in p.line_generator()]
     1360            sage: p.lines_list() == [list(x) for x in p.line_generator()]
    13091361            True
    13101362        """
    1311         try:
    1312             return self._lines
    1313         except AttributeError:
    1314             self._lines = [list(x) for x in self.line_generator()]
    1315             return self._lines
    1316 
    1317                
     1363        return [list(x) for x in self.line_generator()]
     1364
    13181365    def bounded_edges(self):
    13191366        """
    13201367        Return the bounded edges (excluding rays and lines).
    1321        
     1368
    13221369        OUTPUT:
    13231370
    13241371        A generator for pairs of vertices, one pair per edge.
     
    13401387                if self.vertex_adjacency_matrix()[i,j] == 0: continue
    13411388                yield (obj[i], obj[j])
    13421389
    1343 
    1344     @cached_method
    1345     def ambient_space(self):
     1390    def Vrepresentation_space(self):
    13461391        r"""
    13471392        Return the ambient vector space.
    1348        
     1393
    13491394        OUTPUT:
    1350        
     1395
    13511396        A free module over the base ring of dimension :meth:`ambient_dim`.
    1352        
     1397
    13531398        EXAMPLES::
    13541399
    13551400            sage: poly_test = Polyhedron(vertices = [[1,0,0,0],[0,1,0,0]])
    1356             sage: poly_test.ambient_space()
    1357             Vector space of dimension 4 over Rational Field
     1401            sage: poly_test.Vrepresentation_space()
     1402            Ambient free module of rank 4 over the principal ideal domain Integer Ring
     1403            sage: poly_test.ambient_space() is poly_test.Vrepresentation_space()
     1404            True
    13581405        """
    1359         from sage.modules.free_module import VectorSpace
    1360         return VectorSpace(self.base_ring(), self.ambient_dim())
    1361 
    1362     Vrepresentation_space = ambient_space
    1363 
    1364     @cached_method
     1406        return self.parent().Vrepresentation_space()
     1407
     1408    ambient_space = Vrepresentation_space
     1409
    13651410    def Hrepresentation_space(self):
    13661411        r"""
    13671412        Return the linear space containing the H-representation vectors.
    13681413
    13691414        OUTPUT:
    1370        
     1415
    13711416        A free module over the base ring of dimension :meth:`ambient_dim` + 1.
    1372        
     1417
    13731418        EXAMPLES::
    1374        
     1419
    13751420            sage: poly_test = Polyhedron(vertices = [[1,0,0,0],[0,1,0,0]])
    1376             sage: poly_test.ambient_space()
    1377             Vector space of dimension 4 over Rational Field
     1421            sage: poly_test.Hrepresentation_space()
     1422            Ambient free module of rank 5 over the principal ideal domain Integer Ring
    13781423        """
    1379         from sage.modules.free_module import VectorSpace
    1380         return VectorSpace(self.base_ring(), self.ambient_dim()+1)
    1381 
     1424        return self.parent().Hrepresentation_space()
    13821425
    13831426    def ambient_dim(self):
    13841427        r"""
     
    13901433            sage: poly_test.ambient_dim()
    13911434            4
    13921435        """
    1393         return self._ambient_dim
    1394 
    1395            
     1436        return self.parent().ambient_dim()
     1437
    13961438    def dim(self):
    13971439        """
    13981440        Return the dimension of the polyhedron.
     
    14041446            3
    14051447            sage: simplex.ambient_dim()
    14061448            4
    1407        """
     1449        """
    14081450        return self.ambient_dim() - self.n_equations()
    14091451
    1410 
    1411     def adjacency_matrix(self):
    1412         """
    1413         This is an alias for :meth:`vertex_adjacency_matrix`
    1414 
    1415         EXAMPLES::
    1416 
    1417             sage: polytopes.n_cube(3).adjacency_matrix()
    1418             [0 1 1 0 1 0 0 0]
    1419             [1 0 0 1 0 1 0 0]
    1420             [1 0 0 1 0 0 1 0]
    1421             [0 1 1 0 0 0 0 1]
    1422             [1 0 0 0 0 1 1 0]
    1423             [0 1 0 0 1 0 0 1]
    1424             [0 0 1 0 1 0 0 1]
    1425             [0 0 0 1 0 1 1 0]
    1426         """
    1427         return self.vertex_adjacency_matrix()
    1428 
    1429 
     1452    @cached_method
    14301453    def vertex_adjacency_matrix(self):
    14311454        """
    14321455        Return the binary matrix of vertex adjacencies.
     
    14401463            [1 1 1 0 1]
    14411464            [1 1 1 1 0]
    14421465        """
    1443         if '_V_adjacency_matrix' not in self.__dict__:
    1444             self._init_vertex_adjacency_matrix()
    1445         return self._V_adjacency_matrix;
    1446 
    1447 
     1466        return self._vertex_adjacency_matrix()
     1467
     1468    adjacency_matrix = vertex_adjacency_matrix
     1469
     1470    @cached_method
    14481471    def facet_adjacency_matrix(self):
    14491472        """
    14501473        Return the adjacency matrix for the facets and hyperplanes.
     
    14581481            [1 1 1 0 1]
    14591482            [1 1 1 1 0]
    14601483        """
    1461         if '_H_adjacency_matrix' not in self.__dict__:
    1462             self._init_facet_adjacency_matrix()
    1463         return self._H_adjacency_matrix;
    1464 
    1465 
     1484        return self._facet_adjacency_matrix()
     1485
     1486    @cached_method
    14661487    def incidence_matrix(self):
    14671488        """
    14681489        Return the incidence matrix.
     
    14751496            :meth:`Vrepresentation`
    14761497
    14771498        EXAMPLES::
    1478        
     1499
    14791500            sage: p = polytopes.cuboctahedron()
    14801501            sage: p.incidence_matrix()
    14811502            [0 0 1 1 0 1 0 0 0 0 1 0 0 0]
     
    15071528            sage: p.incidence_matrix() [2,0]   # note: not symmetric
    15081529            0
    15091530        """
    1510         try:
    1511             return self._incidence_matrix
    1512         except AttributeError:
    1513             self._incidence_matrix = matrix(ZZ, len(self.Vrepresentation()),
    1514                                                 len(self.Hrepresentation()), 0)
    1515             for V in self.Vrep_generator():
    1516                 for H in self.Hrep_generator():
    1517                     if self._is_zero(H*V):
    1518                         self._incidence_matrix[V.index(),H.index()] = 1
    1519 
    1520             return self._incidence_matrix
    1521 
     1531        incidence_matrix = matrix(ZZ, self.n_Vrepresentation(),
     1532                                  self.n_Hrepresentation(), 0)
     1533        for V in self.Vrep_generator():
     1534            for H in self.Hrep_generator():
     1535                if self._is_zero(H*V):
     1536                    incidence_matrix[V.index(),H.index()] = 1
     1537        return incidence_matrix
    15221538
    15231539    def base_ring(self):
    15241540        """
     
    15321548        EXAMPLES::
    15331549
    15341550            sage: triangle = Polyhedron(vertices = [[1,0],[0,1],[1,1]])
    1535             sage: triangle.base_ring() == QQ
     1551            sage: triangle.base_ring() == ZZ
    15361552            True
    15371553        """
    1538         return self._base_ring
     1554        return self.parent().base_ring()
    15391555
    15401556    field = base_ring
    15411557
    1542 
    1543     def coerce_field(self, other):
    1544         """
    1545         Return the common field for both ``self`` and ``other``.
    1546 
    1547         INPUT:
    1548 
    1549         - ``other`` -- must be either:
    1550        
    1551             * another ``Polyhedron`` object
    1552        
    1553             * `\QQ` or `RDF`
    1554        
    1555             * a constant that can be coerced to `\QQ` or `RDF`
    1556 
    1557         OUTPUT:
    1558 
    1559         Either `\QQ` or `RDF`. Raises ``TypeError`` if ``other`` is not a
    1560         suitable input.
    1561 
    1562         .. NOTE::
    1563        
    1564             "Real" numbers in sage are not necessarily elements of
    1565             `RDF`. For example, the literal `1.0` is not.
    1566 
    1567         EXAMPLES::
    1568 
    1569             sage: triangle_QQ  = Polyhedron(vertices = [[1,0],[0,1],[1,1]], base_ring=QQ)
    1570             sage: triangle_RDF = Polyhedron(vertices = [[1,0],[0,1],[1,1]], base_ring=RDF)
    1571             sage: triangle_QQ.coerce_field(QQ)
    1572             Rational Field
    1573             sage: triangle_QQ.coerce_field(triangle_RDF)
    1574             Real Double Field
    1575             sage: triangle_RDF.coerce_field(triangle_QQ)
    1576             Real Double Field
    1577             sage: triangle_QQ.coerce_field(RDF)
    1578             Real Double Field
    1579             sage: triangle_QQ.coerce_field(ZZ)
    1580             Rational Field
    1581             sage: triangle_QQ.coerce_field(1/2)
    1582             Rational Field
    1583             sage: triangle_QQ.coerce_field(0.5)
    1584             Real Double Field
    1585         """
    1586         try:
    1587             # other is a Polyhedron object?
    1588             other_field = other.field()
    1589         except AttributeError:
    1590 
    1591             try:
    1592                 # other is a constant?
    1593                 other_parent = other.parent()
    1594             except AttributeError:
    1595                 other_parent = other
    1596 
    1597             # other is a field?
    1598             if QQ.coerce_map_from(other_parent) != None:
    1599                 other_field = QQ
    1600             elif RDF.coerce_map_from(other_parent) != None:
    1601                 other_field = RDF
    1602             else:
    1603                 raise TypeError("cannot determine field from %s!" % other)
    1604 
    1605         assert other_field==QQ or other_field==RDF
    1606            
    1607         if self.field()==RDF or other_field==RDF:
    1608             return RDF
    1609         else:
    1610             return QQ
    1611 
    1612 
    16131558    @cached_method
    16141559    def center(self):
    16151560        """
     
    16661611        distance measure.
    16671612
    16681613        EXAMPLES::
    1669        
     1614
    16701615            sage: p = polytopes.n_cube(4)
    16711616            sage: p.radius()
    16721617            2
    16731618        """
    16741619        return sqrt(self.radius_square())
    16751620
    1676 
    16771621    def is_compact(self):
    16781622        """
    16791623        Test for boundedness of the polytope.
     
    16891633        """
    16901634        return self.n_rays()==0 and self.n_lines()==0
    16911635
    1692 
    16931636    def is_simple(self):
    16941637        """
    16951638        Test for simplicity of a polytope.
     
    17131656            adj = [a for a in v.neighbors()]
    17141657            if len(adj) != self.dim():
    17151658                return False
    1716 
    17171659        return True
    17181660
     1661    @cached_method
    17191662    def gale_transform(self):
    17201663        """
    17211664        Return the Gale transform of a polytope as described in the
     
    17351678            sage: p2 = p.prism()
    17361679            sage: p2.gale_transform()
    17371680            [(1, 0), (0, 1), (-1, -1), (-1, 0), (0, -1), (1, 1)]
    1738        
     1681
    17391682        REFERENCES:
    17401683
    17411684            Lectures in Geometric Combinatorics, R.R.Thomas, 2006, AMS Press.
     
    17431686        if not self.is_compact(): raise ValueError('Not a polytope.')
    17441687
    17451688        A = matrix(self.n_vertices(),
    1746                    [ [1]+list(x) for x in self.vertex_generator()])
     1689                   [ [1]+x for x in self.vertex_generator()])
    17471690        A = A.transpose()
    17481691        A_ker = A.right_kernel()
    17491692        return A_ker.basis_matrix().transpose().rows()
     
    17721715        - ``fine`` -- boolean (default: ``False``). Whether the
    17731716          triangulations must be fine, that is, make use of all points
    17741717          of the configuration.
    1775    
     1718
    17761719        - ``regular`` -- boolean or ``None`` (default:
    17771720          ``None``). Whether the triangulations must be regular. A
    17781721          regular triangulation is one that is induced by a
    17791722          piecewise-linear convex support function. In other words,
    17801723          the shadows of the faces of a polyhedron in one higher
    17811724          dimension.
    1782      
     1725
    17831726          * ``True``: Only regular triangulations.
    17841727
    17851728          * ``False``: Only non-regular triangulations.
     
    17981741        :class:`~sage.geometry.triangulation.point_configuration.Triangulation`. The
    17991742        indices in the triangulation correspond to the
    18001743        :meth:`Vrepresentation` objects.
    1801        
     1744
    18021745        EXAMPLES::
    18031746
    18041747            sage: cube = polytopes.n_cube(3)
     
    18131756            [A vertex at (-1, -1, -1), A vertex at (-1, -1, 1),
    18141757             A vertex at (-1, 1, -1), A vertex at (1, 1, 1)]
    18151758            sage: Polyhedron(simplex_vertices)
    1816             A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
     1759            A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices
    18171760        """
    18181761        if not self.is_compact():
    18191762            raise NotImplementedError('I can only triangulate compact polytopes.')
     
    18421785
    18431786            sage: Polyhedron(vertices = [[5,0,0],[0,5,0],[5,5,0],[2,2,5]]
    18441787            ...             ).triangulated_facial_incidences()
    1845             doctest:...: DeprecationWarning: This method is
    1846             deprecated. Use triangulate() instead.
     1788            doctest:...: DeprecationWarning:
     1789            This method is deprecated. Use triangulate() instead.
    18471790            See http://trac.sagemath.org/11634 for details.
     1791            doctest:...: DeprecationWarning:
     1792            This method is deprecated. Use self.Hrepresentation(i).incident() instead.
     1793            See http://trac.sagemath.org/11763 for details.
    18481794            [[0, [0, 1, 2]], [1, [0, 1, 3]], [2, [0, 2, 3]], [3, [1, 2, 3]]]
    1849                              
     1795
    18501796        Otherwise some faces get split up to triangles::
    18511797
    18521798            sage: Polyhedron(vertices = [[2,0,0],[4,1,0],[0,5,0],[5,5,0],
    18531799            ...       [1,1,0],[0,0,1]]).triangulated_facial_incidences()
    1854             doctest:...: DeprecationWarning: This method is
    1855             deprecated. Use triangulate() instead.
     1800            doctest:...: DeprecationWarning:
     1801            This method is deprecated. Use triangulate() instead.
    18561802            See http://trac.sagemath.org/11634 for details.
     1803            doctest:...: DeprecationWarning:
     1804            This method is deprecated. Use self.Vrepresentation(i).neighbors() instead.
     1805            See http://trac.sagemath.org/11763 for details.
    18571806            [[0, [1, 2, 5]], [0, [2, 5, 3]], [0, [5, 3, 4]], [1, [0, 1, 2]],
    18581807             [2, [0, 2, 3]], [3, [0, 3, 4]], [4, [0, 4, 5]], [5, [0, 1, 5]]]
    18591808        """
     
    19081857        self._triangulated_facial_incidences = t_fac_incs
    19091858        return t_fac_incs
    19101859
    1911 
    19121860    def simplicial_complex(self):
    19131861        """
    19141862        Return a simplicial complex from a triangulation of the polytope.
     
    19401888        return SimplicialComplex(vertex_set = self.n_vertices(),
    19411889                                 maximal_faces = [x[1] for x in self.triangulated_facial_incidences()])
    19421890
    1943     def __add__(self, other):
     1891    @coerce_binop
     1892    def Minkowski_sum(self, other):
    19441893        """
     1894        Return the Minkowski sum.
     1895
     1896        INPUT:
     1897
     1898        - ``other`` -- a :class:`Polyhedron_base`.
     1899
     1900        OUTPUT:
     1901
    19451902        The Minkowski sum of ``self`` and ``other``.
    19461903
    1947         INPUT:
    1948 
    1949         - ``other`` -- a :class:`Polyhedron`.
    1950 
    19511904        EXAMPLES::
    19521905
    19531906            sage: four_cube = polytopes.n_cube(4)
    19541907            sage: four_simplex = Polyhedron(vertices = [[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]])
    1955             sage: unholy_union = four_cube + four_simplex
    1956             sage: unholy_union.dim()
    1957             4
    1958             sage: poly_spam = Polyhedron([[3,4,5,2],[1,0,0,1],[0,0,0,0],[0,4,3,2],[-3,-3,-3,-3]])
    1959             sage: poly_eggs = Polyhedron([[5,4,5,4],[-4,5,-4,5],[4,-5,4,-5],[0,0,0,0]])
    1960             sage: poly_spam_and_eggs = poly_spam + poly_spam + poly_eggs
    1961             sage: poly_spam_and_eggs.n_vertices()
    1962             12
     1908            sage: four_cube + four_simplex
     1909            A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 36 vertices
     1910            sage: four_cube.Minkowski_sum(four_simplex) == four_cube + four_simplex
     1911            True
     1912
     1913            sage: poly_spam = Polyhedron([[3,4,5,2],[1,0,0,1],[0,0,0,0],[0,4,3,2],[-3,-3,-3,-3]], base_ring=ZZ)
     1914            sage: poly_eggs = Polyhedron([[5,4,5,4],[-4,5,-4,5],[4,-5,4,-5],[0,0,0,0]], base_ring=QQ)
     1915            sage: poly_spam + poly_spam + poly_eggs
     1916            A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 12 vertices
    19631917        """
    1964         if is_Polyhedron(other):
    1965             new_vertices = []
    1966             for v1 in self.vertex_generator():
    1967                 for v2 in other.vertex_generator():
    1968                     new_vertices.append(list(v1() + v2()))
     1918        new_vertices = []
     1919        for v1 in self.vertex_generator():
     1920            for v2 in other.vertex_generator():
     1921                new_vertices.append(list(v1() + v2()))
     1922        if new_vertices != []:
    19691923            new_rays = self.rays() + other.rays()
    19701924            new_lines = self.lines() + other.lines()
    1971             other_field = other.field()
    1972 
    1973         else:  # assume other is a vector and try to add vertices
    1974             displacement = vector(other)
    1975             new_vertices = [list(x() + displacement) for x in self.vertex_generator()]
    1976             new_rays = self.rays()
    1977             new_lines = self.lines()
    1978             other_field = displacement.base_ring()
    1979 
     1925            return self.parent().element_class(self.parent(), [new_vertices, new_rays, new_lines], None)
     1926        else:
     1927            return self.parent().element_class(self.parent(), None, None)
     1928
     1929    _add_ = Minkowski_sum
     1930
     1931    def translation(self, displacement):
     1932        """
     1933        Return the translated polyhedron.
     1934
     1935        INPUT:
     1936
     1937        - ``displacement`` -- a displacement vector or a list/tuple of
     1938          coordinates that determines a displacement vector.
     1939
     1940        OUTPUT:
     1941
     1942        The translated polyhedron.
     1943
     1944        EXAMPLES::
     1945
     1946            sage: P = Polyhedron([[0,0],[1,0],[0,1]], base_ring=ZZ)
     1947            sage: P.translation([2,1])
     1948            A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
     1949            sage: P.translation( vector(QQ,[2,1]) )
     1950            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
     1951        """
     1952        displacement = vector(displacement)
     1953        new_vertices = [x.vector()+displacement for x in self.vertex_generator()]
     1954        new_rays = self.rays()
     1955        new_lines = self.lines()
     1956        new_ring = self.parent()._coerce_base_ring(displacement.base_ring())
     1957        return Polyhedron(vertices=new_vertices, rays=new_rays, lines=new_lines, base_ring=new_ring)
     1958
     1959    @coerce_binop
     1960    def product(self, other):
     1961        """
     1962        Return the cartesian product.
     1963
     1964        INPUT:
     1965
     1966        - ``other`` -- a :class:`Polyhedron_base`.
     1967
     1968        OUTPUT:
     1969
     1970        The cartesian product of ``self`` and ``other`` with a
     1971        suitable base ring to encompass the two.
     1972
     1973        EXAMPLES::
     1974
     1975            sage: P1 = Polyhedron([[0],[1]], base_ring=ZZ)
     1976            sage: P2 = Polyhedron([[0],[1]], base_ring=QQ)
     1977            sage: P1.product(P2)
     1978            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
     1979
     1980        The cartesian product is the product in the semiring of polyhedra::
     1981
     1982            sage: P1 * P1
     1983            A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 4 vertices
     1984            sage: P1 * P2
     1985            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
     1986            sage: P2 * P2
     1987            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
     1988            sage: 2 * P1
     1989            A 1-dimensional polyhedron in ZZ^1 defined as the convex hull of 2 vertices
     1990            sage: P1 * 2.0
     1991            A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices
     1992        """
     1993        new_vertices = [ list(x)+list(y)
     1994                         for x in self.vertex_generator() for y in other.vertex_generator()]
     1995        new_rays = []
     1996        new_rays.extend( [ r+[0]*other.ambient_dim()
     1997                           for r in self.ray_generator() ] )
     1998        new_rays.extend( [ [0]*self.ambient_dim()+r
     1999                           for r in other.ray_generator() ] )
     2000        new_lines = []
     2001        new_lines.extend( [ l+[0]*other.ambient_dim()
     2002                            for l in self.line_generator() ] )
     2003        new_lines.extend( [ [0]*self.ambient_dim()+l
     2004                            for l in other.line_generator() ] )
    19802005        return Polyhedron(vertices=new_vertices,
    19812006                          rays=new_rays, lines=new_lines,
    1982                           base_ring=self.coerce_field(other_field))
    1983            
    1984 
    1985     def __mul__(self, other):
     2007                          base_ring=self.parent()._coerce_base_ring(other))
     2008
     2009    _mul_ = product
     2010
     2011    def dilation(self, scalar):
    19862012        """
    1987         Multiplication by ``other``.
     2013        Return the dilated (uniformly stretched) polyhedron.
    19882014
    19892015        INPUT:
    19902016
    1991         - ``other`` -- A scalar, not necessarily in :meth:`field`, or
    1992           a :class:`Polyhedron`.
     2017        - ``scalar`` -- A scalar, not necessarily in :meth:`base_ring`,
     2018          or a :class:`Polyhedron`.
    19932019
    19942020        OUTPUT:
    19952021
     
    20022028             sage: p = Polyhedron(vertices = [[t,t^2,t^3] for t in srange(2,6)])
    20032029             sage: p.vertex_generator().next()
    20042030             A vertex at (2, 4, 8)
    2005              sage: p2 = p*2
     2031             sage: p2 = p.dilation(2)
    20062032             sage: p2.vertex_generator().next()
    20072033             A vertex at (4, 8, 16)
     2034             sage: p.dilation(2) == p * 2
     2035             True
    20082036        """
    2009         if is_Polyhedron(other):
    2010             new_vertices = [ list(x)+list(y)
    2011                              for x in self.vertex_generator() for y in other.vertex_generator()]
    2012             new_rays = []
    2013             new_rays.extend( [ list(r)+[0]*other.ambient_dim()
    2014                                for r in self.ray_generator() ] )
    2015             new_rays.extend( [ [0]*self.ambient_dim()+list(r)
    2016                                for r in other.ray_generator() ] )
    2017             new_lines = []
    2018             new_lines.extend( [ list(l)+[0]*other.ambient_dim()
    2019                                 for l in self.line_generator() ] )
    2020             new_lines.extend( [ [0]*self.ambient_dim()+list(l)
    2021                                for l in other.line_generator() ] )
    2022         else:
    2023             new_vertices = [ list(other*v()) for v in self.vertex_generator()]
    2024             new_rays =  self.rays()
    2025             new_lines = self.lines()
    2026 
     2037        new_vertices = [ list(scalar*v.vector()) for v in self.vertex_generator()]
     2038        new_rays =  self.rays()
     2039        new_lines = self.lines()
    20272040        return Polyhedron(vertices=new_vertices,
    20282041                          rays=new_rays, lines=new_lines,
    2029                           base_ring=self.coerce_field(other))
    2030 
    2031 
    2032     def __rmul__(self,other):
     2042                          base_ring=self.parent()._coerce_base_ring(scalar.parent()))
     2043
     2044    def _acted_upon_(self, actor, self_on_left):
    20332045        """
    2034         Right multiplication.
    2035 
    2036         See :meth:`__mul__` for details.
     2046        Implement the multiplicative action by scalars or other polyhedra.
     2047
     2048        INPUT:
     2049
     2050        - ``actor`` -- A scalar, not necessarily in :meth:`base_ring`,
     2051          or a :class:`Polyhedron`.
     2052
     2053        OUTPUT:
     2054
     2055        Multiplication by another polyhedron returns the product
     2056        polytope. Multiplication by a scalar returns the polytope
     2057        dilated by that scalar, possibly coerced to the bigger field.
    20372058
    20382059        EXAMPLES::
    20392060
     2061             sage: p = Polyhedron(vertices = [[t,t^2,t^3] for t in srange(2,6)])
     2062             sage: p._acted_upon_(2, True) == p.dilation(2)
     2063             True
     2064             sage: p*2 == p.dilation(2)
     2065             True
     2066             sage: p*p == p.product(p)
     2067             True
     2068             sage: p + vector(ZZ,[1,2,3]) == p.translation([1,2,3])
     2069             True
     2070        """
     2071        if is_Polyhedron(actor):
     2072            return self.product(actor)
     2073        if is_Vector(actor):
     2074            return self.translation(actor)
     2075        else:
     2076            return self.dilation(actor)
     2077
     2078    def __div__(self, scalar):
     2079        """
     2080        Divide by a scalar factor.
     2081
     2082        See :meth:`dilation` for details.
     2083
     2084        EXAMPLES::
     2085
    20402086            sage: p = Polyhedron(vertices = [[t,t^2,t^3] for t in srange(2,4)])
    2041             sage: p2 = 3*p + p
    2042             sage: p2.vertex_generator().next()
    2043             A vertex at (8, 16, 32)
     2087            sage: (p/5).Vrepresentation()
     2088            (A vertex at (2/5, 4/5, 8/5), A vertex at (3/5, 9/5, 27/5))
    20442089        """
    2045         return self.__mul__(other)
    2046 
    2047 
    2048     def union(self, other):
    2049         """
    2050         Deprecated.  Use ``self.convex_hull(other)`` instead.
    2051        
    2052         EXAMPLES::
    2053        
    2054             sage: Polyhedron(vertices=[[0]]).union( Polyhedron(vertices=[[1]]) )
    2055             doctest:...: DeprecationWarning:
    2056             The function union is replaced by convex_hull.
    2057             See http://trac.sagemath.org/11634 for details.
    2058             A 1-dimensional polyhedron in QQ^1 defined as the convex hull of 2 vertices
    2059         """
    2060         from sage.misc.superseded import deprecation
    2061         deprecation(11634, 'The function union is replaced by convex_hull.')
    2062         return self.convex_hull(other)
    2063 
    2064 
     2090        return self.dilation(1/scalar)
     2091
     2092    @coerce_binop
    20652093    def convex_hull(self, other):
    20662094        """
    20672095        Return the convex hull of the set-theoretic union of the two
     
    20882116        hull_vertices = self.vertices() + other.vertices()
    20892117        hull_rays = self.rays() + other.rays()
    20902118        hull_lines = self.lines() + other.lines()
    2091         hull_field = self.coerce_field(other)
    2092         return Polyhedron(vertices=hull_vertices,
    2093                           rays=hull_rays, lines=hull_lines,
    2094                           base_ring=hull_field)
    2095 
    2096 
     2119        return self.parent().element_class(self.parent(), [hull_vertices, hull_rays, hull_lines], None)
     2120
     2121    @coerce_binop
    20972122    def intersection(self, other):
    20982123        """
    20992124        Return the intersection of one polyhedron with another.
     
    21062131
    21072132        The intersection.
    21082133
     2134        Note that the intersection of two `\ZZ`-polyhedra might not be
     2135        a `\ZZ`-polyhedron. In this case, a `\QQ`-polyhedron is
     2136        returned.
     2137
    21092138        EXAMPLES::
    21102139
    21112140            sage: cube = polytopes.n_cube(3)
    21122141            sage: oct = polytopes.cross_polytope(3)
    2113             sage: cube_oct = cube.intersection(oct*2)
    2114             sage: len(list( cube_oct.vertex_generator() ))
    2115             12
    2116             sage: cube_oct
    2117             A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 12 vertices
     2142            sage: cube.intersection(oct*2)
     2143            A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 12 vertices
     2144
     2145       The intersection of two `\ZZ`-polyhedra is not necessarily a `\ZZ`-polyhedron::
     2146
     2147            sage: P = Polyhedron([(0,0),(1,1)], base_ring=ZZ)
     2148            sage: P.intersection(P)
     2149            A 1-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices
     2150            sage: Q = Polyhedron([(0,1),(1,0)], base_ring=ZZ)
     2151            sage: P.intersection(Q)
     2152            A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex
     2153            sage: _.Vrepresentation()
     2154            (A vertex at (1/2, 1/2),)
    21182155        """
    2119         new_ieqs = []
    2120         new_ieqs.extend(self.inequalities())
    2121         new_ieqs.extend(other.inequalities())
    2122 
    2123         new_eqns = []
    2124         new_eqns.extend(self.equations())
    2125         new_eqns.extend(other.equations())
    2126 
    2127         return Polyhedron(ieqs = new_ieqs, eqns = new_eqns,
    2128                           base_ring=self.coerce_field(other))
    2129 
     2156        new_ieqs = self.inequalities() + other.inequalities()
     2157        new_eqns = self.equations() + other.equations()
     2158        parent = self.parent()
     2159        try:
     2160            return parent.element_class(parent, None, [new_ieqs, new_eqns])
     2161        except TypeError,msg:
     2162            if self.base_ring() is ZZ:
     2163                parent = parent.base_extend(QQ)
     2164                return parent.element_class(parent, None, [new_ieqs, new_eqns])
     2165            else:
     2166                raise TypeError(msg)
    21302167
    21312168    def edge_truncation(self, cut_frac = Integer(1)/3):
    21322169        r"""
    21332170        Return a new polyhedron formed from two points on each edge
    21342171        between two vertices.
    2135        
     2172
    21362173        INPUT:
    2137        
     2174
    21382175        - ``cut_frac`` -- integer. how deeply to cut into the edge.
    21392176            Default is `\frac{1}{3}`.
    2140            
     2177
    21412178        OUTPUT:
    21422179
    21432180        A Polyhedron object, truncated as described above.
    2144            
     2181
    21452182        EXAMPLES::
    21462183
    21472184            sage: cube = polytopes.n_cube(3)
     
    21622199
    21632200        return Polyhedron(vertices=new_vertices, rays=new_rays,
    21642201                          lines=new_lines,
    2165                           base_ring=self.coerce_field(cut_frac))
     2202                          base_ring=self.parent()._coerce_base_ring(cut_frac))
    21662203
    21672204
    21682205    def _make_polyhedron_face(self, Vindices, Hindices):
     
    21792216          face.
    21802217
    21812218        OUTPUT:
    2182        
    2183         A new :class:`PolyhedronFace_base` instance. It is not checked
     2219
     2220        A new :class:`~sage.geometry.polyhedron.face.PolyhedronFace` instance. It is not checked
    21842221        whether the input data actually defines a face.
    21852222
    21862223        EXAMPLES::
     
    21892226            sage: square._make_polyhedron_face((0,2), (1,))
    21902227            <0,2>
    21912228        """
    2192         return PolyhedronFace_base(self, Vindices, Hindices)
    2193 
    2194 
     2229        from sage.geometry.polyhedron.face import PolyhedronFace
     2230        return PolyhedronFace(self, Vindices, Hindices)
     2231
     2232    @cached_method
    21952233    def face_lattice(self):
    21962234        """
    21972235        Return the face-lattice poset.
    21982236
    21992237        OUTPUT:
    2200        
     2238
    22012239        A :class:`~sage.combinat.posets.posets.FinitePoset`. Elements
    22022240        are given as
    2203         :class:`~sage.geometry.polyhedron.PolyhedronFace_base`.
     2241        :class:`~sage.geometry.polyhedron.face.PolyhedronFace`.
    22042242
    22052243        In the case of a full-dimensional polytope, the faces are
    22062244        pairs (vertices, inequalities) of the spanning vertices and
     
    22352273        * Lines are removed before calling
    22362274          :func:`Hasse_diagram_from_incidences`, and then added back
    22372275          to each face V-representation except for the "empty face".
    2238        
     2276
    22392277        * Equations are removed before calling
    22402278          :func:`Hasse_diagram_from_incidences`, and then added back
    22412279          to each face H-representation.
     
    22712309            (A vertex at (-1, -1), A vertex at (1, -1))
    22722310            sage: a_face.ambient_Hrepresentation()
    22732311            (An inequality (0, 1) x + 1 >= 0,)
    2274            
     2312
    22752313        A more complicated example::
    22762314
    22772315            sage: c5_10 = Polyhedron(vertices = [[i,i^2,i^3,i^4,i^5] for i in range(1,11)])
    22782316            sage: c5_10_fl = c5_10.face_lattice()
    22792317            sage: [len(x) for x in c5_10_fl.level_sets()]
    22802318            [1, 10, 45, 100, 105, 42, 1]
    2281            
     2319
    22822320        Note that if the polyhedron contains lines then there is a
    22832321        dimension gap between the empty face and the first non-empty
    22842322        face in the face lattice::
     
    23282366        REFERENCES:
    23292367
    23302368        ..  [KP2002]
    2331        
     2369
    23322370            Volker Kaibel and Marc E. Pfetsch, "Computing the Face
    23332371            Lattice of a Polytope from its Vertex-Facet Incidences",
    23342372            Computational Geometry: Theory and Applications, Volume
     
    23362374            http://portal.acm.org/citation.cfm?id=763203 and free of
    23372375            charge at http://arxiv.org/abs/math/0106043
    23382376        """
    2339         try:
    2340             return self._face_lattice
    2341         except AttributeError:
    2342             pass
    2343        
    23442377        coatom_to_Hindex = [ h.index() for h in self.inequality_generator() ]
    23452378        Hindex_to_coatom = [None] * self.n_Hrepresentation()
    23462379        for i in range(0,len(coatom_to_Hindex)):
    23472380            Hindex_to_coatom[ coatom_to_Hindex[i] ] = i
    2348            
     2381
    23492382        atom_to_Vindex = [ v.index() for v in self.Vrep_generator() if not v.is_line() ]
    23502383        Vindex_to_atom = [None] * self.n_Vrepresentation()
    23512384        for i in range(0,len(atom_to_Vindex)):
    23522385                        Vindex_to_atom[ atom_to_Vindex[i] ] = i
    2353            
     2386
    23542387        atoms_incidences   = [ tuple([ Hindex_to_coatom[h.index()]
    23552388                                       for h in v.incident() if h.is_inequality() ])
    23562389                               for v in self.Vrepresentation() if not v.is_line() ]
    2357        
     2390
    23582391        coatoms_incidences = [ tuple([ Vindex_to_atom[v.index()]
    23592392                                       for v in h.incident() if not v.is_line() ])
    23602393                               for h in self.Hrepresentation() if h.is_inequality() ]
    2361        
     2394
    23622395        atoms_vertices = [ Vindex_to_atom[v.index()] for v in self.vertex_generator() ]
    23632396        equations = [ e.index() for e in self.equation_generator() ]
    23642397        lines     = [ l.index() for l in self.line_generator() ]
     
    23722405            return self._make_polyhedron_face(Vindices, Hindices)
    23732406
    23742407        from sage.geometry.hasse_diagram import Hasse_diagram_from_incidences
    2375         self._face_lattice = Hasse_diagram_from_incidences\
     2408        return Hasse_diagram_from_incidences\
    23762409            (atoms_incidences, coatoms_incidences,
    23772410             face_constructor=face_constructor, required_atoms=atoms_vertices)
    2378         return self._face_lattice
    2379 
    2380 
     2411
     2412    def faces(self, face_dimension):
     2413        """
     2414        Return the faces of given dimension
     2415
     2416        INPUT:
     2417
     2418        - ``face_dimension`` -- integer.
     2419       
     2420        OUTPUT:
     2421       
     2422        A tuple of
     2423        :class:`~sage.geometry.polyhedron.face.PolyhedronFace`. See
     2424        :mod:`~sage.geometry.polyhedron.face` for details. The order
     2425        random but fixed.
     2426
     2427        EXAMPLES:
     2428
     2429        Here we find the vertex and face indices of the eight three-dimensional
     2430        facets of the four-dimensional hypercube::
     2431
     2432            sage: p = polytopes.n_cube(4)
     2433            sage: p.faces(3)
     2434            (<0,1,2,3,4,5,6,7>, <0,1,2,3,8,9,10,11>, <0,1,4,5,8,9,12,13>,
     2435             <0,2,4,6,8,10,12,14>, <2,3,6,7,10,11,14,15>, <8,9,10,11,12,13,14,15>,
     2436             <4,5,6,7,12,13,14,15>, <1,3,5,7,9,11,13,15>)
     2437
     2438            sage: face = p.faces(3)[0]
     2439            sage: face.ambient_Hrepresentation()
     2440            (An inequality (1, 0, 0, 0) x + 1 >= 0,)
     2441            sage: face.vertices()
     2442            (A vertex at (-1, -1, -1, -1), A vertex at (-1, -1, -1, 1),
     2443             A vertex at (-1, -1, 1, -1), A vertex at (-1, -1, 1, 1),
     2444             A vertex at (-1, 1, -1, -1), A vertex at (-1, 1, -1, 1),
     2445             A vertex at (-1, 1, 1, -1), A vertex at (-1, 1, 1, 1))
     2446
     2447        You can use the
     2448        :meth:`~sage.geometry.polyhedron.representation.PolyhedronRepresentation.index`
     2449        method to enumerate vertices and inequalities::
     2450
     2451            sage: def get_idx(rep): return rep.index()
     2452            sage: map(get_idx, face.ambient_Hrepresentation())
     2453            [4]
     2454            sage: map(get_idx, face.ambient_Vrepresentation())
     2455            [0, 1, 2, 3, 4, 5, 6, 7]
     2456
     2457            sage: [ (map(get_idx, face.ambient_Vrepresentation()), map(get_idx, face.ambient_Hrepresentation()))
     2458            ...     for face in p.faces(3) ]
     2459            [([0, 1, 2, 3, 4, 5, 6, 7], [4]),
     2460             ([0, 1, 2, 3, 8, 9, 10, 11], [5]),
     2461             ([0, 1, 4, 5, 8, 9, 12, 13], [6]),
     2462             ([0, 2, 4, 6, 8, 10, 12, 14], [7]),
     2463             ([2, 3, 6, 7, 10, 11, 14, 15], [2]),
     2464             ([8, 9, 10, 11, 12, 13, 14, 15], [0]),
     2465             ([4, 5, 6, 7, 12, 13, 14, 15], [1]),
     2466             ([1, 3, 5, 7, 9, 11, 13, 15], [3])]
     2467           
     2468        TESTS::
     2469
     2470            sage: pr = Polyhedron(rays = [[1,0,0],[-1,0,0],[0,1,0]], vertices = [[-1,-1,-1]], lines=[(0,0,1)])
     2471            sage: pr.faces(4)
     2472            ()
     2473            sage: pr.faces(3)
     2474            (<0,1,2,3>,)
     2475            sage: pr.faces(2)
     2476            (<0,1,2>,)
     2477            sage: pr.faces(1)
     2478            ()
     2479            sage: pr.faces(0)
     2480            ()
     2481            sage: pr.faces(-1)
     2482            ()
     2483        """
     2484        fl = self.face_lattice().level_sets()
     2485        codim = self.dim() - face_dimension
     2486        index = len(fl) - 1 - codim
     2487        if index>=len(fl) or index<1:
     2488            return tuple()
     2489        return tuple(face.element for face in fl[index])
     2490
     2491    @cached_method
    23812492    def f_vector(self):
    23822493        r"""
    23832494        Return the f-vector.
    23842495
    23852496        OUTPUT:
    2386        
     2497
    23872498        Returns a vector whose ``i``-th entry is the number of
    23882499        ``i``-dimensional faces of the polytope.
    23892500
     
    23942505            sage: p.f_vector()
    23952506            (1, 7, 12, 7, 1)
    23962507        """
    2397         try:
    2398             return self._f_vector
    2399         except AttributeError:
    2400             self._f_vector = vector(ZZ,[len(x) for x in self.face_lattice().level_sets()])
    2401             return self._f_vector
    2402 
    2403 
     2508        return vector(ZZ,[len(x) for x in self.face_lattice().level_sets()])
     2509
     2510    @cached_method
    24042511    def vertex_graph(self):
    24052512        """
    24062513        Return a graph in which the vertices correspond to vertices
     
    24152522            sage: s4.is_eulerian()
    24162523            True
    24172524        """
    2418         try:
    2419             return self._graph
    2420         except AttributeError:
    2421             self._graph = Graph(self.vertex_adjacency_matrix(), loops=True)
    2422             return self._graph
    2423 
     2525        return Graph(self.vertex_adjacency_matrix(), loops=True)
    24242526
    24252527    graph = vertex_graph
    24262528
    2427 
    24282529    def polar(self):
    24292530        """
    2430         Return the polar (dual) polytope.  The original vertices are
    2431         translated so that their barycenter is at the origin, and then
    2432         the vertices are used as the coefficients in the polar inequalities.
     2531        Return the polar (dual) polytope.
     2532
     2533        The original vertices are translated so that their barycenter
     2534        is at the origin, and then the vertices are used as the
     2535        coefficients in the polar inequalities.
    24332536
    24342537        EXAMPLES::
    24352538
    2436             sage: p = Polyhedron(vertices = [[0,0,1],[0,1,0],[1,0,0],[0,0,0],[1,1,1]])
     2539            sage: p = Polyhedron(vertices = [[0,0,1],[0,1,0],[1,0,0],[0,0,0],[1,1,1]], base_ring=QQ)
    24372540            sage: p
    24382541            A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 5 vertices
    24392542            sage: p.polar()
     
    24412544        """
    24422545        assert self.is_compact(), "Not a polytope."
    24432546
    2444         verts = [list(v() - self.center()) for v in self.vertex_generator()]
    2445         return Polyhedron(ieqs=[[1] + list(v) for v in verts],
    2446                           base_ring=self.base_ring())
    2447 
     2547        verts = [list(v.vector() - self.center()) for v in self.vertex_generator()]
     2548        base_ring = self.parent()._coerce_base_ring(self.center().parent().base_ring())
     2549        return Polyhedron(ieqs=[[1] + list(v) for v in verts], base_ring=base_ring)
    24482550
    24492551    def pyramid(self):
    24502552        """
     
    24522554
    24532555        EXAMPLES::
    24542556
    2455             sage: square = polytopes.n_cube(2)
    2456             sage: egyptian_pyramid = square.pyramid()
     2557            sage: square = polytopes.n_cube(2);  square
     2558            A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 4 vertices
     2559            sage: egyptian_pyramid = square.pyramid();  egyptian_pyramid
     2560            A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 5 vertices
    24572561            sage: egyptian_pyramid.n_vertices()
    24582562            5
    24592563            sage: for v in egyptian_pyramid.vertex_generator(): print v
     
    24642568            A vertex at (1, 0, 0)
    24652569        """
    24662570        new_verts = \
    2467             [[0] + list(x) for x in self.Vrep_generator()] + \
     2571            [[0] + x for x in self.Vrep_generator()] + \
    24682572            [[1] + list(self.center())]
    2469 
    2470         return Polyhedron(vertices = new_verts, base_ring=self.field())
    2471 
     2573        return Polyhedron(vertices=new_verts)
    24722574
    24732575    def bipyramid(self):
    24742576        """
     
    24902592             [0, 0, 1, 0],
    24912593             [0, 1, 0, 0],
    24922594             [1, 0, 0, 0]]
    2493        
     2595
    24942596        Now check that bipyramids of cross-polytopes are cross-polytopes::
    24952597
    24962598            sage: q2 = [list(v) for v in polytopes.cross_polytope(4).vertex_generator()]
     
    25032605            [[-1] + list(self.center())]
    25042606        new_rays = [[0] + r for r in self.rays()]
    25052607        new_lines = [[0] + list(l) for l in self.lines()]
    2506         return Polyhedron(vertices=new_verts,
    2507                           rays=new_rays, lines=new_lines, base_ring=self.field())
    2508 
     2608        return Polyhedron(vertices=new_verts, rays=new_rays, lines=new_lines)
    25092609
    25102610    def prism(self):
    25112611        """
     
    25162616            sage: square = polytopes.n_cube(2)
    25172617            sage: cube = square.prism()
    25182618            sage: cube
    2519             A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 8 vertices
     2619            A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices
    25202620            sage: hypercube = cube.prism()
    25212621            sage: hypercube.n_vertices()
    25222622            16
     
    25252625        new_verts.extend( [ [0] + v for v in self.vertices()] )
    25262626        new_verts.extend( [ [1] + v for v in self.vertices()] )
    25272627        new_rays =        [ [0] + r for r in self.rays()]
    2528         new_lines =       [ [0] + list(l) for l in self.lines()]
    2529         return Polyhedron(vertices=new_verts,
    2530                           rays=new_rays, lines=new_lines, base_ring=self.field())
    2531 
     2628        new_lines =       [ [0] + l for l in self.lines()]
     2629        return Polyhedron(vertices=new_verts, rays=new_rays, lines=new_lines,
     2630                          base_ring=self.base_ring())
    25322631
    25332632    def projection(self):
    25342633        """
     
    25452644        self.projection = Projection(self)
    25462645        return self.projection
    25472646
    2548 
    25492647    def render_solid(self, **kwds):
    25502648        """
    25512649        Return a solid rendering of a 2- or 3-d polytope.
     
    25642662            return proj.render_fill_2d(**kwds)
    25652663        raise ValueError, "render_solid is only defined for 2 and 3 dimensional polyhedra."
    25662664
    2567 
    25682665    def render_wireframe(self, **kwds):
    25692666        """
    25702667        For polytopes in 2 or 3 dimensions, return the edges
     
    25842681            return proj.render_outline_2d(**kwds)
    25852682        raise ValueError, "render_wireframe is only defined for 2 and 3 dimensional polyhedra."
    25862683
    2587 
    25882684    def schlegel_projection(self, projection_dir = None, height = 1.1):
    25892685        """
    25902686        Returns a projection object whose transformed coordinates are
     
    26012697        """
    26022698        proj = self.projection()
    26032699        if projection_dir == None:
    2604             v = self.vertices()
    2605             f0 = (self.facial_incidences()[0])[1]
    2606             projection_dir = [sum([v[f0[i]][j]/len(f0) for i in range(len(f0))])
    2607                               for j in range(len(v[0]))]
     2700            vertices = self.vertices()
     2701            facet = self.Hrepresentation(0)
     2702            f0 = [ v.index() for v in facet.incident() ]
     2703            projection_dir = [sum([vertices[f0[i]][j]/len(f0) for i in range(len(f0))])
     2704                              for j in range(self.ambient_dim())]
    26082705        return proj.schlegel(projection_direction = projection_dir, height = height)
    2609        
    26102706
    26112707    def lrs_volume(self, verbose = False):
    26122708        """
     
    26272723            2.0
    26282724
    26292725        REFERENCES:
    2630        
     2726
    26312727             David Avis's lrs program.
    26322728        """
    26332729        if is_package_installed('lrs') != True:
     
    26582754
    26592755        raise ValueError, "lrs did not return a volume"
    26602756
    2661 
    26622757    def contains(self, point):
    26632758        """
    26642759        Test whether the polyhedron contains the given ``point``.
     
    26752770        Boolean.
    26762771
    26772772        EXAMPLES::
    2678        
     2773
    26792774            sage: P = Polyhedron(vertices=[[1,1],[1,-1],[0,0]])
    26802775            sage: P.contains( [1,0] )
    26812776            True
     
    26962791            True
    26972792            sage: ray.contains(['hello', 'kitty'])   # no common ring for coordinates
    26982793            False
    2699            
     2794
    27002795        The empty polyhedron needs extra care, see trac #10238::
    27012796
    27022797            sage: empty = Polyhedron(); empty
    2703             The empty polyhedron in QQ^0
     2798            The empty polyhedron in ZZ^0
    27042799            sage: empty.contains([])
    27052800            False
    27062801            sage: empty.contains([0])               # not a point in QQ^0
    27072802            False
    27082803            sage: full = Polyhedron(vertices=[()]); full
    2709             A 0-dimensional polyhedron in QQ^0 defined as the convex hull of 1 vertex
     2804            A 0-dimensional polyhedron in ZZ^0 defined as the convex hull of 1 vertex
    27102805            sage: full.contains([])
    27112806            True
    27122807            sage: full.contains([0])
     
    27182813            if len(point)>0:
    27192814                return False
    27202815            else:
    2721                 p = vector(self.field(), [])
     2816                p = vector(self.base_ring(), [])
    27222817
    27232818        if len(p)!=self.ambient_dim():
    27242819            return False
    2725        
     2820
    27262821        for H in self.Hrep_generator():
    27272822            if not H.contains(p):
    27282823                return False
    27292824        return True
    27302825
    2731 
    27322826    def interior_contains(self, point):
    27332827        """
    27342828        Test whether the interior of the polyhedron contains the
     
    27382832        :meth:`relative_interior_contains`.
    27392833
    27402834        INPUT:
    2741        
     2835
    27422836        - ``point`` -- coordinates of a point.
    27432837
    27442838        OUTPUT:
    2745        
     2839
    27462840        ``True`` or ``False``.
    27472841
    27482842        EXAMPLES::
    2749        
     2843
    27502844            sage: P = Polyhedron(vertices=[[0,0],[1,1],[1,-1]])
    27512845            sage: P.contains( [1,0] )
    27522846            True
     
    27652859        The empty polyhedron needs extra care, see trac #10238::
    27662860
    27672861            sage: empty = Polyhedron(); empty
    2768             The empty polyhedron in QQ^0
     2862            The empty polyhedron in ZZ^0
    27692863            sage: empty.interior_contains([])
    27702864            False
    27712865        """
     
    27752869            if len(point)>0:
    27762870                return False
    27772871            else:
    2778                 p = vector(self.field(), [])
     2872                p = vector(self.base_ring(), [])
    27792873
    27802874        if len(p)!=self.ambient_dim():
    27812875            return False
    2782        
     2876
    27832877        for H in self.Hrep_generator():
    27842878            if not H.interior_contains(p):
    27852879                return False
    27862880        return True
    27872881
    2788 
    27892882    def relative_interior_contains(self, point):
    27902883        """
    27912884        Test whether the relative interior of the polyhedron
     
    27942887        See also :meth:`contains` and :meth:`interior_contains`.
    27952888
    27962889        INPUT:
    2797        
     2890
    27982891        - ``point`` -- coordinates of a point.
    27992892
    28002893        OUTPUT:
    2801        
     2894
    28022895        ``True`` or ``False``.
    28032896
    28042897        EXAMPLES::
    2805        
     2898
    28062899            sage: P = Polyhedron(vertices=[(1,0), (-1,0)])
    28072900            sage: P.contains( (0,0) )
    28082901            True
     
    28162909        The empty polyhedron needs extra care, see trac #10238::
    28172910
    28182911            sage: empty = Polyhedron(); empty
    2819             The empty polyhedron in QQ^0
     2912            The empty polyhedron in ZZ^0
    28202913            sage: empty.relative_interior_contains([])
    28212914            False
    28222915        """
     
    28262919            if len(point)>0:
    28272920                return False
    28282921            else:
    2829                 p = vector(self.field(), [])
     2922                p = vector(self.base_ring(), [])
    28302923
    28312924        if len(p)!=self.ambient_dim():
    28322925            return False
    2833          
     2926
    28342927        for eq in self.equation_generator():
    28352928            if not eq.contains(p):
    28362929                return False
     
    28442937    def is_simplex(self):
    28452938        r"""
    28462939        Return whether the polyhedron is a simplex.
    2847        
     2940
    28482941        EXAMPLES::
    28492942
    28502943            sage: Polyhedron([(0,0,0), (1,0,0), (0,1,0)]).is_simplex()
     
    28562949        """
    28572950        return self.is_compact() and (self.dim()+1==self.n_vertices())
    28582951
     2952    @cached_method
    28592953    def is_lattice_polytope(self):
    28602954        r"""
    28612955        Return whether the polyhedron is a lattice polytope.
    2862        
     2956
    28632957        OUTPUT:
    28642958
    28652959        ``True`` if the polyhedron is compact and has only integral
    28662960        vertices, ``False`` otherwise.
    2867        
     2961
    28682962        EXAMPLES::
    2869        
     2963
    28702964            sage: polytopes.cross_polytope(3).is_lattice_polytope()
    28712965            True
    28722966            sage: polytopes.regular_polygon(5).is_lattice_polytope()
    28732967            False
    28742968        """
    2875         try:
    2876             return self._is_lattice_polytope
    2877         except AttributeError:
    2878             pass
    2879         self._is_lattice_polytope = self.is_compact() and \
    2880             all(v.is_integral() for v in self.vertex_generator())
    2881         return self._is_lattice_polytope
    2882        
     2969        if not self.is_compact():
     2970            return False
     2971        if self.base_ring() is ZZ:
     2972            return True
     2973        return all(v.is_integral() for v in self.vertex_generator())
     2974
     2975    @cached_method
    28832976    def lattice_polytope(self, envelope=False):
    28842977        r"""
    28852978        Return an encompassing lattice polytope.
    2886        
     2979
    28872980        INPUT:
    28882981
    28892982        - ``envelope`` -- boolean (default: ``False``). If the
     
    29143007        is returned.
    29153008
    29163009        EXAMPLES:
    2917        
     3010
    29183011        First, a polyhedron with integral vertices::
    29193012
    29203013            sage: P = Polyhedron( vertices = [(1, 0), (0, 1), (-1, 0), (0, -1)])
     
    29423035        if not self.is_compact():
    29433036            raise NotImplementedError, 'Only compact lattice polytopes are allowed.'
    29443037
    2945         def nonintegral_error():
    2946             raise ValueError, 'Some vertices are not integral. '+\
    2947                 'You probably want to add the argument '+\
    2948                 '"envelope=True" to compute an enveloping lattice polytope.'
    2949 
    2950         # try to make use of cached values, if possible
    2951         if envelope:
    2952             try:
    2953                 return self._lattice_polytope
    2954             except AttributeError:
    2955                 pass
    2956         else:
    2957             try:
    2958                 assert self._is_lattice_polytope
    2959                 return self._lattice_polytope
    2960             except AttributeError:
    2961                 pass
    2962             except AssertionError:
    2963                 nonintegral_error()
    2964 
    2965         # find the integral vertices
    29663038        try:
    2967             vertices = matrix(ZZ, self.vertices()).transpose()
    2968             self._is_lattice_polytope = True
     3039            vertices = self.vertices_matrix(ZZ)
    29693040        except TypeError:
    2970             self._is_lattice_polytope = False
    2971             if envelope==False: nonintegral_error()
     3041            if envelope==False:
     3042                raise ValueError, 'Some vertices are not integral. '+\
     3043                    'You probably want to add the argument '+\
     3044                    '"envelope=True" to compute an enveloping lattice polytope.'
    29723045            vertices = []
    29733046            for v in self.vertex_generator():
    29743047                vbox = [ set([floor(x),ceil(x)]) for x in v ]
     
    29773050
    29783051        # construct the (enveloping) lattice polytope
    29793052        from sage.geometry.lattice_polytope import LatticePolytope
    2980         self._lattice_polytope = LatticePolytope(vertices)
    2981         return self._lattice_polytope
     3053        return LatticePolytope(vertices)
    29823054
    29833055    def _integral_points_PALP(self):
    29843056        r"""
     
    29873059        This method is for testing purposes and will eventually be removed.
    29883060
    29893061        OUTPUT:
    2990        
     3062
    29913063        The list of integral points in the polyhedron. If the
    29923064        polyhedron is not compact, a ``ValueError`` is raised.
    29933065
    29943066        EXAMPLES::
    2995        
     3067
    29963068            sage: Polyhedron(vertices=[(-1,-1),(1,0),(1,1),(0,1)])._integral_points_PALP()
    29973069            [(-1, -1), (0, 1), (1, 0), (1, 1), (0, 0)]
    29983070            sage: Polyhedron(vertices=[(-1/2,-1/2),(1,0),(1,1),(0,1)]).lattice_polytope(True).points()
     
    30253097
    30263098        - ``integral`` -- Boolean (default: ``False``). Whether to
    30273099          only allow integral coordinates in the bounding box.
    3028        
     3100
    30293101        OUTPUT:
    30303102
    30313103        A pair of tuples ``(box_min, box_max)`` where ``box_min`` are
     
    30463118        box_max = []
    30473119        if self.n_vertices==0:
    30483120            raise ValueError('Empty polytope is not allowed')
     3121        if not self.is_compact():
     3122            raise ValueError('Only polytopes (compact polyhedra) are allowed.')
    30493123        for i in range(0,self.ambient_dim()):
    3050             coords = [ v[i] for v in self.Vrep_generator() ]
     3124            coords = [ v[i] for v in self.vertex_generator() ]
    30513125            max_coord = max(coords)
    30523126            min_coord = min(coords)
    30533127            if integral:
     
    30573131                box_max.append(max_coord)
    30583132                box_min.append(min_coord)
    30593133        return (tuple(box_min), tuple(box_max))
    3060        
     3134
    30613135    def integral_points(self, threshold=100000):
    30623136        r"""
    30633137        Return the integral points in the polyhedron.
     
    30713145          algorith as long as the bounding box is smaller than this.
    30723146
    30733147        OUTPUT:
    3074        
     3148
    30753149        The list of integral points in the polyhedron. If the
    30763150        polyhedron is not compact, a ``ValueError`` is raised.
    30773151
    30783152        EXAMPLES::
    3079        
     3153
    30803154            sage: Polyhedron(vertices=[(-1,-1),(1,0),(1,1),(0,1)]).integral_points()
    30813155            ((-1, -1), (0, 0), (0, 1), (1, 0), (1, 1))
    30823156
     
    31043178
    31053179            sage: v = [(1,0,7,-1), (-2,-2,4,-3), (-1,-1,-1,4), (2,9,0,-5), (-2,-1,5,1)]
    31063180            sage: simplex = Polyhedron(v); simplex
    3107             A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 5 vertices
     3181            A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 5 vertices
    31083182            sage: len(simplex.integral_points())
    31093183            49
    31103184
     
    31533227            points.update(new_points)
    31543228        # assert all(self.contains(p) for p in points)   # slow
    31553229        return tuple(points)
    3156    
     3230
     3231    @cached_method
    31573232    def combinatorial_automorphism_group(self):
    31583233        """
    31593234        Computes the combinatorial automorphism group of the vertex
     
    31723247        chosen to be shifted by ``+1``. That is, ``i`` in the
    31733248        permutation group corresponds to the V-representation object
    31743249        ``self.Vrepresentation(i-1)``.
    3175        
     3250
    31763251        EXAMPLES::
    3177        
     3252
    31783253            sage: quadrangle = Polyhedron(vertices=[(0,0),(1,0),(0,1),(2,3)])
    31793254            sage: quadrangle.combinatorial_automorphism_group()
    31803255            Permutation Group with generators [(2,3), (1,2)(3,4)]
     
    31883263            sage: P.combinatorial_automorphism_group()
    31893264            Permutation Group with generators [(3,4)]
    31903265        """
    3191         if '_combinatorial_automorphism_group' in self.__dict__:
    3192             return self._combinatorial_automorphism_group
    3193 
    31943266        from sage.groups.perm_gps.permgroup import PermutationGroup
    3195 
    31963267        G = Graph()
    31973268        for edge in self.vertex_graph().edges():
    31983269            i = edge[0]
     
    32103281        self._combinatorial_automorphism_group = group
    32113282        return group
    32123283
    3213 
    32143284    def _affine_coordinates(self, Vrep_object):
    32153285        r"""
    32163286        Return affine coordinates for a V-representation object.
    3217        
     3287
    32183288        INPUT:
    32193289
    32203290        - ``v`` -- a V-representation object or any iterable
     
    32283298        A ``self.dim()``-dimensional coordinate vector. It contains
    32293299        the coordinates of ``v`` in an arbitrary but fixed basis for
    32303300        the affine span of the polyhedron.
    3231        
     3301
    32323302        EXAMPLES::
    3233        
     3303
    32343304            sage: P = Polyhedron(rays=[(1,0,0),(0,1,0)])
    32353305            sage: P._affine_coordinates( (-1,-2,-3) )
    32363306            (-1, -2)
     
    32443314                v_list = [ v - origin for v in v_list ]
    32453315            coordinates = matrix(v_list)
    32463316            self._affine_coordinates_pivots = coordinates.pivots()
    3247    
     3317
    32483318        v = list(Vrep_object)
    32493319        if len(v) != self.ambient_dim():
    32503320            raise ValueError('Incorrect dimension: '+str(v))
    32513321
    3252         return vector(self.field(), [ v[i] for i in self._affine_coordinates_pivots ])
    3253        
    3254 
     3322        return vector(self.base_ring(), [ v[i] for i in self._affine_coordinates_pivots ])
     3323
     3324    @cached_method
    32553325    def restricted_automorphism_group(self):
    32563326        r"""
    32573327        Return the restricted automorphism group.
     
    32693339        generators with line generators.
    32703340
    32713341        For example, take the first quadrant
    3272        
     3342
    32733343        .. MATH::
    3274        
     3344
    32753345            Q = \Big\{ (x,y) \Big| x\geq 0,\; y\geq0 \Big\}
    32763346            \subset \QQ^2
    3277            
     3347
    32783348        Then the linear automorphism group is
    3279        
     3349
    32803350        .. MATH::
    32813351
    32823352            \mathrm{Aut}(Q) =
     
    33203390        A :class:`PermutationGroup<sage.groups.perm_gps.permgroup.PermutationGroup_generic>`
    33213391        that is isomorphic to the restricted automorphism group is
    33223392        returned.
    3323        
     3393
    33243394        Note that in Sage, permutation groups always act on positive
    33253395        integers while ``self.Vrepresentation()`` is indexed by
    33263396        nonnegative integers. The indexing of the permutation group is
     
    33883458
    33893459        Floating-point computations are supported with a simple fuzzy
    33903460        zero implementation::
    3391        
     3461
    33923462            sage: P = Polyhedron(vertices=[(1.0/3.0,0,0),(0,1.0/3.0,0),(0,0,1.0/3.0)], base_ring=RDF)
    33933463            sage: P.restricted_automorphism_group()
    33943464            Permutation Group with generators [(2,3), (1,2)]
     
    33993469            sage: p.restricted_automorphism_group()
    34003470            Permutation Group with generators [(2,3)]
    34013471        """
    3402         if '_restricted_automorphism_group' in self.__dict__:
    3403             return self._restricted_automorphism_group
    3404 
    34053472        from sage.groups.perm_gps.permgroup import PermutationGroup
    34063473
    3407         if self.field() is QQ:
     3474        if self.base_ring() is ZZ or self.base_ring() is QQ:
    34083475            def rational_approximation(c):
    34093476                return c
    34103477
    3411         else:  # self.field() is RDF
     3478        elif self.base_ring() is RDF:
    34123479            c_list = []
    34133480            def rational_approximation(c):
    34143481                # Implementation detail: Return unique integer if two
     
    34203487                        return i
    34213488                c_list.append(c)
    34223489                return len(c_list)-1
    3423        
     3490
    34243491        # The algorithm identifies the restricted automorphism group
    34253492        # with the automorphism group of a edge-colored graph. The
    34263493        # nodes of the graph are the V-representation objects. If all
     
    34773544
    34783545
    34793546
    3480 
    3481 
    3482 
    3483 #########################################################################
    3484 class PolyhedronFace_base(SageObject):
    3485     r"""
    3486     A face of a polyhedron.
    3487    
    3488     This class is for use in
    3489     :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.face_lattice`.
    3490 
    3491     INPUT:
    3492 
    3493     No checking is performed whether the H/V-representation indices
    3494     actually determine a face of the polyhedron. You should not
    3495     manually create :class:`PolyhedronFace_base` objects unless you know
    3496     what you are doing.
    3497 
    3498     OUTPUT:
    3499 
    3500     A :class:`PolyhedronFace_base`.
    3501 
    3502     EXAMPLES::
    3503 
    3504         sage: octahedron = polytopes.cross_polytope(3)
    3505         sage: inequality = octahedron.Hrepresentation(2)
    3506         sage: face_h = tuple([ inequality ])
    3507         sage: face_v = tuple( inequality.incident() )
    3508         sage: face_h_indices = [ h.index() for h in face_h ]
    3509         sage: face_v_indices = [ v.index() for v in face_v ]
    3510         sage: from sage.geometry.polyhedron.base import PolyhedronFace_base
    3511         sage: face = PolyhedronFace_base(octahedron, face_v_indices, face_h_indices)
    3512         sage: face
    3513         <0,1,2>
    3514         sage: face.dim()
    3515         2
    3516         sage: face.ambient_Hrepresentation()
    3517         (An inequality (1, 1, 1) x + 1 >= 0,)
    3518         sage: face.ambient_Vrepresentation()
    3519         (A vertex at (-1, 0, 0), A vertex at (0, -1, 0), A vertex at (0, 0, -1))
    3520     """
    3521 
    3522     def __init__(self, polyhedron, V_indices, H_indices):
    3523         r"""
    3524         The constructor.
    3525 
    3526         See :class:`PolyhedronFace_base` for more information.
    3527 
    3528         INPUT:
    3529 
    3530         - ``polyhedron`` -- a :class:`Polyhedron`. The ambient
    3531           polyhedron.
    3532 
    3533         - ``V_indices`` -- list of integers. The indices of the
    3534           face-spanning V-representation objects in the ambient
    3535           polyhedron.
    3536 
    3537         - ``H_indices`` -- list of integers. The indices of the
    3538           H-representation objects of the ambient polyhedron that are
    3539           saturated on the face.
    3540        
    3541         TESTS::
    3542 
    3543             sage: from sage.geometry.polyhedron.base import PolyhedronFace_base
    3544             sage: PolyhedronFace_base(Polyhedron(), [], [])   # indirect doctest
    3545             <>
    3546         """
    3547         self._polyhedron = polyhedron
    3548         self._ambient_Vrepresentation_indices = tuple(V_indices)
    3549         self._ambient_Hrepresentation_indices = tuple(H_indices)
    3550         self._ambient_Vrepresentation = tuple( polyhedron.Vrepresentation(i) for i in V_indices )
    3551         self._ambient_Hrepresentation = tuple( polyhedron.Hrepresentation(i) for i in H_indices )
    3552         # self._Vrepresentation =
    3553         # self._Hrepresentation =
    3554        
    3555 
    3556     def ambient_Hrepresentation(self, index=None):
    3557         r"""
    3558         Return the H-representation objects of the ambient polytope
    3559         defining the face.
    3560        
    3561         INPUT:
    3562        
    3563         - ``index`` -- optional. Either an integer or ``None``
    3564           (default).
    3565 
    3566         OUTPUT:
    3567        
    3568         If the optional argument is not present, a tuple of
    3569         H-representation objects. Each entry is either an inequality
    3570         or an equation.
    3571 
    3572         If the optional integer ``index`` is specified, the
    3573         ``index``-th element of the tuple is returned.
    3574 
    3575         EXAMPLES::
    3576          
    3577             sage: square = polytopes.n_cube(2)
    3578             sage: for fl in square.face_lattice():
    3579             ...       print fl.element.ambient_Hrepresentation()
    3580             ...
    3581             (An inequality (1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0,
    3582              An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0)
    3583             (An inequality (1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0)
    3584             (An inequality (1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0)
    3585             (An inequality (0, 1) x + 1 >= 0, An inequality (-1, 0) x + 1 >= 0)
    3586             (An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0)
    3587             (An inequality (1, 0) x + 1 >= 0,)
    3588             (An inequality (0, 1) x + 1 >= 0,)
    3589             (An inequality (-1, 0) x + 1 >= 0,)
    3590             (An inequality (0, -1) x + 1 >= 0,)
    3591             ()
    3592         """
    3593         if index==None:
    3594             return self._ambient_Hrepresentation
    3595         else:
    3596             return self._ambient_Hrepresentation[index]
    3597        
    3598 
    3599     def ambient_Vrepresentation(self, index=None):
    3600         r"""
    3601         Return the V-representation objects of the ambient polytope
    3602         defining the face.
    3603 
    3604         INPUT:
    3605        
    3606         - ``index`` -- optional. Either an integer or ``None``
    3607           (default).
    3608 
    3609         OUTPUT:
    3610        
    3611         If the optional argument is not present, a tuple of
    3612         V-representation objects. Each entry is either a vertex, a
    3613         ray, or a line.
    3614 
    3615         If the optional integer ``index`` is specified, the
    3616         ``index``-th element of the tuple is returned.
    3617        
    3618         EXAMPLES::
    3619          
    3620             sage: square = polytopes.n_cube(2)
    3621             sage: for fl in square.face_lattice():
    3622             ...       print fl.element.ambient_Vrepresentation()
    3623             ...
    3624             ()
    3625             (A vertex at (-1, -1),)
    3626             (A vertex at (-1, 1),)
    3627             (A vertex at (1, -1),)
    3628             (A vertex at (1, 1),)
    3629             (A vertex at (-1, -1), A vertex at (-1, 1))
    3630             (A vertex at (-1, -1), A vertex at (1, -1))
    3631             (A vertex at (1, -1), A vertex at (1, 1))
    3632             (A vertex at (-1, 1), A vertex at (1, 1))
    3633             (A vertex at (-1, -1), A vertex at (-1, 1),
    3634              A vertex at (1, -1), A vertex at (1, 1))
    3635         """
    3636         if index==None:
    3637             return self._ambient_Vrepresentation
    3638         else:
    3639             return self._ambient_Vrepresentation[index]
    3640 
    3641 
    3642     def n_ambient_Hrepresentation(self):
    3643         """
    3644         Return the number of objects that make up the ambient
    3645         H-representation of the polyhedron.
    3646 
    3647         See also :meth:`ambient_Hrepresentation`.
    3648 
    3649         OUTPUT:
    3650 
    3651         Integer.
    3652 
    3653         EXAMPLES::
    3654 
    3655             sage: p = polytopes.cross_polytope(4)
    3656             sage: face = p.face_lattice()[10].element
    3657             sage: face
    3658             <0,2>
    3659             sage: face.ambient_Hrepresentation()
    3660             (An inequality (1, -1, 1, -1) x + 1 >= 0,
    3661              An inequality (1, 1, 1, 1) x + 1 >= 0,
    3662              An inequality (1, 1, 1, -1) x + 1 >= 0,
    3663              An inequality (1, -1, 1, 1) x + 1 >= 0)
    3664             sage: face.n_ambient_Hrepresentation()
    3665             4
    3666         """
    3667         return len(self._ambient_Hrepresentation)
    3668 
    3669 
    3670     def n_ambient_Vrepresentation(self):
    3671         """
    3672         Return the number of objects that make up the ambient
    3673         V-representation of the polyhedron.
    3674 
    3675         See also :meth:`ambient_Vrepresentation`.
    3676 
    3677         OUTPUT:
    3678 
    3679         Integer.
    3680 
    3681         EXAMPLES::
    3682 
    3683             sage: p = polytopes.cross_polytope(4)
    3684             sage: face = p.face_lattice()[10].element
    3685             sage: face
    3686             <0,2>
    3687             sage: face.ambient_Vrepresentation()
    3688             (A vertex at (-1, 0, 0, 0), A vertex at (0, 0, -1, 0))
    3689             sage: face.n_ambient_Vrepresentation()
    3690             2
    3691         """
    3692         return len(self._ambient_Vrepresentation)
    3693 
    3694 
    3695     def dim(self):
    3696         """
    3697         Return the dimension of the face.
    3698        
    3699         OUTPUT:
    3700        
    3701         Integer.
    3702        
    3703         EXAMPLES::
    3704 
    3705             sage: fl = polytopes.dodecahedron().face_lattice()
    3706             sage: [ x.element.dim() for x in fl ]
    3707             [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    3708               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    3709               1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3]
    3710         """
    3711         if '_dim' in self.__dict__:
    3712             return self._dim
    3713 
    3714         if self.n_ambient_Vrepresentation()==0:
    3715             self._dim = -1
    3716         else:
    3717             origin = vector(self.ambient_Vrepresentation(0))
    3718             v_list = [ vector(v)-origin for v in self.ambient_Vrepresentation() ]
    3719             self._dim = matrix(v_list).rank()
    3720         return self._dim
    3721 
    3722 
    3723     def _repr_(self):
    3724         r"""
    3725         Return a string representation.
    3726 
    3727         OUTPUT:
    3728 
    3729         A string listing the V-representation indices of the face.
    3730 
    3731         EXAMPLES::
    3732 
    3733             sage: square = polytopes.n_cube(2)
    3734             sage: a_face = list( square.face_lattice() )[8].element
    3735             sage: a_face.__repr__()
    3736             '<1,3>'
    3737         """
    3738         s = '<'
    3739         s += ','.join([ str(v.index()) for v in self.ambient_Vrepresentation() ])
    3740         s += '>'
    3741         return s
    3742 
  • sage/geometry/polyhedron/base_QQ.py

    diff --git a/sage/geometry/polyhedron/base_QQ.py b/sage/geometry/polyhedron/base_QQ.py
    a b  
    1111    Base class for Polyhedra over `\QQ`
    1212
    1313    TESTS::
    14      
     14
    1515        sage: p = Polyhedron([(0,0)], base_ring=QQ);  p
    1616        A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex
    1717        sage: TestSuite(p).run()
     
    1919    def _is_zero(self, x):
    2020        """
    2121        Test whether ``x`` is zero.
    22        
     22
    2323        INPUT:
    2424
    2525        - ``x`` -- a number in the base ring.
     
    2929        Boolean.
    3030
    3131        EXAMPLES::
    32          
     32
    3333            sage: p = Polyhedron([(0,0)], base_ring=QQ)
    3434            sage: p._is_zero(0)
    3535            True
     
    4141    def _is_nonneg(self, x):
    4242        """
    4343        Test whether ``x`` is nonnegative.
    44        
     44
    4545        INPUT:
    4646
    4747        - ``x`` -- a number in the base ring.
     
    5151        Boolean.
    5252
    5353        EXAMPLES::
    54          
     54
    5555            sage: p = Polyhedron([(0,0)], base_ring=QQ)
    5656            sage: p._is_nonneg(1)
    5757            True
     
    6363    def _is_positive(self, x):
    6464        """
    6565        Test whether ``x`` is positive.
    66        
     66
    6767        INPUT:
    6868
    6969        - ``x`` -- a number in the base ring.
     
    7373        Boolean.
    7474
    7575        EXAMPLES::
    76          
     76
    7777            sage: p = Polyhedron([(0,0)], base_ring=QQ)
    7878            sage: p._is_positive(1)
    7979            True
     
    8383        return x>0
    8484
    8585    _base_ring = QQ
    86      
    87      
    88      
     86
  • sage/geometry/polyhedron/base_RDF.py

    diff --git a/sage/geometry/polyhedron/base_RDF.py b/sage/geometry/polyhedron/base_RDF.py
    a b  
    1212    Base class for polyhedra over ``RDF``.
    1313
    1414    TESTS::
    15      
     15
    1616        sage: p = Polyhedron([(0,0)], base_ring=RDF);  p
    1717        A 0-dimensional polyhedron in RDF^2 defined as the convex hull of 1 vertex
    1818        sage: TestSuite(p).run()
     
    2222    def _is_zero(self, x):
    2323        """
    2424        Test whether ``x`` is zero.
    25        
     25
    2626        INPUT:
    2727
    2828        - ``x`` -- a number in the base ring.
     
    3232        Boolean.
    3333
    3434        EXAMPLES::
    35          
     35
    3636            sage: p = Polyhedron([(0,0)], base_ring=RDF)
    3737            sage: p._is_zero(0)
    3838            True
     
    4949    def _is_nonneg(self, x):
    5050        """
    5151        Test whether ``x`` is nonnegative.
    52        
     52
    5353        INPUT:
    5454
    5555        - ``x`` -- a number in the base ring.
     
    5959        Boolean.
    6060
    6161        EXAMPLES::
    62          
     62
    6363            sage: p = Polyhedron([(0,0)], base_ring=RDF)
    6464            sage: p._is_nonneg(1)
    6565            True
     
    7676    def _is_positive(self, x):
    7777        """
    7878        Test whether ``x`` is positive.
    79        
     79
    8080        INPUT:
    8181
    8282        - ``x`` -- a number in the base ring.
     
    8686        Boolean.
    8787
    8888        EXAMPLES::
    89          
     89
    9090            sage: p = Polyhedron([(0,0)], base_ring=RDF)
    9191            sage: p._is_positive(1)
    9292            True
     
    9999            True
    100100        """
    101101        return x>=-1e-6
    102      
     102
    103103    _base_ring = RDF
    104104
  • new file sage/geometry/polyhedron/base_ZZ.py

    diff --git a/sage/geometry/polyhedron/base_ZZ.py b/sage/geometry/polyhedron/base_ZZ.py
    new file mode 100644
    - +  
     1r"""
     2Base class for polyhedra over `\ZZ`
     3"""
     4
     5########################################################################
     6#       Copyright (C) 2011 Volker Braun <vbraun.name@gmail.com>
     7#
     8#  Distributed under the terms of the GNU General Public License (GPL)
     9#
     10#                  http://www.gnu.org/licenses/
     11########################################################################
     12
     13
     14
     15from sage.rings.all import ZZ, QQ
     16from sage.misc.all import cached_method
     17from sage.matrix.constructor import matrix
     18
     19from constructor import Polyhedron
     20from base import Polyhedron_base
     21
     22
     23
     24#########################################################################
     25class Polyhedron_ZZ(Polyhedron_base):
     26    """
     27    Base class for Polyhedra over `\ZZ`
     28
     29    TESTS::
     30
     31        sage: p = Polyhedron([(0,0)], base_ring=ZZ);  p
     32        A 0-dimensional polyhedron in ZZ^2 defined as the convex hull of 1 vertex
     33        sage: TestSuite(p).run(skip='_test_pickling')
     34    """
     35    def _is_zero(self, x):
     36        """
     37        Test whether ``x`` is zero.
     38
     39        INPUT:
     40
     41        - ``x`` -- a number in the base ring.
     42
     43        OUTPUT:
     44
     45        Boolean.
     46
     47        EXAMPLES::
     48
     49            sage: p = Polyhedron([(0,0)], base_ring=ZZ)
     50            sage: p._is_zero(0)
     51            True
     52            sage: p._is_zero(1/100000)
     53            False
     54        """
     55        return x==0
     56
     57    def _is_nonneg(self, x):
     58        """
     59        Test whether ``x`` is nonnegative.
     60
     61        INPUT:
     62
     63        - ``x`` -- a number in the base ring.
     64
     65        OUTPUT:
     66
     67        Boolean.
     68
     69        EXAMPLES::
     70
     71            sage: p = Polyhedron([(0,0)], base_ring=ZZ)
     72            sage: p._is_nonneg(1)
     73            True
     74            sage: p._is_nonneg(-1/100000)
     75            False
     76        """
     77        return x>=0
     78
     79    def _is_positive(self, x):
     80        """
     81        Test whether ``x`` is positive.
     82
     83        INPUT:
     84
     85        - ``x`` -- a number in the base ring.
     86
     87        OUTPUT:
     88
     89        Boolean.
     90
     91        EXAMPLES::
     92
     93            sage: p = Polyhedron([(0,0)], base_ring=ZZ)
     94            sage: p._is_positive(1)
     95            True
     96            sage: p._is_positive(0)
     97            False
     98        """
     99        return x>0
     100
     101    _base_ring = ZZ
     102
     103    def is_lattice_polytope(self):
     104        r"""
     105        Return whether the polyhedron is a lattice polytope.
     106
     107        OUTPUT:
     108
     109        ``True`` if the polyhedron is compact and has only integral
     110        vertices, ``False`` otherwise.
     111
     112        EXAMPLES::
     113
     114            sage: polytopes.cross_polytope(3).is_lattice_polytope()
     115            True
     116            sage: polytopes.regular_polygon(5).is_lattice_polytope()
     117            False
     118        """
     119        return True
     120
     121    @cached_method
     122    def polar(self):
     123        """
     124        Return the polar (dual) polytope.
     125
     126        The polytope must have the IP-property (see
     127        :meth:`has_IP_property`), that is, the origin must be an
     128        interior point. In particular, it must be full-dimensional.
     129
     130        OUTPUT:
     131
     132        The polytope whose vertices are the coefficient vectors of the
     133        inequalities of ``self`` with inhomogeneous term normalized to
     134        unity.
     135
     136        EXAMPLES::
     137
     138            sage: p = Polyhedron(vertices=[(1,0,0),(0,1,0),(0,0,1),(-1,-1,-1)], base_ring=ZZ)
     139            sage: p.polar()
     140            A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices
     141            sage: type(_)
     142            <class 'sage.geometry.polyhedron.backend_ppl.Polyhedra_ZZ_ppl_with_category.element_class'>
     143            sage: p.polar().base_ring()
     144            Integer Ring
     145        """
     146        if not self.has_IP_property():
     147            raise ValueError('The polytope must have the IP property.')
     148
     149        vertices = [ ieq.A()/ieq.b() for
     150                     ieq in self.inequality_generator() ]
     151        if all( all(v_i in ZZ for v_i in v) for v in vertices):
     152            return Polyhedron(vertices=vertices, base_ring=ZZ)
     153        else:
     154            return Polyhedron(vertices=vertices, base_ring=QQ)
     155
     156    @cached_method
     157    def is_reflexive(self):
     158        """
     159        EXAMPLES::
     160
     161            sage: p = Polyhedron(vertices=[(1,0,0),(0,1,0),(0,0,1),(-1,-1,-1)], base_ring=ZZ)
     162            sage: p.is_reflexive()
     163            True
     164        """
     165        return self.polar().is_lattice_polytope()
     166
     167    @cached_method
     168    def has_IP_property(self):
     169        """
     170        Test whether the polyhedron has the IP property.
     171
     172        The IP (interior point) property means that
     173
     174        * ``self`` is compact (a polytope).
     175
     176        * ``self`` contains the origin as an interior point.
     177
     178        This implies that
     179
     180        * ``self`` is full-dimensional.
     181
     182        * The dual polyhedron is again a polytope (that is, a compact
     183          polyhedron), though not necessarily a lattice polytope.
     184
     185        EXAMPLES::
     186
     187            sage: Polyhedron([(1,1),(1,0),(0,1)], base_ring=ZZ).has_IP_property()
     188            False
     189            sage: Polyhedron([(0,0),(1,0),(0,1)], base_ring=ZZ).has_IP_property()
     190            False
     191            sage: Polyhedron([(-1,-1),(1,0),(0,1)], base_ring=ZZ).has_IP_property()
     192            True
     193
     194        REFERENCES:
     195
     196        ..  [PALP]
     197            Maximilian Kreuzer, Harald Skarke:
     198            "PALP: A Package for Analyzing Lattice Polytopes
     199            with Applications to Toric Geometry"
     200            Comput.Phys.Commun. 157 (2004) 87-106
     201            http://arxiv.org/abs/math/0204356
     202        """
     203        return self.is_compact() and self.interior_contains(self.ambient_space().zero())
     204
     205    def fibration_generator(self, dim):
     206        """
     207        Generate the lattice polytope fibrations.
     208
     209        For the purposes of this function, a lattice polytope fiber is
     210        a sub-lattice polytope. Projecting the plane spanned by the
     211        subpolytope to a point yields another lattice polytope, the
     212        base of the fibration.
     213
     214        INPUT:
     215
     216        - ``dim`` -- integer. The dimension of the lattice polytope
     217          fiber.
     218
     219        OUTPUT:
     220
     221        A generator yielding the distinct lattice polytope fibers of
     222        given dimension.
     223
     224        EXAMPLES::
     225
     226            sage: P = Polyhedron(toric_varieties.P4_11169().fan().rays(), base_ring=ZZ)
     227            sage: list( P.fibration_generator(2) )
     228            [A 2-dimensional polyhedron in ZZ^4 defined as the convex hull of 3 vertices]
     229        """
     230        from sage.combinat.combinat import combinations_iterator
     231        if not self.is_compact():
     232            raise ValueError('Only polytopes (compact polyhedra) are allowed.')
     233
     234        nonzero_points = [p for p in self.integral_points() if not p.is_zero()]
     235        origin = [[0]*self.ambient_dim()]
     236        fibers = set()
     237        parent = self.parent()
     238
     239        for points in combinations_iterator(nonzero_points, dim):
     240                plane = parent.element_class(parent, [origin,[],points], None)
     241                if plane.dim() != dim:
     242                    continue
     243                fiber = self.intersection(plane)
     244                if fiber.base_ring() is not ZZ:
     245                    continue
     246                fiber_vertices = tuple(sorted(tuple(v) for v in fiber.vertex_generator()))
     247                if fiber_vertices not in fibers:
     248                    yield fiber
     249                    fibers.update([fiber_vertices])
     250                plane.delete()
     251
  • sage/geometry/polyhedron/cdd_file_format.py

    diff --git a/sage/geometry/polyhedron/cdd_file_format.py b/sage/geometry/polyhedron/cdd_file_format.py
    a b  
    2222    Return a string containing the V-representation in cddlib's ext format.
    2323
    2424    NOTE:
    25        
     25
    2626    If there is no vertex given, then the origin will be implicitly
    2727    added. You cannot write the empty V-representation (which cdd
    2828    would refuse to process).
  • sage/geometry/polyhedron/constructor.py

    diff --git a/sage/geometry/polyhedron/constructor.py b/sage/geometry/polyhedron/constructor.py
    a b  
    1212    finite number of
    1313
    1414        * linear inequalities `A \vec{x} + b \geq 0`, and
    15         * linear equations  `C \vec{x} + d \geq 0`.
     15        * linear equations  `C \vec{x} + d = 0`.
    1616
    1717
    1818**V(ertex)-representation**
     
    2121    polyhedron is then the Minkowski sum
    2222
    2323    .. MATH::
    24    
     24
    2525        P = \text{conv}\{v_1,\dots,v_k\} +
    2626        \sum_{i=1}^m \RR_+ r_i +
    2727        \sum_{j=1}^n \RR \ell_j
    2828
    2929    where
    30        
     30
    3131        * `v_1`, `\dots`, `v_k` are a finite number of vertices,
    3232        * `r_1`, `\dots`, `r_m` are generators of rays,
    3333        * and `\ell_1`, `\dots`, `\ell_n` are generators of full lines.
     
    3939
    4040    sage: trunc_quadr = Polyhedron(vertices=[[1,0],[0,1]], rays=[[1,0],[0,1]])
    4141    sage: trunc_quadr
    42     A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 2 rays
     42    A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices and 2 rays
    4343    sage: v = trunc_quadr.vertex_generator().next()  # the first vertex in the internal enumeration
    4444    sage: v
    4545    A vertex at (0, 1)
     
    5656    sage: type(v)
    5757    <class 'sage.geometry.polyhedron.representation.Vertex'>
    5858    sage: type( v() )
    59     <type 'sage.modules.vector_rational_dense.Vector_rational_dense'>
     59    <type 'sage.modules.vector_integer_dense.Vector_integer_dense'>
    6060    sage: v.polyhedron()
    61     A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 2 rays
     61    A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices and 2 rays
    6262    sage: r = trunc_quadr.ray_generator().next()
    6363    sage: r
    6464    A ray in the direction (0, 1)
     
    105105from sage.rings.all import QQ, ZZ, RDF
    106106from sage.misc.decorators import rename_keyword
    107107
    108 from misc import (
    109     _set_to_None_if_empty, _set_to_empty_if_None,
    110     _common_length_of )
     108from misc import _make_listlist, _common_length_of
    111109
    112110
    113111
    114        
     112
    115113
    116114
    117115#########################################################################
    118116@rename_keyword(deprecation=11634, field='base_ring')
    119117def Polyhedron(vertices=None, rays=None, lines=None,
    120118               ieqs=None, eqns=None,
    121                base_ring=QQ, minimize=True, verbose=False,
     119               ambient_dim=None, base_ring=None, minimize=True, verbose=False,
    122120               backend=None):
    123121    """
    124122    Construct a polyhedron object.
     
    131129    INPUT:
    132130
    133131    - ``vertices`` -- list of point. Each point can be specified as
    134       any iterable container of ``base_ring`` elements.
    135        
     132      any iterable container of ``base_ring`` elements. If ``rays`` or
     133      ``lines`` are specified but no ``vertices``, the origin is
     134      taken to be the single vertex.
     135
    136136    - ``rays`` -- list of rays. Each ray can be specified as any
    137137      iterable container of ``base_ring`` elements.
    138        
     138
    139139    - ``lines`` -- list of lines. Each line can be specified as any
    140140      iterable container of ``base_ring`` elements.
    141141
     
    151151      used. Floating point arithmetic is faster but might give the
    152152      wrong result for degenerate input.
    153153
     154    - ``ambient_dim`` -- integer. The ambient space dimension. Usually
     155      can be figured out automatically from the H/Vrepresentation
     156      dimensions.
     157
    154158    - ``backend`` -- string or ``None`` (default). The backend to use. Valid choices are
    155159
    156       * ``'cddr'``: cdd (:mod:`~sage.geometry.polyhedron.backend_cdd`)
    157         with rational coefficients
     160      * ``'cdd'``: use cdd
     161        (:mod:`~sage.geometry.polyhedron.backend_cdd`) with `\QQ` or
     162        `\RDF` coefficients depending on ``base_ring``.
    158163
    159       * ``'cddf'``: cdd with floating-point coefficients
    160164
    161165      * ``'ppl'``: use ppl
    162         (:mod:`~sage.geometry.polyhedron.backend_ppl`) with `\QQ`
    163         coefficients.
     166        (:mod:`~sage.geometry.polyhedron.backend_ppl`) with `\ZZ` or
     167        `\QQ` coefficients depending on ``base_ring``.
    164168
    165169    Some backends support further optional arguments:
    166170
     
    215219      * The inequality `e+b \geq c+d`
    216220      * The inequality `e+c \geq b+d`
    217221      * The equation `a+b+c+d+e+f = 31`
    218      
     222
    219223    ::
    220224
    221225        sage: positive_coords = Polyhedron(ieqs=[
    222226        ...       [0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0],
    223227        ...       [0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 0, 1]])
    224         sage: P = Polyhedron(ieqs=positive_coords.inequalities() + [
    225         ...       [0,0,1,-1,-1,1,0], [0,0,-1,1,-1,1,0]], eqns=[[-31,1,1,1,1,1,1]])
     228        sage: P = Polyhedron(ieqs=positive_coords.inequalities() + (
     229        ...       [0,0,1,-1,-1,1,0], [0,0,-1,1,-1,1,0]), eqns=[[-31,1,1,1,1,1,1]])
    226230        sage: P
    227231        A 5-dimensional polyhedron in QQ^6 defined as the convex hull of 7 vertices
    228232        sage: P.dim()
     
    234238         A vertex at (0, 0, 0, 31/2, 31/2, 0))
    235239
    236240    .. NOTE::
    237    
     241
    238242      * Once constructed, a ``Polyhedron`` object is immutable.
    239243      * Although the option ``field=RDF`` allows numerical data to
    240244        be used, it might not give the right answer for degenerate
     
    242246        setting of cdd.
    243247    """
    244248    # Clean up the arguments
    245     vertices = _set_to_None_if_empty(vertices)
    246     rays     = _set_to_None_if_empty(rays)
    247     lines    = _set_to_None_if_empty(lines)
    248     ieqs     = _set_to_None_if_empty(ieqs)
    249     eqns     = _set_to_None_if_empty(eqns)
     249    vertices = _make_listlist(vertices)
     250    rays     = _make_listlist(rays)
     251    lines    = _make_listlist(lines)
     252    ieqs     = _make_listlist(ieqs)
     253    eqns     = _make_listlist(eqns)
    250254
    251     got_Vrep = (vertices is not None or rays is not None or lines is not None)
    252     got_Hrep = (ieqs is not None or eqns is not None)
    253    
     255    got_Vrep = (len(vertices+rays+lines) > 0)
     256    got_Hrep = (len(ieqs+eqns) > 0)
     257
    254258    if got_Vrep and got_Hrep:
    255259        raise ValueError('You cannot specify both H- and V-representation.')
    256260    elif got_Vrep:
    257         vertices = _set_to_empty_if_None(vertices)
    258         rays     = _set_to_empty_if_None(rays)
    259         lines    = _set_to_empty_if_None(lines)
    260         Vrep = [vertices, rays, lines]
    261         Hrep = None
    262         ambient_dim = _common_length_of(*Vrep)[1]
     261        deduced_ambient_dim = _common_length_of(vertices, rays, lines)[1]
    263262    elif got_Hrep:
    264         ieqs = _set_to_empty_if_None(ieqs)
    265         eqns = _set_to_empty_if_None(eqns)
    266         Vrep = None
    267         Hrep = [ieqs, eqns]
    268         ambient_dim = _common_length_of(*Hrep)[1] - 1
     263        deduced_ambient_dim = _common_length_of(ieqs, eqns)[1] - 1
    269264    else:
    270         Vrep = None
    271         Hrep = None
    272         ambient_dim = 0
     265        if ambient_dim is None:
     266            deduced_ambient_dim = 0
     267        else:
     268            deduced_ambient_dim = ambient_dim
     269        if base_ring is None:
     270            base_ring = ZZ
    273271
    274     if backend is not None:
    275         if backend=='ppl':
    276             from backend_ppl import Polyhedron_QQ_ppl
    277             return Polyhedron_QQ_ppl(ambient_dim, Vrep, Hrep, minimize=minimize)
    278         if backend=='cddr':
    279             from backend_cdd import Polyhedron_QQ_cdd
    280             return Polyhedron_QQ_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)
    281         if backend=='cddf':
    282             from backend_cdd import Polyhedron_RDF_cdd
    283             return Polyhedron_RDF_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)
     272    # set ambient_dim
     273    if ambient_dim is not None and deduced_ambient_dim!=ambient_dim:
     274        raise ValueError('Ambient space dimension mismatch. Try removing the "ambient_dim" parameter.')
     275    ambient_dim = deduced_ambient_dim
    284276
    285     if base_ring is QQ:
    286         from backend_ppl import Polyhedron_QQ_ppl
    287         return Polyhedron_QQ_ppl(ambient_dim, Vrep, Hrep, minimize=minimize)
    288     elif base_ring is RDF:
    289         from backend_cdd import Polyhedron_RDF_cdd
    290         return Polyhedron_RDF_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)
     277    # figure out base_ring
     278    from sage.misc.flatten import flatten
     279    values = flatten(vertices+rays+lines+ieqs+eqns)
     280    if base_ring is not None:
     281        try:
     282            convert = not all(x.parent() is base_ring for x in values)
     283        except AttributeError:   # No x.parent() method?
     284            convert = True
    291285    else:
    292         raise ValueError('Polyhedron objects can only be constructed over QQ and RDF')
     286        from sage.rings.integer import is_Integer
     287        from sage.rings.rational import is_Rational
     288        from sage.rings.real_double import is_RealDoubleElement
     289        if all(is_Integer(x) for x in values):
     290            if got_Vrep:
     291                base_ring = ZZ
     292            else:   # integral inequalities usually do not determine a latice polytope!
     293                base_ring = QQ
     294            convert=False
     295        elif all(is_Rational(x) for x in values):
     296            base_ring = QQ
     297            convert=False
     298        elif all(is_RealDoubleElement(x) for x in values):
     299            base_ring = RDF
     300            convert=False
     301        else:
     302            try:
     303                map(ZZ, values)
     304                if got_Vrep:
     305                    base_ring = ZZ
     306                else:
     307                    base_ring = QQ
     308                convert = True
     309            except TypeError:
     310                from sage.structure.sequence import Sequence
     311                values = Sequence(values)
     312                if QQ.has_coerce_map_from(values.universe()):
     313                    base_ring = QQ
     314                    convert = True
     315                else:
     316                    base_ring = RDF
     317                    convert = True
    293318
     319    # Add the origin if necesarry
     320    if got_Vrep and len(vertices)==0:
     321        vertices = [ [0]*ambient_dim ]
    294322
     323    # Specific backends can override the base_ring
     324    from sage.geometry.polyhedron.parent import Polyhedra
     325    parent = Polyhedra(base_ring, ambient_dim, backend=backend)
     326    base_ring = parent.base_ring()
    295327
     328    # Convert into base_ring if necessary
     329    def convert_base_ring(lstlst):
     330        return [ [base_ring(x) for x in lst] for lst in lstlst]
     331    Hrep = Vrep = None
     332    if got_Hrep:
     333        if convert:
     334            Hrep = [convert_base_ring(ieqs), convert_base_ring(eqns)]
     335        else:
     336            Hrep = [ieqs, eqns]
     337    if got_Vrep:
     338        if convert:
     339            Vrep = [convert_base_ring(vertices), convert_base_ring(rays), convert_base_ring(lines)]
     340        else:
     341            Vrep = [vertices, rays, lines]
    296342
    297 
     343    # finally, construct the Polyhedron
     344    return parent.element_class(parent, Vrep, Hrep)
  • new file sage/geometry/polyhedron/face.py

    diff --git a/sage/geometry/polyhedron/face.py b/sage/geometry/polyhedron/face.py
    new file mode 100644
    - +  
     1"""
     2A class to keep information about faces of a polyhedron
     3
     4This module gives you a tool to work with the faces of a polyhedron
     5and their relative position. First, you need to find the faces. To get
     6the faces in a particular dimension, use the
     7:meth:`~sage.geometry.poylhedron.base.face` method::
     8
     9    sage: P = polytopes.cross_polytope(3)
     10    sage: P.faces(3)
     11    (<0,1,2,3,4,5>,)
     12    sage: P.faces(2)
     13    (<0,1,2>, <0,1,3>, <0,2,4>, <0,3,4>, <3,4,5>, <2,4,5>, <1,3,5>, <1,2,5>)
     14    sage: P.faces(1)
     15    (<0,1>, <0,2>, <1,2>, <0,3>, <1,3>, <0,4>, <2,4>, <3,4>, <2,5>, <3,5>, <4,5>, <1,5>)
     16
     17or :meth:`~sage.geometry.poylhedron.base.face_lattice` to get the
     18whole face lattice as a poset::
     19
     20    sage: P.face_lattice()
     21    Finite poset containing 28 elements
     22
     23The faces are printed in shorthand notation where each integer is the
     24index of a vertex/ray/line in the same order as the containing
     25Polyhedron's :meth:`~sage.geometry.polyhedron.base.Vrepresentation` ::
     26
     27    sage: face = P.faces(1)[3];  face
     28    <0,3>
     29    sage: P.Vrepresentation(0)
     30    A vertex at (-1, 0, 0)
     31    sage: P.Vrepresentation(3)
     32    A vertex at (0, 0, 1)
     33    sage: face.vertices()
     34    (A vertex at (-1, 0, 0), A vertex at (0, 0, 1))
     35
     36The face itself is not represented by Sage's
     37:func:`sage.geometry.polyhedron.constructor.Polyhedron` class, but by
     38an auxiliary class to keep the information. You can get the face as a
     39polyhedron with the :meth:`PolyhedronFace.as_polyhedron` method::
     40
     41    sage: face.as_polyhedron()
     42    A 1-dimensional polyhedron in ZZ^3 defined as the convex hull of 2 vertices
     43    sage: _.equations()
     44    (An equation (0, 1, 0) x + 0 == 0,
     45     An equation (1, 0, -1) x + 1 == 0)
     46"""
     47
     48########################################################################
     49#       Copyright (C) 2012 Volker Braun <vbraun.name@gmail.com>
     50#
     51#  Distributed under the terms of the GNU General Public License (GPL)
     52#
     53#                  http://www.gnu.org/licenses/
     54########################################################################
     55
     56
     57from sage.structure.sage_object import SageObject
     58from sage.misc.all import cached_method
     59from sage.modules.free_module_element import vector
     60from sage.matrix.constructor import matrix
     61
     62
     63
     64#########################################################################
     65class PolyhedronFace(SageObject):
     66    r"""
     67    A face of a polyhedron.
     68
     69    This class is for use in
     70    :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.face_lattice`.
     71
     72    INPUT:
     73
     74    No checking is performed whether the H/V-representation indices
     75    actually determine a face of the polyhedron. You should not
     76    manually create :class:`PolyhedronFace` objects unless you know
     77    what you are doing.
     78
     79    OUTPUT:
     80
     81    A :class:`PolyhedronFace`.
     82
     83    EXAMPLES::
     84
     85        sage: octahedron = polytopes.cross_polytope(3)
     86        sage: inequality = octahedron.Hrepresentation(2)
     87        sage: face_h = tuple([ inequality ])
     88        sage: face_v = tuple( inequality.incident() )
     89        sage: face_h_indices = [ h.index() for h in face_h ]
     90        sage: face_v_indices = [ v.index() for v in face_v ]
     91        sage: from sage.geometry.polyhedron.face import PolyhedronFace
     92        sage: face = PolyhedronFace(octahedron, face_v_indices, face_h_indices)
     93        sage: face
     94        <0,1,2>
     95        sage: face.dim()
     96        2
     97        sage: face.ambient_Hrepresentation()
     98        (An inequality (1, 1, 1) x + 1 >= 0,)
     99        sage: face.ambient_Vrepresentation()
     100        (A vertex at (-1, 0, 0), A vertex at (0, -1, 0), A vertex at (0, 0, -1))
     101    """
     102
     103    def __init__(self, polyhedron, V_indices, H_indices):
     104        r"""
     105        The constructor.
     106
     107        See :class:`PolyhedronFace` for more information.
     108
     109        INPUT:
     110
     111        - ``polyhedron`` -- a :class:`Polyhedron`. The ambient
     112          polyhedron.
     113
     114        - ``V_indices`` -- list of integers. The indices of the
     115          face-spanning V-representation objects in the ambient
     116          polyhedron.
     117
     118        - ``H_indices`` -- list of integers. The indices of the
     119          H-representation objects of the ambient polyhedron that are
     120          saturated on the face.
     121
     122        TESTS::
     123
     124            sage: from sage.geometry.polyhedron.face import PolyhedronFace
     125            sage: PolyhedronFace(Polyhedron(), [], [])   # indirect doctest
     126            <>
     127        """
     128        self._polyhedron = polyhedron
     129        self._ambient_Vrepresentation_indices = tuple(V_indices)
     130        self._ambient_Hrepresentation_indices = tuple(H_indices)
     131        self._ambient_Vrepresentation = tuple( polyhedron.Vrepresentation(i) for i in V_indices )
     132        self._ambient_Hrepresentation = tuple( polyhedron.Hrepresentation(i) for i in H_indices )
     133
     134    def vertex_generator(self):
     135        """
     136        Return a generator for the vertices of the face.
     137
     138        EXAMPLES::
     139
     140            sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[1,1]])
     141            sage: face = triangle.faces(1)[0]
     142            sage: for v in face.vertex_generator(): print(v)
     143            A vertex at (0, 1)
     144            A vertex at (1, 0)
     145            sage: type(face.vertex_generator())
     146            <type 'generator'>
     147        """
     148        for V in self.ambient_Vrepresentation():
     149            if V.is_vertex():
     150                yield V
     151
     152    @cached_method
     153    def vertices(self):
     154        """
     155        Return all vertices of the face.
     156
     157        OUTPUT:
     158
     159        A tuple of vertices.
     160
     161        EXAMPLES::
     162
     163            sage: triangle = Polyhedron(vertices=[[1,0],[0,1],[1,1]])
     164            sage: face = triangle.faces(1)[0]
     165            sage: face.vertices()
     166            (A vertex at (0, 1), A vertex at (1, 0))
     167        """
     168        return tuple(self.vertex_generator())
     169
     170    def ray_generator(self):
     171        """
     172        Return a generator for the rays of the face.
     173
     174        EXAMPLES::
     175
     176            sage: pi = Polyhedron(ieqs = [[1,1,0],[1,0,1]])
     177            sage: face = pi.faces(1)[0]
     178            sage: face.ray_generator().next()
     179            A ray in the direction (1, 0)
     180        """
     181        for V in self.ambient_Vrepresentation():
     182            if V.is_ray():
     183                yield V
     184
     185    @cached_method
     186    def rays(self):
     187        """
     188        Return the rays of the face.
     189
     190        OUTPUT:
     191
     192        A tuple of rays.
     193
     194        EXAMPLES::
     195
     196            sage: p = Polyhedron(ieqs = [[0,0,0,1],[0,0,1,0],[1,1,0,0]])
     197            sage: face = p.faces(2)[0]
     198            sage: face.rays()
     199            (A ray in the direction (1, 0, 0), A ray in the direction (0, 1, 0))
     200        """
     201        return tuple(self.ray_generator())
     202
     203    def line_generator(self):
     204        """
     205        Return a generator for the lines of the face.
     206
     207        EXAMPLES::
     208
     209            sage: pr = Polyhedron(rays = [[1,0],[-1,0],[0,1]], vertices = [[-1,-1]])
     210            sage: face = pr.faces(1)[0]
     211            sage: face.line_generator().next()
     212            A line in the direction (1, 0)
     213        """
     214        for V in self.ambient_Vrepresentation():
     215            if V.is_line():
     216                yield V
     217
     218    @cached_method
     219    def lines(self):
     220        """
     221        Return all lines of the face.
     222
     223        OUTPUT:
     224
     225        A tuple of lines.
     226
     227        EXAMPLES::
     228
     229            sage: p = Polyhedron(rays = [[1,0],[-1,0],[0,1],[1,1]], vertices = [[-2,-2],[2,3]])
     230            sage: p.lines()
     231            (A line in the direction (1, 0),)
     232        """
     233        return tuple(self.line_generator())
     234
     235    def __cmp__(self, other):
     236        """
     237        Compare ``self`` and ``other``.
     238
     239        INPUT:
     240
     241        - ``other`` -- anything.
     242
     243        OUTPUT:
     244       
     245        Two faces test equal if and only if they are faces of the same
     246        (not just isomorphic) polyhedron and their generators have the
     247        same indices.
     248
     249        EXAMPLES::
     250
     251            sage: square = polytopes.n_cube(2)
     252            sage: f = square.face_lattice()[5:9]
     253            sage: matrix(4,4, lambda i,j: cmp(f[i].element, f[j].element))
     254            [ 0 -1 -1 -1]
     255            [ 1  0 -1 -1]
     256            [ 1  1  0  1]
     257            [ 1  1 -1  0]
     258        """
     259        if not isinstance(other, PolyhedronFace):
     260            return -1
     261        if self._polyhedron is not other._polyhedron:
     262            return -1
     263        return cmp(self._ambient_Vrepresentation_indices,
     264                   other._ambient_Vrepresentation_indices)
     265
     266    def ambient_Hrepresentation(self, index=None):
     267        r"""
     268        Return the H-representation objects of the ambient polytope
     269        defining the face.
     270
     271        INPUT:
     272
     273        - ``index`` -- optional. Either an integer or ``None``
     274          (default).
     275
     276        OUTPUT:
     277
     278        If the optional argument is not present, a tuple of
     279        H-representation objects. Each entry is either an inequality
     280        or an equation.
     281
     282        If the optional integer ``index`` is specified, the
     283        ``index``-th element of the tuple is returned.
     284
     285        EXAMPLES::
     286
     287            sage: square = polytopes.n_cube(2)
     288            sage: for fl in square.face_lattice():
     289            ...       print fl.element.ambient_Hrepresentation()
     290            ...
     291            (An inequality (1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0,
     292             An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0)
     293            (An inequality (1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0)
     294            (An inequality (1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0)
     295            (An inequality (0, 1) x + 1 >= 0, An inequality (-1, 0) x + 1 >= 0)
     296            (An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0)
     297            (An inequality (1, 0) x + 1 >= 0,)
     298            (An inequality (0, 1) x + 1 >= 0,)
     299            (An inequality (-1, 0) x + 1 >= 0,)
     300            (An inequality (0, -1) x + 1 >= 0,)
     301            ()
     302        """
     303        if index==None:
     304            return self._ambient_Hrepresentation
     305        else:
     306            return self._ambient_Hrepresentation[index]
     307
     308    def ambient_Vrepresentation(self, index=None):
     309        r"""
     310        Return the V-representation objects of the ambient polytope
     311        defining the face.
     312
     313        INPUT:
     314
     315        - ``index`` -- optional. Either an integer or ``None``
     316          (default).
     317
     318        OUTPUT:
     319
     320        If the optional argument is not present, a tuple of
     321        V-representation objects. Each entry is either a vertex, a
     322        ray, or a line.
     323
     324        If the optional integer ``index`` is specified, the
     325        ``index``-th element of the tuple is returned.
     326
     327        EXAMPLES::
     328
     329            sage: square = polytopes.n_cube(2)
     330            sage: for fl in square.face_lattice():
     331            ...       print fl.element.ambient_Vrepresentation()
     332            ...
     333            ()
     334            (A vertex at (-1, -1),)
     335            (A vertex at (-1, 1),)
     336            (A vertex at (1, -1),)
     337            (A vertex at (1, 1),)
     338            (A vertex at (-1, -1), A vertex at (-1, 1))
     339            (A vertex at (-1, -1), A vertex at (1, -1))
     340            (A vertex at (1, -1), A vertex at (1, 1))
     341            (A vertex at (-1, 1), A vertex at (1, 1))
     342            (A vertex at (-1, -1), A vertex at (-1, 1),
     343             A vertex at (1, -1), A vertex at (1, 1))
     344        """
     345        if index==None:
     346            return self._ambient_Vrepresentation
     347        else:
     348            return self._ambient_Vrepresentation[index]
     349
     350    def n_ambient_Hrepresentation(self):
     351        """
     352        Return the number of objects that make up the ambient
     353        H-representation of the polyhedron.
     354
     355        See also :meth:`ambient_Hrepresentation`.
     356
     357        OUTPUT:
     358
     359        Integer.
     360
     361        EXAMPLES::
     362
     363            sage: p = polytopes.cross_polytope(4)
     364            sage: face = p.face_lattice()[10].element
     365            sage: face
     366            <0,2>
     367            sage: face.ambient_Hrepresentation()
     368            (An inequality (1, -1, 1, -1) x + 1 >= 0,
     369             An inequality (1, 1, 1, 1) x + 1 >= 0,
     370             An inequality (1, 1, 1, -1) x + 1 >= 0,
     371             An inequality (1, -1, 1, 1) x + 1 >= 0)
     372            sage: face.n_ambient_Hrepresentation()
     373            4
     374        """
     375        return len(self.ambient_Hrepresentation())
     376
     377    def n_ambient_Vrepresentation(self):
     378        """
     379        Return the number of objects that make up the ambient
     380        V-representation of the polyhedron.
     381
     382        See also :meth:`ambient_Vrepresentation`.
     383
     384        OUTPUT:
     385
     386        Integer.
     387
     388        EXAMPLES::
     389
     390            sage: p = polytopes.cross_polytope(4)
     391            sage: face = p.face_lattice()[10].element
     392            sage: face
     393            <0,2>
     394            sage: face.ambient_Vrepresentation()
     395            (A vertex at (-1, 0, 0, 0), A vertex at (0, 0, -1, 0))
     396            sage: face.n_ambient_Vrepresentation()
     397            2
     398        """
     399        return len(self.ambient_Vrepresentation())
     400
     401    def ambient_dim(self):
     402        r"""
     403        Return the dimension of the containing polyhedron.
     404
     405        EXAMPLES::
     406
     407            sage: P = Polyhedron(vertices = [[1,0,0,0],[0,1,0,0]])
     408            sage: face = P.faces(1)[0]
     409            sage: face.ambient_dim()
     410            4
     411        """
     412        return self._polyhedron.ambient_dim()
     413
     414    @cached_method
     415    def dim(self):
     416        """
     417        Return the dimension of the face.
     418
     419        OUTPUT:
     420
     421        Integer.
     422
     423        EXAMPLES::
     424
     425            sage: fl = polytopes.dodecahedron().face_lattice()
     426            sage: [ x.element.dim() for x in fl ]
     427            [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     428              1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
     429              1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3]
     430        """
     431        if self.n_ambient_Vrepresentation()==0:
     432            return -1
     433        else:
     434            origin = vector(self.ambient_Vrepresentation(0))
     435            v_list = [ vector(v)-origin for v in self.ambient_Vrepresentation() ]
     436            return matrix(v_list).rank()
     437
     438    def _repr_(self):
     439        r"""
     440        Return a string representation.
     441
     442        OUTPUT:
     443
     444        A string listing the V-representation indices of the face.
     445
     446        EXAMPLES::
     447
     448            sage: square = polytopes.n_cube(2)
     449            sage: a_face = list( square.face_lattice() )[8].element
     450            sage: a_face.__repr__()
     451            '<1,3>'
     452        """
     453        s = '<'
     454        s += ','.join([ str(v.index()) for v in self.ambient_Vrepresentation() ])
     455        s += '>'
     456        return s
     457
     458    def polyhedron(self):
     459        """
     460        Return the containing polyhedron.
     461
     462        EXAMPLES::
     463
     464            sage: P = polytopes.cross_polytope(3); P
     465            A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 6 vertices
     466           sage: face = P.faces(2)[3]
     467            sage: face
     468            <0,3,4>
     469            sage: face.polyhedron()
     470            A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 6 vertices
     471        """
     472        return self._polyhedron
     473   
     474    @cached_method
     475    def as_polyhedron(self):
     476        """
     477        Return the face as an independent polyhedron.
     478
     479        OUTPUT:
     480
     481        A polyhedron.
     482
     483        EXAMPLES::
     484
     485            sage: P = polytopes.cross_polytope(3);  P
     486            A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 6 vertices
     487            sage: face = P.faces(2)[3]
     488            sage: face
     489            <0,3,4>
     490            sage: face.as_polyhedron()
     491            A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 3 vertices
     492
     493            sage: P.intersection(face.as_polyhedron()) == face.as_polyhedron()
     494            True
     495        """
     496        P = self._polyhedron
     497        parent = P.parent()
     498        Vrep = (self.vertices(), self.rays(), self.lines())
     499        return P.__class__(parent, Vrep, None)
  • sage/geometry/polyhedron/library.py

    diff --git a/sage/geometry/polyhedron/library.py b/sage/geometry/polyhedron/library.py
    a b  
    4242        """
    4343        A matrix of rational approximations to orthonormal vectors to
    4444        ``(1,...,1)``.
    45    
     45
    4646        INPUT:
    4747
    4848        - ``dim_n`` - the dimension of the vectors
     
    100100        An internal utility function for constructing the Birkhoff polytopes.
    101101
    102102        EXAMPLES::
    103        
     103
    104104            sage: from sage.geometry.polyhedron.library import Polytopes
    105105            sage: Polytopes._pfunc(1,2,permutations(3)[0])
    106106            0
     
    195195        Return an icosahedron with edge length 1.
    196196
    197197        INPUT:
    198        
     198
    199199        - ``base_ring`` -- Either ``QQ`` or ``RDF``.
    200200
    201201        OUTPUT:
     
    233233    def dodecahedron(self, base_ring=QQ):
    234234        """
    235235        Return a dodecahedron.
    236        
     236
    237237        INPUT:
    238        
     238
    239239        - ``base_ring`` -- Either ``QQ`` (in which case a rational
    240240          approximation to the golden ratio is used) or ``RDF``.
    241241
     
    537537        - ``n`` -- the numbers ``(1,...,n)`` are permuted
    538538
    539539        - ``project`` -- If ``False`` the polyhedron is left in dimension ``n``.
    540  
     540
    541541        OUTPUT:
    542542
    543543        A Polyhedron object representing the permutahedron.
     
    562562        Return a cube in the given dimension
    563563
    564564        INPUT:
    565  
     565
    566566        - ``dim_n`` -- integer. The dimension of the cube.
    567567
    568568        OUTPUT:
     
    613613        verts = verts + permutations([0 for i in range(dim_n-1)] + [-1])
    614614        return Polyhedron(vertices=verts)
    615615
    616    
     616
    617617    def parallelotope(self, generators):
    618618        r"""
    619619        Return the parallelotope spanned by the generators.
    620620
    621621        INPUT:
    622        
     622
    623623        - ``generators`` -- an iterable of anything convertible to vector
    624624          (for example, a list of vectors) such that the vectors all
    625625          have the same dimension.
     
    631631        parallelepiped (3 generators).
    632632
    633633        EXAMPLES::
    634        
     634
    635635            sage: polytopes.parallelotope([ (1,0), (0,1) ])
    636636            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
    637637            sage: polytopes.parallelotope([[1,2,3,4],[0,1,0,7],[3,1,0,2],[0,0,1,0]])
     
    643643        except TypeError:
    644644            generators = [ vector(RDF,v) for v in generators ]
    645645            base_ring = RDF
    646            
     646
    647647        from sage.combinat.combination import Combinations
    648648        par =  [ 0*generators[0] ]
    649649        par += [ sum(c) for c in Combinations(generators) if c!=[] ]
    650650        return Polyhedron(vertices=par, base_ring=base_ring)
    651                            
     651
    652652
    653653
    654654polytopes = Polytopes()
  • sage/geometry/polyhedron/misc.py

    diff --git a/sage/geometry/polyhedron/misc.py b/sage/geometry/polyhedron/misc.py
    a b  
    2525    INPUT:
    2626
    2727    - ``l`` -- anything iterable.
    28    
     28
    2929    OUTPUT:
    3030
    3131    String.
     
    5858        [1]
    5959    """
    6060    if x is None: return x
     61    x = list(x)
    6162    if len(x)==0: return None
    6263    return x
    6364
    6465
    6566#########################################################################
    66 def _set_to_empty_if_None(x):
     67def _make_listlist(x):
    6768    """
    68     Helper function to clean up arguments: Returns the empty list if
    69     x==None or x is an empty container.
     69    Helper function to clean up arguments.
     70
     71    INPUT:
     72
     73    - ``x`` -- ``None`` or an iterable of iterables.
     74
     75    OUTPUT
     76
     77    A list of lists.
    7078
    7179    EXAMPLES::
    7280
    7381        sage: import sage.geometry.polyhedron.misc as P
    74         sage: [] == P._set_to_empty_if_None(tuple())
     82        sage: [] == P._make_listlist(tuple())
    7583        True
    76         sage: [] == P._set_to_empty_if_None(None)
     84        sage: [] == P._make_listlist(None)
    7785        True
    78         sage: P._set_to_empty_if_None([1])
    79         [1]
     86        sage: P._make_listlist([(1,2),[3,4]])
     87        [[1, 2], [3, 4]]
    8088    """
    8189    if x is None: return []
    82     if len(x)==0: return []
    83     return x
     90    return [list(y) for y in x]
    8491
    8592
    8693#########################################################################
     
    9198    length differs, ``ValueError`` is raised. Used to check arguments.
    9299
    93100    OUTPUT:
    94    
     101
    95102    A tuple (number of entries, common length of the entries)
    96103
    97104    EXAMPLES::
  • new file sage/geometry/polyhedron/parent.py

    diff --git a/sage/geometry/polyhedron/parent.py b/sage/geometry/polyhedron/parent.py
    new file mode 100644
    - +  
     1r"""
     2Parents for Polyhedra
     3"""
     4
     5#*****************************************************************************
     6#       Copyright (C) 2011 Volker Braun <vbraun.name@gmail.com>
     7#
     8#  Distributed under the terms of the GNU General Public License (GPL)
     9#                  http://www.gnu.org/licenses/
     10#******************************************************************************
     11
     12from sage.structure.parent import Parent
     13from sage.structure.element import get_coercion_model
     14from sage.structure.unique_representation import UniqueRepresentation
     15from sage.modules.free_module import is_FreeModule
     16from sage.misc.cachefunc import cached_method
     17from sage.rings.all import ZZ, QQ, RDF, is_Field, is_CommutativeRing
     18
     19from sage.geometry.polyhedron.base import Polyhedron_base, is_Polyhedron
     20from representation import Inequality, Equation, Vertex, Ray, Line
     21
     22
     23def Polyhedra(base_ring, ambient_dim, backend=None):
     24    """
     25    Construct a suitable parent class for polyhedra
     26
     27    INPUT:
     28
     29    - ``base_ring`` -- A ring. Currently there are backends for `\ZZ`,
     30      `\QQ`, and `\RDF`.
     31     
     32    - ``ambient_dim`` -- integer. The ambient space dimension.
     33
     34    - ``backend`` -- string. The name of the backend for computations. Currently there are two backends implemented:
     35
     36         * ``backend=ppl`` uses the Parma Polyhedra Library
     37
     38         * ``backend=cdd`` uses CDD
     39
     40    OUTPUT:
     41
     42    A parent class for polyhedra over the given base ring if the
     43    backend supports it. If not, the parent base ring can be larger
     44    (for example, `\QQ` instead of `\ZZ`). If there is no
     45    implementation at all, a ``ValueError`` is raised.
     46
     47    EXAMPLES::
     48
     49        sage: from sage.geometry.polyhedron.parent import Polyhedra
     50        sage: Polyhedra(ZZ, 3)
     51        Polyhedra in ZZ^3
     52        sage: type(_)
     53        <class 'sage.geometry.polyhedron.parent.Polyhedra_ZZ_ppl_with_category'>
     54        sage: Polyhedra(QQ, 3, backend='cdd')
     55        Polyhedra in QQ^3
     56        sage: type(_)
     57        <class 'sage.geometry.polyhedron.parent.Polyhedra_QQ_cdd_with_category'>
     58
     59    CDD does not support integer polytopes directly::
     60
     61        sage: Polyhedra(ZZ, 3, backend='cdd')
     62        Polyhedra in QQ^3
     63    """
     64    if backend is None:
     65        if base_ring is ZZ:
     66            return Polyhedra_ZZ_ppl(base_ring, ambient_dim)
     67        elif base_ring is QQ:
     68            return Polyhedra_QQ_ppl(base_ring, ambient_dim)
     69        elif base_ring is RDF:
     70            return Polyhedra_RDF_cdd(base_ring, ambient_dim)
     71        else:
     72            raise ValueError('Polyhedral objects can only be constructed over ZZ, QQ, and RDF')
     73    elif backend=='ppl' and base_ring is QQ:
     74        return Polyhedra_QQ_ppl(base_ring, ambient_dim)
     75    elif backend=='ppl' and base_ring is ZZ:
     76        return Polyhedra_ZZ_ppl(base_ring, ambient_dim)
     77    elif backend=='cdd' and base_ring in (ZZ, QQ):
     78        return Polyhedra_QQ_cdd(QQ, ambient_dim)
     79    elif backend=='cdd' and base_ring is RDF:
     80        return Polyhedra_RDF_cdd(RDF, ambient_dim)
     81    else:
     82        raise ValueError('No such backend (='+str(backend)+
     83                         ') implemented for given basering (='+str(base_ring)+').')
     84
     85
     86
     87class Polyhedra_base(UniqueRepresentation, Parent):
     88    r"""
     89    Polyhedra in a fixed ambient space.
     90
     91    INPUT:
     92
     93    - ``base_ring`` -- either ``ZZ``, ``QQ``, or ``RDF``. The base
     94      ring of the ambient module/vector space.
     95
     96    - ``ambient_dim`` -- integer. The ambient space dimension.
     97
     98    EXAMPLES::
     99
     100        sage: from sage.geometry.polyhedron.parent import Polyhedra
     101        sage: Polyhedra(ZZ, 3)
     102        Polyhedra in ZZ^3
     103    """
     104    def __init__(self, base_ring, ambient_dim):
     105        """
     106        The Python constructor.
     107
     108        EXAMPLES::
     109
     110            sage: from sage.geometry.polyhedron.parent import Polyhedra
     111            sage: Polyhedra(QQ, 3)
     112            Polyhedra in QQ^3
     113
     114        TESTS::
     115
     116            sage: from sage.geometry.polyhedron.parent import Polyhedra
     117            sage: P = Polyhedra(QQ, 3)
     118            sage: TestSuite(P).run(skip='_test_pickling')
     119        """
     120        self._ambient_dim = ambient_dim
     121        from sage.categories.polyhedra import PolyhedralSets
     122        Parent.__init__(self, base=base_ring, category=PolyhedralSets(base_ring))
     123        self._Inequality_pool = []
     124        self._Equation_pool = []
     125        self._Vertex_pool = []
     126        self._Ray_pool = []
     127        self._Line_pool = []
     128
     129    def recycle(self, polyhedron):
     130        """
     131        Recycle the H/V-representation objects of a polyhedron.
     132
     133        This speeds up creation of new polyhedra by reusing
     134        objects. After recycling a polyhedron object, it is not in a
     135        consistent state any more and neither the polyhedron nor its
     136        H/V-representation objects may be used any more.
     137
     138        INPUT:
     139
     140        - ``polyhedron`` -- a polyhedron whose parent is ``self``.
     141
     142
     143        EXAMPLES::
     144
     145            sage: p = Polyhedron([(0,0),(1,0),(0,1)])
     146            sage: p.parent().recycle(p)
     147
     148        TESTS::
     149
     150            sage: p = Polyhedron([(0,0),(1,0),(0,1)])
     151            sage: n = len(p.parent()._Vertex_pool)
     152            sage: p.delete()
     153            sage: len(p.parent()._Vertex_pool) - n
     154            3
     155        """
     156        if self is not polyhedron.parent():
     157            raise TypeError('The polyhedron has the wrong parent class.')
     158        self._Inequality_pool.extend(polyhedron.inequalities())
     159        self._Equation_pool.extend(polyhedron.equations())
     160        self._Vertex_pool.extend(polyhedron.vertices())
     161        self._Ray_pool.extend(polyhedron.rays())
     162        self._Line_pool.extend(polyhedron.lines())
     163        for Hrep in polyhedron.Hrep_generator():
     164            Hrep._polyhedron = None
     165        for Vrep in polyhedron.Vrep_generator():
     166            Vrep._polyhedron = None
     167        polyhedron._Hrepresentation = None
     168        polyhedron._Vrepresentation = None
     169
     170    def ambient_dim(self):
     171        r"""
     172        Return the dimension of the ambient space.
     173
     174        EXAMPLES::
     175
     176            sage: from sage.geometry.polyhedron.parent import Polyhedra
     177            sage: Polyhedra(QQ, 3).ambient_dim()
     178            3
     179        """
     180        return self._ambient_dim
     181
     182    @cached_method
     183    def an_element(self):
     184        r"""
     185        Returns a Polyhedron.
     186
     187        EXAMPLES::
     188
     189            sage: from sage.geometry.polyhedron.parent import Polyhedra
     190            sage: Polyhedra(QQ, 4).an_element()
     191            A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 5 vertices
     192        """
     193        p = [0] * self.ambient_dim()
     194        points = [p]
     195        for i in range(0,self.ambient_dim()):
     196            p = [0] * self.ambient_dim()
     197            p[i] = 1
     198            points.append(p)
     199        return self.element_class(self, [points,[],[]], None)
     200
     201    @cached_method
     202    def some_elements(self):
     203        r"""
     204        Returns a list of some elements of the semigroup.
     205
     206        EXAMPLES::
     207
     208            sage: from sage.geometry.polyhedron.parent import Polyhedra
     209            sage: Polyhedra(QQ, 4).some_elements()
     210            [A 3-dimensional polyhedron in QQ^4 defined as the convex hull of 4 vertices,
     211             A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 1 vertex and 4 rays,
     212             A 2-dimensional polyhedron in QQ^4 defined as the convex hull of 2 vertices and 1 ray,
     213             The empty polyhedron in QQ^4]
     214            sage: Polyhedra(ZZ,0).some_elements()
     215            [The empty polyhedron in ZZ^0,
     216             A 0-dimensional polyhedron in ZZ^0 defined as the convex hull of 1 vertex]
     217        """
     218        if self.ambient_dim() == 0:
     219            return [
     220                self.element_class(self, None, None),
     221                self.element_class(self, None, [[],[]]) ]
     222        points = []
     223        for i in range(0,self.ambient_dim()+5):
     224            points.append([i*j^2 for j in range(0,self.ambient_dim())])
     225        return [
     226            self.element_class(self, [points[0:self.ambient_dim()+1], [], []], None),
     227            self.element_class(self, [points[0:1], points[1:self.ambient_dim()+1], []], None),
     228            self.element_class(self, [points[0:3], points[4:5], []], None),
     229            self.element_class(self, None, None) ]
     230
     231    @cached_method
     232    def zero_element(self):
     233        r"""
     234        Returns the polyhedron consisting of the origin, which is the
     235        neutral element for Minkowski addition.
     236
     237        EXAMPLES::
     238
     239            sage: from sage.geometry.polyhedron.parent import Polyhedra
     240            sage: p = Polyhedra(QQ, 4).zero_element();  p
     241            A 0-dimensional polyhedron in QQ^4 defined as the convex hull of 1 vertex
     242            sage: p+p == p
     243            True
     244        """
     245        Vrep = [[[self.base_ring().zero()]*self.ambient_dim()], [], []]
     246        return self.element_class(self, Vrep, None)
     247
     248    @cached_method
     249    def Vrepresentation_space(self):
     250        r"""
     251        Return the ambient vector space.
     252
     253        This is the vector space or module containing the
     254        Vrepresentation vectors.
     255
     256        OUTPUT:
     257
     258        A free module over the base ring of dimension :meth:`ambient_dim`.
     259
     260        EXAMPLES::
     261
     262            sage: from sage.geometry.polyhedron.parent import Polyhedra
     263            sage: Polyhedra(QQ, 4).Vrepresentation_space()
     264            Vector space of dimension 4 over Rational Field
     265            sage: Polyhedra(QQ, 4).ambient_space()
     266            Vector space of dimension 4 over Rational Field
     267        """
     268        if is_Field(self.base_ring()):
     269            from sage.modules.free_module import VectorSpace
     270            return VectorSpace(self.base_ring(), self.ambient_dim())
     271        else:
     272            from sage.modules.free_module import FreeModule
     273            return FreeModule(self.base_ring(), self.ambient_dim())
     274
     275    ambient_space = Vrepresentation_space
     276
     277    @cached_method
     278    def Hrepresentation_space(self):
     279        r"""
     280        Return the linear space containing the H-representation vectors.
     281
     282        OUTPUT:
     283
     284        A free module over the base ring of dimension :meth:`ambient_dim` + 1.
     285
     286        EXAMPLES::
     287
     288            sage: from sage.geometry.polyhedron.parent import Polyhedra
     289            sage: Polyhedra(ZZ, 2).Hrepresentation_space()
     290            Ambient free module of rank 3 over the principal ideal domain Integer Ring
     291        """
     292        if is_Field(self.base_ring()):
     293            from sage.modules.free_module import VectorSpace
     294            return VectorSpace(self.base_ring(), self.ambient_dim()+1)
     295        else:
     296            from sage.modules.free_module import FreeModule
     297            return FreeModule(self.base_ring(), self.ambient_dim()+1)
     298
     299    def _repr_ambient_module(self):
     300        """
     301        Return an abbreviated string representation of the ambient
     302        space.
     303
     304        OUTPUT:
     305
     306        String.
     307
     308        EXAMPLES::
     309
     310            sage: from sage.geometry.polyhedron.parent import Polyhedra
     311            sage: Polyhedra(QQ, 3)._repr_ambient_module()
     312            'QQ^3'
     313        """
     314        if self.base_ring() is ZZ:
     315            s = 'ZZ'
     316        elif self.base_ring() is QQ:
     317            s = 'QQ'
     318        elif self.base_ring() is RDF:
     319            s = 'RDF'
     320        else:
     321            assert False
     322        s += '^' + repr(self.ambient_dim())
     323        return s
     324
     325    def _repr_(self):
     326        """
     327        Return a string representation.
     328
     329        OUTPUT:
     330
     331        String.
     332