passagemath-graphs 10.6.1rc1__cp310-cp310-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 (260) hide show
  1. passagemath_graphs-10.6.1rc1.dist-info/METADATA +292 -0
  2. passagemath_graphs-10.6.1rc1.dist-info/RECORD +260 -0
  3. passagemath_graphs-10.6.1rc1.dist-info/WHEEL +5 -0
  4. passagemath_graphs-10.6.1rc1.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 +2723 -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 +124 -0
  15. sage/combinat/cluster_algebra_quiver/mutation_class.py +625 -0
  16. sage/combinat/cluster_algebra_quiver/mutation_type.py +1555 -0
  17. sage/combinat/cluster_algebra_quiver/quiver.py +2290 -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 +530 -0
  25. sage/combinat/designs/database.py +5615 -0
  26. sage/combinat/designs/design_catalog.py +122 -0
  27. sage/combinat/designs/designs_pyx.cpython-310-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-310-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-310-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 +581 -0
  40. sage/combinat/designs/orthogonal_arrays.py +2244 -0
  41. sage/combinat/designs/orthogonal_arrays_build_recursive.py +1780 -0
  42. sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-310-aarch64-linux-gnu.so +0 -0
  43. sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +967 -0
  44. sage/combinat/designs/resolvable_bibd.py +815 -0
  45. sage/combinat/designs/steiner_quadruple_systems.py +1306 -0
  46. sage/combinat/designs/subhypergraph_search.cpython-310-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/bubble_shuffle.py +247 -0
  57. sage/combinat/posets/cartesian_product.py +493 -0
  58. sage/combinat/posets/d_complete.py +182 -0
  59. sage/combinat/posets/elements.py +273 -0
  60. sage/combinat/posets/forest.py +30 -0
  61. sage/combinat/posets/hasse_cython.cpython-310-aarch64-linux-gnu.so +0 -0
  62. sage/combinat/posets/hasse_cython.pyx +174 -0
  63. sage/combinat/posets/hasse_diagram.py +3672 -0
  64. sage/combinat/posets/hochschild_lattice.py +158 -0
  65. sage/combinat/posets/incidence_algebras.py +794 -0
  66. sage/combinat/posets/lattices.py +5117 -0
  67. sage/combinat/posets/linear_extension_iterator.cpython-310-aarch64-linux-gnu.so +0 -0
  68. sage/combinat/posets/linear_extension_iterator.pyx +292 -0
  69. sage/combinat/posets/linear_extensions.py +1037 -0
  70. sage/combinat/posets/mobile.py +275 -0
  71. sage/combinat/posets/moebius_algebra.py +776 -0
  72. sage/combinat/posets/poset_examples.py +2178 -0
  73. sage/combinat/posets/posets.py +9360 -0
  74. sage/combinat/rooted_tree.py +1070 -0
  75. sage/combinat/shard_order.py +239 -0
  76. sage/combinat/tamari_lattices.py +384 -0
  77. sage/combinat/yang_baxter_graph.py +923 -0
  78. sage/databases/all__sagemath_graphs.py +1 -0
  79. sage/databases/knotinfo_db.py +1231 -0
  80. sage/ext_data/all__sagemath_graphs.py +1 -0
  81. sage/ext_data/graphs/graph_plot_js.html +330 -0
  82. sage/ext_data/kenzo/CP2.txt +45 -0
  83. sage/ext_data/kenzo/CP3.txt +349 -0
  84. sage/ext_data/kenzo/CP4.txt +4774 -0
  85. sage/ext_data/kenzo/README.txt +49 -0
  86. sage/ext_data/kenzo/S4.txt +20 -0
  87. sage/graphs/all.py +42 -0
  88. sage/graphs/asteroidal_triples.cpython-310-aarch64-linux-gnu.so +0 -0
  89. sage/graphs/asteroidal_triples.pyx +320 -0
  90. sage/graphs/base/all.py +1 -0
  91. sage/graphs/base/boost_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  92. sage/graphs/base/boost_graph.pxd +106 -0
  93. sage/graphs/base/boost_graph.pyx +3045 -0
  94. sage/graphs/base/c_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  95. sage/graphs/base/c_graph.pxd +106 -0
  96. sage/graphs/base/c_graph.pyx +5096 -0
  97. sage/graphs/base/dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  98. sage/graphs/base/dense_graph.pxd +28 -0
  99. sage/graphs/base/dense_graph.pyx +801 -0
  100. sage/graphs/base/graph_backends.cpython-310-aarch64-linux-gnu.so +0 -0
  101. sage/graphs/base/graph_backends.pxd +5 -0
  102. sage/graphs/base/graph_backends.pyx +797 -0
  103. sage/graphs/base/overview.py +85 -0
  104. sage/graphs/base/sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  105. sage/graphs/base/sparse_graph.pxd +90 -0
  106. sage/graphs/base/sparse_graph.pyx +1653 -0
  107. sage/graphs/base/static_dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  108. sage/graphs/base/static_dense_graph.pxd +5 -0
  109. sage/graphs/base/static_dense_graph.pyx +1032 -0
  110. sage/graphs/base/static_sparse_backend.cpython-310-aarch64-linux-gnu.so +0 -0
  111. sage/graphs/base/static_sparse_backend.pxd +27 -0
  112. sage/graphs/base/static_sparse_backend.pyx +1583 -0
  113. sage/graphs/base/static_sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  114. sage/graphs/base/static_sparse_graph.pxd +37 -0
  115. sage/graphs/base/static_sparse_graph.pyx +1375 -0
  116. sage/graphs/bipartite_graph.py +2732 -0
  117. sage/graphs/centrality.cpython-310-aarch64-linux-gnu.so +0 -0
  118. sage/graphs/centrality.pyx +1038 -0
  119. sage/graphs/cographs.py +519 -0
  120. sage/graphs/comparability.cpython-310-aarch64-linux-gnu.so +0 -0
  121. sage/graphs/comparability.pyx +851 -0
  122. sage/graphs/connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
  123. sage/graphs/connectivity.pxd +157 -0
  124. sage/graphs/connectivity.pyx +4813 -0
  125. sage/graphs/convexity_properties.cpython-310-aarch64-linux-gnu.so +0 -0
  126. sage/graphs/convexity_properties.pxd +16 -0
  127. sage/graphs/convexity_properties.pyx +870 -0
  128. sage/graphs/digraph.py +4754 -0
  129. sage/graphs/digraph_generators.py +1993 -0
  130. sage/graphs/distances_all_pairs.cpython-310-aarch64-linux-gnu.so +0 -0
  131. sage/graphs/distances_all_pairs.pxd +12 -0
  132. sage/graphs/distances_all_pairs.pyx +2938 -0
  133. sage/graphs/domination.py +1363 -0
  134. sage/graphs/dot2tex_utils.py +100 -0
  135. sage/graphs/edge_connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
  136. sage/graphs/edge_connectivity.pyx +1215 -0
  137. sage/graphs/generators/all.py +1 -0
  138. sage/graphs/generators/basic.py +1769 -0
  139. sage/graphs/generators/chessboard.py +538 -0
  140. sage/graphs/generators/classical_geometries.py +1611 -0
  141. sage/graphs/generators/degree_sequence.py +235 -0
  142. sage/graphs/generators/distance_regular.cpython-310-aarch64-linux-gnu.so +0 -0
  143. sage/graphs/generators/distance_regular.pyx +2846 -0
  144. sage/graphs/generators/families.py +4759 -0
  145. sage/graphs/generators/intersection.py +565 -0
  146. sage/graphs/generators/platonic_solids.py +262 -0
  147. sage/graphs/generators/random.py +2623 -0
  148. sage/graphs/generators/smallgraphs.py +5741 -0
  149. sage/graphs/generators/world_map.py +724 -0
  150. sage/graphs/generic_graph.py +26867 -0
  151. sage/graphs/generic_graph_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
  152. sage/graphs/generic_graph_pyx.pxd +34 -0
  153. sage/graphs/generic_graph_pyx.pyx +1673 -0
  154. sage/graphs/genus.cpython-310-aarch64-linux-gnu.so +0 -0
  155. sage/graphs/genus.pyx +622 -0
  156. sage/graphs/graph.py +9645 -0
  157. sage/graphs/graph_coloring.cpython-310-aarch64-linux-gnu.so +0 -0
  158. sage/graphs/graph_coloring.pyx +2284 -0
  159. sage/graphs/graph_database.py +1177 -0
  160. sage/graphs/graph_decompositions/all.py +1 -0
  161. sage/graphs/graph_decompositions/bandwidth.cpython-310-aarch64-linux-gnu.so +0 -0
  162. sage/graphs/graph_decompositions/bandwidth.pyx +428 -0
  163. sage/graphs/graph_decompositions/clique_separators.cpython-310-aarch64-linux-gnu.so +0 -0
  164. sage/graphs/graph_decompositions/clique_separators.pyx +616 -0
  165. sage/graphs/graph_decompositions/cutwidth.cpython-310-aarch64-linux-gnu.so +0 -0
  166. sage/graphs/graph_decompositions/cutwidth.pyx +753 -0
  167. sage/graphs/graph_decompositions/fast_digraph.cpython-310-aarch64-linux-gnu.so +0 -0
  168. sage/graphs/graph_decompositions/fast_digraph.pxd +13 -0
  169. sage/graphs/graph_decompositions/fast_digraph.pyx +212 -0
  170. sage/graphs/graph_decompositions/graph_products.cpython-310-aarch64-linux-gnu.so +0 -0
  171. sage/graphs/graph_decompositions/graph_products.pyx +508 -0
  172. sage/graphs/graph_decompositions/modular_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
  173. sage/graphs/graph_decompositions/modular_decomposition.pxd +27 -0
  174. sage/graphs/graph_decompositions/modular_decomposition.pyx +1536 -0
  175. sage/graphs/graph_decompositions/slice_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
  176. sage/graphs/graph_decompositions/slice_decomposition.pxd +18 -0
  177. sage/graphs/graph_decompositions/slice_decomposition.pyx +1106 -0
  178. sage/graphs/graph_decompositions/tree_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
  179. sage/graphs/graph_decompositions/tree_decomposition.pxd +17 -0
  180. sage/graphs/graph_decompositions/tree_decomposition.pyx +1996 -0
  181. sage/graphs/graph_decompositions/vertex_separation.cpython-310-aarch64-linux-gnu.so +0 -0
  182. sage/graphs/graph_decompositions/vertex_separation.pxd +5 -0
  183. sage/graphs/graph_decompositions/vertex_separation.pyx +1963 -0
  184. sage/graphs/graph_editor.py +82 -0
  185. sage/graphs/graph_generators.py +3314 -0
  186. sage/graphs/graph_generators_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
  187. sage/graphs/graph_generators_pyx.pyx +95 -0
  188. sage/graphs/graph_input.py +812 -0
  189. sage/graphs/graph_latex.py +2064 -0
  190. sage/graphs/graph_list.py +410 -0
  191. sage/graphs/graph_plot.py +1756 -0
  192. sage/graphs/graph_plot_js.py +338 -0
  193. sage/graphs/hyperbolicity.cpython-310-aarch64-linux-gnu.so +0 -0
  194. sage/graphs/hyperbolicity.pyx +1704 -0
  195. sage/graphs/hypergraph_generators.py +364 -0
  196. sage/graphs/independent_sets.cpython-310-aarch64-linux-gnu.so +0 -0
  197. sage/graphs/independent_sets.pxd +13 -0
  198. sage/graphs/independent_sets.pyx +402 -0
  199. sage/graphs/isgci.py +1033 -0
  200. sage/graphs/isoperimetric_inequalities.cpython-310-aarch64-linux-gnu.so +0 -0
  201. sage/graphs/isoperimetric_inequalities.pyx +489 -0
  202. sage/graphs/line_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  203. sage/graphs/line_graph.pyx +743 -0
  204. sage/graphs/lovasz_theta.py +77 -0
  205. sage/graphs/matching.py +1633 -0
  206. sage/graphs/matching_covered_graph.py +3590 -0
  207. sage/graphs/orientations.py +1489 -0
  208. sage/graphs/partial_cube.py +459 -0
  209. sage/graphs/path_enumeration.cpython-310-aarch64-linux-gnu.so +0 -0
  210. sage/graphs/path_enumeration.pyx +2040 -0
  211. sage/graphs/pq_trees.py +1129 -0
  212. sage/graphs/print_graphs.py +201 -0
  213. sage/graphs/schnyder.py +865 -0
  214. sage/graphs/spanning_tree.cpython-310-aarch64-linux-gnu.so +0 -0
  215. sage/graphs/spanning_tree.pyx +1457 -0
  216. sage/graphs/strongly_regular_db.cpython-310-aarch64-linux-gnu.so +0 -0
  217. sage/graphs/strongly_regular_db.pyx +3340 -0
  218. sage/graphs/traversals.cpython-310-aarch64-linux-gnu.so +0 -0
  219. sage/graphs/traversals.pxd +9 -0
  220. sage/graphs/traversals.pyx +1872 -0
  221. sage/graphs/trees.cpython-310-aarch64-linux-gnu.so +0 -0
  222. sage/graphs/trees.pxd +15 -0
  223. sage/graphs/trees.pyx +310 -0
  224. sage/graphs/tutte_polynomial.py +713 -0
  225. sage/graphs/views.cpython-310-aarch64-linux-gnu.so +0 -0
  226. sage/graphs/views.pyx +794 -0
  227. sage/graphs/weakly_chordal.cpython-310-aarch64-linux-gnu.so +0 -0
  228. sage/graphs/weakly_chordal.pyx +604 -0
  229. sage/groups/all__sagemath_graphs.py +1 -0
  230. sage/groups/perm_gps/all__sagemath_graphs.py +1 -0
  231. sage/groups/perm_gps/partn_ref/all__sagemath_graphs.py +1 -0
  232. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-310-aarch64-linux-gnu.so +0 -0
  233. sage/groups/perm_gps/partn_ref/refinement_graphs.pxd +38 -0
  234. sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +1666 -0
  235. sage/knots/all.py +6 -0
  236. sage/knots/free_knotinfo_monoid.py +507 -0
  237. sage/knots/gauss_code.py +291 -0
  238. sage/knots/knot.py +682 -0
  239. sage/knots/knot_table.py +284 -0
  240. sage/knots/knotinfo.py +2900 -0
  241. sage/knots/link.py +4715 -0
  242. sage/sandpiles/all.py +13 -0
  243. sage/sandpiles/examples.py +225 -0
  244. sage/sandpiles/sandpile.py +6365 -0
  245. sage/topology/all.py +22 -0
  246. sage/topology/cell_complex.py +1214 -0
  247. sage/topology/cubical_complex.py +1976 -0
  248. sage/topology/delta_complex.py +1806 -0
  249. sage/topology/filtered_simplicial_complex.py +744 -0
  250. sage/topology/moment_angle_complex.py +823 -0
  251. sage/topology/simplicial_complex.py +5160 -0
  252. sage/topology/simplicial_complex_catalog.py +92 -0
  253. sage/topology/simplicial_complex_examples.py +1680 -0
  254. sage/topology/simplicial_complex_homset.py +205 -0
  255. sage/topology/simplicial_complex_morphism.py +836 -0
  256. sage/topology/simplicial_set.py +4102 -0
  257. sage/topology/simplicial_set_catalog.py +55 -0
  258. sage/topology/simplicial_set_constructions.py +2954 -0
  259. sage/topology/simplicial_set_examples.py +865 -0
  260. sage/topology/simplicial_set_morphism.py +1464 -0
