Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/homology/cell_complex.py
8818 views
1
r"""
2
Generic cell complexes
3
4
AUTHORS:
5
6
- John H. Palmieri (2009-08)
7
8
This module defines a class of abstract finite cell complexes. This
9
is meant as a base class from which other classes (like
10
:class:`~sage.homology.simplicial_complex.SimplicialComplex`,
11
:class:`~sage.homology.cubical_complex.CubicalComplex`, and
12
:class:`~sage.homology.delta_complex.DeltaComplex`) should derive. As
13
such, most of its properties are not implemented. It is meant for use
14
by developers producing new classes, not casual users.
15
16
.. NOTE::
17
18
Keywords for :meth:`~GenericCellComplex.chain_complex`,
19
:meth:`~GenericCellComplex.homology`, etc.: any keywords given to
20
the :meth:`~GenericCellComplex.homology` method get passed on to
21
the :meth:`~GenericCellComplex.chain_complex` method and also to
22
the constructor for chain complexes in
23
:class:`sage.homology.chain_complex.ChainComplex_class <ChainComplex>`,
24
as well as its associated
25
:meth:`~sage.homology.chain_complex.ChainComplex_class.homology` method.
26
This means that those keywords should have consistent meaning in
27
all of those situations. It also means that it is easy to
28
implement new keywords: for example, if you implement a new
29
keyword for the
30
:meth:`sage.homology.chain_complex.ChainComplex_class.homology` method,
31
then it will be automatically accessible through the
32
:meth:`~GenericCellComplex.homology` method for cell complexes --
33
just make sure it gets documented.
34
"""
35
36
37
from sage.structure.sage_object import SageObject
38
from sage.rings.integer_ring import ZZ
39
from sage.rings.rational_field import QQ
40
41
class GenericCellComplex(SageObject):
42
r"""
43
Class of abstract cell complexes.
44
45
This is meant to be used by developers to produce new classes, not
46
by casual users. Classes which derive from this are
47
:class:`~sage.homology.simplicial_complex.SimplicialComplex`,
48
:class:`~sage.homology.delta_complex.DeltaComplex`, and
49
:class:`~sage.homology.cubical_complex.CubicalComplex`.
50
51
Most of the methods here are not implemented, but probably should
52
be implemented in a derived class. Most of the other methods call
53
a non-implemented one; their docstrings contain examples from
54
derived classes in which the various methods have been defined.
55
For example, :meth:`homology` calls :meth:`chain_complex`; the
56
class :class:`~sage.homology.delta_complex.DeltaComplex`
57
implements
58
:meth:`~sage.homology.delta_complex.DeltaComplex.chain_complex`,
59
and so the :meth:`homology` method here is illustrated with
60
examples involving `\Delta`-complexes.
61
62
EXAMPLES:
63
64
It's hard to give informative examples of the base class, since
65
essentially nothing is implemented. ::
66
67
sage: from sage.homology.cell_complex import GenericCellComplex
68
sage: A = GenericCellComplex()
69
"""
70
def __cmp__(self,right):
71
"""
72
Comparisons of cell complexes are not implemented.
73
74
EXAMPLES::
75
76
sage: from sage.homology.cell_complex import GenericCellComplex
77
sage: A = GenericCellComplex(); B = GenericCellComplex()
78
sage: A == B # indirect doctest
79
Traceback (most recent call last):
80
...
81
NotImplementedError
82
"""
83
raise NotImplementedError
84
85
############################################################
86
# self.cells() and related methods
87
############################################################
88
89
def cells(self, subcomplex=None):
90
"""
91
The cells of this cell complex, in the form of a dictionary:
92
the keys are integers, representing dimension, and the value
93
associated to an integer `d` is the set of `d`-cells. If the
94
optional argument ``subcomplex`` is present, then return only
95
the faces which are *not* in the subcomplex.
96
97
:param subcomplex: a subcomplex of this cell complex. Return
98
the cells which are not in this subcomplex.
99
:type subcomplex: optional, default None
100
101
This is not implemented in general; it should be implemented
102
in any derived class. When implementing, see the warning in
103
the :meth:`dimension` method.
104
105
This method is used by various other methods, such as
106
:meth:`n_cells` and :meth:`f_vector`.
107
108
EXAMPLES::
109
110
sage: from sage.homology.cell_complex import GenericCellComplex
111
sage: A = GenericCellComplex()
112
sage: A.cells()
113
Traceback (most recent call last):
114
...
115
NotImplementedError
116
"""
117
raise NotImplementedError
118
119
def dimension(self):
120
"""
121
The dimension of this cell complex: the maximum
122
dimension of its cells.
123
124
.. WARNING::
125
126
If the :meth:`cells` method calls :meth:`dimension`,
127
then you'll get an infinite loop. So either don't use
128
:meth:`dimension` or override :meth:`dimension`.
129
130
EXAMPLES::
131
132
sage: simplicial_complexes.RandomComplex(d=5, n=8).dimension()
133
5
134
sage: delta_complexes.Sphere(3).dimension()
135
3
136
sage: T = cubical_complexes.Torus()
137
sage: T.product(T).dimension()
138
4
139
"""
140
try:
141
return max([x.dimension() for x in self._facets])
142
except AttributeError:
143
return max(self.cells())
144
145
def n_cells(self, n, subcomplex=None):
146
"""
147
List of cells of dimension ``n`` of this cell complex.
148
If the optional argument ``subcomplex`` is present, then
149
return the ``n``-dimensional faces which are *not* in the
150
subcomplex.
151
152
:param n: the dimension
153
:type n: non-negative integer
154
:param subcomplex: a subcomplex of this cell complex. Return
155
the cells which are not in this subcomplex.
156
:type subcomplex: optional, default ``None``
157
158
EXAMPLES::
159
160
sage: simplicial_complexes.Simplex(2).n_cells(1)
161
[(1, 2), (0, 2), (0, 1)]
162
sage: delta_complexes.Torus().n_cells(1)
163
[(0, 0), (0, 0), (0, 0)]
164
sage: cubical_complexes.Cube(1).n_cells(0)
165
[[1,1], [0,0]]
166
"""
167
if n in self.cells(subcomplex):
168
return list(self.cells(subcomplex)[n])
169
else:
170
# don't barf if someone asks for n_cells in a dimension where there are none
171
return []
172
173
def f_vector(self):
174
"""
175
The `f`-vector of this cell complex: a list whose `n^{th}`
176
item is the number of `(n-1)`-cells. Note that, like all
177
lists in Sage, this is indexed starting at 0: the 0th element
178
in this list is the number of `(-1)`-cells (which is 1: the
179
empty cell is the only `(-1)`-cell).
180
181
EXAMPLES::
182
183
sage: simplicial_complexes.KleinBottle().f_vector()
184
[1, 8, 24, 16]
185
sage: delta_complexes.KleinBottle().f_vector()
186
[1, 1, 3, 2]
187
sage: cubical_complexes.KleinBottle().f_vector()
188
[1, 42, 84, 42]
189
"""
190
return [self._f_dict()[n] for n in range(-1, self.dimension()+1)]
191
192
def _f_dict(self):
193
"""
194
The `f`-vector of this cell complex as a dictionary: the
195
item associated to an integer `n` is the number of the
196
`n`-cells.
197
198
EXAMPLES::
199
200
sage: simplicial_complexes.KleinBottle()._f_dict()[1]
201
24
202
sage: delta_complexes.KleinBottle()._f_dict()[1]
203
3
204
"""
205
answer = {}
206
answer[-1] = 1
207
for n in range(self.dimension() + 1):
208
answer[n] = len(self.n_cells(n))
209
return answer
210
211
def euler_characteristic(self):
212
r"""
213
The Euler characteristic of this cell complex: the
214
alternating sum over `n \geq 0` of the number of
215
`n`-cells.
216
217
EXAMPLES::
218
219
sage: simplicial_complexes.Simplex(5).euler_characteristic()
220
1
221
sage: delta_complexes.Sphere(6).euler_characteristic()
222
2
223
sage: cubical_complexes.KleinBottle().euler_characteristic()
224
0
225
"""
226
return sum([(-1)**n * self.f_vector()[n+1] for n in range(self.dimension() + 1)])
227
228
############################################################
229
# end of methods using self.cells()
230
############################################################
231
232
def product(self, right, rename_vertices=True):
233
"""
234
The (Cartesian) product of this cell complex with another one.
235
236
Products are not implemented for general cell complexes. They
237
may be implemented in some derived classes (like simplicial
238
complexes).
239
240
EXAMPLES::
241
242
sage: from sage.homology.cell_complex import GenericCellComplex
243
sage: A = GenericCellComplex(); B = GenericCellComplex()
244
sage: A.product(B)
245
Traceback (most recent call last):
246
...
247
NotImplementedError
248
"""
249
raise NotImplementedError
250
251
def disjoint_union(self, right):
252
"""
253
The disjoint union of this simplicial complex with another one.
254
255
:param right: the other simplicial complex (the right-hand factor)
256
257
Disjoint unions are not implemented for general cell complexes.
258
259
EXAMPLES::
260
261
sage: from sage.homology.cell_complex import GenericCellComplex
262
sage: A = GenericCellComplex(); B = GenericCellComplex()
263
sage: A.disjoint_union(B)
264
Traceback (most recent call last):
265
...
266
NotImplementedError
267
"""
268
raise NotImplementedError
269
270
def wedge(self, right):
271
"""
272
The wedge (one-point union) of this simplicial complex with
273
another one.
274
275
:param right: the other simplicial complex (the right-hand factor)
276
277
Wedges are not implemented for general cell complexes.
278
279
EXAMPLES::
280
281
sage: from sage.homology.cell_complex import GenericCellComplex
282
sage: A = GenericCellComplex(); B = GenericCellComplex()
283
sage: A.wedge(B)
284
Traceback (most recent call last):
285
...
286
NotImplementedError
287
"""
288
raise NotImplementedError
289
290
############################################################
291
# self.join() and related methods
292
############################################################
293
294
def join(self, right, **kwds):
295
"""
296
The join of this cell complex with another one.
297
298
:param right: the other simplicial complex (the right-hand factor)
299
300
Joins are not implemented for general cell complexes. They
301
may be implemented in some derived classes (like simplicial
302
complexes).
303
304
EXAMPLES::
305
306
sage: from sage.homology.cell_complex import GenericCellComplex
307
sage: A = GenericCellComplex(); B = GenericCellComplex()
308
sage: A.join(B)
309
Traceback (most recent call last):
310
...
311
NotImplementedError
312
"""
313
raise NotImplementedError
314
315
# for some classes, you may want * to mean join:
316
###
317
# __mul__ = join
318
319
# the cone on X is the join of X with a point. See
320
# simplicial_complex.py for one implementation.
321
###
322
# def cone(self):
323
# return self.join(POINT)
324
325
# the suspension of X is the join of X with the 0-sphere (two
326
# points). See simplicial_complex.py for one implementation.
327
###
328
# def suspension(self, n=1):
329
# """
330
# The suspension of this cell complex.
331
#
332
# INPUT:
333
#
334
# - ``n`` - positive integer (optional, default 1): suspend this
335
# many times.
336
# """
337
# raise NotImplementedError
338
339
############################################################
340
# end of methods using self.join()
341
############################################################
342
343
############################################################
344
# chain complexes, homology
345
############################################################
346
347
def chain_complex(self, **kwds):
348
"""
349
This is not implemented for general cell complexes.
350
351
Some keywords to possibly implement in a derived class:
352
353
- ``subcomplex`` -- a subcomplex: compute the relative chain complex
354
- ``augmented`` -- a bool: whether to return the augmented complex
355
- ``verbose`` -- a bool: whether to print informational messages as
356
the chain complex is being computed
357
- ``check_diffs`` -- a bool: whether to check that the each
358
composite of two consecutive differentials is zero
359
- ``dimensions`` -- if ``None``, compute the chain complex in all
360
dimensions. If a list or tuple of integers, compute the
361
chain complex in those dimensions, setting the chain groups
362
in all other dimensions to zero.
363
364
Definitely implement the following:
365
366
- ``base_ring`` -- commutative ring (optional, default ZZ)
367
- ``cochain`` -- a bool: whether to return the cochain complex
368
369
EXAMPLES::
370
371
sage: from sage.homology.cell_complex import GenericCellComplex
372
sage: A = GenericCellComplex()
373
sage: A.chain_complex()
374
Traceback (most recent call last):
375
...
376
NotImplementedError
377
"""
378
raise NotImplementedError
379
380
def homology(self, dim=None, **kwds):
381
r"""
382
The reduced homology of this cell complex.
383
384
:param dim: If None, then return the homology in every
385
dimension. If ``dim`` is an integer or list, return the
386
homology in the given dimensions. (Actually, if ``dim`` is
387
a list, return the homology in the range from ``min(dim)``
388
to ``max(dim)``.)
389
:type dim: integer or list of integers or None; optional,
390
default None
391
:param base_ring: commutative ring, must be ZZ or a field.
392
:type base_ring: optional, default ZZ
393
:param subcomplex: a subcomplex of this simplicial complex.
394
Compute homology relative to this subcomplex.
395
:type subcomplex: optional, default empty
396
:param generators: If ``True``, return generators for the homology
397
groups along with the groups. NOTE: Since :trac:`6100`, the result
398
may not be what you expect when not using CHomP since its return
399
is in terms of the chain complex.
400
:type generators: boolean; optional, default False
401
:param cohomology: If True, compute cohomology rather than homology.
402
:type cohomology: boolean; optional, default False
403
:param algorithm: The options are 'auto', 'dhsw', 'pari' or 'no_chomp'.
404
See below for a description of what they mean.
405
:type algorithm: string; optional, default 'auto'
406
:param verbose: If True, print some messages as the homology is
407
computed.
408
:type verbose: boolean; optional, default False
409
410
.. note::
411
412
The keyword arguments to this function get passed on to
413
:meth:``chain_complex`` and its homology.
414
415
ALGORITHM:
416
417
If ``algorithm`` is set to 'auto' (the default), then use
418
CHomP if available. (CHomP is available at the web page
419
http://chomp.rutgers.edu/. It is also an experimental package
420
for Sage.)
421
422
CHomP computes homology, not cohomology, and only works over
423
the integers or finite prime fields. Therefore if any of
424
these conditions fails, or if CHomP is not present, or if
425
``algorithm`` is set to 'no_chomp', go to plan B: if ``self``
426
has a ``_homology`` method -- each simplicial complex has
427
this, for example -- then call that. Such a method implements
428
specialized algorithms for the particular type of cell
429
complex.
430
431
Otherwise, move on to plan C: compute the chain complex of
432
``self`` and compute its homology groups. To do this: over a
433
field, just compute ranks and nullities, thus obtaining
434
dimensions of the homology groups as vector spaces. Over the
435
integers, compute Smith normal form of the boundary matrices
436
defining the chain complex according to the value of
437
``algorithm``. If ``algorithm`` is 'auto' or 'no_chomp', then
438
for each relatively small matrix, use the standard Sage
439
method, which calls the Pari package. For any large matrix,
440
reduce it using the Dumas, Heckenbach, Saunders, and Welker
441
elimination algorithm: see
442
:func:`sage.homology.matrix_utils.dhsw_snf` for details.
443
444
Finally, ``algorithm`` may also be 'pari' or 'dhsw', which
445
forces the named algorithm to be used regardless of the size
446
of the matrices and regardless of whether CHomP is available.
447
448
As of this writing, CHomP is by far the fastest option,
449
followed by the 'auto' or 'no_chomp' setting of using the
450
Dumas, Heckenbach, Saunders, and Welker elimination algorithm
451
for large matrices and Pari for small ones.
452
453
EXAMPLES::
454
455
sage: P = delta_complexes.RealProjectivePlane()
456
sage: P.homology()
457
{0: 0, 1: C2, 2: 0}
458
sage: P.homology(base_ring=GF(2))
459
{0: Vector space of dimension 0 over Finite Field of size 2,
460
1: Vector space of dimension 1 over Finite Field of size 2,
461
2: Vector space of dimension 1 over Finite Field of size 2}
462
sage: S7 = delta_complexes.Sphere(7)
463
sage: S7.homology(7)
464
Z
465
sage: cubical_complexes.KleinBottle().homology(1, base_ring=GF(2))
466
Vector space of dimension 2 over Finite Field of size 2
467
468
If CHomP is installed, Sage can compute generators of homology
469
groups::
470
471
sage: S2 = simplicial_complexes.Sphere(2)
472
sage: S2.homology(dim=2, generators=True, base_ring=GF(2)) # optional - CHomP
473
(Vector space of dimension 1 over Finite Field of size 2, [(0, 1, 2) + (0, 1, 3) + (0, 2, 3) + (1, 2, 3)])
474
475
When generators are computed, Sage returns a pair for each
476
dimension: the group and the list of generators. For
477
simplicial complexes, each generator is represented as a
478
linear combination of simplices, as above, and for cubical
479
complexes, each generator is a linear combination of cubes::
480
481
sage: S2_cub = cubical_complexes.Sphere(2)
482
sage: S2_cub.homology(dim=2, generators=True) # optional - CHomP
483
(Z, [-[[0,1] x [0,1] x [0,0]] + [[0,1] x [0,1] x [1,1]] - [[0,0] x [0,1] x [0,1]] - [[0,1] x [1,1] x [0,1]] + [[0,1] x [0,0] x [0,1]] + [[1,1] x [0,1] x [0,1]]])
484
"""
485
from sage.interfaces.chomp import have_chomp, homcubes, homsimpl
486
from sage.homology.cubical_complex import CubicalComplex
487
from sage.homology.simplicial_complex import SimplicialComplex
488
from sage.modules.all import VectorSpace
489
from sage.homology.homology_group import HomologyGroup
490
491
base_ring = kwds.get('base_ring', ZZ)
492
cohomology = kwds.get('cohomology', False)
493
subcomplex = kwds.pop('subcomplex', None)
494
verbose = kwds.get('verbose', False)
495
algorithm = kwds.get('algorithm', 'auto')
496
497
if dim is not None:
498
if isinstance(dim, (list, tuple)):
499
low = min(dim) - 1
500
high = max(dim) + 2
501
else:
502
low = dim - 1
503
high = dim + 2
504
dims = range(low, high)
505
else:
506
dims = None
507
508
# try to use CHomP if computing homology (not cohomology) and
509
# working over Z or F_p, p a prime.
510
if (algorithm == 'auto' and cohomology is False
511
and (base_ring == ZZ or (base_ring.is_prime_field()
512
and base_ring != QQ))):
513
# homcubes, homsimpl seems fastest if all of homology is computed.
514
H = None
515
if isinstance(self, CubicalComplex):
516
if have_chomp('homcubes'):
517
H = homcubes(self, subcomplex, **kwds)
518
elif isinstance(self, SimplicialComplex):
519
if have_chomp('homsimpl'):
520
H = homsimpl(self, subcomplex, **kwds)
521
522
# now pick off the requested dimensions
523
if H:
524
answer = {}
525
if not dims:
526
dims =range(self.dimension() + 1)
527
for d in dims:
528
answer[d] = H.get(d, HomologyGroup(0, base_ring))
529
if dim is not None:
530
if not isinstance(dim, (list, tuple)):
531
answer = answer.get(dim, HomologyGroup(0, base_ring))
532
return answer
533
534
# Derived classes can implement specialized algorithms using a
535
# _homology_ method. See SimplicialComplex for one example.
536
if hasattr(self, '_homology_'):
537
return self._homology_(dim, subcomplex=subcomplex, **kwds)
538
539
C = self.chain_complex(cochain=cohomology, augmented=True,
540
dimensions=dims, subcomplex=subcomplex, **kwds)
541
answer = C.homology(**kwds)
542
if dim is None:
543
dim = range(self.dimension()+1)
544
zero = HomologyGroup(0, base_ring)
545
if isinstance(dim, (list, tuple)):
546
return dict([d, answer.get(d, zero)] for d in dim)
547
return answer.get(dim, zero)
548
549
def cohomology(self, dim=None, **kwds):
550
r"""
551
The reduced cohomology of this cell complex.
552
553
The arguments are the same as for the :meth:`homology` method,
554
except that :meth:`homology` accepts a ``cohomology`` key
555
word, while this function does not: ``cohomology`` is
556
automatically true here. Indeed, this function just calls
557
:meth:`homology` with ``cohomology`` set to ``True``.
558
559
:param dim:
560
:param base_ring:
561
:param subcomplex:
562
:param algorithm:
563
:param verbose:
564
565
EXAMPLES::
566
567
sage: circle = SimplicialComplex([[0,1], [1,2], [0, 2]])
568
sage: circle.cohomology(0)
569
0
570
sage: circle.cohomology(1)
571
Z
572
sage: P2 = SimplicialComplex([[0,1,2], [0,2,3], [0,1,5], [0,4,5], [0,3,4], [1,2,4], [1,3,4], [1,3,5], [2,3,5], [2,4,5]]) # projective plane
573
sage: P2.cohomology(2)
574
C2
575
sage: P2.cohomology(2, base_ring=GF(2))
576
Vector space of dimension 1 over Finite Field of size 2
577
sage: P2.cohomology(2, base_ring=GF(3))
578
Vector space of dimension 0 over Finite Field of size 3
579
580
sage: cubical_complexes.KleinBottle().cohomology(2)
581
C2
582
583
Relative cohomology::
584
585
sage: T = SimplicialComplex([[0,1]])
586
sage: U = SimplicialComplex([[0], [1]])
587
sage: T.cohomology(1, subcomplex=U)
588
Z
589
590
A `\Delta`-complex example::
591
592
sage: s5 = delta_complexes.Sphere(5)
593
sage: s5.cohomology(base_ring=GF(7))[5]
594
Vector space of dimension 1 over Finite Field of size 7
595
"""
596
return self.homology(dim=dim, cohomology=True, **kwds)
597
598
def betti(self, dim=None, subcomplex=None):
599
r"""
600
The Betti numbers of this simplicial complex as a dictionary
601
(or a single Betti number, if only one dimension is given):
602
the ith Betti number is the rank of the ith homology group.
603
604
:param dim: If ``None``, then return every Betti number, as
605
a dictionary with keys the non-negative integers. If
606
``dim`` is an integer or list, return the Betti number for
607
each given dimension. (Actually, if ``dim`` is a list,
608
return the Betti numbers, as a dictionary, in the range
609
from ``min(dim)`` to ``max(dim)``. If ``dim`` is a number,
610
return the Betti number in that dimension.)
611
:type dim: integer or list of integers or ``None``; optional,
612
default ``None``
613
:param subcomplex: a subcomplex of this cell complex. Compute
614
the Betti numbers of the homology relative to this subcomplex.
615
:type subcomplex: optional, default ``None``
616
617
EXAMPLES:
618
619
Build the two-sphere as a three-fold join of a
620
two-point space with itself::
621
622
sage: S = SimplicialComplex([[0], [1]])
623
sage: (S*S*S).betti()
624
{0: 1, 1: 0, 2: 1}
625
sage: (S*S*S).betti([1,2])
626
{1: 0, 2: 1}
627
sage: (S*S*S).betti(2)
628
1
629
630
Or build the two-sphere as a `\Delta`-complex::
631
632
sage: S2 = delta_complexes.Sphere(2)
633
sage: S2.betti([1,2])
634
{1: 0, 2: 1}
635
636
Or as a cubical complex::
637
638
sage: S2c = cubical_complexes.Sphere(2)
639
sage: S2c.betti(2)
640
1
641
"""
642
dict = {}
643
H = self.homology(dim, base_ring=QQ, subcomplex=subcomplex)
644
try:
645
for n in H.keys():
646
dict[n] = H[n].dimension()
647
if n == 0:
648
dict[n] += 1
649
return dict
650
except AttributeError:
651
return H.dimension()
652
653
############################################################
654
# end of chain complexes, homology
655
############################################################
656
657
def face_poset(self):
658
r"""
659
The face poset of this cell complex, the poset of
660
nonempty cells, ordered by inclusion.
661
662
This uses the :meth:`cells` method, and also assumes that for
663
each cell ``f``, all of ``f.faces()``, ``tuple(f)``, and
664
``f.dimension()`` make sense. (If this is not the case in
665
some derived class, as happens with `\Delta`-complexes, then
666
override this method.)
667
668
EXAMPLES::
669
670
sage: P = SimplicialComplex([[0, 1], [1,2], [2,3]]).face_poset(); P
671
Finite poset containing 7 elements
672
sage: P.list()
673
[(3,), (2,), (2, 3), (1,), (0,), (0, 1), (1, 2)]
674
675
sage: S2 = cubical_complexes.Sphere(2)
676
sage: S2.face_poset()
677
Finite poset containing 26 elements
678
"""
679
from sage.combinat.posets.posets import Poset
680
from sage.misc.flatten import flatten
681
covers = {}
682
# The code for posets seems to work better if each cell is
683
# converted to a tuple.
684
all_cells = flatten([list(f) for f in self.cells().values()])
685
686
for C in all_cells:
687
if C.dimension() >= 0:
688
covers[tuple(C)] = []
689
for C in all_cells:
690
for face in C.faces():
691
if face.dimension() >= 0:
692
covers[tuple(face)].append(tuple(C))
693
return Poset(covers)
694
695
def graph(self):
696
"""
697
The 1-skeleton of this cell complex, as a graph.
698
699
This is not implemented for general cell complexes.
700
701
EXAMPLES::
702
703
sage: from sage.homology.cell_complex import GenericCellComplex
704
sage: A = GenericCellComplex()
705
sage: A.graph()
706
Traceback (most recent call last):
707
...
708
NotImplementedError
709
"""
710
raise NotImplementedError
711
712
def n_skeleton(self, n):
713
"""
714
The `n`-skeleton of this cell complex: the cell
715
complex obtained by discarding all of the simplices in
716
dimensions larger than `n`.
717
718
:param n: non-negative integer
719
720
This is not implemented for general cell complexes.
721
722
EXAMPLES::
723
724
sage: from sage.homology.cell_complex import GenericCellComplex
725
sage: A = GenericCellComplex()
726
sage: A.n_skeleton(3)
727
Traceback (most recent call last):
728
...
729
NotImplementedError
730
"""
731
raise NotImplementedError
732
733
def category(self):
734
"""
735
Return the category to which this chain complex belongs: the
736
category of all cell complexes.
737
738
This is not implemented for general cell complexes.
739
740
EXAMPLES::
741
742
sage: from sage.homology.cell_complex import GenericCellComplex
743
sage: A = GenericCellComplex()
744
sage: A.category()
745
Traceback (most recent call last):
746
...
747
NotImplementedError
748
"""
749
raise NotImplementedError
750
751
def _string_constants(self):
752
"""
753
Tuple containing the name of the type of complex, and the
754
singular and plural of the name of the cells from which it is
755
built. This is used in constructing the string representation.
756
757
:return: tuple of strings
758
759
This returns ``('Cell', 'cell', 'cells')``, as in "Cell
760
complex", "1 cell", and "24 cells", but in other classes it
761
could be overridden, as for example with ``('Cubical', 'cube',
762
'cubes')`` or ``('Delta', 'simplex', 'simplices')``. If for a
763
derived class, the basic form of the print representation is
764
acceptable, you can just modify these strings.
765
766
EXAMPLES::
767
768
sage: from sage.homology.cell_complex import GenericCellComplex
769
sage: GenericCellComplex()._string_constants()
770
('Cell', 'cell', 'cells')
771
sage: delta_complexes.Sphere(0)._string_constants()
772
('Delta', 'simplex', 'simplices')
773
sage: cubical_complexes.Sphere(0)._string_constants()
774
('Cubical', 'cube', 'cubes')
775
"""
776
return ('Cell', 'cell', 'cells')
777
778
def _repr_(self):
779
"""
780
Print representation.
781
782
:return: string
783
784
EXAMPLES::
785
786
sage: delta_complexes.Sphere(7) # indirect doctest
787
Delta complex with 8 vertices and 257 simplices
788
sage: delta_complexes.Torus()._repr_()
789
'Delta complex with 1 vertex and 7 simplices'
790
"""
791
vertices = len(self.n_cells(0))
792
Name, cell_name, cells_name = self._string_constants()
793
if vertices != 1:
794
vertex_string = "with %s vertices" % vertices
795
else:
796
vertex_string = "with 1 vertex"
797
cells = 0
798
for dim in self.cells():
799
cells += len(self.cells()[dim])
800
if cells != 1:
801
cells_string = " and %s %s" % (cells, cells_name)
802
else:
803
cells_string = " and 1 %s" % cell_name
804
return Name + " complex " + vertex_string + cells_string
805
806