Path: blob/master/sage/geometry/triangulation/base.pyx
4072 views
r"""1Base classes for triangulations23We provide (fast) cython implementations here.45AUTHORS:67- Volker Braun (2010-09-14): initial version.8"""91011########################################################################12# Copyright (C) 2010 Volker Braun <[email protected]>13#14# Distributed under the terms of the GNU General Public License (GPL)15#16# http://www.gnu.org/licenses/17########################################################################18192021from sage.structure.sage_object cimport SageObject22from sage.structure.parent cimport Parent23from sage.categories.sets_cat import Sets24from sage.matrix.constructor import matrix25from sage.misc.misc import uniq26from sage.misc.cachefunc import cached_method2728from functions cimport binomial29from triangulations cimport \30triangulations_ptr, init_triangulations, next_triangulation, delete_triangulations313233########################################################################34cdef class Point(SageObject):35r"""36A point of a point configuration.3738Note that the coordinates of the points of a point configuration39are somewhat arbitrary. What counts are the abstract linear40relations between the points, for example encoded by the41:meth:`~sage.geometry.triangulation.point_configuration.PointConfiguration.circuits`.4243.. Warning::4445You should not create :class:`Point` objects manually. The46constructor of :class:`PointConfiguration_base` takes care of47this for you.4849INPUT:5051- ``point_configuration`` -- :class:`PointConfiguration_base`. The52point configuration to which the point belongs.5354- ``i`` -- integer. The index of the point in the point55configuration.5657- ``projective`` -- the projective coordinates of the point.5859- ``affine`` -- the affine coordinates of the point.6061- ``reduced`` -- the reduced (with linearities removed)62coordinates of the point.6364EXAMPLES::6566sage: pc = PointConfiguration([(0,0)])67sage: from sage.geometry.triangulation.base import Point68sage: Point(pc, 123, (0,0,1), (0,0), ())69P(0, 0)70"""7172cdef int _index73cdef tuple _projective, _affine, _reduced_affine74cdef object _point_configuration75cdef object _reduced_affine_vector, _reduced_projective_vector767778def __init__(self, point_configuration, i, projective, affine, reduced):79r"""80Construct a :class:`Point`.8182EXAMPLES::8384sage: pc = PointConfiguration([(0,0)])85sage: from sage.geometry.triangulation.base import Point86sage: Point(pc, 123, (0,0,1), (0,0), ()) # indirect doctest87P(0, 0)88"""89self._index = i90self._projective = tuple(projective)91self._affine = tuple(affine)92self._reduced_affine = tuple(reduced)93self._point_configuration = point_configuration94V = point_configuration.reduced_affine_vector_space()95self._reduced_affine_vector = V(self._reduced_affine)96P = point_configuration.reduced_projective_vector_space()97self._reduced_projective_vector = P(self.reduced_projective())9899100cpdef point_configuration(self):101r"""102Return the point configuration to which the point belongs.103104OUTPUT:105106A :class:`~sage.geometry.triangulation.point_configuration.PointConfiguration`.107108EXAMPLES:109110sage: pc = PointConfiguration([ (0,0), (1,0), (0,1) ])111sage: p = pc.point(0)112sage: p is pc.point(0)113True114sage: p.point_configuration() is pc115True116"""117return self._point_configuration118119120def __iter__(self):121r"""122Iterate through the affine ambient space coordinates of the point.123124EXAMPLES::125126sage: pc = PointConfiguration([(0,0)])127sage: from sage.geometry.triangulation.base import Point128sage: p = Point(pc, 123, (1,2,1), (3,4), ())129sage: list(p) # indirect doctest130[3, 4]131"""132return self._affine.__iter__()133134135def __len__(self):136r"""137Return the affine ambient space dimension.138139EXAMPLES::140141sage: pc = PointConfiguration([(0,0)])142sage: from sage.geometry.triangulation.base import Point143sage: p = Point(pc, 123, (1,2,1), (3,4), ())144sage: len(p)1452146sage: p.__len__()1472148"""149return len(self._affine)150151152cpdef index(self):153"""154Return the index of the point in the point configuration.155156EXAMPLES::157158sage: pc = PointConfiguration([[0, 1], [0, 0], [1, 0]])159sage: p = pc.point(2); p160P(1, 0)161sage: p.index()1622163"""164return self._index165166167cpdef projective(self):168r"""169Return the projective coordinates of the point in the ambient space.170171OUTPUT:172173A tuple containing the coordinates.174175EXAMPLES::176177sage: pc = PointConfiguration([[10, 0, 1], [10, 0, 0], [10, 2, 3]])178sage: p = pc.point(2); p179P(10, 2, 3)180sage: p.affine()181(10, 2, 3)182sage: p.projective()183(10, 2, 3, 1)184sage: p.reduced_affine()185(2, 2)186sage: p.reduced_projective()187(2, 2, 1)188sage: p.reduced_affine_vector()189(2, 2)190"""191return self._projective192193194cpdef affine(self):195r"""196Return the affine coordinates of the point in the ambient space.197198OUTPUT:199200A tuple containing the coordinates.201202EXAMPLES::203204sage: pc = PointConfiguration([[10, 0, 1], [10, 0, 0], [10, 2, 3]])205sage: p = pc.point(2); p206P(10, 2, 3)207sage: p.affine()208(10, 2, 3)209sage: p.projective()210(10, 2, 3, 1)211sage: p.reduced_affine()212(2, 2)213sage: p.reduced_projective()214(2, 2, 1)215sage: p.reduced_affine_vector()216(2, 2)217"""218return self._affine219220221cpdef reduced_affine(self):222r"""223Return the affine coordinates of the point on the hyperplane224spanned by the point configuration.225226OUTPUT:227228A tuple containing the coordinates.229230EXAMPLES::231232sage: pc = PointConfiguration([[10, 0, 1], [10, 0, 0], [10, 2, 3]])233sage: p = pc.point(2); p234P(10, 2, 3)235sage: p.affine()236(10, 2, 3)237sage: p.projective()238(10, 2, 3, 1)239sage: p.reduced_affine()240(2, 2)241sage: p.reduced_projective()242(2, 2, 1)243sage: p.reduced_affine_vector()244(2, 2)245"""246return self._reduced_affine247248249cpdef reduced_projective(self):250r"""251Return the projective coordinates of the point on the hyperplane252spanned by the point configuration.253254OUTPUT:255256A tuple containing the coordinates.257258EXAMPLES::259260sage: pc = PointConfiguration([[10, 0, 1], [10, 0, 0], [10, 2, 3]])261sage: p = pc.point(2); p262P(10, 2, 3)263sage: p.affine()264(10, 2, 3)265sage: p.projective()266(10, 2, 3, 1)267sage: p.reduced_affine()268(2, 2)269sage: p.reduced_projective()270(2, 2, 1)271sage: p.reduced_affine_vector()272(2, 2)273"""274return tuple(self._reduced_affine)+(1,)275276277cpdef reduced_affine_vector(self):278"""279Return the affine coordinates of the point on the hyperplane280spanned by the point configuration.281282OUTPUT:283284A tuple containing the coordinates.285286EXAMPLES::287288sage: pc = PointConfiguration([[10, 0, 1], [10, 0, 0], [10, 2, 3]])289sage: p = pc.point(2); p290P(10, 2, 3)291sage: p.affine()292(10, 2, 3)293sage: p.projective()294(10, 2, 3, 1)295sage: p.reduced_affine()296(2, 2)297sage: p.reduced_projective()298(2, 2, 1)299sage: p.reduced_affine_vector()300(2, 2)301"""302return self._reduced_affine_vector303304305cpdef reduced_projective_vector(self):306"""307Return the affine coordinates of the point on the hyperplane308spanned by the point configuration.309310OUTPUT:311312A tuple containing the coordinates.313314EXAMPLES::315316sage: pc = PointConfiguration([[10, 0, 1], [10, 0, 0], [10, 2, 3]])317sage: p = pc.point(2); p318P(10, 2, 3)319sage: p.affine()320(10, 2, 3)321sage: p.projective()322(10, 2, 3, 1)323sage: p.reduced_affine()324(2, 2)325sage: p.reduced_projective()326(2, 2, 1)327sage: p.reduced_affine_vector()328(2, 2)329sage: type(p.reduced_affine_vector())330<type 'sage.modules.vector_rational_dense.Vector_rational_dense'>331"""332return self._reduced_projective_vector333334335cpdef _repr_(self):336"""337Return a string representation of the point.338339OUTPUT:340341String.342343EXAMPLES::344345sage: pc = PointConfiguration([[10, 0, 1], [10, 0, 0]])346sage: from sage.geometry.triangulation.base import Point347sage: p = Point(pc, 123, (0,0,1), (0,0), (0,))348sage: p._repr_()349'P(0, 0)'350"""351return 'P'+str(self._affine)352353354########################################################################355cdef class PointConfiguration_base(Parent):356r"""357The cython abstract base class for358:class:`~sage.geometry.triangulation.PointConfiguration`.359360.. WARNING::361362You should not instantiate this base class, but only its363derived class364:class:`~sage.geometry.triangulation.point_configuration.PointConfiguration`.365"""366367def __init__(self, points, defined_affine):368r"""369Construct a :class:`PointConfiguration_base`.370371INPUT:372373- ``points`` -- a tuple of tuples of projective coordinates374with ``1`` as the final coordinate.375376- ``defined_affine`` -- Boolean. Whether the point377configuration is defined as a configuration of affine (as378opposed to projective) points.379380TESTS::381382sage: from sage.geometry.triangulation.base import PointConfiguration_base383sage: PointConfiguration_base(((1,2,1),(2,3,1),(3,4,1)), False) # indirect doctest384<type 'sage.geometry.triangulation.base.PointConfiguration_base'>385"""386Parent.__init__(self, category = Sets())387self._init_points(points)388self._is_affine = defined_affine389390391cdef tuple _pts392cdef int _ambient_dim393cdef int _dim394cdef object _base_ring395cdef bint _is_affine396cdef object _reduced_affine_vector_space, _reduced_projective_vector_space397398399cdef _init_points(self, tuple projective_points):400"""401Internal method to determine coordinates of points.402403EXAMPLES::404405sage: p = PointConfiguration([[0, 1], [0, 0], [1, 0]]) # indirect doctest406sage: p.points()407(P(0, 1), P(0, 0), P(1, 0))408409Special cases::410411sage: PointConfiguration([])412A point configuration in QQ^0 consisting of 0 points. The413triangulations of this point configuration are assumed to414be connected, not necessarily fine, not necessarily regular.415sage: PointConfiguration([(1,2,3)])416A point configuration in QQ^3 consisting of 1 point. The417triangulations of this point configuration are assumed to418be connected, not necessarily fine, not necessarily regular.419"""420n = len(projective_points)421if n==0:422self._ambient_dim = 0423self._dim = -1424self._pts = tuple()425return426427# We now are sure that projective_points is not empty428self._ambient_dim = len(projective_points[0])-1429assert all([ len(p)==self._ambient_dim+1 for p in projective_points ]), \430'The given point coordinates must all have the same length.'431assert len(uniq(projective_points)) == len(projective_points), \432'Not all points are pairwise distinct.'433434proj = matrix(projective_points).transpose()435self._base_ring = proj.base_ring()436437if all([ x==1 for x in proj.row(self.ambient_dim()) ]):438aff = proj.submatrix(0,0,nrows=self.ambient_dim())439else:440raise NotImplementedError # TODO441442if n>1:443# shift first point to origin444red = matrix([ aff.column(i)-aff.column(0) for i in range(0,n) ]).transpose()445# pick linearly independent rows446red = matrix([ red.row(i) for i in red.pivot_rows()])447else:448red = matrix(0,1)449self._dim = red.nrows()450451from sage.modules.free_module import VectorSpace452self._reduced_affine_vector_space = VectorSpace(self._base_ring.fraction_field(), self._dim)453self._reduced_projective_vector_space = VectorSpace(self._base_ring.fraction_field(), self._dim+1)454self._pts = tuple([ Point(self, i, proj.column(i), aff.column(i), red.column(i))455for i in range(0,n) ])456457458cpdef reduced_affine_vector_space(self):459"""460Return the vector space that contains the affine points.461462OUTPUT:463464A vector space over the fraction field of :meth:`base_ring`.465466EXAMPLES::467468sage: p = PointConfiguration([[0,0,0], [1,2,3]])469sage: p.base_ring()470Integer Ring471sage: p.reduced_affine_vector_space()472Vector space of dimension 1 over Rational Field473sage: p.reduced_projective_vector_space()474Vector space of dimension 2 over Rational Field475"""476return self._reduced_affine_vector_space477478479cpdef reduced_projective_vector_space(self):480"""481Return the vector space that is spanned by the homogeneous482coordinates.483484OUTPUT:485486A vector space over the fraction field of :meth:`base_ring`.487488EXAMPLES::489490sage: p = PointConfiguration([[0,0,0], [1,2,3]])491sage: p.base_ring()492Integer Ring493sage: p.reduced_affine_vector_space()494Vector space of dimension 1 over Rational Field495sage: p.reduced_projective_vector_space()496Vector space of dimension 2 over Rational Field497"""498return self._reduced_projective_vector_space499500501cpdef ambient_dim(self):502"""503Return the dimension of the ambient space of the point504configuration.505506See also :meth:`dimension`507508EXAMPLES::509510sage: p = PointConfiguration([[0,0,0]])511sage: p.ambient_dim()5123513sage: p.dim()5140515"""516return self._ambient_dim517518519cpdef dim(self):520"""521Return the actual dimension of the point522configuration.523524See also :meth:`ambient_dim`525526EXAMPLES::527528sage: p = PointConfiguration([[0,0,0]])529sage: p.ambient_dim()5303531sage: p.dim()5320533"""534return self._dim535536537cpdef base_ring(self):538r"""539Return the base ring, that is, the ring containing the540coordinates of the points.541542OUTPUT:543544A ring.545546EXAMPLES::547548sage: p = PointConfiguration([(0,0)])549sage: p.base_ring()550Integer Ring551552sage: p = PointConfiguration([(1/2,3)])553sage: p.base_ring()554Rational Field555556sage: p = PointConfiguration([(0.2, 5)])557sage: p.base_ring()558Real Field with 53 bits of precision559"""560return self._base_ring561562563cpdef bint is_affine(self):564"""565Whether the configuration is defined by affine points.566567OUTPUT:568569Boolean. If true, the homogeneous coordinates all have `1` as570their last entry.571572EXAMPLES::573574sage: p = PointConfiguration([(0.2, 5), (3, 0.1)])575sage: p.is_affine()576True577578sage: p = PointConfiguration([(0.2, 5, 1), (3, 0.1, 1)], projective=True)579sage: p.is_affine()580False581"""582return self._is_affine583584585def _assert_is_affine(self):586"""587Raise a ``ValueError`` if the point configuration is not588defined by affine points.589590EXAMPLES::591592sage: p = PointConfiguration([(0.2, 5), (3, 0.1)])593sage: p._assert_is_affine()594sage: p = PointConfiguration([(0.2, 5, 1), (3, 0.1, 1)], projective=True)595sage: p._assert_is_affine()596Traceback (most recent call last):597...598ValueError: The point configuration contains projective points.599"""600if not self.is_affine():601raise ValueError('The point configuration contains projective points.')602603604def __getitem__(self, i):605"""606Return the ``i``-th point.607608Same as :meth:`point`.609610INPUT:611612- ``i`` -- integer.613614OUTPUT:615616The ``i``-th point of the point configuration.617618EXAMPLES::619620sage: p = PointConfiguration([[1,0], [2,3], [3,2]])621sage: [ p[i] for i in range(0,p.n_points()) ]622[P(1, 0), P(2, 3), P(3, 2)]623sage: list(p)624[P(1, 0), P(2, 3), P(3, 2)]625sage: list(p.points())626[P(1, 0), P(2, 3), P(3, 2)]627sage: [ p.point(i) for i in range(0,p.n_points()) ]628[P(1, 0), P(2, 3), P(3, 2)]629"""630return self._pts[i]631632633cpdef n_points(self):634"""635Return the number of points.636637Same as ``len(self)``.638639EXAMPLES::640641sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])642sage: p643A point configuration in QQ^2 consisting of 5 points. The644triangulations of this point configuration are assumed to645be connected, not necessarily fine, not necessarily regular.646sage: len(p)6475648sage: p.n_points()6495650"""651return len(self._pts)652653654cpdef points(self):655"""656Return a list of the points.657658OUTPUT:659660Returns a list of the points. See also the :meth:`__iter__`661method, which returns the corresponding generator.662663EXAMPLES::664665sage: pconfig = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])666sage: list(pconfig)667[P(0, 0), P(0, 1), P(1, 0), P(1, 1), P(-1, -1)]668sage: [ p for p in pconfig.points() ]669[P(0, 0), P(0, 1), P(1, 0), P(1, 1), P(-1, -1)]670sage: pconfig.point(0)671P(0, 0)672sage: pconfig.point(1)673P(0, 1)674sage: pconfig.point( pconfig.n_points()-1 )675P(-1, -1)676"""677return self._pts678679680def point(self, i):681"""682Return the i-th point of the configuration.683684Same as :meth:`__getitem__`685686INPUT:687688- ``i`` -- integer.689690OUTPUT:691692A point of the point configuration.693694EXAMPLES::695696sage: pconfig = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])697sage: list(pconfig)698[P(0, 0), P(0, 1), P(1, 0), P(1, 1), P(-1, -1)]699sage: [ p for p in pconfig.points() ]700[P(0, 0), P(0, 1), P(1, 0), P(1, 1), P(-1, -1)]701sage: pconfig.point(0)702P(0, 0)703sage: pconfig[0]704P(0, 0)705sage: pconfig.point(1)706P(0, 1)707sage: pconfig.point( pconfig.n_points()-1 )708P(-1, -1)709"""710return self._pts[i]711712713def __len__(self):714"""715Return the number of points.716717Same as :meth:`n_points`718719EXAMPLES::720721sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])722sage: p723A point configuration in QQ^2 consisting of 5 points. The724triangulations of this point configuration are assumed to725be connected, not necessarily fine, not necessarily regular.726sage: len(p)7275728sage: p.n_points()7295730"""731return len(self._pts)732733734cpdef simplex_to_int(self, simplex):735r"""736Returns an integer that uniquely identifies the given simplex.737738See also the inverse method :meth:`int_to_simplex`.739740The enumeration is compatible with [PUNTOS]_.741742INPUT:743744- ``simplex`` -- iterable, for example a list. The elements745are the vertex indices of the simplex.746747OUTPUT:748749An integer that uniquely specifies the simplex.750751EXAMPLES::752753sage: U=matrix([754... [ 0, 0, 0, 0, 0, 2, 4,-1, 1, 1, 0, 0, 1, 0],755... [ 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0],756... [ 0, 2, 0, 0, 0, 0,-1, 0, 1, 0, 1, 0, 0, 1],757... [ 0, 1, 1, 0, 0, 1, 0,-2, 1, 0, 0,-1, 1, 1],758... [ 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0]759... ])760sage: pc = PointConfiguration(U.columns())761sage: pc.simplex_to_int([1,3,4,7,10,13])7621678763sage: pc.int_to_simplex(1678)764(1, 3, 4, 7, 10, 13)765"""766cdef int s = 1767cdef int k = 1768cdef int n = self.n_points()769cdef int d = len(simplex)770assert d==self.dim()+1771cdef int i, j772for i in range(1,d+1):773l = simplex[i-1]+1774for j in range(k,l):775s += binomial(n-j,d-i)776k = l+1777return s778779780cpdef int_to_simplex(self, int s):781r"""782Reverses the enumeration of possible simplices in783:meth:`simplex_to_int`.784785The enumeration is compatible with [PUNTOS]_.786787INPUT:788789- ``s`` -- int. An integer that uniquely specifies a simplex.790791OUTPUT:792793An ordered tuple consisting of the indices of the vertices of794the simplex.795796EXAMPLES::797798sage: U=matrix([799... [ 0, 0, 0, 0, 0, 2, 4,-1, 1, 1, 0, 0, 1, 0],800... [ 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0],801... [ 0, 2, 0, 0, 0, 0,-1, 0, 1, 0, 1, 0, 0, 1],802... [ 0, 1, 1, 0, 0, 1, 0,-2, 1, 0, 0,-1, 1, 1],803... [ 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0]804... ])805sage: pc = PointConfiguration(U.columns())806sage: pc.simplex_to_int([1,3,4,7,10,13])8071678808sage: pc.int_to_simplex(1678)809(1, 3, 4, 7, 10, 13)810"""811simplex = []812cdef int l = 0813cdef int n = self.n_points()814cdef int d = self.dim()+1815cdef int k, b816for k in range(1,d):817l += 1818i = l819j = 1820b = binomial(n-l,d-k)821while (s>b) and (b>0):822j += 1823l += 1824s -= b825b = binomial(n-l,d-k)826simplex.append(l-1)827simplex.append(s+l-1)828assert len(simplex) == d829return tuple(simplex)830831832833########################################################################834cdef class ConnectedTriangulationsIterator(SageObject):835r"""836A Python shim for the C++-class 'triangulations'837838INPUT:839840- ``point_configuration`` -- a841:class:`~sage.geometry.triangulation.point_configuration.PointConfiguration`.842843- ``seed`` -- a regular triangulation or ``None`` (default). In844the latter case, a suitable triangulation is generated845automatically. Otherwise, you can explicitly specify the seed846triangulation as847848* A849:class:`~sage.geometry.triangulation.element.Triangulation`850object, or851852* an iterable of iterables specifying the vertices of the simplices, or853854* an iterable of integers, which are then considered the855enumerated simplices (see856:meth:`~PointConfiguration_base.simplex_to_int`.857858- ``star`` -- either ``None`` (default) or an integer. If an859integer is passed, all returned triangulations will be star with860respect to the861862- ``fine`` -- boolean (default: ``False``). Whether to return only863fine triangulations, that is, simplicial decompositions that864make use of all the points of the configuration.865866OUTPUT:867868An iterator. The generated values are tuples of869integers, which encode simplices of the triangulation. The output870is a suitable input to871:class:`~sage.geometry.triangulation.element.Triangulation`.872873EXAMPLES::874875sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])876sage: from sage.geometry.triangulation.base import ConnectedTriangulationsIterator877sage: ci = ConnectedTriangulationsIterator(p)878sage: ci.next()879(9, 10)880sage: ci.next()881(2, 3, 4, 5)882sage: ci.next()883(7, 8)884sage: ci.next()885(1, 3, 5, 7)886sage: ci.next()887Traceback (most recent call last):888...889StopIteration890891You can reconstruct the triangulation from the compressed output via::892893sage: from sage.geometry.triangulation.element import Triangulation894sage: Triangulation((2, 3, 4, 5), p)895(<0,1,3>, <0,1,4>, <0,2,3>, <0,2,4>)896897How to use the restrictions::898899sage: ci = ConnectedTriangulationsIterator(p, fine=True)900sage: list(ci)901[(2, 3, 4, 5), (1, 3, 5, 7)]902sage: ci = ConnectedTriangulationsIterator(p, star=1)903sage: list(ci)904[(7, 8)]905sage: ci = ConnectedTriangulationsIterator(p, star=1, fine=True)906sage: list(ci)907[]908"""909910cdef triangulations_ptr _tp911912913def __cinit__(self):914"""915The Cython constructor.916917TESTS::918919sage: from sage.geometry.triangulation.base import ConnectedTriangulationsIterator920sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])921sage: ConnectedTriangulationsIterator(p, fine=True) # indirect doctest922<type 'sage.geometry.triangulation.base.ConnectedTriangulationsIterator'>923"""924self._tp = NULL925926927def __init__(self, point_configuration, seed=None, star=None, fine=False):928r"""929The Python constructor.930931See :class:`ConnectedTriangulationsIterator` for a description932of the arguments.933934TESTS::935936sage: p = PointConfiguration([[0,4],[2,3],[3,2],[4,0],[3,-2],[2,-3],[0,-4],[-2,-3],[-3,-2],[-4,0],[-3,2],[-2,3]])937sage: from sage.geometry.triangulation.base import ConnectedTriangulationsIterator938sage: ci = ConnectedTriangulationsIterator(p)939sage: len(list(ci)) # long time (23s on sage.math, 2011)94016796941sage: ci = ConnectedTriangulationsIterator(p, star=3)942sage: len(list(ci)) # long time (23s on sage.math, 2011)9431944"""945if star==None:946star = -1947if seed==None:948seed = point_configuration.lexicographic_triangulation().enumerate_simplices()949try:950enumerated_simplices_seed = seed.enumerated_simplices()951except AttributeError:952enumerated_simplices_seed = tuple([ int(t) for t in seed ])953assert self._tp == NULL954self._tp = init_triangulations(point_configuration.n_points(),955point_configuration.dim()+1,956star, fine,957enumerated_simplices_seed,958point_configuration.bistellar_flips())959960961def __dealloc__(self):962r"""963The Cython destructor.964"""965delete_triangulations(self._tp)966967968def __iter__(self):969r"""970The iterator interface: Start iterating.971972TESTS::973974sage: from sage.geometry.triangulation.base import ConnectedTriangulationsIterator975sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])976sage: ci = ConnectedTriangulationsIterator(p, fine=True)977sage: ci.__iter__()978<type 'sage.geometry.triangulation.base.ConnectedTriangulationsIterator'>979sage: ci.__iter__() is ci980True981"""982return self983984985def __next__(self):986r"""987The iterator interface: Next iteration.988989EXAMPLES::990991sage: from sage.geometry.triangulation.base import ConnectedTriangulationsIterator992sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])993sage: ci = ConnectedTriangulationsIterator(p)994sage: ci.__next__()995(9, 10)996"""997t = next_triangulation(self._tp)998if len(t)==0:999raise StopIteration1000return t1001100210031004100510061007