passagemath-graphs 10.5.43__cp39-cp39-musllinux_1_2_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. passagemath_graphs-10.5.43.dist-info/METADATA +293 -0
  2. passagemath_graphs-10.5.43.dist-info/RECORD +258 -0
  3. passagemath_graphs-10.5.43.dist-info/WHEEL +5 -0
  4. passagemath_graphs-10.5.43.dist-info/top_level.txt +2 -0
  5. passagemath_graphs.libs/libgcc_s-69c45f16.so.1 +0 -0
  6. passagemath_graphs.libs/libgmp-8e78bd9b.so.10.5.0 +0 -0
  7. passagemath_graphs.libs/libstdc++-1f1a71be.so.6.0.33 +0 -0
  8. sage/all__sagemath_graphs.py +39 -0
  9. sage/combinat/abstract_tree.py +2552 -0
  10. sage/combinat/all__sagemath_graphs.py +34 -0
  11. sage/combinat/binary_tree.py +5306 -0
  12. sage/combinat/cluster_algebra_quiver/all.py +22 -0
  13. sage/combinat/cluster_algebra_quiver/cluster_seed.py +5208 -0
  14. sage/combinat/cluster_algebra_quiver/interact.py +125 -0
  15. sage/combinat/cluster_algebra_quiver/mutation_class.py +625 -0
  16. sage/combinat/cluster_algebra_quiver/mutation_type.py +1556 -0
  17. sage/combinat/cluster_algebra_quiver/quiver.py +2262 -0
  18. sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py +2468 -0
  19. sage/combinat/designs/MOLS_handbook_data.py +570 -0
  20. sage/combinat/designs/all.py +58 -0
  21. sage/combinat/designs/bibd.py +1655 -0
  22. sage/combinat/designs/block_design.py +1071 -0
  23. sage/combinat/designs/covering_array.py +269 -0
  24. sage/combinat/designs/covering_design.py +534 -0
  25. sage/combinat/designs/database.py +5614 -0
  26. sage/combinat/designs/design_catalog.py +122 -0
  27. sage/combinat/designs/designs_pyx.cpython-39-aarch64-linux-gnu.so +0 -0
  28. sage/combinat/designs/designs_pyx.pxd +21 -0
  29. sage/combinat/designs/designs_pyx.pyx +993 -0
  30. sage/combinat/designs/difference_family.py +3951 -0
  31. sage/combinat/designs/difference_matrices.py +279 -0
  32. sage/combinat/designs/evenly_distributed_sets.cpython-39-aarch64-linux-gnu.so +0 -0
  33. sage/combinat/designs/evenly_distributed_sets.pyx +661 -0
  34. sage/combinat/designs/ext_rep.py +1064 -0
  35. sage/combinat/designs/gen_quadrangles_with_spread.cpython-39-aarch64-linux-gnu.so +0 -0
  36. sage/combinat/designs/gen_quadrangles_with_spread.pyx +339 -0
  37. sage/combinat/designs/group_divisible_designs.py +361 -0
  38. sage/combinat/designs/incidence_structures.py +2357 -0
  39. sage/combinat/designs/latin_squares.py +548 -0
  40. sage/combinat/designs/orthogonal_arrays.py +2243 -0
  41. sage/combinat/designs/orthogonal_arrays_build_recursive.py +1780 -0
  42. sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-39-aarch64-linux-gnu.so +0 -0
  43. sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +966 -0
  44. sage/combinat/designs/resolvable_bibd.py +781 -0
  45. sage/combinat/designs/steiner_quadruple_systems.py +1306 -0
  46. sage/combinat/designs/subhypergraph_search.cpython-39-aarch64-linux-gnu.so +0 -0
  47. sage/combinat/designs/subhypergraph_search.pyx +530 -0
  48. sage/combinat/designs/twographs.py +306 -0
  49. sage/combinat/finite_state_machine.py +14874 -0
  50. sage/combinat/finite_state_machine_generators.py +2006 -0
  51. sage/combinat/graph_path.py +448 -0
  52. sage/combinat/interval_posets.py +3908 -0
  53. sage/combinat/nu_tamari_lattice.py +269 -0
  54. sage/combinat/ordered_tree.py +1446 -0
  55. sage/combinat/posets/all.py +46 -0
  56. sage/combinat/posets/cartesian_product.py +493 -0
  57. sage/combinat/posets/d_complete.py +182 -0
  58. sage/combinat/posets/elements.py +273 -0
  59. sage/combinat/posets/forest.py +30 -0
  60. sage/combinat/posets/hasse_cython.cpython-39-aarch64-linux-gnu.so +0 -0
  61. sage/combinat/posets/hasse_cython.pyx +174 -0
  62. sage/combinat/posets/hasse_diagram.py +3678 -0
  63. sage/combinat/posets/incidence_algebras.py +796 -0
  64. sage/combinat/posets/lattices.py +5119 -0
  65. sage/combinat/posets/linear_extension_iterator.cpython-39-aarch64-linux-gnu.so +0 -0
  66. sage/combinat/posets/linear_extension_iterator.pyx +292 -0
  67. sage/combinat/posets/linear_extensions.py +1039 -0
  68. sage/combinat/posets/mobile.py +275 -0
  69. sage/combinat/posets/moebius_algebra.py +776 -0
  70. sage/combinat/posets/poset_examples.py +2131 -0
  71. sage/combinat/posets/posets.py +9169 -0
  72. sage/combinat/rooted_tree.py +1070 -0
  73. sage/combinat/shard_order.py +239 -0
  74. sage/combinat/tamari_lattices.py +384 -0
  75. sage/combinat/yang_baxter_graph.py +923 -0
  76. sage/databases/all__sagemath_graphs.py +1 -0
  77. sage/databases/knotinfo_db.py +1230 -0
  78. sage/ext_data/all__sagemath_graphs.py +1 -0
  79. sage/ext_data/graphs/graph_plot_js.html +330 -0
  80. sage/ext_data/kenzo/CP2.txt +45 -0
  81. sage/ext_data/kenzo/CP3.txt +349 -0
  82. sage/ext_data/kenzo/CP4.txt +4774 -0
  83. sage/ext_data/kenzo/README.txt +49 -0
  84. sage/ext_data/kenzo/S4.txt +20 -0
  85. sage/graphs/all.py +42 -0
  86. sage/graphs/asteroidal_triples.cpython-39-aarch64-linux-gnu.so +0 -0
  87. sage/graphs/asteroidal_triples.pyx +299 -0
  88. sage/graphs/base/all.py +1 -0
  89. sage/graphs/base/boost_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  90. sage/graphs/base/boost_graph.pxd +106 -0
  91. sage/graphs/base/boost_graph.pyx +3045 -0
  92. sage/graphs/base/c_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  93. sage/graphs/base/c_graph.pxd +106 -0
  94. sage/graphs/base/c_graph.pyx +5096 -0
  95. sage/graphs/base/dense_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  96. sage/graphs/base/dense_graph.pxd +26 -0
  97. sage/graphs/base/dense_graph.pyx +757 -0
  98. sage/graphs/base/graph_backends.cpython-39-aarch64-linux-gnu.so +0 -0
  99. sage/graphs/base/graph_backends.pxd +5 -0
  100. sage/graphs/base/graph_backends.pyx +797 -0
  101. sage/graphs/base/overview.py +85 -0
  102. sage/graphs/base/sparse_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  103. sage/graphs/base/sparse_graph.pxd +90 -0
  104. sage/graphs/base/sparse_graph.pyx +1653 -0
  105. sage/graphs/base/static_dense_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  106. sage/graphs/base/static_dense_graph.pxd +5 -0
  107. sage/graphs/base/static_dense_graph.pyx +1032 -0
  108. sage/graphs/base/static_sparse_backend.cpython-39-aarch64-linux-gnu.so +0 -0
  109. sage/graphs/base/static_sparse_backend.pxd +27 -0
  110. sage/graphs/base/static_sparse_backend.pyx +1580 -0
  111. sage/graphs/base/static_sparse_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  112. sage/graphs/base/static_sparse_graph.pxd +37 -0
  113. sage/graphs/base/static_sparse_graph.pyx +1304 -0
  114. sage/graphs/bipartite_graph.py +2709 -0
  115. sage/graphs/centrality.cpython-39-aarch64-linux-gnu.so +0 -0
  116. sage/graphs/centrality.pyx +965 -0
  117. sage/graphs/cographs.py +519 -0
  118. sage/graphs/comparability.cpython-39-aarch64-linux-gnu.so +0 -0
  119. sage/graphs/comparability.pyx +813 -0
  120. sage/graphs/connectivity.cpython-39-aarch64-linux-gnu.so +0 -0
  121. sage/graphs/connectivity.pxd +157 -0
  122. sage/graphs/connectivity.pyx +4813 -0
  123. sage/graphs/convexity_properties.cpython-39-aarch64-linux-gnu.so +0 -0
  124. sage/graphs/convexity_properties.pxd +16 -0
  125. sage/graphs/convexity_properties.pyx +827 -0
  126. sage/graphs/digraph.py +4410 -0
  127. sage/graphs/digraph_generators.py +1921 -0
  128. sage/graphs/distances_all_pairs.cpython-39-aarch64-linux-gnu.so +0 -0
  129. sage/graphs/distances_all_pairs.pxd +12 -0
  130. sage/graphs/distances_all_pairs.pyx +2938 -0
  131. sage/graphs/domination.py +1363 -0
  132. sage/graphs/dot2tex_utils.py +100 -0
  133. sage/graphs/edge_connectivity.cpython-39-aarch64-linux-gnu.so +0 -0
  134. sage/graphs/edge_connectivity.pyx +1215 -0
  135. sage/graphs/generators/all.py +1 -0
  136. sage/graphs/generators/basic.py +1769 -0
  137. sage/graphs/generators/chessboard.py +538 -0
  138. sage/graphs/generators/classical_geometries.py +1611 -0
  139. sage/graphs/generators/degree_sequence.py +235 -0
  140. sage/graphs/generators/distance_regular.cpython-39-aarch64-linux-gnu.so +0 -0
  141. sage/graphs/generators/distance_regular.pyx +2846 -0
  142. sage/graphs/generators/families.py +4749 -0
  143. sage/graphs/generators/intersection.py +565 -0
  144. sage/graphs/generators/platonic_solids.py +262 -0
  145. sage/graphs/generators/random.py +2623 -0
  146. sage/graphs/generators/smallgraphs.py +5741 -0
  147. sage/graphs/generators/world_map.py +724 -0
  148. sage/graphs/generic_graph.py +26395 -0
  149. sage/graphs/generic_graph_pyx.cpython-39-aarch64-linux-gnu.so +0 -0
  150. sage/graphs/generic_graph_pyx.pxd +34 -0
  151. sage/graphs/generic_graph_pyx.pyx +1626 -0
  152. sage/graphs/genus.cpython-39-aarch64-linux-gnu.so +0 -0
  153. sage/graphs/genus.pyx +623 -0
  154. sage/graphs/graph.py +9362 -0
  155. sage/graphs/graph_coloring.cpython-39-aarch64-linux-gnu.so +0 -0
  156. sage/graphs/graph_coloring.pyx +2284 -0
  157. sage/graphs/graph_database.py +1122 -0
  158. sage/graphs/graph_decompositions/all.py +1 -0
  159. sage/graphs/graph_decompositions/bandwidth.cpython-39-aarch64-linux-gnu.so +0 -0
  160. sage/graphs/graph_decompositions/bandwidth.pyx +428 -0
  161. sage/graphs/graph_decompositions/clique_separators.cpython-39-aarch64-linux-gnu.so +0 -0
  162. sage/graphs/graph_decompositions/clique_separators.pyx +595 -0
  163. sage/graphs/graph_decompositions/cutwidth.cpython-39-aarch64-linux-gnu.so +0 -0
  164. sage/graphs/graph_decompositions/cutwidth.pyx +753 -0
  165. sage/graphs/graph_decompositions/fast_digraph.cpython-39-aarch64-linux-gnu.so +0 -0
  166. sage/graphs/graph_decompositions/fast_digraph.pxd +13 -0
  167. sage/graphs/graph_decompositions/fast_digraph.pyx +212 -0
  168. sage/graphs/graph_decompositions/graph_products.cpython-39-aarch64-linux-gnu.so +0 -0
  169. sage/graphs/graph_decompositions/graph_products.pyx +462 -0
  170. sage/graphs/graph_decompositions/modular_decomposition.cpython-39-aarch64-linux-gnu.so +0 -0
  171. sage/graphs/graph_decompositions/modular_decomposition.pxd +27 -0
  172. sage/graphs/graph_decompositions/modular_decomposition.pyx +1536 -0
  173. sage/graphs/graph_decompositions/slice_decomposition.cpython-39-aarch64-linux-gnu.so +0 -0
  174. sage/graphs/graph_decompositions/slice_decomposition.pxd +18 -0
  175. sage/graphs/graph_decompositions/slice_decomposition.pyx +1080 -0
  176. sage/graphs/graph_decompositions/tree_decomposition.cpython-39-aarch64-linux-gnu.so +0 -0
  177. sage/graphs/graph_decompositions/tree_decomposition.pxd +17 -0
  178. sage/graphs/graph_decompositions/tree_decomposition.pyx +1996 -0
  179. sage/graphs/graph_decompositions/vertex_separation.cpython-39-aarch64-linux-gnu.so +0 -0
  180. sage/graphs/graph_decompositions/vertex_separation.pxd +5 -0
  181. sage/graphs/graph_decompositions/vertex_separation.pyx +1963 -0
  182. sage/graphs/graph_editor.py +82 -0
  183. sage/graphs/graph_generators.py +3301 -0
  184. sage/graphs/graph_generators_pyx.cpython-39-aarch64-linux-gnu.so +0 -0
  185. sage/graphs/graph_generators_pyx.pyx +95 -0
  186. sage/graphs/graph_input.py +812 -0
  187. sage/graphs/graph_latex.py +2064 -0
  188. sage/graphs/graph_list.py +367 -0
  189. sage/graphs/graph_plot.py +1749 -0
  190. sage/graphs/graph_plot_js.py +338 -0
  191. sage/graphs/hyperbolicity.cpython-39-aarch64-linux-gnu.so +0 -0
  192. sage/graphs/hyperbolicity.pyx +1702 -0
  193. sage/graphs/hypergraph_generators.py +364 -0
  194. sage/graphs/independent_sets.cpython-39-aarch64-linux-gnu.so +0 -0
  195. sage/graphs/independent_sets.pxd +13 -0
  196. sage/graphs/independent_sets.pyx +402 -0
  197. sage/graphs/isgci.py +1033 -0
  198. sage/graphs/isoperimetric_inequalities.cpython-39-aarch64-linux-gnu.so +0 -0
  199. sage/graphs/isoperimetric_inequalities.pyx +453 -0
  200. sage/graphs/line_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  201. sage/graphs/line_graph.pyx +627 -0
  202. sage/graphs/lovasz_theta.py +77 -0
  203. sage/graphs/matching.py +1633 -0
  204. sage/graphs/matching_covered_graph.py +3566 -0
  205. sage/graphs/orientations.py +1504 -0
  206. sage/graphs/partial_cube.py +459 -0
  207. sage/graphs/path_enumeration.cpython-39-aarch64-linux-gnu.so +0 -0
  208. sage/graphs/path_enumeration.pyx +2040 -0
  209. sage/graphs/pq_trees.py +1129 -0
  210. sage/graphs/print_graphs.py +201 -0
  211. sage/graphs/schnyder.py +865 -0
  212. sage/graphs/spanning_tree.cpython-39-aarch64-linux-gnu.so +0 -0
  213. sage/graphs/spanning_tree.pyx +1457 -0
  214. sage/graphs/strongly_regular_db.cpython-39-aarch64-linux-gnu.so +0 -0
  215. sage/graphs/strongly_regular_db.pyx +3340 -0
  216. sage/graphs/traversals.cpython-39-aarch64-linux-gnu.so +0 -0
  217. sage/graphs/traversals.pxd +9 -0
  218. sage/graphs/traversals.pyx +1871 -0
  219. sage/graphs/trees.cpython-39-aarch64-linux-gnu.so +0 -0
  220. sage/graphs/trees.pxd +15 -0
  221. sage/graphs/trees.pyx +310 -0
  222. sage/graphs/tutte_polynomial.py +713 -0
  223. sage/graphs/views.cpython-39-aarch64-linux-gnu.so +0 -0
  224. sage/graphs/views.pyx +794 -0
  225. sage/graphs/weakly_chordal.cpython-39-aarch64-linux-gnu.so +0 -0
  226. sage/graphs/weakly_chordal.pyx +562 -0
  227. sage/groups/all__sagemath_graphs.py +1 -0
  228. sage/groups/perm_gps/all__sagemath_graphs.py +1 -0
  229. sage/groups/perm_gps/partn_ref/all__sagemath_graphs.py +1 -0
  230. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-39-aarch64-linux-gnu.so +0 -0
  231. sage/groups/perm_gps/partn_ref/refinement_graphs.pxd +38 -0
  232. sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +1666 -0
  233. sage/knots/all.py +6 -0
  234. sage/knots/free_knotinfo_monoid.py +507 -0
  235. sage/knots/gauss_code.py +291 -0
  236. sage/knots/knot.py +682 -0
  237. sage/knots/knot_table.py +284 -0
  238. sage/knots/knotinfo.py +2880 -0
  239. sage/knots/link.py +4682 -0
  240. sage/sandpiles/all.py +13 -0
  241. sage/sandpiles/examples.py +225 -0
  242. sage/sandpiles/sandpile.py +6365 -0
  243. sage/topology/all.py +22 -0
  244. sage/topology/cell_complex.py +1214 -0
  245. sage/topology/cubical_complex.py +1977 -0
  246. sage/topology/delta_complex.py +1806 -0
  247. sage/topology/filtered_simplicial_complex.py +744 -0
  248. sage/topology/moment_angle_complex.py +823 -0
  249. sage/topology/simplicial_complex.py +5161 -0
  250. sage/topology/simplicial_complex_catalog.py +86 -0
  251. sage/topology/simplicial_complex_examples.py +1692 -0
  252. sage/topology/simplicial_complex_homset.py +205 -0
  253. sage/topology/simplicial_complex_morphism.py +836 -0
  254. sage/topology/simplicial_set.py +4102 -0
  255. sage/topology/simplicial_set_catalog.py +55 -0
  256. sage/topology/simplicial_set_constructions.py +2954 -0
  257. sage/topology/simplicial_set_examples.py +865 -0
  258. sage/topology/simplicial_set_morphism.py +1464 -0
