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.
- passagemath_graphs-10.6.1rc1.dist-info/METADATA +292 -0
- passagemath_graphs-10.6.1rc1.dist-info/RECORD +260 -0
- passagemath_graphs-10.6.1rc1.dist-info/WHEEL +5 -0
- passagemath_graphs-10.6.1rc1.dist-info/top_level.txt +2 -0
- passagemath_graphs.libs/libgcc_s-69c45f16.so.1 +0 -0
- passagemath_graphs.libs/libgmp-8e78bd9b.so.10.5.0 +0 -0
- passagemath_graphs.libs/libstdc++-1f1a71be.so.6.0.33 +0 -0
- sage/all__sagemath_graphs.py +39 -0
- sage/combinat/abstract_tree.py +2723 -0
- sage/combinat/all__sagemath_graphs.py +34 -0
- sage/combinat/binary_tree.py +5306 -0
- sage/combinat/cluster_algebra_quiver/all.py +22 -0
- sage/combinat/cluster_algebra_quiver/cluster_seed.py +5208 -0
- sage/combinat/cluster_algebra_quiver/interact.py +124 -0
- sage/combinat/cluster_algebra_quiver/mutation_class.py +625 -0
- sage/combinat/cluster_algebra_quiver/mutation_type.py +1555 -0
- sage/combinat/cluster_algebra_quiver/quiver.py +2290 -0
- sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py +2468 -0
- sage/combinat/designs/MOLS_handbook_data.py +570 -0
- sage/combinat/designs/all.py +58 -0
- sage/combinat/designs/bibd.py +1655 -0
- sage/combinat/designs/block_design.py +1071 -0
- sage/combinat/designs/covering_array.py +269 -0
- sage/combinat/designs/covering_design.py +530 -0
- sage/combinat/designs/database.py +5615 -0
- sage/combinat/designs/design_catalog.py +122 -0
- sage/combinat/designs/designs_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/designs_pyx.pxd +21 -0
- sage/combinat/designs/designs_pyx.pyx +993 -0
- sage/combinat/designs/difference_family.py +3951 -0
- sage/combinat/designs/difference_matrices.py +279 -0
- sage/combinat/designs/evenly_distributed_sets.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/evenly_distributed_sets.pyx +661 -0
- sage/combinat/designs/ext_rep.py +1064 -0
- sage/combinat/designs/gen_quadrangles_with_spread.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/gen_quadrangles_with_spread.pyx +339 -0
- sage/combinat/designs/group_divisible_designs.py +361 -0
- sage/combinat/designs/incidence_structures.py +2357 -0
- sage/combinat/designs/latin_squares.py +581 -0
- sage/combinat/designs/orthogonal_arrays.py +2244 -0
- sage/combinat/designs/orthogonal_arrays_build_recursive.py +1780 -0
- sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +967 -0
- sage/combinat/designs/resolvable_bibd.py +815 -0
- sage/combinat/designs/steiner_quadruple_systems.py +1306 -0
- sage/combinat/designs/subhypergraph_search.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/subhypergraph_search.pyx +530 -0
- sage/combinat/designs/twographs.py +306 -0
- sage/combinat/finite_state_machine.py +14874 -0
- sage/combinat/finite_state_machine_generators.py +2006 -0
- sage/combinat/graph_path.py +448 -0
- sage/combinat/interval_posets.py +3908 -0
- sage/combinat/nu_tamari_lattice.py +269 -0
- sage/combinat/ordered_tree.py +1446 -0
- sage/combinat/posets/all.py +46 -0
- sage/combinat/posets/bubble_shuffle.py +247 -0
- sage/combinat/posets/cartesian_product.py +493 -0
- sage/combinat/posets/d_complete.py +182 -0
- sage/combinat/posets/elements.py +273 -0
- sage/combinat/posets/forest.py +30 -0
- sage/combinat/posets/hasse_cython.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/posets/hasse_cython.pyx +174 -0
- sage/combinat/posets/hasse_diagram.py +3672 -0
- sage/combinat/posets/hochschild_lattice.py +158 -0
- sage/combinat/posets/incidence_algebras.py +794 -0
- sage/combinat/posets/lattices.py +5117 -0
- sage/combinat/posets/linear_extension_iterator.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/posets/linear_extension_iterator.pyx +292 -0
- sage/combinat/posets/linear_extensions.py +1037 -0
- sage/combinat/posets/mobile.py +275 -0
- sage/combinat/posets/moebius_algebra.py +776 -0
- sage/combinat/posets/poset_examples.py +2178 -0
- sage/combinat/posets/posets.py +9360 -0
- sage/combinat/rooted_tree.py +1070 -0
- sage/combinat/shard_order.py +239 -0
- sage/combinat/tamari_lattices.py +384 -0
- sage/combinat/yang_baxter_graph.py +923 -0
- sage/databases/all__sagemath_graphs.py +1 -0
- sage/databases/knotinfo_db.py +1231 -0
- sage/ext_data/all__sagemath_graphs.py +1 -0
- sage/ext_data/graphs/graph_plot_js.html +330 -0
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/graphs/all.py +42 -0
- sage/graphs/asteroidal_triples.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/asteroidal_triples.pyx +320 -0
- sage/graphs/base/all.py +1 -0
- sage/graphs/base/boost_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/boost_graph.pxd +106 -0
- sage/graphs/base/boost_graph.pyx +3045 -0
- sage/graphs/base/c_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/c_graph.pxd +106 -0
- sage/graphs/base/c_graph.pyx +5096 -0
- sage/graphs/base/dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/dense_graph.pxd +28 -0
- sage/graphs/base/dense_graph.pyx +801 -0
- sage/graphs/base/graph_backends.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/graph_backends.pxd +5 -0
- sage/graphs/base/graph_backends.pyx +797 -0
- sage/graphs/base/overview.py +85 -0
- sage/graphs/base/sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/sparse_graph.pxd +90 -0
- sage/graphs/base/sparse_graph.pyx +1653 -0
- sage/graphs/base/static_dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/static_dense_graph.pxd +5 -0
- sage/graphs/base/static_dense_graph.pyx +1032 -0
- sage/graphs/base/static_sparse_backend.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/static_sparse_backend.pxd +27 -0
- sage/graphs/base/static_sparse_backend.pyx +1583 -0
- sage/graphs/base/static_sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/static_sparse_graph.pxd +37 -0
- sage/graphs/base/static_sparse_graph.pyx +1375 -0
- sage/graphs/bipartite_graph.py +2732 -0
- sage/graphs/centrality.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/centrality.pyx +1038 -0
- sage/graphs/cographs.py +519 -0
- sage/graphs/comparability.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/comparability.pyx +851 -0
- sage/graphs/connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/connectivity.pxd +157 -0
- sage/graphs/connectivity.pyx +4813 -0
- sage/graphs/convexity_properties.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/convexity_properties.pxd +16 -0
- sage/graphs/convexity_properties.pyx +870 -0
- sage/graphs/digraph.py +4754 -0
- sage/graphs/digraph_generators.py +1993 -0
- sage/graphs/distances_all_pairs.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/distances_all_pairs.pxd +12 -0
- sage/graphs/distances_all_pairs.pyx +2938 -0
- sage/graphs/domination.py +1363 -0
- sage/graphs/dot2tex_utils.py +100 -0
- sage/graphs/edge_connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/edge_connectivity.pyx +1215 -0
- sage/graphs/generators/all.py +1 -0
- sage/graphs/generators/basic.py +1769 -0
- sage/graphs/generators/chessboard.py +538 -0
- sage/graphs/generators/classical_geometries.py +1611 -0
- sage/graphs/generators/degree_sequence.py +235 -0
- sage/graphs/generators/distance_regular.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/generators/distance_regular.pyx +2846 -0
- sage/graphs/generators/families.py +4759 -0
- sage/graphs/generators/intersection.py +565 -0
- sage/graphs/generators/platonic_solids.py +262 -0
- sage/graphs/generators/random.py +2623 -0
- sage/graphs/generators/smallgraphs.py +5741 -0
- sage/graphs/generators/world_map.py +724 -0
- sage/graphs/generic_graph.py +26867 -0
- sage/graphs/generic_graph_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/generic_graph_pyx.pxd +34 -0
- sage/graphs/generic_graph_pyx.pyx +1673 -0
- sage/graphs/genus.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/genus.pyx +622 -0
- sage/graphs/graph.py +9645 -0
- sage/graphs/graph_coloring.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_coloring.pyx +2284 -0
- sage/graphs/graph_database.py +1177 -0
- sage/graphs/graph_decompositions/all.py +1 -0
- sage/graphs/graph_decompositions/bandwidth.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/bandwidth.pyx +428 -0
- sage/graphs/graph_decompositions/clique_separators.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/clique_separators.pyx +616 -0
- sage/graphs/graph_decompositions/cutwidth.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/cutwidth.pyx +753 -0
- sage/graphs/graph_decompositions/fast_digraph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/fast_digraph.pxd +13 -0
- sage/graphs/graph_decompositions/fast_digraph.pyx +212 -0
- sage/graphs/graph_decompositions/graph_products.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/graph_products.pyx +508 -0
- sage/graphs/graph_decompositions/modular_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/modular_decomposition.pxd +27 -0
- sage/graphs/graph_decompositions/modular_decomposition.pyx +1536 -0
- sage/graphs/graph_decompositions/slice_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/slice_decomposition.pxd +18 -0
- sage/graphs/graph_decompositions/slice_decomposition.pyx +1106 -0
- sage/graphs/graph_decompositions/tree_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/tree_decomposition.pxd +17 -0
- sage/graphs/graph_decompositions/tree_decomposition.pyx +1996 -0
- sage/graphs/graph_decompositions/vertex_separation.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/vertex_separation.pxd +5 -0
- sage/graphs/graph_decompositions/vertex_separation.pyx +1963 -0
- sage/graphs/graph_editor.py +82 -0
- sage/graphs/graph_generators.py +3314 -0
- sage/graphs/graph_generators_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_generators_pyx.pyx +95 -0
- sage/graphs/graph_input.py +812 -0
- sage/graphs/graph_latex.py +2064 -0
- sage/graphs/graph_list.py +410 -0
- sage/graphs/graph_plot.py +1756 -0
- sage/graphs/graph_plot_js.py +338 -0
- sage/graphs/hyperbolicity.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/hyperbolicity.pyx +1704 -0
- sage/graphs/hypergraph_generators.py +364 -0
- sage/graphs/independent_sets.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/independent_sets.pxd +13 -0
- sage/graphs/independent_sets.pyx +402 -0
- sage/graphs/isgci.py +1033 -0
- sage/graphs/isoperimetric_inequalities.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/isoperimetric_inequalities.pyx +489 -0
- sage/graphs/line_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/line_graph.pyx +743 -0
- sage/graphs/lovasz_theta.py +77 -0
- sage/graphs/matching.py +1633 -0
- sage/graphs/matching_covered_graph.py +3590 -0
- sage/graphs/orientations.py +1489 -0
- sage/graphs/partial_cube.py +459 -0
- sage/graphs/path_enumeration.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/path_enumeration.pyx +2040 -0
- sage/graphs/pq_trees.py +1129 -0
- sage/graphs/print_graphs.py +201 -0
- sage/graphs/schnyder.py +865 -0
- sage/graphs/spanning_tree.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/spanning_tree.pyx +1457 -0
- sage/graphs/strongly_regular_db.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/strongly_regular_db.pyx +3340 -0
- sage/graphs/traversals.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/traversals.pxd +9 -0
- sage/graphs/traversals.pyx +1872 -0
- sage/graphs/trees.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/trees.pxd +15 -0
- sage/graphs/trees.pyx +310 -0
- sage/graphs/tutte_polynomial.py +713 -0
- sage/graphs/views.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/views.pyx +794 -0
- sage/graphs/weakly_chordal.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/weakly_chordal.pyx +604 -0
- sage/groups/all__sagemath_graphs.py +1 -0
- sage/groups/perm_gps/all__sagemath_graphs.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_graphs.py +1 -0
- sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_graphs.pxd +38 -0
- sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +1666 -0
- sage/knots/all.py +6 -0
- sage/knots/free_knotinfo_monoid.py +507 -0
- sage/knots/gauss_code.py +291 -0
- sage/knots/knot.py +682 -0
- sage/knots/knot_table.py +284 -0
- sage/knots/knotinfo.py +2900 -0
- sage/knots/link.py +4715 -0
- sage/sandpiles/all.py +13 -0
- sage/sandpiles/examples.py +225 -0
- sage/sandpiles/sandpile.py +6365 -0
- sage/topology/all.py +22 -0
- sage/topology/cell_complex.py +1214 -0
- sage/topology/cubical_complex.py +1976 -0
- sage/topology/delta_complex.py +1806 -0
- sage/topology/filtered_simplicial_complex.py +744 -0
- sage/topology/moment_angle_complex.py +823 -0
- sage/topology/simplicial_complex.py +5160 -0
- sage/topology/simplicial_complex_catalog.py +92 -0
- sage/topology/simplicial_complex_examples.py +1680 -0
- sage/topology/simplicial_complex_homset.py +205 -0
- sage/topology/simplicial_complex_morphism.py +836 -0
- sage/topology/simplicial_set.py +4102 -0
- sage/topology/simplicial_set_catalog.py +55 -0
- sage/topology/simplicial_set_constructions.py +2954 -0
- sage/topology/simplicial_set_examples.py +865 -0
- 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)
|