Ticket #12159: trac_12159_placing_triangulation.patch

File trac_12159_placing_triangulation.patch, 39.0 KB (added by vbraun, 10 years ago)

Initial patch

  • sage/geometry/polyhedra.py

    # HG changeset patch
    # User Volker Braun <vbraun@stp.dias.ie>
    # Date 1323978224 0
    # Node ID 9d0d38fe091ce0784d9ba8a4263eb1fc5836988a
    # Parent  ae07be5b23656ab77ad7735dd36b32369e2bcce5
    Trac #12159: Placing triangulation and normal cones
    
    This patch implements the placing triangulation.
    
    diff --git a/sage/geometry/polyhedra.py b/sage/geometry/polyhedra.py
    a b  
    35043504        :meth:`Vrepresentation` objects.
    35053505       
    35063506        EXAMPLES::
    3507 
     3507       
    35083508            sage: cube = polytopes.n_cube(3)
    35093509            sage: triangulation = cube.triangulate(engine='internal') # to make doctest independent of TOPCOM
    35103510            sage: triangulation
    3511             (<0,1,2,4>, <1,2,3,4>, <1,3,4,5>, <2,3,4,6>, <3,4,5,6>, <3,5,6,7>)
     3511            (<0,1,2,7>, <0,1,4,7>, <0,2,4,7>, <1,2,3,7>, <1,4,5,7>, <2,4,6,7>)
    35123512            sage: simplex_indices = triangulation[0]; simplex_indices
    3513             (0, 1, 2, 4)
     3513            (0, 1, 2, 7)
    35143514            sage: simplex_vertices = [ cube.Vrepresentation(i) for i in simplex_indices ]
    35153515            sage: simplex_vertices
    35163516            [A vertex at (1, 1, 1), A vertex at (-1, 1, 1),
    3517              A vertex at (1, -1, 1), A vertex at (1, 1, -1)]
     3517             A vertex at (1, -1, 1), A vertex at (-1, -1, -1)]
    35183518            sage: Polyhedron(simplex_vertices)
    35193519            A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices.
    35203520        """
  • sage/geometry/triangulation/base.pyx

    diff --git a/sage/geometry/triangulation/base.pyx b/sage/geometry/triangulation/base.pyx
    a b  
    2424from sage.categories.sets_cat import Sets
    2525from sage.matrix.constructor import matrix
    2626from sage.misc.misc import uniq
     27from sage.misc.cachefunc import cached_method
    2728
    2829from functions cimport binomial
    2930from triangulations cimport \
     
    4849
    4950    INPUT:
    5051
     52    - ``point_configuration`` -- :class:`PointConfiguration_base`. The
     53      point configuration to which the point belongs.
     54
    5155    - ``i`` -- integer. The index of the point in the point
    5256      configuration.
    5357
     
    6064
    6165    EXAMPLES::
    6266     
     67        sage: pc = PointConfiguration([(0,0)])
    6368        sage: from sage.geometry.triangulation.base import Point
    64         sage: Point(123, (0,0,1), (0,0), (0,))
     69        sage: Point(pc, 123, (0,0,1), (0,0), ())
    6570        P(0, 0)
    6671    """
    6772
    6873    cdef int _index
    6974    cdef tuple _projective, _affine, _reduced_affine
     75    cdef object _point_configuration
     76    cdef object _reduced_affine_vector, _reduced_projective_vector
    7077
    71     def __init__(self, i, projective, affine, reduced):
     78
     79    def __init__(self, point_configuration, i, projective, affine, reduced):
    7280        r"""
    7381        Construct a :class:`Point`.
    7482       
    7583        EXAMPLES::
    76      
     84       
     85            sage: pc = PointConfiguration([(0,0)])
    7786            sage: from sage.geometry.triangulation.base import Point
    78             sage: Point(123, (0,0,1), (0,0), (0,))   # indirect doctest
     87            sage: Point(pc, 123, (0,0,1), (0,0), ())   # indirect doctest
    7988            P(0, 0)
    8089        """
    8190        self._index = i
    8291        self._projective = tuple(projective)
    8392        self._affine = tuple(affine)
    8493        self._reduced_affine = tuple(reduced)
     94        self._point_configuration = point_configuration
     95        V = point_configuration.reduced_affine_vector_space()
     96        self._reduced_affine_vector = V(self._reduced_affine)
     97        P = point_configuration.reduced_projective_vector_space()
     98        self._reduced_projective_vector = P(self.reduced_projective())
     99
     100
     101    cpdef point_configuration(self):
     102        r"""
     103        Return the point configuration to which the point belongs.
     104       
     105        OUTPUT:
     106
     107        A :class:`~sage.geometry.triangulation.point_configuration.PointConfiguration`.
     108
     109        EXAMPLES:
     110
     111            sage: pc = PointConfiguration([ (0,0), (1,0), (0,1) ])
     112            sage: p = pc.point(0)
     113            sage: p is pc.point(0)
     114            True
     115            sage: p.point_configuration() is pc
     116            True
     117        """
     118        return self._point_configuration
    85119
    86120
    87121    def __iter__(self):
     
    90124       
    91125        EXAMPLES::
    92126     
     127            sage: pc = PointConfiguration([(0,0)])
    93128            sage: from sage.geometry.triangulation.base import Point
    94             sage: p = Point(123, (1,2,1), (3,4), (5,))
     129            sage: p = Point(pc, 123, (1,2,1), (3,4), ())
    95130            sage: list(p)  # indirect doctest
    96131            [3, 4]
    97132        """
     
    104139       
    105140        EXAMPLES::
    106141       
     142            sage: pc = PointConfiguration([(0,0)])
    107143            sage: from sage.geometry.triangulation.base import Point
    108             sage: p = Point(123, (1,2,1), (3,4), (5,))
     144            sage: p = Point(pc, 123, (1,2,1), (3,4), ())
    109145            sage: len(p)
    110146            2
    111147            sage: p.__len__()
     
    133169        r"""
    134170        Return the projective coordinates of the point in the ambient space.
    135171
    136         EXAMPLES::
    137        
    138             sage: pc = PointConfiguration([[10, 0, 1], [10, 0, 0], [10, 2, 3]])
    139             sage: p = pc.point(2); p
    140             P(10, 2, 3)
    141             sage: p.affine()
    142             (10, 2, 3)
    143             sage: p.projective()
    144             (10, 2, 3, 1)
    145             sage: p.reduced_affine()
    146             (2, 2)
    147             sage: p.reduced_projective()
    148             (2, 2, 1)
    149         """
    150         return self._projective
     172        OUTPUT:
    151173
    152    
    153     cpdef affine(self):
    154         r"""
    155         Return the affine coordinates of the point in the ambient space.
     174        A tuple containing the coordinates.
    156175
    157176        EXAMPLES::
    158177       
     
    167186            (2, 2)
    168187            sage: p.reduced_projective()
    169188            (2, 2, 1)
     189            sage: p.reduced_affine_vector()
     190            (2, 2)
    170191        """
    171         return self._affine
     192        return self._projective
    172193
    173194   
    174     cpdef reduced_affine(self):
     195    cpdef affine(self):
    175196        r"""
    176         Return the affine coordinates of the point on the hyperplane
    177         spanned by the point configuration.
     197        Return the affine coordinates of the point in the ambient space.
     198
     199        OUTPUT:
     200
     201        A tuple containing the coordinates.
    178202
    179203        EXAMPLES::
    180204       
     
    189213            (2, 2)
    190214            sage: p.reduced_projective()
    191215            (2, 2, 1)
     216            sage: p.reduced_affine_vector()
     217            (2, 2)
    192218        """
    193         return self._reduced_affine
     219        return self._affine
    194220
     221   
     222    cpdef reduced_affine(self):
     223        r"""
     224        Return the affine coordinates of the point on the hyperplane
     225        spanned by the point configuration.
    195226
    196     cpdef reduced_projective(self):
    197         r"""
    198         Return the projective coordinates of the point on the hyperplane
    199         spanned by the point configuration.
     227        OUTPUT:
     228
     229        A tuple containing the coordinates.
    200230
    201231        EXAMPLES::
    202232       
     
    211241            (2, 2)
    212242            sage: p.reduced_projective()
    213243            (2, 2, 1)
     244            sage: p.reduced_affine_vector()
     245            (2, 2)
     246        """
     247        return self._reduced_affine
     248
     249
     250    cpdef reduced_projective(self):
     251        r"""
     252        Return the projective coordinates of the point on the hyperplane
     253        spanned by the point configuration.
     254
     255        OUTPUT:
     256
     257        A tuple containing the coordinates.
     258
     259        EXAMPLES::
     260       
     261            sage: pc = PointConfiguration([[10, 0, 1], [10, 0, 0], [10, 2, 3]])
     262            sage: p = pc.point(2); p
     263            P(10, 2, 3)
     264            sage: p.affine()
     265            (10, 2, 3)
     266            sage: p.projective()
     267            (10, 2, 3, 1)
     268            sage: p.reduced_affine()
     269            (2, 2)
     270            sage: p.reduced_projective()
     271            (2, 2, 1)
     272            sage: p.reduced_affine_vector()
     273            (2, 2)
    214274        """
    215275        return tuple(self._reduced_affine)+(1,)
    216276
    217277   
     278    cpdef reduced_affine_vector(self):
     279        """
     280        Return the affine coordinates of the point on the hyperplane
     281        spanned by the point configuration.
     282
     283        OUTPUT:
     284
     285        A tuple containing the coordinates.
     286
     287        EXAMPLES::
     288       
     289            sage: pc = PointConfiguration([[10, 0, 1], [10, 0, 0], [10, 2, 3]])
     290            sage: p = pc.point(2); p
     291            P(10, 2, 3)
     292            sage: p.affine()
     293            (10, 2, 3)
     294            sage: p.projective()
     295            (10, 2, 3, 1)
     296            sage: p.reduced_affine()
     297            (2, 2)
     298            sage: p.reduced_projective()
     299            (2, 2, 1)
     300            sage: p.reduced_affine_vector()
     301            (2, 2)
     302        """
     303        return self._reduced_affine_vector
     304
     305
     306    cpdef reduced_projective_vector(self):
     307        """
     308        Return the affine coordinates of the point on the hyperplane
     309        spanned by the point configuration.
     310
     311        OUTPUT:
     312
     313        A tuple containing the coordinates.
     314
     315        EXAMPLES::
     316       
     317            sage: pc = PointConfiguration([[10, 0, 1], [10, 0, 0], [10, 2, 3]])
     318            sage: p = pc.point(2); p
     319            P(10, 2, 3)
     320            sage: p.affine()
     321            (10, 2, 3)
     322            sage: p.projective()
     323            (10, 2, 3, 1)
     324            sage: p.reduced_affine()
     325            (2, 2)
     326            sage: p.reduced_projective()
     327            (2, 2, 1)
     328            sage: p.reduced_affine_vector()
     329            (2, 2)
     330            sage: type(p.reduced_affine_vector())
     331            <type 'sage.modules.vector_rational_dense.Vector_rational_dense'>
     332        """
     333        return self._reduced_projective_vector
     334
     335
    218336    cpdef _repr_(self):
    219337        """
    220338        Return a string representation of the point.
    221339
     340        OUTPUT:
     341       
     342        String.
     343       
    222344        EXAMPLES::
    223345
     346            sage: pc = PointConfiguration([[10, 0, 1], [10, 0, 0]])
    224347            sage: from sage.geometry.triangulation.base import Point
    225             sage: p = Point(123, (0,0,1), (0,0), (0,))
     348            sage: p = Point(pc, 123, (0,0,1), (0,0), (0,))
    226349            sage: p._repr_()
    227350            'P(0, 0)'
    228351        """
     
    242365        :class:`~sage.geometry.triangulation.point_configuration.PointConfiguration`.
    243366    """
    244367
    245     def __init__(self, points):
     368    def __init__(self, points, defined_affine):
    246369        r"""
    247370        Construct a :class:`PointConfiguration_base`.
    248371       
     
    251374        - ``points`` -- a tuple of tuples of projective coordinates
    252375          with ``1`` as the final coordinate.
    253376       
     377        - ``defined_affine`` -- Boolean. Whether the point
     378          configuration is defined as a configuration of affine (as
     379          opposed to projective) points.
     380
    254381        TESTS::
    255382       
    256383            sage: from sage.geometry.triangulation.base import PointConfiguration_base
    257             sage: PointConfiguration_base(((1,2,1),(2,3,1),(3,4,1)))  # indirect doctest
     384            sage: PointConfiguration_base(((1,2,1),(2,3,1),(3,4,1)), False)  # indirect doctest
    258385            <type 'sage.geometry.triangulation.base.PointConfiguration_base'>
    259386        """
    260387        Parent.__init__(self, category = Sets())
    261388        self._init_points(points)
     389        self._is_affine = defined_affine
    262390
    263391
    264     cpdef tuple _pts
    265     cpdef int _ambient_dim
    266     cpdef int _dim
    267     cpdef object _base_ring
     392    cdef tuple _pts
     393    cdef int _ambient_dim
     394    cdef int _dim
     395    cdef object _base_ring
     396    cdef bint _is_affine
     397    cdef object _reduced_affine_vector_space, _reduced_projective_vector_space
     398
    268399
    269400    cdef _init_points(self, tuple projective_points):
    270401        """
     
    316447            red = matrix([ red.row(i) for i in red.pivot_rows()])
    317448        else:
    318449            red = matrix(0,1)
     450        self._dim = red.nrows()
    319451
    320         self._pts = tuple([ Point(i, proj.column(i), aff.column(i), red.column(i))
     452        from sage.modules.free_module import VectorSpace
     453        self._reduced_affine_vector_space = VectorSpace(self._base_ring.fraction_field(), self._dim)
     454        self._reduced_projective_vector_space = VectorSpace(self._base_ring.fraction_field(), self._dim+1)
     455        self._pts = tuple([ Point(self, i, proj.column(i), aff.column(i), red.column(i))
    321456                           for i in range(0,n) ])
    322         self._dim = len(self._pts[0].reduced_affine())
    323457                 
    324458
     459    cpdef reduced_affine_vector_space(self):
     460        """
     461        Return the vector space that contains the affine points.
     462       
     463        OUTPUT:
     464
     465        A vector space over the fraction field of :meth:`base_ring`.
     466       
     467        EXAMPLES::
     468
     469            sage: p = PointConfiguration([[0,0,0], [1,2,3]])
     470            sage: p.base_ring()
     471            Integer Ring
     472            sage: p.reduced_affine_vector_space()
     473            Vector space of dimension 1 over Rational Field
     474            sage: p.reduced_projective_vector_space()
     475            Vector space of dimension 2 over Rational Field
     476        """
     477        return self._reduced_affine_vector_space
     478
     479
     480    cpdef reduced_projective_vector_space(self):
     481        """
     482        Return the vector space that is spanned by the homogeneous
     483        coordinates.
     484       
     485        OUTPUT:
     486
     487        A vector space over the fraction field of :meth:`base_ring`.
     488       
     489        EXAMPLES::
     490
     491            sage: p = PointConfiguration([[0,0,0], [1,2,3]])
     492            sage: p.base_ring()
     493            Integer Ring
     494            sage: p.reduced_affine_vector_space()
     495            Vector space of dimension 1 over Rational Field
     496            sage: p.reduced_projective_vector_space()
     497            Vector space of dimension 2 over Rational Field
     498        """
     499        return self._reduced_projective_vector_space
     500
     501
    325502    cpdef ambient_dim(self):
    326503        """
    327504        Return the dimension of the ambient space of the point
     
    331508
    332509        EXAMPLES::
    333510       
    334             sage: p = PointConfiguration([[0,0,0]]);
     511            sage: p = PointConfiguration([[0,0,0]])
    335512            sage: p.ambient_dim()
    336513            3
    337514            sage: p.dim()
     
    349526
    350527        EXAMPLES::
    351528       
    352             sage: p = PointConfiguration([[0,0,0]]);
     529            sage: p = PointConfiguration([[0,0,0]])
    353530            sage: p.ambient_dim()
    354531            3
    355532            sage: p.dim()
     
    369546
    370547        EXAMPLES::
    371548
    372             sage: p = PointConfiguration([(0,0)]);
     549            sage: p = PointConfiguration([(0,0)])
    373550            sage: p.base_ring()
    374551            Integer Ring
    375552
    376             sage: p = PointConfiguration([(1/2,3)]);
     553            sage: p = PointConfiguration([(1/2,3)])
    377554            sage: p.base_ring()
    378555            Rational Field
    379556           
    380             sage: p = PointConfiguration([(0.2, 5)]);
     557            sage: p = PointConfiguration([(0.2, 5)])
    381558            sage: p.base_ring()
    382559            Real Field with 53 bits of precision
    383560        """
    384561        return self._base_ring
    385562
    386563
     564    cpdef bint is_affine(self):
     565        """
     566        Whether the configuration is defined by affine points.
     567
     568        OUTPUT:
     569       
     570        Boolean. If true, the homogeneous coordinates all have `1` as
     571        their last entry.
     572       
     573        EXAMPLES::
     574
     575            sage: p = PointConfiguration([(0.2, 5), (3, 0.1)])
     576            sage: p.is_affine()
     577            True
     578
     579            sage: p = PointConfiguration([(0.2, 5, 1), (3, 0.1, 1)], projective=True)
     580            sage: p.is_affine()
     581            False
     582        """
     583        return self._is_affine
     584
     585
     586    def _assert_is_affine(self):
     587        """
     588        Raise a ``ValueError`` if the point configuration is not
     589        defined by affine points.
     590
     591        EXAMPLES::
     592
     593            sage: p = PointConfiguration([(0.2, 5), (3, 0.1)])
     594            sage: p._assert_is_affine()
     595            sage: p = PointConfiguration([(0.2, 5, 1), (3, 0.1, 1)], projective=True)
     596            sage: p._assert_is_affine()
     597            Traceback (most recent call last):
     598            ...
     599            ValueError: The point configuration contains projective points.
     600        """
     601        if not self.is_affine():
     602            raise ValueError('The point configuration contains projective points.')
     603
     604
    387605    def __getitem__(self, i):
    388606        """
    389607        Return the ``i``-th point.
     
    400618       
    401619        EXAMPLES::
    402620
    403             sage: p = PointConfiguration([[1,0], [2,3], [3,2]]);
     621            sage: p = PointConfiguration([[1,0], [2,3], [3,2]])
    404622            sage: [ p[i] for i in range(0,p.n_points()) ]
    405623            [P(1, 0), P(2, 3), P(3, 2)]
    406624            sage: list(p)
  • sage/geometry/triangulation/element.py

    diff --git a/sage/geometry/triangulation/element.py b/sage/geometry/triangulation/element.py
    a b  
    1212
    1313EXAMPLES::
    1414
     15    sage: PointConfiguration.set_engine('internal')   # to make doctests independent of TOPCOM
     16
    1517    sage: p = [[0,-1,-1],[0,0,1],[0,1,0], [1,-1,-1],[1,0,1],[1,1,0]]
    1618    sage: points = PointConfiguration(p)
    1719    sage: triang = points.triangulate()
     
    439441
    440442            sage: p = PointConfiguration([[0,0],[1,0],[2,1],[1,2],[0,1]])
    441443            sage: p.triangulate().gkz_phi()
     444            (3, 1, 5, 2, 4)
     445            sage: p.lexicographic_triangulation().gkz_phi()
    442446            (1, 3, 4, 2, 5)
    443447
    444448        NOTE:
     
    564568        EXAMPLES::
    565569
    566570            sage: p = polytopes.cuboctahedron()
    567             sage: sc = p.triangulate().simplicial_complex()
     571            sage: sc = p.triangulate(engine='internal').simplicial_complex()
    568572            sage: sc   
    569             Simplicial complex with 12 vertices and 16 facets
     573            Simplicial complex with 12 vertices and 17 facets
     574
     575        Any convex set is contractable, so its reduced homology groups vanish::
     576           
     577            sage: sc.homology()
     578            {0: 0, 1: 0, 2: 0, 3: 0}
    570579        """
    571580        from sage.homology.simplicial_complex import SimplicialComplex
    572581        from sage.misc.all import flatten
  • sage/geometry/triangulation/point_configuration.py

    diff --git a/sage/geometry/triangulation/point_configuration.py b/sage/geometry/triangulation/point_configuration.py
    a b  
    1818
    1919Finding a single triangulation and listing all connected
    2020triangulations is implemented natively in this package. However, for
    21 more advanced options [TOPCOM]_ needs to be installed. You can find an
    22 experimental spkg at http://trac.sagemath.org/sage_trac/ticket/8169
     21more advanced options [TOPCOM]_ needs to be installed. It is available
     22as an optional package for Sage, and you can install it with the
     23command::
    2324
    24 NOTE:
     25    sage: install_package('TOPCOM')     # not tested
    2526
    26 TOPCOM and the internal algorithms tend to enumerate triangulations in
    27 a different order. This is why we always explicitly specify the engine
    28 as ``engine='TOPCOM'`` or ``engine='internal'`` in the doctests. In
    29 your own applications, you do not need to specify the engine. By
    30 default, TOPCOM is used if it is available and the internal algorithms
    31 are used otherwise.
     27.. note::
     28
     29    TOPCOM and the internal algorithms tend to enumerate
     30    triangulations in a different order. This is why we always
     31    explicitly specify the engine as ``engine='TOPCOM'`` or
     32    ``engine='internal'`` in the doctests. In your own applications,
     33    you do not need to specify the engine. By default, TOPCOM is used
     34    if it is available and the internal algorithms are used otherwise.
    3235
    3336EXAMPLES:
    3437
    3538First, we select the internal implementation for enumerating
    3639triangulations::
    3740
    38    sage: PointConfiguration.set_engine('internal')   # to make doctests independent of TOPCOM
     41    sage: PointConfiguration.set_engine('internal')   # to make doctests independent of TOPCOM
    3942
    4043A 2-dimensional point configuration::
    4144
     
    100103    sage: pc.dim()
    101104    3
    102105    sage: pc.triangulate()
    103     (<0,1,2,3>, <1,2,3,4>, <2,3,4,5>, <3,4,5,6>)
     106    (<0,1,2,6>, <0,1,3,6>, <0,2,3,6>, <1,2,4,6>, <1,3,4,6>, <2,3,5,6>, <2,4,5,6>)
     107    sage: _ in pc.triangulations()
     108    True
    104109    sage: len( pc.triangulations_list() )
    105110    26
    106111
     
    133138    - Volker Braun: Cythonized parts of it, added a C++ implementation
    134139      of the bistellar flip algorithm to enumerate all connected
    135140      triangulations.
     141     
     142    - Volker Braun 2011: switched the triangulate() method to the
     143      placing triangulation (faster).
    136144"""
    137145
    138146########################################################################
     
    156164
    157165from sage.structure.unique_representation import UniqueRepresentation
    158166from sage.structure.element import Element
     167from sage.misc.cachefunc import cached_method
    159168
    160169from sage.combinat.combination import Combinations
    161170from sage.rings.all import QQ, ZZ
     
    282291            sage: pc1 is pc2   # indirect doctest
    283292            True
    284293        """
    285         if isinstance(points, PointConfiguration):
     294        if isinstance(points, PointConfiguration_base):
     295            pc = points
    286296            points = tuple( p.projective() for p in points )
    287297            projective = True
     298            defined_affine = pc.is_affine()
    288299        elif projective:
    289300            points = tuple( tuple(p) for p in points )
     301            defined_affine = False
    290302        else:
    291303            points = tuple( tuple(p)+(1,) for p in points )
     304            defined_affine = True
    292305        if star!=None and star not in ZZ:
    293306            star_point = tuple(star)
    294307            if len(star_point)<len(points[0]):
    295308                star_point = tuple(star)+(1,)
    296309            star = points.index(star_point)
    297310        return super(PointConfiguration, cls)\
    298             .__classcall__(cls, points, connected, fine, regular, star)
     311            .__classcall__(cls, points, connected, fine, regular, star, defined_affine)
    299312
    300313 
    301     def __init__(self, points, connected, fine, regular, star):
     314    def __init__(self, points, connected, fine, regular, star, defined_affine):
    302315        """
    303316        Initialize a :class:`PointConfiguration` object.
    304317
     
    331344        assert star==None or star in ZZ, 'Unknown value: fine='+str(star)
    332345        self._star = star
    333346       
    334         PointConfiguration_base.__init__(self, points)
     347        PointConfiguration_base.__init__(self, points, defined_affine)
    335348
    336349
    337350    @classmethod
     
    413426            sage: p = PointConfiguration([[0, 1], [0, 0], [1, 0], [1,1]])
    414427            sage: loads(p.dumps()) is p
    415428            True
     429
     430            sage: p = PointConfiguration([[0, 1, 1], [0, 0, 1], [1, 0, 1], [1,1, 1]], projective=True)
     431            sage: loads(p.dumps()) is p
     432            True
    416433        """
    417         points = tuple( p.projective() for p in self )
    418         return (PointConfiguration, (points, True, self._connected, self._fine, self._regular, self._star))
     434        if self.is_affine():
     435            points = tuple( p.affine() for p in self )
     436            return (PointConfiguration, (points, False,
     437                                         self._connected, self._fine, self._regular, self._star))
     438        else:
     439            points = tuple( p.projective() for p in self )
     440            return (PointConfiguration, (points, True,
     441                                         self._connected, self._fine, self._regular, self._star))
    419442
    420443
    421444    def an_element(self):
     
    479502
    480503        TESTS::
    481504
    482             sage: p = PointConfiguration([[1, 1, 1], [-1, 1, 1], [1, -1, 1], [-1, -1, 1], [1, 1, -1], [-1, 1, -1], [1, -1, -1], [-1, -1, -1], [0, 0, 0]])
     505            sage: p = PointConfiguration([[1,1,1],[-1,1,1],[1,-1,1],[-1,-1,1],[1,1,-1],
     506            ...                           [-1,1,-1],[1,-1,-1],[-1,-1,-1],[0,0,0]])
    483507            sage: p._repr_()
    484             'A point configuration in QQ^3 consisting of 9 points. The triangulations of this point configuration are assumed to be connected, not necessarily fine, not necessarily regular.'
     508            'A point configuration in QQ^3 consisting of 9 points. The triangulations
     509            of this point configuration are assumed to be connected, not necessarily
     510            fine, not necessarily regular.'
     511
     512            sage: PointConfiguration([[1, 1, 1], [-1, 1, 1], [1, -1, 1], [-1, -1, 1]], projective=True)
     513            A point configuration in P(QQ^3) consisting of 4 points. The triangulations
     514            of this point configuration are assumed to be connected, not necessarily
     515            fine, not necessarily regular.
    485516        """
    486517        s = 'A point configuration'
    487         s += ' in QQ^'+str(self.ambient_dim())
     518        if self.is_affine():
     519            s += ' in QQ^'+str(self.ambient_dim())
     520        else:
     521            s += ' in P(QQ^'+str(self.ambient_dim()+1)+')'
    488522        if len(self)==1:
    489523            s += ' consisting of '+str(len(self))+' point. '
    490524        else:
     
    10201054                pass
    10211055
    10221056        if self._connected and not self._fine and self._regular!=False and self._star==None:
    1023             return self.lexicographic_triangulation()
     1057            return self.placing_triangulation()
    10241058
    10251059        try:
    10261060            return self.triangulations(verbose).next()
     
    10771111        integers while lists etc. are indexed by nonnegative
    10781112        integers. The indexing of the permutation group is chosen to
    10791113        be shifted by ``+1``. That is, the transposition ``(i,j)`` in
    1080         the permutation group corresponds to exchange of `self[i-1]``
    1081         and `self[j-1]`.
     1114        the permutation group corresponds to exchange of ``self[i-1]``
     1115        and ``self[j-1]``.
    10821116
    10831117        EXAMPLES::
    10841118
     
    12381272
    12391273        OUTPUT:
    12401274       
    1241         * If a simplex was passed as an argument: n!*(volume of the simplex simp).
     1275        * If a simplex was passed as an argument: n!*(volume of ``simplex``).
    12421276
    12431277        * Without argument: n!*(the total volume of the convex hull).
    12441278
     
    12541288            1
    12551289
    12561290        The square can be triangulated into two minimal simplices, so
    1257         in the "integral" normalization ts volume equals two::
     1291        in the "integral" normalization its volume equals two::
    12581292           
    12591293            sage: p.volume()
    12601294            2
    12611295
    1262         NOTES:
     1296        .. note::
    12631297
    1264         We need to have n!*(volume of the simplex) to ensure that
    1265         the volume is an integer.  Essentially, this normalizes things so that
    1266         the volume of the standard n-simplex is 1.  See [GKZ]_ page 182.
     1298            We return n!*(metric volume of the simplex) to ensure that
     1299            the volume is an integer.  Essentially, this normalizes
     1300            things so that the volume of the standard n-simplex is 1.
     1301            See [GKZ]_ page 182.
    12671302        """
    12681303        if (simplex==None):
    12691304            return sum([ self.volume(s) for s in self.triangulate() ])
    12701305       
    12711306        #Form a matrix whose columns are the points of simplex
    12721307        #with the first point of simplex shifted to the origin.
    1273         v = [ vector(self.point(i).reduced_affine()) for i in simplex ]
    1274         m = matrix([ v_i - v[0] for v_i in v[1:] ]).transpose()
     1308        v = [ self.point(i).reduced_affine_vector() for i in simplex ]
     1309        m = matrix([ v_i - v[0] for v_i in v[1:] ])
    12751310        return abs(m.det())
    12761311
    12771312
     
    14621497
    14631498        OUTPUT:
    14641499
    1465         A tuple of all circuits with `C_- = ` ``negative``.
     1500        A tuple of all circuits with `C_-` = ``negative``.
    14661501
    14671502        EXAMPLE::
    14681503
     
    16151650        return self(triangulation)
    16161651
    16171652
     1653    @cached_method
     1654    def distance_affine(self, x, y):
     1655        r"""
     1656        Returns the distance between two points.
     1657       
     1658        The distance function used in this method is `d_{aff}(x,y)^2`,
     1659        the square of the usual affine distance function
     1660
     1661        .. math::
     1662
     1663            d_{aff}(x,y) = |x-y|
     1664
     1665        INPUT:
     1666
     1667        - ``x``, ``y`` -- two points of the point configuration.
     1668
     1669        OUTPUT:
     1670
     1671        The metric distance-square `d_{aff}(x,y)^2`. Note that this
     1672        distance lies in the same field as the entries of ``x``,
     1673        ``y``. That is, the distance of rational points will be
     1674        rational and so on.
     1675
     1676        EXAMPLES::
     1677
     1678            sage: pc = PointConfiguration([(0,0),(1,0),(2,1),(1,2),(0,1)])
     1679            sage: [ pc.distance_affine(pc.point(0), p) for p in pc.points() ]
     1680            [0, 1, 5, 5, 1]
     1681        """
     1682        self._assert_is_affine()
     1683        d = 0
     1684        for xi, yi in zip(x.projective(), y.projective()):
     1685            d += (xi-yi)**2
     1686        return d
     1687
     1688
     1689    @cached_method
     1690    def distance_FS(self, x, y):
     1691        r"""
     1692        Returns the distance between two points.
     1693
     1694        The distance function used in this method is `1-\cos
     1695        d_{FS}(x,y)^2`, where `d_{FS}` is the Fubini-Study distance of
     1696        projective points. Recall the Fubini-Studi distance function
     1697
     1698        .. math::
     1699
     1700            d_{FS}(x,y) = \arccos \sqrt{ \frac{(x\cdot y)^2}{|x|^2 |y|^2} }
     1701
     1702        INPUT:
     1703
     1704        - ``x``, ``y`` -- two points of the point configuration.
     1705
     1706        OUTPUT:
     1707
     1708        The distance `1-\cos d_{FS}(x,y)^2`. Note that this distance
     1709        lies in the same field as the entries of ``x``, ``y``. That
     1710        is, the distance of rational points will be rational and so
     1711        on.
     1712
     1713        EXAMPLES::
     1714
     1715            sage: pc = PointConfiguration([(0,0),(1,0),(2,1),(1,2),(0,1)])
     1716            sage: [ pc.distance_FS(pc.point(0), p) for p in pc.points() ]
     1717            [0, 1/2, 5/6, 5/6, 1/2]
     1718        """
     1719        x2 = y2 = xy = 0
     1720        for xi, yi in zip(x.projective(), y.projective()):
     1721            x2 += xi*xi
     1722            y2 += yi*yi
     1723            xy += xi*yi
     1724        return 1-xy*xy/(x2*y2)
     1725
     1726   
     1727    @cached_method
     1728    def distance(self, x, y):
     1729        """
     1730        Returns the distance between two points.
     1731
     1732        INPUT:
     1733
     1734        - ``x``, ``y`` -- two points of the point configuration.
     1735
     1736        OUTPUT:
     1737       
     1738        The distance between ``x`` and ``y``, measured either with
     1739        :meth:`distance_affine` or :meth:`distance_FS` depending on
     1740        whether the point configuration is defined by affine or
     1741        projective points. These are related, but not equal to the
     1742        usual flat and Fubini-Study distance.
     1743
     1744        EXAMPLES::
     1745
     1746            sage: pc = PointConfiguration([(0,0),(1,0),(2,1),(1,2),(0,1)])
     1747            sage: [ pc.distance(pc.point(0), p) for p in pc.points() ]
     1748            [0, 1, 5, 5, 1]
     1749
     1750            sage: pc = PointConfiguration([(0,0,1),(1,0,1),(2,1,1),(1,2,1),(0,1,1)], projective=True)
     1751            sage: [ pc.distance(pc.point(0), p) for p in pc.points() ]
     1752            [0, 1/2, 5/6, 5/6, 1/2]
     1753        """
     1754        if self.is_affine():
     1755            return self.distance_affine(x,y)
     1756        else:
     1757            return self.distance_FS(x,y)
     1758
     1759
     1760    def farthest_point(self, points, among=None):
     1761        """
     1762        Return the point with the most distance from ``points``.
     1763       
     1764        INPUT:
     1765       
     1766        - ``points`` -- a list of points.
     1767
     1768        - ``among`` -- a list of points or ``None`` (default). The set
     1769          of points from which to pick the farthest one. By default,
     1770          all points of the configuration are considered.
     1771
     1772        OUTPUT:
     1773
     1774        A :class:`~sage.geometry.triangulation.base.Point` with
     1775        largest minimal distance from all given ``points``.
     1776       
     1777        EXAMPLES::
     1778
     1779            sage: pc = PointConfiguration([(0,0),(1,0),(1,1),(0,1)])
     1780            sage: pc.farthest_point([ pc.point(0) ])
     1781            P(1, 1)
     1782        """
     1783        if len(points)==0:
     1784            return self.point(0)
     1785        if among is None:
     1786            among = self.points()
     1787        p_max = None
     1788        for p in among:
     1789            if p in points:
     1790                continue
     1791            if p_max is None:
     1792                p_max = p
     1793                d_max = min(self.distance(p,q) for q in points)
     1794                continue
     1795            d = min(self.distance(p,q) for q in points)
     1796            if d>d_max:
     1797                p_max = p
     1798        return p_max
     1799
     1800
     1801    def contained_simplex(self, large=True, initial_point=None):
     1802        """
     1803        Return a simplex contained in the point configuration.
     1804
     1805        INPUT:
     1806
     1807        - ``large`` -- boolean. Whether to attempt to return a large
     1808          simplex.
     1809
     1810        - ``initial_point`` -- a
     1811          :class:`~sage.geometry.triangulation.base.Point` or ``None``
     1812          (default). A specific point to start with when picking the
     1813          simplex vertices.
     1814
     1815        OUTPUT:
     1816
     1817        A tuple of points that span a simplex of dimension
     1818        :meth:`dim`. If ``large==True``, the simplex is constructed by
     1819        sucessively picking the farthest point. This will ensure that
     1820        the simplex is not unneccessarily small, but will in general
     1821        not return a maximal simplex.
     1822
     1823        EXAMPLES::
     1824
     1825            sage: pc = PointConfiguration([(0,0),(1,0),(2,1),(1,1),(0,1)])
     1826            sage: pc.contained_simplex()
     1827            (P(0, 1), P(2, 1), P(1, 0))
     1828            sage: pc.contained_simplex(large=False)
     1829            (P(0, 1), P(1, 1), P(1, 0))
     1830            sage: pc.contained_simplex(initial_point=pc.point(0))
     1831            (P(0, 0), P(1, 1), P(1, 0))
     1832
     1833            sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])
     1834            sage: pc.contained_simplex()
     1835            (P(-1, -1), P(1, 1), P(0, 1))
     1836
     1837        TESTS::
     1838
     1839            sage: pc = PointConfiguration([[0,0],[0,1],[1,0]])
     1840            sage: pc.contained_simplex()
     1841            (P(1, 0), P(0, 1), P(0, 0))
     1842            sage: pc = PointConfiguration([[0,0],[0,1]])
     1843            sage: pc.contained_simplex()
     1844            (P(0, 1), P(0, 0))
     1845            sage: pc = PointConfiguration([[0,0]])
     1846            sage: pc.contained_simplex()
     1847            (P(0, 0),)
     1848            sage: pc = PointConfiguration([])
     1849            sage: pc.contained_simplex()
     1850            ()
     1851        """
     1852        self._assert_is_affine()
     1853        if self.n_points()==0:
     1854            return tuple()
     1855        points = list(self.points())
     1856        if initial_point is None:
     1857            origin = points.pop()
     1858        else:
     1859            origin = initial_point
     1860            points.remove(origin)
     1861        vertices = [origin]
     1862        edges = []
     1863        while len(vertices) <= self.dim():
     1864            if large:
     1865                p = self.farthest_point(vertices, points)
     1866                points.remove(p)
     1867            else:
     1868                p = points.pop()
     1869            edge = p.reduced_affine_vector()-origin.reduced_affine_vector()
     1870            if len(edges)>0 and (ker * edge).is_zero():
     1871                continue
     1872            vertices.append(p)
     1873            edges.append(edge)
     1874            ker = matrix(edges).right_kernel().matrix()
     1875        return tuple(vertices)
     1876
     1877
     1878    def placing_triangulation(self, point_order=None):
     1879        r"""
     1880        Construct the placing (pushing) triangulation.
     1881
     1882        INPUT:
     1883
     1884        - ``point_order`` -- list of points or integers. The order in
     1885          which the points are to be placed.
     1886         
     1887        OUTPUT:
     1888
     1889        A :class:`~sage.geometry.triangulation.triangulation.Triangulation`.
     1890       
     1891        EXAMPLES::
     1892
     1893            sage: pc = PointConfiguration([(0,0),(1,0),(2,1),(1,2),(0,1)])
     1894            sage: pc.placing_triangulation()
     1895            (<0,1,2>, <0,2,4>, <2,3,4>)
     1896
     1897            sage: U=matrix([
     1898            ...      [ 0, 0, 0, 0, 0, 2, 4,-1, 1, 1, 0, 0, 1, 0],
     1899            ...      [ 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0],
     1900            ...      [ 0, 2, 0, 0, 0, 0,-1, 0, 1, 0, 1, 0, 0, 1],
     1901            ...      [ 0, 1, 1, 0, 0, 1, 0,-2, 1, 0, 0,-1, 1, 1],
     1902            ...      [ 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0]
     1903            ...   ])
     1904            sage: p = PointConfiguration(U.columns())
     1905            sage: triangulation = p.placing_triangulation();  triangulation
     1906            (<0,2,3,4,6,7>, <0,2,3,4,6,12>, <0,2,3,4,7,13>, <0,2,3,4,12,13>,
     1907             <0,2,3,6,7,13>, <0,2,3,6,12,13>, <0,2,4,6,7,13>, <0,2,4,6,12,13>,
     1908             <0,3,4,6,7,12>, <0,3,4,7,12,13>, <0,3,6,7,12,13>, <0,4,6,7,12,13>,
     1909             <1,3,4,5,6,12>, <1,3,4,6,11,12>, <1,3,4,7,11,13>, <1,3,4,11,12,13>,
     1910             <1,3,6,7,11,13>, <1,3,6,11,12,13>, <1,4,6,7,11,13>, <1,4,6,11,12,13>,
     1911             <3,4,6,7,11,12>, <3,4,7,11,12,13>, <3,6,7,11,12,13>, <4,6,7,11,12,13>)
     1912            sage: sum(p.volume(t) for t in triangulation)
     1913            42
     1914        """
     1915        facet_normals = dict()
     1916        def facets_of_simplex(simplex):
     1917            """
     1918            Return the facets of the simplex and store the normals in facet_normals
     1919            """
     1920            simplex = list(simplex)
     1921            origin = simplex[0]
     1922            rest = simplex[1:]
     1923            span = matrix([ origin.reduced_affine_vector()-p.reduced_affine_vector()
     1924                            for p in rest ])
     1925            # span.inverse() linearly transforms the simplex into the unit simplex
     1926            normals = span.inverse().columns()
     1927            facets = []
     1928            # The facets incident to the chosen vertex "origin"
     1929            for opposing_vertex, normal in zip(rest, normals):
     1930                facet = frozenset([origin] + [ p for p in rest if p is not opposing_vertex ])
     1931                facets.append(facet)
     1932                normal.set_immutable()
     1933                facet_normals[facet] = normal
     1934            # The remaining facet that is not incident to "origin"
     1935            facet = frozenset(rest)
     1936            normal = -sum(normals)
     1937            normal.set_immutable()
     1938            facet_normals[facet] = normal
     1939            facets.append(facet)
     1940            return set(facets)
     1941       
     1942        # input verification
     1943        self._assert_is_affine()
     1944        if point_order is None:
     1945            point_order = list(self.points())
     1946        elif isinstance(point_order[0], Point):
     1947            point_order = list(point_order)
     1948            assert all(p.point_configuration()==self for p in point_order)
     1949        else:
     1950            point_order = [ self.point(i) for i in point_order ]
     1951        assert all(p in self.points() for p in point_order)
     1952
     1953        # construct the initial simplex
     1954        simplices = [ frozenset(self.contained_simplex()) ]
     1955        for s in simplices[0]:
     1956            try:
     1957                point_order.remove(s)
     1958            except ValueError:
     1959                pass
     1960        facets = facets_of_simplex(simplices[0])
     1961       
     1962        # successively place the remaining points
     1963        for point in point_order:
     1964            # identify visible facets
     1965            visible_facets = []
     1966            for facet in facets:
     1967                origin = iter(facet).next()
     1968                normal = facet_normals[facet]
     1969                v = point.reduced_affine_vector() - origin.reduced_affine_vector()
     1970                if v*normal>0:
     1971                    visible_facets.append(facet)
     1972
     1973            # construct simplices over each visible facet
     1974            new_facets = set()
     1975            for facet in visible_facets:
     1976                simplex = frozenset(list(facet) + [point])
     1977                # print 'simplex', simplex
     1978                simplices.append(simplex)
     1979                for facet in facets_of_simplex(simplex):
     1980                    if facet in visible_facets: continue
     1981                    if facet in new_facets:
     1982                        new_facets.remove(facet)
     1983                        continue
     1984                    new_facets.add(facet)
     1985            facets.difference_update(visible_facets)
     1986            facets.update(new_facets)
     1987
     1988        # construct the triangulation
     1989        triangulation = [ [p.index() for p in simplex] for simplex in simplices ]
     1990        return self(triangulation)
     1991           
     1992    pushing_triangulation = placing_triangulation
     1993
     1994