passagemath-combinat 10.6.1__cp312-cp312-musllinux_1_2_aarch64.whl → 10.8.1a1__cp312-cp312-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_combinat/__init__.py +3 -0
- {passagemath_combinat-10.6.1.dist-info → passagemath_combinat-10.8.1a1.dist-info}/METADATA +17 -20
- {passagemath_combinat-10.6.1.dist-info → passagemath_combinat-10.8.1a1.dist-info}/RECORD +220 -218
- {passagemath_combinat-10.6.1.dist-info → passagemath_combinat-10.8.1a1.dist-info}/WHEEL +1 -1
- passagemath_combinat-10.8.1a1.dist-info/top_level.txt +3 -0
- sage/algebras/affine_nil_temperley_lieb.py +3 -3
- sage/algebras/all.py +0 -1
- sage/algebras/askey_wilson.py +1 -1
- sage/algebras/associated_graded.py +2 -2
- sage/algebras/cellular_basis.py +3 -6
- sage/algebras/cluster_algebra.py +2 -3
- sage/algebras/down_up_algebra.py +6 -6
- sage/algebras/free_algebra.py +3 -32
- sage/algebras/free_algebra_element.py +21 -25
- sage/algebras/free_algebra_quotient_element.py +9 -38
- sage/algebras/free_zinbiel_algebra.py +4 -3
- sage/algebras/hall_algebra.py +2 -2
- sage/algebras/hecke_algebras/ariki_koike_algebra.py +8 -8
- sage/algebras/hecke_algebras/ariki_koike_specht_modules.py +2 -2
- sage/algebras/hecke_algebras/cubic_hecke_algebra.py +11 -14
- sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +1 -1
- sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py +5 -5
- sage/algebras/iwahori_hecke_algebra.py +59 -57
- sage/algebras/jordan_algebra.py +97 -89
- sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py +6 -6
- sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py +14 -12
- sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py +6 -6
- sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py +4 -4
- sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py +13 -13
- sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py +8 -6
- sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +7 -5
- sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py +7 -7
- sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py +6 -5
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +12 -11
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py +3 -3
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py +3 -3
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +11 -11
- sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py +3 -3
- sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py +8 -7
- sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py +9 -8
- sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py +6 -5
- sage/algebras/nil_coxeter_algebra.py +4 -4
- sage/algebras/q_commuting_polynomials.py +6 -6
- sage/algebras/q_system.py +3 -3
- sage/algebras/quantum_clifford.py +8 -8
- sage/algebras/quantum_groups/fock_space.py +48 -8
- sage/algebras/quantum_groups/quantum_group_gap.py +5 -7
- sage/algebras/quantum_matrix_coordinate_algebra.py +7 -7
- sage/algebras/quantum_oscillator.py +3 -3
- sage/algebras/quaternion_algebra_element.py +5 -3
- sage/algebras/schur_algebra.py +3 -3
- sage/algebras/shuffle_algebra.py +5 -8
- sage/algebras/splitting_algebra.py +129 -85
- sage/algebras/tensor_algebra.py +7 -7
- sage/algebras/yangian.py +16 -15
- sage/algebras/yokonuma_hecke_algebra.py +13 -11
- sage/combinat/all.py +9 -0
- sage/combinat/all__sagemath_combinat.py +1 -0
- sage/combinat/alternating_sign_matrix.py +36 -29
- sage/combinat/baxter_permutations.py +32 -12
- sage/combinat/bijectionist.py +13 -17
- sage/combinat/chas/fsym.py +6 -6
- sage/combinat/chas/wqsym.py +23 -29
- sage/combinat/colored_permutations.py +9 -11
- sage/combinat/colored_permutations_representations.py +13 -12
- sage/combinat/composition_tableau.py +2 -2
- sage/combinat/constellation.py +57 -30
- sage/combinat/crystals/affine_factorization.py +5 -4
- sage/combinat/crystals/alcove_path.py +2 -2
- sage/combinat/crystals/fully_commutative_stable_grothendieck.py +3 -2
- sage/combinat/crystals/infinity_crystals.py +18 -18
- sage/combinat/crystals/kac_modules.py +1 -1
- sage/combinat/crystals/kirillov_reshetikhin.py +2 -2
- sage/combinat/crystals/letters.cpython-312-aarch64-linux-musl.so +0 -0
- sage/combinat/crystals/littelmann_path.py +1 -1
- sage/combinat/crystals/pbw_datum.cpython-312-aarch64-linux-musl.so +0 -0
- sage/combinat/crystals/pbw_datum.pyx +3 -2
- sage/combinat/crystals/spins.cpython-312-aarch64-linux-musl.so +0 -0
- sage/combinat/crystals/tensor_product.py +7 -5
- sage/combinat/crystals/tensor_product_element.cpython-312-aarch64-linux-musl.so +0 -0
- sage/combinat/debruijn_sequence.cpython-312-aarch64-linux-musl.so +0 -0
- sage/combinat/debruijn_sequence.pyx +1 -2
- sage/combinat/degree_sequences.cpython-312-aarch64-linux-musl.so +0 -0
- sage/combinat/degree_sequences.pyx +241 -188
- sage/combinat/derangements.py +28 -22
- sage/combinat/diagram_algebras.py +12 -14
- sage/combinat/dyck_word.py +15 -14
- sage/combinat/e_one_star.py +1 -1
- sage/combinat/expnums.cpython-312-aarch64-linux-musl.so +0 -0
- sage/combinat/fast_vector_partitions.cpython-312-aarch64-linux-musl.so +0 -0
- sage/combinat/fqsym.py +13 -19
- sage/combinat/free_dendriform_algebra.py +2 -2
- sage/combinat/free_prelie_algebra.py +2 -2
- sage/combinat/fully_commutative_elements.py +8 -8
- sage/combinat/fully_packed_loop.py +9 -9
- sage/combinat/gelfand_tsetlin_patterns.py +4 -5
- sage/combinat/gray_codes.py +3 -4
- sage/combinat/grossman_larson_algebras.py +2 -2
- sage/combinat/growth.py +13 -13
- sage/combinat/hall_polynomial.py +1 -1
- sage/combinat/hillman_grassl.py +1 -1
- sage/combinat/integer_matrices.py +5 -7
- sage/combinat/k_tableau.py +8 -7
- sage/combinat/kazhdan_lusztig.py +3 -3
- sage/combinat/key_polynomial.py +845 -298
- sage/combinat/knutson_tao_puzzles.py +11 -13
- sage/combinat/matrices/hadamard_matrix.py +1 -1
- sage/combinat/matrices/latin.py +75 -92
- sage/combinat/misc.py +3 -3
- sage/combinat/multiset_partition_into_sets_ordered.py +27 -10
- sage/combinat/ncsf_qsym/generic_basis_code.py +5 -5
- sage/combinat/ncsf_qsym/ncsf.py +6 -5
- sage/combinat/ncsf_qsym/qsym.py +9 -17
- sage/combinat/ncsym/ncsym.py +8 -12
- sage/combinat/nu_dyck_word.py +1 -1
- sage/combinat/parallelogram_polyomino.py +3 -5
- sage/combinat/parking_functions.py +6 -5
- sage/combinat/partition_algebra.py +22 -57
- sage/combinat/partition_kleshchev.py +4 -4
- sage/combinat/partition_tuple.py +12 -10
- sage/combinat/plane_partition.py +10 -13
- sage/combinat/positive_integer_semigroup_test.py +17 -0
- sage/combinat/q_bernoulli.cpython-312-aarch64-linux-musl.so +0 -0
- sage/combinat/quickref.py +2 -2
- sage/combinat/recognizable_series.py +2 -2
- sage/combinat/regular_sequence.py +7 -7
- sage/combinat/regular_sequence_bounded.py +15 -21
- sage/combinat/restricted_growth.py +3 -3
- sage/combinat/ribbon.py +3 -3
- sage/combinat/rigged_configurations/bijection.py +3 -3
- sage/combinat/rigged_configurations/rigged_partition.cpython-312-aarch64-linux-musl.so +0 -0
- sage/combinat/rsk.py +2 -0
- sage/combinat/schubert_polynomial.py +11 -2
- sage/combinat/set_partition.py +3 -7
- sage/combinat/set_partition_iterator.cpython-312-aarch64-linux-musl.so +0 -0
- sage/combinat/set_partition_iterator.pyx +0 -1
- sage/combinat/set_partition_ordered.py +2 -2
- sage/combinat/sf/classical.py +1 -1
- sage/combinat/sf/dual.py +4 -8
- sage/combinat/sf/elementary.py +13 -7
- sage/combinat/sf/hall_littlewood.py +10 -8
- sage/combinat/sf/homogeneous.py +6 -3
- sage/combinat/sf/jack.py +11 -9
- sage/combinat/sf/llt.py +4 -5
- sage/combinat/sf/macdonald.py +10 -11
- sage/combinat/sf/monomial.py +6 -0
- sage/combinat/sf/ns_macdonald.py +92 -51
- sage/combinat/sf/powersum.py +9 -14
- sage/combinat/sf/schur.py +6 -0
- sage/combinat/sf/sf.py +21 -19
- sage/combinat/sf/sfa.py +13 -64
- sage/combinat/shifted_primed_tableau.py +5 -7
- sage/combinat/shuffle.py +1 -1
- sage/combinat/sine_gordon.py +18 -38
- sage/combinat/skew_partition.py +9 -12
- sage/combinat/skew_tableau.py +2 -7
- sage/combinat/sloane_functions.py +1 -1
- sage/combinat/species/all.py +67 -2
- sage/combinat/species/characteristic_species.py +3 -0
- sage/combinat/species/composition_species.py +3 -0
- sage/combinat/species/cycle_species.py +4 -0
- sage/combinat/species/empty_species.py +3 -0
- sage/combinat/species/functorial_composition_species.py +3 -0
- sage/combinat/species/generating_series.py +3 -0
- sage/combinat/species/library.py +3 -0
- sage/combinat/species/linear_order_species.py +3 -0
- sage/combinat/species/partition_species.py +3 -0
- sage/combinat/species/permutation_species.py +4 -0
- sage/combinat/species/product_species.py +3 -0
- sage/combinat/species/recursive_species.py +3 -0
- sage/combinat/species/set_species.py +3 -0
- sage/combinat/species/species.py +13 -7
- sage/combinat/species/structure.py +8 -9
- sage/combinat/species/subset_species.py +3 -0
- sage/combinat/species/sum_species.py +3 -0
- sage/combinat/subword.py +4 -1
- sage/combinat/subword_complex.py +7 -7
- sage/combinat/subword_complex_c.cpython-312-aarch64-linux-musl.so +0 -0
- sage/combinat/superpartition.py +1 -1
- sage/combinat/symmetric_group_algebra.py +9 -9
- sage/combinat/symmetric_group_representations.py +5 -5
- sage/combinat/t_sequences.py +4 -4
- sage/combinat/tableau.py +3 -4
- sage/combinat/tableau_tuple.py +2 -2
- sage/combinat/tiling.py +39 -42
- sage/combinat/triangles_FHM.py +38 -15
- sage/combinat/tutorial.py +2 -2
- sage/combinat/vector_partition.py +43 -31
- sage/combinat/words/abstract_word.py +4 -4
- sage/combinat/words/alphabet.py +12 -12
- sage/combinat/words/finite_word.py +25 -229
- sage/combinat/words/infinite_word.py +1 -1
- sage/combinat/words/morphic.py +13 -13
- sage/combinat/words/morphism.py +3 -12
- sage/combinat/words/paths.py +16 -17
- sage/combinat/words/word.py +60 -35
- sage/combinat/words/word_char.cpython-312-aarch64-linux-musl.so +0 -0
- sage/combinat/words/word_char.pyx +46 -7
- sage/combinat/words/word_datatypes.cpython-312-aarch64-linux-musl.so +0 -0
- sage/combinat/words/word_generators.py +39 -38
- sage/databases/findstat.py +72 -31
- sage/databases/oeis.py +125 -25
- sage/databases/sloane.py +14 -8
- sage/games/sudoku_backtrack.cpython-312-aarch64-linux-musl.so +0 -0
- sage/groups/indexed_free_group.py +3 -4
- sage/libs/symmetrica/symmetrica.cpython-312-aarch64-linux-musl.so +0 -0
- sage/libs/symmetrica/symmetrica.pxi +1 -0
- sage/monoids/automatic_semigroup.py +1 -3
- sage/monoids/free_abelian_monoid.py +7 -33
- sage/monoids/free_abelian_monoid_element.cpython-312-aarch64-linux-musl.so +0 -0
- sage/monoids/free_monoid.py +8 -40
- sage/monoids/free_monoid_element.py +1 -9
- sage/monoids/string_monoid.py +5 -2
- sage/monoids/string_monoid_element.py +12 -66
- sage/rings/all__sagemath_combinat.py +7 -0
- sage/sat/solvers/__init__.py +3 -4
- sage/sat/solvers/cryptominisat.py +2 -3
- sage/sat/solvers/picosat.py +2 -3
- sage/sat/solvers/sat_lp.py +2 -2
- sage/sat/solvers/satsolver.cpython-312-aarch64-linux-musl.so +0 -0
- passagemath_combinat-10.6.1.dist-info/top_level.txt +0 -2
|
@@ -180,7 +180,7 @@ class PuzzlePiece:
|
|
|
180
180
|
else:
|
|
181
181
|
edges = self.edges()
|
|
182
182
|
P = Graphics()
|
|
183
|
-
for
|
|
183
|
+
for i, edge in enumerate(edges):
|
|
184
184
|
P += line([coords[i], coords[(i + 1) % 3]],
|
|
185
185
|
color=self.edge_color(edge),
|
|
186
186
|
thickness=border_thickness)
|
|
@@ -1148,11 +1148,10 @@ class PuzzleFilling:
|
|
|
1148
1148
|
sage: P.north_west_label_of_kink()
|
|
1149
1149
|
'1'
|
|
1150
1150
|
"""
|
|
1151
|
-
|
|
1151
|
+
i, j = self.kink_coordinates()
|
|
1152
1152
|
if i == 1:
|
|
1153
1153
|
return self._nw_labels[j - 1]
|
|
1154
|
-
|
|
1155
|
-
return self._squares[i - 1, j]['south_east']
|
|
1154
|
+
return self._squares[i - 1, j]['south_east']
|
|
1156
1155
|
|
|
1157
1156
|
def north_east_label_of_kink(self):
|
|
1158
1157
|
r"""
|
|
@@ -1165,13 +1164,12 @@ class PuzzleFilling:
|
|
|
1165
1164
|
sage: P.north_east_label_of_kink()
|
|
1166
1165
|
'0'
|
|
1167
1166
|
"""
|
|
1168
|
-
|
|
1167
|
+
i, j = self.kink_coordinates()
|
|
1169
1168
|
if j == self._n:
|
|
1170
1169
|
return self._ne_labels[i - 1]
|
|
1171
|
-
|
|
1172
|
-
return self._squares[i, j + 1]['south_west']
|
|
1170
|
+
return self._squares[i, j + 1]['south_west']
|
|
1173
1171
|
|
|
1174
|
-
def is_completed(self):
|
|
1172
|
+
def is_completed(self) -> bool:
|
|
1175
1173
|
r"""
|
|
1176
1174
|
Whether partial puzzle is complete (completely filled) or not.
|
|
1177
1175
|
|
|
@@ -1191,7 +1189,7 @@ class PuzzleFilling:
|
|
|
1191
1189
|
i, _ = self.kink_coordinates()
|
|
1192
1190
|
return i == self._n + 1
|
|
1193
1191
|
|
|
1194
|
-
def south_labels(self):
|
|
1192
|
+
def south_labels(self) -> tuple:
|
|
1195
1193
|
r"""
|
|
1196
1194
|
Return south labels for completed puzzle.
|
|
1197
1195
|
|
|
@@ -1366,9 +1364,9 @@ class PuzzleFilling:
|
|
|
1366
1364
|
"""
|
|
1367
1365
|
P = Graphics()
|
|
1368
1366
|
coords = [(k, -d) for d in range(self._n) for k in range(-d, d + 1, 2)]
|
|
1369
|
-
for (
|
|
1367
|
+
for (k, d), piece in zip(coords, self):
|
|
1370
1368
|
if isinstance(piece, RhombusPiece):
|
|
1371
|
-
for
|
|
1369
|
+
for i, triangle in enumerate(piece):
|
|
1372
1370
|
P += triangle._plot_piece([(k, d - 2 * i), (k - 1, d - 1), (k + 1, d - 1)], style=style)
|
|
1373
1371
|
if labels:
|
|
1374
1372
|
P += piece._plot_label(piece['north_west'], (k - 0.5, d - 0.5), rotation=60)
|
|
@@ -1450,10 +1448,10 @@ class PuzzleFilling:
|
|
|
1450
1448
|
s += ";\n"
|
|
1451
1449
|
return s
|
|
1452
1450
|
|
|
1453
|
-
for (
|
|
1451
|
+
for (k, d), piece in zip(coords, self):
|
|
1454
1452
|
for tikzcmd in (tikztriangle_fill, tikztriangle_edges, tikzlabels):
|
|
1455
1453
|
if isinstance(piece, RhombusPiece):
|
|
1456
|
-
for
|
|
1454
|
+
for i, triangle in enumerate([piece.north_piece(), piece.south_piece()]):
|
|
1457
1455
|
if i == 0:
|
|
1458
1456
|
s += tikzcmd(triangle.color(), k, d, i, *triangle.border())
|
|
1459
1457
|
else:
|
|
@@ -1962,7 +1962,7 @@ def hadamard_matrix_www(url_file, comments=False):
|
|
|
1962
1962
|
[ 1 -1 -1 1 1 1 -1 -1 -1 1 1 -1 -1 -1 1 1]
|
|
1963
1963
|
[ 1 -1 -1 1 -1 -1 1 1 -1 1 1 -1 1 1 -1 -1]
|
|
1964
1964
|
"""
|
|
1965
|
-
n =
|
|
1965
|
+
n = int(url_file.split(".")[1])
|
|
1966
1966
|
rws = []
|
|
1967
1967
|
url = "http://neilsloane.com/hadamard/" + url_file
|
|
1968
1968
|
with urlopen(url) as f:
|
sage/combinat/matrices/latin.py
CHANGED
|
@@ -76,8 +76,8 @@ EXAMPLES::
|
|
|
76
76
|
sage: B.is_latin_square()
|
|
77
77
|
False
|
|
78
78
|
|
|
79
|
-
sage:
|
|
80
|
-
sage:
|
|
79
|
+
sage: a, b, c, G = alternating_group_bitrade_generators(1)
|
|
80
|
+
sage: T1, T2 = bitrade_from_group(a, b, c, G)
|
|
81
81
|
sage: T1
|
|
82
82
|
[ 0 -1 3 1]
|
|
83
83
|
[-1 1 0 2]
|
|
@@ -88,7 +88,7 @@ EXAMPLES::
|
|
|
88
88
|
[-1 0 2 1]
|
|
89
89
|
[ 2 1 3 -1]
|
|
90
90
|
[ 0 3 -1 2]
|
|
91
|
-
sage: T1.
|
|
91
|
+
sage: T1.n_filled_cells()
|
|
92
92
|
12
|
|
93
93
|
sage: genus(T1, T2)
|
|
94
94
|
1
|
|
@@ -149,7 +149,7 @@ from functools import reduce
|
|
|
149
149
|
|
|
150
150
|
|
|
151
151
|
class LatinSquare:
|
|
152
|
-
def __init__(self, *args):
|
|
152
|
+
def __init__(self, *args) -> None:
|
|
153
153
|
"""
|
|
154
154
|
Latin squares.
|
|
155
155
|
|
|
@@ -204,7 +204,7 @@ class LatinSquare:
|
|
|
204
204
|
from sage.misc.persist import dumps
|
|
205
205
|
return dumps(self.square)
|
|
206
206
|
|
|
207
|
-
def __str__(self):
|
|
207
|
+
def __str__(self) -> str:
|
|
208
208
|
"""
|
|
209
209
|
The string representation of a latin square is the same as the
|
|
210
210
|
underlying matrix.
|
|
@@ -217,7 +217,7 @@ class LatinSquare:
|
|
|
217
217
|
"""
|
|
218
218
|
return str(self.square)
|
|
219
219
|
|
|
220
|
-
def __repr__(self):
|
|
220
|
+
def __repr__(self) -> str:
|
|
221
221
|
"""
|
|
222
222
|
The representation of a latin square is the same as the underlying
|
|
223
223
|
matrix.
|
|
@@ -242,13 +242,9 @@ class LatinSquare:
|
|
|
242
242
|
sage: B[1, 1]
|
|
243
243
|
2
|
|
244
244
|
"""
|
|
245
|
+
return self.square[*rc]
|
|
245
246
|
|
|
246
|
-
|
|
247
|
-
c = rc[1]
|
|
248
|
-
|
|
249
|
-
return self.square[r, c]
|
|
250
|
-
|
|
251
|
-
def __setitem__(self, rc, val):
|
|
247
|
+
def __setitem__(self, rc, val) -> None:
|
|
252
248
|
"""
|
|
253
249
|
If L is a LatinSquare then this method allows us to set L[r, c].
|
|
254
250
|
|
|
@@ -260,13 +256,9 @@ class LatinSquare:
|
|
|
260
256
|
sage: B[1, 1]
|
|
261
257
|
10
|
|
262
258
|
"""
|
|
259
|
+
self.square[*rc] = val
|
|
263
260
|
|
|
264
|
-
|
|
265
|
-
c = rc[1]
|
|
266
|
-
|
|
267
|
-
self.square[r, c] = val
|
|
268
|
-
|
|
269
|
-
def set_immutable(self):
|
|
261
|
+
def set_immutable(self) -> None:
|
|
270
262
|
"""
|
|
271
263
|
A latin square is immutable if the underlying matrix is immutable.
|
|
272
264
|
|
|
@@ -278,10 +270,9 @@ class LatinSquare:
|
|
|
278
270
|
{[0 1]
|
|
279
271
|
[2 3]: 0}
|
|
280
272
|
"""
|
|
281
|
-
|
|
282
273
|
self.square.set_immutable()
|
|
283
274
|
|
|
284
|
-
def __hash__(self):
|
|
275
|
+
def __hash__(self) -> int:
|
|
285
276
|
"""
|
|
286
277
|
The hash of a latin square is precisely the hash of the underlying
|
|
287
278
|
matrix.
|
|
@@ -296,7 +287,7 @@ class LatinSquare:
|
|
|
296
287
|
"""
|
|
297
288
|
return hash(self.square)
|
|
298
289
|
|
|
299
|
-
def __eq__(self, Q):
|
|
290
|
+
def __eq__(self, Q) -> bool:
|
|
300
291
|
"""
|
|
301
292
|
Two latin squares are equal if the underlying matrices are equal.
|
|
302
293
|
|
|
@@ -310,7 +301,6 @@ class LatinSquare:
|
|
|
310
301
|
sage: A == B
|
|
311
302
|
True
|
|
312
303
|
"""
|
|
313
|
-
|
|
314
304
|
return self.square == Q.square
|
|
315
305
|
|
|
316
306
|
def __copy__(self):
|
|
@@ -330,7 +320,7 @@ class LatinSquare:
|
|
|
330
320
|
C.square = copy(self.square)
|
|
331
321
|
return C
|
|
332
322
|
|
|
333
|
-
def clear_cells(self):
|
|
323
|
+
def clear_cells(self) -> None:
|
|
334
324
|
"""
|
|
335
325
|
Mark every cell in ``self`` as being empty.
|
|
336
326
|
|
|
@@ -392,7 +382,7 @@ class LatinSquare:
|
|
|
392
382
|
"""
|
|
393
383
|
return self.square.column(x)
|
|
394
384
|
|
|
395
|
-
def list(self):
|
|
385
|
+
def list(self) -> list:
|
|
396
386
|
"""
|
|
397
387
|
Convert the latin square into a list, in a row-wise manner.
|
|
398
388
|
|
|
@@ -404,7 +394,7 @@ class LatinSquare:
|
|
|
404
394
|
"""
|
|
405
395
|
return self.square.list()
|
|
406
396
|
|
|
407
|
-
def
|
|
397
|
+
def n_filled_cells(self) -> int:
|
|
408
398
|
"""
|
|
409
399
|
Return the number of filled cells (i.e. cells with a positive
|
|
410
400
|
value) in the partial latin square ``self``.
|
|
@@ -412,17 +402,15 @@ class LatinSquare:
|
|
|
412
402
|
EXAMPLES::
|
|
413
403
|
|
|
414
404
|
sage: from sage.combinat.matrices.latin import *
|
|
415
|
-
sage: LatinSquare(matrix([[0, -1], [-1, 0]])).
|
|
405
|
+
sage: LatinSquare(matrix([[0, -1], [-1, 0]])).n_filled_cells()
|
|
416
406
|
2
|
|
417
407
|
"""
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
for c in range(self.ncols()):
|
|
421
|
-
if self[r, c] >= 0:
|
|
422
|
-
s += 1
|
|
423
|
-
return s
|
|
408
|
+
return sum(1 for r in range(self.nrows()) for c in range(self.ncols())
|
|
409
|
+
if self[r, c] >= 0)
|
|
424
410
|
|
|
425
|
-
|
|
411
|
+
nr_filled_cells = n_filled_cells
|
|
412
|
+
|
|
413
|
+
def actual_row_col_sym_sizes(self) -> tuple:
|
|
426
414
|
"""
|
|
427
415
|
Bitrades sometimes end up in partial latin squares with unused
|
|
428
416
|
rows, columns, or symbols. This function works out the actual
|
|
@@ -449,7 +437,7 @@ class LatinSquare:
|
|
|
449
437
|
"""
|
|
450
438
|
row_max = self.nrows()
|
|
451
439
|
col_max = self.ncols()
|
|
452
|
-
sym_max = self.
|
|
440
|
+
sym_max = self.n_distinct_symbols()
|
|
453
441
|
|
|
454
442
|
while self.is_empty_row(row_max-1):
|
|
455
443
|
row_max -= 1
|
|
@@ -458,7 +446,7 @@ class LatinSquare:
|
|
|
458
446
|
|
|
459
447
|
return row_max, col_max, sym_max
|
|
460
448
|
|
|
461
|
-
def is_empty_column(self, c):
|
|
449
|
+
def is_empty_column(self, c) -> bool:
|
|
462
450
|
"""
|
|
463
451
|
Check if column c of the partial latin square ``self`` is empty.
|
|
464
452
|
|
|
@@ -472,9 +460,9 @@ class LatinSquare:
|
|
|
472
460
|
sage: L.is_empty_column(0)
|
|
473
461
|
True
|
|
474
462
|
"""
|
|
475
|
-
return
|
|
463
|
+
return all(cf == -1 for cf in self.column(c))
|
|
476
464
|
|
|
477
|
-
def is_empty_row(self, r):
|
|
465
|
+
def is_empty_row(self, r) -> bool:
|
|
478
466
|
"""
|
|
479
467
|
Check if row r of the partial latin square ``self`` is empty.
|
|
480
468
|
|
|
@@ -488,9 +476,9 @@ class LatinSquare:
|
|
|
488
476
|
sage: L.is_empty_row(0)
|
|
489
477
|
True
|
|
490
478
|
"""
|
|
491
|
-
return
|
|
479
|
+
return all(cf == -1 for cf in self.row(r))
|
|
492
480
|
|
|
493
|
-
def
|
|
481
|
+
def n_distinct_symbols(self) -> int:
|
|
494
482
|
"""
|
|
495
483
|
Return the number of distinct symbols in the partial latin square
|
|
496
484
|
``self``.
|
|
@@ -498,19 +486,21 @@ class LatinSquare:
|
|
|
498
486
|
EXAMPLES::
|
|
499
487
|
|
|
500
488
|
sage: from sage.combinat.matrices.latin import *
|
|
501
|
-
sage: back_circulant(5).
|
|
489
|
+
sage: back_circulant(5).n_distinct_symbols()
|
|
502
490
|
5
|
|
503
491
|
sage: L = LatinSquare(10)
|
|
504
|
-
sage: L.
|
|
492
|
+
sage: L.n_distinct_symbols()
|
|
505
493
|
0
|
|
506
494
|
sage: L[0, 0] = 0
|
|
507
495
|
sage: L[0, 1] = 1
|
|
508
|
-
sage: L.
|
|
496
|
+
sage: L.n_distinct_symbols()
|
|
509
497
|
2
|
|
510
498
|
"""
|
|
511
499
|
symbols = set(flatten([list(x) for x in list(self.square)]))
|
|
512
500
|
return sum(1 for x in symbols if x >= 0)
|
|
513
501
|
|
|
502
|
+
nr_distinct_symbols = n_distinct_symbols
|
|
503
|
+
|
|
514
504
|
def apply_isotopism(self, row_perm, col_perm, sym_perm):
|
|
515
505
|
"""
|
|
516
506
|
An isotopism is a permutation of the rows, columns, and symbols of
|
|
@@ -571,8 +561,8 @@ class LatinSquare:
|
|
|
571
561
|
EXAMPLES::
|
|
572
562
|
|
|
573
563
|
sage: from sage.combinat.matrices.latin import *
|
|
574
|
-
sage:
|
|
575
|
-
sage:
|
|
564
|
+
sage: a, b, c, G = alternating_group_bitrade_generators(1)
|
|
565
|
+
sage: T1, T2 = bitrade_from_group(a, b, c, G)
|
|
576
566
|
sage: D = T1.filled_cells_map()
|
|
577
567
|
sage: {i: v for i,v in D.items() if i in ZZ}
|
|
578
568
|
{1: (0, 0),
|
|
@@ -642,7 +632,7 @@ class LatinSquare:
|
|
|
642
632
|
|
|
643
633
|
return None
|
|
644
634
|
|
|
645
|
-
def is_partial_latin_square(self):
|
|
635
|
+
def is_partial_latin_square(self) -> bool:
|
|
646
636
|
"""
|
|
647
637
|
``self`` is a partial latin square if it is an n by n matrix, and each
|
|
648
638
|
symbol in [0, 1, ..., n-1] appears at most once in each row, and at
|
|
@@ -703,7 +693,7 @@ class LatinSquare:
|
|
|
703
693
|
|
|
704
694
|
return True
|
|
705
695
|
|
|
706
|
-
def is_latin_square(self):
|
|
696
|
+
def is_latin_square(self) -> bool:
|
|
707
697
|
"""
|
|
708
698
|
``self`` is a latin square if it is an n by n matrix, and each symbol
|
|
709
699
|
in [0, 1, ..., n-1] appears exactly once in each row, and exactly
|
|
@@ -729,10 +719,7 @@ class LatinSquare:
|
|
|
729
719
|
return False
|
|
730
720
|
|
|
731
721
|
# By necessity self must be a partial latin square:
|
|
732
|
-
|
|
733
|
-
return False
|
|
734
|
-
|
|
735
|
-
return True
|
|
722
|
+
return self.is_partial_latin_square()
|
|
736
723
|
|
|
737
724
|
def permissable_values(self, r, c):
|
|
738
725
|
"""
|
|
@@ -821,7 +808,7 @@ class LatinSquare:
|
|
|
821
808
|
|
|
822
809
|
return [rc[0], rc[1]]
|
|
823
810
|
|
|
824
|
-
def is_uniquely_completable(self):
|
|
811
|
+
def is_uniquely_completable(self) -> bool:
|
|
825
812
|
"""
|
|
826
813
|
Return ``True`` if the partial latin square ``self`` has exactly one
|
|
827
814
|
completion to a latin square. This is just a wrapper for the
|
|
@@ -846,10 +833,9 @@ class LatinSquare:
|
|
|
846
833
|
sage: G.is_uniquely_completable()
|
|
847
834
|
False
|
|
848
835
|
"""
|
|
849
|
-
|
|
850
836
|
return self.dlxcpp_has_unique_completion()
|
|
851
837
|
|
|
852
|
-
def is_completable(self):
|
|
838
|
+
def is_completable(self) -> bool:
|
|
853
839
|
"""
|
|
854
840
|
Return ``True`` if the partial latin square can be completed to a
|
|
855
841
|
latin square.
|
|
@@ -917,7 +903,6 @@ class LatinSquare:
|
|
|
917
903
|
[ 6 -1 4 -1 2 -1 0 -1]
|
|
918
904
|
[-1 -1 -1 -1 -1 -1 -1 -1]
|
|
919
905
|
"""
|
|
920
|
-
|
|
921
906
|
n = self.nrows()
|
|
922
907
|
|
|
923
908
|
from copy import copy
|
|
@@ -933,7 +918,7 @@ class LatinSquare:
|
|
|
933
918
|
|
|
934
919
|
return G
|
|
935
920
|
|
|
936
|
-
def dlxcpp_has_unique_completion(self):
|
|
921
|
+
def dlxcpp_has_unique_completion(self) -> bool:
|
|
937
922
|
"""
|
|
938
923
|
Check if the partial latin square ``self`` of order n can be embedded
|
|
939
924
|
in precisely one latin square of order n.
|
|
@@ -952,7 +937,7 @@ class LatinSquare:
|
|
|
952
937
|
"""
|
|
953
938
|
return len(dlxcpp_find_completions(self, nr_to_find=2)) == 1
|
|
954
939
|
|
|
955
|
-
def vals_in_row(self, r):
|
|
940
|
+
def vals_in_row(self, r) -> dict:
|
|
956
941
|
"""
|
|
957
942
|
Return a dictionary with key e if and only if row r of ``self`` has
|
|
958
943
|
the symbol e.
|
|
@@ -965,7 +950,6 @@ class LatinSquare:
|
|
|
965
950
|
sage: back_circulant(3).vals_in_row(0)
|
|
966
951
|
{0: True, 1: True, 2: True}
|
|
967
952
|
"""
|
|
968
|
-
|
|
969
953
|
n = self.ncols()
|
|
970
954
|
vals_in_row = {}
|
|
971
955
|
|
|
@@ -976,7 +960,7 @@ class LatinSquare:
|
|
|
976
960
|
|
|
977
961
|
return vals_in_row
|
|
978
962
|
|
|
979
|
-
def vals_in_col(self, c):
|
|
963
|
+
def vals_in_col(self, c) -> dict:
|
|
980
964
|
"""
|
|
981
965
|
Return a dictionary with key e if and only if column c of ``self`` has
|
|
982
966
|
the symbol e.
|
|
@@ -999,7 +983,7 @@ class LatinSquare:
|
|
|
999
983
|
|
|
1000
984
|
return vals_in_col
|
|
1001
985
|
|
|
1002
|
-
def latex(self):
|
|
986
|
+
def latex(self) -> str:
|
|
1003
987
|
r"""
|
|
1004
988
|
Return LaTeX code for the latin square.
|
|
1005
989
|
|
|
@@ -1167,7 +1151,6 @@ class LatinSquare:
|
|
|
1167
1151
|
(15, 27, 43): (2, 3, 3),
|
|
1168
1152
|
(15, 31, 47): (3, 3, 3)})
|
|
1169
1153
|
"""
|
|
1170
|
-
|
|
1171
1154
|
assert self.nrows() == self.ncols()
|
|
1172
1155
|
|
|
1173
1156
|
n = self.nrows()
|
|
@@ -1258,10 +1241,10 @@ class LatinSquare:
|
|
|
1258
1241
|
|
|
1259
1242
|
dlx_rows, cmap = self.disjoint_mate_dlxcpp_rows_and_map(allow_subtrade)
|
|
1260
1243
|
|
|
1261
|
-
|
|
1244
|
+
n_found = 0
|
|
1262
1245
|
|
|
1263
1246
|
for x in DLXCPP(dlx_rows):
|
|
1264
|
-
|
|
1247
|
+
n_found += 1
|
|
1265
1248
|
|
|
1266
1249
|
from copy import deepcopy
|
|
1267
1250
|
Q = deepcopy(self)
|
|
@@ -1269,15 +1252,15 @@ class LatinSquare:
|
|
|
1269
1252
|
for y in x:
|
|
1270
1253
|
if len(dlx_rows[y]) == 1:
|
|
1271
1254
|
continue # dummy row
|
|
1272
|
-
|
|
1255
|
+
r, c, e = cmap[tuple(dlx_rows[y])]
|
|
1273
1256
|
Q[r, c] = e
|
|
1274
1257
|
|
|
1275
1258
|
yield Q
|
|
1276
1259
|
|
|
1277
|
-
if nr_to_find is not None and
|
|
1260
|
+
if nr_to_find is not None and n_found >= nr_to_find:
|
|
1278
1261
|
return
|
|
1279
1262
|
|
|
1280
|
-
def contained_in(self, Q):
|
|
1263
|
+
def contained_in(self, Q) -> bool:
|
|
1281
1264
|
r"""
|
|
1282
1265
|
Return ``True`` if ``self`` is a subset of `Q`.
|
|
1283
1266
|
|
|
@@ -1318,17 +1301,17 @@ def genus(T1, T2):
|
|
|
1318
1301
|
EXAMPLES::
|
|
1319
1302
|
|
|
1320
1303
|
sage: from sage.combinat.matrices.latin import *
|
|
1321
|
-
sage:
|
|
1322
|
-
sage:
|
|
1304
|
+
sage: a, b, c, G = alternating_group_bitrade_generators(1)
|
|
1305
|
+
sage: T1, T2 = bitrade_from_group(a, b, c, G)
|
|
1323
1306
|
sage: genus(T1, T2)
|
|
1324
1307
|
1
|
|
1325
|
-
sage:
|
|
1326
|
-
sage:
|
|
1308
|
+
sage: a, b, c, G = pq_group_bitrade_generators(3, 7)
|
|
1309
|
+
sage: T1, T2 = bitrade_from_group(a, b, c, G)
|
|
1327
1310
|
sage: genus(T1, T2)
|
|
1328
1311
|
3
|
|
1329
1312
|
"""
|
|
1330
1313
|
cells_map, t1, t2, t3 = tau123(T1, T2)
|
|
1331
|
-
return (len(t1.to_cycles()) + len(t2.to_cycles()) + len(t3.to_cycles()) - T1.
|
|
1314
|
+
return (len(t1.to_cycles()) + len(t2.to_cycles()) + len(t3.to_cycles()) - T1.n_filled_cells() - 2) // (-2)
|
|
1332
1315
|
|
|
1333
1316
|
|
|
1334
1317
|
def tau123(T1, T2):
|
|
@@ -1348,8 +1331,8 @@ def tau123(T1, T2):
|
|
|
1348
1331
|
EXAMPLES::
|
|
1349
1332
|
|
|
1350
1333
|
sage: from sage.combinat.matrices.latin import *
|
|
1351
|
-
sage:
|
|
1352
|
-
sage:
|
|
1334
|
+
sage: a, b, c, G = pq_group_bitrade_generators(3, 7)
|
|
1335
|
+
sage: T1, T2 = bitrade_from_group(a, b, c, G)
|
|
1353
1336
|
sage: T1
|
|
1354
1337
|
[ 0 1 3 -1 -1 -1 -1]
|
|
1355
1338
|
[ 1 2 4 -1 -1 -1 -1]
|
|
@@ -1366,7 +1349,7 @@ def tau123(T1, T2):
|
|
|
1366
1349
|
[ 5 0 4 -1 -1 -1 -1]
|
|
1367
1350
|
[ 6 1 5 -1 -1 -1 -1]
|
|
1368
1351
|
[ 0 2 6 -1 -1 -1 -1]
|
|
1369
|
-
sage:
|
|
1352
|
+
sage: cells_map, t1, t2, t3 = tau123(T1, T2)
|
|
1370
1353
|
sage: D = cells_map
|
|
1371
1354
|
sage: {i: v for i,v in D.items() if i in ZZ}
|
|
1372
1355
|
{1: (0, 0),
|
|
@@ -1438,7 +1421,7 @@ def tau123(T1, T2):
|
|
|
1438
1421
|
|
|
1439
1422
|
The product t1\*t2\*t3 is the identity, i.e. it fixes every point::
|
|
1440
1423
|
|
|
1441
|
-
sage: len((t1*t2*t3).fixed_points()) == T1.
|
|
1424
|
+
sage: len((t1*t2*t3).fixed_points()) == T1.n_filled_cells()
|
|
1442
1425
|
True
|
|
1443
1426
|
"""
|
|
1444
1427
|
assert is_bitrade(T1, T2)
|
|
@@ -1559,8 +1542,8 @@ def cells_map_as_square(cells_map, n):
|
|
|
1559
1542
|
EXAMPLES::
|
|
1560
1543
|
|
|
1561
1544
|
sage: from sage.combinat.matrices.latin import *
|
|
1562
|
-
sage:
|
|
1563
|
-
sage:
|
|
1545
|
+
sage: a, b, c, G = alternating_group_bitrade_generators(1)
|
|
1546
|
+
sage: T1, T2 = bitrade_from_group(a, b, c, G)
|
|
1564
1547
|
sage: T1
|
|
1565
1548
|
[ 0 -1 3 1]
|
|
1566
1549
|
[-1 1 0 2]
|
|
@@ -1732,7 +1715,7 @@ def tau1(T1, T2, cells_map):
|
|
|
1732
1715
|
sage: T2 = T1.apply_isotopism(x, y, z)
|
|
1733
1716
|
sage: is_bitrade(T1, T2)
|
|
1734
1717
|
True
|
|
1735
|
-
sage:
|
|
1718
|
+
sage: cells_map, t1, t2, t3 = tau123(T1, T2)
|
|
1736
1719
|
sage: t1 = tau1(T1, T2, cells_map)
|
|
1737
1720
|
sage: t1
|
|
1738
1721
|
[2, 3, 4, 5, 1, 7, 8, 9, 10, 6, 12, 13, 14, 15, 11, 17, 18, 19, 20, 16, 22, 23, 24, 25, 21]
|
|
@@ -1752,8 +1735,8 @@ def tau1(T1, T2, cells_map):
|
|
|
1752
1735
|
if e < 0:
|
|
1753
1736
|
continue
|
|
1754
1737
|
|
|
1755
|
-
|
|
1756
|
-
|
|
1738
|
+
r2, c2, e2 = beta2((r, c, e), T1, T2)
|
|
1739
|
+
r3, c3, e3 = beta3((r2, c2, e2), T2, T1)
|
|
1757
1740
|
|
|
1758
1741
|
x[cells_map[(r, c)]] = cells_map[(r3, c3)]
|
|
1759
1742
|
|
|
@@ -1786,7 +1769,7 @@ def tau2(T1, T2, cells_map):
|
|
|
1786
1769
|
sage: T2 = T1.apply_isotopism(x, y, z)
|
|
1787
1770
|
sage: is_bitrade(T1, T2)
|
|
1788
1771
|
True
|
|
1789
|
-
sage:
|
|
1772
|
+
sage: cells_map, t1, t2, t3 = tau123(T1, T2)
|
|
1790
1773
|
sage: t2 = tau2(T1, T2, cells_map)
|
|
1791
1774
|
sage: t2
|
|
1792
1775
|
[21, 22, 23, 24, 25, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
|
@@ -1806,8 +1789,8 @@ def tau2(T1, T2, cells_map):
|
|
|
1806
1789
|
if e < 0:
|
|
1807
1790
|
continue
|
|
1808
1791
|
|
|
1809
|
-
|
|
1810
|
-
|
|
1792
|
+
r2, c2, e2 = beta3((r, c, e), T1, T2)
|
|
1793
|
+
r3, c3, e3 = beta1((r2, c2, e2), T2, T1)
|
|
1811
1794
|
|
|
1812
1795
|
x[cells_map[(r, c)]] = cells_map[(r3, c3)]
|
|
1813
1796
|
|
|
@@ -1840,7 +1823,7 @@ def tau3(T1, T2, cells_map):
|
|
|
1840
1823
|
sage: T2 = T1.apply_isotopism(x, y, z)
|
|
1841
1824
|
sage: is_bitrade(T1, T2)
|
|
1842
1825
|
True
|
|
1843
|
-
sage:
|
|
1826
|
+
sage: cells_map, t1, t2, t3 = tau123(T1, T2)
|
|
1844
1827
|
sage: t3 = tau3(T1, T2, cells_map)
|
|
1845
1828
|
sage: t3
|
|
1846
1829
|
[10, 6, 7, 8, 9, 15, 11, 12, 13, 14, 20, 16, 17, 18, 19, 25, 21, 22, 23, 24, 5, 1, 2, 3, 4]
|
|
@@ -1860,8 +1843,8 @@ def tau3(T1, T2, cells_map):
|
|
|
1860
1843
|
if e < 0:
|
|
1861
1844
|
continue
|
|
1862
1845
|
|
|
1863
|
-
|
|
1864
|
-
|
|
1846
|
+
r2, c2, e2 = beta1((r, c, e), T1, T2)
|
|
1847
|
+
r3, c3, e3 = beta2((r2, c2, e2), T2, T1)
|
|
1865
1848
|
|
|
1866
1849
|
x[cells_map[(r, c)]] = cells_map[(r3, c3)]
|
|
1867
1850
|
|
|
@@ -2358,7 +2341,7 @@ def alternating_group_bitrade_generators(m):
|
|
|
2358
2341
|
|
|
2359
2342
|
::
|
|
2360
2343
|
|
|
2361
|
-
sage:
|
|
2344
|
+
sage: T1, T2 = bitrade_from_group(a, b, c, G)
|
|
2362
2345
|
sage: T1
|
|
2363
2346
|
[ 0 -1 3 1]
|
|
2364
2347
|
[-1 1 0 2]
|
|
@@ -2531,7 +2514,7 @@ def is_primary_bitrade(a, b, c, G):
|
|
|
2531
2514
|
EXAMPLES::
|
|
2532
2515
|
|
|
2533
2516
|
sage: from sage.combinat.matrices.latin import *
|
|
2534
|
-
sage:
|
|
2517
|
+
sage: a, b, c, G = p3_group_bitrade_generators(5)
|
|
2535
2518
|
sage: is_primary_bitrade(a, b, c, G)
|
|
2536
2519
|
True
|
|
2537
2520
|
"""
|
|
@@ -2596,11 +2579,11 @@ def tau_to_bitrade(t1, t2, t3):
|
|
|
2596
2579
|
for r in range(len(c1)):
|
|
2597
2580
|
for c in range(len(c2)):
|
|
2598
2581
|
for s in range(len(c3)):
|
|
2599
|
-
|
|
2582
|
+
n_common = len(reduce(set.intersection,
|
|
2600
2583
|
[set(c1[r]), set(c2[c]), set(c3[s])]))
|
|
2601
|
-
assert
|
|
2584
|
+
assert n_common in [0, 1]
|
|
2602
2585
|
|
|
2603
|
-
if
|
|
2586
|
+
if n_common == 1:
|
|
2604
2587
|
T1[r, c] = s
|
|
2605
2588
|
|
|
2606
2589
|
for cycle in c1:
|
|
@@ -2629,7 +2612,7 @@ def bitrade_from_group(a, b, c, G):
|
|
|
2629
2612
|
|
|
2630
2613
|
sage: from sage.combinat.matrices.latin import *
|
|
2631
2614
|
sage: a, b, c, G = alternating_group_bitrade_generators(1)
|
|
2632
|
-
sage:
|
|
2615
|
+
sage: T1, T2 = bitrade_from_group(a, b, c, G)
|
|
2633
2616
|
sage: T1
|
|
2634
2617
|
[ 0 -1 3 1]
|
|
2635
2618
|
[-1 1 0 2]
|
|
@@ -2854,7 +2837,7 @@ def dlxcpp_find_completions(P, nr_to_find=None):
|
|
|
2854
2837
|
Q = deepcopy(P)
|
|
2855
2838
|
|
|
2856
2839
|
for x in soln:
|
|
2857
|
-
|
|
2840
|
+
r, c, e = cmap[tuple(dlx_rows[x])]
|
|
2858
2841
|
|
|
2859
2842
|
if Q[r, c] >= 0:
|
|
2860
2843
|
assert Q[r, c] == e
|
sage/combinat/misc.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
r"""
|
|
3
3
|
Miscellaneous
|
|
4
4
|
"""
|
|
5
|
-
|
|
5
|
+
# ***************************************************************************
|
|
6
6
|
# Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
|
|
7
7
|
#
|
|
8
8
|
# Distributed under the terms of the GNU General Public License (GPL)
|
|
@@ -14,8 +14,8 @@ Miscellaneous
|
|
|
14
14
|
#
|
|
15
15
|
# The full text of the GPL is available at:
|
|
16
16
|
#
|
|
17
|
-
#
|
|
18
|
-
|
|
17
|
+
# https://www.gnu.org/licenses/
|
|
18
|
+
# ***************************************************************************
|
|
19
19
|
|
|
20
20
|
from sage.misc.misc_c import prod
|
|
21
21
|
|