Ticket #12159: trac_12159_separate_triangulation_file.patch

File trac_12159_separate_triangulation_file.patch, 43.9 KB (added by vbraun, 10 years ago)

Initial patch

  • doc/en/reference/geometry.rst

    # HG changeset patch
    # User Volker Braun <vbraun@stp.dias.ie>
    # Date 1323978220 0
    # Node ID ae07be5b23656ab77ad7735dd36b32369e2bcce5
    # Parent  34e2452138cbb44b74e43529c1ca6a7cbbaa58b2
    Trac #12159: Placing triangulation and normal cones
    
    This patch renames triangulation.py -> element.py since
    all files are in the sage/geometry/triangulation directory.
    
    diff --git a/doc/en/reference/geometry.rst b/doc/en/reference/geometry.rst
    a b  
    2121
    2222   sage/geometry/triangulation/point_configuration
    2323   sage/geometry/triangulation/base
     24   sage/geometry/triangulation/element
     25
  • sage/geometry/triangulation/base.pyx

    diff --git a/sage/geometry/triangulation/base.pyx b/sage/geometry/triangulation/base.pyx
    a b  
    629629      triangulation as
    630630   
    631631        * A
    632           :class:`~sage.geometry.triangulation.point_configuration.Triangulation`
     632          :class:`~sage.geometry.triangulation.element.Triangulation`
    633633          object, or
    634634
    635635        * an iterable of iterables specifying the vertices of the simplices, or
     
    651651    An iterator. The generated values are tuples of
    652652    integers, which encode simplices of the triangulation. The output
    653653    is a suitable input to
    654     :class:`~sage.geometry.triangulation.point_configuration.Triangulation`.
     654    :class:`~sage.geometry.triangulation.element.Triangulation`.
    655655
    656656    EXAMPLES::
    657657   
     
    673673
    674674    You can reconstruct the triangulation from the compressed output via::
    675675
    676         sage: from sage.geometry.triangulation.point_configuration import Triangulation
     676        sage: from sage.geometry.triangulation.element import Triangulation
    677677        sage: Triangulation((2, 3, 4, 5), p)
    678678        (<0,1,3>, <0,1,4>, <0,2,3>, <0,2,4>)
    679679
  • new file sage/geometry/triangulation/element.py

    diff --git a/sage/geometry/triangulation/element.py b/sage/geometry/triangulation/element.py
    new file mode 100644
    - +  
     1""""
     2A triangulation
     3
     4In Sage, the
     5:class:`~sage.geometry.triangulation.point_configuration.PointConfiguration`
     6and :class:`Triangulation` satisfy a parent/element relationship. In
     7particular, each triangulation refers back to its point
     8configuration. If you want to triangulate a point configuration, you
     9should construct a point configuration first and then use one of its
     10methods to triangulate it according to your requirements. You should
     11never have to construct a :class:`Triangulation` object directly.
     12
     13EXAMPLES::
     14
     15    sage: p = [[0,-1,-1],[0,0,1],[0,1,0], [1,-1,-1],[1,0,1],[1,1,0]]
     16    sage: points = PointConfiguration(p)
     17    sage: triang = points.triangulate()
     18    sage: triang.plot(axes=False)
     19
     20See :mod:`sage.geometry.triangulation.point_configuration` for more details.
     21"""
     22
     23
     24########################################################################
     25#       Copyright (C) 2010 Volker Braun <vbraun.name@gmail.com>
     26#
     27#  Distributed under the terms of the GNU General Public License (GPL)
     28#
     29#                  http://www.gnu.org/licenses/
     30########################################################################
     31
     32from sage.structure.element import Element
     33from sage.rings.all import QQ, ZZ
     34from sage.modules.all import vector
     35
     36
     37
     38########################################################################
     39def triangulation_render_2d(triangulation, **kwds):
     40    r"""
     41    Return a graphical representation of a 2-d triangulation.
     42
     43    INPUT:
     44   
     45    - ``triangulation`` -- a :class:`Triangulation`.
     46   
     47    - ``**kwds`` -- keywords that are passed on to the graphics primitives.
     48
     49    OUTPUT:
     50
     51    A 2-d graphics object.
     52
     53    EXAMPLES::
     54   
     55        sage: points = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])
     56        sage: triang = points.triangulate()
     57        sage: triang.plot(axes=False)   # indirect doctest
     58    """
     59    from sage.plot.all import point2d, line2d, arrow, polygon2d
     60    points = [ point.reduced_affine() for point in triangulation.point_configuration() ]
     61    coord = [ [p[0], p[1]] for p in points ]
     62    plot_points = sum([ point2d(p,
     63                                zorder=2, pointsize=10, **kwds)
     64                        for p in coord ])
     65
     66    tmp_lines = []
     67    for t in triangulation:
     68        if len(t)>=2:
     69            tmp_lines.append([t[0], t[1]])
     70        if len(t)>=3:
     71            tmp_lines.append([t[0], t[2]])
     72            tmp_lines.append([t[1], t[2]])
     73    all_lines = []
     74    interior_lines = []
     75    for l in tmp_lines:
     76        if l not in all_lines:
     77            all_lines.append(l)
     78        else:
     79            interior_lines.append(l)
     80    exterior_lines = [ l for l in all_lines if not l in interior_lines ]
     81           
     82    plot_interior_lines = sum([ line2d([ coord[l[0]], coord[l[1]] ],
     83                                       zorder=1, rgbcolor=(0,1,0), **kwds)
     84                                for l in interior_lines ])
     85    plot_exterior_lines = sum([ line2d([ coord[l[0]], coord[l[1]] ],
     86                                       zorder=1, rgbcolor=(0,0,1), **kwds)
     87                                for l in exterior_lines ])
     88
     89    plot_triangs = sum([ polygon2d([coord[t[0]], coord[t[1]], coord[t[2]]],
     90                                   zorder=0, rgbcolor=(0.8, 1, 0.8), **kwds)
     91                         for t in triangulation if len(t)>=3 ])
     92
     93    return \
     94        plot_points + \
     95        plot_interior_lines + plot_exterior_lines + \
     96        plot_triangs
     97
     98
     99
     100
     101def triangulation_render_3d(triangulation, **kwds):
     102    r"""
     103    Return a graphical representation of a 3-d triangulation.
     104
     105    INPUT:
     106   
     107    - ``triangulation`` -- a :class:`Triangulation`.
     108   
     109    - ``**kwds`` -- keywords that are  passed on to the graphics primitives.
     110
     111    OUTPUT:
     112
     113    A 3-d graphics object.
     114
     115    EXAMPLES::
     116   
     117        sage: p = [[0,-1,-1],[0,0,1],[0,1,0], [1,-1,-1],[1,0,1],[1,1,0]]
     118        sage: points = PointConfiguration(p)
     119        sage: triang = points.triangulate()
     120        sage: triang.plot(axes=False)     # indirect doctest
     121    """
     122    from sage.plot.plot3d.all import point3d, line3d, arrow3d, polygon3d
     123    points = [ point.reduced_affine() for point in triangulation.point_configuration() ]
     124    coord = [ [p[0], p[1], p[2] ] for p in points ]
     125    plot_points = sum([ point3d(p, size=15,
     126                                **kwds)
     127                        for p in coord ])
     128
     129    tmp_lines = []
     130    for t in triangulation:
     131        if len(t)>=2:
     132            tmp_lines.append([t[0], t[1]])
     133        if len(t)>=3:
     134            tmp_lines.append([t[0], t[2]])
     135            tmp_lines.append([t[1], t[2]])
     136        if len(t)>=4:
     137            tmp_lines.append([t[0], t[3]])
     138            tmp_lines.append([t[1], t[3]])
     139            tmp_lines.append([t[2], t[3]])
     140    all_lines = []
     141    interior_lines = []
     142    for l in tmp_lines:
     143        if l not in all_lines:
     144            all_lines.append(l)
     145        else:
     146            interior_lines.append(l)
     147    exterior_lines = [ l for l in all_lines if not l in interior_lines ]
     148
     149    from sage.plot.plot3d.texture import Texture
     150    line_int = Texture(color='darkblue', ambient=1, diffuse=0)
     151    line_ext = Texture(color='green', ambient=1, diffuse=0)
     152    triang_int = Texture(opacity=0.3, specular=0, shininess=0, diffuse=0, ambient=1, color='yellow')
     153    triang_ext = Texture(opacity=0.6, specular=0, shininess=0, diffuse=0, ambient=1, color='green')
     154           
     155    plot_interior_lines = sum([ line3d([ coord[l[0]], coord[l[1]] ],
     156                                       thickness=2, texture=line_int, **kwds)
     157                                for l in interior_lines ])
     158    plot_exterior_lines = sum([ line3d([ coord[l[0]], coord[l[1]] ],
     159                                       thickness=3, texture=line_ext, **kwds)
     160                                for l in exterior_lines ])
     161
     162    tmp_triangs = []
     163    for t in triangulation:
     164        if len(t)>=3:
     165            tmp_triangs.append([t[0], t[1], t[2]])
     166        if len(t)>=4:
     167            tmp_triangs.append([t[0], t[1], t[3]])
     168            tmp_triangs.append([t[0], t[2], t[3]])
     169            tmp_triangs.append([t[1], t[2], t[3]])
     170    all_triangs = []
     171    interior_triangs = []
     172    for l in tmp_triangs:
     173        if l not in all_triangs:
     174            all_triangs.append(l)
     175        else:
     176            interior_triangs.append(l)
     177    exterior_triangs = [ l for l in all_triangs if not l in interior_triangs ]
     178   
     179    plot_interior_triangs = \
     180        sum([ polygon3d([coord[t[0]], coord[t[1]], coord[t[2]]],
     181                        texture = triang_int, **kwds)
     182              for t in interior_triangs ])
     183    plot_exterior_triangs = \
     184        sum([ polygon3d([coord[t[0]], coord[t[1]], coord[t[2]]],
     185                        texture = triang_ext, **kwds)
     186              for t in exterior_triangs ])
     187
     188    return \
     189        plot_points + \
     190        plot_interior_lines + plot_exterior_lines + \
     191        plot_interior_triangs + plot_exterior_triangs
     192
     193
     194
     195
     196
     197########################################################################
     198class Triangulation(Element):
     199    """
     200    A triangulation of a
     201    :class:`~sage.geometry.triangulation.point_configuration.PointConfiguration`.
     202
     203    .. WARNING::
     204 
     205        You should never create :class:`Triangulation` objects
     206        manually. See
     207        :meth:`~sage.geometry.triangulation.point_configuration.PointConfiguration.triangulate`
     208        and
     209        :meth:`~sage.geometry.triangulation.point_configuration.PointConfiguration.triangulations`
     210        to triangulate point configurations.
     211    """
     212
     213    def __init__(self, triangulation, parent, check=True):
     214        """
     215        The constructor of a ``Triangulation`` object. Note that an
     216        internal reference to the underlying ``PointConfiguration`` is
     217        kept.
     218
     219        INPUT:
     220
     221        - ``parent`` -- a
     222          :class:`~sage.geometry.triangulation.point_configuration.PointConfiguration`
     223       
     224        - ``triangulation`` -- an iterable of integers or iterable of
     225          iterables (e.g. a list of lists). In the first case, the
     226          integers specify simplices via
     227          :meth:`PointConfiguration.simplex_to_int`. In the second
     228          case, the point indices of the maximal simplices of the
     229          triangulation.
     230
     231        - ``check`` -- boolean. Whether to perform checks that the
     232          triangulation is, indeed, a triangulation of the point
     233          configuration.
     234
     235        NOTE:
     236
     237        Passing ``check=False`` allows you to create triangulations of
     238        subsets of the points of the configuration, see
     239        :meth:`~sage.geometry.triangulation.point_configuration.PointConfiguration.bistellar_flips`.
     240
     241        EXAMPLES::
     242       
     243            sage: p = [[0,1],[0,0],[1,0]]
     244            sage: points = PointConfiguration(p)
     245            sage: from sage.geometry.triangulation.point_configuration import Triangulation
     246            sage: Triangulation([(0,1,2)], points)
     247            (<0,1,2>)
     248            sage: Triangulation([1], points)
     249            (<0,1,2>)
     250        """
     251        Element.__init__(self, parent=parent)
     252        self._point_configuration = parent
     253
     254        try:
     255            triangulation = tuple(sorted( tuple(sorted(t)) for t in triangulation))
     256        except TypeError:
     257            triangulation = tuple( self.point_configuration().int_to_simplex(i)
     258                                   for i in triangulation )
     259        assert not check or all( len(t)==self.point_configuration().dim()+1
     260                                 for t in triangulation)
     261        self._triangulation = triangulation
     262
     263
     264    def point_configuration(self):
     265        """
     266        Returns the point configuration underlying the triangulation.
     267
     268        EXAMPLES::
     269       
     270            sage: pconfig = PointConfiguration([[0,0],[0,1],[1,0]])
     271            sage: pconfig
     272            A point configuration in QQ^2 consisting of 3 points. The
     273            triangulations of this point configuration are assumed to
     274            be connected, not necessarily fine, not necessarily regular.
     275            sage: triangulation = pconfig.triangulate()
     276            sage: triangulation
     277            (<0,1,2>)
     278            sage: triangulation.point_configuration()
     279            A point configuration in QQ^2 consisting of 3 points. The
     280            triangulations of this point configuration are assumed to
     281            be connected, not necessarily fine, not necessarily regular.
     282            sage: pconfig == triangulation.point_configuration()
     283            True
     284        """
     285        return self._point_configuration
     286
     287
     288    def __cmp__(self, right):
     289        r"""
     290        Compare ``self`` and ``right``.
     291
     292        INPUT:
     293
     294        - ``right`` -- anything.
     295
     296        OUTPUT:
     297
     298        - 0 if ``right`` is the same triangulation as ``self``, 1 or
     299          -1 otherwise.
     300
     301        TESTS::
     302
     303            sage: pc = PointConfiguration([[0,0],[0,1],[1,0]])
     304            sage: t1 = pc.triangulate()
     305            sage: from sage.geometry.triangulation.point_configuration import Triangulation
     306            sage: t2 = Triangulation([[2,1,0]], pc)
     307            sage: t1 is t2
     308            False
     309            sage: cmp(t1, t2)
     310            0
     311            sage: t1 == t2    # indirect doctest
     312            True
     313            sage: abs( cmp(t1, Triangulation(((0,1),(1,2)), pc, check=False) ))
     314            1
     315            sage: abs( cmp(t2, "not a triangulation") )
     316            1
     317        """
     318        left = self
     319        c = cmp(isinstance(left,Triangulation), isinstance(right,Triangulation))
     320        if c: return c
     321        c = cmp(left.point_configuration(), right.point_configuration())
     322        if c: return c
     323        return cmp(left._triangulation, right._triangulation)
     324
     325
     326    def __iter__(self):
     327        """
     328        Iterate through the simplices of the triangulation.
     329
     330        EXAMPLES::
     331
     332            sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])
     333            sage: triangulation = pc.triangulate()
     334            sage: iter = triangulation.__iter__()
     335            sage: iter.next()
     336            (1, 3, 4)
     337            sage: iter.next()
     338            (2, 3, 4)
     339            sage: iter.next()
     340            Traceback (most recent call last):
     341            ...
     342            StopIteration
     343        """
     344        for p in self._triangulation:
     345            yield p
     346
     347
     348    def __getitem__(self, i):
     349        """
     350        Access the point indices of the i-th simplex of the triangulation.
     351
     352        INPUT:
     353
     354        - ``i`` -- integer. The index of a simplex.
     355       
     356        OUTPUT:
     357
     358        A tuple of integers. The vertex indices of the i-th simplex.
     359
     360        EXAMPLES::
     361       
     362            sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])
     363            sage: triangulation = pc.triangulate()
     364            sage: triangulation[1]
     365            (2, 3, 4)
     366        """
     367        return self._triangulation[i]
     368
     369
     370    def __len__(self):
     371        """
     372        Returns the length of the triangulation.
     373
     374        TESTS::
     375
     376            sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])
     377            sage: triangulation = pc.triangulations().next()
     378            sage: triangulation.__len__()
     379            2
     380            sage: len(triangulation)    # equivalent
     381            2
     382        """
     383        return len(self._triangulation)
     384
     385
     386    def _repr_(self):
     387        r"""
     388        Return a string representation.
     389       
     390        TESTS::
     391
     392            sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1],[2,2]])
     393            sage: t = pc.triangulations()
     394            sage: t.next()._repr_()
     395            '(<1,4,5>, <2,4,5>)'
     396        """
     397        #s = 'A triangulation'
     398        #s += ' in QQ^'+str(self.point_configuration().ambient_dim())
     399        #s += ' consisting of '+str(len(self))+' simplices.'
     400        s = '('
     401        s += ', '.join([ '<'+','.join(map(str,t))+'>' for t in self._triangulation])
     402        s += ')'
     403        return s
     404   
     405
     406    def plot(self, **kwds):
     407        r"""
     408        Produce a graphical representation of the triangulation.
     409
     410        EXAMPLES::
     411       
     412            sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])
     413            sage: triangulation = p.triangulate()
     414            sage: triangulation
     415            (<1,3,4>, <2,3,4>)
     416            sage: triangulation.plot(axes=False)
     417        """
     418        dim = self.point_configuration().dim()
     419       
     420        if dim == 2:
     421            return triangulation_render_2d(self, **kwds)
     422
     423        if dim == 3:
     424            return triangulation_render_3d(self, **kwds)
     425
     426        raise NotImplementedError, \
     427            'Plotting '+str(dim)+'-dimensional triangulations not implemented!'
     428   
     429
     430    def gkz_phi(self):
     431        r"""
     432        Calculate the GKZ phi vector of the triangulation. 
     433       
     434        OUTPUT:
     435
     436        Vector -- the phi vector of self.
     437
     438        EXAMPLES::
     439
     440            sage: p = PointConfiguration([[0,0],[1,0],[2,1],[1,2],[0,1]])
     441            sage: p.triangulate().gkz_phi()
     442            (1, 3, 4, 2, 5)
     443
     444        NOTE:
     445
     446        For a definition of the phi vector, see [GKZ]_ page 220 equation 1.4.
     447        """
     448        vec = vector(ZZ, self.point_configuration().n_points())
     449        for simplex in self:
     450            vol = self.point_configuration().volume(simplex)
     451            for i in simplex:
     452                vec[i] = vec[i] + vol
     453        return vec
     454
     455
     456    def enumerate_simplices(self):
     457        r"""
     458        Return the enumerated simplices.
     459
     460        OUTPUT:
     461       
     462        A tuple of integers that uniquely specifies the triangulation.
     463
     464        EXAMPLES::
     465
     466            sage: pc = PointConfiguration(matrix([
     467            ...      [ 0, 0, 0, 0, 0, 2, 4,-1, 1, 1, 0, 0, 1, 0],
     468            ...      [ 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0],
     469            ...      [ 0, 2, 0, 0, 0, 0,-1, 0, 1, 0, 1, 0, 0, 1],
     470            ...      [ 0, 1, 1, 0, 0, 1, 0,-2, 1, 0, 0,-1, 1, 1],
     471            ...      [ 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0]
     472            ...   ]).columns())
     473            sage: triangulation = pc.lexicographic_triangulation()
     474            sage: triangulation.enumerate_simplices()
     475            (1678, 1688, 1769, 1779, 1895, 1905, 2112, 2143, 2234, 2360, 2555, 2580,
     476             2610, 2626, 2650, 2652, 2654, 2661, 2663, 2667, 2685, 2755, 2757, 2759,
     477             2766, 2768, 2772, 2811, 2881, 2883, 2885, 2892, 2894, 2898)
     478
     479        You can recreate the triangulation from this list by passing
     480        it to the constructor::
     481
     482            sage: from sage.geometry.triangulation.point_configuration import Triangulation
     483            sage: Triangulation([1678, 1688, 1769, 1779, 1895, 1905, 2112, 2143,
     484            ...    2234, 2360, 2555, 2580, 2610, 2626, 2650, 2652, 2654, 2661, 2663,
     485            ...    2667, 2685, 2755, 2757, 2759, 2766, 2768, 2772, 2811, 2881, 2883,
     486            ...    2885, 2892, 2894, 2898], pc)
     487            (<1,3,4,7,10,13>, <1,3,4,8,10,13>, <1,3,6,7,10,13>, <1,3,6,8,10,13>,
     488             <1,4,6,7,10,13>, <1,4,6,8,10,13>, <2,3,4,6,7,12>, <2,3,4,7,12,13>,
     489             <2,3,6,7,12,13>, <2,4,6,7,12,13>, <3,4,5,6,9,12>, <3,4,5,8,9,12>,
     490             <3,4,6,7,11,12>, <3,4,6,9,11,12>, <3,4,7,10,11,13>, <3,4,7,11,12,13>,
     491             <3,4,8,9,10,12>, <3,4,8,10,12,13>, <3,4,9,10,11,12>, <3,4,10,11,12,13>,
     492             <3,5,6,8,9,12>, <3,6,7,10,11,13>, <3,6,7,11,12,13>, <3,6,8,9,10,12>,
     493             <3,6,8,10,12,13>, <3,6,9,10,11,12>, <3,6,10,11,12,13>, <4,5,6,8,9,12>,
     494             <4,6,7,10,11,13>, <4,6,7,11,12,13>, <4,6,8,9,10,12>, <4,6,8,10,12,13>,
     495             <4,6,9,10,11,12>, <4,6,10,11,12,13>)
     496        """
     497        pc = self._point_configuration
     498        return tuple( pc.simplex_to_int(t) for t in self )
     499
     500
     501    def fan(self, origin=None):
     502        r"""
     503        Construct the fan of cones over the simplices of the triangulation.
     504
     505        INPUT:
     506
     507        - ``origin`` -- ``None`` (default) or coordinates of a
     508          point. The common apex of all cones of the fan. If ``None``,
     509          the triangulation must be a star triangulation and the
     510          distinguished central point is used as the origin.
     511
     512        OUTPUT:
     513
     514        A :class:`~sage.geometry.fan.RationalPolyhedralFan`. The
     515        coordinates of the points are shifted so that the apex of the
     516        fan is the origin of the coordinate system.
     517       
     518        .. note:: If the set of cones over the simplices is not a fan, a
     519            suitable exception is raised.
     520
     521        EXAMPLES::
     522       
     523            sage: pc = PointConfiguration([(0,0), (1,0), (0,1), (-1,-1)], star=0, fine=True)
     524            sage: pc.set_engine('internal')   # to make doctests independent of TOPCOM
     525            sage: triangulation = pc.triangulate()
     526            sage: fan = triangulation.fan(); fan
     527            Rational polyhedral fan in 2-d lattice N
     528            sage: fan.is_equivalent( toric_varieties.P2().fan() )
     529            True
     530
     531        Toric diagrams (the `\ZZ_5` hyperconifold)::
     532
     533            sage: vertices=[(0, 1, 0), (0, 3, 1), (0, 2, 3), (0, 0, 2)]
     534            sage: interior=[(0, 1, 1), (0, 1, 2), (0, 2, 1), (0, 2, 2)]
     535            sage: points = vertices+interior
     536            sage: pc = PointConfiguration(points, fine=True)
     537            sage: pc.set_engine('internal')   # to make doctests independent of TOPCOM
     538            sage: triangulation = pc.triangulate()
     539            sage: fan = triangulation.fan( (-1,0,0) )
     540            sage: fan
     541            Rational polyhedral fan in 3-d lattice N
     542            sage: fan.rays()
     543            (N(1, 1, 0), N(1, 3, 1), N(1, 2, 3), N(1, 0, 2),
     544             N(1, 1, 1), N(1, 1, 2), N(1, 2, 1), N(1, 2, 2))
     545        """
     546        from sage.geometry.fan import Fan
     547        if origin is None:
     548            origin = self.point_configuration().star_center()
     549        R = self.base_ring()
     550        origin = vector(R, origin)
     551        points = self.point_configuration().points()
     552        return Fan(self, (vector(R, p) - origin for p in points))
     553
     554
     555    def simplicial_complex(self):
     556        r"""
     557        Return a simplicial complex from a triangulation of the point
     558        configuration.
     559
     560        OUTPUT:
     561
     562        A :class:`~sage.homology.simplicial_complex.SimplicialComplex`.
     563
     564        EXAMPLES::
     565
     566            sage: p = polytopes.cuboctahedron()
     567            sage: sc = p.triangulate().simplicial_complex()
     568            sage: sc   
     569            Simplicial complex with 12 vertices and 16 facets
     570        """
     571        from sage.homology.simplicial_complex import SimplicialComplex
     572        from sage.misc.all import flatten
     573        vertex_set = set(flatten(self))
     574        return SimplicialComplex(vertex_set = vertex_set,
     575                                 maximal_faces = self)
     576
  • sage/geometry/triangulation/point_configuration.py

    diff --git a/sage/geometry/triangulation/point_configuration.py b/sage/geometry/triangulation/point_configuration.py
    a b  
    171171from sage.geometry.triangulation.base import \
    172172    PointConfiguration_base, Point, ConnectedTriangulationsIterator
    173173
    174 
    175 ########################################################################
    176 def triangulation_render_2d(triangulation, **kwds):
    177     r"""
    178     Return a graphical representation of a 2-d triangulation.
    179 
    180     INPUT:
    181    
    182     - ``triangulation`` -- a :class:`Triangulation`.
    183    
    184     - ``**kwds`` -- keywords that are passed on to the graphics primitives.
    185 
    186     OUTPUT:
    187 
    188     A 2-d graphics object.
    189 
    190     EXAMPLES::
    191    
    192         sage: points = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])
    193         sage: triang = points.triangulate()
    194         sage: triang.plot(axes=False)   # indirect doctest
    195     """
    196     from sage.plot.all import point2d, line2d, arrow, polygon2d
    197     points = [ point.reduced_affine() for point in triangulation.point_configuration() ]
    198     coord = [ [p[0], p[1]] for p in points ]
    199     plot_points = sum([ point2d(p,
    200                                 zorder=2, pointsize=10, **kwds)
    201                         for p in coord ])
    202 
    203     tmp_lines = []
    204     for t in triangulation:
    205         if len(t)>=2:
    206             tmp_lines.append([t[0], t[1]])
    207         if len(t)>=3:
    208             tmp_lines.append([t[0], t[2]])
    209             tmp_lines.append([t[1], t[2]])
    210     all_lines = []
    211     interior_lines = []
    212     for l in tmp_lines:
    213         if l not in all_lines:
    214             all_lines.append(l)
    215         else:
    216             interior_lines.append(l)
    217     exterior_lines = [ l for l in all_lines if not l in interior_lines ]
    218            
    219     plot_interior_lines = sum([ line2d([ coord[l[0]], coord[l[1]] ],
    220                                        zorder=1, rgbcolor=(0,1,0), **kwds)
    221                                 for l in interior_lines ])
    222     plot_exterior_lines = sum([ line2d([ coord[l[0]], coord[l[1]] ],
    223                                        zorder=1, rgbcolor=(0,0,1), **kwds)
    224                                 for l in exterior_lines ])
    225 
    226     plot_triangs = sum([ polygon2d([coord[t[0]], coord[t[1]], coord[t[2]]],
    227                                    zorder=0, rgbcolor=(0.8, 1, 0.8), **kwds)
    228                          for t in triangulation if len(t)>=3 ])
    229 
    230     return \
    231         plot_points + \
    232         plot_interior_lines + plot_exterior_lines + \
    233         plot_triangs
    234 
    235 
    236 
    237 
    238 def triangulation_render_3d(triangulation, **kwds):
    239     r"""
    240     Return a graphical representation of a 3-d triangulation.
    241 
    242     INPUT:
    243    
    244     - ``triangulation`` -- a :class:`Triangulation`.
    245    
    246     - ``**kwds`` -- keywords that are  passed on to the graphics primitives.
    247 
    248     OUTPUT:
    249 
    250     A 3-d graphics object.
    251 
    252     EXAMPLES::
    253    
    254         sage: p = [[0,-1,-1],[0,0,1],[0,1,0], [1,-1,-1],[1,0,1],[1,1,0]]
    255         sage: points = PointConfiguration(p)
    256         sage: triang = points.triangulate()
    257         sage: triang.plot(axes=False)     # indirect doctest
    258     """
    259     from sage.plot.plot3d.all import point3d, line3d, arrow3d, polygon3d
    260     points = [ point.reduced_affine() for point in triangulation.point_configuration() ]
    261     coord = [ [p[0], p[1], p[2] ] for p in points ]
    262     plot_points = sum([ point3d(p, size=15,
    263                                 **kwds)
    264                         for p in coord ])
    265 
    266     tmp_lines = []
    267     for t in triangulation:
    268         if len(t)>=2:
    269             tmp_lines.append([t[0], t[1]])
    270         if len(t)>=3:
    271             tmp_lines.append([t[0], t[2]])
    272             tmp_lines.append([t[1], t[2]])
    273         if len(t)>=4:
    274             tmp_lines.append([t[0], t[3]])
    275             tmp_lines.append([t[1], t[3]])
    276             tmp_lines.append([t[2], t[3]])
    277     all_lines = []
    278     interior_lines = []
    279     for l in tmp_lines:
    280         if l not in all_lines:
    281             all_lines.append(l)
    282         else:
    283             interior_lines.append(l)
    284     exterior_lines = [ l for l in all_lines if not l in interior_lines ]
    285 
    286     from sage.plot.plot3d.texture import Texture
    287     line_int = Texture(color='darkblue', ambient=1, diffuse=0)
    288     line_ext = Texture(color='green', ambient=1, diffuse=0)
    289     triang_int = Texture(opacity=0.3, specular=0, shininess=0, diffuse=0, ambient=1, color='yellow')
    290     triang_ext = Texture(opacity=0.6, specular=0, shininess=0, diffuse=0, ambient=1, color='green')
    291            
    292     plot_interior_lines = sum([ line3d([ coord[l[0]], coord[l[1]] ],
    293                                        thickness=2, texture=line_int, **kwds)
    294                                 for l in interior_lines ])
    295     plot_exterior_lines = sum([ line3d([ coord[l[0]], coord[l[1]] ],
    296                                        thickness=3, texture=line_ext, **kwds)
    297                                 for l in exterior_lines ])
    298 
    299     tmp_triangs = []
    300     for t in triangulation:
    301         if len(t)>=3:
    302             tmp_triangs.append([t[0], t[1], t[2]])
    303         if len(t)>=4:
    304             tmp_triangs.append([t[0], t[1], t[3]])
    305             tmp_triangs.append([t[0], t[2], t[3]])
    306             tmp_triangs.append([t[1], t[2], t[3]])
    307     all_triangs = []
    308     interior_triangs = []
    309     for l in tmp_triangs:
    310         if l not in all_triangs:
    311             all_triangs.append(l)
    312         else:
    313             interior_triangs.append(l)
    314     exterior_triangs = [ l for l in all_triangs if not l in interior_triangs ]
    315    
    316     plot_interior_triangs = \
    317         sum([ polygon3d([coord[t[0]], coord[t[1]], coord[t[2]]],
    318                         texture = triang_int, **kwds)
    319               for t in interior_triangs ])
    320     plot_exterior_triangs = \
    321         sum([ polygon3d([coord[t[0]], coord[t[1]], coord[t[2]]],
    322                         texture = triang_ext, **kwds)
    323               for t in exterior_triangs ])
    324 
    325     return \
    326         plot_points + \
    327         plot_interior_lines + plot_exterior_lines + \
    328         plot_interior_triangs + plot_exterior_triangs
    329 
    330 
    331 
    332 
    333 
    334 ########################################################################
    335 class Triangulation(Element):
    336     """
    337     A triangulation of a :class:`PointConfiguration`.
    338 
    339     .. WARNING::
    340  
    341         You should never create :class:`Triangulation` objects
    342         manually. See
    343         :meth:`~sage.geometry.triangulate.PointConfiguration.triangulate`
    344         and
    345         :meth:`~sage.geometry.triangulate.PointConfiguration.triangulations`
    346         to triangulate point configurations.
    347     """
    348 
    349     def __init__(self, triangulation, parent, check=True):
    350         """
    351         The constructor of a ``Triangulation`` object. Note that an
    352         internal reference to the underlying ``PointConfiguration`` is
    353         kept.
    354 
    355         INPUT:
    356 
    357         - ``parent`` -- a :class:`PointConfiguration`
    358        
    359         - ``triangulation`` -- an iterable of integers or iterable of
    360           iterables (e.g. a list of lists). In the first case, the
    361           integers specify simplices via
    362           :meth:`PointConfiguration.simplex_to_int`. In the second
    363           case, the point indices of the maximal simplices of the
    364           triangulation.
    365 
    366         - ``check`` -- boolean. Whether to perform checks that the
    367           triangulation is, indeed, a triangulation of the point
    368           configuration.
    369 
    370         NOTE:
    371 
    372         Passing ``check=False`` allows you to create triangulations of
    373         subsets of the points of the configuration, see
    374         :meth:`PointConfiguration.bistellar_flips`.
    375 
    376         EXAMPLES::
    377        
    378             sage: p = [[0,1],[0,0],[1,0]]
    379             sage: points = PointConfiguration(p)
    380             sage: from sage.geometry.triangulation.point_configuration import Triangulation
    381             sage: Triangulation([(0,1,2)], points)
    382             (<0,1,2>)
    383             sage: Triangulation([1], points)
    384             (<0,1,2>)
    385         """
    386         Element.__init__(self, parent=parent)
    387         self._point_configuration = parent
    388 
    389         try:
    390             triangulation = tuple(sorted( tuple(sorted(t)) for t in triangulation))
    391         except TypeError:
    392             triangulation = tuple( self.point_configuration().int_to_simplex(i)
    393                                    for i in triangulation )
    394         assert not check or all( len(t)==self.point_configuration().dim()+1
    395                                  for t in triangulation)
    396         self._triangulation = triangulation
    397 
    398 
    399     def point_configuration(self):
    400         """
    401         Returns the point configuration underlying the triangulation.
    402 
    403         EXAMPLES::
    404        
    405             sage: pconfig = PointConfiguration([[0,0],[0,1],[1,0]])
    406             sage: pconfig
    407             A point configuration in QQ^2 consisting of 3 points. The
    408             triangulations of this point configuration are assumed to
    409             be connected, not necessarily fine, not necessarily regular.
    410             sage: triangulation = pconfig.triangulate()
    411             sage: triangulation
    412             (<0,1,2>)
    413             sage: triangulation.point_configuration()
    414             A point configuration in QQ^2 consisting of 3 points. The
    415             triangulations of this point configuration are assumed to
    416             be connected, not necessarily fine, not necessarily regular.
    417             sage: pconfig == triangulation.point_configuration()
    418             True
    419         """
    420         return self._point_configuration
    421 
    422 
    423     def __cmp__(self, right):
    424         r"""
    425         Compare ``self`` and ``right``.
    426 
    427         INPUT:
    428 
    429         - ``right`` -- anything.
    430 
    431         OUTPUT:
    432 
    433         - 0 if ``right`` is the same triangulation as ``self``, 1 or
    434           -1 otherwise.
    435 
    436         TESTS::
    437 
    438             sage: pc = PointConfiguration([[0,0],[0,1],[1,0]])
    439             sage: t1 = pc.triangulate()
    440             sage: from sage.geometry.triangulation.point_configuration import Triangulation
    441             sage: t2 = Triangulation([[2,1,0]], pc)
    442             sage: t1 is t2
    443             False
    444             sage: cmp(t1, t2)
    445             0
    446             sage: t1 == t2    # indirect doctest
    447             True
    448             sage: abs( cmp(t1, Triangulation(((0,1),(1,2)), pc, check=False) ))
    449             1
    450             sage: abs( cmp(t2, "not a triangulation") )
    451             1
    452         """
    453         left = self
    454         c = cmp(isinstance(left,Triangulation), isinstance(right,Triangulation))
    455         if c: return c
    456         c = cmp(left.point_configuration(), right.point_configuration())
    457         if c: return c
    458         return cmp(left._triangulation, right._triangulation)
    459 
    460 
    461     def __iter__(self):
    462         """
    463         Iterate through the simplices of the triangulation.
    464 
    465         EXAMPLES::
    466 
    467             sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])
    468             sage: triangulation = pc.triangulate()
    469             sage: iter = triangulation.__iter__()
    470             sage: iter.next()
    471             (1, 3, 4)
    472             sage: iter.next()
    473             (2, 3, 4)
    474             sage: iter.next()
    475             Traceback (most recent call last):
    476             ...
    477             StopIteration
    478         """
    479         for p in self._triangulation:
    480             yield p
    481 
    482 
    483     def __getitem__(self, i):
    484         """
    485         Access the point indices of the i-th simplex of the triangulation.
    486 
    487         INPUT:
    488 
    489         - ``i`` -- integer. The index of a simplex.
    490        
    491         OUTPUT:
    492 
    493         A tuple of integers. The vertex indices of the i-th simplex.
    494 
    495         EXAMPLES::
    496        
    497             sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])
    498             sage: triangulation = pc.triangulate()
    499             sage: triangulation[1]
    500             (2, 3, 4)
    501         """
    502         return self._triangulation[i]
    503 
    504 
    505     def __len__(self):
    506         """
    507         Returns the length of the triangulation.
    508 
    509         TESTS::
    510 
    511             sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])
    512             sage: triangulation = pc.triangulations().next()
    513             sage: triangulation.__len__()
    514             2
    515             sage: len(triangulation)    # equivalent
    516             2
    517         """
    518         return len(self._triangulation)
    519 
    520 
    521     def _repr_(self):
    522         r"""
    523         Return a string representation.
    524        
    525         TESTS::
    526 
    527             sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1],[2,2]])
    528             sage: t = pc.triangulations()
    529             sage: t.next()._repr_()
    530             '(<1,4,5>, <2,4,5>)'
    531         """
    532         #s = 'A triangulation'
    533         #s += ' in QQ^'+str(self.point_configuration().ambient_dim())
    534         #s += ' consisting of '+str(len(self))+' simplices.'
    535         s = '('
    536         s += ', '.join([ '<'+','.join(map(str,t))+'>' for t in self._triangulation])
    537         s += ')'
    538         return s
    539    
    540 
    541     def plot(self, **kwds):
    542         r"""
    543         Produce a graphical representation of the triangulation.
    544 
    545         EXAMPLES::
    546        
    547             sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]])
    548             sage: triangulation = p.triangulate()
    549             sage: triangulation
    550             (<1,3,4>, <2,3,4>)
    551             sage: triangulation.plot(axes=False)
    552         """
    553         dim = self.point_configuration().dim()
    554        
    555         if dim == 2:
    556             return triangulation_render_2d(self, **kwds)
    557 
    558         if dim == 3:
    559             return triangulation_render_3d(self, **kwds)
    560 
    561         raise NotImplementedError, \
    562             'Plotting '+str(dim)+'-dimensional triangulations not implemented!'
    563    
    564 
    565     def gkz_phi(self):
    566         r"""
    567         Calculate the GKZ phi vector of the triangulation. 
    568        
    569         OUTPUT:
    570 
    571         Vector -- the phi vector of self.
    572 
    573         EXAMPLES::
    574 
    575             sage: p = PointConfiguration([[0,0],[1,0],[2,1],[1,2],[0,1]])
    576             sage: p.triangulate().gkz_phi()
    577             (1, 3, 4, 2, 5)
    578 
    579         NOTE:
    580 
    581         For a definition of the phi vector, see [GKZ]_ page 220 equation 1.4.
    582         """
    583         vec = vector(ZZ, self.point_configuration().n_points())
    584         for simplex in self:
    585             vol = self.point_configuration().volume(simplex)
    586             for i in simplex:
    587                 vec[i] = vec[i] + vol
    588         return vec
    589 
    590 
    591     def enumerate_simplices(self):
    592         r"""
    593         Return the enumerated simplices.
    594 
    595         OUTPUT:
    596        
    597         A tuple of integers that uniquely specifies the triangulation.
    598 
    599         EXAMPLES::
    600 
    601             sage: pc = PointConfiguration(matrix([
    602             ...      [ 0, 0, 0, 0, 0, 2, 4,-1, 1, 1, 0, 0, 1, 0],
    603             ...      [ 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0],
    604             ...      [ 0, 2, 0, 0, 0, 0,-1, 0, 1, 0, 1, 0, 0, 1],
    605             ...      [ 0, 1, 1, 0, 0, 1, 0,-2, 1, 0, 0,-1, 1, 1],
    606             ...      [ 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0]
    607             ...   ]).columns())
    608             sage: triangulation = pc.lexicographic_triangulation()
    609             sage: triangulation.enumerate_simplices()
    610             (1678, 1688, 1769, 1779, 1895, 1905, 2112, 2143, 2234, 2360, 2555, 2580,
    611              2610, 2626, 2650, 2652, 2654, 2661, 2663, 2667, 2685, 2755, 2757, 2759,
    612              2766, 2768, 2772, 2811, 2881, 2883, 2885, 2892, 2894, 2898)
    613 
    614         You can recreate the triangulation from this list by passing
    615         it to the constructor::
    616 
    617             sage: from sage.geometry.triangulation.point_configuration import Triangulation
    618             sage: Triangulation([1678, 1688, 1769, 1779, 1895, 1905, 2112, 2143,
    619             ...    2234, 2360, 2555, 2580, 2610, 2626, 2650, 2652, 2654, 2661, 2663,
    620             ...    2667, 2685, 2755, 2757, 2759, 2766, 2768, 2772, 2811, 2881, 2883,
    621             ...    2885, 2892, 2894, 2898], pc)
    622             (<1,3,4,7,10,13>, <1,3,4,8,10,13>, <1,3,6,7,10,13>, <1,3,6,8,10,13>,
    623              <1,4,6,7,10,13>, <1,4,6,8,10,13>, <2,3,4,6,7,12>, <2,3,4,7,12,13>,
    624              <2,3,6,7,12,13>, <2,4,6,7,12,13>, <3,4,5,6,9,12>, <3,4,5,8,9,12>,
    625              <3,4,6,7,11,12>, <3,4,6,9,11,12>, <3,4,7,10,11,13>, <3,4,7,11,12,13>,
    626              <3,4,8,9,10,12>, <3,4,8,10,12,13>, <3,4,9,10,11,12>, <3,4,10,11,12,13>,
    627              <3,5,6,8,9,12>, <3,6,7,10,11,13>, <3,6,7,11,12,13>, <3,6,8,9,10,12>,
    628              <3,6,8,10,12,13>, <3,6,9,10,11,12>, <3,6,10,11,12,13>, <4,5,6,8,9,12>,
    629              <4,6,7,10,11,13>, <4,6,7,11,12,13>, <4,6,8,9,10,12>, <4,6,8,10,12,13>,
    630              <4,6,9,10,11,12>, <4,6,10,11,12,13>)
    631         """
    632         pc = self._point_configuration
    633         return tuple( pc.simplex_to_int(t) for t in self )
    634 
    635 
    636     def fan(self, origin=None):
    637         r"""
    638         Construct the fan of cones over the simplices of the triangulation.
    639 
    640         INPUT:
    641 
    642         - ``origin`` -- ``None`` (default) or coordinates of a
    643           point. The common apex of all cones of the fan. If ``None``,
    644           the triangulation must be a star triangulation and the
    645           distinguished central point is used as the origin.
    646 
    647         OUTPUT:
    648 
    649         A :class:`sage.geometry.fan.RationalPolyhedralFan`. The
    650         coordinates of the points are shifted so that the apex of
    651         the fan is the origin of the coordinate system.
    652        
    653         .. note:: If the set of cones over the simplices is not a fan, a
    654             suitable exception is raised.
    655 
    656         EXAMPLES::
    657        
    658             sage: pc = PointConfiguration([(0,0), (1,0), (0,1), (-1,-1)], star=0, fine=True)
    659             sage: pc.set_engine('internal')   # to make doctests independent of TOPCOM
    660             sage: triangulation = pc.triangulate()
    661             sage: fan = triangulation.fan(); fan
    662             Rational polyhedral fan in 2-d lattice N
    663             sage: fan.is_equivalent( toric_varieties.P2().fan() )
    664             True
    665 
    666         Toric diagrams (the `\ZZ_5` hyperconifold)::
    667 
    668             sage: vertices=[(0, 1, 0), (0, 3, 1), (0, 2, 3), (0, 0, 2)]
    669             sage: interior=[(0, 1, 1), (0, 1, 2), (0, 2, 1), (0, 2, 2)]
    670             sage: points = vertices+interior
    671             sage: pc = PointConfiguration(points, fine=True)
    672             sage: pc.set_engine('internal')   # to make doctests independent of TOPCOM
    673             sage: triangulation = pc.triangulate()
    674             sage: fan = triangulation.fan( (-1,0,0) )
    675             sage: fan
    676             Rational polyhedral fan in 3-d lattice N
    677             sage: fan.rays()
    678             (N(1, 1, 0), N(1, 3, 1), N(1, 2, 3), N(1, 0, 2),
    679              N(1, 1, 1), N(1, 1, 2), N(1, 2, 1), N(1, 2, 2))
    680         """
    681         from sage.geometry.fan import Fan
    682         if origin is None:
    683             origin = self.point_configuration().star_center()
    684         R = self.base_ring()
    685         origin = vector(R, origin)
    686         points = self.point_configuration().points()
    687         return Fan(self, (vector(R, p) - origin for p in points))
    688 
    689 
    690     def simplicial_complex(self):
    691         r"""
    692         Return a simplicial complex from a triangulation of the point
    693         configuration.
    694 
    695         OUTPUT:
    696 
    697         A :class:`~sage.homology.simplicial_complex.SimplicialComplex`.
    698 
    699         EXAMPLES::
    700 
    701             sage: p = polytopes.cuboctahedron()
    702             sage: sc = p.triangulate().simplicial_complex()
    703             sage: sc   
    704             Simplicial complex with 12 vertices and 16 facets
    705         """
    706         from sage.homology.simplicial_complex import SimplicialComplex
    707         from sage.misc.all import flatten
    708         vertex_set = set(flatten(self))
    709         return SimplicialComplex(vertex_set = vertex_set,
    710                                  maximal_faces = self)
     174from sage.geometry.triangulation.element import Triangulation
    711175
    712176
    713177########################################################################
     
    910374
    911375        OUTPUT:
    912376       
    913         A :class:`sage.geometry.triangulation.base.Point` if a
     377        A :class:`~sage.geometry.triangulation.base.Point` if a
    914378        distinguished star central point has been fixed.
    915379        ``ValueError`` exception is raised otherwise.
    916380
     
    1144608       
    1145609
    1146610    def _TOPCOM_communicate(self, executable, verbose=True):
    1147         r"""
    1148         Execute TOPCOM and parse the output into a :class:`Triangulation`.
     611        r"""
     612        Execute TOPCOM and parse the output into a
     613        :class:`~sage.geometry.triangulation.element.Triangulation`.
    1149614       
    1150615        TESTS::
    1151616
     
    1222687
    1223688        OUTPUT:
    1224689
    1225         A :class:`sage.geometry.triangulation.Triangulation`
     690        A :class:`~sage.geometry.triangulation.element.Triangulation`
    1226691        satisfying all restrictions imposed. Raises a ``ValueError``
    1227692        if no such triangulation exists.
    1228693
     
    1422887
    1423888        A generator for the triangulations satisfying all the
    1424889        restrictions imposed. Each triangulation is returned as a
    1425         :class:`Triangulation` object.
     890        :class:`~sage.geometry.triangulation.element.Triangulation` object.
    1426891
    1427892        EXAMPLES::
    1428893       
     
    1496961
    1497962        OUTPUT:
    1498963
    1499         A list of triangulations (see :class:`Triangulation`)
     964        A list of triangulations (see
     965        :class:`~sage.geometry.triangulation.element.Triangulation`)
    1500966        satisfying all restrictions imposed previously.
    1501967
    1502968        EXAMPLES::
     
    1525991
    1526992        OUTPUT:
    1527993
    1528         A :class:`Triangulation` satisfying all restrictions
    1529         imposed. Raises a ``ValueError`` if no such triangulation
    1530         exists.
     994        A :class:`~sage.geometry.triangulation.element.Triangulation`
     995        satisfying all restrictions imposed. Raises a ``ValueError``
     996        if no such triangulation exists.
    1531997
    1532998        EXAMPLES::
    1533999