Ticket #9122: trac_9122-cubical-simplicial.patch

File trac_9122-cubical-simplicial.patch, 12.2 KB (added by John Palmieri, 12 years ago)
  • sage/homology/cubical_complex.py

    # HG changeset patch
    # User J. H. Palmieri <palmieri@math.washington.edu>
    # Date 1275517397 25200
    # Node ID 7993564c6cb70b65d2f637b7017566e585d7f094
    # Parent  3a18981812ffcad0bfbba8c9823ad3005f81ce86
    trac 9122: conversions between simplicial and cubical complexes
    
    diff -r 3a18981812ff -r 7993564c6cb7 sage/homology/cubical_complex.py
    a b  
    497497
    498498        return (insert_self, insert_other, translate)
    499499
     500    def _triangulation_(self):
     501        r"""
     502        Triangulate this cube by "pulling vertices," as described by
     503        Hetyei.  Return a list of simplices which triangulate
     504        ``self``.
     505
     506        ALGORITHM:
     507
     508        If the cube is given by
     509
     510        .. math::
     511
     512           C = [i_1, j_1] \times [i_2, j_2] \times ... \times [i_k, j_k]
     513
     514        let `v_1` be the "upper" corner of `C`: `v` is the point
     515        `(j_1, ..., j_k)`.  Choose a coordinate `n` where the interval
     516        `[i_n, j_n]` is non-degenerate and form `v_2` by replacing
     517        `j_n` by `i_n`; repeat to define `v_3`, etc.  The last vertex
     518        so defined will be `(i_1, ..., i_k)`.  These vertices define a
     519        simplex, as do the vertices obtained by making different
     520        choices at each stage.  Return the list of such simplices;
     521        thus if `C` is `n`-dimensional, then it is subdivided into
     522        `n!` simplices.
     523
     524        REFERENCES:
     525
     526        - G. Hetyei, "On the Stanley ring of a cubical complex",
     527          Discrete Comput. Geom. 14 (1995), 305-330.
     528
     529        EXAMPLES::
     530
     531            sage: from sage.homology.cubical_complex import Cube
     532            sage: C = Cube([[1,2], [3,4]]); C
     533            [1,2] x [3,4]
     534            sage: C._triangulation_()
     535            [((1, 3), (1, 4), (2, 4)), ((1, 3), (2, 3), (2, 4))]
     536            sage: C = Cube([[1,2], [3,4], [8,9]])
     537            sage: len(C._triangulation_())
     538            6
     539        """
     540        from sage.homology.simplicial_complex import Simplex
     541        if self.dimension() < 0: # the empty cube
     542            return [Simplex(())] # the empty simplex
     543        v = tuple([max(j) for j in self.tuple()])
     544        if self.dimension() == 0: # just v
     545            return [Simplex((v,))]
     546        simplices = []
     547        for i in range(self.dimension()):
     548            for S in self.face(i, upper=False)._triangulation_():
     549                simplices.append(S.join(Simplex((v,)), rename_vertices=False))
     550        return simplices
     551
    500552    def __cmp__(self, other):
    501553        """
    502554        Return True iff this cube is the same as ``other``: that is,
     
    583635    class :class:`Cube`, or lists or tuples suitable for conversion to
    584636    cubes.  These cubes are the maximal cubes in the complex.
    585637
     638    In addition, ``maximal_faces`` may be a cubical complex, in which
     639    case that complex is returned.  Also, ``maximal_faces`` may
     640    instead be any object which has a ``_cubical_`` method (e.g., a
     641    simplicial complex); then that method is used to convert the
     642    object to a cubical complex.
     643
    586644    If ``maximality_check`` is True, check that each maximal face is,
    587645    in fact, maximal. In this case, when producing the internal
    588646    representation of the cubical complex, omit those that are not.
     
    618676        sage: X.homology()
    619677        {0: Z x Z x Z x Z, 1: Z^5}
    620678
     679    Converting a simplicial complex to a cubical complex::
     680
     681        sage: S2 = simplicial_complexes.Sphere(2)
     682        sage: C2 = CubicalComplex(S2)
     683        sage: all([C2.homology(n) == S2.homology(n) for n in range(3)])
     684        True
     685
    621686    You can get the set of maximal cells or a dictionary of all cells::
    622687
    623688        sage: X.maximal_cells()
     
    663728        """
    664729        maximality_check = kwds.get('maximality_check', True)
    665730
     731        C = None
     732        if isinstance(maximal_faces, CubicalComplex):
     733            C = maximal_faces
     734        try:
     735            C = maximal_faces._cubical_()
     736        except AttributeError:
     737            pass
     738        if C is not None:
     739            self._facets = copy(C._facets)
     740            self._cells = copy(C._cells)
     741            self._complex = copy(C._complex)
     742            return
     743
    666744        good_faces = []
    667745        maximal_cubes = [Cube(f) for f in maximal_faces]
    668746        for face in maximal_cubes:
     
    13531431            s += "\n"
    13541432        return s
    13551433
     1434    def _simplicial_(self):
     1435        r"""
     1436        Simplicial complex constructed from self.
     1437
     1438        ALGORITHM:
     1439
     1440        This is constructed as described by Hetyei: choose a total
     1441        ordering of the vertices of the cubical complex.  Then for
     1442        each maximal face
     1443
     1444        .. math::
     1445
     1446           C = [i_1, j_1] \times [i_2, j_2] \times ... \times [i_k, j_k]
     1447
     1448        let `v_1` be the "upper" corner of `C`: `v` is the point
     1449        `(j_1, ..., j_k)`.  Choose a coordinate `n` where the interval
     1450        `[i_n, j_n]` is non-degenerate and form `v_2` by replacing
     1451        `j_n` by `i_n`; repeat to define `v_3`, etc.  The last vertex
     1452        so defined will be `(i_1, ..., i_k)`.  These vertices define a
     1453        simplex, and do the vertices obtained by making different
     1454        choices at each stage.  Thus each `n`-cube is subdivided into
     1455        `n!` simplices.
     1456
     1457        REFERENCES:
     1458
     1459        - G. Hetyei, "On the Stanley ring of a cubical complex",
     1460          Discrete Comput. Geom. 14 (1995), 305-330.
     1461
     1462        EXAMPLES::
     1463
     1464            sage: T = cubical_complexes.Torus(); T
     1465            Cubical complex with 16 vertices and 64 cubes
     1466            sage: len(T.maximal_cells())
     1467            16
     1468
     1469        When this is triangulated, each maximal 2-dimensional cube
     1470        gets turned into a pair of triangles.  Since there were 16
     1471        maximal cubes, this results in 32 facets in the simplicial
     1472        complex::
     1473
     1474            sage: Ts = T._simplicial_(); Ts
     1475            Simplicial complex with 16 vertices and 32 facets
     1476            sage: T.homology() == Ts.homology()
     1477            True
     1478
     1479        Each `n`-dimensional cube produces `n!` `n`-simplices::
     1480
     1481            sage: S4 = cubical_complexes.Sphere(4)
     1482            sage: len(S4.maximal_cells())
     1483            10
     1484            sage: SimplicialComplex(S4) # calls S4._simplicial_()
     1485            Simplicial complex with 32 vertices and 240 facets
     1486        """
     1487        from sage.homology.simplicial_complex import SimplicialComplex
     1488        simplices = []
     1489        for C in self.maximal_cells():
     1490            simplices.extend(C._triangulation_())
     1491        return SimplicialComplex(simplices)
     1492
    13561493    def _string_constants(self):
    13571494        """
    13581495        Tuple containing the name of the type of complex, and the
  • sage/homology/simplicial_complex.py

    diff -r 3a18981812ff -r 7993564c6cb7 sage/homology/simplicial_complex.py
    a b  
    103103#  should + have any meaning?
    104104#  cohomology: compute cup products (and Massey products?)
    105105
     106from copy import copy
    106107from sage.homology.cell_complex import GenericCellComplex
    107108from sage.structure.sage_object import SageObject
    108109from sage.rings.integer import Integer
     
    713714        sage: SimplicialComplex([[0,2], [0,3], [0,6]])
    714715        Simplicial complex with vertex set (0, 2, 3, 6) and facets {(0, 6), (0, 2), (0, 3)}
    715716
     717    Finally, if ``vertex_set`` is the only argument and it is a
     718    simplicial complex, return that complex.  If it is an object with
     719    a built-in conversion to simplicial complexes (via a
     720    ``_simplicial_`` method), then the resulting simplicial complex is
     721    returned::
     722
     723        sage: S = SimplicialComplex([[0,2], [0,3], [0,6]])
     724        sage: SimplicialComplex(S) == S
     725        True
     726        sage: Tc = cubical_complexes.Torus(); Tc
     727        Cubical complex with 16 vertices and 64 cubes
     728        sage: Ts = SimplicialComplex(Tc); Ts
     729        Simplicial complex with 16 vertices and 32 facets
     730        sage: Ts.homology()
     731        {0: 0, 1: Z x Z, 2: Z}
     732
    716733    TESTS::
    717734
    718735        sage: S = SimplicialComplex(['a', 'b', 'c'], (('a', 'b'), ('a', 'c'), ('b', 'c')))
     
    745762        # 'maximal_faces', and use the union of all of the vertices for
    746763        # 'vertex_set'.
    747764        if maximal_faces == []:
     765            C = None
    748766            if isinstance(vertex_set, (list, tuple)) and isinstance(vertex_set[0], (list, tuple, Simplex)):
    749767                maximal_faces = vertex_set
    750768                vertex_set = reduce(union, vertex_set)
     769            elif isinstance(vertex_set, SimplicialComplex):
     770                C = vertex_set
     771            else:
     772                try:
     773                    C = vertex_set._simplicial_()
     774                except AttributeError:
     775                    pass
     776            if C is not None:
     777                self._vertex_set = copy(C.vertices())
     778                self._facets = list(C.facets())
     779                self._faces = copy(C._faces)
     780                self._gen_dict = copy(C._gen_dict)
     781                self._complex = copy(C._complex)
     782                self.__contractible = copy(C.__contractible)
     783                self.__enlarged = copy(C.__enlarged)
     784                self._graph = copy(C._graph)
     785                self._numeric = C._numeric
     786                self._numeric_translation = copy(C._numeric_translation)
     787                return
     788
    751789        if sort_facets:
    752790            try:  # vertex_set is an iterable
    753791                vertices = Simplex(sorted(vertex_set))
     
    23922430                              vertex_check=False, sort_facets=False)
    23932431        self.__enlarged[subcomplex] = L
    23942432        return L
     2433
     2434    def _cubical_(self):
     2435        r"""
     2436        Cubical complex constructed from self.
     2437
     2438        ALGORITHM:
     2439
     2440        The algorithm comes from a paper by Shtan'ko and Shtogrin, as
     2441        reported by Bukhshtaber and Panov.  Let `I^m` denote the unit
     2442        `m`-cube, viewed as a cubical complex.  Let `[m] = \{1, 2,
     2443        ..., m\}`; then each face of `I^m` has the following form, for
     2444        subsets `I \subset J \subset [m]`:
     2445
     2446        .. math::
     2447
     2448            F_{I \subset J} = \{ (y_1,...,y_m) \in I^m \,:\, y_i =0 \text{
     2449            for } i \in I, y_j = 1 \text{ for } j \not \in J\}.
     2450
     2451        If `K` is a simplicial complex on vertex set `[m]` and if `I
     2452        \subset [m]`, write `I \in K` if `I` is a simplex of `K`.
     2453        Then we associate to `K` the cubical subcomplex of `I^m` with
     2454        faces
     2455
     2456        .. math::
     2457
     2458            \{F_{I \subset J} \,:\, J \in K, I \neq \emptyset \}
     2459
     2460        The geometric realization of this cubical complex is
     2461        homeomorphic to the geometric realization of the original
     2462        simplicial complex.
     2463
     2464        REFERENCES:
     2465
     2466        - V. M. Bukhshtaber and T. E. Panov, "Moment-angle complexes
     2467          and combinatorics of simplicial manifolds," *Uspekhi
     2468          Mat. Nauk* 55 (2000), 171--172.
     2469
     2470        - M. A. Shtan'ko and and M. I. Shtogrin, "Embedding cubic
     2471          manifolds and complexes into a cubic lattice", *Uspekhi
     2472          Mat. Nauk* 47 (1992), 219-220.
     2473
     2474        EXAMPLES::
     2475
     2476            sage: T = simplicial_complexes.Torus()
     2477            sage: T.homology()
     2478            {0: 0, 1: Z x Z, 2: Z}
     2479            sage: Tc = T._cubical_()
     2480            sage: Tc
     2481            Cubical complex with 42 vertices and 168 cubes
     2482            sage: Tc.homology()
     2483            {0: 0, 1: Z x Z, 2: Z}
     2484        """
     2485        from sage.homology.cubical_complex import Cube, CubicalComplex
     2486        V = self.vertices()
     2487        embed = V.dimension() + 1
     2488        # dictionary to translate vertices to the numbers 1, ..., embed
     2489        vd = dict(zip(V, range(1, embed + 1)))
     2490        cubes = []
     2491        for JJ in self.facets():
     2492            J = [vd[i] for i in JJ]
     2493            for i in J:
     2494                # loop over indices from 1 to embed.  if equal to i,
     2495                # set to 0. if not in J, set to 1.  Otherwise, range
     2496                # from 0 to 1
     2497                cube = []
     2498                for n in range(1, embed+1):
     2499                    if n == i:
     2500                        cube.append([0,])
     2501                    elif n not in J:
     2502                        cube.append([1,])
     2503                    else:
     2504                        cube.append([0,1])
     2505                cubes.append(cube)
     2506        return CubicalComplex(cubes)
    23952507 
    23962508    def category(self):
    23972509        """