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.
- {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/METADATA +5 -6
- {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/RECORD +132 -130
- sage/combinat/abstract_tree.py +188 -17
- sage/combinat/cluster_algebra_quiver/interact.py +1 -2
- sage/combinat/cluster_algebra_quiver/mutation_type.py +518 -519
- sage/combinat/cluster_algebra_quiver/quiver.py +233 -205
- sage/combinat/designs/covering_design.py +2 -6
- sage/combinat/designs/database.py +11 -10
- sage/combinat/designs/designs_pyx.cpython-312-darwin.so +0 -0
- sage/combinat/designs/designs_pyx.pyx +2 -2
- sage/combinat/designs/evenly_distributed_sets.cpython-312-darwin.so +0 -0
- sage/combinat/designs/evenly_distributed_sets.pyx +4 -4
- sage/combinat/designs/gen_quadrangles_with_spread.cpython-312-darwin.so +0 -0
- sage/combinat/designs/latin_squares.py +53 -20
- sage/combinat/designs/orthogonal_arrays.py +2 -1
- sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-312-darwin.so +0 -0
- sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +22 -21
- sage/combinat/designs/resolvable_bibd.py +191 -157
- sage/combinat/designs/subhypergraph_search.cpython-312-darwin.so +0 -0
- sage/combinat/designs/subhypergraph_search.pyx +4 -4
- sage/combinat/designs/twographs.py +2 -2
- sage/combinat/finite_state_machine.py +6 -6
- sage/combinat/posets/bubble_shuffle.py +247 -0
- sage/combinat/posets/d_complete.py +3 -3
- sage/combinat/posets/elements.py +3 -3
- sage/combinat/posets/hasse_cython.cpython-312-darwin.so +0 -0
- sage/combinat/posets/hasse_cython.pyx +1 -1
- sage/combinat/posets/hasse_diagram.py +16 -22
- sage/combinat/posets/hochschild_lattice.py +158 -0
- sage/combinat/posets/incidence_algebras.py +14 -16
- sage/combinat/posets/lattices.py +51 -53
- sage/combinat/posets/linear_extension_iterator.cpython-312-darwin.so +0 -0
- sage/combinat/posets/linear_extensions.py +10 -12
- sage/combinat/posets/moebius_algebra.py +4 -4
- sage/combinat/posets/poset_examples.py +70 -23
- sage/combinat/posets/posets.py +294 -103
- sage/databases/knotinfo_db.py +2 -1
- sage/graphs/asteroidal_triples.cpython-312-darwin.so +0 -0
- sage/graphs/asteroidal_triples.pyx +24 -3
- sage/graphs/base/boost_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/boost_graph.pxd +3 -3
- sage/graphs/base/c_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/c_graph.pyx +1 -1
- sage/graphs/base/dense_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/dense_graph.pxd +5 -3
- sage/graphs/base/dense_graph.pyx +44 -0
- sage/graphs/base/graph_backends.cpython-312-darwin.so +0 -0
- sage/graphs/base/sparse_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/static_dense_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/static_sparse_backend.cpython-312-darwin.so +0 -0
- sage/graphs/base/static_sparse_backend.pyx +8 -5
- sage/graphs/base/static_sparse_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/static_sparse_graph.pyx +86 -15
- sage/graphs/bipartite_graph.py +59 -36
- sage/graphs/centrality.cpython-312-darwin.so +0 -0
- sage/graphs/centrality.pyx +82 -9
- sage/graphs/cographs.py +1 -1
- sage/graphs/comparability.cpython-312-darwin.so +0 -0
- sage/graphs/comparability.pyx +64 -26
- sage/graphs/connectivity.cpython-312-darwin.so +0 -0
- sage/graphs/convexity_properties.cpython-312-darwin.so +0 -0
- sage/graphs/convexity_properties.pyx +52 -9
- sage/graphs/digraph.py +439 -95
- sage/graphs/digraph_generators.py +174 -102
- sage/graphs/distances_all_pairs.cpython-312-darwin.so +0 -0
- sage/graphs/dot2tex_utils.py +1 -1
- sage/graphs/edge_connectivity.cpython-312-darwin.so +0 -0
- sage/graphs/generators/basic.py +1 -1
- sage/graphs/generators/distance_regular.cpython-312-darwin.so +0 -0
- sage/graphs/generators/distance_regular.pyx +1 -1
- sage/graphs/generators/families.py +37 -27
- sage/graphs/generators/random.py +2 -2
- sage/graphs/generators/smallgraphs.py +3 -3
- sage/graphs/generic_graph.py +558 -86
- sage/graphs/generic_graph_pyx.cpython-312-darwin.so +0 -0
- sage/graphs/generic_graph_pyx.pyx +58 -11
- sage/graphs/genus.cpython-312-darwin.so +0 -0
- sage/graphs/genus.pyx +3 -4
- sage/graphs/graph.py +291 -8
- sage/graphs/graph_coloring.cpython-312-darwin.so +0 -0
- sage/graphs/graph_database.py +67 -12
- sage/graphs/graph_decompositions/bandwidth.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/clique_separators.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/clique_separators.pyx +24 -3
- sage/graphs/graph_decompositions/cutwidth.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/fast_digraph.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/fast_digraph.pyx +1 -1
- sage/graphs/graph_decompositions/graph_products.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/graph_products.pyx +67 -21
- sage/graphs/graph_decompositions/modular_decomposition.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/slice_decomposition.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/slice_decomposition.pyx +34 -8
- sage/graphs/graph_decompositions/tree_decomposition.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/vertex_separation.cpython-312-darwin.so +0 -0
- sage/graphs/graph_generators.py +45 -32
- sage/graphs/graph_generators_pyx.cpython-312-darwin.so +0 -0
- sage/graphs/graph_generators_pyx.pyx +15 -15
- sage/graphs/graph_latex.py +1 -1
- sage/graphs/graph_list.py +52 -9
- sage/graphs/graph_plot.py +7 -0
- sage/graphs/hyperbolicity.cpython-312-darwin.so +0 -0
- sage/graphs/hyperbolicity.pyx +2 -0
- sage/graphs/independent_sets.cpython-312-darwin.so +0 -0
- sage/graphs/isoperimetric_inequalities.cpython-312-darwin.so +0 -0
- sage/graphs/isoperimetric_inequalities.pyx +42 -6
- sage/graphs/line_graph.cpython-312-darwin.so +0 -0
- sage/graphs/line_graph.pyx +153 -37
- sage/graphs/matching_covered_graph.py +84 -60
- sage/graphs/orientations.py +3 -18
- sage/graphs/path_enumeration.cpython-312-darwin.so +0 -0
- sage/graphs/path_enumeration.pyx +2 -2
- sage/graphs/spanning_tree.cpython-312-darwin.so +0 -0
- sage/graphs/strongly_regular_db.cpython-312-darwin.so +0 -0
- sage/graphs/strongly_regular_db.pyx +15 -15
- sage/graphs/traversals.cpython-312-darwin.so +0 -0
- sage/graphs/traversals.pyx +13 -12
- sage/graphs/trees.cpython-312-darwin.so +0 -0
- sage/graphs/tutte_polynomial.py +1 -1
- sage/graphs/views.cpython-312-darwin.so +0 -0
- sage/graphs/weakly_chordal.cpython-312-darwin.so +0 -0
- sage/graphs/weakly_chordal.pyx +50 -8
- sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-312-darwin.so +0 -0
- sage/knots/free_knotinfo_monoid.py +3 -3
- sage/knots/knotinfo.py +102 -82
- sage/knots/link.py +72 -39
- sage/topology/cubical_complex.py +4 -5
- sage/topology/delta_complex.py +4 -4
- sage/topology/simplicial_complex.py +0 -1
- sage/topology/simplicial_complex_catalog.py +6 -0
- sage/topology/simplicial_complex_examples.py +4 -16
- {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/WHEEL +0 -0
- {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
|
-
#
|
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
|
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
|
-
|
131
|
-
|
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
|
|
sage/combinat/posets/elements.py
CHANGED
@@ -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
|
|
Binary file
|
@@ -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
|
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
|
-
|
264
|
-
|
265
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1186
|
+
if algorithm == 'cython':
|
1189
1187
|
return coxeter_matrix_fast(self._leq_storage) # noqa: F821
|
1190
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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)])
|