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,836 @@
1
+ # sage_setup: distribution = sagemath-graphs
2
+ # sage.doctest: needs sage.graphs
3
+ r"""
4
+ Morphisms of simplicial complexes
5
+
6
+ AUTHORS:
7
+
8
+ - Benjamin Antieau <d.ben.antieau@gmail.com> (2009.06)
9
+
10
+ - Travis Scrimshaw (2012-08-18): Made all simplicial complexes immutable to
11
+ work with the homset cache.
12
+
13
+ This module implements morphisms of simplicial complexes. The input is given
14
+ by a dictionary on the vertex set of a simplicial complex. The initialization
15
+ checks that faces are sent to faces.
16
+
17
+ There is also the capability to create the fiber product of two morphisms with
18
+ the same codomain.
19
+
20
+ EXAMPLES::
21
+
22
+ sage: S = SimplicialComplex([[0,2],[1,5],[3,4]], is_mutable=False)
23
+ sage: H = Hom(S,S.product(S, is_mutable=False))
24
+ sage: H.diagonal_morphism()
25
+ Simplicial complex morphism:
26
+ From: Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and facets {(0, 2), (1, 5), (3, 4)}
27
+ To: Simplicial complex with 36 vertices and 18 facets
28
+ Defn: [0, 1, 2, 3, 4, 5] --> ['L0R0', 'L1R1', 'L2R2', 'L3R3', 'L4R4', 'L5R5']
29
+
30
+ sage: S = SimplicialComplex([[0,2],[1,5],[3,4]], is_mutable=False)
31
+ sage: T = SimplicialComplex([[0,2],[1,3]], is_mutable=False)
32
+ sage: f = {0:0,1:1,2:2,3:1,4:3,5:3}
33
+ sage: H = Hom(S,T)
34
+ sage: x = H(f)
35
+ sage: x.image()
36
+ Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2), (1, 3)}
37
+ sage: x.is_surjective()
38
+ True
39
+ sage: x.is_injective()
40
+ False
41
+ sage: x.is_identity()
42
+ False
43
+
44
+ sage: S = simplicial_complexes.Sphere(2)
45
+ sage: H = Hom(S,S)
46
+ sage: i = H.identity()
47
+ sage: i.image()
48
+ Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)}
49
+ sage: i.is_surjective()
50
+ True
51
+ sage: i.is_injective()
52
+ True
53
+ sage: i.is_identity()
54
+ True
55
+
56
+ sage: S = simplicial_complexes.Sphere(2)
57
+ sage: H = Hom(S,S)
58
+ sage: i = H.identity()
59
+ sage: j = i.fiber_product(i)
60
+ sage: j
61
+ Simplicial complex morphism:
62
+ From: Simplicial complex with 4 vertices and 4 facets
63
+ To: Minimal triangulation of the 2-sphere
64
+ Defn: L0R0 |--> 0
65
+ L1R1 |--> 1
66
+ L2R2 |--> 2
67
+ L3R3 |--> 3
68
+ sage: S = simplicial_complexes.Sphere(2)
69
+ sage: T = S.product(SimplicialComplex([[0,1]]), rename_vertices = False, is_mutable=False)
70
+ sage: H = Hom(T,S)
71
+ sage: T
72
+ Simplicial complex with 8 vertices and 12 facets
73
+ sage: sorted(T.vertices())
74
+ [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1), (3, 0), (3, 1)]
75
+ sage: f = {(0, 0): 0, (0, 1): 0, (1, 0): 1, (1, 1): 1, (2, 0): 2, (2, 1): 2, (3, 0): 3, (3, 1): 3}
76
+ sage: x = H(f)
77
+ sage: U = simplicial_complexes.Sphere(1)
78
+ sage: G = Hom(U,S)
79
+ sage: U
80
+ Minimal triangulation of the 1-sphere
81
+ sage: g = {0:0,1:1,2:2}
82
+ sage: y = G(g)
83
+ sage: z = y.fiber_product(x)
84
+ sage: z # this is the mapping path space
85
+ Simplicial complex morphism:
86
+ From: Simplicial complex with 6 vertices and ... facets
87
+ To: Minimal triangulation of the 2-sphere
88
+ Defn: ['L0R(0, 0)', 'L0R(0, 1)', 'L1R(1, 0)', 'L1R(1, 1)', 'L2R(2, 0)', 'L2R(2, 1)'] --> [0, 0, 1, 1, 2, 2]
89
+ """
90
+
91
+ # ****************************************************************************
92
+ # Copyright (C) 2009 D. Benjamin Antieau <d.ben.antieau@gmail.com>
93
+ #
94
+ # Distributed under the terms of the GNU General Public License (GPL)
95
+ #
96
+ # This code is distributed in the hope that it will be useful,
97
+ # but WITHOUT ANY WARRANTY; without even the implied warranty
98
+ # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
99
+ #
100
+ # See the GNU General Public License for more details; the full text
101
+ # is available at:
102
+ #
103
+ # https://www.gnu.org/licenses/
104
+ #
105
+ # ****************************************************************************
106
+
107
+ from sage.categories.homset import Hom
108
+ from sage.categories.morphism import Morphism
109
+ from sage.categories.simplicial_complexes import SimplicialComplexes
110
+ from sage.misc.lazy_import import lazy_import
111
+ from sage.rings.integer_ring import ZZ
112
+
113
+ from .simplicial_complex import Simplex, SimplicialComplex
114
+
115
+ lazy_import('sage.matrix.constructor', ['matrix', 'zero_matrix'])
116
+
117
+
118
+ def is_SimplicialComplexMorphism(x):
119
+ """
120
+ Return ``True`` if and only if ``x`` is a morphism of simplicial complexes.
121
+
122
+ EXAMPLES::
123
+
124
+ sage: from sage.topology.simplicial_complex_morphism import is_SimplicialComplexMorphism
125
+ sage: S = SimplicialComplex([[0,1],[3,4]], is_mutable=False)
126
+ sage: H = Hom(S,S)
127
+ sage: f = {0:0,1:1,3:3,4:4}
128
+ sage: x = H(f)
129
+ sage: is_SimplicialComplexMorphism(x)
130
+ doctest:warning...
131
+ DeprecationWarning: The function is_SimplicialComplexMorphism is deprecated;
132
+ use 'isinstance(..., SimplicialComplexMorphism)' instead.
133
+ See https://github.com/sagemath/sage/issues/38103 for details.
134
+ True
135
+ """
136
+ from sage.misc.superseded import deprecation
137
+ deprecation(38103,
138
+ "The function is_SimplicialComplexMorphism is deprecated; "
139
+ "use 'isinstance(..., SimplicialComplexMorphism)' instead.")
140
+ return isinstance(x, SimplicialComplexMorphism)
141
+
142
+
143
+ class SimplicialComplexMorphism(Morphism):
144
+ """
145
+ An element of this class is a morphism of simplicial complexes.
146
+ """
147
+ def __init__(self, f, X, Y):
148
+ """
149
+ Input is a dictionary ``f``, the domain ``X``, and the codomain ``Y``.
150
+
151
+ One can define the dictionary on the vertices of `X`.
152
+
153
+ EXAMPLES::
154
+
155
+ sage: S = SimplicialComplex([[0,1],[2],[3,4],[5]], is_mutable=False)
156
+ sage: H = Hom(S,S)
157
+ sage: f = {0:0,1:1,2:2,3:3,4:4,5:5}
158
+ sage: g = {0:0,1:1,2:0,3:3,4:4,5:0}
159
+ sage: x = H(f)
160
+ sage: y = H(g)
161
+ sage: x == y
162
+ False
163
+ sage: x.image()
164
+ Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and facets {(2,), (5,), (0, 1), (3, 4)}
165
+ sage: y.image()
166
+ Simplicial complex with vertex set (0, 1, 3, 4) and facets {(0, 1), (3, 4)}
167
+ sage: x.image() == y.image()
168
+ False
169
+ """
170
+ if not isinstance(X, SimplicialComplex) or not isinstance(Y, SimplicialComplex):
171
+ raise ValueError("X and Y must be SimplicialComplexes")
172
+ if set(f.keys()) != set(X.vertices()):
173
+ raise ValueError("f must be a dictionary from the vertex set of X to single values in the vertex set of Y")
174
+ dim = X.dimension()
175
+ Y_faces = Y.faces()
176
+ for k in range(dim + 1):
177
+ for i in X.faces()[k]:
178
+ fi = {f[j] for j in i.tuple()}
179
+ v = Simplex(fi)
180
+ if v not in Y_faces[v.dimension()]:
181
+ raise ValueError("f must be a dictionary from the vertices of X to the vertices of Y")
182
+ self._vertex_dictionary = f
183
+ Morphism.__init__(self, Hom(X, Y, SimplicialComplexes()))
184
+
185
+ def __eq__(self, x):
186
+ """
187
+ Return ``True`` if and only if ``self == x``.
188
+
189
+ EXAMPLES::
190
+
191
+ sage: S = simplicial_complexes.Sphere(2)
192
+ sage: H = Hom(S,S)
193
+ sage: i = H.identity()
194
+ sage: i
195
+ Simplicial complex endomorphism of Minimal triangulation of the 2-sphere
196
+ Defn: 0 |--> 0
197
+ 1 |--> 1
198
+ 2 |--> 2
199
+ 3 |--> 3
200
+ sage: f = {0:0,1:1,2:2,3:2}
201
+ sage: j = H(f)
202
+ sage: i==j
203
+ False
204
+
205
+ sage: T = SimplicialComplex([[1,2]], is_mutable=False)
206
+ sage: T
207
+ Simplicial complex with vertex set (1, 2) and facets {(1, 2)}
208
+ sage: G = Hom(T,T)
209
+ sage: k = G.identity()
210
+ sage: g = {1:1,2:2}
211
+ sage: l = G(g)
212
+ sage: k == l
213
+ True
214
+ """
215
+ if not isinstance(x, SimplicialComplexMorphism) or self.codomain() != x.codomain() or self.domain() != x.domain() or self._vertex_dictionary != x._vertex_dictionary:
216
+ return False
217
+ else:
218
+ return True
219
+
220
+ def __call__(self, x, orientation=False):
221
+ """
222
+ Input is a simplex of the domain. Output is the image simplex.
223
+
224
+ If the optional argument ``orientation`` is ``True``, then this
225
+ returns a pair ``(image simplex, oriented)`` where ``oriented``
226
+ is 1 or `-1` depending on whether the map preserves or reverses
227
+ the orientation of the image simplex.
228
+
229
+ EXAMPLES::
230
+
231
+ sage: S = simplicial_complexes.Sphere(2)
232
+ sage: T = simplicial_complexes.Sphere(3)
233
+ sage: S
234
+ Minimal triangulation of the 2-sphere
235
+ sage: T
236
+ Minimal triangulation of the 3-sphere
237
+ sage: f = {0:0,1:1,2:2,3:3}
238
+ sage: H = Hom(S,T)
239
+ sage: x = H(f)
240
+ sage: from sage.topology.simplicial_complex import Simplex
241
+ sage: x(Simplex([0,2,3]))
242
+ (0, 2, 3)
243
+
244
+ An orientation-reversing example::
245
+
246
+ sage: X = SimplicialComplex([[0,1]], is_mutable=False)
247
+ sage: g = Hom(X,X)({0:1, 1:0})
248
+ sage: g(Simplex([0,1]))
249
+ (0, 1)
250
+ sage: g(Simplex([0,1]), orientation=True) # needs sage.modules
251
+ ((0, 1), -1)
252
+
253
+ TESTS:
254
+
255
+ Test that the problem in :issue:`36849` has been fixed::
256
+
257
+ sage: S = SimplicialComplex([[1,2]],is_mutable=False).barycentric_subdivision()
258
+ sage: T = SimplicialComplex([[1,2],[2,3],[1,3]],is_mutable=False).barycentric_subdivision()
259
+ sage: f = {x[0]:x[0] for x in S.cells()[0]}
260
+ sage: H = Hom(S,T)
261
+ sage: z = H(f)
262
+ sage: z.associated_chain_complex_morphism() # needs sage.modules
263
+ Chain complex morphism:
264
+ From: Chain complex with at most 2 nonzero terms over Integer Ring
265
+ To: Chain complex with at most 2 nonzero terms over Integer Ring
266
+ """
267
+ dim = self.domain().dimension()
268
+ if not isinstance(x, Simplex) or x.dimension() > dim or x not in self.domain().faces()[x.dimension()]:
269
+ raise ValueError("x must be a simplex of the source of f")
270
+ tup = x.tuple()
271
+ fx = [self._vertex_dictionary[j] for j in tup]
272
+ if orientation:
273
+ from sage.algebras.steenrod.steenrod_algebra_misc import convert_perm
274
+ from sage.combinat.permutation import Permutation
275
+
276
+ if len(set(fx)) == len(tup):
277
+ # We need to compare the image simplex, as given in
278
+ # the order specified by self, with its orientation in
279
+ # the codomain.
280
+ image = Simplex(set(fx))
281
+ Y_faces = self.codomain()._n_cells_sorted(image.dimension())
282
+ idx = Y_faces.index(image)
283
+ actual_image = Y_faces[idx]
284
+ # The signature of the permutation specified by self:
285
+ sign_image = Permutation(convert_perm(fx)).signature()
286
+ # The signature of the permutation of the simplex in the domain:
287
+ sign_simplex = Permutation(convert_perm(actual_image)).signature()
288
+ oriented = sign_image * sign_simplex
289
+ else:
290
+ oriented = 1
291
+ return (Simplex(set(fx)), oriented)
292
+ else:
293
+ return Simplex(set(fx))
294
+
295
+ def _repr_type(self):
296
+ """
297
+ EXAMPLES::
298
+
299
+ sage: S = simplicial_complexes.Sphere(1)
300
+ sage: T = simplicial_complexes.Sphere(2)
301
+ sage: H = Hom(S,T)
302
+ sage: f = {0:0,1:1,2:2}
303
+ sage: H(f)._repr_type()
304
+ 'Simplicial complex'
305
+ """
306
+ return "Simplicial complex"
307
+
308
+ def _repr_defn(self):
309
+ """
310
+ If there are fewer than 5 vertices, print the image of each vertex
311
+ on a separate line. Otherwise, print the map as a single line.
312
+
313
+ EXAMPLES::
314
+
315
+ sage: S = simplicial_complexes.Simplex(1)
316
+ sage: print(Hom(S,S).identity()._repr_defn())
317
+ 0 |--> 0
318
+ 1 |--> 1
319
+ sage: T = simplicial_complexes.Torus()
320
+ sage: print(Hom(T,T).identity()._repr_defn())
321
+ [0, 1, 2, 3, 4, 5, 6] --> [0, 1, 2, 3, 4, 5, 6]
322
+ """
323
+ vd = self._vertex_dictionary
324
+ try:
325
+ keys = sorted(vd.keys())
326
+ except TypeError:
327
+ keys = sorted(vd.keys(), key=str)
328
+ if len(vd) < 5:
329
+ return '\n'.join("{} |--> {}".format(v, vd[v]) for v in keys)
330
+ domain = list(vd.keys())
331
+ try:
332
+ domain = sorted(domain)
333
+ except TypeError:
334
+ domain = sorted(domain, key=str)
335
+ codomain = [vd[v] for v in domain]
336
+ return "{} --> {}".format(domain, codomain)
337
+
338
+ def associated_chain_complex_morphism(self, base_ring=ZZ,
339
+ augmented=False, cochain=False):
340
+ """
341
+ Return the associated chain complex morphism of ``self``.
342
+
343
+ EXAMPLES::
344
+
345
+ sage: # needs sage.modules
346
+ sage: S = simplicial_complexes.Sphere(1)
347
+ sage: T = simplicial_complexes.Sphere(2)
348
+ sage: H = Hom(S, T)
349
+ sage: f = {0:0, 1:1, 2:2}
350
+ sage: x = H(f); x
351
+ Simplicial complex morphism:
352
+ From: Minimal triangulation of the 1-sphere
353
+ To: Minimal triangulation of the 2-sphere
354
+ Defn: 0 |--> 0
355
+ 1 |--> 1
356
+ 2 |--> 2
357
+ sage: a = x.associated_chain_complex_morphism(); a
358
+ Chain complex morphism:
359
+ From: Chain complex with at most 2 nonzero terms over Integer Ring
360
+ To: Chain complex with at most 3 nonzero terms over Integer Ring
361
+ sage: a._matrix_dictionary
362
+ {0: [1 0 0]
363
+ [0 1 0]
364
+ [0 0 1]
365
+ [0 0 0],
366
+ 1: [1 0 0]
367
+ [0 1 0]
368
+ [0 0 0]
369
+ [0 0 1]
370
+ [0 0 0]
371
+ [0 0 0],
372
+ 2: []}
373
+ sage: x.associated_chain_complex_morphism(augmented=True)
374
+ Chain complex morphism:
375
+ From: Chain complex with at most 3 nonzero terms over Integer Ring
376
+ To: Chain complex with at most 4 nonzero terms over Integer Ring
377
+ sage: x.associated_chain_complex_morphism(cochain=True)
378
+ Chain complex morphism:
379
+ From: Chain complex with at most 3 nonzero terms over Integer Ring
380
+ To: Chain complex with at most 2 nonzero terms over Integer Ring
381
+ sage: x.associated_chain_complex_morphism(augmented=True, cochain=True)
382
+ Chain complex morphism:
383
+ From: Chain complex with at most 4 nonzero terms over Integer Ring
384
+ To: Chain complex with at most 3 nonzero terms over Integer Ring
385
+ sage: x.associated_chain_complex_morphism(base_ring=GF(11))
386
+ Chain complex morphism:
387
+ From: Chain complex with at most 2 nonzero terms over Finite Field of size 11
388
+ To: Chain complex with at most 3 nonzero terms over Finite Field of size 11
389
+
390
+ Some simplicial maps which reverse the orientation of a few simplices::
391
+
392
+ sage: # needs sage.modules
393
+ sage: g = {0:1, 1:2, 2:0}
394
+ sage: H(g).associated_chain_complex_morphism()._matrix_dictionary
395
+ {0: [0 0 1]
396
+ [1 0 0]
397
+ [0 1 0]
398
+ [0 0 0],
399
+ 1: [ 0 -1 0]
400
+ [ 0 0 -1]
401
+ [ 0 0 0]
402
+ [ 1 0 0]
403
+ [ 0 0 0]
404
+ [ 0 0 0],
405
+ 2: []}
406
+ sage: X = SimplicialComplex([[0, 1]], is_mutable=False)
407
+ sage: Hom(X,X)({0:1, 1:0}).associated_chain_complex_morphism()._matrix_dictionary
408
+ {0: [0 1]
409
+ [1 0],
410
+ 1: [-1]}
411
+ """
412
+ from sage.homology.chain_complex_morphism import ChainComplexMorphism
413
+
414
+ max_dim = max(self.domain().dimension(), self.codomain().dimension())
415
+ min_dim = min(self.domain().dimension(), self.codomain().dimension())
416
+ matrices = {}
417
+ if augmented is True:
418
+ m = matrix(base_ring, 1, 1, 1)
419
+ if not cochain:
420
+ matrices[-1] = m
421
+ else:
422
+ matrices[-1] = m.transpose()
423
+ for dim in range(min_dim+1):
424
+ X_faces = self.domain()._n_cells_sorted(dim)
425
+ Y_faces = self.codomain()._n_cells_sorted(dim)
426
+ num_faces_X = len(X_faces)
427
+ num_faces_Y = len(Y_faces)
428
+ mval = [0 for i in range(num_faces_X*num_faces_Y)]
429
+ for i in X_faces:
430
+ y, oriented = self(i, orientation=True)
431
+ if y.dimension() < dim:
432
+ pass
433
+ else:
434
+ mval[X_faces.index(i)+(Y_faces.index(y)*num_faces_X)] = oriented
435
+ m = matrix(base_ring, num_faces_Y, num_faces_X, mval, sparse=True)
436
+ if not cochain:
437
+ matrices[dim] = m
438
+ else:
439
+ matrices[dim] = m.transpose()
440
+ for dim in range(min_dim+1, max_dim+1):
441
+ try:
442
+ l1 = len(self.codomain().n_cells(dim))
443
+ except KeyError:
444
+ l1 = 0
445
+ try:
446
+ l2 = len(self.domain().n_cells(dim))
447
+ except KeyError:
448
+ l2 = 0
449
+ m = zero_matrix(base_ring, l1, l2, sparse=True)
450
+ if not cochain:
451
+ matrices[dim] = m
452
+ else:
453
+ matrices[dim] = m.transpose()
454
+ if not cochain:
455
+ return ChainComplexMorphism(matrices,
456
+ self.domain().chain_complex(base_ring=base_ring, augmented=augmented, cochain=cochain),
457
+ self.codomain().chain_complex(base_ring=base_ring, augmented=augmented, cochain=cochain))
458
+ return ChainComplexMorphism(matrices,
459
+ self.codomain().chain_complex(base_ring=base_ring, augmented=augmented, cochain=cochain),
460
+ self.domain().chain_complex(base_ring=base_ring, augmented=augmented, cochain=cochain))
461
+
462
+ def image(self):
463
+ """
464
+ Compute the image simplicial complex of `f`.
465
+
466
+ EXAMPLES::
467
+
468
+ sage: S = SimplicialComplex([[0,1],[2,3]], is_mutable=False)
469
+ sage: T = SimplicialComplex([[0,1]], is_mutable=False)
470
+ sage: f = {0:0,1:1,2:0,3:1}
471
+ sage: H = Hom(S,T)
472
+ sage: x = H(f)
473
+ sage: x.image()
474
+ Simplicial complex with vertex set (0, 1) and facets {(0, 1)}
475
+
476
+ sage: S = SimplicialComplex(is_mutable=False)
477
+ sage: H = Hom(S,S)
478
+ sage: i = H.identity()
479
+ sage: i.image()
480
+ Simplicial complex with vertex set () and facets {()}
481
+ sage: i.is_surjective()
482
+ True
483
+ sage: S = SimplicialComplex([[0,1]], is_mutable=False)
484
+ sage: T = SimplicialComplex([[0,1], [0,2]], is_mutable=False)
485
+ sage: f = {0:0,1:1}
486
+ sage: g = {0:0,1:1}
487
+ sage: k = {0:0,1:2}
488
+ sage: H = Hom(S,T)
489
+ sage: x = H(f)
490
+ sage: y = H(g)
491
+ sage: z = H(k)
492
+ sage: x == y
493
+ True
494
+ sage: x == z
495
+ False
496
+ sage: x.image()
497
+ Simplicial complex with vertex set (0, 1) and facets {(0, 1)}
498
+ sage: y.image()
499
+ Simplicial complex with vertex set (0, 1) and facets {(0, 1)}
500
+ sage: z.image()
501
+ Simplicial complex with vertex set (0, 2) and facets {(0, 2)}
502
+ """
503
+ fa = [self(i) for i in self.domain().facets()]
504
+ return SimplicialComplex(fa, maximality_check=True)
505
+
506
+ def is_surjective(self):
507
+ """
508
+ Return ``True`` if and only if ``self`` is surjective.
509
+
510
+ EXAMPLES::
511
+
512
+ sage: S = SimplicialComplex([(0,1,2)], is_mutable=False)
513
+ sage: S
514
+ Simplicial complex with vertex set (0, 1, 2) and facets {(0, 1, 2)}
515
+ sage: T = SimplicialComplex([(0,1)], is_mutable=False)
516
+ sage: T
517
+ Simplicial complex with vertex set (0, 1) and facets {(0, 1)}
518
+ sage: H = Hom(S,T)
519
+ sage: x = H({0:0,1:1,2:1})
520
+ sage: x.is_surjective()
521
+ True
522
+
523
+ sage: S = SimplicialComplex([[0,1],[2,3]], is_mutable=False)
524
+ sage: T = SimplicialComplex([[0,1]], is_mutable=False)
525
+ sage: f = {0:0,1:1,2:0,3:1}
526
+ sage: H = Hom(S,T)
527
+ sage: x = H(f)
528
+ sage: x.is_surjective()
529
+ True
530
+ """
531
+ return self.codomain() == self.image()
532
+
533
+ def is_injective(self):
534
+ """
535
+ Return ``True`` if and only if ``self`` is injective.
536
+
537
+ EXAMPLES::
538
+
539
+ sage: S = simplicial_complexes.Sphere(1)
540
+ sage: T = simplicial_complexes.Sphere(2)
541
+ sage: U = simplicial_complexes.Sphere(3)
542
+ sage: H = Hom(T,S)
543
+ sage: G = Hom(T,U)
544
+ sage: f = {0:0,1:1,2:0,3:1}
545
+ sage: x = H(f)
546
+ sage: g = {0:0,1:1,2:2,3:3}
547
+ sage: y = G(g)
548
+ sage: x.is_injective()
549
+ False
550
+ sage: y.is_injective()
551
+ True
552
+ """
553
+ v = [self._vertex_dictionary[i[0]] for i in self.domain().faces()[0]]
554
+ for i in v:
555
+ if v.count(i) > 1:
556
+ return False
557
+ return True
558
+
559
+ def is_identity(self) -> bool:
560
+ """
561
+ If ``self`` is an identity morphism, returns ``True``.
562
+ Otherwise, ``False``.
563
+
564
+ EXAMPLES::
565
+
566
+ sage: T = simplicial_complexes.Sphere(1)
567
+ sage: G = Hom(T,T)
568
+ sage: T
569
+ Minimal triangulation of the 1-sphere
570
+ sage: j = G({0:0,1:1,2:2})
571
+ sage: j.is_identity()
572
+ True
573
+
574
+ sage: S = simplicial_complexes.Sphere(2)
575
+ sage: T = simplicial_complexes.Sphere(3)
576
+ sage: H = Hom(S,T)
577
+ sage: f = {0:0,1:1,2:2,3:3}
578
+ sage: x = H(f)
579
+ sage: x
580
+ Simplicial complex morphism:
581
+ From: Minimal triangulation of the 2-sphere
582
+ To: Minimal triangulation of the 3-sphere
583
+ Defn: 0 |--> 0
584
+ 1 |--> 1
585
+ 2 |--> 2
586
+ 3 |--> 3
587
+ sage: x.is_identity()
588
+ False
589
+ """
590
+ if self.domain() != self.codomain():
591
+ return False
592
+
593
+ f = {i: i for i in self.domain().vertices()}
594
+ return self._vertex_dictionary == f
595
+
596
+ def fiber_product(self, other, rename_vertices=True):
597
+ """
598
+ Fiber product of ``self`` and ``other``.
599
+
600
+ Both morphisms should have
601
+ the same codomain. The method returns a morphism of simplicial
602
+ complexes, which is the morphism from the space of the fiber product
603
+ to the codomain.
604
+
605
+ EXAMPLES::
606
+
607
+ sage: S = SimplicialComplex([[0,1],[1,2]], is_mutable=False)
608
+ sage: T = SimplicialComplex([[0,2],[1]], is_mutable=False)
609
+ sage: U = SimplicialComplex([[0,1],[2]], is_mutable=False)
610
+ sage: H = Hom(S,U)
611
+ sage: G = Hom(T,U)
612
+ sage: f = {0:0,1:1,2:0}
613
+ sage: g = {0:0,1:1,2:1}
614
+ sage: x = H(f)
615
+ sage: y = G(g)
616
+ sage: z = x.fiber_product(y)
617
+ sage: z
618
+ Simplicial complex morphism:
619
+ From: Simplicial complex with 4 vertices and facets {...}
620
+ To: Simplicial complex with vertex set (0, 1, 2) and facets {(2,), (0, 1)}
621
+ Defn: L0R0 |--> 0
622
+ L1R1 |--> 1
623
+ L1R2 |--> 1
624
+ L2R0 |--> 0
625
+ """
626
+ if self.codomain() != other.codomain():
627
+ raise ValueError("self and other must have the same codomain")
628
+ X = self.domain().product(other.domain(), rename_vertices=rename_vertices)
629
+ v = []
630
+ f = {}
631
+ eff1 = self.domain().vertices()
632
+ eff2 = other.domain().vertices()
633
+ for i in eff1:
634
+ for j in eff2:
635
+ if self(Simplex([i])) == other(Simplex([j])):
636
+ if rename_vertices:
637
+ v.append("L"+str(i)+"R"+str(j))
638
+ f["L"+str(i)+"R"+str(j)] = self._vertex_dictionary[i]
639
+ else:
640
+ v.append((i, j))
641
+ f[(i, j)] = self._vertex_dictionary[i]
642
+ return SimplicialComplexMorphism(f, X.generated_subcomplex(v), self.codomain())
643
+
644
+ def mapping_torus(self):
645
+ r"""
646
+ The mapping torus of a simplicial complex endomorphism.
647
+
648
+ The mapping torus is the simplicial complex formed by taking
649
+ the product of the domain of ``self`` with a `4` point
650
+ interval `[I_0, I_1, I_2, I_3]` and identifying vertices of
651
+ the form `(I_0, v)` with `(I_3, w)` where `w` is the image of
652
+ `v` under the given morphism.
653
+
654
+ See :wikipedia:`Mapping torus`
655
+
656
+ EXAMPLES::
657
+
658
+ sage: C = simplicial_complexes.Sphere(1) # Circle
659
+ sage: T = Hom(C,C).identity().mapping_torus() ; T # Torus
660
+ Simplicial complex with 9 vertices and 18 facets
661
+ sage: T.homology() == simplicial_complexes.Torus().homology() # needs sage.modules
662
+ True
663
+
664
+ sage: f = Hom(C,C)({0:0, 1:2, 2:1})
665
+ sage: K = f.mapping_torus(); K # Klein Bottle
666
+ Simplicial complex with 9 vertices and 18 facets
667
+ sage: K.homology() == simplicial_complexes.KleinBottle().homology() # needs sage.modules
668
+ True
669
+
670
+ TESTS::
671
+
672
+ sage: g = Hom(simplicial_complexes.Simplex([1]),C)({1:0})
673
+ sage: g.mapping_torus()
674
+ Traceback (most recent call last):
675
+ ...
676
+ ValueError: self must have the same domain and codomain
677
+ """
678
+ if self.domain() != self.codomain():
679
+ raise ValueError("self must have the same domain and codomain")
680
+ map_dict = self._vertex_dictionary
681
+ interval = SimplicialComplex([["I0", "I1"], ["I1", "I2"]])
682
+ product = interval.product(self.domain(), False)
683
+ facets = list(product.maximal_faces())
684
+ for facet in self.domain()._facets:
685
+ left = [("I0", v) for v in facet]
686
+ right = [("I2", map_dict[v]) for v in facet]
687
+ facets.extend(tuple(left[:i + 1] + right[i:])
688
+ for i in range(facet.dimension() + 1))
689
+ return SimplicialComplex(facets)
690
+
691
+ def induced_homology_morphism(self, base_ring=None, cohomology=False):
692
+ """
693
+ Return the map in (co)homology induced by this map.
694
+
695
+ INPUT:
696
+
697
+ - ``base_ring`` -- must be a field (default: ``QQ``)
698
+
699
+ - ``cohomology`` -- boolean (default: ``False``); if
700
+ ``True``, the map induced in cohomology rather than homology
701
+
702
+ EXAMPLES::
703
+
704
+ sage: S = simplicial_complexes.Sphere(1)
705
+ sage: T = S.product(S, is_mutable=False)
706
+ sage: H = Hom(S,T)
707
+ sage: diag = H.diagonal_morphism()
708
+ sage: h = diag.induced_homology_morphism(QQ); h # needs sage.modules
709
+ Graded vector space morphism:
710
+ From: Homology module of
711
+ Minimal triangulation of the 1-sphere over Rational Field
712
+ To: Homology module of
713
+ Simplicial complex with 9 vertices and 18 facets over Rational Field
714
+ Defn: induced by:
715
+ Simplicial complex morphism:
716
+ From: Minimal triangulation of the 1-sphere
717
+ To: Simplicial complex with 9 vertices and 18 facets
718
+ Defn: 0 |--> L0R0
719
+ 1 |--> L1R1
720
+ 2 |--> L2R2
721
+
722
+ We can view the matrix form for the homomorphism::
723
+
724
+ sage: h.to_matrix(0) # in degree 0 # needs sage.modules
725
+ [1]
726
+ sage: h.to_matrix(1) # in degree 1 # needs sage.modules
727
+ [1]
728
+ [1]
729
+ sage: h.to_matrix() # the entire homomorphism # needs sage.modules
730
+ [1|0]
731
+ [-+-]
732
+ [0|1]
733
+ [0|1]
734
+ [-+-]
735
+ [0|0]
736
+
737
+ The map on cohomology should be dual to the map on homology::
738
+
739
+ sage: coh = diag.induced_homology_morphism(QQ, cohomology=True) # needs sage.modules
740
+ sage: coh.to_matrix(1) # needs sage.modules
741
+ [1 1]
742
+ sage: h.to_matrix() == coh.to_matrix().transpose() # needs sage.modules
743
+ True
744
+
745
+ We can evaluate the map on (co)homology classes::
746
+
747
+ sage: x,y = list(T.cohomology_ring(QQ).basis(1)) # needs sage.modules
748
+ sage: coh(x) # needs sage.modules
749
+ h^{1,0}
750
+ sage: coh(2*x + 3*y) # needs sage.modules
751
+ 5*h^{1,0}
752
+
753
+ Note that the complexes must be immutable for this to
754
+ work. Many, but not all, complexes are immutable when
755
+ constructed::
756
+
757
+ sage: S.is_immutable()
758
+ True
759
+ sage: S.barycentric_subdivision().is_immutable()
760
+ False
761
+ sage: S2 = S.suspension()
762
+ sage: S2.is_immutable()
763
+ False
764
+ sage: h = Hom(S, S2)({0: 0, 1: 1, 2: 2}).induced_homology_morphism() # needs sage.modules
765
+ Traceback (most recent call last):
766
+ ...
767
+ ValueError: the domain and codomain complexes must be immutable
768
+ sage: S2.set_immutable(); S2.is_immutable()
769
+ True
770
+ sage: h = Hom(S, S2)({0: 0, 1: 1, 2: 2}).induced_homology_morphism() # needs sage.modules
771
+ """
772
+ from sage.homology.homology_morphism import InducedHomologyMorphism
773
+ return InducedHomologyMorphism(self, base_ring, cohomology)
774
+
775
+ def is_contiguous_to(self, other):
776
+ r"""
777
+ Return ``True`` if ``self`` is contiguous to ``other``.
778
+
779
+ Two morphisms `f_0, f_1: K \to L` are *contiguous* if for any
780
+ simplex `\sigma \in K`, the union `f_0(\sigma) \cup
781
+ f_1(\sigma)` is a simplex in `L`. This is not a transitive
782
+ relation, but it induces an equivalence relation on simplicial
783
+ maps: `f` is equivalent to `g` if there is a finite sequence
784
+ `f_0 = f`, `f_1`, ..., `f_n = g` such that `f_i` and `f_{i+1}`
785
+ are contiguous for each `i`.
786
+
787
+ This is related to maps being homotopic: if they are
788
+ contiguous, then they induce homotopic maps on the geometric
789
+ realizations. Given two homotopic maps on the geometric
790
+ realizations, then after barycentrically subdividing `n` times
791
+ for some `n`, the maps have simplicial approximations which
792
+ are in the same contiguity class. (This last fact is only true
793
+ if the domain is a *finite* simplicial complex, by the way.)
794
+
795
+ See Section 3.5 of Spanier [Spa1966]_ for details.
796
+
797
+ ALGORITHM:
798
+
799
+ It is enough to check when `\sigma` ranges over the facets.
800
+
801
+ INPUT:
802
+
803
+ - ``other`` -- a simplicial complex morphism with the same
804
+ domain and codomain as ``self``
805
+
806
+ EXAMPLES::
807
+
808
+ sage: K = simplicial_complexes.Simplex(1)
809
+ sage: L = simplicial_complexes.Sphere(1)
810
+ sage: H = Hom(K, L)
811
+ sage: f = H({0: 0, 1: 1})
812
+ sage: g = H({0: 0, 1: 0})
813
+ sage: f.is_contiguous_to(f)
814
+ True
815
+ sage: f.is_contiguous_to(g)
816
+ True
817
+ sage: h = H({0: 1, 1: 2})
818
+ sage: f.is_contiguous_to(h)
819
+ False
820
+
821
+ TESTS::
822
+
823
+ sage: one = Hom(K,K).identity()
824
+ sage: one.is_contiguous_to(f)
825
+ False
826
+ sage: one.is_contiguous_to(3) # nonsensical input
827
+ False
828
+ """
829
+ if not isinstance(other, SimplicialComplexMorphism):
830
+ return False
831
+ if self.codomain() != other.codomain() or self.domain() != other.domain():
832
+ return False
833
+ domain = self.domain()
834
+ codomain = self.codomain()
835
+ return all(Simplex(self(sigma).set().union(other(sigma))) in codomain
836
+ for sigma in domain.facets())