Ticket #11763: trac_11763-polyhedra_coercion_folded.3.patch

File trac_11763-polyhedra_coercion_folded.3.patch, 247.0 KB (added by jdemeyer, 6 years ago)
  • doc/en/reference/geometry.rst

    # HG changeset patch
    # User Volker Braun <vbraun@stp.dias.ie>
    # Date 1315501129 14400
    # Node ID 41f05e3d2ddf00d12e52a3cd351bda8af35ad80d
    # Parent  b1aaa12656642898da735755c67975acaf36e0bc
    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.
     
    19391887        from sage.homology.simplicial_complex import SimplicialComplex
    19401888        return SimplicialComplex([x[1] for x in self.triangulated_facial_incidences()])
    19411889
    1942     def __add__(self, other):
     1890    @coerce_binop
     1891    def Minkowski_sum(self, other):
    19431892        """
     1893        Return the Minkowski sum.
     1894
     1895        INPUT:
     1896
     1897        - ``other`` -- a :class:`Polyhedron_base`.
     1898
     1899        OUTPUT:
     1900
    19441901        The Minkowski sum of ``self`` and ``other``.
    19451902
    1946         INPUT:
    1947 
    1948         - ``other`` -- a :class:`Polyhedron`.
    1949 
    19501903        EXAMPLES::
    19511904
    19521905            sage: four_cube = polytopes.n_cube(4)
    19531906            sage: four_simplex = Polyhedron(vertices = [[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]])
    1954             sage: unholy_union = four_cube + four_simplex
    1955             sage: unholy_union.dim()
    1956             4
    1957             sage: poly_spam = Polyhedron([[3,4,5,2],[1,0,0,1],[0,0,0,0],[0,4,3,2],[-3,-3,-3,-3]])
    1958             sage: poly_eggs = Polyhedron([[5,4,5,4],[-4,5,-4,5],[4,-5,4,-5],[0,0,0,0]])
    1959             sage: poly_spam_and_eggs = poly_spam + poly_spam + poly_eggs
    1960             sage: poly_spam_and_eggs.n_vertices()
    1961             12
     1907            sage: four_cube + four_simplex
     1908            A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 36 vertices
     1909            sage: four_cube.Minkowski_sum(four_simplex) == four_cube + four_simplex
     1910            True
     1911
     1912            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)
     1913            sage: poly_eggs = Polyhedron([[5,4,5,4],[-4,5,-4,5],[4,-5,4,-5],[0,0,0,0]], base_ring=QQ)
     1914            sage: poly_spam + poly_spam + poly_eggs
     1915            A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 12 vertices
    19621916        """
    1963         if is_Polyhedron(other):
    1964             new_vertices = []
    1965             for v1 in self.vertex_generator():
    1966                 for v2 in other.vertex_generator():
    1967                     new_vertices.append(list(v1() + v2()))
     1917        new_vertices = []
     1918        for v1 in self.vertex_generator():
     1919            for v2 in other.vertex_generator():
     1920                new_vertices.append(list(v1() + v2()))
     1921        if new_vertices != []:
    19681922            new_rays = self.rays() + other.rays()
    19691923            new_lines = self.lines() + other.lines()
    1970             other_field = other.field()
    1971 
    1972         else:  # assume other is a vector and try to add vertices
    1973             displacement = vector(other)
    1974             new_vertices = [list(x() + displacement) for x in self.vertex_generator()]
    1975             new_rays = self.rays()
    1976             new_lines = self.lines()
    1977             other_field = displacement.base_ring()
    1978 
     1924            return self.parent().element_class(self.parent(), [new_vertices, new_rays, new_lines], None)
     1925        else:
     1926            return self.parent().element_class(self.parent(), None, None)
     1927
     1928    _add_ = Minkowski_sum
     1929
     1930    def translation(self, displacement):
     1931        """
     1932        Return the translated polyhedron.
     1933
     1934        INPUT:
     1935
     1936        - ``displacement`` -- a displacement vector or a list/tuple of
     1937          coordinates that determines a displacement vector.
     1938
     1939        OUTPUT:
     1940
     1941        The translated polyhedron.
     1942
     1943        EXAMPLES::
     1944
     1945            sage: P = Polyhedron([[0,0],[1,0],[0,1]], base_ring=ZZ)
     1946            sage: P.translation([2,1])
     1947            A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
     1948            sage: P.translation( vector(QQ,[2,1]) )
     1949            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices
     1950        """
     1951        displacement = vector(displacement)
     1952        new_vertices = [x.vector()+displacement for x in self.vertex_generator()]
     1953        new_rays = self.rays()
     1954        new_lines = self.lines()
     1955        new_ring = self.parent()._coerce_base_ring(displacement.base_ring())
     1956        return Polyhedron(vertices=new_vertices, rays=new_rays, lines=new_lines, base_ring=new_ring)
     1957
     1958    @coerce_binop
     1959    def product(self, other):
     1960        """
     1961        Return the cartesian product.
     1962
     1963        INPUT:
     1964
     1965        - ``other`` -- a :class:`Polyhedron_base`.
     1966
     1967        OUTPUT:
     1968
     1969        The cartesian product of ``self`` and ``other`` with a
     1970        suitable base ring to encompass the two.
     1971
     1972        EXAMPLES::
     1973
     1974            sage: P1 = Polyhedron([[0],[1]], base_ring=ZZ)
     1975            sage: P2 = Polyhedron([[0],[1]], base_ring=QQ)
     1976            sage: P1.product(P2)
     1977            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
     1978
     1979        The cartesian product is the product in the semiring of polyhedra::
     1980
     1981            sage: P1 * P1
     1982            A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 4 vertices
     1983            sage: P1 * P2
     1984            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
     1985            sage: P2 * P2
     1986            A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
     1987            sage: 2 * P1
     1988            A 1-dimensional polyhedron in ZZ^1 defined as the convex hull of 2 vertices
     1989            sage: P1 * 2.0
     1990            A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices
     1991        """
     1992        new_vertices = [ list(x)+list(y)
     1993                         for x in self.vertex_generator() for y in other.vertex_generator()]
     1994        new_rays = []
     1995        new_rays.extend( [ r+[0]*other.ambient_dim()
     1996                           for r in self.ray_generator() ] )
     1997        new_rays.extend( [ [0]*self.ambient_dim()+r
     1998                           for r in other.ray_generator() ] )
     1999        new_lines = []
     2000        new_lines.extend( [ l+[0]*other.ambient_dim()
     2001                            for l in self.line_generator() ] )
     2002        new_lines.extend( [ [0]*self.ambient_dim()+l
     2003                            for l in other.line_generator() ] )
    19792004        return Polyhedron(vertices=new_vertices,
    19802005                          rays=new_rays, lines=new_lines,
    1981                           base_ring=self.coerce_field(other_field))
    1982            
    1983 
    1984     def __mul__(self, other):
     2006                          base_ring=self.parent()._coerce_base_ring(other))
     2007
     2008    _mul_ = product
     2009
     2010    def dilation(self, scalar):
    19852011        """
    1986         Multiplication by ``other``.
     2012        Return the dilated (uniformly stretched) polyhedron.
    19872013
    19882014        INPUT:
    19892015
    1990         - ``other`` -- A scalar, not necessarily in :meth:`field`, or
    1991           a :class:`Polyhedron`.
     2016        - ``scalar`` -- A scalar, not necessarily in :meth:`base_ring`,
     2017          or a :class:`Polyhedron`.
    19922018
    19932019        OUTPUT:
    19942020
     
    20012027             sage: p = Polyhedron(vertices = [[t,t^2,t^3] for t in srange(2,6)])
    20022028             sage: p.vertex_generator().next()
    20032029             A vertex at (2, 4, 8)
    2004              sage: p2 = p*2
     2030             sage: p2 = p.dilation(2)
    20052031             sage: p2.vertex_generator().next()
    20062032             A vertex at (4, 8, 16)
     2033             sage: p.dilation(2) == p * 2
     2034             True
    20072035        """
    2008         if is_Polyhedron(other):
    2009             new_vertices = [ list(x)+list(y)
    2010                              for x in self.vertex_generator() for y in other.vertex_generator()]
    2011             new_rays = []
    2012             new_rays.extend( [ list(r)+[0]*other.ambient_dim()
    2013                                for r in self.ray_generator() ] )
    2014             new_rays.extend( [ [0]*self.ambient_dim()+list(r)
    2015                                for r in other.ray_generator() ] )
    2016             new_lines = []
    2017             new_lines.extend( [ list(l)+[0]*other.ambient_dim()
    2018                                 for l in self.line_generator() ] )
    2019             new_lines.extend( [ [0]*self.ambient_dim()+list(l)
    2020                                for l in other.line_generator() ] )
    2021         else:
    2022             new_vertices = [ list(other*v()) for v in self.vertex_generator()]
    2023             new_rays =  self.rays()
    2024             new_lines = self.lines()
    2025 
     2036        new_vertices = [ list(scalar*v.vector()) for v in self.vertex_generator()]
     2037        new_rays =  self.rays()
     2038        new_lines = self.lines()
    20262039        return Polyhedron(vertices=new_vertices,
    20272040                          rays=new_rays, lines=new_lines,
    2028                           base_ring=self.coerce_field(other))
    2029 
    2030 
    2031     def __rmul__(self,other):
     2041                          base_ring=self.parent()._coerce_base_ring(scalar.parent()))
     2042
     2043    def _acted_upon_(self, actor, self_on_left):
    20322044        """
    2033         Right multiplication.
    2034 
    2035         See :meth:`__mul__` for details.
     2045        Implement the multiplicative action by scalars or other polyhedra.
     2046
     2047        INPUT:
     2048
     2049        - ``actor`` -- A scalar, not necessarily in :meth:`base_ring`,
     2050          or a :class:`Polyhedron`.
     2051
     2052        OUTPUT:
     2053
     2054        Multiplication by another polyhedron returns the product
     2055        polytope. Multiplication by a scalar returns the polytope
     2056        dilated by that scalar, possibly coerced to the bigger field.
    20362057
    20372058        EXAMPLES::
    20382059
     2060             sage: p = Polyhedron(vertices = [[t,t^2,t^3] for t in srange(2,6)])
     2061             sage: p._acted_upon_(2, True) == p.dilation(2)
     2062             True
     2063             sage: p*2 == p.dilation(2)
     2064             True
     2065             sage: p*p == p.product(p)
     2066             True
     2067             sage: p + vector(ZZ,[1,2,3]) == p.translation([1,2,3])
     2068             True
     2069        """
     2070        if is_Polyhedron(actor):
     2071            return self.product(actor)
     2072        if is_Vector(actor):
     2073            return self.translation(actor)
     2074        else:
     2075            return self.dilation(actor)
     2076
     2077    def __div__(self, scalar):
     2078        """
     2079        Divide by a scalar factor.
     2080
     2081        See :meth:`dilation` for details.
     2082
     2083        EXAMPLES::
     2084
    20392085            sage: p = Polyhedron(vertices = [[t,t^2,t^3] for t in srange(2,4)])
    2040             sage: p2 = 3*p + p
    2041             sage: p2.vertex_generator().next()
    2042             A vertex at (8, 16, 32)
     2086            sage: (p/5).Vrepresentation()
     2087            (A vertex at (2/5, 4/5, 8/5), A vertex at (3/5, 9/5, 27/5))
    20432088        """
    2044         return self.__mul__(other)
    2045 
    2046 
    2047     def union(self, other):
    2048         """
    2049         Deprecated.  Use ``self.convex_hull(other)`` instead.
    2050        
    2051         EXAMPLES::
    2052        
    2053             sage: Polyhedron(vertices=[[0]]).union( Polyhedron(vertices=[[1]]) )
    2054             doctest:...: DeprecationWarning:
    2055             The function union is replaced by convex_hull.
    2056             See http://trac.sagemath.org/11634 for details.
    2057             A 1-dimensional polyhedron in QQ^1 defined as the convex hull of 2 vertices
    2058         """
    2059         from sage.misc.superseded import deprecation
    2060         deprecation(11634, 'The function union is replaced by convex_hull.')
    2061         return self.convex_hull(other)
    2062 
    2063 
     2089        return self.dilation(1/scalar)
     2090
     2091    @coerce_binop
    20642092    def convex_hull(self, other):
    20652093        """
    20662094        Return the convex hull of the set-theoretic union of the two
     
    20872115        hull_vertices = self.vertices() + other.vertices()
    20882116        hull_rays = self.rays() + other.rays()
    20892117        hull_lines = self.lines() + other.lines()
    2090         hull_field = self.coerce_field(other)
    2091         return Polyhedron(vertices=hull_vertices,
    2092                           rays=hull_rays, lines=hull_lines,
    2093                           base_ring=hull_field)
    2094 
    2095 
     2118        return self.parent().element_class(self.parent(), [hull_vertices, hull_rays, hull_lines], None)
     2119
     2120    @coerce_binop
    20962121    def intersection(self, other):
    20972122        """
    20982123        Return the intersection of one polyhedron with another.
     
    21052130
    21062131        The intersection.
    21072132
     2133        Note that the intersection of two `\ZZ`-polyhedra might not be
     2134        a `\ZZ`-polyhedron. In this case, a `\QQ`-polyhedron is
     2135        returned.
     2136
    21082137        EXAMPLES::
    21092138
    21102139            sage: cube = polytopes.n_cube(3)
    21112140            sage: oct = polytopes.cross_polytope(3)
    2112             sage: cube_oct = cube.intersection(oct*2)
    2113             sage: len(list( cube_oct.vertex_generator() ))
    2114             12
    2115             sage: cube_oct
    2116             A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 12 vertices
     2141            sage: cube.intersection(oct*2)
     2142            A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 12 vertices
     2143
     2144       The intersection of two `\ZZ`-polyhedra is not necessarily a `\ZZ`-polyhedron::
     2145
     2146            sage: P = Polyhedron([(0,0),(1,1)], base_ring=ZZ)
     2147            sage: P.intersection(P)
     2148            A 1-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices
     2149            sage: Q = Polyhedron([(0,1),(1,0)], base_ring=ZZ)
     2150            sage: P.intersection(Q)
     2151            A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex
     2152            sage: _.Vrepresentation()
     2153            (A vertex at (1/2, 1/2),)
    21172154        """
    2118         new_ieqs = []
    2119         new_ieqs.extend(self.inequalities())
    2120         new_ieqs.extend(other.inequalities())
    2121 
    2122         new_eqns = []
    2123         new_eqns.extend(self.equations())
    2124         new_eqns.extend(other.equations())
    2125 
    2126         return Polyhedron(ieqs = new_ieqs, eqns = new_eqns,
    2127                           base_ring=self.coerce_field(other))
    2128 
     2155        new_ieqs = self.inequalities() + other.inequalities()
     2156        new_eqns = self.equations() + other.equations()
     2157        parent = self.parent()
     2158        try:
     2159            return parent.element_class(parent, None, [new_ieqs, new_eqns])
     2160        except TypeError,msg:
     2161            if self.base_ring() is ZZ:
     2162                parent = parent.base_extend(QQ)
     2163                return parent.element_class(parent, None, [new_ieqs, new_eqns])
     2164            else:
     2165                raise TypeError(msg)
    21292166
    21302167    def edge_truncation(self, cut_frac = Integer(1)/3):
    21312168        r"""
    21322169        Return a new polyhedron formed from two points on each edge
    21332170        between two vertices.
    2134        
     2171
    21352172        INPUT:
    2136        
     2173
    21372174        - ``cut_frac`` -- integer. how deeply to cut into the edge.
    21382175            Default is `\frac{1}{3}`.
    2139            
     2176
    21402177        OUTPUT:
    21412178
    21422179        A Polyhedron object, truncated as described above.
    2143            
     2180
    21442181        EXAMPLES::
    21452182
    21462183            sage: cube = polytopes.n_cube(3)
     
    21612198
    21622199        return Polyhedron(vertices=new_vertices, rays=new_rays,
    21632200                          lines=new_lines,
    2164                           base_ring=self.coerce_field(cut_frac))
     2201                          base_ring=self.parent()._coerce_base_ring(cut_frac))
    21652202
    21662203
    21672204    def _make_polyhedron_face(self, Vindices, Hindices):
     
    21782215          face.
    21792216
    21802217        OUTPUT:
    2181        
    2182         A new :class:`PolyhedronFace_base` instance. It is not checked
     2218
     2219        A new :class:`~sage.geometry.polyhedron.face.PolyhedronFace` instance. It is not checked
    21832220        whether the input data actually defines a face.
    21842221
    21852222        EXAMPLES::
     
    21882225            sage: square._make_polyhedron_face((0,2), (1,))
    21892226            <0,2>
    21902227        """
    2191         return PolyhedronFace_base(self, Vindices, Hindices)
    2192 
    2193 
     2228        from sage.geometry.polyhedron.face import PolyhedronFace
     2229        return PolyhedronFace(self, Vindices, Hindices)
     2230
     2231    @cached_method
    21942232    def face_lattice(self):
    21952233        """
    21962234        Return the face-lattice poset.
    21972235
    21982236        OUTPUT:
    2199        
     2237
    22002238        A :class:`~sage.combinat.posets.posets.FinitePoset`. Elements
    22012239        are given as
    2202         :class:`~sage.geometry.polyhedron.PolyhedronFace_base`.
     2240        :class:`~sage.geometry.polyhedron.face.PolyhedronFace`.
    22032241
    22042242        In the case of a full-dimensional polytope, the faces are
    22052243        pairs (vertices, inequalities) of the spanning vertices and
     
    22342272        * Lines are removed before calling
    22352273          :func:`Hasse_diagram_from_incidences`, and then added back
    22362274          to each face V-representation except for the "empty face".
    2237        
     2275
    22382276        * Equations are removed before calling
    22392277          :func:`Hasse_diagram_from_incidences`, and then added back
    22402278          to each face H-representation.
     
    22702308            (A vertex at (-1, -1), A vertex at (1, -1))
    22712309            sage: a_face.ambient_Hrepresentation()
    22722310            (An inequality (0, 1) x + 1 >= 0,)
    2273            
     2311
    22742312        A more complicated example::
    22752313
    22762314            sage: c5_10 = Polyhedron(vertices = [[i,i^2,i^3,i^4,i^5] for i in range(1,11)])
    22772315            sage: c5_10_fl = c5_10.face_lattice()
    22782316            sage: [len(x) for x in c5_10_fl.level_sets()]
    22792317            [1, 10, 45, 100, 105, 42, 1]
    2280            
     2318
    22812319        Note that if the polyhedron contains lines then there is a
    22822320        dimension gap between the empty face and the first non-empty
    22832321        face in the face lattice::
     
    23272365        REFERENCES:
    23282366
    23292367        ..  [KP2002]
    2330        
     2368
    23312369            Volker Kaibel and Marc E. Pfetsch, "Computing the Face
    23322370            Lattice of a Polytope from its Vertex-Facet Incidences",
    23332371            Computational Geometry: Theory and Applications, Volume
     
    23352373            http://portal.acm.org/citation.cfm?id=763203 and free of
    23362374            charge at http://arxiv.org/abs/math/0106043
    23372375        """
    2338         try:
    2339             return self._face_lattice
    2340         except AttributeError:
    2341             pass
    2342        
    23432376        coatom_to_Hindex = [ h.index() for h in self.inequality_generator() ]
    23442377        Hindex_to_coatom = [None] * self.n_Hrepresentation()
    23452378        for i in range(0,len(coatom_to_Hindex)):
    23462379            Hindex_to_coatom[ coatom_to_Hindex[i] ] = i
    2347            
     2380
    23482381        atom_to_Vindex = [ v.index() for v in self.Vrep_generator() if not v.is_line() ]
    23492382        Vindex_to_atom = [None] * self.n_Vrepresentation()
    23502383        for i in range(0,len(atom_to_Vindex)):
    23512384                        Vindex_to_atom[ atom_to_Vindex[i] ] = i
    2352            
     2385
    23532386        atoms_incidences   = [ tuple([ Hindex_to_coatom[h.index()]
    23542387                                       for h in v.incident() if h.is_inequality() ])
    23552388                               for v in self.Vrepresentation() if not v.is_line() ]
    2356        
     2389
    23572390        coatoms_incidences = [ tuple([ Vindex_to_atom[v.index()]
    23582391                                       for v in h.incident() if not v.is_line() ])
    23592392                               for h in self.Hrepresentation() if h.is_inequality() ]
    2360        
     2393
    23612394        atoms_vertices = [ Vindex_to_atom[v.index()] for v in self.vertex_generator() ]
    23622395        equations = [ e.index() for e in self.equation_generator() ]
    23632396        lines     = [ l.index() for l in self.line_generator() ]
     
    23712404            return self._make_polyhedron_face(Vindices, Hindices)
    23722405
    23732406        from sage.geometry.hasse_diagram import Hasse_diagram_from_incidences
    2374         self._face_lattice = Hasse_diagram_from_incidences\
     2407        return Hasse_diagram_from_incidences\
    23752408            (atoms_incidences, coatoms_incidences,
    23762409             face_constructor=face_constructor, required_atoms=atoms_vertices)
    2377         return self._face_lattice
    2378 
    2379 
     2410
     2411    def faces(self, face_dimension):
     2412        """
     2413        Return the faces of given dimension
     2414
     2415        INPUT:
     2416
     2417        - ``face_dimension`` -- integer.
     2418       
     2419        OUTPUT:
     2420       
     2421        A tuple of
     2422        :class:`~sage.geometry.polyhedron.face.PolyhedronFace`. See
     2423        :mod:`~sage.geometry.polyhedron.face` for details. The order
     2424        random but fixed.
     2425
     2426        EXAMPLES:
     2427
     2428        Here we find the vertex and face indices of the eight three-dimensional
     2429        facets of the four-dimensional hypercube::
     2430
     2431            sage: p = polytopes.n_cube(4)
     2432            sage: p.faces(3)
     2433            (<0,1,2,3,4,5,6,7>, <0,1,2,3,8,9,10,11>, <0,1,4,5,8,9,12,13>,
     2434             <0,2,4,6,8,10,12,14>, <2,3,6,7,10,11,14,15>, <8,9,10,11,12,13,14,15>,
     2435             <4,5,6,7,12,13,14,15>, <1,3,5,7,9,11,13,15>)
     2436
     2437            sage: face = p.faces(3)[0]
     2438            sage: face.ambient_Hrepresentation()
     2439            (An inequality (1, 0, 0, 0) x + 1 >= 0,)
     2440            sage: face.vertices()
     2441            (A vertex at (-1, -1, -1, -1), A vertex at (-1, -1, -1, 1),
     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
     2446        You can use the
     2447        :meth:`~sage.geometry.polyhedron.representation.PolyhedronRepresentation.index`
     2448        method to enumerate vertices and inequalities::
     2449
     2450            sage: def get_idx(rep): return rep.index()
     2451            sage: map(get_idx, face.ambient_Hrepresentation())
     2452            [4]
     2453            sage: map(get_idx, face.ambient_Vrepresentation())
     2454            [0, 1, 2, 3, 4, 5, 6, 7]
     2455
     2456            sage: [ (map(get_idx, face.ambient_Vrepresentation()), map(get_idx, face.ambient_Hrepresentation()))
     2457            ...     for face in p.faces(3) ]
     2458            [([0, 1, 2, 3, 4, 5, 6, 7], [4]),
     2459             ([0, 1, 2, 3, 8, 9, 10, 11], [5]),
     2460             ([0, 1, 4, 5, 8, 9, 12, 13], [6]),
     2461             ([0, 2, 4, 6, 8, 10, 12, 14], [7]),
     2462             ([2, 3, 6, 7, 10, 11, 14, 15], [2]),
     2463             ([8, 9, 10, 11, 12, 13, 14, 15], [0]),
     2464             ([4, 5, 6, 7, 12, 13, 14, 15], [1]),
     2465             ([1, 3, 5, 7, 9, 11, 13, 15], [3])]
     2466           
     2467        TESTS::
     2468
     2469            sage: pr = Polyhedron(rays = [[1,0,0],[-1,0,0],[0,1,0]], vertices = [[-1,-1,-1]], lines=[(0,0,1)])
     2470            sage: pr.faces(4)
     2471            ()
     2472            sage: pr.faces(3)
     2473            (<0,1,2,3>,)
     2474            sage: pr.faces(2)
     2475            (<0,1,2>,)
     2476            sage: pr.faces(1)
     2477            ()
     2478            sage: pr.faces(0)
     2479            ()
     2480            sage: pr.faces(-1)
     2481            ()
     2482        """
     2483        fl = self.face_lattice().level_sets()
     2484        codim = self.dim() - face_dimension
     2485        index = len(fl) - 1 - codim
     2486        if index>=len(fl) or index<1:
     2487            return tuple()
     2488        return tuple(face.element for face in fl[index])
     2489
     2490    @cached_method
    23802491    def f_vector(self):
    23812492        r"""
    23822493        Return the f-vector.
    23832494
    23842495        OUTPUT:
    2385        
     2496
    23862497        Returns a vector whose ``i``-th entry is the number of
    23872498        ``i``-dimensional faces of the polytope.
    23882499
     
    23932504            sage: p.f_vector()
    23942505            (1, 7, 12, 7, 1)
    23952506        """
    2396         try:
    2397             return self._f_vector
    2398         except AttributeError:
    2399             self._f_vector = vector(ZZ,[len(x) for x in self.face_lattice().level_sets()])
    2400             return self._f_vector
    2401 
    2402 
     2507        return vector(ZZ,[len(x) for x in self.face_lattice().level_sets()])
     2508
     2509    @cached_method
    24032510    def vertex_graph(self):
    24042511        """
    24052512        Return a graph in which the vertices correspond to vertices
     
    24142521            sage: s4.is_eulerian()
    24152522            True
    24162523        """
    2417         try:
    2418             return self._graph
    2419         except AttributeError:
    2420             self._graph = Graph(self.vertex_adjacency_matrix(), loops=True)
    2421             return self._graph
    2422 
     2524        return Graph(self.vertex_adjacency_matrix(), loops=True)
    24232525
    24242526    graph = vertex_graph
    24252527
    2426 
    24272528    def polar(self):
    24282529        """
    2429         Return the polar (dual) polytope.  The original vertices are
    2430         translated so that their barycenter is at the origin, and then
    2431         the vertices are used as the coefficients in the polar inequalities.
     2530        Return the polar (dual) polytope.
     2531
     2532        The original vertices are translated so that their barycenter
     2533        is at the origin, and then the vertices are used as the
     2534        coefficients in the polar inequalities.
    24322535
    24332536        EXAMPLES::
    24342537
    2435             sage: p = Polyhedron(vertices = [[0,0,1],[0,1,0],[1,0,0],[0,0,0],[1,1,1]])
     2538            sage: p = Polyhedron(vertices = [[0,0,1],[0,1,0],[1,0,0],[0,0,0],[1,1,1]], base_ring=QQ)
    24362539            sage: p
    24372540            A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 5 vertices
    24382541            sage: p.polar()
     
    24402543        """
    24412544        assert self.is_compact(), "Not a polytope."
    24422545
    2443         verts = [list(v() - self.center()) for v in self.vertex_generator()]
    2444         return Polyhedron(ieqs=[[1] + list(v) for v in verts],
    2445                           base_ring=self.base_ring())
    2446 
     2546        verts = [list(v.vector() - self.center()) for v in self.vertex_generator()]
     2547        base_ring = self.parent()._coerce_base_ring(self.center().parent().base_ring())
     2548        return Polyhedron(ieqs=[[1] + list(v) for v in verts], base_ring=base_ring)
    24472549
    24482550    def pyramid(self):
    24492551        """
     
    24512553
    24522554        EXAMPLES::
    24532555
    2454             sage: square = polytopes.n_cube(2)
    2455             sage: egyptian_pyramid = square.pyramid()
     2556            sage: square = polytopes.n_cube(2);  square
     2557            A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 4 vertices
     2558            sage: egyptian_pyramid = square.pyramid();  egyptian_pyramid
     2559            A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 5 vertices
    24562560            sage: egyptian_pyramid.n_vertices()
    24572561            5
    24582562            sage: for v in egyptian_pyramid.vertex_generator(): print v
     
    24632567            A vertex at (1, 0, 0)
    24642568        """
    24652569        new_verts = \
    2466             [[0] + list(x) for x in self.Vrep_generator()] + \
     2570            [[0] + x for x in self.Vrep_generator()] + \
    24672571            [[1] + list(self.center())]
    2468 
    2469         return Polyhedron(vertices = new_verts, base_ring=self.field())
    2470 
     2572        return Polyhedron(vertices=new_verts)
    24712573
    24722574    def bipyramid(self):
    24732575        """
     
    24892591             [0, 0, 1, 0],
    24902592             [0, 1, 0, 0],
    24912593             [1, 0, 0, 0]]
    2492        
     2594
    24932595        Now check that bipyramids of cross-polytopes are cross-polytopes::
    24942596
    24952597            sage: q2 = [list(v) for v in polytopes.cross_polytope(4).vertex_generator()]
     
    25022604            [[-1] + list(self.center())]
    25032605        new_rays = [[0] + r for r in self.rays()]
    25042606        new_lines = [[0] + list(l) for l in self.lines()]
    2505         return Polyhedron(vertices=new_verts,
    2506                           rays=new_rays, lines=new_lines, base_ring=self.field())
    2507 
     2607        return Polyhedron(vertices=new_verts, rays=new_rays, lines=new_lines)
    25082608
    25092609    def prism(self):
    25102610        """
     
    25152615            sage: square = polytopes.n_cube(2)
    25162616            sage: cube = square.prism()
    25172617            sage: cube
    2518             A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 8 vertices
     2618            A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices
    25192619            sage: hypercube = cube.prism()
    25202620            sage: hypercube.n_vertices()
    25212621            16
     
    25242624        new_verts.extend( [ [0] + v for v in self.vertices()] )
    25252625        new_verts.extend( [ [1] + v for v in self.vertices()] )
    25262626        new_rays =        [ [0] + r for r in self.rays()]
    2527         new_lines =       [ [0] + list(l) for l in self.lines()]
    2528         return Polyhedron(vertices=new_verts,
    2529                           rays=new_rays, lines=new_lines, base_ring=self.field())
    2530 
     2627        new_lines =       [ [0] + l for l in self.lines()]
     2628        return Polyhedron(vertices=new_verts, rays=new_rays, lines=new_lines,
     2629                          base_ring=self.base_ring())
    25312630
    25322631    def projection(self):
    25332632        """
     
    25442643        self.projection = Projection(self)
    25452644        return self.projection
    25462645
    2547 
    25482646    def render_solid(self, **kwds):
    25492647        """
    25502648        Return a solid rendering of a 2- or 3-d polytope.
     
    25632661            return proj.render_fill_2d(**kwds)
    25642662        raise ValueError, "render_solid is only defined for 2 and 3 dimensional polyhedra."
    25652663
    2566 
    25672664    def render_wireframe(self, **kwds):
    25682665        """
    25692666        For polytopes in 2 or 3 dimensions, return the edges
     
    25832680            return proj.render_outline_2d(**kwds)
    25842681        raise ValueError, "render_wireframe is only defined for 2 and 3 dimensional polyhedra."
    25852682
    2586 
    25872683    def schlegel_projection(self, projection_dir = None, height = 1.1):
    25882684        """
    25892685        Returns a projection object whose transformed coordinates are
     
    26002696        """
    26012697        proj = self.projection()
    26022698        if projection_dir == None:
    2603             v = self.vertices()
    2604             f0 = (self.facial_incidences()[0])[1]
    2605             projection_dir = [sum([v[f0[i]][j]/len(f0) for i in range(len(f0))])
    2606                               for j in range(len(v[0]))]
     2699            vertices = self.vertices()
     2700            facet = self.Hrepresentation(0)
     2701            f0 = [ v.index() for v in facet.incident() ]
     2702            projection_dir = [sum([vertices[f0[i]][j]/len(f0) for i in range(len(f0))])
     2703                              for j in range(self.ambient_dim())]
    26072704        return proj.schlegel(projection_direction = projection_dir, height = height)
    2608        
    26092705
    26102706    def lrs_volume(self, verbose = False):
    26112707        """
     
    26262722            2.0
    26272723
    26282724        REFERENCES:
    2629        
     2725
    26302726             David Avis's lrs program.
    26312727        """
    26322728        if is_package_installed('lrs') != True:
     
    26572753
    26582754        raise ValueError, "lrs did not return a volume"
    26592755
    2660 
    26612756    def contains(self, point):
    26622757        """
    26632758        Test whether the polyhedron contains the given ``point``.
     
    26742769        Boolean.
    26752770
    26762771        EXAMPLES::
    2677        
     2772
    26782773            sage: P = Polyhedron(vertices=[[1,1],[1,-1],[0,0]])
    26792774            sage: P.contains( [1,0] )
    26802775            True
     
    26952790            True
    26962791            sage: ray.contains(['hello', 'kitty'])   # no common ring for coordinates
    26972792            False
    2698            
     2793
    26992794        The empty polyhedron needs extra care, see trac #10238::
    27002795
    27012796            sage: empty = Polyhedron(); empty
    2702             The empty polyhedron in QQ^0
     2797            The empty polyhedron in ZZ^0
    27032798            sage: empty.contains([])
    27042799            False
    27052800            sage: empty.contains([0])               # not a point in QQ^0
    27062801            False
    27072802            sage: full = Polyhedron(vertices=[()]); full
    2708             A 0-dimensional polyhedron in QQ^0 defined as the convex hull of 1 vertex
     2803            A 0-dimensional polyhedron in ZZ^0 defined as the convex hull of 1 vertex
    27092804            sage: full.contains([])
    27102805            True
    27112806            sage: full.contains([0])
     
    27172812            if len(point)>0:
    27182813                return False
    27192814            else:
    2720                 p = vector(self.field(), [])
     2815                p = vector(self.base_ring(), [])
    27212816
    27222817        if len(p)!=self.ambient_dim():
    27232818            return False
    2724        
     2819
    27252820        for H in self.Hrep_generator():
    27262821            if not H.contains(p):
    27272822                return False
    27282823        return True
    27292824
    2730 
    27312825    def interior_contains(self, point):
    27322826        """
    27332827        Test whether the interior of the polyhedron contains the
     
    27372831        :meth:`relative_interior_contains`.
    27382832
    27392833        INPUT:
    2740        
     2834
    27412835        - ``point`` -- coordinates of a point.
    27422836
    27432837        OUTPUT:
    2744        
     2838
    27452839        ``True`` or ``False``.
    27462840
    27472841        EXAMPLES::
    2748        
     2842
    27492843            sage: P = Polyhedron(vertices=[[0,0],[1,1],[1,-1]])
    27502844            sage: P.contains( [1,0] )
    27512845            True
     
    27642858        The empty polyhedron needs extra care, see trac #10238::
    27652859
    27662860            sage: empty = Polyhedron(); empty
    2767             The empty polyhedron in QQ^0
     2861            The empty polyhedron in ZZ^0
    27682862            sage: empty.interior_contains([])
    27692863            False
    27702864        """
     
    27742868            if len(point)>0:
    27752869                return False
    27762870            else:
    2777                 p = vector(self.field(), [])
     2871                p = vector(self.base_ring(), [])
    27782872
    27792873        if len(p)!=self.ambient_dim():
    27802874            return False
    2781        
     2875
    27822876        for H in self.Hrep_generator():
    27832877            if not H.interior_contains(p):
    27842878                return False
    27852879        return True
    27862880
    2787 
    27882881    def relative_interior_contains(self, point):
    27892882        """
    27902883        Test whether the relative interior of the polyhedron
     
    27932886        See also :meth:`contains` and :meth:`interior_contains`.
    27942887
    27952888        INPUT:
    2796        
     2889
    27972890        - ``point`` -- coordinates of a point.
    27982891
    27992892        OUTPUT:
    2800        
     2893
    28012894        ``True`` or ``False``.
    28022895
    28032896        EXAMPLES::
    2804        
     2897
    28052898            sage: P = Polyhedron(vertices=[(1,0), (-1,0)])
    28062899            sage: P.contains( (0,0) )
    28072900            True
     
    28152908        The empty polyhedron needs extra care, see trac #10238::
    28162909
    28172910            sage: empty = Polyhedron(); empty
    2818             The empty polyhedron in QQ^0
     2911            The empty polyhedron in ZZ^0
    28192912            sage: empty.relative_interior_contains([])
    28202913            False
    28212914        """
     
    28252918            if len(point)>0:
    28262919                return False
    28272920            else:
    2828                 p = vector(self.field(), [])
     2921                p = vector(self.base_ring(), [])
    28292922
    28302923        if len(p)!=self.ambient_dim():
    28312924            return False
    2832          
     2925
    28332926        for eq in self.equation_generator():
    28342927            if not eq.contains(p):
    28352928                return False
     
    28432936    def is_simplex(self):
    28442937        r"""
    28452938        Return whether the polyhedron is a simplex.
    2846        
     2939
    28472940        EXAMPLES::
    28482941
    28492942            sage: Polyhedron([(0,0,0), (1,0,0), (0,1,0)]).is_simplex()
     
    28552948        """
    28562949        return self.is_compact() and (self.dim()+1==self.n_vertices())
    28572950
     2951    @cached_method
    28582952    def is_lattice_polytope(self):
    28592953        r"""
    28602954        Return whether the polyhedron is a lattice polytope.
    2861        
     2955
    28622956        OUTPUT:
    28632957
    28642958        ``True`` if the polyhedron is compact and has only integral
    28652959        vertices, ``False`` otherwise.
    2866        
     2960
    28672961        EXAMPLES::
    2868        
     2962
    28692963            sage: polytopes.cross_polytope(3).is_lattice_polytope()
    28702964            True
    28712965            sage: polytopes.regular_polygon(5).is_lattice_polytope()
    28722966            False
    28732967        """
    2874         try:
    2875             return self._is_lattice_polytope
    2876         except AttributeError:
    2877             pass
    2878         self._is_lattice_polytope = self.is_compact() and \
    2879             all(v.is_integral() for v in self.vertex_generator())
    2880         return self._is_lattice_polytope
    2881        
     2968        if not self.is_compact():
     2969            return False
     2970        if self.base_ring() is ZZ:
     2971            return True
     2972        return all(v.is_integral() for v in self.vertex_generator())
     2973
     2974    @cached_method
    28822975    def lattice_polytope(self, envelope=False):
    28832976        r"""
    28842977        Return an encompassing lattice polytope.
    2885        
     2978
    28862979        INPUT:
    28872980
    28882981        - ``envelope`` -- boolean (default: ``False``). If the
     
    29133006        is returned.
    29143007
    29153008        EXAMPLES:
    2916        
     3009
    29173010        First, a polyhedron with integral vertices::
    29183011
    29193012            sage: P = Polyhedron( vertices = [(1, 0), (0, 1), (-1, 0), (0, -1)])
     
    29413034        if not self.is_compact():
    29423035            raise NotImplementedError, 'Only compact lattice polytopes are allowed.'
    29433036
    2944         def nonintegral_error():
    2945             raise ValueError, 'Some vertices are not integral. '+\
    2946                 'You probably want to add the argument '+\
    2947                 '"envelope=True" to compute an enveloping lattice polytope.'
    2948 
    2949         # try to make use of cached values, if possible
    2950         if envelope:
    2951             try:
    2952                 return self._lattice_polytope
    2953             except AttributeError:
    2954                 pass
    2955         else:
    2956             try:
    2957                 assert self._is_lattice_polytope
    2958                 return self._lattice_polytope
    2959             except AttributeError:
    2960                 pass
    2961             except AssertionError:
    2962                 nonintegral_error()
    2963 
    2964         # find the integral vertices
    29653037        try:
    2966             vertices = matrix(ZZ, self.vertices()).transpose()
    2967             self._is_lattice_polytope = True
     3038            vertices = self.vertices_matrix(ZZ)
    29683039        except TypeError:
    2969             self._is_lattice_polytope = False
    2970             if envelope==False: nonintegral_error()
     3040            if envelope==False:
     3041                raise ValueError, 'Some vertices are not integral. '+\
     3042                    'You probably want to add the argument '+\
     3043                    '"envelope=True" to compute an enveloping lattice polytope.'
    29713044            vertices = []
    29723045            for v in self.vertex_generator():
    29733046                vbox = [ set([floor(x),ceil(x)]) for x in v ]
     
    29763049
    29773050        # construct the (enveloping) lattice polytope
    29783051        from sage.geometry.lattice_polytope import LatticePolytope
    2979         self._lattice_polytope = LatticePolytope(vertices)
    2980         return self._lattice_polytope
     3052        return LatticePolytope(vertices)
    29813053
    29823054    def _integral_points_PALP(self):
    29833055        r"""
     
    29863058        This method is for testing purposes and will eventually be removed.
    29873059
    29883060        OUTPUT:
    2989        
     3061
    29903062        The list of integral points in the polyhedron. If the
    29913063        polyhedron is not compact, a ``ValueError`` is raised.
    29923064
    29933065        EXAMPLES::
    2994        
     3066
    29953067            sage: Polyhedron(vertices=[(-1,-1),(1,0),(1,1),(0,1)])._integral_points_PALP()
    29963068            [(-1, -1), (0, 1), (1, 0), (1, 1), (0, 0)]
    29973069            sage: Polyhedron(vertices=[(-1/2,-1/2),(1,0),(1,1),(0,1)]).lattice_polytope(True).points()
     
    30243096
    30253097        - ``integral`` -- Boolean (default: ``False``). Whether to
    30263098          only allow integral coordinates in the bounding box.
    3027        
     3099
    30283100        OUTPUT:
    30293101
    30303102        A pair of tuples ``(box_min, box_max)`` where ``box_min`` are
     
    30453117        box_max = []
    30463118        if self.n_vertices==0:
    30473119            raise ValueError('Empty polytope is not allowed')
     3120        if not self.is_compact():
     3121            raise ValueError('Only polytopes (compact polyhedra) are allowed.')
    30483122        for i in range(0,self.ambient_dim()):
    3049             coords = [ v[i] for v in self.Vrep_generator() ]
     3123            coords = [ v[i] for v in self.vertex_generator() ]
    30503124            max_coord = max(coords)
    30513125            min_coord = min(coords)
    30523126            if integral:
     
    30563130                box_max.append(max_coord)
    30573131                box_min.append(min_coord)
    30583132        return (tuple(box_min), tuple(box_max))
    3059        
     3133
    30603134    def integral_points(self, threshold=100000):
    30613135        r"""
    30623136        Return the integral points in the polyhedron.
     
    30703144          algorith as long as the bounding box is smaller than this.
    30713145
    30723146        OUTPUT:
    3073        
     3147
    30743148        The list of integral points in the polyhedron. If the
    30753149        polyhedron is not compact, a ``ValueError`` is raised.
    30763150
    30773151        EXAMPLES::
    3078        
     3152
    30793153            sage: Polyhedron(vertices=[(-1,-1),(1,0),(1,1),(0,1)]).integral_points()
    30803154            ((-1, -1), (0, 0), (0, 1), (1, 0), (1, 1))
    30813155
     
    31033177
    31043178            sage: v = [(1,0,7,-1), (-2,-2,4,-3), (-1,-1,-1,4), (2,9,0,-5), (-2,-1,5,1)]
    31053179            sage: simplex = Polyhedron(v); simplex
    3106             A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 5 vertices
     3180            A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 5 vertices
    31073181            sage: len(simplex.integral_points())
    31083182            49
    31093183
     
    31523226            points.update(new_points)
    31533227        # assert all(self.contains(p) for p in points)   # slow
    31543228        return tuple(points)
    3155    
     3229
     3230    @cached_method
    31563231    def combinatorial_automorphism_group(self):
    31573232        """
    31583233        Computes the combinatorial automorphism group of the vertex
     
    31713246        chosen to be shifted by ``+1``. That is, ``i`` in the
    31723247        permutation group corresponds to the V-representation object
    31733248        ``self.Vrepresentation(i-1)``.
    3174        
     3249
    31753250        EXAMPLES::
    3176        
     3251
    31773252            sage: quadrangle = Polyhedron(vertices=[(0,0),(1,0),(0,1),(2,3)])
    31783253            sage: quadrangle.combinatorial_automorphism_group()
    31793254            Permutation Group with generators [(2,3), (1,2)(3,4)]
     
    31873262            sage: P.combinatorial_automorphism_group()
    31883263            Permutation Group with generators [(3,4)]
    31893264        """
    3190         if '_combinatorial_automorphism_group' in self.__dict__:
    3191             return self._combinatorial_automorphism_group
    3192 
    31933265        from sage.groups.perm_gps.permgroup import PermutationGroup
    3194 
    31953266        G = Graph()
    31963267        for edge in self.vertex_graph().edges():
    31973268            i = edge[0]
     
    32093280        self._combinatorial_automorphism_group = group
    32103281        return group
    32113282
    3212 
    32133283    def _affine_coordinates(self, Vrep_object):
    32143284        r"""
    32153285        Return affine coordinates for a V-representation object.
    3216        
     3286
    32173287        INPUT:
    32183288
    32193289        - ``v`` -- a V-representation object or any iterable
     
    32273297        A ``self.dim()``-dimensional coordinate vector. It contains
    32283298        the coordinates of ``v`` in an arbitrary but fixed basis for
    32293299        the affine span of the polyhedron.
    3230        
     3300
    32313301        EXAMPLES::
    3232        
     3302
    32333303            sage: P = Polyhedron(rays=[(1,0,0),(0,1,0)])
    32343304            sage: P._affine_coordinates( (-1,-2,-3) )
    32353305            (-1, -2)
     
    32433313                v_list = [ v - origin for v in v_list ]
    32443314            coordinates = matrix(v_list)
    32453315            self._affine_coordinates_pivots = coordinates.pivots()
    3246    
     3316
    32473317        v = list(Vrep_object)
    32483318        if len(v) != self.ambient_dim():
    32493319            raise ValueError('Incorrect dimension: '+str(v))
    32503320
    3251         return vector(self.field(), [ v[i] for i in self._affine_coordinates_pivots ])
    3252        
    3253 
     3321        return vector(self.base_ring(), [ v[i] for i in self._affine_coordinates_pivots ])
     3322
     3323    @cached_method
    32543324    def restricted_automorphism_group(self):
    32553325        r"""
    32563326        Return the restricted automorphism group.
     
    32683338        generators with line generators.
    32693339
    32703340        For example, take the first quadrant
    3271        
     3341
    32723342        .. MATH::
    3273        
     3343
    32743344            Q = \Big\{ (x,y) \Big| x\geq 0,\; y\geq0 \Big\}
    32753345            \subset \QQ^2
    3276            
     3346
    32773347        Then the linear automorphism group is
    3278        
     3348
    32793349        .. MATH::
    32803350
    32813351            \mathrm{Aut}(Q) =
     
    33193389        A :class:`PermutationGroup<sage.groups.perm_gps.permgroup.PermutationGroup_generic>`
    33203390        that is isomorphic to the restricted automorphism group is
    33213391        returned.
    3322        
     3392
    33233393        Note that in Sage, permutation groups always act on positive
    33243394        integers while ``self.Vrepresentation()`` is indexed by
    33253395        nonnegative integers. The indexing of the permutation group is
     
    33873457
    33883458        Floating-point computations are supported with a simple fuzzy
    33893459        zero implementation::
    3390        
     3460
    33913461            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)
    33923462            sage: P.restricted_automorphism_group()
    33933463            Permutation Group with generators [(2,3), (1,2)]
     
    33983468            sage: p.restricted_automorphism_group()
    33993469            Permutation Group with generators [(2,3)]
    34003470        """
    3401         if '_restricted_automorphism_group' in self.__dict__:
    3402             return self._restricted_automorphism_group
    3403 
    34043471        from sage.groups.perm_gps.permgroup import PermutationGroup
    34053472
    3406         if self.field() is QQ:
     3473        if self.base_ring() is ZZ or self.base_ring() is QQ:
    34073474            def rational_approximation(c):
    34083475                return c
    34093476
    3410         else:  # self.field() is RDF
     3477        elif self.base_ring() is RDF:
    34113478            c_list = []
    34123479            def rational_approximation(c):
    34133480                # Implementation detail: Return unique integer if two
     
    34193486                        return i
    34203487                c_list.append(c)
    34213488                return len(c_list)-1
    3422        
     3489
    34233490        # The algorithm identifies the restricted automorphism group
    34243491        # with the automorphism group of a edge-colored graph. The
    34253492        # nodes of the graph are the V-representation objects. If all
     
    34763543
    34773544
    34783545
    3479 
    3480 
    3481 
    3482 #########################################################################
    3483 class PolyhedronFace_base(SageObject):
    3484     r"""
    3485     A face of a polyhedron.
    3486    
    3487     This class is for use in
    3488     :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.face_lattice`.
    3489 
    3490     INPUT:
    3491 
    3492     No checking is performed whether the H/V-representation indices
    3493     actually determine a face of the polyhedron. You should not
    3494     manually create :class:`PolyhedronFace_base` objects unless you know
    3495     what you are doing.
    3496 
    3497     OUTPUT:
    3498 
    3499     A :class:`PolyhedronFace_base`.
    3500 
    3501     EXAMPLES::
    3502 
    3503         sage: octahedron = polytopes.cross_polytope(3)
    3504         sage: inequality = octahedron.Hrepresentation(2)
    3505         sage: face_h = tuple([ inequality ])
    3506         sage: face_v = tuple( inequality.incident() )
    3507         sage: face_h_indices = [ h.index() for h in face_h ]
    3508         sage: face_v_indices = [ v.index() for v in face_v ]
    3509         sage: from sage.geometry.polyhedron.base import PolyhedronFace_base
    3510         sage: face = PolyhedronFace_base(octahedron, face_v_indices, face_h_indices)
    3511         sage: face
    3512         <0,1,2>
    3513         sage: face.dim()
    3514         2
    3515         sage: face.ambient_Hrepresentation()
    3516         (An inequality (1, 1, 1) x + 1 >= 0,)
    3517         sage: face.ambient_Vrepresentation()
    3518         (A vertex at (-1, 0, 0), A vertex at (0, -1, 0), A vertex at (0, 0, -1))
    3519     """
    3520 
    3521     def __init__(self, polyhedron, V_indices, H_indices):
    3522         r"""
    3523         The constructor.
    3524 
    3525         See :class:`PolyhedronFace_base` for more information.
    3526 
    3527         INPUT:
    3528 
    3529         - ``polyhedron`` -- a :class:`Polyhedron`. The ambient
    3530           polyhedron.
    3531 
    3532         - ``V_indices`` -- list of integers. The indices of the
    3533           face-spanning V-representation objects in the ambient
    3534           polyhedron.
    3535 
    3536         - ``H_indices`` -- list of integers. The indices of the
    3537           H-representation objects of the ambient polyhedron that are
    3538           saturated on the face.
    3539        
    3540         TESTS::
    3541 
    3542             sage: from sage.geometry.polyhedron.base import PolyhedronFace_base
    3543             sage: PolyhedronFace_base(Polyhedron(), [], [])   # indirect doctest
    3544             <>
    3545         """
    3546         self._polyhedron = polyhedron
    3547         self._ambient_Vrepresentation_indices = tuple(V_indices)
    3548         self._ambient_Hrepresentation_indices = tuple(H_indices)
    3549         self._ambient_Vrepresentation = tuple( polyhedron.Vrepresentation(i) for i in V_indices )
    3550         self._ambient_Hrepresentation = tuple( polyhedron.Hrepresentation(i) for i in H_indices )
    3551         # self._Vrepresentation =
    3552         # self._Hrepresentation =
    3553        
    3554 
    3555     def ambient_Hrepresentation(self, index=None):
    3556         r"""
    3557         Return the H-representation objects of the ambient polytope
    3558         defining the face.
    3559        
    3560         INPUT:
    3561        
    3562         - ``index`` -- optional. Either an integer or ``None``
    3563           (default).
    3564 
    3565         OUTPUT:
    3566        
    3567         If the optional argument is not present, a tuple of
    3568         H-representation objects. Each entry is either an inequality
    3569         or an equation.
    3570 
    3571         If the optional integer ``index`` is specified, the
    3572         ``index``-th element of the tuple is returned.
    3573 
    3574         EXAMPLES::
    3575          
    3576             sage: square = polytopes.n_cube(2)
    3577             sage: for fl in square.face_lattice():
    3578             ...       print fl.element.ambient_Hrepresentation()
    3579             ...
    3580             (An inequality (1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0,
    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 (0, 1) x + 1 >= 0, An inequality (-1, 0) x + 1 >= 0)
    3585             (An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0)
    3586             (An inequality (1, 0) x + 1 >= 0,)
    3587             (An inequality (0, 1) x + 1 >= 0,)
    3588             (An inequality (-1, 0) x + 1 >= 0,)
    3589             (An inequality (0, -1) x + 1 >= 0,)
    3590             ()
    3591         """
    3592         if index==None:
    3593             return self._ambient_Hrepresentation
    3594         else:
    3595             return self._ambient_Hrepresentation[index]
    3596        
    3597 
    3598     def ambient_Vrepresentation(self, index=None):
    3599         r"""
    3600         Return the V-representation objects of the ambient polytope
    3601         defining the face.
    3602 
    3603         INPUT:
    3604        
    3605         - ``index`` -- optional. Either an integer or ``None``
    3606           (default).
    3607 
    3608         OUTPUT:
    3609        
    3610         If the optional argument is not present, a tuple of
    3611         V-representation objects. Each entry is either a vertex, a
    3612         ray, or a line.
    3613 
    3614         If the optional integer ``index`` is specified, the
    3615         ``index``-th element of the tuple is returned.
    3616        
    3617         EXAMPLES::
    3618          
    3619             sage: square = polytopes.n_cube(2)
    3620             sage: for fl in square.face_lattice():
    3621             ...       print fl.element.ambient_Vrepresentation()
    3622             ...
    3623             ()
    3624             (A vertex at (-1, -1),)
    3625             (A vertex at (-1, 1),)
    3626             (A vertex at (1, -1),)
    3627             (A vertex at (1, 1),)
    3628             (A vertex at (-1, -1), 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         """
    3635         if index==None:
    3636             return self._ambient_Vrepresentation
    3637         else:
    3638             return self._ambient_Vrepresentation[index]
    3639 
    3640 
    3641     def n_ambient_Hrepresentation(self):
    3642         """
    3643         Return the number of objects that make up the ambient
    3644         H-representation of the polyhedron.
    3645 
    3646         See also :meth:`ambient_Hrepresentation`.
    3647 
    3648         OUTPUT:
    3649 
    3650         Integer.
    3651 
    3652         EXAMPLES::
    3653 
    3654             sage: p = polytopes.cross_polytope(4)
    3655             sage: face = p.face_lattice()[10].element
    3656             sage: face
    3657             <0,2>
    3658             sage: face.ambient_Hrepresentation()
    3659             (An inequality (1, -1, 1, -1) x + 1 >= 0,
    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             sage: face.n_ambient_Hrepresentation()
    3664             4
    3665         """
    3666         return len(self._ambient_Hrepresentation)
    3667 
    3668 
    3669     def n_ambient_Vrepresentation(self):
    3670         """
    3671         Return the number of objects that make up the ambient
    3672         V-representation of the polyhedron.
    3673 
    3674         See also :meth:`ambient_Vrepresentation`.
    3675 
    3676         OUTPUT:
    3677 
    3678         Integer.
    3679 
    3680         EXAMPLES::
    3681 
    3682             sage: p = polytopes.cross_polytope(4)
    3683             sage: face = p.face_lattice()[10].element
    3684             sage: face
    3685             <0,2>
    3686             sage: face.ambient_Vrepresentation()
    3687             (A vertex at (-1, 0, 0, 0), A vertex at (0, 0, -1, 0))
    3688             sage: face.n_ambient_Vrepresentation()
    3689             2
    3690         """
    3691         return len(self._ambient_Vrepresentation)
    3692 
    3693 
    3694     def dim(self):
    3695         """
    3696         Return the dimension of the face.
    3697        
    3698         OUTPUT:
    3699        
    3700         Integer.
    3701        
    3702         EXAMPLES::
    3703 
    3704             sage: fl = polytopes.dodecahedron().face_lattice()
    3705             sage: [ x.element.dim() for x in fl ]
    3706             [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    3707               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    3708               1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3]
    3709         """
    3710         if '_dim' in self.__dict__:
    3711             return self._dim
    3712 
    3713         if self.n_ambient_Vrepresentation()==0:
    3714             self._dim = -1
    3715         else:
    3716             origin = vector(self.ambient_Vrepresentation(0))
    3717             v_list = [ vector(v)-origin for v in self.ambient_Vrepresentation() ]
    3718             self._dim = matrix(v_list).rank()
    3719         return self._dim
    3720 
    3721 
    3722     def _repr_(self):
    3723         r"""
    3724         Return a string representation.
    3725 
    3726         OUTPUT:
    3727 
    3728         A string listing the V-representation indices of the face.
    3729 
    3730         EXAMPLES::
    3731 
    3732             sage: square = polytopes.n_cube(2)
    3733             sage: a_face = list( square.face_lattice() )[8].element
    3734             sage: a_face.__repr__()
    3735             '<1,3>'
    3736         """
    3737         s = '<'
    3738         s += ','.join([ str(v.index()) for v in self.ambient_Vrepresentation() ])
    3739         s += '>'
    3740         return s
    3741 
  • 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
     333        EXAMPLES::