passagemath-graphs 10.5.43__cp312-cp312-macosx_14_0_arm64.whl → 10.6.1rc2__cp312-cp312-macosx_14_0_arm64.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 (132) hide show
  1. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/METADATA +5 -6
  2. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/RECORD +132 -130
  3. sage/combinat/abstract_tree.py +188 -17
  4. sage/combinat/cluster_algebra_quiver/interact.py +1 -2
  5. sage/combinat/cluster_algebra_quiver/mutation_type.py +518 -519
  6. sage/combinat/cluster_algebra_quiver/quiver.py +233 -205
  7. sage/combinat/designs/covering_design.py +2 -6
  8. sage/combinat/designs/database.py +11 -10
  9. sage/combinat/designs/designs_pyx.cpython-312-darwin.so +0 -0
  10. sage/combinat/designs/designs_pyx.pyx +2 -2
  11. sage/combinat/designs/evenly_distributed_sets.cpython-312-darwin.so +0 -0
  12. sage/combinat/designs/evenly_distributed_sets.pyx +4 -4
  13. sage/combinat/designs/gen_quadrangles_with_spread.cpython-312-darwin.so +0 -0
  14. sage/combinat/designs/latin_squares.py +53 -20
  15. sage/combinat/designs/orthogonal_arrays.py +2 -1
  16. sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-312-darwin.so +0 -0
  17. sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +22 -21
  18. sage/combinat/designs/resolvable_bibd.py +191 -157
  19. sage/combinat/designs/subhypergraph_search.cpython-312-darwin.so +0 -0
  20. sage/combinat/designs/subhypergraph_search.pyx +4 -4
  21. sage/combinat/designs/twographs.py +2 -2
  22. sage/combinat/finite_state_machine.py +6 -6
  23. sage/combinat/posets/bubble_shuffle.py +247 -0
  24. sage/combinat/posets/d_complete.py +3 -3
  25. sage/combinat/posets/elements.py +3 -3
  26. sage/combinat/posets/hasse_cython.cpython-312-darwin.so +0 -0
  27. sage/combinat/posets/hasse_cython.pyx +1 -1
  28. sage/combinat/posets/hasse_diagram.py +16 -22
  29. sage/combinat/posets/hochschild_lattice.py +158 -0
  30. sage/combinat/posets/incidence_algebras.py +14 -16
  31. sage/combinat/posets/lattices.py +51 -53
  32. sage/combinat/posets/linear_extension_iterator.cpython-312-darwin.so +0 -0
  33. sage/combinat/posets/linear_extensions.py +10 -12
  34. sage/combinat/posets/moebius_algebra.py +4 -4
  35. sage/combinat/posets/poset_examples.py +70 -23
  36. sage/combinat/posets/posets.py +294 -103
  37. sage/databases/knotinfo_db.py +2 -1
  38. sage/graphs/asteroidal_triples.cpython-312-darwin.so +0 -0
  39. sage/graphs/asteroidal_triples.pyx +24 -3
  40. sage/graphs/base/boost_graph.cpython-312-darwin.so +0 -0
  41. sage/graphs/base/boost_graph.pxd +3 -3
  42. sage/graphs/base/c_graph.cpython-312-darwin.so +0 -0
  43. sage/graphs/base/c_graph.pyx +1 -1
  44. sage/graphs/base/dense_graph.cpython-312-darwin.so +0 -0
  45. sage/graphs/base/dense_graph.pxd +5 -3
  46. sage/graphs/base/dense_graph.pyx +44 -0
  47. sage/graphs/base/graph_backends.cpython-312-darwin.so +0 -0
  48. sage/graphs/base/sparse_graph.cpython-312-darwin.so +0 -0
  49. sage/graphs/base/static_dense_graph.cpython-312-darwin.so +0 -0
  50. sage/graphs/base/static_sparse_backend.cpython-312-darwin.so +0 -0
  51. sage/graphs/base/static_sparse_backend.pyx +8 -5
  52. sage/graphs/base/static_sparse_graph.cpython-312-darwin.so +0 -0
  53. sage/graphs/base/static_sparse_graph.pyx +86 -15
  54. sage/graphs/bipartite_graph.py +59 -36
  55. sage/graphs/centrality.cpython-312-darwin.so +0 -0
  56. sage/graphs/centrality.pyx +82 -9
  57. sage/graphs/cographs.py +1 -1
  58. sage/graphs/comparability.cpython-312-darwin.so +0 -0
  59. sage/graphs/comparability.pyx +64 -26
  60. sage/graphs/connectivity.cpython-312-darwin.so +0 -0
  61. sage/graphs/convexity_properties.cpython-312-darwin.so +0 -0
  62. sage/graphs/convexity_properties.pyx +52 -9
  63. sage/graphs/digraph.py +439 -95
  64. sage/graphs/digraph_generators.py +174 -102
  65. sage/graphs/distances_all_pairs.cpython-312-darwin.so +0 -0
  66. sage/graphs/dot2tex_utils.py +1 -1
  67. sage/graphs/edge_connectivity.cpython-312-darwin.so +0 -0
  68. sage/graphs/generators/basic.py +1 -1
  69. sage/graphs/generators/distance_regular.cpython-312-darwin.so +0 -0
  70. sage/graphs/generators/distance_regular.pyx +1 -1
  71. sage/graphs/generators/families.py +37 -27
  72. sage/graphs/generators/random.py +2 -2
  73. sage/graphs/generators/smallgraphs.py +3 -3
  74. sage/graphs/generic_graph.py +558 -86
  75. sage/graphs/generic_graph_pyx.cpython-312-darwin.so +0 -0
  76. sage/graphs/generic_graph_pyx.pyx +58 -11
  77. sage/graphs/genus.cpython-312-darwin.so +0 -0
  78. sage/graphs/genus.pyx +3 -4
  79. sage/graphs/graph.py +291 -8
  80. sage/graphs/graph_coloring.cpython-312-darwin.so +0 -0
  81. sage/graphs/graph_database.py +67 -12
  82. sage/graphs/graph_decompositions/bandwidth.cpython-312-darwin.so +0 -0
  83. sage/graphs/graph_decompositions/clique_separators.cpython-312-darwin.so +0 -0
  84. sage/graphs/graph_decompositions/clique_separators.pyx +24 -3
  85. sage/graphs/graph_decompositions/cutwidth.cpython-312-darwin.so +0 -0
  86. sage/graphs/graph_decompositions/fast_digraph.cpython-312-darwin.so +0 -0
  87. sage/graphs/graph_decompositions/fast_digraph.pyx +1 -1
  88. sage/graphs/graph_decompositions/graph_products.cpython-312-darwin.so +0 -0
  89. sage/graphs/graph_decompositions/graph_products.pyx +67 -21
  90. sage/graphs/graph_decompositions/modular_decomposition.cpython-312-darwin.so +0 -0
  91. sage/graphs/graph_decompositions/slice_decomposition.cpython-312-darwin.so +0 -0
  92. sage/graphs/graph_decompositions/slice_decomposition.pyx +34 -8
  93. sage/graphs/graph_decompositions/tree_decomposition.cpython-312-darwin.so +0 -0
  94. sage/graphs/graph_decompositions/vertex_separation.cpython-312-darwin.so +0 -0
  95. sage/graphs/graph_generators.py +45 -32
  96. sage/graphs/graph_generators_pyx.cpython-312-darwin.so +0 -0
  97. sage/graphs/graph_generators_pyx.pyx +15 -15
  98. sage/graphs/graph_latex.py +1 -1
  99. sage/graphs/graph_list.py +52 -9
  100. sage/graphs/graph_plot.py +7 -0
  101. sage/graphs/hyperbolicity.cpython-312-darwin.so +0 -0
  102. sage/graphs/hyperbolicity.pyx +2 -0
  103. sage/graphs/independent_sets.cpython-312-darwin.so +0 -0
  104. sage/graphs/isoperimetric_inequalities.cpython-312-darwin.so +0 -0
  105. sage/graphs/isoperimetric_inequalities.pyx +42 -6
  106. sage/graphs/line_graph.cpython-312-darwin.so +0 -0
  107. sage/graphs/line_graph.pyx +153 -37
  108. sage/graphs/matching_covered_graph.py +84 -60
  109. sage/graphs/orientations.py +3 -18
  110. sage/graphs/path_enumeration.cpython-312-darwin.so +0 -0
  111. sage/graphs/path_enumeration.pyx +2 -2
  112. sage/graphs/spanning_tree.cpython-312-darwin.so +0 -0
  113. sage/graphs/strongly_regular_db.cpython-312-darwin.so +0 -0
  114. sage/graphs/strongly_regular_db.pyx +15 -15
  115. sage/graphs/traversals.cpython-312-darwin.so +0 -0
  116. sage/graphs/traversals.pyx +13 -12
  117. sage/graphs/trees.cpython-312-darwin.so +0 -0
  118. sage/graphs/tutte_polynomial.py +1 -1
  119. sage/graphs/views.cpython-312-darwin.so +0 -0
  120. sage/graphs/weakly_chordal.cpython-312-darwin.so +0 -0
  121. sage/graphs/weakly_chordal.pyx +50 -8
  122. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-312-darwin.so +0 -0
  123. sage/knots/free_knotinfo_monoid.py +3 -3
  124. sage/knots/knotinfo.py +102 -82
  125. sage/knots/link.py +72 -39
  126. sage/topology/cubical_complex.py +4 -5
  127. sage/topology/delta_complex.py +4 -4
  128. sage/topology/simplicial_complex.py +0 -1
  129. sage/topology/simplicial_complex_catalog.py +6 -0
  130. sage/topology/simplicial_complex_examples.py +4 -16
  131. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/WHEEL +0 -0
  132. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/top_level.txt +0 -0
