Ticket #13226: trac_13226-pseudomanifold.patch

File trac_13226-pseudomanifold.patch, 6.2 KB (added by jhpalmieri, 9 years ago)
  • sage/homology/simplicial_complex.py

    # HG changeset patch
    # User J. H. Palmieri <palmieri@math.washington.edu>
    # Date 1270868091 25200
    # Node ID ccc751f3509c5fad8b73d506a78831ee73b45d7e
    # Parent  4bc630d1ba6bae24ce7fbdd5fda5bb949eeea32f
    Implement test for whether a simplicial complex is a pseudomanifold.
    For pseudomanifolds, construct their suspension using Datta's one-point
    suspension.
    
    diff --git a/sage/homology/simplicial_complex.py b/sage/homology/simplicial_complex.py
    a b class SimplicialComplex(GenericCellCompl 
    11151115            g.append(h[i] - h[i-1])
    11161116        return g
    11171117
     1118    def is_pseudomanifold(self):
     1119        """
     1120        Return True if self is a pseudomanifold.
     1121
     1122        A pseudomanifold is a simplicial complex with the following properties:
     1123
     1124        - it is pure of some dimension `d` (all of its facets are `d`-dimensional)
     1125        - every `(d-1)`-dimensional simplex is the face of exactly two facets
     1126        - for every two facets `S` and `T`, there is a sequence of
     1127          facets
     1128
     1129          .. math::
     1130
     1131            S = f_0, f_1, ..., f_n = T
     1132
     1133          such that for each `i`, `f_i` and `f_{i-1}` intersect in a
     1134          `(d-1)`-simplex.
     1135
     1136        By convention, `S^0` is the only 0-dimensional pseudomanifold.
     1137
     1138        EXAMPLES::
     1139
     1140            sage: S0 = simplicial_complexes.Sphere(0)
     1141            sage: S0.is_pseudomanifold()
     1142            True
     1143            sage: (S0.wedge(S0)).is_pseudomanifold()
     1144            False
     1145            sage: S1 = simplicial_complexes.Sphere(1)
     1146            sage: S2 = simplicial_complexes.Sphere(2)
     1147            sage: (S1.wedge(S1)).is_pseudomanifold()
     1148            False
     1149            sage: (S1.wedge(S2)).is_pseudomanifold()
     1150            False
     1151            sage: S2.is_pseudomanifold()
     1152            True
     1153            sage: T = simplicial_complexes.Torus()
     1154            sage: T.suspension(4).is_pseudomanifold()
     1155            True
     1156        """
     1157        if not self.is_pure():
     1158            return False
     1159        d = self.dimension()
     1160        if d == 0:
     1161            return len(self.facets()) == 2
     1162        F = self.facets()
     1163        X = self.n_faces(d-1)
     1164        # is each (d-1)-simplex is the face of exactly two facets?
     1165        for s in X:
     1166            if len([a for a in [s.is_face(f) for f in F] if a]) != 2:
     1167                return False
     1168        # construct a graph with one vertex for each facet, one edge
     1169        # when two facets intersect in a (d-1)-simplex, and see
     1170        # whether that graph is connected.
     1171        V = [f.set() for f in self.facets()]
     1172        E = (lambda a,b: len(a.intersection(b)) == d)
     1173        g = Graph([V,E])
     1174        return g.is_connected()
     1175
    11181176    def product(self, right, rename_vertices=True):
    11191177        """
    11201178        The product of this simplicial complex with another one.
    class SimplicialComplex(GenericCellCompl 
    12491307                         rename_vertices = True)
    12501308
    12511309    def suspension(self, n=1):
    1252         """
     1310        r"""
    12531311        The suspension of this simplicial complex.
    12541312
    12551313        :param n: positive integer -- suspend this many times.
    class SimplicialComplex(GenericCellCompl 
    12631321        is, the suspension is the join of the original complex with a
    12641322        two-point simplicial complex.
    12651323
     1324        If the simplicial complex `M` happens to be a pseudomanifold
     1325        (see :meth:`is_pseudomanifold`), then this instead constructs
     1326        Datta's one-point suspension (see p. 434 in the cited
     1327        article): choose a vertex `u` in `M` and choose a new vertex
     1328        `w` to add.  Denote the join of simplices by "`*`".  The
     1329        facets in the one-point suspension are of the two forms
     1330
     1331        - `u * \alpha` where `\alpha` is a facet of `M` not containing
     1332          `u`
     1333
     1334        - `w * \beta` where `\beta` is any facet of `M`.
     1335
     1336        REFERENCES:
     1337       
     1338        - Basudeb Datta, "Minimal triangulations of manifolds",
     1339          J. Indian Inst. Sci. 87 (2007), no. 4, 429-449.
     1340
    12661341        EXAMPLES::
    12671342
    1268             sage: S = SimplicialComplex(1, [[0], [1]])
    1269             sage: S.suspension()
    1270             Simplicial complex with vertex set ('L0', 'L1', 'R0', 'R1') and 4 facets
    1271             sage: S3 = S.suspension(3)  # the 3-sphere
     1343            sage: S0 = SimplicialComplex(1, [[0], [1]])
     1344            sage: S0.suspension() == simplicial_complexes.Sphere(1)
     1345            True
     1346            sage: S3 = S0.suspension(3)  # the 3-sphere
    12721347            sage: S3.homology()
    12731348            {0: 0, 1: 0, 2: 0, 3: Z}
     1349
     1350        For pseudomanifolds, the complex constructed here will be
     1351        smaller than that obtained by taking the join with the
     1352        0-sphere: the join adds two vertices, while this construction
     1353        only adds one. ::
     1354
     1355            sage: T = simplicial_complexes.Torus()
     1356            sage: T.join(S0).vertices()      # 9 vertices
     1357            ('L0', 'L1', 'L2', 'L3', 'L4', 'L5', 'L6', 'R0', 'R1')
     1358            sage: T.suspension().vertices()  # 8 vertices
     1359            (0, 1, 2, 3, 4, 5, 6, 7)
    12741360        """
    12751361        if n<0:
    12761362            raise ValueError, "n must be non-negative."
    12771363        if n==0:
    12781364            return self
    12791365        if n==1:
    1280             return self.join(SimplicialComplex(["0", "1"], [["0"], ["1"]]),
    1281                              rename_vertices = True)
     1366            if self.is_pseudomanifold():
     1367                # Use one-point compactification of Datta. The
     1368                # construction is a bit slower, but the resulting
     1369                # complex is smaller.
     1370                V = self.vertices()
     1371                u = V[0]
     1372                w = 0
     1373                while w in V:
     1374                    w += 1
     1375                w = Simplex([w])
     1376                new_facets = []
     1377                for f in self.facets():
     1378                    if u not in f:
     1379                        new_facets.append(f.join(Simplex([u]), rename_vertices=False))
     1380                    new_facets.append(f.join(w, rename_vertices=False))
     1381                return SimplicialComplex(new_facets)
     1382            else:
     1383                return self.join(SimplicialComplex(["0", "1"], [["0"], ["1"]]),
     1384                                 rename_vertices = True)
    12821385        return self.suspension().suspension(int(n-1))
    12831386
    12841387    def disjoint_union(self, right, rename_vertices=True):