@@ -0,0 +1,823 @@
1
+ # sage_setup: distribution = sagemath-graphs
2
+ """
3
+ Moment-angle complexes
4
+
5
+ AUTHORS:
6
+
7
+ - Ognjen Petrov (2023-06-25): initial version
8
+ """
9
+
10
+ # ****************************************************************************
11
+ # Copyright (C) 2023 Ognjen Petrov <ognjenpetrov@yahoo.com>
12
+ #
13
+ # This program is free software: you can redistribute it and/or modify
14
+ # it under the terms of the GNU General Public License as published by
15
+ # the Free Software Foundation, either version 2 of the License, or
16
+ # (at your option) any later version.
17
+ # https://www.gnu.org/licenses/
18
+ # ****************************************************************************
19
+ from itertools import combinations
20
+
21
+ from sage.categories.fields import Fields
22
+ from sage.misc.cachefunc import cached_method
23
+ from sage.misc.lazy_attribute import lazy_attribute
24
+ from sage.misc.lazy_import import lazy_import
25
+ from sage.rings.integer_ring import ZZ
26
+ from sage.rings.rational_field import QQ
27
+ from sage.structure.sage_object import SageObject
28
+ from sage.structure.unique_representation import UniqueRepresentation
29
+ from sage.topology import simplicial_complex_catalog as simplicial_complexes
30
+ from sage.topology.cubical_complex import CubicalComplex, cubical_complexes
31
+ from sage.topology.simplicial_complex import SimplicialComplex, copy
32
+
33
+ lazy_import('sage.homology.homology_group', 'HomologyGroup')
34
+
35
+
36
+ def _cubical_complex_union(c1, c2):
37
+ """
38
+ Return the union of cubical complexes.
39
+
40
+ This method returns a cubical complex whose set of maximal faces
41
+ is the union of sets of maximal faces of ``c1`` and ``c2``.
42
+
43
+ INPUT:
44
+
45
+ - ``c1``, ``c2`` -- a cubical complex
46
+
47
+ OUTPUT: the union of cubical complexes ``c1`` and ``c2``
48
+
49
+ .. WARNING::
50
+
51
+ This is regular union, not disjoint union. One should be careful
52
+ with the nomenclature of the vertices.
53
+
54
+ EXAMPLES::
55
+
56
+ sage: from sage.topology.moment_angle_complex import (
57
+ ....: _cubical_complex_union as union
58
+ ....: )
59
+ sage: C1 = CubicalComplex([([0,0], [2,3]), ([0,1], [3,3]),
60
+ ....: ([0,1], [2,2]), ([1,1], [2,3])]); C1
61
+ Cubical complex with 4 vertices and 8 cubes
62
+ sage: C2 = CubicalComplex([([0,0], [2,3]), ([0,1], [3,3]),
63
+ ....: ([0,1], [2,2]), ([2,2], [2,3])]); C2
64
+ Cubical complex with 6 vertices and 10 cubes
65
+ sage: union(C1, C2)
66
+ Cubical complex with 6 vertices and 11 cubes
67
+ sage: union(C1, C1) == C1
68
+ True
69
+ """
70
+ facets = list(c1.maximal_cells())
71
+ facets.extend(c2.maximal_cells())
72
+ return CubicalComplex(facets)
73
+
74
+
75
+ class MomentAngleComplex(UniqueRepresentation, SageObject):
76
+ r"""
77
+ A moment-angle complex.
78
+
79
+ Given a simplicial complex `K`, with a set of vertices
80
+ `V = \{v_1, v_2, \ldots, v_n\}`, a moment-angle complex over `K` is a
81
+ topological space `Z`, which is a union of `X_{\sigma}`, where
82
+ `\sigma \in K`, and `X_{\sigma} = Y_{v_1} \times Y_{v_2} \times \cdots
83
+ \times Y_{v_n}` and `Y_{v_i}` is a 2-disk (a 2-simplex) if
84
+ `v_i \in \sigma` , or a 1-sphere otherwise.
85
+
86
+ .. MATH::
87
+
88
+ Y_{v_i} =
89
+ \begin{cases}
90
+ D^2, &v_i \in \sigma,\\
91
+ S^1, &v_i \notin \sigma.
92
+ \end{cases}
93
+
94
+ .. NOTE::
95
+
96
+ The mentioned union is not a disjoint union of topological spaces.
97
+ The unit disks and the unit spheres are considered subsets of `\CC`,
98
+ so the union is just a normal union of subsets of `\CC^n`.
99
+
100
+ Here we view moment-angle complexes as cubical complexes and
101
+ try to compute mostly things which would not require computing
102
+ the moment-angle complex itself, but rather work with the
103
+ corresponding simplicial complex.
104
+
105
+ .. NOTE::
106
+
107
+ One of the more useful properties will be the
108
+ :meth:`bigraded Betti numbers
109
+ <sage.topology.simplicial_complex.bigraded_betti_numbers>`,
110
+ and the underlying theorem which makes this possible is Hochter's
111
+ formula, which can be found on page 104 of [BP2014]_.
112
+
113
+ INPUT:
114
+
115
+ - ``simplicial_complex`` -- an instance of ``SimplicialComplex``,
116
+ or an object from which an instance of ``SimplicialComplex`` can be
117
+ created (e.g., list of facets), which represents the associated
118
+ simplicial complex over which this moment-angle complex is created
119
+
120
+ EXAMPLES::
121
+
122
+ sage: MomentAngleComplex([[1,2,3], [2,4], [3,4]])
123
+ Moment-angle complex of Simplicial complex with vertex set
124
+ (1, 2, 3, 4) and facets {(2, 4), (3, 4), (1, 2, 3)}
125
+ sage: X = SimplicialComplex([[0,1], [1,2], [1,3], [2,3]])
126
+ sage: Z = MomentAngleComplex(X); Z
127
+ Moment-angle complex of Simplicial complex with vertex set
128
+ (0, 1, 2, 3) and facets {(0, 1), (1, 2), (1, 3), (2, 3)}
129
+ sage: M = MomentAngleComplex([[1], [2]]); M
130
+ Moment-angle complex of Simplicial complex with vertex set
131
+ (1, 2) and facets {(1,), (2,)}
132
+
133
+ We can perform a number of operations, such as find the dimension or
134
+ compute the homology::
135
+
136
+ sage: M.homology() # needs sage.modules
137
+ {0: 0, 1: 0, 2: 0, 3: Z}
138
+ sage: Z.dimension()
139
+ 6
140
+ sage: Z.homology() # needs sage.modules
141
+ {0: 0, 1: 0, 2: 0, 3: Z x Z, 4: Z, 5: Z, 6: Z}
142
+
143
+ If the associated simplicial complex is an `n`-simplex, then the
144
+ corresponding moment-angle complex is a polydisc (a complex ball) of
145
+ complex dimension `n+1`::
146
+
147
+ sage: Z = MomentAngleComplex([[0, 1, 2]]); Z
148
+ Moment-angle complex of Simplicial complex with vertex set (0, 1, 2)
149
+ and facets {(0, 1, 2)}
150
+
151
+ This can be seen by viewing the components used in the construction
152
+ of this moment-angle complex by calling :meth:`components()`::
153
+
154
+ sage: Z.components()
155
+ {(0, 1, 2): [The 2-simplex, The 2-simplex, The 2-simplex]}
156
+
157
+ If the associated simplicial complex is a disjoint union of 2 points,
158
+ then the corresponding moment-angle complex is homeomorphic to a boundary
159
+ of a 3-sphere::
160
+
161
+ sage: Z = MomentAngleComplex([[0], [1]]); Z
162
+ Moment-angle complex of Simplicial complex with vertex set
163
+ (0, 1) and facets {(0,), (1,)}
164
+ sage: dict(sorted(Z.components().items()))
165
+ {(0,): [The 2-simplex, Minimal triangulation of the 1-sphere],
166
+ (1,): [Minimal triangulation of the 1-sphere, The 2-simplex]}
167
+
168
+ The moment-angle complex passes all the tests of the test suite relative
169
+ to its category::
170
+
171
+ sage: TestSuite(Z).run()
172
+ """
173
+ @staticmethod
174
+ def __classcall_private__(cls, simplicial_complex):
175
+ """
176
+ Normalize input to ensure a unique representation.
177
+
178
+ TESTS::
179
+
180
+ sage: Z = MomentAngleComplex([[0,2], [1,2,3]])
181
+ sage: W = MomentAngleComplex([[0,2], [1,2,3]])
182
+ sage: Z is W
183
+ True
184
+ sage: Z is MomentAngleComplex(Z)
185
+ True
186
+ """
187
+ if simplicial_complex:
188
+ if isinstance(simplicial_complex, MomentAngleComplex):
189
+ # Allows for copy constructor
190
+ immutable_complex = SimplicialComplex(simplicial_complex._simplicial_complex, is_mutable=False)
191
+ elif not isinstance(simplicial_complex, SimplicialComplex):
192
+ # Try to create a SimplicialComplex out of simplicial_complex
193
+ # in case that simplicial_complex is a list of facets, or
194
+ # something that can generate a SimplicialComplex
195
+ immutable_complex = SimplicialComplex(simplicial_complex, is_mutable=False)
196
+ elif simplicial_complex.is_mutable():
197
+ immutable_complex = SimplicialComplex(simplicial_complex, is_mutable=False)
198
+ else:
199
+ immutable_complex = simplicial_complex
200
+ else:
201
+ immutable_complex = SimplicialComplex(is_mutable=False)
202
+ return super().__classcall__(cls, immutable_complex)
203
+
204
+ def __init__(self, simplicial_complex) -> None:
205
+ """
206
+ Initialize ``self``.
207
+
208
+ TESTS::
209
+
210
+ sage: Z = MomentAngleComplex([[0,1,2], [1,2,3], [0, 3]])
211
+ sage: TestSuite(Z).run()
212
+ """
213
+ # The underlying simplicial complex
214
+ self._simplicial_complex = copy(simplicial_complex)
215
+ vertices = self._simplicial_complex.vertices()
216
+
217
+ disk = simplicial_complexes.Simplex(2)
218
+ circle = simplicial_complexes.Sphere(1)
219
+
220
+ # A dictionary of components indexed by facets
221
+ self._components = {facet: [disk if j in facet else circle
222
+ for j in vertices]
223
+ for facet in self._simplicial_complex.maximal_faces()}
224
+
225
+ @lazy_attribute
226
+ def _moment_angle_complex(self):
227
+ """
228
+ Create the moment-angle complex as a cubical complex.
229
+
230
+ If this lazy attribute is accessed, we explicitly compute
231
+ the moment-angle complex, viewed as a cubical complex.
232
+
233
+ .. WARNING::
234
+
235
+ The construction can be very slow, it is not recommended unless
236
+ the corresponding simplicial complex has 5 or less vertices.
237
+
238
+ TESTS::
239
+
240
+ sage: Z = MomentAngleComplex([[0], [1], [2]]); Z
241
+ Moment-angle complex of Simplicial complex with vertex set
242
+ (0, 1, 2) and facets {(0,), (1,), (2,)}
243
+ sage: Z._moment_angle_complex
244
+ Cubical complex with 64 vertices and 705 cubes
245
+
246
+ This is called by :meth:`cubical_complex()`::
247
+
248
+ sage: Z.cubical_complex()
249
+ Cubical complex with 64 vertices and 705 cubes
250
+ sage: Z.cubical_complex() == Z._moment_angle_complex
251
+ True
252
+ """
253
+ cube = cubical_complexes.Cube(2)
254
+ sphere = cubical_complexes.Sphere(1)
255
+
256
+ moment_angle_complex = CubicalComplex()
257
+ for component in self._components.values():
258
+ x = cube if component[0] == simplicial_complexes.Simplex(2) else sphere
259
+ for j in range(1, len(component)):
260
+ y = cube if component[j] == simplicial_complexes.Simplex(2) else sphere
261
+ x = x.product(y)
262
+ moment_angle_complex = _cubical_complex_union(moment_angle_complex, x)
263
+
264
+ return moment_angle_complex
265
+
266
+ def _repr_(self) -> str:
267
+ """
268
+ Return a string representation of ``self``.
269
+
270
+ TESTS::
271
+
272
+ sage: Z = MomentAngleComplex([[0,1], [1,2], [2,0]])
273
+ sage: Z._repr_()
274
+ 'Moment-angle complex of Simplicial complex with vertex set
275
+ (0, 1, 2) and facets {(0, 1), (0, 2), (1, 2)}'
276
+ sage: repr(Z)
277
+ 'Moment-angle complex of Simplicial complex with vertex set
278
+ (0, 1, 2) and facets {(0, 1), (0, 2), (1, 2)}'
279
+ sage: Z
280
+ Moment-angle complex of Simplicial complex with vertex set
281
+ (0, 1, 2) and facets {(0, 1), (0, 2), (1, 2)}
282
+ sage: Z = MomentAngleComplex([[i for i in range(20)]])
283
+ sage: Z._repr_()
284
+ 'Moment-angle complex of Simplicial complex with
285
+ 20 vertices and 1 facets'
286
+ """
287
+ return "Moment-angle complex of " + repr(self._simplicial_complex)
288
+
289
+ def cubical_complex(self):
290
+ """
291
+ Return the cubical complex that represents ``self``.
292
+
293
+ This method returns returns a cubical complex which is
294
+ derived by explicitly computing products and unions in the
295
+ definition of a moment-angle complex.
296
+
297
+ .. WARNING::
298
+
299
+ The construction can be very slow, it is not recommended unless
300
+ the corresponding simplicial complex has 5 or less vertices.
301
+
302
+ EXAMPLES::
303
+
304
+ sage: Z = MomentAngleComplex([[0,1,2], [1,3]]); Z
305
+ Moment-angle complex of Simplicial complex with vertex set
306
+ (0, 1, 2, 3) and facets {(1, 3), (0, 1, 2)}
307
+ sage: Z.cubical_complex()
308
+ Cubical complex with 256 vertices and 6409 cubes
309
+ sage: dim(Z.cubical_complex()) == dim(Z)
310
+ True
311
+ sage: Z = MomentAngleComplex([[0,1], [1,2], [2,0], [1,3]]); Z
312
+ Moment-angle complex of Simplicial complex with vertex set
313
+ (0, 1, 2, 3) and facets {(0, 1), (0, 2), (1, 2), (1, 3)}
314
+ sage: Z.betti() == Z.cubical_complex().betti() # long time
315
+ True
316
+
317
+ We can now work with moment-angle complexes as concrete cubical
318
+ complexes. Though, it can be very slow, due to the size of the
319
+ complex. However, for some smaller moment-angle complexes, this
320
+ may be possible::
321
+
322
+ sage: Z = MomentAngleComplex([[0], [1]]); Z
323
+ Moment-angle complex of Simplicial complex with vertex set
324
+ (0, 1) and facets {(0,), (1,)}
325
+ sage: Z.cubical_complex().f_vector()
326
+ [1, 16, 32, 24, 8]
327
+ """
328
+ return self._moment_angle_complex
329
+
330
+ def simplicial_complex(self):
331
+ """
332
+ Return the simplicial complex that defines ``self``.
333
+
334
+ EXAMPLES::
335
+
336
+ sage: RP2 = simplicial_complexes.RealProjectivePlane()
337
+ sage: Z = MomentAngleComplex(RP2)
338
+ sage: Z.simplicial_complex()
339
+ Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and 10 facets
340
+ sage: Z = MomentAngleComplex([[0], [1], [2]])
341
+ sage: Z.simplicial_complex()
342
+ Simplicial complex with vertex set (0, 1, 2)
343
+ and facets {(0,), (1,), (2,)}
344
+ """
345
+ return self._simplicial_complex
346
+
347
+ def components(self) -> dict:
348
+ r"""
349
+ Return the dictionary of components of ``self``, indexed by facets
350
+ of the associated simplicial complex.
351
+
352
+ OUTPUT:
353
+
354
+ A dictionary, whose values are lists, representing spheres
355
+ and disks described in the construction of the moment-angle
356
+ complex. ``The 2-simplex`` represents a 2-disk, and
357
+ ``Minimal triangulation of the 1-sphere`` represents a 1-sphere.
358
+
359
+ EXAMPLES::
360
+
361
+ sage: M = MomentAngleComplex([[0, 1, 2]]); M
362
+ Moment-angle complex of Simplicial complex with vertex set
363
+ (0, 1, 2) and facets {(0, 1, 2)}
364
+ sage: M.components()
365
+ {(0, 1, 2): [The 2-simplex, The 2-simplex, The 2-simplex]}
366
+ sage: Z = MomentAngleComplex([[0], [1]]); Z
367
+ Moment-angle complex of Simplicial complex with vertex set
368
+ (0, 1) and facets {(0,), (1,)}
369
+ sage: sorted(Z.components().items())
370
+ [((0,), [The 2-simplex, Minimal triangulation of the 1-sphere]),
371
+ ((1,), [Minimal triangulation of the 1-sphere, The 2-simplex])]
372
+
373
+ We interpret the output of this method by taking the product
374
+ of all the elements in each list, and then taking the union
375
+ of all products. From the previous example, we have
376
+ `\mathcal{Z} = S^1 \times D^2 \cup D^2 \times S^1
377
+ = \partial (D^2 \times D^2) = \partial D^4 = S^3`::
378
+
379
+ sage: Z = MomentAngleComplex([[0,1], [1,2], [2,3], [3,0]])
380
+ sage: sorted(Z.components().items())
381
+ [((0, 1),
382
+ [The 2-simplex,
383
+ The 2-simplex,
384
+ Minimal triangulation of the 1-sphere,
385
+ Minimal triangulation of the 1-sphere]),
386
+ ((0, 3),
387
+ [The 2-simplex,
388
+ Minimal triangulation of the 1-sphere,
389
+ Minimal triangulation of the 1-sphere,
390
+ The 2-simplex]),
391
+ ((1, 2),
392
+ [Minimal triangulation of the 1-sphere,
393
+ The 2-simplex,
394
+ The 2-simplex,
395
+ Minimal triangulation of the 1-sphere]),
396
+ ((2, 3),
397
+ [Minimal triangulation of the 1-sphere,
398
+ Minimal triangulation of the 1-sphere,
399
+ The 2-simplex,
400
+ The 2-simplex])]
401
+
402
+ It is not that difficult to prove that the previous
403
+ moment-angle complex is homeomorphic to a product of
404
+ two 3-spheres. We can look at the cohomologies to try
405
+ and validate whether this makes sense::
406
+
407
+ sage: S3 = simplicial_complexes.Sphere(3)
408
+ sage: product_of_spheres = S3.product(S3)
409
+ sage: Z.cohomology() # needs sage.modules
410
+ {0: 0, 1: 0, 2: 0, 3: Z x Z, 4: 0, 5: 0, 6: Z}
411
+ sage: Z.cohomology() == product_of_spheres.cohomology() # long time # needs sage.modules
412
+ True
413
+ """
414
+ return self._components
415
+
416
+ def dimension(self):
417
+ r"""
418
+ The dimension of ``self``.
419
+
420
+ The dimension of a moment-angle complex is the dimension
421
+ of the constructed (cubical) complex. It is not difficult
422
+ to see that this turns out to be `m+n+1`, where `m` is the
423
+ number of vertices and `n` is the dimension of the associated
424
+ simplicial complex.
425
+
426
+ EXAMPLES::
427
+
428
+ sage: Z = MomentAngleComplex([[0,1], [1,2,3]])
429
+ sage: Z.dimension()
430
+ 7
431
+ sage: Z = MomentAngleComplex([[0, 1, 2]])
432
+ sage: Z.dimension()
433
+ 6
434
+ sage: dim(Z)
435
+ 6
436
+
437
+ We can construct the cubical complex and compare whether
438
+ the dimensions coincide::
439
+
440
+ sage: dim(Z) == dim(Z.cubical_complex())
441
+ True
442
+ """
443
+ number_of_vertices = len(self._simplicial_complex.vertices())
444
+ dim = self._simplicial_complex.dimension()
445
+ return number_of_vertices + dim + 1
446
+
447
+ @cached_method # maybe ignore the algorithm?
448
+ def _homology_group(self, i, base_ring, cohomology, algorithm, verbose, reduced):
449
+ """
450
+ The `i`-th (reduced) homology group of ``self``.
451
+
452
+ .. SEEALSO::
453
+
454
+ :meth:`homology`,
455
+ :meth:`.cell_complex.GenericCellComplex.homology`.
456
+
457
+ TESTS::
458
+
459
+ sage: # needs sage.modules
460
+ sage: Z = MomentAngleComplex([[0,1,2], [1,2,3]]); Z
461
+ Moment-angle complex of Simplicial complex with vertex set
462
+ (0, 1, 2, 3) and facets {(0, 1, 2), (1, 2, 3)}
463
+ sage: Z._homology_group(3, base_ring=ZZ,
464
+ ....: reduced=True, verbose=False,
465
+ ....: cohomology=False, algorithm='pari')
466
+ Z
467
+ sage: Z._homology_group(4, base_ring=ZZ,
468
+ ....: reduced=True, verbose=False,
469
+ ....: cohomology=False, algorithm='pari')
470
+ 0
471
+ sage: Z.homology()
472
+ {0: 0, 1: 0, 2: 0, 3: Z, 4: 0, 5: 0, 6: 0, 7: 0}
473
+ sage: RP2 = simplicial_complexes.RealProjectivePlane()
474
+ sage: Z = MomentAngleComplex(RP2)
475
+ sage: Z._homology_group(8, base_ring=ZZ,
476
+ ....: reduced=True, verbose=False,
477
+ ....: cohomology=False, algorithm='pari')
478
+ C2
479
+ """
480
+ if i == 0:
481
+ # This is a special case when computing (co)homology
482
+ if reduced:
483
+ return HomologyGroup(0, base_ring)
484
+ return HomologyGroup(1, base_ring)
485
+
486
+ vertices = self._simplicial_complex.vertices()
487
+ n = len(vertices)
488
+ invfac = []
489
+
490
+ in_field = base_ring in Fields()
491
+
492
+ for j in range(n + 1):
493
+ for x in combinations(vertices, j):
494
+ S = self._simplicial_complex.generated_subcomplex(x)
495
+ if in_field:
496
+ invfac.append(S.homology(i - j - 1, base_ring=base_ring,
497
+ cohomology=cohomology, algorithm=algorithm,
498
+ verbose=verbose, reduced=True).dimension())
499
+ else:
500
+ invfac.extend(S.homology(i - j - 1, base_ring=base_ring,
501
+ cohomology=cohomology, algorithm=algorithm,
502
+ verbose=verbose, reduced=True)._original_invts)
503
+
504
+ if in_field:
505
+ return HomologyGroup(sum(invfac), base_ring)
506
+
507
+ m = len(invfac)
508
+ return HomologyGroup(m, base_ring, invfac)
509
+
510
+ def homology(self, dim=None, base_ring=ZZ, cohomology=False,
511
+ algorithm='pari', verbose=False, reduced=True) -> dict:
512
+ r"""
513
+ The (reduced) homology of ``self``.
514
+
515
+ INPUT:
516
+
517
+ - ``dim`` -- integer or a list of integers; represents the
518
+ homology (or homologies) we want to compute
519
+ - ``base_ring`` -- commutative ring (default: ``ZZ``); must be ``ZZ``
520
+ or a field
521
+ - ``cohomology`` -- boolean (default: ``False``);
522
+ if ``True``, compute cohomology rather than homology
523
+ - ``algorithm`` -- string (default: ``'pari'``); the options are
524
+ ``'auto'``, ``'dhsw'``, or ``'pari'``; see
525
+ :meth:`.cell_complex.GenericCellComplex.homology` documentation
526
+ for a description of what they mean
527
+ - ``verbose`` -- boolean (default: ``False``); if ``True``,
528
+ print some messages as the homology is computed
529
+ - ``reduced`` -- boolean (default: ``True``); if ``True``,
530
+ return the reduced homology
531
+
532
+ ALGORITHM:
533
+
534
+ This algorithm is adopted from Theorem 4.5.8 of [BP2014]_.
535
+
536
+ The (co)homology of the moment-angle complex is closely related
537
+ to the (co)homologies of certain full subcomplexes of the
538
+ associated simplicial complex. More specifically, we know that:
539
+
540
+ .. MATH::
541
+
542
+ H_l(\mathcal{Z}_\mathcal{K}) \cong
543
+ \bigoplus_{J \subseteq [m]} \widetilde{H}_{l-|J|-1}(\mathcal{K}_J),
544
+
545
+ where `\mathcal{Z}_\mathcal{K}` denotes the moment-angle complex
546
+ associated to a simplicial complex `\mathcal{K}`, on the set of
547
+ vertices `\{1, 2, 3, \ldots, m\} =: [m]`. `\mathcal{K}_J` denotes the
548
+ full subcomplex of `\mathcal{K}`, generated by a set of vertices `J`.
549
+ The same formula holds true for cohomology groups as well.
550
+
551
+ .. SEEALSO::
552
+
553
+ :meth:`.cell_complex.GenericCellComplex.homology`
554
+
555
+ EXAMPLES::
556
+
557
+ sage: # needs sage.modules
558
+ sage: Z = MomentAngleComplex([[0,1,2], [1,2,3], [3,0]]); Z
559
+ Moment-angle complex of Simplicial complex with vertex set
560
+ (0, 1, 2, 3) and facets {(0, 3), (0, 1, 2), (1, 2, 3)}
561
+ sage: Z = MomentAngleComplex([[0,1,2], [1,2,3], [3,0]])
562
+ sage: Z.homology()
563
+ {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: Z x Z, 6: Z, 7: 0}
564
+ sage: Z.homology(base_ring=GF(2))
565
+ {0: Vector space of dimension 0 over Finite Field of size 2,
566
+ 1: Vector space of dimension 0 over Finite Field of size 2,
567
+ 2: Vector space of dimension 0 over Finite Field of size 2,
568
+ 3: Vector space of dimension 0 over Finite Field of size 2,
569
+ 4: Vector space of dimension 0 over Finite Field of size 2,
570
+ 5: Vector space of dimension 2 over Finite Field of size 2,
571
+ 6: Vector space of dimension 1 over Finite Field of size 2,
572
+ 7: Vector space of dimension 0 over Finite Field of size 2}
573
+ sage: RP = simplicial_complexes.RealProjectivePlane()
574
+ sage: Z = MomentAngleComplex(RP)
575
+ sage: Z.homology()
576
+ {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: Z^10, 6: Z^15, 7: Z^6, 8: C2, 9: 0}
577
+
578
+ This yields the same result as creating a cubical complex
579
+ from this moment-angle complex, and then computing its (co)homology,
580
+ but that is incomparably slower and is really only possible when
581
+ the associated simplicial complex is very small::
582
+
583
+ sage: Z = MomentAngleComplex([[0,1], [1,2], [2,0]]); Z
584
+ Moment-angle complex of Simplicial complex with vertex set
585
+ (0, 1, 2) and facets {(0, 1), (0, 2), (1, 2)}
586
+ sage: Z.cubical_complex()
587
+ Cubical complex with 64 vertices and 729 cubes
588
+ sage: Z.cubical_complex().homology() == Z.homology() # needs sage.modules
589
+ True
590
+
591
+ Meanwhile, the homology computation used here is quite efficient
592
+ and works well even with significantly larger underlying simplicial
593
+ complexes::
594
+
595
+ sage: # needs sage.modules
596
+ sage: Z = MomentAngleComplex([[0,1,2,3,4,5], [0,1,2,3,4,6],
597
+ ....: [0,1,2,3,5,7], [0,1,2,3,6,8,9]])
598
+ sage: Z.homology() # long time
599
+ {0: 0,
600
+ 1: 0,
601
+ 2: 0,
602
+ 3: Z^9,
603
+ 4: Z^17,
604
+ 5: Z^12,
605
+ 6: Z x Z x Z,
606
+ 7: 0,
607
+ 8: 0,
608
+ 9: 0,
609
+ 10: 0,
610
+ 11: 0,
611
+ 12: 0,
612
+ 13: 0,
613
+ 14: 0,
614
+ 15: 0,
615
+ 16: 0,
616
+ 17: 0}
617
+ sage: Z = MomentAngleComplex([[0,1,2,3], [0,1,2,4], [0,1,3,5],
618
+ ....: [0,1,4,5], [0,2,3,6], [0,2,4,6]])
619
+ sage: Z.homology(dim=range(5), reduced=True)
620
+ {0: 0, 1: 0, 2: 0, 3: Z x Z x Z x Z, 4: Z x Z}
621
+ sage: Z.homology(dim=range(5), reduced=False)
622
+ {0: Z, 1: 0, 2: 0, 3: Z x Z x Z x Z, 4: Z x Z}
623
+ sage: all(Z.homology(i,reduced=True) == Z.homology(i,reduced=False)
624
+ ....: for i in range(1, dim(Z)))
625
+ True
626
+ sage: all(Z.homology(i,reduced=True) == Z.homology(i,reduced=False)
627
+ ....: for i in range(dim(Z)))
628
+ False
629
+ """
630
+ if dim is not None:
631
+ if isinstance(dim, (list, tuple, range)):
632
+ low = min(dim)
633
+ high = max(dim)
634
+ else:
635
+ low = dim
636
+ high = dim
637
+ dims = range(low, high + 1)
638
+ else:
639
+ dims = range(self.dimension() + 1)
640
+
641
+ return {i: self._homology_group(i, base_ring=base_ring, cohomology=cohomology,
642
+ algorithm=algorithm, verbose=verbose, reduced=reduced) for i in dims}
643
+
644
+ def cohomology(self, dim=None, base_ring=ZZ, algorithm='pari',
645
+ verbose=False, reduced=True) -> dict:
646
+ r"""
647
+ The reduced cohomology of ``self``.
648
+
649
+ This is equivalent to calling the ``homology()`` method,
650
+ with ``cohomology=True`` as an argument.
651
+
652
+ .. SEEALSO::
653
+
654
+ :meth:`homology`.
655
+
656
+ EXAMPLES::
657
+
658
+ sage: X = SimplicialComplex([[0,1],[1,2],[2,3],[3,0]])
659
+ sage: Z = MomentAngleComplex(X)
660
+
661
+ It is known that the previous moment-angle complex is homeomorphic
662
+ to a product of two 3-spheres (which can be seen by looking at the
663
+ output of ``components()``)::
664
+
665
+ sage: # needs sage.modules
666
+ sage: S3 = simplicial_complexes.Sphere(3)
667
+ sage: product_of_spheres = S3.product(S3)
668
+ sage: Z.cohomology()
669
+ {0: 0, 1: 0, 2: 0, 3: Z x Z, 4: 0, 5: 0, 6: Z}
670
+ sage: Z.cohomology() == product_of_spheres.cohomology() # long time
671
+ True
672
+ """
673
+ return self.homology(dim=dim, cohomology=True, base_ring=base_ring,
674
+ algorithm=algorithm, verbose=verbose, reduced=reduced)
675
+
676
+ def betti(self, dim=None) -> dict:
677
+ r"""
678
+ Return the Betti number (or numbers) of ``self``.
679
+
680
+ The the `i`-th Betti number is the rank of the `i`-th homology group.
681
+
682
+ INPUT:
683
+
684
+ - ``dim`` -- (optional) an integer or a list of integers
685
+
686
+ OUTPUT:
687
+
688
+ If ``dim`` is an integer or a list of integers, then return
689
+ a dictionary of Betti numbers for each given dimension, indexed
690
+ by dimension. Otherwise, return all Betti numbers.
691
+
692
+ EXAMPLES::
693
+
694
+ sage: # needs sage.modules
695
+ sage: Z = MomentAngleComplex([[0,1], [1,2], [2,0], [1,2,3]])
696
+ sage: Z.betti()
697
+ {0: 1, 1: 0, 2: 0, 3: 1, 4: 0, 5: 1, 6: 1, 7: 0}
698
+ sage: Z = MomentAngleComplex([[0,1], [1,2], [2,0], [1,2,3], [3,0]])
699
+ sage: Z.betti(dim=6)
700
+ {6: 2}
701
+ """
702
+ dic = {}
703
+ H = self.homology(dim=dim, base_ring=QQ)
704
+ try:
705
+ for n in H:
706
+ dic[n] = H[n].dimension()
707
+ if n == 0:
708
+ dic[n] += 1
709
+ except AttributeError:
710
+ return H.dimension()
711
+ else:
712
+ return dic
713
+
714
+ def euler_characteristic(self):
715
+ """
716
+ Return the Euler characteristic of ``self``.
717
+
718
+ The Euler characteristic is defined as the alternating sum
719
+ of the Betti numbers of ``self``.
720
+
721
+ The Euler characteristic of a moment-angle complex is 0
722
+ if the associated simplicial complex is not a simplex.
723
+
724
+ EXAMPLES::
725
+
726
+ sage: # needs sage.modules
727
+ sage: X = SimplicialComplex([[0,1,2,3,4,5], [0,1,2,3,4,6],
728
+ ....: [0,1,2,3,5,7], [0,1,2,3,6,8,9]])
729
+ sage: M = MomentAngleComplex(X)
730
+ sage: M.euler_characteristic() # long time
731
+ 0
732
+ sage: Z = MomentAngleComplex([[0,1,2,3,4]])
733
+ sage: Z.euler_characteristic()
734
+ 1
735
+ """
736
+ sc = self.simplicial_complex()
737
+ return (ZZ.one() if sc.dimension() + 1 == len(sc.vertices())
738
+ else ZZ.zero())
739
+
740
+ def product(self, other):
741
+ """
742
+ Return the product of ``self`` with ``other``.
743
+
744
+ It is known that the product of two moment-angle complexes
745
+ is a moment-angle complex over the join of the two corresponding
746
+ simplicial complexes. This result can be found on page 138 of
747
+ [BP2014]_.
748
+
749
+ OUTPUT: a moment-angle complex which is the product of the
750
+ parsed moment-angle complexes
751
+
752
+ EXAMPLES::
753
+
754
+ sage: X = SimplicialComplex([[0,1,2,3], [1,4], [3,2,4]])
755
+ sage: Y = SimplicialComplex([[1,2,3],[1,2,4],[3,5],[4,5]])
756
+ sage: Z = MomentAngleComplex(X)
757
+ sage: M = MomentAngleComplex(Y)
758
+ sage: Z.product(M)
759
+ Moment-angle complex of Simplicial complex with
760
+ 10 vertices and 12 facets
761
+ sage: Z.product(M) == MomentAngleComplex(X*Y)
762
+ True
763
+ """
764
+ simplicial_complex = self._simplicial_complex.join(other._simplicial_complex, rename_vertices=True)
765
+ return MomentAngleComplex(simplicial_complex)
766
+
767
+ def has_trivial_lowest_deg_massey_product(self) -> bool:
768
+ """
769
+ Return whether ``self`` has a non-trivial lowest degree
770
+ triple Massey product.
771
+
772
+ This is the Massey product in the cohomology of this
773
+ moment-angle complex. This relies on the theorem which was
774
+ proven in [GL2019]_.
775
+
776
+ ALGORITHM:
777
+
778
+ We obtain the one-skeleton from the associated simplicial complex,
779
+ which we consider to be a graph. We then perform ``subgraph_search``,
780
+ searching for any subgraph isomorphic to one of the 8 obstruction
781
+ graphs listed in the mentioned paper.
782
+
783
+ EXAMPLES:
784
+
785
+ A simplex will not have a trivial triple lowest-degree
786
+ Massey product, because its one-skeleton certainly does
787
+ contain a subcomplex isomorphic to one of the 8 mentioned
788
+ in the paper::
789
+
790
+ sage: Z = MomentAngleComplex([[1,2,3,4,5,6]])
791
+ sage: Z.has_trivial_lowest_deg_massey_product()
792
+ False
793
+
794
+ The following is one of the 8 obstruction graphs::
795
+
796
+ sage: Z = MomentAngleComplex([[1, 2], [1, 4], [2, 3], [3, 5],
797
+ ....: [5, 6], [4, 5], [1, 6]])
798
+ sage: Z.has_trivial_lowest_deg_massey_product()
799
+ False
800
+
801
+ A hexagon is not isomorphic to any of the 8 obstruction graphs::
802
+
803
+ sage: Z = MomentAngleComplex([[0,1], [1,2], [2,3],
804
+ ....: [3,4], [4,5], [5,0]])
805
+ sage: Z.has_trivial_lowest_deg_massey_product()
806
+ True
807
+ """
808
+ from sage.graphs.graph import Graph
809
+
810
+ one_skeleton = self._simplicial_complex.graph()
811
+
812
+ obstruction_graphs = [
813
+ Graph([(1, 2), (1, 4), (2, 3), (3, 5), (5, 6), (4, 5), (1, 6)]),
814
+ Graph([(1, 2), (1, 4), (2, 3), (3, 5), (5, 6), (4, 5), (1, 6), (2, 6)]),
815
+ Graph([(1, 2), (1, 4), (2, 3), (3, 5), (5, 6), (4, 5), (1, 6), (4, 6)]),
816
+ Graph([(1, 2), (1, 4), (2, 3), (3, 5), (5, 6), (4, 5), (1, 6), (2, 6), (4, 6)]),
817
+ Graph([(1, 2), (1, 4), (2, 3), (3, 5), (5, 6), (3, 4), (2, 6), (1, 6), (4, 5)]),
818
+ Graph([(1, 2), (1, 4), (2, 3), (3, 5), (5, 6), (3, 4), (2, 6), (1, 6), (4, 5), (4, 6)]),
819
+ Graph([(1, 2), (1, 4), (2, 3), (3, 5), (5, 6), (3, 4), (2, 6), (4, 5), (4, 6)]),
820
+ Graph([(1, 2), (1, 4), (2, 3), (3, 5), (5, 6), (3, 4), (2, 6), (4, 6)]),
821
+ ]
822
+
823
+ return all(one_skeleton.subgraph_search(g) is None for g in obstruction_graphs)