@@ -0,0 +1,1692 @@
1
+ # sage_setup: distribution = sagemath-graphs
2
+ # sage.doctest: needs sage.graphs
3
+ """
4
+ Examples of simplicial complexes
5
+
6
+ There are two main types: manifolds and examples related to graph
7
+ theory.
8
+
9
+ For manifolds, there are functions defining the `n`-sphere for any
10
+ `n`, the torus, `n`-dimensional real projective space for any `n`, the
11
+ complex projective plane, surfaces of arbitrary genus, and some other
12
+ manifolds, all as simplicial complexes.
13
+
14
+ Aside from surfaces, this file also provides functions for
15
+ constructing some other simplicial complexes: the simplicial complex
16
+ of not-`i`-connected graphs on `n` vertices, the matching complex on n
17
+ vertices, the chessboard complex for an `n` by `i` chessboard, and
18
+ others. These provide examples of large simplicial complexes; for
19
+ example, ``simplicial_complexes.NotIConnectedGraphs(7, 2)`` has over a
20
+ million simplices.
21
+
22
+ All of these examples are accessible by typing
23
+ ``simplicial_complexes.NAME``, where ``NAME`` is the name of the example.
24
+
25
+ - :func:`BarnetteSphere`
26
+ - :func:`BrucknerGrunbaumSphere`
27
+ - :func:`ChessboardComplex`
28
+ - :func:`ComplexProjectivePlane`
29
+ - :func:`DunceHat`
30
+ - :func:`FareyMap`
31
+ - :func:`GenusSix`
32
+ - :func:`K3Surface`
33
+ - :func:`KleinBottle`
34
+ - :func:`MatchingComplex`
35
+ - :func:`MooreSpace`
36
+ - :func:`NotIConnectedGraphs`
37
+ - :func:`PoincareHomologyThreeSphere`
38
+ - :func:`QuaternionicProjectivePlane`
39
+ - :func:`RandomComplex`
40
+ - :func:`RandomTwoSphere`
41
+ - :func:`RealProjectivePlane`
42
+ - :func:`RealProjectiveSpace`
43
+ - :func:`RudinBall`
44
+ - :func:`ShiftedComplex`
45
+ - :func:`Simplex`
46
+ - :func:`Sphere`
47
+ - :func:`SumComplex`
48
+ - :func:`SurfaceOfGenus`
49
+ - :func:`Torus`
50
+ - :func:`ZieglerBall`
51
+
52
+ You can also get a list by typing ``simplicial_complexes.`` and hitting the
53
+ :kbd:`Tab` key.
54
+
55
+ EXAMPLES::
56
+
57
+ sage: S = simplicial_complexes.Sphere(2) # the 2-sphere
58
+ sage: S.homology() # needs sage.modules
59
+ {0: 0, 1: 0, 2: Z}
60
+ sage: simplicial_complexes.SurfaceOfGenus(3)
61
+ Triangulation of an orientable surface of genus 3
62
+ sage: M4 = simplicial_complexes.MooreSpace(4)
63
+ sage: M4.homology() # needs sage.modules
64
+ {0: 0, 1: C4, 2: 0}
65
+ sage: simplicial_complexes.MatchingComplex(6).homology() # needs sage.modules
66
+ {0: 0, 1: Z^16, 2: 0}
67
+
68
+ TESTS::
69
+
70
+ sage: from sage.topology.simplicial_complex_examples import PseudoQuaternionicProjectivePlane
71
+ sage: H = PseudoQuaternionicProjectivePlane() # needs sage.groups
72
+ doctest:warning...:
73
+ DeprecationWarning: PseudoQuaternionicProjectivePlane is deprecated.
74
+ Please use sage.topology.simplicial_complex_examples.QuaternionicProjectivePlane instead.
75
+ See https://github.com/sagemath/sage/issues/34568 for details.
76
+ """
77
+
78
+ from .simplicial_complex import SimplicialComplex
79
+ from sage.structure.unique_representation import UniqueRepresentation
80
+ # Below we define a function Simplex to construct a simplex as a
81
+ # simplicial complex. We also need to use actual simplices as
82
+ # simplices, hence:
83
+ from .simplicial_complex import Simplex as TrueSimplex
84
+ from sage.sets.set import Set
85
+ from sage.misc.functional import is_even
86
+ from sage.combinat.subset import Subsets
87
+ import sage.misc.prandom as random
88
+ from sage.misc.superseded import deprecated_function_alias
89
+
90
+ # Miscellaneous utility functions.
91
+
92
+ # The following two functions can be used to generate the facets for
93
+ # the corresponding examples in sage.homology.examples. These take a
94
+ # few seconds to run, so the actual examples have the facets
95
+ # hard-coded. Thus the following functions are not currently used in
96
+ # the Sage library.
97
+
98
+
99
+ def facets_for_RP4():
100
+ """
101
+ Return the list of facets for a minimal triangulation of 4-dimensional
102
+ real projective space.
103
+
104
+ We use vertices numbered 1 through 16, define two facets, and define
105
+ a certain subgroup `G` of the symmetric group `S_{16}`. Then the set
106
+ of all facets is the `G`-orbit of the two given facets.
107
+
108
+ See the description in Example 3.12 in Datta [Dat2007]_.
109
+
110
+ EXAMPLES::
111
+
112
+ sage: from sage.topology.simplicial_complex_examples import facets_for_RP4
113
+ sage: A = facets_for_RP4() # long time (1 or 2 seconds)
114
+ sage: SimplicialComplex(A) == simplicial_complexes.RealProjectiveSpace(4) # long time
115
+ True
116
+ """
117
+ # Define the group:
118
+ from sage.groups.perm_gps.permgroup import PermutationGroup
119
+ g1 = '(2, 7)(4, 10)(5, 6)(11, 12)'
120
+ g2 = '(1, 2, 3, 4, 5, 10)(6, 8, 9)(11, 12, 13, 14, 15, 16)'
121
+ G = PermutationGroup([g1, g2])
122
+ # Define the two simplices:
123
+ t1 = (1, 2, 4, 5, 11)
124
+ t2 = (1, 2, 4, 11, 13)
125
+ # Apply the group elements to the simplices:
126
+ facets = []
127
+ for g in G:
128
+ d = g.dict()
129
+ for t in [t1, t2]:
130
+ new = tuple([d[j] for j in t])
131
+ if new not in facets:
132
+ facets.append(new)
133
+ return facets
134
+
135
+
136
+ def facets_for_K3():
137
+ """
138
+ Return the facets for a minimal triangulation of the K3 surface.
139
+
140
+ This is a pure simplicial complex of dimension 4 with 16
141
+ vertices and 288 facets. The facets are obtained by constructing a
142
+ few facets and a permutation group `G`, and then computing the
143
+ `G`-orbit of those facets.
144
+
145
+ See Casella and Kühnel in [CK2001]_ and Spreer and Kühnel [SK2011]_;
146
+ the construction here uses the labeling from Spreer and Kühnel.
147
+
148
+ EXAMPLES::
149
+
150
+ sage: from sage.topology.simplicial_complex_examples import facets_for_K3
151
+ sage: A = facets_for_K3() # long time (a few seconds)
152
+ sage: SimplicialComplex(A) == simplicial_complexes.K3Surface() # long time
153
+ True
154
+ """
155
+ from sage.groups.perm_gps.permgroup import PermutationGroup
156
+ G = PermutationGroup([[(1, 3, 8, 4, 9, 16, 15, 2, 14, 12, 6, 7, 13, 5, 10)],
157
+ [(1, 11, 16), (2, 10, 14), (3, 12, 13), (4, 9, 15), (5, 7, 8)]])
158
+ return ([tuple([g(i) for i in (1, 2, 3, 8, 12)]) for g in G] +
159
+ [tuple([g(i) for i in (1, 2, 5, 8, 14)]) for g in G])
160
+
161
+
162
+ def matching(A, B):
163
+ r"""
164
+ List of maximal matchings between the sets ``A`` and ``B``.
165
+
166
+ A matching is a set of pairs `(a, b) \in A \times B` where each `a` and
167
+ `b` appears in at most one pair. A maximal matching is one which is
168
+ maximal with respect to inclusion of subsets of `A \times B`.
169
+
170
+ INPUT:
171
+
172
+ - ``A``, ``B`` -- list, tuple, or indeed anything which can be
173
+ converted to a set
174
+
175
+ EXAMPLES::
176
+
177
+ sage: from sage.topology.simplicial_complex_examples import matching
178
+ sage: matching([1, 2], [3, 4])
179
+ [{(1, 3), (2, 4)}, {(1, 4), (2, 3)}]
180
+ sage: matching([0, 2], [0])
181
+ [{(0, 0)}, {(2, 0)}]
182
+ """
183
+ answer = []
184
+ if len(A) == 0 or len(B) == 0:
185
+ return [set()]
186
+ for v in A:
187
+ for w in B:
188
+ for M in matching(set(A).difference([v]), set(B).difference([w])):
189
+ new = M.union([(v, w)])
190
+ if new not in answer:
191
+ answer.append(new)
192
+ return answer
193
+
194
+
195
+ class UniqueSimplicialComplex(SimplicialComplex, UniqueRepresentation):
196
+ """
197
+ This combines :class:`SimplicialComplex` and
198
+ :class:`UniqueRepresentation`. It is intended to be used to make
199
+ standard examples of simplicial complexes unique. See :issue:`13566`.
200
+
201
+ INPUT:
202
+
203
+ - the inputs are the same as for a :class:`SimplicialComplex`,
204
+ with one addition and two exceptions. The exceptions are that
205
+ ``is_mutable`` and ``is_immutable`` are ignored: all instances
206
+ of this class are immutable. The addition:
207
+
208
+ - ``name`` -- string (optional); the string representation for this complex
209
+
210
+ EXAMPLES::
211
+
212
+ sage: from sage.topology.simplicial_complex_examples import UniqueSimplicialComplex
213
+ sage: SimplicialComplex([[0, 1]]) is SimplicialComplex([[0, 1]])
214
+ False
215
+ sage: UniqueSimplicialComplex([[0, 1]]) is UniqueSimplicialComplex([[0, 1]])
216
+ True
217
+ sage: UniqueSimplicialComplex([[0, 1]])
218
+ Simplicial complex with vertex set (0, 1) and facets {(0, 1)}
219
+ sage: UniqueSimplicialComplex([[0, 1]], name='The 1-simplex')
220
+ The 1-simplex
221
+ """
222
+ @staticmethod
223
+ def __classcall__(self, maximal_faces=None, name=None, **kwds):
224
+ """
225
+ TESTS::
226
+
227
+ sage: from sage.topology.simplicial_complex_examples import UniqueSimplicialComplex
228
+ sage: UniqueSimplicialComplex([[1, 2, 3], [0, 1, 3]]) is UniqueSimplicialComplex([(1, 2, 3), (0, 1, 3)])
229
+ True
230
+ sage: X = UniqueSimplicialComplex([[1, 2, 3], [0, 1, 3]])
231
+ sage: X is UniqueSimplicialComplex(X)
232
+ True
233
+
234
+ Testing ``from_characteristic_function``::
235
+
236
+ sage: UniqueSimplicialComplex(from_characteristic_function=(lambda x: sum(x) <= 4, range(5)))
237
+ Simplicial complex with vertex set (0, 1, 2, 3, 4) and facets {(0, 4), (0, 1, 2), (0, 1, 3)}
238
+ """
239
+ char_fcn = kwds.get('from_characteristic_function', None)
240
+ if char_fcn:
241
+ kwds['from_characteristic_function'] = (char_fcn[0], tuple(char_fcn[1]))
242
+ if maximal_faces:
243
+ # Test to see if maximal_faces is a cell complex or another
244
+ # object which can be converted to a simplicial complex:
245
+ C = None
246
+ if isinstance(maximal_faces, SimplicialComplex):
247
+ C = maximal_faces
248
+ else:
249
+ try:
250
+ C = maximal_faces._simplicial_()
251
+ except AttributeError:
252
+ if not isinstance(maximal_faces, (list, tuple, Simplex)):
253
+ # Convert it into a list (in case it is an iterable)
254
+ maximal_faces = list(maximal_faces)
255
+ if C is not None:
256
+ maximal_faces = C.facets()
257
+ # Now convert maximal_faces to a tuple of tuples, so that it is hashable.
258
+ maximal_faces = tuple(tuple(mf) for mf in maximal_faces)
259
+ return super().__classcall__(self, maximal_faces, name=name, **kwds)
260
+
261
+ def __init__(self, maximal_faces=None, name=None, **kwds):
262
+ """
263
+ TESTS::
264
+
265
+ sage: from sage.topology.simplicial_complex_examples import UniqueSimplicialComplex
266
+ sage: UniqueSimplicialComplex([[1, 2, 3], [0, 1, 3]], is_mutable=True).is_mutable()
267
+ False
268
+ """
269
+ if 'is_mutable' in kwds:
270
+ del kwds['is_mutable']
271
+ if 'is_immutable' in kwds:
272
+ del kwds['is_immutable']
273
+ self._name = name
274
+ SimplicialComplex.__init__(self, maximal_faces=maximal_faces, is_mutable=False, **kwds)
275
+
276
+ def _repr_(self):
277
+ """
278
+ Print representation.
279
+
280
+ If the argument ``name`` was specified when defining the
281
+ complex, use that. Otherwise, use the print representation
282
+ from the class :class:`SimplicialComplex`.
283
+
284
+ TESTS::
285
+
286
+ sage: from sage.topology.simplicial_complex_examples import UniqueSimplicialComplex
287
+ sage: UniqueSimplicialComplex([[0, 1]])
288
+ Simplicial complex with vertex set (0, 1) and facets {(0, 1)}
289
+ sage: UniqueSimplicialComplex([[0, 1]], name='Joe')
290
+ Joe
291
+ """
292
+ if self._name:
293
+ return self._name
294
+ return SimplicialComplex._repr_(self)
295
+
296
+ # Now the functions that produce the actual examples...
297
+
298
+
299
+ def Sphere(n):
300
+ """
301
+ A minimal triangulation of the `n`-dimensional sphere.
302
+
303
+ INPUT:
304
+
305
+ - ``n`` -- positive integer
306
+
307
+ EXAMPLES::
308
+
309
+ sage: simplicial_complexes.Sphere(2)
310
+ Minimal triangulation of the 2-sphere
311
+ sage: simplicial_complexes.Sphere(5).homology() # needs sage.modules
312
+ {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: Z}
313
+ sage: [simplicial_complexes.Sphere(n).euler_characteristic() for n in range(6)]
314
+ [2, 0, 2, 0, 2, 0]
315
+ sage: [simplicial_complexes.Sphere(n).f_vector() for n in range(6)]
316
+ [[1, 2],
317
+ [1, 3, 3],
318
+ [1, 4, 6, 4],
319
+ [1, 5, 10, 10, 5],
320
+ [1, 6, 15, 20, 15, 6],
321
+ [1, 7, 21, 35, 35, 21, 7]]
322
+ """
323
+ S = TrueSimplex(n+1)
324
+ facets = tuple(S.faces())
325
+ return UniqueSimplicialComplex(facets,
326
+ name='Minimal triangulation of the {}-sphere'.format(n))
327
+
328
+
329
+ def Simplex(n):
330
+ """
331
+ An `n`-dimensional simplex, as a simplicial complex.
332
+
333
+ INPUT:
334
+
335
+ - ``n`` -- nonnegative integer
336
+
337
+ OUTPUT: the simplicial complex consisting of the `n`-simplex
338
+ on vertices `(0, 1, ..., n)` and all of its faces.
339
+
340
+ EXAMPLES::
341
+
342
+ sage: simplicial_complexes.Simplex(3)
343
+ The 3-simplex
344
+ sage: simplicial_complexes.Simplex(5).euler_characteristic()
345
+ 1
346
+ """
347
+ return UniqueSimplicialComplex([TrueSimplex(n)],
348
+ name='The {}-simplex'.format(n))
349
+
350
+
351
+ def Torus():
352
+ r"""
353
+ A minimal triangulation of the torus.
354
+
355
+ This is a simplicial complex with 7 vertices, 21 edges and 14
356
+ faces. It is the unique triangulation of the torus with 7
357
+ vertices, and has been found by Möbius in 1861.
358
+
359
+ This is also the combinatorial structure of the Császár
360
+ polyhedron (see :wikipedia:`Császár_polyhedron`).
361
+
362
+ EXAMPLES::
363
+
364
+ sage: T = simplicial_complexes.Torus()
365
+ sage: T.homology(1) # needs sage.modules
366
+ Z x Z
367
+ sage: T.f_vector()
368
+ [1, 7, 21, 14]
369
+
370
+ TESTS::
371
+
372
+ sage: T.flip_graph().is_isomorphic(graphs.HeawoodGraph())
373
+ True
374
+
375
+ REFERENCES:
376
+
377
+ - [Lut2002]_
378
+ """
379
+ return UniqueSimplicialComplex([[0, 1, 2], [1, 2, 4], [1, 3, 4], [1, 3, 6],
380
+ [0, 1, 5], [1, 5, 6], [2, 3, 5], [2, 4, 5],
381
+ [2, 3, 6], [0, 2, 6], [0, 3, 4], [0, 3, 5],
382
+ [4, 5, 6], [0, 4, 6]],
383
+ name='Minimal triangulation of the torus')
384
+
385
+
386
+ def RealProjectivePlane():
387
+ """
388
+ A minimal triangulation of the real projective plane.
389
+
390
+ EXAMPLES::
391
+
392
+ sage: P = simplicial_complexes.RealProjectivePlane()
393
+ sage: Q = simplicial_complexes.ProjectivePlane()
394
+ sage: P == Q
395
+ True
396
+
397
+ sage: # needs sage.modules
398
+ sage: P.cohomology(1)
399
+ 0
400
+ sage: P.cohomology(2)
401
+ C2
402
+ sage: P.cohomology(1, base_ring=GF(2))
403
+ Vector space of dimension 1 over Finite Field of size 2
404
+ sage: P.cohomology(2, base_ring=GF(2))
405
+ Vector space of dimension 1 over Finite Field of size 2
406
+ """
407
+ return UniqueSimplicialComplex([[0, 1, 2], [0, 2, 3], [0, 1, 5], [0, 4, 5],
408
+ [0, 3, 4], [1, 2, 4], [1, 3, 4], [1, 3, 5],
409
+ [2, 3, 5], [2, 4, 5]],
410
+ name='Minimal triangulation of the real projective plane')
411
+
412
+
413
+ ProjectivePlane = RealProjectivePlane
414
+
415
+
416
+ def KleinBottle():
417
+ """
418
+ A minimal triangulation of the Klein bottle, as presented for example
419
+ in Davide Cervone's thesis [Cer1994]_.
420
+
421
+ EXAMPLES::
422
+
423
+ sage: simplicial_complexes.KleinBottle()
424
+ Minimal triangulation of the Klein bottle
425
+ """
426
+ return UniqueSimplicialComplex([[2, 3, 7], [1, 2, 3], [1, 3, 5], [1, 5, 7],
427
+ [1, 4, 7], [2, 4, 6], [1, 2, 6], [1, 6, 0],
428
+ [1, 4, 0], [2, 4, 0], [3, 4, 7], [3, 4, 6],
429
+ [3, 5, 6], [5, 6, 0], [2, 5, 0], [2, 5, 7]],
430
+ name='Minimal triangulation of the Klein bottle')
431
+
432
+
433
+ def SurfaceOfGenus(g, orientable=True):
434
+ """
435
+ A surface of genus `g`.
436
+
437
+ INPUT:
438
+
439
+ - ``g`` -- nonnegative integer; the desired genus
440
+
441
+ - ``orientable`` -- boolean (default: ``True``); if
442
+ ``True``, return an orientable surface, and if ``False``,
443
+ return a non-orientable surface.
444
+
445
+ In the orientable case, return a sphere if `g` is zero, and
446
+ otherwise return a `g`-fold connected sum of a torus with itself.
447
+
448
+ In the non-orientable case, raise an error if `g` is zero. If
449
+ `g` is positive, return a `g`-fold connected sum of a
450
+ real projective plane with itself.
451
+
452
+ EXAMPLES::
453
+
454
+ sage: simplicial_complexes.SurfaceOfGenus(2)
455
+ Triangulation of an orientable surface of genus 2
456
+ sage: simplicial_complexes.SurfaceOfGenus(1, orientable=False)
457
+ Triangulation of a non-orientable surface of genus 1
458
+ """
459
+ if g == 0:
460
+ if not orientable:
461
+ raise ValueError("no non-orientable surface of genus zero")
462
+ else:
463
+ return Sphere(2)
464
+ if orientable:
465
+ T = Torus()
466
+ else:
467
+ T = RealProjectivePlane()
468
+ S = T
469
+ for i in range(g-1):
470
+ S = S.connected_sum(T)
471
+ if orientable:
472
+ name_str = 'Triangulation of an orientable surface of genus {}'
473
+ else:
474
+ name_str = 'Triangulation of a non-orientable surface of genus {}'
475
+
476
+ return UniqueSimplicialComplex(S, name=name_str.format(g))
477
+
478
+
479
+ def MooreSpace(q):
480
+ r"""
481
+ Triangulation of the mod `q` Moore space.
482
+
483
+ INPUT:
484
+
485
+ - ``q`` -- integer; at least 2
486
+
487
+ This is a simplicial complex with simplices of dimension 0, 1,
488
+ and 2, such that its reduced homology is isomorphic to
489
+ `\\ZZ/q\\ZZ` in dimension 1, zero otherwise.
490
+
491
+ If `q=2`, this is the real projective plane. If `q>2`, then
492
+ construct it as follows: start with a triangle with vertices
493
+ 1, 2, 3. We take a `3q`-gon forming a `q`-fold cover of the
494
+ triangle, and we form the resulting complex as an
495
+ identification space of the `3q`-gon. To triangulate this
496
+ identification space, put `q` vertices `A_0`, ..., `A_{q-1}`,
497
+ in the interior, each of which is connected to 1, 2, 3 (two
498
+ facets each: `[1, 2, A_i]`, `[2, 3, A_i]`). Put `q` more
499
+ vertices in the interior: `B_0`, ..., `B_{q-1}`, with facets
500
+ `[3, 1, B_i]`, `[3, B_i, A_i]`, `[1, B_i, A_{i+1}]`, `[B_i,
501
+ A_i, A_{i+1}]`. Then triangulate the interior polygon with
502
+ vertices `A_0`, `A_1`, ..., `A_{q-1}`.
503
+
504
+ EXAMPLES::
505
+
506
+ sage: simplicial_complexes.MooreSpace(2)
507
+ Minimal triangulation of the real projective plane
508
+ sage: simplicial_complexes.MooreSpace(3).homology()[1] # needs sage.modules
509
+ C3
510
+ sage: simplicial_complexes.MooreSpace(4).suspension().homology()[2] # needs sage.modules
511
+ C4
512
+ sage: simplicial_complexes.MooreSpace(8)
513
+ Triangulation of the mod 8 Moore space
514
+ """
515
+ if q <= 1:
516
+ raise ValueError("the mod q Moore space is only defined if q is at least 2")
517
+ if q == 2:
518
+ return RealProjectivePlane()
519
+ facets = []
520
+ for i in range(q):
521
+ Ai = "A" + str(i)
522
+ Aiplus = "A" + str((i+1) % q)
523
+ Bi = "B" + str(i)
524
+ facets.append([1, 2, Ai])
525
+ facets.append([2, 3, Ai])
526
+ facets.append([3, 1, Bi])
527
+ facets.append([3, Bi, Ai])
528
+ facets.append([1, Bi, Aiplus])
529
+ facets.append([Bi, Ai, Aiplus])
530
+ for i in range(1, q-1):
531
+ Ai = "A" + str(i)
532
+ Aiplus = "A" + str((i+1) % q)
533
+ facets.append(["A0", Ai, Aiplus])
534
+ return UniqueSimplicialComplex(facets,
535
+ name='Triangulation of the mod {} Moore space'.format(q))
536
+
537
+
538
+ def ComplexProjectivePlane():
539
+ """
540
+ A minimal triangulation of the complex projective plane.
541
+
542
+ This was constructed by Kühnel and Banchoff [KB1983]_.
543
+
544
+ EXAMPLES::
545
+
546
+ sage: C = simplicial_complexes.ComplexProjectivePlane()
547
+ sage: C.f_vector()
548
+ [1, 9, 36, 84, 90, 36]
549
+ sage: C.homology(2) # needs sage.modules
550
+ Z
551
+ sage: C.homology(4) # needs sage.modules
552
+ Z
553
+ """
554
+ return UniqueSimplicialComplex(
555
+ [[1, 2, 4, 5, 6], [2, 3, 5, 6, 4], [3, 1, 6, 4, 5],
556
+ [1, 2, 4, 5, 9], [2, 3, 5, 6, 7], [3, 1, 6, 4, 8],
557
+ [2, 3, 6, 4, 9], [3, 1, 4, 5, 7], [1, 2, 5, 6, 8],
558
+ [3, 1, 5, 6, 9], [1, 2, 6, 4, 7], [2, 3, 4, 5, 8],
559
+ [4, 5, 7, 8, 9], [5, 6, 8, 9, 7], [6, 4, 9, 7, 8],
560
+ [4, 5, 7, 8, 3], [5, 6, 8, 9, 1], [6, 4, 9, 7, 2],
561
+ [5, 6, 9, 7, 3], [6, 4, 7, 8, 1], [4, 5, 8, 9, 2],
562
+ [6, 4, 8, 9, 3], [4, 5, 9, 7, 1], [5, 6, 7, 8, 2],
563
+ [7, 8, 1, 2, 3], [8, 9, 2, 3, 1], [9, 7, 3, 1, 2],
564
+ [7, 8, 1, 2, 6], [8, 9, 2, 3, 4], [9, 7, 3, 1, 5],
565
+ [8, 9, 3, 1, 6], [9, 7, 1, 2, 4], [7, 8, 2, 3, 5],
566
+ [9, 7, 2, 3, 6], [7, 8, 3, 1, 4], [8, 9, 1, 2, 5]],
567
+ name='Minimal triangulation of the complex projective plane')
568
+
569
+
570
+ def QuaternionicProjectivePlane():
571
+ r"""
572
+ Return a pure simplicial complex of dimension 8 with 490 facets.
573
+
574
+ .. WARNING::
575
+
576
+ This was proven to be a triangulation of the projective plane
577
+ `HP^2` over the ring of quaternions by Gorodkov in 2016 [Gor2016]_.
578
+
579
+ This simplicial complex has the same homology as `HP^2`. Its
580
+ automorphism group is isomorphic to the alternating group `A_5`
581
+ and acts transitively on vertices.
582
+
583
+ This is defined here using the description in [BK1992]_. This
584
+ article deals with three different triangulations. This procedure
585
+ returns the only one which has a transitive group of automorphisms.
586
+
587
+ EXAMPLES::
588
+
589
+ sage: HP2 = simplicial_complexes.QuaternionicProjectivePlane(); HP2 # needs sage.groups
590
+ Simplicial complex with 15 vertices and 490 facets
591
+ sage: HP2.f_vector() # needs sage.groups
592
+ [1, 15, 105, 455, 1365, 3003, 4515, 4230, 2205, 490]
593
+
594
+ Checking its automorphism group::
595
+
596
+ sage: HP2.automorphism_group().is_isomorphic(AlternatingGroup(5)) # needs sage.groups
597
+ True
598
+ """
599
+ from sage.groups.perm_gps.permgroup import PermutationGroup
600
+ P = [(1, 2, 3, 4, 5), (6, 7, 8, 9, 10), (11, 12, 13, 14, 15)]
601
+ S = [(1, 6, 11), (2, 15, 14), (3, 13, 8), (4, 7, 5), (9, 12, 10)]
602
+ start_list = [
603
+ (1, 2, 3, 6, 8, 11, 13, 14, 15), # A
604
+ (1, 3, 6, 8, 9, 10, 11, 12, 13), # B
605
+ (1, 2, 6, 9, 10, 11, 12, 14, 15), # C
606
+ (1, 2, 3, 4, 7, 9, 12, 14, 15), # D
607
+ (1, 2, 4, 7, 9, 10, 12, 13, 14), # E
608
+ (1, 2, 6, 8, 9, 10, 11, 14, 15), # F
609
+ (1, 2, 3, 4, 5, 6, 9, 11, 13), # G
610
+ (1, 3, 5, 6, 8, 9, 10, 11, 12), # H
611
+ (1, 3, 5, 6, 7, 8, 9, 10, 11), # I
612
+ (1, 2, 3, 4, 5, 7, 10, 12, 15), # J
613
+ (1, 2, 3, 7, 8, 10, 12, 13, 14), # K
614
+ (2, 5, 6, 7, 8, 9, 10, 13, 14), # M
615
+
616
+ (3, 4, 6, 7, 11, 12, 13, 14, 15), # L
617
+ (3, 4, 6, 7, 10, 12, 13, 14, 15)] # N
618
+ return UniqueSimplicialComplex([[g(index) for index in tup]
619
+ for tup in start_list
620
+ for g in PermutationGroup([P, S])])
621
+
622
+
623
+ PseudoQuaternionicProjectivePlane = deprecated_function_alias(34568, QuaternionicProjectivePlane)
624
+
625
+
626
+ def PoincareHomologyThreeSphere():
627
+ """
628
+ A triangulation of the Poincaré homology 3-sphere.
629
+
630
+ This is a manifold whose integral homology is identical to the
631
+ ordinary 3-sphere, but it is not simply connected. In particular,
632
+ its fundamental group is the binary icosahedral group, which has
633
+ order 120. The triangulation given here has 16 vertices and is
634
+ due to Björner and Lutz [BL2000]_.
635
+
636
+ EXAMPLES::
637
+
638
+ sage: S3 = simplicial_complexes.Sphere(3)
639
+ sage: Sigma3 = simplicial_complexes.PoincareHomologyThreeSphere()
640
+ sage: S3.homology() == Sigma3.homology() # needs sage.modules
641
+ True
642
+ sage: Sigma3.fundamental_group().cardinality() # long time # needs sage.groups
643
+ 120
644
+ """
645
+ return UniqueSimplicialComplex(
646
+ [[1, 2, 4, 9], [1, 2, 4, 15], [1, 2, 6, 14], [1, 2, 6, 15],
647
+ [1, 2, 9, 14], [1, 3, 4, 12], [1, 3, 4, 15], [1, 3, 7, 10],
648
+ [1, 3, 7, 12], [1, 3, 10, 15], [1, 4, 9, 12], [1, 5, 6, 13],
649
+ [1, 5, 6, 14], [1, 5, 8, 11], [1, 5, 8, 13], [1, 5, 11, 14],
650
+ [1, 6, 13, 15], [1, 7, 8, 10], [1, 7, 8, 11], [1, 7, 11, 12],
651
+ [1, 8, 10, 13], [1, 9, 11, 12], [1, 9, 11, 14], [1, 10, 13, 15],
652
+ [2, 3, 5, 10], [2, 3, 5, 11], [2, 3, 7, 10], [2, 3, 7, 13],
653
+ [2, 3, 11, 13], [2, 4, 9, 13], [2, 4, 11, 13], [2, 4, 11, 15],
654
+ [2, 5, 8, 11], [2, 5, 8, 12], [2, 5, 10, 12], [2, 6, 10, 12],
655
+ [2, 6, 10, 14], [2, 6, 12, 15], [2, 7, 9, 13], [2, 7, 9, 14],
656
+ [2, 7, 10, 14], [2, 8, 11, 15], [2, 8, 12, 15], [3, 4, 5, 14],
657
+ [3, 4, 5, 15], [3, 4, 12, 14], [3, 5, 10, 15], [3, 5, 11, 14],
658
+ [3, 7, 12, 13], [3, 11, 13, 14], [3, 12, 13, 14], [4, 5, 6, 7],
659
+ [4, 5, 6, 14], [4, 5, 7, 15], [4, 6, 7, 11], [4, 6, 10, 11],
660
+ [4, 6, 10, 14], [4, 7, 11, 15], [4, 8, 9, 12], [4, 8, 9, 13],
661
+ [4, 8, 10, 13], [4, 8, 10, 14], [4, 8, 12, 14], [4, 10, 11, 13],
662
+ [5, 6, 7, 13], [5, 7, 9, 13], [5, 7, 9, 15], [5, 8, 9, 12],
663
+ [5, 8, 9, 13], [5, 9, 10, 12], [5, 9, 10, 15], [6, 7, 11, 12],
664
+ [6, 7, 12, 13], [6, 10, 11, 12], [6, 12, 13, 15], [7, 8, 10, 14],
665
+ [7, 8, 11, 15], [7, 8, 14, 15], [7, 9, 14, 15], [8, 12, 14, 15],
666
+ [9, 10, 11, 12], [9, 10, 11, 16], [9, 10, 15, 16], [9, 11, 14, 16],
667
+ [9, 14, 15, 16], [10, 11, 13, 16], [10, 13, 15, 16],
668
+ [11, 13, 14, 16], [12, 13, 14, 15], [13, 14, 15, 16]],
669
+ name='Triangulation of the Poincare homology 3-sphere')
670
+
671
+
672
+ def RealProjectiveSpace(n):
673
+ r"""
674
+ A triangulation of `\Bold{R}P^n` for any `n \geq 0`.
675
+
676
+ INPUT:
677
+
678
+ - ``n`` -- integer; the dimension of the real projective space
679
+ to construct
680
+
681
+ The first few cases are pretty trivial:
682
+
683
+ - `\Bold{R}P^0` is a point.
684
+
685
+ - `\Bold{R}P^1` is a circle, triangulated as the boundary of a
686
+ single 2-simplex.
687
+
688
+ - `\Bold{R}P^2` is the real projective plane, here given its
689
+ minimal triangulation with 6 vertices, 15 edges, and 10
690
+ triangles.
691
+
692
+ - `\Bold{R}P^3`: any triangulation has at least 11 vertices by
693
+ a result of Walkup [Wal1970]_; this function returns a
694
+ triangulation with 11 vertices, as given by Lutz [Lut2005]_.
695
+
696
+ - `\Bold{R}P^4`: any triangulation has at least 16 vertices by
697
+ a result of Walkup; this function returns a triangulation
698
+ with 16 vertices as given by Lutz; see also Datta [Dat2007]_,
699
+ Example 3.12.
700
+
701
+ - `\Bold{R}P^n`: Lutz has found a triangulation of
702
+ `\Bold{R}P^5` with 24 vertices, but it does not seem to have
703
+ been published. Kühnel [Kuh1987]_ has described a triangulation of
704
+ `\Bold{R}P^n`, in general, with `2^{n+1}-1` vertices; see
705
+ also Datta, Example 3.21. This triangulation is presumably
706
+ not minimal, but it seems to be the best in the published
707
+ literature as of this writing. So this function returns it
708
+ when `n > 4`.
709
+
710
+ ALGORITHM: For `n < 4`, these are constructed explicitly by
711
+ listing the facets. For `n = 4`, this is constructed by
712
+ specifying 16 vertices, two facets, and a certain subgroup `G`
713
+ of the symmetric group `S_{16}`. Then the set of all facets
714
+ is the `G`-orbit of the two given facets. This is implemented
715
+ here by explicitly listing all of the facets; the facets
716
+ can be computed by the function :func:`~sage.homology.simplicial_complex.facets_for_RP4`, but
717
+ running the function takes a few seconds.
718
+
719
+ For `n > 4`, the construction is as follows: let `S` denote
720
+ the simplicial complex structure on the `n`-sphere given by
721
+ the first barycentric subdivision of the boundary of an
722
+ `(n+1)`-simplex. This has a simplicial antipodal action: if
723
+ `V` denotes the vertices in the boundary of the simplex, then
724
+ the vertices in its barycentric subdivision `S` correspond to
725
+ nonempty proper subsets `U` of `V`, and the antipodal action
726
+ sends any subset `U` to its complement. One can show that
727
+ modding out by this action results in a triangulation for
728
+ `\Bold{R}P^n`. To find the facets in this triangulation, find
729
+ the facets in `S`. These are identified in pairs to form
730
+ `\Bold{R}P^n`, so choose a representative from each pair: for
731
+ each facet in `S`, replace any vertex in `S` containing 0 with
732
+ its complement.
733
+
734
+ Of course these complexes increase in size pretty quickly as
735
+ `n` increases.
736
+
737
+ EXAMPLES::
738
+
739
+ sage: P3 = simplicial_complexes.RealProjectiveSpace(3)
740
+ sage: P3.f_vector()
741
+ [1, 11, 51, 80, 40]
742
+ sage: P3.homology() # needs sage.modules
743
+ {0: 0, 1: C2, 2: 0, 3: Z}
744
+ sage: P4 = simplicial_complexes.RealProjectiveSpace(4)
745
+ sage: P4.f_vector()
746
+ [1, 16, 120, 330, 375, 150]
747
+ sage: P4.homology() # long time
748
+ {0: 0, 1: C2, 2: 0, 3: C2, 4: 0}
749
+ sage: P5 = simplicial_complexes.RealProjectiveSpace(5) # long time (44s on sage.math, 2012)
750
+ sage: P5.f_vector() # long time
751
+ [1, 63, 903, 4200, 8400, 7560, 2520]
752
+
753
+ The following computation can take a long time -- over half an
754
+ hour. ::
755
+
756
+ sage: P5.homology() # not tested
757
+ {0: 0, 1: C2, 2: 0, 3: C2, 4: 0, 5: Z}
758
+ sage: simplicial_complexes.RealProjectiveSpace(2).dimension()
759
+ 2
760
+ sage: P3.dimension()
761
+ 3
762
+ sage: P4.dimension() # long time
763
+ 4
764
+ sage: P5.dimension() # long time
765
+ 5
766
+ """
767
+ if n == 0:
768
+ return Simplex(0)
769
+ if n == 1:
770
+ return Sphere(1)
771
+ if n == 2:
772
+ return RealProjectivePlane()
773
+ if n == 3:
774
+ # Minimal triangulation found by Walkup and given
775
+ # explicitly by Lutz
776
+ return UniqueSimplicialComplex(
777
+ [[1, 2, 3, 7], [1, 4, 7, 9], [2, 3, 4, 8], [2, 5, 8, 10],
778
+ [3, 6, 7, 10], [1, 2, 3, 11], [1, 4, 7, 10], [2, 3, 4, 11],
779
+ [2, 5, 9, 10], [3, 6, 8, 9], [1, 2, 6, 9], [1, 4, 8, 9],
780
+ [2, 3, 7, 8], [2, 6, 9, 10], [3, 6, 9, 10], [1, 2, 6, 11],
781
+ [1, 4, 8, 10], [2, 4, 6, 10], [3, 4, 5, 9], [4, 5, 6, 7],
782
+ [1, 2, 7, 9], [1, 5, 6, 8], [2, 4, 6, 11], [3, 4, 5, 11],
783
+ [4, 5, 6, 11], [1, 3, 5, 10], [1, 5, 6, 11], [2, 4, 8, 10],
784
+ [3, 4, 8, 9], [4, 5, 7, 9], [1, 3, 5, 11], [1, 5, 8, 10],
785
+ [2, 5, 7, 8], [3, 5, 9, 10], [4, 6, 7, 10], [1, 3, 7, 10],
786
+ [1, 6, 8, 9], [2, 5, 7, 9], [3, 6, 7, 8], [5, 6, 7, 8]],
787
+ name='Minimal triangulation of RP^3')
788
+ if n == 4:
789
+ return UniqueSimplicialComplex(
790
+ [(1, 3, 8, 12, 13), (2, 7, 8, 13, 16), (4, 8, 9, 12, 14),
791
+ (2, 6, 10, 12, 16), (5, 7, 9, 10, 13), (1, 2, 7, 8, 15),
792
+ (1, 3, 9, 11, 16), (5, 6, 8, 13, 16), (1, 3, 8, 11, 13),
793
+ (3, 4, 10, 13, 15), (4, 6, 9, 12, 15), (2, 4, 6, 11, 13),
794
+ (2, 3, 9, 12, 16), (1, 6, 9, 12, 15), (2, 5, 10, 11, 12),
795
+ (1, 7, 8, 12, 15), (2, 6, 9, 13, 16), (1, 5, 9, 11, 15),
796
+ (4, 9, 10, 13, 14), (2, 7, 8, 15, 16), (2, 3, 9, 12, 14),
797
+ (1, 6, 7, 10, 14), (2, 5, 10, 11, 15), (1, 2, 4, 13, 14),
798
+ (1, 6, 10, 14, 16), (2, 6, 9, 12, 16), (1, 3, 9, 12, 16),
799
+ (4, 5, 7, 11, 16), (5, 9, 10, 11, 15), (3, 5, 8, 12, 14),
800
+ (5, 6, 9, 13, 16), (5, 6, 9, 13, 15), (1, 3, 4, 10, 16),
801
+ (1, 6, 10, 12, 16), (2, 4, 6, 9, 13), (2, 4, 6, 9, 12),
802
+ (1, 2, 4, 11, 13), (7, 9, 10, 13, 14), (1, 7, 8, 12, 13),
803
+ (4, 6, 7, 11, 12), (3, 4, 6, 11, 13), (1, 5, 6, 9, 15),
804
+ (1, 6, 7, 14, 15), (2, 3, 7, 14, 15), (2, 6, 10, 11, 12),
805
+ (5, 7, 9, 10, 11), (1, 2, 4, 5, 14), (3, 5, 10, 13, 15),
806
+ (3, 8, 9, 12, 14), (5, 9, 10, 13, 15), (2, 6, 8, 13, 16),
807
+ (1, 2, 7, 13, 14), (1, 7, 10, 12, 13), (3, 4, 6, 13, 15),
808
+ (4, 9, 10, 13, 15), (2, 3, 10, 12, 16), (1, 2, 5, 14, 15),
809
+ (2, 6, 8, 10, 11), (1, 3, 10, 12, 13), (4, 8, 9, 12, 15),
810
+ (1, 3, 8, 9, 11), (4, 6, 7, 12, 15), (1, 8, 9, 11, 15),
811
+ (4, 5, 8, 14, 16), (1, 2, 8, 11, 13), (3, 6, 8, 11, 13),
812
+ (3, 6, 8, 11, 14), (3, 5, 8, 12, 13), (3, 7, 9, 11, 14),
813
+ (4, 6, 9, 13, 15), (2, 3, 5, 10, 12), (4, 7, 8, 15, 16),
814
+ (1, 2, 7, 14, 15), (3, 7, 9, 11, 16), (3, 6, 7, 14, 15),
815
+ (2, 6, 8, 11, 13), (4, 8, 9, 10, 14), (1, 4, 10, 13, 14),
816
+ (4, 8, 9, 10, 15), (2, 7, 9, 13, 16), (1, 6, 9, 12, 16),
817
+ (2, 3, 7, 9, 14), (4, 8, 10, 15, 16), (1, 5, 9, 11, 16),
818
+ (1, 5, 6, 14, 15), (5, 7, 9, 11, 16), (4, 5, 7, 11, 12),
819
+ (5, 7, 10, 11, 12), (2, 3, 10, 15, 16), (1, 2, 7, 8, 13),
820
+ (1, 6, 7, 10, 12), (1, 3, 10, 12, 16), (7, 9, 10, 11, 14),
821
+ (1, 7, 10, 13, 14), (1, 2, 4, 5, 11), (3, 4, 6, 7, 11),
822
+ (1, 6, 7, 12, 15), (1, 3, 4, 10, 13), (1, 4, 10, 14, 16),
823
+ (2, 4, 6, 11, 12), (5, 6, 8, 14, 16), (3, 5, 6, 8, 13),
824
+ (3, 5, 6, 8, 14), (1, 2, 8, 11, 15), (1, 4, 5, 14, 16),
825
+ (2, 3, 7, 15, 16), (8, 9, 10, 11, 14), (1, 3, 4, 11, 16),
826
+ (6, 8, 10, 14, 16), (8, 9, 10, 11, 15), (1, 3, 4, 11, 13),
827
+ (2, 4, 5, 12, 14), (2, 4, 9, 13, 14), (3, 4, 7, 11, 16),
828
+ (3, 6, 7, 11, 14), (3, 8, 9, 11, 14), (2, 8, 10, 11, 15),
829
+ (1, 3, 8, 9, 12), (4, 5, 7, 8, 16), (4, 5, 8, 12, 14),
830
+ (2, 4, 9, 12, 14), (6, 8, 10, 11, 14), (3, 5, 6, 13, 15),
831
+ (1, 4, 5, 11, 16), (3, 5, 6, 14, 15), (2, 4, 5, 11, 12),
832
+ (4, 5, 7, 8, 12), (1, 8, 9, 12, 15), (5, 7, 8, 13, 16),
833
+ (2, 3, 5, 12, 14), (3, 5, 10, 12, 13), (6, 7, 10, 11, 12),
834
+ (5, 7, 9, 13, 16), (6, 7, 10, 11, 14), (5, 7, 10, 12, 13),
835
+ (1, 2, 5, 11, 15), (1, 5, 6, 9, 16), (5, 7, 8, 12, 13),
836
+ (4, 7, 8, 12, 15), (2, 3, 5, 10, 15), (2, 6, 8, 10, 16),
837
+ (3, 4, 10, 15, 16), (1, 5, 6, 14, 16), (2, 3, 5, 14, 15),
838
+ (2, 3, 7, 9, 16), (2, 7, 9, 13, 14), (3, 4, 6, 7, 15),
839
+ (4, 8, 10, 14, 16), (3, 4, 7, 15, 16), (2, 8, 10, 15, 16)],
840
+ name='Minimal triangulation of RP^4')
841
+ if n >= 5:
842
+ # Use the construction given by Datta in Example 3.21.
843
+ V = set(range(0, n+2))
844
+ S = Sphere(n).barycentric_subdivision()
845
+ X = S.facets()
846
+ facets = set()
847
+ for f in X:
848
+ new = []
849
+ for v in f:
850
+ if 0 in v:
851
+ new.append(tuple(V.difference(v)))
852
+ else:
853
+ new.append(v)
854
+ facets.add(tuple(new))
855
+ return UniqueSimplicialComplex(list(facets),
856
+ name='Triangulation of RP^{}'.format(n))
857
+
858
+
859
+ def K3Surface():
860
+ """
861
+ Return a minimal triangulation of the K3 surface.
862
+
863
+ This is a pure simplicial complex of dimension 4 with 16 vertices
864
+ and 288 facets. It was constructed by Casella and Kühnel
865
+ in [CK2001]_. The construction here uses the labeling from
866
+ Spreer and Kühnel [SK2011]_.
867
+
868
+ EXAMPLES::
869
+
870
+ sage: K3 = simplicial_complexes.K3Surface(); K3
871
+ Minimal triangulation of the K3 surface
872
+ sage: K3.f_vector()
873
+ [1, 16, 120, 560, 720, 288]
874
+
875
+ This simplicial complex is implemented just by listing all 288
876
+ facets. The list of facets can be computed by the function
877
+ :func:`~sage.homology.simplicial_complex.facets_for_K3`, but running the function takes a few
878
+ seconds.
879
+ """
880
+ return UniqueSimplicialComplex(
881
+ [(2, 10, 13, 15, 16), (2, 8, 11, 15, 16), (2, 5, 7, 8, 10),
882
+ (1, 9, 11, 13, 14), (1, 2, 8, 10, 12), (1, 3, 5, 6, 11),
883
+ (1, 5, 6, 9, 12), (1, 2, 6, 13, 16), (1, 4, 10, 13, 14),
884
+ (1, 9, 10, 14, 15), (2, 4, 7, 8, 12), (3, 4, 6, 10, 12),
885
+ (1, 6, 7, 8, 9), (3, 4, 5, 7, 15), (1, 7, 12, 15, 16),
886
+ (4, 5, 7, 13, 16), (5, 8, 11, 12, 15), (2, 4, 7, 12, 14),
887
+ (1, 4, 5, 14, 16), (2, 5, 6, 10, 11), (1, 6, 8, 12, 14),
888
+ (5, 8, 9, 14, 16), (5, 10, 11, 12, 13), (2, 4, 8, 9, 12),
889
+ (7, 9, 12, 15, 16), (1, 2, 6, 9, 15), (1, 5, 14, 15, 16),
890
+ (2, 3, 4, 5, 9), (6, 8, 10, 11, 15), (1, 5, 8, 10, 12),
891
+ (1, 3, 7, 9, 10), (6, 7, 8, 9, 13), (1, 2, 9, 11, 15),
892
+ (2, 8, 11, 14, 16), (2, 4, 5, 13, 16), (1, 4, 8, 13, 15),
893
+ (4, 7, 8, 10, 11), (2, 3, 9, 11, 14), (2, 3, 4, 9, 13),
894
+ (2, 8, 10, 12, 13), (1, 2, 4, 11, 15), (2, 3, 9, 11, 15),
895
+ (3, 5, 10, 13, 15), (3, 4, 5, 9, 11), (6, 10, 13, 15, 16),
896
+ (8, 10, 11, 15, 16), (6, 7, 11, 13, 15), (1, 5, 7, 15, 16),
897
+ (4, 5, 7, 9, 15), (3, 4, 6, 7, 16), (2, 3, 11, 14, 16),
898
+ (3, 4, 9, 11, 13), (1, 2, 5, 14, 15), (2, 3, 9, 13, 14),
899
+ (1, 2, 5, 13, 16), (2, 3, 7, 8, 12), (2, 9, 11, 12, 14),
900
+ (1, 9, 11, 15, 16), (4, 6, 9, 14, 16), (1, 4, 9, 13, 14),
901
+ (1, 2, 3, 12, 16), (8, 11, 12, 14, 15), (2, 4, 11, 12, 14),
902
+ (1, 4, 10, 12, 13), (1, 2, 6, 7, 13), (1, 3, 6, 10, 11),
903
+ (1, 6, 8, 9, 12), (1, 4, 5, 6, 14), (3, 9, 10, 12, 15),
904
+ (5, 8, 11, 12, 16), (5, 9, 10, 14, 15), (3, 9, 12, 15, 16),
905
+ (3, 6, 8, 14, 15), (2, 4, 9, 10, 16), (5, 8, 9, 13, 15),
906
+ (2, 3, 6, 9, 15), (6, 11, 12, 14, 16), (2, 3, 10, 13, 15),
907
+ (2, 8, 9, 10, 13), (3, 4, 8, 11, 13), (3, 4, 5, 7, 13),
908
+ (5, 7, 8, 10, 14), (4, 12, 13, 14, 15), (6, 7, 10, 14, 16),
909
+ (5, 10, 11, 13, 14), (3, 4, 7, 13, 16), (6, 8, 9, 12, 13),
910
+ (1, 3, 4, 10, 14), (2, 4, 6, 11, 12), (1, 7, 9, 10, 14),
911
+ (4, 6, 8, 13, 14), (4, 9, 10, 11, 16), (3, 7, 8, 10, 16),
912
+ (5, 7, 9, 15, 16), (1, 7, 9, 11, 14), (6, 8, 10, 15, 16),
913
+ (5, 8, 9, 10, 14), (7, 8, 10, 14, 16), (2, 6, 7, 9, 11),
914
+ (7, 9, 10, 13, 15), (3, 6, 7, 10, 12), (2, 4, 6, 10, 11),
915
+ (4, 5, 8, 9, 11), (1, 2, 3, 8, 16), (3, 7, 9, 10, 12),
916
+ (1, 2, 6, 8, 14), (3, 5, 6, 13, 15), (1, 5, 6, 12, 14),
917
+ (2, 5, 7, 14, 15), (1, 5, 10, 11, 12), (3, 7, 8, 10, 11),
918
+ (1, 2, 6, 14, 15), (1, 2, 6, 8, 16), (7, 9, 10, 12, 15),
919
+ (3, 4, 6, 8, 14), (3, 7, 13, 14, 16), (2, 5, 7, 8, 14),
920
+ (6, 7, 9, 10, 14), (2, 3, 7, 12, 14), (4, 10, 12, 13, 14),
921
+ (2, 5, 6, 11, 13), (4, 5, 6, 7, 16), (1, 3, 12, 13, 16),
922
+ (1, 4, 11, 15, 16), (1, 3, 4, 6, 10), (1, 10, 11, 12, 13),
923
+ (6, 9, 11, 12, 14), (1, 4, 7, 8, 15), (5, 8, 9, 10, 13),
924
+ (1, 2, 5, 7, 15), (1, 7, 12, 13, 16), (3, 11, 13, 14, 16),
925
+ (1, 2, 5, 7, 13), (4, 7, 8, 9, 15), (1, 5, 6, 10, 11),
926
+ (6, 7, 10, 13, 15), (3, 4, 7, 14, 15), (7, 11, 13, 14, 16),
927
+ (3, 4, 10, 12, 14), (3, 6, 8, 10, 16), (2, 7, 8, 14, 16),
928
+ (2, 3, 4, 5, 13), (5, 8, 12, 13, 15), (4, 6, 9, 13, 14),
929
+ (2, 4, 5, 6, 12), (1, 3, 7, 8, 9), (8, 11, 12, 14, 16),
930
+ (1, 7, 12, 13, 15), (8, 12, 13, 14, 15), (2, 8, 9, 12, 13),
931
+ (4, 6, 10, 12, 15), (2, 8, 11, 14, 15), (2, 6, 9, 11, 12),
932
+ (8, 9, 10, 11, 16), (2, 3, 6, 13, 15), (2, 3, 12, 15, 16),
933
+ (1, 3, 5, 9, 12), (2, 5, 6, 9, 12), (2, 10, 12, 13, 14),
934
+ (2, 6, 13, 15, 16), (2, 3, 11, 15, 16), (3, 5, 6, 8, 15),
935
+ (2, 4, 5, 9, 12), (5, 6, 8, 11, 15), (6, 8, 12, 13, 14),
936
+ (1, 2, 3, 8, 12), (1, 4, 7, 8, 11), (3, 5, 7, 14, 15),
937
+ (3, 5, 7, 13, 14), (1, 7, 10, 11, 14), (6, 7, 11, 12, 15),
938
+ (3, 4, 6, 7, 12), (1, 2, 4, 7, 11), (6, 9, 10, 14, 16),
939
+ (4, 10, 12, 15, 16), (5, 6, 7, 12, 16), (3, 9, 11, 13, 14),
940
+ (5, 9, 14, 15, 16), (4, 5, 6, 7, 12), (1, 3, 9, 10, 15),
941
+ (4, 7, 8, 9, 12), (5, 9, 10, 13, 15), (1, 3, 8, 13, 16),
942
+ (2, 9, 12, 13, 14), (6, 7, 10, 12, 15), (2, 6, 8, 14, 15),
943
+ (3, 5, 6, 8, 11), (3, 4, 7, 12, 14), (1, 3, 10, 14, 15),
944
+ (7, 11, 12, 13, 16), (3, 11, 12, 13, 16), (3, 4, 5, 8, 15),
945
+ (2, 4, 7, 8, 10), (2, 4, 7, 14, 15), (1, 2, 10, 12, 16),
946
+ (1, 6, 8, 13, 16), (1, 7, 8, 13, 15), (3, 9, 11, 15, 16),
947
+ (4, 6, 10, 11, 15), (2, 4, 11, 14, 15), (1, 3, 8, 9, 12),
948
+ (1, 3, 6, 14, 15), (2, 4, 5, 6, 10), (1, 4, 9, 14, 16),
949
+ (5, 7, 9, 12, 16), (1, 3, 7, 10, 11), (7, 8, 9, 13, 15),
950
+ (3, 5, 10, 14, 15), (1, 4, 10, 12, 16), (3, 4, 5, 8, 11),
951
+ (1, 2, 6, 7, 9), (1, 3, 11, 12, 13), (1, 5, 7, 13, 16),
952
+ (5, 7, 10, 11, 14), (2, 10, 12, 15, 16), (3, 6, 7, 10, 16),
953
+ (1, 2, 5, 8, 10), (4, 10, 11, 15, 16), (5, 8, 10, 12, 13),
954
+ (3, 6, 8, 10, 11), (4, 5, 7, 9, 12), (6, 7, 11, 12, 16),
955
+ (3, 5, 9, 11, 16), (8, 9, 10, 14, 16), (3, 4, 6, 8, 16),
956
+ (1, 10, 11, 13, 14), (2, 9, 10, 13, 16), (1, 2, 5, 8, 14),
957
+ (2, 4, 5, 10, 16), (1, 2, 7, 9, 11), (1, 3, 5, 6, 9),
958
+ (5, 7, 11, 13, 14), (3, 5, 10, 13, 14), (2, 4, 8, 9, 10),
959
+ (4, 11, 12, 14, 15), (2, 3, 7, 14, 16), (3, 4, 8, 13, 16),
960
+ (6, 7, 9, 11, 14), (5, 6, 11, 13, 15), (4, 5, 6, 14, 16),
961
+ (3, 4, 8, 14, 15), (4, 5, 8, 9, 15), (1, 4, 8, 11, 13),
962
+ (5, 6, 12, 14, 16), (2, 3, 10, 12, 14), (1, 2, 5, 10, 16),
963
+ (2, 5, 7, 10, 11), (2, 6, 7, 11, 13), (1, 4, 5, 10, 16),
964
+ (2, 6, 8, 15, 16), (2, 3, 10, 12, 15), (7, 11, 12, 13, 15),
965
+ (1, 3, 8, 11, 13), (4, 8, 9, 10, 11), (1, 9, 14, 15, 16),
966
+ (1, 3, 6, 9, 15), (6, 9, 12, 13, 14), (2, 3, 10, 13, 14),
967
+ (2, 5, 7, 11, 13), (2, 3, 5, 6, 13), (4, 6, 8, 13, 16),
968
+ (6, 7, 9, 10, 13), (5, 8, 12, 14, 16), (4, 6, 9, 13, 16),
969
+ (5, 8, 9, 11, 16), (2, 3, 5, 6, 9), (1, 3, 5, 11, 12),
970
+ (3, 7, 8, 9, 12), (4, 6, 11, 12, 15), (3, 5, 9, 12, 16),
971
+ (5, 11, 12, 13, 15), (1, 3, 4, 6, 14), (3, 5, 11, 12, 16),
972
+ (1, 5, 8, 12, 14), (4, 8, 13, 14, 15), (1, 3, 7, 8, 11),
973
+ (6, 9, 10, 13, 16), (2, 4, 9, 13, 16), (1, 6, 7, 8, 13),
974
+ (1, 4, 12, 13, 15), (2, 4, 7, 10, 11), (1, 4, 9, 11, 13),
975
+ (6, 7, 11, 14, 16), (1, 4, 9, 11, 16), (1, 4, 12, 15, 16),
976
+ (1, 2, 4, 7, 15), (2, 3, 7, 8, 16), (1, 4, 5, 6, 10)],
977
+ name='Minimal triangulation of the K3 surface')
978
+
979
+
980
+ def BarnetteSphere():
981
+ r"""
982
+ Return Barnette's triangulation of the 3-sphere.
983
+
984
+ This is a pure simplicial complex of dimension 3 with 8
985
+ vertices and 19 facets, which is a non-polytopal triangulation
986
+ of the 3-sphere. It was constructed by Barnette in
987
+ [Bar1970]_. The construction here uses the labeling from De
988
+ Loera, Rambau and Santos [DLRS2010]_. Another reference is chapter
989
+ III.4 of Ewald [Ewa1996]_.
990
+
991
+ EXAMPLES::
992
+
993
+ sage: BS = simplicial_complexes.BarnetteSphere(); BS
994
+ Barnette's triangulation of the 3-sphere
995
+ sage: BS.f_vector()
996
+ [1, 8, 27, 38, 19]
997
+
998
+ TESTS:
999
+
1000
+ Checks that this is indeed the same Barnette Sphere as the one
1001
+ given on page 87 of [Ewa1996]_.::
1002
+
1003
+ sage: BS2 = SimplicialComplex([[1, 2, 3, 4], [3, 4, 5, 6], [1, 2, 5, 6],
1004
+ ....: [1, 2, 4, 7], [1, 3, 4, 7], [3, 4, 6, 7],
1005
+ ....: [3, 5, 6, 7], [1, 2, 5, 7], [2, 5, 6, 7],
1006
+ ....: [2, 4, 6, 7], [1, 2, 3, 8], [2, 3, 4, 8],
1007
+ ....: [3, 4, 5, 8], [4, 5, 6, 8], [1, 2, 6, 8],
1008
+ ....: [1, 5, 6, 8], [1, 3, 5, 8], [2, 4, 6, 8],
1009
+ ....: [1, 3, 5, 7]])
1010
+ sage: BS.is_isomorphic(BS2)
1011
+ True
1012
+ """
1013
+ return UniqueSimplicialComplex([(1, 2, 4, 5), (2, 3, 5, 6), (1, 3, 4, 6),
1014
+ (1, 2, 3, 7), (4, 5, 6, 7), (1, 2, 4, 7),
1015
+ (2, 4, 5, 7), (2, 3, 5, 7), (3, 5, 6, 7),
1016
+ (3, 1, 6, 7), (1, 6, 4, 7), (1, 2, 3, 8),
1017
+ (4, 5, 6, 8), (1, 2, 5, 8), (1, 4, 5, 8),
1018
+ (2, 3, 6, 8), (2, 5, 6, 8), (3, 1, 4, 8),
1019
+ (3, 6, 4, 8)],
1020
+ name="Barnette's triangulation of the 3-sphere")
1021
+
1022
+
1023
+ def BrucknerGrunbaumSphere():
1024
+ r"""
1025
+ Return Bruckner and Grunbaum's triangulation of the 3-sphere.
1026
+
1027
+ This is a pure simplicial complex of dimension 3 with 8
1028
+ vertices and 20 facets, which is a non-polytopal triangulation
1029
+ of the 3-sphere. It appeared first in [Br1910]_ and was studied in
1030
+ [GrS1967]_.
1031
+
1032
+ It is defined here as the link of any vertex in the unique minimal
1033
+ triangulation of the complex projective plane, see chapter 4 of
1034
+ [Kuh1995]_.
1035
+
1036
+ EXAMPLES::
1037
+
1038
+ sage: BGS = simplicial_complexes.BrucknerGrunbaumSphere(); BGS
1039
+ Bruckner and Grunbaum's triangulation of the 3-sphere
1040
+ sage: BGS.f_vector()
1041
+ [1, 8, 28, 40, 20]
1042
+ """
1043
+ # X = ComplexProjectivePlane().link([9])
1044
+ # return UniqueSimplicialComplex(X.facets(),
1045
+ # name="Bruckner and Grunbaum's triangulation of the 3-sphere")
1046
+ return UniqueSimplicialComplex(ComplexProjectivePlane().link([9]),
1047
+ name="Bruckner and Grunbaum's triangulation of the 3-sphere")
1048
+
1049
+ ###############################################################
1050
+ # examples from graph theory:
1051
+
1052
+
1053
+ def NotIConnectedGraphs(n, i):
1054
+ """
1055
+ The simplicial complex of all graphs on `n` vertices which are
1056
+ not `i`-connected.
1057
+
1058
+ Fix an integer `n>0` and consider the set of graphs on `n`
1059
+ vertices. View each graph as its set of edges, so it is a
1060
+ subset of a set of size `n` choose 2. A graph is
1061
+ `i`-connected if, for any `j<i`, if any `j` vertices are
1062
+ removed along with the edges emanating from them, then the
1063
+ graph remains connected. Now fix `i`: it is clear that if `G`
1064
+ is not `i`-connected, then the same is true for any graph
1065
+ obtained from `G` by deleting edges. Thus the set of all
1066
+ graphs which are not `i`-connected, viewed as a set of subsets
1067
+ of the `n` choose 2 possible edges, is closed under taking
1068
+ subsets, and thus forms a simplicial complex. This function
1069
+ produces that simplicial complex.
1070
+
1071
+ INPUT:
1072
+
1073
+ - ``n``, ``i`` -- nonnegative integers with `i` at most `n`
1074
+
1075
+ See Dumas et al. [DHSW2003]_ for information on computing its homology
1076
+ by computer, and see Babson et al. [BBLSW1999]_ for theory. For
1077
+ example, Babson et al. show that when `i=2`, the reduced homology of
1078
+ this complex is nonzero only in dimension `2n-5`, where it is
1079
+ free abelian of rank `(n-2)!`.
1080
+
1081
+ EXAMPLES::
1082
+
1083
+ sage: NICG52 = simplicial_complexes.NotIConnectedGraphs(5, 2)
1084
+ sage: NICG52.f_vector()
1085
+ [1, 10, 45, 120, 210, 240, 140, 20]
1086
+ sage: NICG52.homology(5).ngens() # needs sage.modules
1087
+ 6
1088
+ """
1089
+ G_list = range(1, n+1)
1090
+ G_vertices = Set(G_list)
1091
+ E_list = []
1092
+ for w in G_list:
1093
+ for v in range(1, w):
1094
+ E_list.append((v, w))
1095
+ E = Set(E_list)
1096
+ facets = []
1097
+ i_minus_one_sets = list(G_vertices.subsets(size=i-1))
1098
+ for A in i_minus_one_sets:
1099
+ G_minus_A = G_vertices.difference(A)
1100
+ for B in G_minus_A.subsets():
1101
+ if len(B) > 0 and len(B) < len(G_minus_A):
1102
+ C = G_minus_A.difference(B)
1103
+ facet = E
1104
+ for v in B:
1105
+ for w in C:
1106
+ bad_edge = (min(v, w), max(v, w))
1107
+ facet = facet.difference(Set([bad_edge]))
1108
+ facets.append(facet)
1109
+ return UniqueSimplicialComplex(facets, name='Simplicial complex of not {}-connected graphs on {} vertices'.format(i, n))
1110
+
1111
+
1112
+ def MatchingComplex(n):
1113
+ """
1114
+ The matching complex of graphs on `n` vertices.
1115
+
1116
+ Fix an integer `n>0` and consider a set `V` of `n` vertices.
1117
+ A 'partial matching' on `V` is a graph formed by edges so that
1118
+ each vertex is in at most one edge. If `G` is a partial
1119
+ matching, then so is any graph obtained by deleting edges from
1120
+ `G`. Thus the set of all partial matchings on `n` vertices,
1121
+ viewed as a set of subsets of the `n` choose 2 possible edges,
1122
+ is closed under taking subsets, and thus forms a simplicial
1123
+ complex called the 'matching complex'. This function produces
1124
+ that simplicial complex.
1125
+
1126
+ INPUT:
1127
+
1128
+ - ``n`` -- positive integer
1129
+
1130
+ See Dumas et al. [DHSW2003]_ for information on computing its homology
1131
+ by computer, and see Wachs [Wac2003]_ for an expository article about
1132
+ the theory. For example, the homology of these complexes seems to
1133
+ have only mod 3 torsion, and this has been proved for the
1134
+ bottom non-vanishing homology group for the matching complex `M_n`.
1135
+
1136
+ EXAMPLES::
1137
+
1138
+ sage: M = simplicial_complexes.MatchingComplex(7)
1139
+ sage: H = M.homology(); H # needs sage.modules
1140
+ {0: 0, 1: C3, 2: Z^20}
1141
+ sage: H[2].ngens() # needs sage.modules
1142
+ 20
1143
+ sage: M8 = simplicial_complexes.MatchingComplex(8)
1144
+ sage: M8.homology(2) # long time (6s on sage.math, 2012), needs sage.modules
1145
+ Z^132
1146
+ """
1147
+ G_vertices = Set(range(1, n+1))
1148
+ facets = []
1149
+ if is_even(n):
1150
+ half = int(n/2)
1151
+ half_n_sets = list(G_vertices.subsets(size=half))
1152
+ else:
1153
+ half = int((n-1)/2)
1154
+ half_n_sets = list(G_vertices.subsets(size=half))
1155
+ for X in half_n_sets:
1156
+ Xcomp = G_vertices.difference(X)
1157
+ if is_even(n):
1158
+ if 1 in X:
1159
+ A = X
1160
+ B = Xcomp
1161
+ else:
1162
+ A = Xcomp
1163
+ B = X
1164
+ for M in matching(A, B):
1165
+ facet = []
1166
+ for pair in M:
1167
+ facet.append(tuple(sorted(pair)))
1168
+ facets.append(facet)
1169
+ else:
1170
+ for w in Xcomp:
1171
+ if 1 in X or (w == 1 and 2 in X):
1172
+ A = X
1173
+ B = Xcomp.difference([w])
1174
+ else:
1175
+ B = X
1176
+ A = Xcomp.difference([w])
1177
+ for M in matching(A, B):
1178
+ facet = []
1179
+ for pair in M:
1180
+ facet.append(tuple(sorted(pair)))
1181
+ facets.append(facet)
1182
+ return UniqueSimplicialComplex(facets, name='Matching complex on {} vertices'.format(n))
1183
+
1184
+
1185
+ def ChessboardComplex(n, i):
1186
+ r"""
1187
+ The chessboard complex for an `n \times i` chessboard.
1188
+
1189
+ Fix integers `n, i > 0` and consider sets `V` of `n` vertices
1190
+ and `W` of `i` vertices. A 'partial matching' between `V` and
1191
+ `W` is a graph formed by edges `(v, w)` with `v \in V` and `w
1192
+ \in W` so that each vertex is in at most one edge. If `G` is
1193
+ a partial matching, then so is any graph obtained by deleting
1194
+ edges from `G`. Thus the set of all partial matchings on `V`
1195
+ and `W`, viewed as a set of subsets of the `n+i` choose 2
1196
+ possible edges, is closed under taking subsets, and thus forms
1197
+ a simplicial complex called the 'chessboard complex'. This
1198
+ function produces that simplicial complex. (It is called the
1199
+ chessboard complex because such graphs also correspond to ways
1200
+ of placing rooks on an `n` by `i` chessboard so that none of
1201
+ them are attacking each other.)
1202
+
1203
+ INPUT:
1204
+
1205
+ - ``n``, ``i`` -- positive integers
1206
+
1207
+ See Dumas et al. [DHSW2003]_ for information on computing its homology
1208
+ by computer, and see Wachs [Wac2003]_ for an expository article about
1209
+ the theory.
1210
+
1211
+ EXAMPLES::
1212
+
1213
+ sage: C = simplicial_complexes.ChessboardComplex(5, 5)
1214
+ sage: C.f_vector()
1215
+ [1, 25, 200, 600, 600, 120]
1216
+ sage: simplicial_complexes.ChessboardComplex(3, 3).homology() # needs sage.modules
1217
+ {0: 0, 1: Z x Z x Z x Z, 2: 0}
1218
+ """
1219
+ A = range(n)
1220
+ B = range(i)
1221
+ E_dict = {}
1222
+ index = 0
1223
+ for v in A:
1224
+ for w in B:
1225
+ E_dict[(v, w)] = index
1226
+ index += 1
1227
+ facets = []
1228
+ for M in matching(A, B):
1229
+ facet = []
1230
+ for pair in M:
1231
+ facet.append(E_dict[pair])
1232
+ facets.append(facet)
1233
+ return UniqueSimplicialComplex(facets, name='Chessboard complex for an {}x{} chessboard'.format(n, i))
1234
+
1235
+
1236
+ def RandomComplex(n, d, p=0.5):
1237
+ """
1238
+ A random `d`-dimensional simplicial complex on `n` vertices.
1239
+
1240
+ INPUT:
1241
+
1242
+ - ``n`` -- number of vertices
1243
+
1244
+ - ``d`` -- dimension of the complex
1245
+
1246
+ - ``p`` -- floating point number between 0 and 1 (default: 0.5)
1247
+
1248
+ A random `d`-dimensional simplicial complex on `n` vertices,
1249
+ as defined for example by Meshulam and Wallach [MW2009]_, is
1250
+ constructed as follows: take `n` vertices and include all of
1251
+ the simplices of dimension strictly less than `d`, and then for each
1252
+ possible simplex of dimension `d`, include it with probability `p`.
1253
+
1254
+ EXAMPLES::
1255
+
1256
+ sage: X = simplicial_complexes.RandomComplex(6, 2); X
1257
+ Random 2-dimensional simplicial complex on 6 vertices
1258
+ sage: len(list(X.vertices()))
1259
+ 6
1260
+
1261
+ If `d` is too large (if `d+1 > n`, so that there are no
1262
+ `d`-dimensional simplices), then return the simplicial complex
1263
+ with a single `(n+1)`-dimensional simplex::
1264
+
1265
+ sage: simplicial_complexes.RandomComplex(6, 12)
1266
+ The 5-simplex
1267
+ """
1268
+ if d+1 > n:
1269
+ return Simplex(n-1)
1270
+ else:
1271
+ vertices = range(n)
1272
+ facets = Subsets(vertices, d).list()
1273
+ maybe = Subsets(vertices, d+1)
1274
+ facets.extend([f for f in maybe if random.random() <= p])
1275
+ return UniqueSimplicialComplex(facets,
1276
+ name='Random {}-dimensional simplicial complex on {} vertices'.format(d, n))
1277
+
1278
+
1279
+ def SumComplex(n, A):
1280
+ r"""
1281
+ The sum complexes of Linial, Meshulam, and Rosenthal [LMR2010]_.
1282
+
1283
+ If `k+1` is the cardinality of `A`, then this returns a
1284
+ `k`-dimensional simplicial complex `X_A` with vertices
1285
+ `\ZZ/(n)`, and facets given by all `k+1`-tuples `(x_0, x_1,
1286
+ ..., x_k)` such that the sum `\sum x_i` is in `A`. See the
1287
+ paper by Linial, Meshulam, and Rosenthal [LMR2010]_, in which
1288
+ they prove various results about these complexes; for example,
1289
+ if `n` is prime, then `X_A` is rationally acyclic, and if in
1290
+ addition `A` forms an arithmetic progression in `\ZZ/(n)`,
1291
+ then `X_A` is `\ZZ`-acyclic. Throughout their paper, they
1292
+ assume that `n` and `k` are relatively prime, but the
1293
+ construction makes sense in general.
1294
+
1295
+ In addition to the results from the cited paper, these
1296
+ complexes can have large torsion, given the number of
1297
+ vertices; for example, if `n=10`, and `A=\{0, 1, 2, 3, 6\}`, then
1298
+ `H_3(X_A)` is cyclic of order 2728, and there is a
1299
+ 4-dimensional complex on 13 vertices with `H_3` having a
1300
+ cyclic summand of order
1301
+
1302
+ .. MATH::
1303
+
1304
+ 706565607945 = 3 \cdot 5 \cdot 53 \cdot 79 \cdot 131
1305
+ \cdot 157 \cdot 547.
1306
+
1307
+ See the examples.
1308
+
1309
+ INPUT:
1310
+
1311
+ - ``n`` -- positive integer
1312
+
1313
+ - ``A`` -- a subset of `\ZZ/(n)`
1314
+
1315
+ EXAMPLES::
1316
+
1317
+ sage: S = simplicial_complexes.SumComplex(10, [0, 1, 2, 3, 6]); S
1318
+ Sum complex on vertices Z/10Z associated to {0, 1, 2, 3, 6}
1319
+ sage: S.homology() # needs sage.modules
1320
+ {0: 0, 1: 0, 2: 0, 3: C2728, 4: 0}
1321
+ sage: factor(2728)
1322
+ 2^3 * 11 * 31
1323
+
1324
+ sage: S = simplicial_complexes.SumComplex(11, [0, 1, 3]); S
1325
+ Sum complex on vertices Z/11Z associated to {0, 1, 3}
1326
+ sage: S.homology(1) # needs sage.modules
1327
+ C23
1328
+ sage: S = simplicial_complexes.SumComplex(11, [0, 1, 2, 3, 4, 7]); S
1329
+ Sum complex on vertices Z/11Z associated to {0, 1, 2, 3, 4, 7}
1330
+ sage: S.homology() # long time # needs sage.modules
1331
+ {0: 0, 1: 0, 2: 0, 3: 0, 4: C645679, 5: 0}
1332
+ sage: factor(645679)
1333
+ 23 * 67 * 419
1334
+
1335
+ sage: S = simplicial_complexes.SumComplex(13, [0, 1, 3]); S
1336
+ Sum complex on vertices Z/13Z associated to {0, 1, 3}
1337
+ sage: S.homology(1) # needs sage.modules
1338
+ C159
1339
+ sage: factor(159)
1340
+ 3 * 53
1341
+ sage: S = simplicial_complexes.SumComplex(13, [0, 1, 2, 5]); S
1342
+ Sum complex on vertices Z/13Z associated to {0, 1, 2, 5}
1343
+ sage: S.homology() # long time # needs sage.modules
1344
+ {0: 0, 1: 0, 2: C146989209, 3: 0}
1345
+ sage: factor(1648910295)
1346
+ 3^2 * 5 * 53 * 521 * 1327
1347
+ sage: S = simplicial_complexes.SumComplex(13, [0, 1, 2, 3, 5]); S
1348
+ Sum complex on vertices Z/13Z associated to {0, 1, 2, 3, 5}
1349
+ sage: S.homology() # long time # needs sage.modules
1350
+ {0: 0, 1: 0, 2: 0, 3: C3 x C237 x C706565607945, 4: 0}
1351
+ sage: factor(706565607945) # needs sage.libs.pari
1352
+ 3 * 5 * 53 * 79 * 131 * 157 * 547
1353
+
1354
+ sage: S = simplicial_complexes.SumComplex(17, [0, 1, 4]); S
1355
+ Sum complex on vertices Z/17Z associated to {0, 1, 4}
1356
+ sage: S.homology(1) # needs sage.modules
1357
+ C140183
1358
+ sage: factor(140183)
1359
+ 103 * 1361
1360
+ sage: S = simplicial_complexes.SumComplex(19, [0, 1, 4]); S
1361
+ Sum complex on vertices Z/19Z associated to {0, 1, 4}
1362
+ sage: S.homology(1) # needs sage.modules
1363
+ C5670599
1364
+ sage: factor(5670599)
1365
+ 11 * 191 * 2699
1366
+ sage: S = simplicial_complexes.SumComplex(31, [0, 1, 4]); S
1367
+ Sum complex on vertices Z/31Z associated to {0, 1, 4}
1368
+ sage: S.homology(1) # long time # needs sage.modules
1369
+ C5 x C5 x C5 x C5 x C26951480558170926865
1370
+ sage: factor(26951480558170926865) # needs sage.libs.pari
1371
+ 5 * 311 * 683 * 1117 * 11657 * 1948909
1372
+ """
1373
+ from sage.rings.finite_rings.integer_mod_ring import Integers
1374
+ Zn = Integers(n)
1375
+ A = frozenset([Zn(x) for x in A])
1376
+ facets = []
1377
+ for f in Set(Zn).subsets(len(A)):
1378
+ if sum(f) in A:
1379
+ facets.append(tuple(f))
1380
+ return UniqueSimplicialComplex(facets, name='Sum complex on vertices Z/{}Z associated to {}'.format(n, Set(A)))
1381
+
1382
+
1383
+ def RandomTwoSphere(n):
1384
+ r"""
1385
+ Return a random triangulation of the 2-dimensional sphere with `n`
1386
+ vertices.
1387
+
1388
+ INPUT:
1389
+
1390
+ - ``n`` -- integer
1391
+
1392
+ OUTPUT:
1393
+
1394
+ A random triangulation of the sphere chosen uniformly among
1395
+ the *rooted* triangulations on `n` vertices. Because some
1396
+ triangulations have nontrivial automorphism groups, this may
1397
+ not be equal to the uniform distribution among unrooted
1398
+ triangulations.
1399
+
1400
+ ALGORITHM:
1401
+
1402
+ The algorithm is taken from [PS2006]_, section 2.1.
1403
+
1404
+ Starting from a planar tree (represented by its contour as a
1405
+ sequence of vertices), one first performs local closures, until no
1406
+ one is possible. A local closure amounts to replace in the cyclic
1407
+ contour word a sequence ``in1, in2, in3, lf, in3`` by
1408
+ ``in1, in3``. After all local closures are done, one has reached
1409
+ the partial closure, as in [PS2006]_, figure 5 (a).
1410
+
1411
+ Then one has to perform complete closure by adding two more
1412
+ vertices, in order to reach the situation of [PS2006]_, figure 5
1413
+ (b). For this, it is necessary to find inside the final contour
1414
+ one of the two subsequences ``lf, in, lf``.
1415
+
1416
+ At every step of the algorithm, newly created triangles are added
1417
+ in a simplicial complex.
1418
+
1419
+ This algorithm is implemented in
1420
+ :meth:`~sage.graphs.generators.random.RandomTriangulation`, which
1421
+ creates an embedded graph. The triangles of the simplicial
1422
+ complex are recovered from this embedded graph.
1423
+
1424
+ EXAMPLES::
1425
+
1426
+ sage: G = simplicial_complexes.RandomTwoSphere(6); G
1427
+ Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and 8 facets
1428
+ sage: G.homology() # needs sage.modules
1429
+ {0: 0, 1: 0, 2: Z}
1430
+ sage: G.is_pure()
1431
+ True
1432
+ sage: fg = G.flip_graph(); fg
1433
+ Graph on 8 vertices
1434
+ sage: fg.is_planar() and fg.is_regular(3) # needs planarity
1435
+ True
1436
+ """
1437
+ from sage.graphs.generators.random import RandomTriangulation
1438
+
1439
+ graph = RandomTriangulation(n)
1440
+
1441
+ graph = graph.relabel(inplace=False)
1442
+ triangles = [(u, v, w) for u, L in graph._embedding.items()
1443
+ for v, w in zip(L, L[1:] + [L[0]]) if u < v and u < w]
1444
+
1445
+ return SimplicialComplex(triangles, maximality_check=False)
1446
+
1447
+
1448
+ def ShiftedComplex(generators):
1449
+ r"""
1450
+ Return the smallest shifted simplicial complex containing ``generators``
1451
+ as faces.
1452
+
1453
+ Let `V` be a set of vertices equipped with a total order. The
1454
+ 'componentwise partial ordering' on k-subsets of `V` is defined as
1455
+ follows: if `A = \{a_1 < \cdots < a_k\}` and `B = \{b_1 < \cdots < b_k\}`,
1456
+ then `A \leq_C B` iff `a_i \leq b_i` for all `i`. A simplicial complex
1457
+ `X` on vertex set `[n]` is *shifted* if its faces form an order ideal
1458
+ under the componentwise partial ordering, i.e., if `B \in X` and
1459
+ `A \leq_C B` then `A \in X`. Shifted complexes of dimension 1 are also
1460
+ known as threshold graphs.
1461
+
1462
+ .. NOTE::
1463
+
1464
+ This method assumes that `V` consists of positive integers
1465
+ with the natural ordering.
1466
+
1467
+ INPUT:
1468
+
1469
+ - ``generators`` -- list of generators of the order ideal, which may
1470
+ be lists, tuples or simplices
1471
+
1472
+ EXAMPLES::
1473
+
1474
+ sage: # needs sage.combinat
1475
+ sage: X = simplicial_complexes.ShiftedComplex([Simplex([1, 6]), (2, 4), [8]])
1476
+ sage: sorted(X.facets())
1477
+ [(1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 3), (2, 4), (7,), (8,)]
1478
+ sage: X = simplicial_complexes.ShiftedComplex([[2, 3, 5]])
1479
+ sage: sorted(X.facets())
1480
+ [(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 3, 4), (1, 3, 5), (2, 3, 4), (2, 3, 5)]
1481
+ sage: X = simplicial_complexes.ShiftedComplex([[1, 3, 5], [2, 6]])
1482
+ sage: sorted(X.facets())
1483
+ [(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 3, 4), (1, 3, 5), (1, 6), (2, 6)]
1484
+ """
1485
+ from sage.combinat.partition import Partitions
1486
+ Facets = []
1487
+ for G in generators:
1488
+ G = sorted(G, reverse=True)
1489
+ L = len(G)
1490
+ for k in range(L * (L+1) // 2, sum(G) + 1):
1491
+ for P in Partitions(k, length=L, max_slope=-1, outer=G):
1492
+ Facets.append(list(reversed(P)))
1493
+ return SimplicialComplex(Facets)
1494
+
1495
+
1496
+ def RudinBall():
1497
+ r"""
1498
+ Return the non-shellable ball constructed by Rudin.
1499
+
1500
+ This complex is a non-shellable triangulation of the 3-ball
1501
+ with 14 vertices and 41 facets, constructed by Rudin in
1502
+ [Rud1958]_.
1503
+
1504
+ EXAMPLES::
1505
+
1506
+ sage: R = simplicial_complexes.RudinBall(); R
1507
+ Rudin ball
1508
+ sage: R.f_vector()
1509
+ [1, 14, 66, 94, 41]
1510
+ sage: R.homology() # needs sage.modules
1511
+ {0: 0, 1: 0, 2: 0, 3: 0}
1512
+ sage: R.is_cohen_macaulay() # needs sage.modules
1513
+ True
1514
+ """
1515
+ return UniqueSimplicialComplex(
1516
+ [[1, 9, 2, 5], [1, 10, 2, 5], [1, 10, 5, 11], [1, 10, 7, 11], [1, 13, 5, 11],
1517
+ [1, 13, 7, 11], [2, 10, 3, 6], [2, 11, 3, 6], [2, 11, 6, 12], [2, 11, 8, 12],
1518
+ [2, 14, 6, 12], [2, 14, 8, 12], [3, 11, 4, 7], [3, 12, 4, 7], [3, 12, 5, 9],
1519
+ [3, 12, 7, 9], [3, 13, 5, 9], [3, 13, 7, 9], [4, 9, 1, 8], [4, 9, 6, 10],
1520
+ [4, 9, 8, 10], [4, 12, 1, 8], [4, 14, 6, 10], [4, 14, 8, 10], [9, 10, 2, 5],
1521
+ [9, 10, 2, 6], [9, 10, 5, 11], [9, 10, 11, 12], [9, 13, 5, 11], [10, 11, 3, 6],
1522
+ [10, 11, 3, 7], [10, 11, 6, 12], [10, 14, 6, 12], [11, 12, 4, 7], [11, 12, 4, 8],
1523
+ [11, 12, 7, 9], [11, 13, 7, 9], [12, 9, 1, 5], [12, 9, 1, 8], [12, 9, 8, 10],
1524
+ [12, 14, 8, 10]],
1525
+ name="Rudin ball"
1526
+ )
1527
+
1528
+
1529
+ def ZieglerBall():
1530
+ r"""
1531
+ Return the non-shellable ball constructed by Ziegler.
1532
+
1533
+ This complex is a non-shellable triangulation of the 3-ball
1534
+ with 10 vertices and 21 facets, constructed by Ziegler in
1535
+ [Zie1998]_ and the smallest such complex known.
1536
+
1537
+ EXAMPLES::
1538
+
1539
+ sage: Z = simplicial_complexes.ZieglerBall(); Z
1540
+ Ziegler ball
1541
+ sage: Z.f_vector()
1542
+ [1, 10, 38, 50, 21]
1543
+ sage: Z.homology() # needs sage.modules
1544
+ {0: 0, 1: 0, 2: 0, 3: 0}
1545
+ sage: Z.is_cohen_macaulay() # needs sage.modules
1546
+ True
1547
+ """
1548
+
1549
+ return UniqueSimplicialComplex(
1550
+ [[1, 2, 3, 4], [1, 2, 5, 6], [1, 5, 6, 9], [2, 5, 6, 0], [3, 6, 7, 8], [4, 5, 7, 8],
1551
+ [2, 3, 6, 7], [1, 6, 2, 9], [2, 6, 7, 0], [3, 2, 4, 8], [4, 1, 3, 7], [3, 4, 7, 8],
1552
+ [1, 2, 4, 9], [2, 7, 3, 0], [3, 2, 6, 8], [4, 1, 5, 7], [4, 1, 8, 5], [1, 4, 8, 9],
1553
+ [2, 3, 1, 0], [1, 8, 5, 9], [2, 1, 5, 0]],
1554
+ name="Ziegler ball")
1555
+
1556
+
1557
+ def DunceHat():
1558
+ r"""
1559
+ Return the minimal triangulation of the dunce hat given by Hachimori
1560
+ [Hac2016]_.
1561
+
1562
+ This is a standard example of a space that is contractible
1563
+ but not collapsible.
1564
+
1565
+ EXAMPLES::
1566
+
1567
+ sage: D = simplicial_complexes.DunceHat(); D
1568
+ Minimal triangulation of the dunce hat
1569
+ sage: D.f_vector()
1570
+ [1, 8, 24, 17]
1571
+ sage: D.homology() # needs sage.modules
1572
+ {0: 0, 1: 0, 2: 0}
1573
+ sage: D.is_cohen_macaulay() # needs sage.modules
1574
+ True
1575
+ """
1576
+ return UniqueSimplicialComplex(
1577
+ [[1, 3, 5], [2, 3, 5], [2, 4, 5], [1, 2, 4], [1, 3, 4], [3, 4, 8],
1578
+ [1, 2, 8], [1, 7, 8], [1, 2, 7], [2, 3, 7], [3, 6, 7], [1, 3, 6],
1579
+ [1, 5, 6], [4, 5, 6], [4, 6, 8], [6, 7, 8], [2, 3, 8]],
1580
+ name="Minimal triangulation of the dunce hat")
1581
+
1582
+
1583
+ def FareyMap(p):
1584
+ r"""
1585
+ Return a discrete surface associated with `PSL(2, \GF(p))`.
1586
+
1587
+ INPUT:
1588
+
1589
+ - ``p`` -- a prime number
1590
+
1591
+ The vertices are the nonzero pairs `(x,y)` in `\GF(p)^2` modulo
1592
+ the identification of `(-x, -y)` with `(x,y)`.
1593
+
1594
+ The triangles are the images of the base triangle ((1,0),(0,1),(1,1))
1595
+ under the action of `PSL(2, \GF(p))`.
1596
+
1597
+ For `p = 3`, the result is a tetrahedron, for `p = 5` an icosahedron,
1598
+ and for `p = 7` a triangulation of the Klein quartic of genus `3`.
1599
+
1600
+ As a Riemann surface, this is the quotient of the upper half plane
1601
+ by the principal congruence subgroup `\Gamma(p)`.
1602
+
1603
+ EXAMPLES::
1604
+
1605
+ sage: S5 = simplicial_complexes.FareyMap(5); S5 # needs sage.groups
1606
+ Simplicial complex with 12 vertices and 20 facets
1607
+ sage: S5.automorphism_group().cardinality() # needs sage.groups
1608
+ 120
1609
+
1610
+ sage: S7 = simplicial_complexes.FareyMap(7); S7 # needs sage.groups
1611
+ Simplicial complex with 24 vertices and 56 facets
1612
+ sage: S7.f_vector() # needs sage.groups
1613
+ [1, 24, 84, 56]
1614
+
1615
+ REFERENCES:
1616
+
1617
+ - [ISS2019] Ioannis Ivrissimtzis, David Singerman and James Strudwick,
1618
+ *From Farey Fractions to the Klein Quartic and Beyond*.
1619
+ :arxiv:`1909.08568`
1620
+ """
1621
+ from sage.combinat.permutation import Permutation
1622
+ from sage.groups.perm_gps.permgroup import PermutationGroup
1623
+ from sage.matrix.constructor import matrix
1624
+ from sage.modules.free_module_element import vector
1625
+ from sage.rings.finite_rings.finite_field_constructor import GF
1626
+ from sage.libs.gap.libgap import libgap
1627
+
1628
+ def normalise(pair):
1629
+ x, y = pair
1630
+ if x != 0 and p - x < x:
1631
+ return ((-x) % p, (-y) % p)
1632
+ elif x == 0 and p - y < y:
1633
+ return (0, (-y) % p)
1634
+ return (x, y)
1635
+
1636
+ points = [(x, y) for x in range(p) for y in range(p)
1637
+ if (x, y) != (0, 0) and
1638
+ (x != 0 and p - x >= x or (x == 0 and p - y >= y))]
1639
+ convert = {pt: i + 1 for i, pt in enumerate(points)}
1640
+
1641
+ F = GF(p)
1642
+ S = matrix(F, 2, 2, [0, -1, 1, 0])
1643
+ T = matrix(F, 2, 2, [1, 1, 0, 1])
1644
+ perm_S = Permutation([convert[normalise(S * vector(pt))]
1645
+ for pt in points])
1646
+ perm_T = Permutation([convert[normalise(T * vector(pt))]
1647
+ for pt in points])
1648
+ group = PermutationGroup([perm_S, perm_T])
1649
+ triangle = [convert[normalise(pt)] for pt in [(1, 0), (0, 1), (1, 1)]]
1650
+ triangle = libgap.Set(triangle)
1651
+ triangles = libgap.Orbit(group, triangle, libgap.OnSets).sage()
1652
+ return SimplicialComplex(triangles)
1653
+
1654
+
1655
+ def GenusSix():
1656
+ """
1657
+ Return a triangulated surface of genus 6.
1658
+
1659
+ This is triangulated with 12 vertices, 66 edges and 44 faces. Each
1660
+ vertex is neighbour to all other vertices.
1661
+
1662
+ It appears as number `58` in the classification of Altshuler,
1663
+ Bokowski and Schuchert in [ABS96]_, where it is the unique surface
1664
+ with the largest symmetry group, of order 12. This article refers
1665
+ for this surface to Ringel.
1666
+
1667
+ EXAMPLES::
1668
+
1669
+ sage: S = simplicial_complexes.GenusSix()
1670
+ sage: S.automorphism_group().cardinality() # needs sage.groups
1671
+ 12
1672
+ sage: S.betti() # needs sage.modules
1673
+ {0: 1, 1: 12, 2: 1}
1674
+ sage: S.f_vector()
1675
+ [1, 12, 66, 44]
1676
+
1677
+ REFERENCES:
1678
+
1679
+ .. [ABS96] Amos Altshule, Jürgen Bokowski and Peter Schuchert,
1680
+ *Neighborly 2-Manifolds with 12 Vertices*,
1681
+ Journal of Combinatorial Theory, Series A, 75, 148-162 (1996),
1682
+ :doi:`10.1006/jcta.1996.0069`
1683
+ """
1684
+ L = ["014", "018", "023", "027", "036", "049",
1685
+ "056", "05b", "07a", "08a", "09b",
1686
+ "125", "126", "137", "139", "147", "15a",
1687
+ "16b", "18b", "19a", "23b", "248",
1688
+ "24a", "258", "269", "279", "2ab", "345",
1689
+ "34b", "35a", "367", "389", "38a",
1690
+ "459", "46a", "46b", "478", "568", "579",
1691
+ "57b", "67a", "689", "78b", "9ab"]
1692
+ return SimplicialComplex([list(w) for w in L])