@@ -115,7 +115,7 @@ Methods
115
115
  # Distributed under the terms of the GNU General Public License (GPL)
116
116
  # as published by the Free Software Foundation; either version 2 of
117
117
  # the License, or (at your option) any later version.
118
- # http://www.gnu.org/licenses/
118
+ # https://www.gnu.org/licenses/
119
119
  # ****************************************************************************
120
120
 
121
121
  from libc.stdlib cimport qsort
@@ -134,7 +134,7 @@ cdef inline int bs_get(uint64_t * bitset, int index) noexcept:
134
134
  r"""
135
135
  Return a bit of a bitset
136
136
  """
137
- return (bitset[index//64]>>(index%64))&1
137
+ return (bitset[index // 64] >> (index % 64)) & 1
138
138
 
139
139
  cdef inline void bs_set(uint64_t * bitset, int index, int bit) noexcept:
140
140
  r"""
@@ -143,8 +143,8 @@ cdef inline void bs_set(uint64_t * bitset, int index, int bit) noexcept:
143
143
  "bit" *MUST* be equal to either 0 or to 1. The code does not involve any
144
144
  "if".
145
145
  """
146
- bitset[index//64] &= ~((<uint64_t> 1)<<index%64)
147
- bitset[index//64] |= (<uint64_t> bit)<<index%64
146
+ bitset[index // 64] &= ~((<uint64_t> 1) << index % 64)
147
+ bitset[index // 64] |= (<uint64_t> bit) << index % 64
148
148
 
149
149
  cdef inline int bs_issubset64(uint64_t * b1, uint64_t b2, int limbs) noexcept:
150
150
  r"""
@@ -244,13 +244,13 @@ def is_twograph(T) -> bool:
244
244
  for x in B:
245
245
  v_to_blocks[x].add(B)
246
246
 
247
- def has_triple(x_y_z):
247
+ def has_triple(x_y_z) -> bool:
248
248
  x, y, z = x_y_z
249
249
  return bool(v_to_blocks[x] & v_to_blocks[y] & v_to_blocks[z])
250
250
 
251
251
  # Check that every quadruple contains an even number of triples
252
252
  for quad in combinations(range(T.num_points()), 4):
253
- if sum(map(has_triple, combinations(quad, 3))) % 2 == 1:
253
+ if sum(map(has_triple, combinations(quad, 3))) % 2:
254
254
  return False
255
255
 
256
256
  return True
@@ -5416,7 +5416,7 @@ class FiniteStateMachine(SageObject):
5416
5416
  # properties (state and transitions)
5417
5417
  # ************************************************************************
5418
5418
 
5419
- def has_state(self, state):
5419
+ def has_state(self, state) -> bool:
5420
5420
  """
5421
5421
  Return whether ``state`` is one of the states of the finite
5422
5422
  state machine.
@@ -5438,7 +5438,7 @@ class FiniteStateMachine(SageObject):
5438
5438
  except LookupError:
5439
5439
  return False
5440
5440
 
5441
- def has_transition(self, transition):
5441
+ def has_transition(self, transition) -> bool:
5442
5442
  """
5443
5443
  Return whether ``transition`` is one of the transitions of
5444
5444
  the finite state machine.
@@ -5464,7 +5464,7 @@ class FiniteStateMachine(SageObject):
5464
5464
  return transition in self.iter_transitions()
5465
5465
  raise TypeError("Transition is not an instance of FSMTransition.")
5466
5466
 
5467
- def has_initial_state(self, state):
5467
+ def has_initial_state(self, state) -> bool:
5468
5468
  """
5469
5469
  Return whether ``state`` is one of the initial states of the
5470
5470
  finite state machine.
@@ -5486,7 +5486,7 @@ class FiniteStateMachine(SageObject):
5486
5486
  except LookupError:
5487
5487
  return False
5488
5488
 
5489
- def has_initial_states(self):
5489
+ def has_initial_states(self) -> bool:
5490
5490
  """
5491
5491
  Return whether the finite state machine has an initial state.
5492
5492
 
@@ -5499,7 +5499,7 @@ class FiniteStateMachine(SageObject):
5499
5499
  """
5500
5500
  return bool(self.initial_states())
5501
5501
 
5502
- def has_final_state(self, state):
5502
+ def has_final_state(self, state) -> bool:
5503
5503
  """
5504
5504
  Return whether ``state`` is one of the final states of the
5505
5505
  finite state machine.
@@ -5520,7 +5520,7 @@ class FiniteStateMachine(SageObject):
5520
5520
  except LookupError:
5521
5521
  return False
5522
5522
 
5523
- def has_final_states(self):
5523
+ def has_final_states(self) -> bool:
5524
5524
  """
5525
5525
  Return whether the finite state machine has a final state.
5526
5526
 
@@ -0,0 +1,247 @@
1
+ # sage_setup: distribution = sagemath-graphs
2
+ # sage.doctest: needs sage.combinat sage.modules
3
+ r"""
4
+ Bubble and Shuffle lattices
5
+
6
+ Shuffle lattices were defined by Greene in [Gre1988]_.
7
+
8
+ Bubble lattices were introduced by McConville and Mühle in [MacCM2022]_.
9
+
10
+ The Bubble lattice `B_{m,n}` and the Shuffle lattice `S_{m,n}` share
11
+ the same underlying set, namely all shuffles of two subwords of the
12
+ two words `X = (x_1,x_2,\ldots,x_{m})` and `Y = (y_1,y_2,\ldots,y_n)`.
13
+
14
+ .. NOTE::
15
+
16
+ In the implementation here, the underlying set is the set of all shuffles
17
+ of subsets of `\{-m,\ldots,-1\}` with subsets of `\{1,\ldots,n\}`.
18
+ """
19
+ from typing import Iterator
20
+
21
+ from sage.combinat.posets.lattices import LatticePoset
22
+ from sage.combinat.subset import subsets
23
+ from sage.graphs.digraph import DiGraph
24
+ from sage.graphs.graph import Graph
25
+ from sage.misc.lazy_import import lazy_import
26
+ from sage.rings.integer import Integer
27
+ from sage.rings.integer_ring import ZZ
28
+
29
+ lazy_import('sage.combinat.shuffle', 'ShuffleProduct')
30
+
31
+
32
+ def bubble_cardinality(m, n) -> Integer:
33
+ r"""
34
+ Return the cardinality of the Bubble lattice `B_{m,n}`.
35
+
36
+ We have
37
+
38
+ .. MATH::
39
+
40
+ |B_{m,n}| = \sum_{i=0}^m \sum_{j=0}^n \binom{i+j}{j} \binom{m}{i} \binom{n}{j}.
41
+
42
+ This is also the cardinality of the Shuffle lattice `S_{m,n}`.
43
+
44
+ INPUT:
45
+
46
+ - ``m`` -- integer
47
+ - ``n`` -- integer
48
+
49
+ EXAMPLES::
50
+
51
+ sage: from sage.combinat.posets.bubble_shuffle import bubble_cardinality
52
+ sage: bubble_cardinality(2,1)
53
+ 12
54
+ """
55
+ return ZZ.sum(ZZ(i + j).binomial(j) * ZZ(m).binomial(i) * ZZ(n).binomial(j)
56
+ for i in range(m + 1) for j in range(n + 1))
57
+
58
+
59
+ def bubble_set(m, n) -> Iterator[tuple[int, ...]]:
60
+ r"""
61
+ Return the underlying set of the Bubble lattice `B_{m,n}`.
62
+
63
+ This is the set of all shuffles of subsets of `\{-m,\ldots,-1\}`
64
+ with subsets of `\{1,\ldots,n\}`.
65
+
66
+ This is also the underlying set of the Shuffle lattice `S_{m,n}`.
67
+
68
+ INPUT:
69
+
70
+ - ``m`` -- integer
71
+ - ``n`` -- integer
72
+
73
+ EXAMPLES::
74
+
75
+ sage: from sage.combinat.posets.bubble_shuffle import bubble_set
76
+ sage: list(bubble_set(2,1))
77
+ [(),
78
+ (1,),
79
+ (-1,),
80
+ (-1, 1),
81
+ (1, -1),
82
+ (-2,),
83
+ (-2, 1),
84
+ (1, -2),
85
+ (-1, -2),
86
+ (-1, -2, 1),
87
+ (1, -1, -2),
88
+ (-1, 1, -2)]
89
+ """
90
+ X = [-i for i in range(1, m + 1)]
91
+ Y = list(range(1, n + 1))
92
+ for subX in subsets(X):
93
+ wX = tuple(subX)
94
+ for subY in subsets(Y):
95
+ for shu in ShuffleProduct(wX, tuple(subY)):
96
+ yield tuple(shu)
97
+
98
+
99
+ def bubble_coverings(m, n, mot, transpose=True) -> Iterator[tuple[int, ...]]:
100
+ """
101
+ Return generating relations of the Bubble lattice `B_{m,n}`.
102
+
103
+ Note that these relations include the cover relations, but not only them.
104
+
105
+ This can also produce covers in the Shuffle lattice `S_{m,n}`.
106
+
107
+ INPUT:
108
+
109
+ - ``m`` -- integer
110
+ - ``n`` -- integer
111
+ - ``mot`` -- element of `B_{m,n}` as a tuple
112
+ - ``transpose`` -- boolean (default: ``True``) whether to return covers
113
+ in the Bubble lattice or in the Shuffle lattice
114
+
115
+ EXAMPLES::
116
+
117
+ sage: from sage.combinat.posets.bubble_shuffle import bubble_coverings
118
+ sage: list(bubble_coverings(2, 1, (-2, 1)))
119
+ [(1,), (1, -2)]
120
+ sage: list(bubble_coverings(2, 1, (-2, 1), False))
121
+ [(1,)]
122
+ """
123
+ # removal of one x
124
+ for j, letter in enumerate(mot):
125
+ if letter < 0:
126
+ yield tuple(mot[:j] + mot[j + 1:])
127
+
128
+ # insertion of one y
129
+ for j in range(len(mot) + 1):
130
+ debut, fin = tuple(mot[:j]), tuple(mot[j:])
131
+ yavant = max((letter for letter in debut if letter > 0), default=0)
132
+ yapres = min((letter for letter in fin if letter > 0), default=n + 1)
133
+ for y in range(yavant + 1, yapres):
134
+ yield debut + (y,) + fin
135
+
136
+ if not transpose:
137
+ return
138
+
139
+ # exchange from xy to yx
140
+ for j in range(len(mot) - 1):
141
+ if mot[j] < 0 and mot[j + 1] > 0:
142
+ mot2 = list(mot)
143
+ mot2[j] = mot[j + 1]
144
+ mot2[j + 1] = mot[j]
145
+ yield tuple(mot2)
146
+
147
+
148
+ def BubblePoset(m, n) -> LatticePoset:
149
+ r"""
150
+ Return the Bubble lattice `B_{m,n}`.
151
+
152
+ Bubble lattices were introduced by McConville and Mühle in [MacCM2022]_.
153
+
154
+ The Bubble lattice `B_{m,n}` and the Shuffle lattice `S_{m,n}` share
155
+ the same underlying set, namely all shuffles of two subwords of the
156
+ two words `X = (x_1,x_2,\ldots,x_{m})` and `Y = (y_1,y_2,\ldots,y_n)`.
157
+
158
+ The Bubble poset is an extension of the Shuffle poset, by adding the
159
+ exchange of adjacent letters from `X` and `Y`, from `xy` to `yx`.
160
+
161
+ .. SEEALSO::
162
+
163
+ :func:`ShufflePoset`, :func:`noncrossing_bipartite_complex`
164
+
165
+ EXAMPLES::
166
+
167
+ sage: P = posets.BubblePoset(2,1); P
168
+ Finite lattice containing 12 elements
169
+ sage: P.zeta_polynomial()
170
+ 1/40*q^5 + 7/24*q^4 + 23/24*q^3 - 7/24*q^2 + 1/60*q
171
+ """
172
+ bubbles = list(bubble_set(m, n))
173
+
174
+ dg = DiGraph([(x, y) for x in bubbles for y in bubble_coverings(m, n, x)])
175
+ # here we have more than just the cover relations
176
+ return LatticePoset(dg)
177
+
178
+
179
+ def ShufflePoset(m, n) -> LatticePoset:
180
+ r"""
181
+ Return the Shuffle lattice `S_{m,n}`.
182
+
183
+ Shuffle lattices were defined by Greene in [Gre1988]_.
184
+
185
+ The Bubble lattice `B_{m,n}` and the Shuffle lattice `S_{m,n}` share
186
+ the same underlying set, namely all shuffles of two subwords of the
187
+ two words `X = (x_1,x_2,\ldots,x_{m})` and `Y = (y_1,y_2,\ldots,y_n)`.
188
+
189
+ The partial order in the Shuffle poset is defined by either inserting a
190
+ letter from `Y` or deleting a letter from `X`.
191
+
192
+ .. SEEALSO:: :func:`BubblePoset`
193
+
194
+ EXAMPLES::
195
+
196
+ sage: P = posets.ShufflePoset(2,1); P
197
+ Finite lattice containing 12 elements
198
+ sage: P.zeta_polynomial()
199
+ 2*q^3 - q^2
200
+ """
201
+ bubbles = list(bubble_set(m, n))
202
+
203
+ dg = DiGraph([(x, y) for x in bubbles
204
+ for y in bubble_coverings(m, n, x, transpose=False)])
205
+ # here we just have the cover relations
206
+ return LatticePoset(dg, cover_relations=True)
207
+
208
+
209
+ def noncrossing_bipartite_complex(m, n):
210
+ """
211
+ Return a simplicial complex related to the Bubble lattice `B_{m,n}`.
212
+
213
+ This is a pure spherical simplicial complex, whose flip graph
214
+ is isomorphic to the Hasse diagram of `B_{m,n}`.
215
+
216
+ .. SEEALSO:: :func:`BubblePoset`
217
+
218
+ EXAMPLES::
219
+
220
+ sage: C = simplicial_complexes.NoncrossingBipartiteComplex(2,1)
221
+ sage: H = C.flip_graph()
222
+ sage: P = posets.BubblePoset(2,1)
223
+ sage: H.is_isomorphic(P.hasse_diagram().to_undirected())
224
+ True
225
+ """
226
+ vertices: list[tuple] = [("x", i) for i in range(1, m + 1)]
227
+ vertices.extend(("y", i) for i in range(1, n + 1))
228
+ vertices.extend(("xy", i, j) for i in range(m + 1) for j in range(n + 1)
229
+ if i or j)
230
+
231
+ def compatible(v: tuple, w: tuple) -> bool:
232
+ if v == w:
233
+ return False
234
+ if v[0] != "xy" and w[0] != "xy":
235
+ return True
236
+ if v[0] == "xy" and w[0] == "xy":
237
+ return not ((w[1] < v[1] and w[2] > v[2])
238
+ or (v[1] < w[1] and v[2] > w[2]))
239
+ if v[0] == "xy":
240
+ if w[0] == "x":
241
+ return v[1] != w[1]
242
+ return v[2] != w[1]
243
+ if v[0] == "x":
244
+ return w[1] != v[1]
245
+ return w[2] != v[1]
246
+
247
+ return Graph([vertices, compatible]).clique_complex()
@@ -127,8 +127,8 @@ class DCompletePoset(FiniteJoinSemilattice):
127
127
  queue.append(c)
128
128
  enqueued.add(c)
129
129
 
130
- poset_hooks = {self._vertex_to_element(key): ZZ(value) for (key, value) in hooks.items()}
131
- return poset_hooks
130
+ return {self._vertex_to_element(key): ZZ(value)
131
+ for (key, value) in hooks.items()}
132
132
 
133
133
  def get_hook(self, elmt):
134
134
  r"""
@@ -143,7 +143,7 @@ class DCompletePoset(FiniteJoinSemilattice):
143
143
  """
144
144
  return self._hooks[elmt]
145
145
 
146
- def get_hooks(self):
146
+ def get_hooks(self) -> dict:
147
147
  r"""
148
148
  Return all the hook lengths as a dictionary.
149
149
 
@@ -54,7 +54,7 @@ class PosetElement(Element):
54
54
  self.element = element
55
55
  self.vertex = vertex
56
56
 
57
- def __hash__(self):
57
+ def __hash__(self) -> int:
58
58
  r"""
59
59
  TESTS::
60
60
 
@@ -65,7 +65,7 @@ class PosetElement(Element):
65
65
  """
66
66
  return hash(self.element)
67
67
 
68
- def _repr_(self):
68
+ def _repr_(self) -> str:
69
69
  """
70
70
  TESTS::
71
71
 
@@ -74,7 +74,7 @@ class PosetElement(Element):
74
74
  """
75
75
  return "%s" % str(self.element)
76
76
 
77
- def _latex_(self):
77
+ def _latex_(self) -> str:
78
78
  r"""
79
79
  Return the latex code of the poset element.
80
80
 
@@ -117,7 +117,7 @@ class IncreasingChains(RecursivelyEnumeratedSet_forest):
117
117
  return True
118
118
  if self._conversion is not None:
119
119
  tup = [self._from_poset[elt] for elt in tup]
120
- if any(not(0 <= i < self._n) for i in tup):
120
+ if not all(0 <= i < self._n for i in tup):
121
121
  return False
122
122
  y = tup[0]
123
123
  for k in range(1, len(tup)):
@@ -92,7 +92,7 @@ class HasseDiagram(DiGraph):
92
92
  Hasse diagram of a poset containing 4 elements
93
93
  sage: TestSuite(H).run()
94
94
  """
95
- def _repr_(self):
95
+ def _repr_(self) -> str:
96
96
  r"""
97
97
  TESTS::
98
98
 
@@ -260,9 +260,9 @@ class HasseDiagram(DiGraph):
260
260
  """
261
261
  if lin_ext is None or lin_ext == list(range(len(self))):
262
262
  return all(x < y for x, y in self.cover_relations_iterator())
263
- else:
264
- return all(lin_ext.index(x) < lin_ext.index(y)
265
- for x, y in self.cover_relations_iterator())
263
+ indices = {x: lin_ext.index(x) for x in self}
264
+ return all(indices[x] < indices[y]
265
+ for x, y in self.cover_relations_iterator())
266
266
 
267
267
  def cover_relations_iterator(self):
268
268
  r"""
@@ -604,7 +604,7 @@ class HasseDiagram(DiGraph):
604
604
  self._intervals = [[sorted(up.intersection(down)) for down in v_down]
605
605
  for up in v_up]
606
606
 
607
- def interval(self, x, y):
607
+ def interval(self, x, y) -> list:
608
608
  r"""
609
609
  Return a list of the elements `z` of ``self`` such that
610
610
  `x \leq z \leq y`.
@@ -674,7 +674,7 @@ class HasseDiagram(DiGraph):
674
674
 
675
675
  closed_interval = interval
676
676
 
677
- def open_interval(self, x, y):
677
+ def open_interval(self, x, y) -> list:
678
678
  """
679
679
  Return a list of the elements `z` of ``self`` such that `x < z < y`.
680
680
 
@@ -694,8 +694,7 @@ class HasseDiagram(DiGraph):
694
694
  ci = self.interval(x, y)
695
695
  if not ci:
696
696
  return []
697
- else:
698
- return ci[1:-1]
697
+ return ci[1:-1]
699
698
 
700
699
  def rank_function(self):
701
700
  r"""
@@ -842,8 +841,7 @@ class HasseDiagram(DiGraph):
842
841
  """
843
842
  if element is None:
844
843
  return len(self.level_sets()) - 1
845
- else:
846
- return self.rank_function()(element)
844
+ return self.rank_function()(element)
847
845
 
848
846
  def is_ranked(self) -> bool:
849
847
  r"""
@@ -1185,10 +1183,9 @@ class HasseDiagram(DiGraph):
1185
1183
  """
1186
1184
  if algorithm == 'matrix':
1187
1185
  return - self.lequal_matrix() * self.moebius_function_matrix().transpose()
1188
- elif algorithm == 'cython':
1186
+ if algorithm == 'cython':
1189
1187
  return coxeter_matrix_fast(self._leq_storage) # noqa: F821
1190
- else:
1191
- raise ValueError("unknown algorithm")
1188
+ raise ValueError("unknown algorithm")
1192
1189
 
1193
1190
  def order_filter(self, elements):
1194
1191
  r"""
@@ -1404,8 +1401,7 @@ class HasseDiagram(DiGraph):
1404
1401
  """
1405
1402
  if boolean:
1406
1403
  return self._leq_matrix_boolean
1407
- else:
1408
- return self._leq_matrix
1404
+ return self._leq_matrix
1409
1405
 
1410
1406
  def _alternate_is_lequal(self, i, j):
1411
1407
  r"""
@@ -1894,8 +1890,7 @@ class HasseDiagram(DiGraph):
1894
1890
  if n < 3:
1895
1891
  if return_list:
1896
1892
  return []
1897
- else:
1898
- return None
1893
+ return None
1899
1894
  result = [] # Never take the bottom element to list.
1900
1895
  m = 0
1901
1896
  for i in range(n - 1):
@@ -1905,8 +1900,7 @@ class HasseDiagram(DiGraph):
1905
1900
  if not return_list:
1906
1901
  if m < n - 1:
1907
1902
  return m
1908
- else:
1909
- return None
1903
+ return None
1910
1904
  result.append(m)
1911
1905
  result.pop() # Remove the top element.
1912
1906
  return result
@@ -2946,7 +2940,7 @@ class HasseDiagram(DiGraph):
2946
2940
 
2947
2941
  return True
2948
2942
 
2949
- def neutral_elements(self):
2943
+ def neutral_elements(self) -> set:
2950
2944
  """
2951
2945
  Return the list of neutral elements of the lattice.
2952
2946
 
@@ -2994,7 +2988,7 @@ class HasseDiagram(DiGraph):
2994
2988
  mt = self.meet_matrix()
2995
2989
  jn = self.join_matrix()
2996
2990
 
2997
- def is_neutral(a):
2991
+ def is_neutral(a) -> bool:
2998
2992
  noncomp = all_elements.difference(self.depth_first_search(a))
2999
2993
  noncomp.difference_update(self.depth_first_search(a, neighbors=self.neighbor_in_iterator))
3000
2994
 
@@ -3086,7 +3080,7 @@ class HasseDiagram(DiGraph):
3086
3080
  result = e
3087
3081
  return result
3088
3082
 
3089
- def atoms_of_congruence_lattice(self):
3083
+ def atoms_of_congruence_lattice(self) -> list:
3090
3084
  r"""
3091
3085
  Return atoms of the congruence lattice.
3092
3086
 
@@ -0,0 +1,158 @@
1
+ # sage_setup: distribution = sagemath-graphs
2
+ # sage.doctest: needs sage.modules
3
+ r"""
4
+ Hochschild lattices
5
+
6
+ Hochschild lattices were defined in [Cha2020]_ as posets and
7
+ shown to be congruence uniform lattices in [Com2021]_.
8
+
9
+ The name comes from the Hochschild polytopes introduced by Sanebdlidze
10
+ in [San2009]_ for the study of free loop spaces in algebraic topology.
11
+ The Hasse diagram of the Hochschild lattice is an orientation of the
12
+ 1-skeleton of the Hochschild polytope.
13
+
14
+ For `n \geq 1`, the cardinality of the Hochschild lattice `H_n` is
15
+ `2^{n - 2} \times (n + 3)`, starting with
16
+ `2, 5, 12, 28, 64, 144, 320, 704, 1536, 3328, 7168, 15360, \ldots`.
17
+
18
+ The underlying set of `H_n` consists of some words in the alphabet
19
+ `(0,1,2)`, whose precise description can be found in [Com2021]_.
20
+ """
21
+ from typing import Iterator
22
+
23
+ from sage.combinat.posets.lattices import LatticePoset
24
+ from sage.topology.simplicial_complex import SimplicialComplex
25
+
26
+
27
+ def hochschild_lattice(n) -> LatticePoset:
28
+ r"""
29
+ Return the Hochschild lattice `H_n`.
30
+
31
+ INPUT:
32
+
33
+ - `n \geq 1` -- an integer
34
+
35
+ The cardinality of `H_n` is `2^{n - 2} \times (n + 3)`.
36
+
37
+ .. SEEALSO:: :func:`hochschild_simplicial_complex`, :func:`hochschild_fan`
38
+
39
+ EXAMPLES::
40
+
41
+ sage: P = posets.HochschildLattice(5); P
42
+ Finite lattice containing 64 elements
43
+ sage: P.degree_polynomial()
44
+ x^5 + 9*x^4*y + 22*x^3*y^2 + 22*x^2*y^3 + 9*x*y^4 + y^5
45
+
46
+ TESTS::
47
+
48
+ sage: posets.HochschildLattice(0)
49
+ Traceback (most recent call last):
50
+ ...
51
+ ValueError: this requires n >= 1
52
+ """
53
+ if n <= 0:
54
+ raise ValueError("this requires n >= 1")
55
+
56
+ def iterator_True(n) -> Iterator[tuple[int, ...]]:
57
+ """
58
+ Iterator over part of the underlying set.
59
+ """
60
+ if n == 0:
61
+ yield ()
62
+ return
63
+ for w in iterator_True(n - 1):
64
+ yield (0,) + w
65
+ yield (2,) + w
66
+
67
+ def iterator_False(n) -> Iterator[tuple[int, ...]]:
68
+ """
69
+ Iterator over rest of the underlying set.
70
+ """
71
+ if n == 0:
72
+ yield ()
73
+ return
74
+ for w in iterator_True(n - 1):
75
+ yield (0,) + w
76
+ for w in iterator_False(n - 1):
77
+ yield (1,) + w
78
+ yield (2,) + w
79
+
80
+ def sommets(n) -> Iterator[tuple[int, ...]]:
81
+ """
82
+ Iterator over the full underlying set.
83
+ """
84
+ for w in iterator_True(n - 1):
85
+ yield (0,) + w
86
+ for w in iterator_False(n - 1):
87
+ yield (1,) + w
88
+
89
+ verts = list(sommets(n))
90
+
91
+ def compare(a, b) -> bool:
92
+ return all(ai <= bi for ai, bi in zip(a, b))
93
+
94
+ return LatticePoset([verts, compare])
95
+
96
+
97
+ def hochschild_fan(n):
98
+ """
99
+ Return Saneblidze's fan for the Hochschild polytope.
100
+
101
+ The dual polytope is obtained from a standard simplex
102
+ by a sequence of truncations.
103
+
104
+ .. SEEALSO::
105
+
106
+ :func:`hochschild_simplicial_complex`, :func:`hochschild_lattice`
107
+
108
+ EXAMPLES::
109
+
110
+ sage: # needs sage.geometry.polyhedron
111
+ sage: from sage.combinat.posets.hochschild_lattice import hochschild_fan
112
+ sage: F = hochschild_fan(4); F
113
+ Rational polyhedral fan in 4-d lattice N
114
+ sage: F.f_vector()
115
+ (1, 11, 39, 56, 28)
116
+ """
117
+ from sage.geometry.cone import Cone
118
+ from sage.geometry.fan import Fan
119
+ from sage.modules.free_module_element import vector
120
+
121
+ rays = [vector([1] * n)]
122
+ rays.extend(vector([0 if j != i else -1 for j in range(n)])
123
+ for i in range(n))
124
+
125
+ cones = [Cone([rays[j] for j in range(n + 1) if j != i])
126
+ for i in range(n + 1)]
127
+
128
+ # standard fan of projective space Pn
129
+ F = Fan(cones, check=False)
130
+
131
+ # double sequence of blowups
132
+ subdiv = [sum(r for r in rays[k + 1:]) for k in range(n - 1)]
133
+ subdiv.extend(sum(r for r in rays[:n - k]) for k in range(n - 1))
134
+
135
+ return F.subdivide(subdiv)
136
+
137
+
138
+ def hochschild_simplicial_complex(n) -> SimplicialComplex:
139
+ """
140
+ Return a simplicial complex related to the Hochschild lattice `H_n`.
141
+
142
+ This is a pure spherical simplicial complex, whose flip graph
143
+ is isomorphic to the Hasse diagram of `H_n`.
144
+
145
+ .. SEEALSO:: :func:`hochschild_fan`, :func:`hochschild_lattice`
146
+
147
+ EXAMPLES::
148
+
149
+ sage: # needs sage.geometry.polyhedron
150
+ sage: C = simplicial_complexes.HochschildSphere(3); C
151
+ Simplicial complex with 8 vertices and 12 facets
152
+ sage: H = C.flip_graph()
153
+ sage: P = posets.HochschildLattice(3)
154
+ sage: H.is_isomorphic(P.hasse_diagram().to_undirected())
155
+ True
156
+ """
157
+ F = hochschild_fan(n)
158
+ return SimplicialComplex([C.rays() for C in F.cones(n)])