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
@@ -84,21 +84,23 @@ def resolvable_balanced_incomplete_block_design(v, k, existence=False):
|
|
84
84
|
|
85
85
|
EXAMPLES::
|
86
86
|
|
87
|
-
sage: KTS15 = designs.resolvable_balanced_incomplete_block_design(15,3)
|
87
|
+
sage: KTS15 = designs.resolvable_balanced_incomplete_block_design(15,3)
|
88
|
+
sage: KTS15
|
88
89
|
(15,3,1)-Balanced Incomplete Block Design
|
89
90
|
sage: KTS15.is_resolvable()
|
90
91
|
True
|
91
92
|
|
92
93
|
TESTS::
|
93
94
|
|
95
|
+
sage: bibd = designs.resolvable_balanced_incomplete_block_design
|
94
96
|
sage: for v in range(40):
|
95
97
|
....: for k in range(v):
|
96
|
-
....: if
|
97
|
-
....: _ =
|
98
|
+
....: if bibd(v,k,existence=True) is True:
|
99
|
+
....: _ = bibd(v,k)
|
98
100
|
"""
|
99
101
|
# Trivial cases
|
100
102
|
if v == 1 or k == v:
|
101
|
-
return balanced_incomplete_block_design(v,k,existence=existence)
|
103
|
+
return balanced_incomplete_block_design(v, k, existence=existence)
|
102
104
|
|
103
105
|
# Non-existence of resolvable BIBD
|
104
106
|
if (v < k or
|
@@ -112,34 +114,34 @@ def resolvable_balanced_incomplete_block_design(v, k, existence=False):
|
|
112
114
|
# (15,5,2)
|
113
115
|
(k == 6 and v == 36) or
|
114
116
|
# Fisher's inequality
|
115
|
-
|
117
|
+
(v*(v-1))/(k*(k-1)) < v):
|
116
118
|
if existence:
|
117
119
|
return False
|
118
|
-
raise EmptySetError("There exists no ({},{},{})-RBIBD".format(v,k,1))
|
120
|
+
raise EmptySetError("There exists no ({},{},{})-RBIBD".format(v, k, 1))
|
119
121
|
|
120
122
|
if k == 2:
|
121
123
|
if existence:
|
122
124
|
return True
|
123
|
-
classes = [[[(c+i) % (v-1),(c+v-i) % (v-1)] for i in range(1, v//2)]
|
125
|
+
classes = [[[(c+i) % (v-1), (c+v-i) % (v-1)] for i in range(1, v//2)]
|
124
126
|
for c in range(v-1)]
|
125
|
-
for i,classs in enumerate(classes):
|
126
|
-
classs.append([v-1,i])
|
127
|
+
for i, classs in enumerate(classes):
|
128
|
+
classs.append([v-1, i])
|
127
129
|
|
128
130
|
B = BalancedIncompleteBlockDesign(v,
|
129
|
-
sum(classes,[]),
|
131
|
+
sum(classes, []),
|
130
132
|
k=k,
|
131
133
|
check=True,
|
132
134
|
copy=False)
|
133
135
|
B._classes = classes
|
134
136
|
return B
|
135
137
|
elif k == 3:
|
136
|
-
return kirkman_triple_system(v,existence=existence)
|
138
|
+
return kirkman_triple_system(v, existence=existence)
|
137
139
|
elif k == 4:
|
138
|
-
return v_4_1_rbibd(v,existence=existence)
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
140
|
+
return v_4_1_rbibd(v, existence=existence)
|
141
|
+
|
142
|
+
if existence:
|
143
|
+
return Unknown
|
144
|
+
raise NotImplementedError(f"I don't know how to build a ({v},3,1)-RBIBD!")
|
143
145
|
|
144
146
|
|
145
147
|
def kirkman_triple_system(v, existence=False):
|
@@ -194,14 +196,15 @@ def kirkman_triple_system(v, existence=False):
|
|
194
196
|
return False
|
195
197
|
|
196
198
|
elif v == 3:
|
197
|
-
return BalancedIncompleteBlockDesign(3,[[0,1,2]],k=3,lambd=1)
|
199
|
+
return BalancedIncompleteBlockDesign(3, [[0, 1, 2]], k=3, lambd=1)
|
198
200
|
|
199
201
|
elif v == 9:
|
200
202
|
classes = [[[0, 1, 5], [2, 6, 7], [3, 4, 8]],
|
201
203
|
[[1, 6, 8], [3, 5, 7], [0, 2, 4]],
|
202
204
|
[[1, 4, 7], [0, 3, 6], [2, 5, 8]],
|
203
205
|
[[4, 5, 6], [0, 7, 8], [1, 2, 3]]]
|
204
|
-
KTS = BalancedIncompleteBlockDesign(v,[tr for cl in classes for tr in cl],
|
206
|
+
KTS = BalancedIncompleteBlockDesign(v, [tr for cl in classes for tr in cl],
|
207
|
+
k=3, lambd=1, copy=False)
|
205
208
|
KTS._classes = classes
|
206
209
|
return KTS
|
207
210
|
|
@@ -211,7 +214,7 @@ def kirkman_triple_system(v, existence=False):
|
|
211
214
|
elif ((v-1)//2) % 6 == 1 and is_prime_power((v-1)//2):
|
212
215
|
from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
|
213
216
|
q = (v-1)//2
|
214
|
-
K = GF(q,'x')
|
217
|
+
K = GF(q, 'x')
|
215
218
|
a = K.primitive_element()
|
216
219
|
t = (q - 1) // 6
|
217
220
|
|
@@ -221,31 +224,33 @@ def kirkman_triple_system(v, existence=False):
|
|
221
224
|
assert 2*a**m == a**t+1
|
222
225
|
|
223
226
|
# First parallel class
|
224
|
-
first_class = [[(0,1),(0,2),'inf']]
|
227
|
+
first_class = [[(0, 1), (0, 2), 'inf']]
|
225
228
|
b0 = K.one()
|
226
229
|
b1 = a**t
|
227
230
|
b2 = a**m
|
228
|
-
first_class.extend([(b0*a**i,1),(b1*a**i,1),(b2*a**i,2)]
|
229
|
-
|
231
|
+
first_class.extend([(b0*a**i, 1), (b1*a**i, 1), (b2*a**i, 2)]
|
232
|
+
for i in list(range(t))+list(range(2*t, 3*t))+list(range(4*t, 5*t)))
|
230
233
|
b0 = a**(m+t)
|
231
234
|
b1 = a**(m+3*t)
|
232
235
|
b2 = a**(m+5*t)
|
233
|
-
first_class.extend([[(b0*a**i,2),(b1*a**i,2),(b2*a**i,2)]
|
236
|
+
first_class.extend([[(b0*a**i, 2), (b1*a**i, 2), (b2*a**i, 2)]
|
234
237
|
for i in range(t)])
|
235
238
|
|
236
239
|
# Action of K on the points
|
237
|
-
action
|
240
|
+
def action(v, x):
|
241
|
+
return (v + x[0], x[1]) if len(x) == 2 else x
|
238
242
|
|
239
243
|
# relabel to integer
|
240
|
-
relabel = {(p,x): i+(x-1)*q
|
241
|
-
for i,p in enumerate(K)
|
242
|
-
for x in [1,2]}
|
244
|
+
relabel = {(p, x): i+(x-1)*q
|
245
|
+
for i, p in enumerate(K)
|
246
|
+
for x in [1, 2]}
|
243
247
|
relabel['inf'] = 2*q
|
244
248
|
|
245
|
-
classes = [[[relabel[action(p,x)] for x in tr] for tr in first_class]
|
249
|
+
classes = [[[relabel[action(p, x)] for x in tr] for tr in first_class]
|
246
250
|
for p in K]
|
247
251
|
|
248
|
-
KTS = BalancedIncompleteBlockDesign(v,[tr for cl in classes for tr in cl],
|
252
|
+
KTS = BalancedIncompleteBlockDesign(v, [tr for cl in classes for tr in cl],
|
253
|
+
k=3, lambd=1, copy=False)
|
249
254
|
|
250
255
|
KTS._classes = classes
|
251
256
|
return KTS
|
@@ -256,32 +261,34 @@ def kirkman_triple_system(v, existence=False):
|
|
256
261
|
elif (v//3) % 6 == 1 and is_prime_power(v//3):
|
257
262
|
from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
|
258
263
|
q = v//3
|
259
|
-
K = GF(q,'x')
|
264
|
+
K = GF(q, 'x')
|
260
265
|
a = K.primitive_element()
|
261
266
|
t = (q - 1) // 6
|
262
|
-
A0 = [(0,0),(0,1),(0,2)]
|
263
|
-
B = [[(a**i,j),(a**(i+2*t),j),(a**(i+4*t),j)] for j in range(3)
|
264
|
-
|
265
|
-
A = [[(a**i,0),(a**(i+2*t),1),(a**(i+4*t),2)] for i in range(6*t)]
|
267
|
+
A0 = [(0, 0), (0, 1), (0, 2)]
|
268
|
+
B = [[(a**i, j), (a**(i+2*t), j), (a**(i+4*t), j)] for j in range(3)
|
269
|
+
for i in range(t)]
|
270
|
+
A = [[(a**i, 0), (a**(i+2*t), 1), (a**(i+4*t), 2)] for i in range(6*t)]
|
266
271
|
|
267
272
|
# Action of K on the points
|
268
|
-
action
|
273
|
+
def action(v, x):
|
274
|
+
return (v + x[0], x[1])
|
269
275
|
|
270
276
|
# relabel to integer
|
271
|
-
relabel = {(p,j): i+j*q
|
272
|
-
for i,p in enumerate(K)
|
277
|
+
relabel = {(p, j): i+j*q
|
278
|
+
for i, p in enumerate(K)
|
273
279
|
for j in range(3)}
|
274
280
|
|
275
281
|
B0 = [A0] + B + A[t:2*t] + A[3*t:4*t] + A[5*t:6*t]
|
276
282
|
|
277
283
|
# Classes
|
278
|
-
classes = [[[relabel[action(p,x)] for x in tr] for tr in B0]
|
284
|
+
classes = [[[relabel[action(p, x)] for x in tr] for tr in B0]
|
279
285
|
for p in K]
|
280
286
|
|
281
|
-
for i in list(range(t))+list(range(2*t,3*t))+list(range(4*t,5*t)):
|
282
|
-
classes.append([[relabel[action(p,x)] for x in A[i]] for p in K])
|
287
|
+
for i in list(range(t))+list(range(2*t, 3*t))+list(range(4*t, 5*t)):
|
288
|
+
classes.append([[relabel[action(p, x)] for x in A[i]] for p in K])
|
283
289
|
|
284
|
-
KTS = BalancedIncompleteBlockDesign(v,[tr for cl in classes for tr in cl],
|
290
|
+
KTS = BalancedIncompleteBlockDesign(v, [tr for cl in classes for tr in cl],
|
291
|
+
k=3, lambd=1, copy=False)
|
285
292
|
KTS._classes = classes
|
286
293
|
return KTS
|
287
294
|
|
@@ -311,14 +318,14 @@ def kirkman_triple_system(v, existence=False):
|
|
311
318
|
for b in X:
|
312
319
|
b.remove(8)
|
313
320
|
X = sum(X, []) + [8]
|
314
|
-
gdd4.relabel({v:i for i,v in enumerate(X)})
|
321
|
+
gdd4.relabel({v: i for i, v in enumerate(X)})
|
315
322
|
gdd4 = gdd4.is_resolvable(True)[1] # the relabeled classes
|
316
323
|
|
317
324
|
X = [B for B in gdd7 if 14 in B]
|
318
325
|
for b in X:
|
319
326
|
b.remove(14)
|
320
327
|
X = sum(X, []) + [14]
|
321
|
-
gdd7.relabel({v:i for i,v in enumerate(X)})
|
328
|
+
gdd7.relabel({v: i for i, v in enumerate(X)})
|
322
329
|
gdd7 = gdd7.is_resolvable(True)[1] # the relabeled classes
|
323
330
|
|
324
331
|
# The first parallel class contains 01(n'-1), the second contains
|
@@ -349,13 +356,14 @@ def kirkman_triple_system(v, existence=False):
|
|
349
356
|
# Pasting the KTS(n') without {x,x',\infty} blocks
|
350
357
|
classes = [[] for _ in repeat(None, (v - 1) // 2)]
|
351
358
|
gdd = {4: gdd4, 7: gdd7}
|
352
|
-
for B in PBD_4_7((v-1)//2,check=False):
|
353
|
-
for i,classs in enumerate(gdd[len(B)]):
|
354
|
-
classes[B[i]].extend([
|
359
|
+
for B in PBD_4_7((v-1)//2, check=False):
|
360
|
+
for i, classs in enumerate(gdd[len(B)]):
|
361
|
+
classes[B[i]].extend([2*B[x//2]+x % 2 for x in BB]
|
362
|
+
for BB in classs)
|
355
363
|
|
356
364
|
# The {x,x',\infty} blocks
|
357
|
-
for i,classs in enumerate(classes):
|
358
|
-
classs.append([2*i,2*i+1,v-1])
|
365
|
+
for i, classs in enumerate(classes):
|
366
|
+
classs.append([2*i, 2*i+1, v-1])
|
359
367
|
|
360
368
|
KTS = BalancedIncompleteBlockDesign(v,
|
361
369
|
blocks=[tr for cl in classes for tr in cl],
|
@@ -410,28 +418,28 @@ def v_4_1_rbibd(v, existence=False):
|
|
410
418
|
if v % 3 != 1 or not is_prime_power((v-1)//3):
|
411
419
|
if existence:
|
412
420
|
return Unknown
|
413
|
-
raise NotImplementedError("I don't know how to build a ({},
|
421
|
+
raise NotImplementedError(f"I don't know how to build a ({v},4,1)-RBIBD!")
|
414
422
|
from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
|
415
423
|
q = (v-1)//3
|
416
424
|
nn = (q-1)//4
|
417
|
-
G = GF(q,'x')
|
425
|
+
G = GF(q, 'x')
|
418
426
|
w = G.primitive_element()
|
419
427
|
e = w**(nn)
|
420
428
|
assert e**2 == -1
|
421
429
|
|
422
|
-
first_class = [[(w**i,j),(-w**i,j),(e*w**i,j+1),(-e*w**i,j+1)]
|
430
|
+
first_class = [[(w**i, j), (-w**i, j), (e*w**i, j+1), (-e*w**i, j+1)]
|
423
431
|
for i in range(nn) for j in range(3)]
|
424
432
|
|
425
|
-
first_class.append([(0,0),(0,1),(0,2),'inf'])
|
433
|
+
first_class.append([(0, 0), (0, 1), (0, 2), 'inf'])
|
426
434
|
|
427
|
-
label = {p:i for i,p in enumerate(G)}
|
435
|
+
label = {p: i for i, p in enumerate(G)}
|
428
436
|
|
429
437
|
classes = [[[v-1 if x == 'inf' else (x[1] % 3)*q+label[x[0]+g] for x in S]
|
430
438
|
for S in first_class]
|
431
439
|
for g in G]
|
432
440
|
|
433
441
|
BIBD = BalancedIncompleteBlockDesign(v,
|
434
|
-
blocks=sum(classes,[]),
|
442
|
+
blocks=sum(classes, []),
|
435
443
|
k=4,
|
436
444
|
check=True,
|
437
445
|
copy=False)
|
@@ -444,9 +452,9 @@ def PBD_4_7(v, check=True, existence=False):
|
|
444
452
|
r"""
|
445
453
|
Return a `(v,\{4,7\})`-PBD.
|
446
454
|
|
447
|
-
For all `v` such that `n\equiv 1\pmod{3}` and `n\neq 10,19, 31` there
|
448
|
-
a `(v,\{4,7\})`-PBD. This is proved in Proposition IX.4.5
|
449
|
-
which this method implements.
|
455
|
+
For all `v` such that `n\equiv 1\pmod{3}` and `n\neq 10,19, 31` there
|
456
|
+
exists a `(v,\{4,7\})`-PBD. This is proved in Proposition IX.4.5
|
457
|
+
from [BJL99]_, which this method implements.
|
450
458
|
|
451
459
|
This construction of PBD is used by the construction of Kirkman Triple
|
452
460
|
Systems.
|
@@ -466,7 +474,7 @@ def PBD_4_7(v, check=True, existence=False):
|
|
466
474
|
....: assert PBD_4_7(i,existence=True) is True
|
467
475
|
....: _ = PBD_4_7(i,check=True)
|
468
476
|
"""
|
469
|
-
if v % 3 != 1 or v in [10,19,31]:
|
477
|
+
if v % 3 != 1 or v in [10, 19, 31]:
|
470
478
|
if existence:
|
471
479
|
return Unknown
|
472
480
|
raise NotImplementedError
|
@@ -482,88 +490,113 @@ def PBD_4_7(v, check=True, existence=False):
|
|
482
490
|
# Beth/Jungnickel/Lenz: take KTS(15) and extend each of the 7 classes
|
483
491
|
# with a new point. Make those new points a 7-set.
|
484
492
|
KTS15 = kirkman_triple_system(15)
|
485
|
-
blocks = [S+[i+15] for i,classs in enumerate(KTS15._classes) for S in classs]+[list(range(15, 22))]
|
493
|
+
blocks = [S+[i+15] for i, classs in enumerate(KTS15._classes) for S in classs] + [list(range(15, 22))]
|
486
494
|
|
487
495
|
elif v == 34:
|
488
496
|
# [BJL99] (p527,vol1), but originally Brouwer
|
489
|
-
A = [(0,0),(1,1),(2,0),(4,1)]
|
490
|
-
B = [(0,0),(1,0),(4,2)]
|
491
|
-
C = [(0,0),(2,2),(5,0)]
|
492
|
-
D = [(0,0),(0,1),(0,2)]
|
493
|
-
|
494
|
-
A = [[(x+i,
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
497
|
+
A = [(0, 0), (1, 1), (2, 0), (4, 1)]
|
498
|
+
B = [(0, 0), (1, 0), (4, 2)]
|
499
|
+
C = [(0, 0), (2, 2), (5, 0)]
|
500
|
+
D = [(0, 0), (0, 1), (0, 2)]
|
501
|
+
|
502
|
+
A = [[(x+i, y+j) for x, y in A]
|
503
|
+
for i in range(9) for j in range(3)]
|
504
|
+
B = [[(x+i, y+i+j) for x, y in B] + [27+j]
|
505
|
+
for i in range(9) for j in range(3)]
|
506
|
+
C = [[(x+i+j, y+2*i+j) for x, y in C] + [30+j]
|
507
|
+
for i in range(9) for j in range(3)]
|
508
|
+
D = [[(x+i, y+i) for x, y in D] + [33]
|
509
|
+
for i in range(9)]
|
510
|
+
|
511
|
+
blocks = [[int(x) if not isinstance(x, tuple) else (x[1] % 3)*9+(x[0] % 9)
|
512
|
+
for x in S]
|
513
|
+
for S in A+B+C+D+[list(range(27, 34))]]
|
501
514
|
elif v == 46:
|
502
515
|
# [BJL99] (p527,vol1), but originally Brouwer
|
503
|
-
A = [(1,0),(3,0),(9,0),(0,1)]
|
504
|
-
B = [(2,0),(6,0),(5,0),(0,1)]
|
505
|
-
C = [(0,0),(1,1),(4,2)]
|
506
|
-
D = [(0,0),(2,1),(7,2)]
|
507
|
-
E = [(0,0),(0,1),(0,2)]
|
508
|
-
|
509
|
-
A = [[(x+i,
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
+
A = [(1, 0), (3, 0), (9, 0), (0, 1)]
|
517
|
+
B = [(2, 0), (6, 0), (5, 0), (0, 1)]
|
518
|
+
C = [(0, 0), (1, 1), (4, 2)]
|
519
|
+
D = [(0, 0), (2, 1), (7, 2)]
|
520
|
+
E = [(0, 0), (0, 1), (0, 2)]
|
521
|
+
|
522
|
+
A = [[(x+i, y+j) for x, y in A]
|
523
|
+
for i in range(13) for j in range(3)]
|
524
|
+
B = [[(x+i, y+j) for x, y in B]
|
525
|
+
for i in range(13) for j in range(3)]
|
526
|
+
C = [[(x+i, y+j) for x, y in C] + [39+j]
|
527
|
+
for i in range(13) for j in range(3)]
|
528
|
+
D = [[(x+i, y+j) for x, y in D] + [42+j]
|
529
|
+
for i in range(13) for j in range(3)]
|
530
|
+
E = [[(x+i, y+i) for x, y in E] + [45]
|
531
|
+
for i in range(13)]
|
532
|
+
|
533
|
+
blocks = [[int(x) if not isinstance(x, tuple) else (x[1] % 3)*13+(x[0] % 13)
|
534
|
+
for x in S]
|
516
535
|
for S in A+B+C+D+E+[list(range(39, 46))]]
|
517
536
|
|
518
537
|
elif v == 58:
|
519
538
|
# [BJL99] (p527,vol1), but originally Brouwer
|
520
|
-
A = [(0,0),(1,0),(4,0),(
|
521
|
-
B = [(0,0),(2,0),(8,0),(11,1)]
|
522
|
-
C = [(0,0),(5,0),(2,1),(12,1)]
|
523
|
-
D = [(0,0),(8,1),(7,2)]
|
524
|
-
E = [(0,0),(6,1),(4,2)]
|
525
|
-
F = [(0,0),(0,1),(0,2)]
|
526
|
-
|
527
|
-
A = [[(x+i,
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
539
|
+
A = [(0, 0), (1, 0), (4, 0), (5, 1)]
|
540
|
+
B = [(0, 0), (2, 0), (8, 0), (11, 1)]
|
541
|
+
C = [(0, 0), (5, 0), (2, 1), (12, 1)]
|
542
|
+
D = [(0, 0), (8, 1), (7, 2)]
|
543
|
+
E = [(0, 0), (6, 1), (4, 2)]
|
544
|
+
F = [(0, 0), (0, 1), (0, 2)]
|
545
|
+
|
546
|
+
A = [[(x+i, y+j) for x, y in A]
|
547
|
+
for i in range(17) for j in range(3)]
|
548
|
+
B = [[(x+i, y+j) for x, y in B]
|
549
|
+
for i in range(17) for j in range(3)]
|
550
|
+
C = [[(x+i, y+j) for x, y in C]
|
551
|
+
for i in range(17) for j in range(3)]
|
552
|
+
D = [[(x+i, y+j) for x, y in D] + [51+j]
|
553
|
+
for i in range(17) for j in range(3)]
|
554
|
+
E = [[(x+i, y+j) for x, y in E] + [54+j]
|
555
|
+
for i in range(17) for j in range(3)]
|
556
|
+
F = [[(x+i, y+i) for x, y in F] + [57]
|
557
|
+
for i in range(17)]
|
558
|
+
|
559
|
+
blocks = [[int(x) if not isinstance(x, tuple) else (x[1] % 3)*17+(x[0] % 17)
|
560
|
+
for x in S]
|
561
|
+
for S in A+B+C+D+E+F+[list(range(51, 58))]]
|
536
562
|
|
537
563
|
elif v == 70:
|
538
564
|
# [BJL99] (p527,vol1), but originally Brouwer
|
539
|
-
A = [(0,0),(1,0),(5,1),(13,1)]
|
540
|
-
B = [(0,0),(4,0),(20,1),(10,1)]
|
541
|
-
C = [(0,0),(16,0),(17,1),(19,1)]
|
542
|
-
D = [(0,0),(2,1),(8,1),(11,1)]
|
543
|
-
E = [(0,0),(3,2),(9,1)]
|
544
|
-
F = [(0,0),(7,0),(14,1)]
|
545
|
-
H = [(0,0),(0,1),(0,2)]
|
546
|
-
|
547
|
-
A = [[(x+i,
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
565
|
+
A = [(0, 0), (1, 0), (5, 1), (13, 1)]
|
566
|
+
B = [(0, 0), (4, 0), (20, 1), (10, 1)]
|
567
|
+
C = [(0, 0), (16, 0), (17, 1), (19, 1)]
|
568
|
+
D = [(0, 0), (2, 1), (8, 1), (11, 1)]
|
569
|
+
E = [(0, 0), (3, 2), (9, 1)]
|
570
|
+
F = [(0, 0), (7, 0), (14, 1)]
|
571
|
+
H = [(0, 0), (0, 1), (0, 2)]
|
572
|
+
|
573
|
+
A = [[(x+i, y+j) for x, y in A]
|
574
|
+
for i in range(21) for j in range(3)]
|
575
|
+
B = [[(x+i, y+j) for x, y in B]
|
576
|
+
for i in range(21) for j in range(3)]
|
577
|
+
C = [[(x+i, y+j) for x, y in C]
|
578
|
+
for i in range(21) for j in range(3)]
|
579
|
+
D = [[(x+i, y+j) for x, y in D]
|
580
|
+
for i in range(21) for j in range(3)]
|
581
|
+
E = [[(x+i, y+j) for x, y in E] + [63+j]
|
582
|
+
for i in range(21) for j in range(3)]
|
583
|
+
F = [[(x+3*i+j, y+ii+j) for x, y in F] + [66+j]
|
584
|
+
for i in range(7) for j in range(3) for ii in range(3)]
|
585
|
+
H = [[(x+i, y+i) for x, y in H] + [69]
|
586
|
+
for i in range(21)]
|
587
|
+
|
588
|
+
blocks = [[int(x) if not isinstance(x, tuple) else (x[1] % 3)*21+(x[0] % 21)
|
556
589
|
for x in S]
|
557
|
-
for S in A+B+C+D+E+F+H+[list(range(63,70))]]
|
590
|
+
for S in A+B+C+D+E+F+H+[list(range(63, 70))]]
|
558
591
|
|
559
592
|
elif v == 82:
|
560
593
|
# This construction is Theorem IX.3.16 from [BJL99] (p.627).
|
561
594
|
#
|
562
595
|
# A (15,{4},{3})-GDD from a (16,4)-BIBD
|
563
596
|
from .group_divisible_designs import group_divisible_design
|
564
|
-
from .orthogonal_arrays
|
565
|
-
GDD = group_divisible_design(3*5,K=[4],G=[3],check=False)
|
566
|
-
TD = transversal_design(5,5)
|
597
|
+
from .orthogonal_arrays import transversal_design
|
598
|
+
GDD = group_divisible_design(3*5, K=[4], G=[3], check=False)
|
599
|
+
TD = transversal_design(5, 5)
|
567
600
|
|
568
601
|
# A (75,{4},{15})-GDD
|
569
602
|
GDD2 = [[3*B[x//3]+x % 3 for x in BB] for B in TD for BB in GDD]
|
@@ -575,7 +608,8 @@ def PBD_4_7(v, check=True, existence=False):
|
|
575
608
|
# new points are a set of the final PBD
|
576
609
|
PBD22 = PBD_4_7(15+7)
|
577
610
|
S = next(SS for SS in PBD22 if len(SS) == 7) # a set of size 7
|
578
|
-
PBD22.relabel({v:i for i,v in enumerate([i for i in range(15+7)
|
611
|
+
PBD22.relabel({v: i for i, v in enumerate([i for i in range(15+7)
|
612
|
+
if i not in S] + S)})
|
579
613
|
|
580
614
|
for B in PBD22:
|
581
615
|
if B == S:
|
@@ -583,7 +617,7 @@ def PBD_4_7(v, check=True, existence=False):
|
|
583
617
|
for i in range(5):
|
584
618
|
GDD2.append([x+i*15 if x < 15 else x+60 for x in B])
|
585
619
|
|
586
|
-
GDD2.append(list(range(75,82)))
|
620
|
+
GDD2.append(list(range(75, 82)))
|
587
621
|
blocks = GDD2
|
588
622
|
|
589
623
|
elif v == 94:
|
@@ -592,7 +626,7 @@ def PBD_4_7(v, check=True, existence=False):
|
|
592
626
|
# take 4 parallel lines from an affine plane of order 7, and a 5th
|
593
627
|
# one. This is a (31,{4,5,7})-BIBD. And 94=3*31+1.
|
594
628
|
from sage.combinat.designs.block_design import AffineGeometryDesign
|
595
|
-
AF = AffineGeometryDesign(2,1,7)
|
629
|
+
AF = AffineGeometryDesign(2, 1, 7)
|
596
630
|
parall = []
|
597
631
|
plus_one = None
|
598
632
|
for S in AF:
|
@@ -608,10 +642,10 @@ def PBD_4_7(v, check=True, existence=False):
|
|
608
642
|
S_4_5_7 = [S for S in S_4_5_7 if len(S) > 1]
|
609
643
|
S_4_5_7 = PairwiseBalancedDesign(X,
|
610
644
|
blocks=S_4_5_7,
|
611
|
-
K=[4,5,7],
|
645
|
+
K=[4, 5, 7],
|
612
646
|
check=False)
|
613
647
|
S_4_5_7.relabel()
|
614
|
-
return PBD_4_7_from_Y(S_4_5_7,check=check)
|
648
|
+
return PBD_4_7_from_Y(S_4_5_7, check=check)
|
615
649
|
|
616
650
|
elif v == 127 or v == 142:
|
617
651
|
# IX.4.5.o from [BJL99].
|
@@ -621,22 +655,22 @@ def PBD_4_7(v, check=True, existence=False):
|
|
621
655
|
points_to_add = 2 if v == 127 else 7
|
622
656
|
rBIBD4 = v_4_1_rbibd(40)
|
623
657
|
GDD = [S+[40+i] if i < points_to_add else S
|
624
|
-
for i,classs in enumerate(rBIBD4._classes)
|
658
|
+
for i, classs in enumerate(rBIBD4._classes)
|
625
659
|
for S in classs]
|
626
660
|
if points_to_add == 7:
|
627
661
|
GDD.append(list(range(40, 40 + points_to_add)))
|
628
662
|
groups = [[x] for x in range(40+points_to_add)]
|
629
663
|
else:
|
630
664
|
groups = [[x] for x in range(40)]
|
631
|
-
groups.append(list(range(40,40+points_to_add)))
|
665
|
+
groups.append(list(range(40, 40+points_to_add)))
|
632
666
|
GDD = GroupDivisibleDesign(40+points_to_add,
|
633
667
|
groups=groups,
|
634
668
|
blocks=GDD,
|
635
|
-
K=[2,4,5,7],
|
669
|
+
K=[2, 4, 5, 7],
|
636
670
|
check=False,
|
637
671
|
copy=False)
|
638
672
|
|
639
|
-
return PBD_4_7_from_Y(GDD,check=check)
|
673
|
+
return PBD_4_7_from_Y(GDD, check=check)
|
640
674
|
|
641
675
|
elif v % 6 == 1 and GDD_4_2((v - 1) // 6, existence=True) is True:
|
642
676
|
# VII.5.17 from [BJL99]
|
@@ -645,14 +679,14 @@ def PBD_4_7(v, check=True, existence=False):
|
|
645
679
|
|
646
680
|
elif v == 202:
|
647
681
|
# IV.4.5.p from [BJL99]
|
648
|
-
PBD = PBD_4_7(22,check=False)
|
649
|
-
PBD = PBD_4_7_from_Y(PBD,check=False)
|
650
|
-
return PBD_4_7_from_Y(PBD,check=check)
|
651
|
-
|
652
|
-
elif balanced_incomplete_block_design(v,4,existence=True) is True:
|
653
|
-
return balanced_incomplete_block_design(v,4)
|
654
|
-
elif balanced_incomplete_block_design(v,7,existence=True) is True:
|
655
|
-
return balanced_incomplete_block_design(v,7)
|
682
|
+
PBD = PBD_4_7(22, check=False)
|
683
|
+
PBD = PBD_4_7_from_Y(PBD, check=False)
|
684
|
+
return PBD_4_7_from_Y(PBD, check=check)
|
685
|
+
|
686
|
+
elif balanced_incomplete_block_design(v, 4, existence=True) is True:
|
687
|
+
return balanced_incomplete_block_design(v, 4)
|
688
|
+
elif balanced_incomplete_block_design(v, 7, existence=True) is True:
|
689
|
+
return balanced_incomplete_block_design(v, 7)
|
656
690
|
else:
|
657
691
|
from sage.combinat.designs.orthogonal_arrays import orthogonal_array
|
658
692
|
# IX.4.5.m from [BJL99].
|
@@ -666,23 +700,23 @@ def PBD_4_7(v, check=True, existence=False):
|
|
666
700
|
vv = (v - 1) // 3
|
667
701
|
for g in range((vv + 5 - 1) // 5, vv // 4 + 1):
|
668
702
|
u = vv-4*g
|
669
|
-
if (orthogonal_array(5,g,existence=True) is True and
|
670
|
-
PBD_4_7(3*g+1,existence=True) is True and
|
671
|
-
|
703
|
+
if (orthogonal_array(5, g, existence=True) is True and
|
704
|
+
PBD_4_7(3*g+1, existence=True) is True and
|
705
|
+
PBD_4_7(3*u+1, existence=True) is True):
|
672
706
|
from .orthogonal_arrays import transversal_design
|
673
707
|
domain = set(range(vv))
|
674
|
-
GDD = transversal_design(5,g)
|
708
|
+
GDD = transversal_design(5, g)
|
675
709
|
GDD = GroupDivisibleDesign(vv,
|
676
710
|
groups=[[x for x in gr if x in domain] for gr in GDD.groups()],
|
677
711
|
blocks=[[x for x in B if x in domain] for B in GDD],
|
678
|
-
G=set([g,u]),
|
679
|
-
K=[4,5],
|
712
|
+
G=set([g, u]),
|
713
|
+
K=[4, 5],
|
680
714
|
check=False)
|
681
|
-
return PBD_4_7_from_Y(GDD,check=check)
|
715
|
+
return PBD_4_7_from_Y(GDD, check=check)
|
682
716
|
|
683
717
|
return PairwiseBalancedDesign(v,
|
684
718
|
blocks=blocks,
|
685
|
-
K=[4,7],
|
719
|
+
K=[4, 7],
|
686
720
|
check=check,
|
687
721
|
copy=False)
|
688
722
|
|
@@ -730,33 +764,33 @@ def PBD_4_7_from_Y(gdd, check=True):
|
|
730
764
|
"""
|
731
765
|
from .group_divisible_designs import group_divisible_design
|
732
766
|
from .bibd import PairwiseBalancedDesign
|
733
|
-
block_sizes = set(map(len,gdd._blocks))
|
734
|
-
group_sizes = set(map(len,gdd._groups))
|
767
|
+
block_sizes = set(map(len, gdd._blocks))
|
768
|
+
group_sizes = set(map(len, gdd._groups))
|
735
769
|
if not block_sizes.issubset([4, 5, 7]):
|
736
770
|
txt = list(block_sizes.difference([4, 5, 7]))
|
737
771
|
raise ValueError("The GDD should only contain blocks of size {{4,5,7}} "
|
738
772
|
"but there are other: {}".format(txt))
|
739
773
|
|
740
774
|
for gs in group_sizes:
|
741
|
-
if PBD_4_7(3*gs+1,existence=True) is not True:
|
775
|
+
if PBD_4_7(3*gs+1, existence=True) is not True:
|
742
776
|
raise RuntimeError("A group has size {} but I do not know how to "
|
743
|
-
"build a ({},[4,7])-PBD".format(gs,3*gs+1))
|
777
|
+
"build a ({},[4,7])-PBD".format(gs, 3*gs+1))
|
744
778
|
|
745
779
|
GDD = {} # the GDD we will need
|
746
780
|
if 4 in block_sizes:
|
747
781
|
# GDD[4] = GDD_from_BIBD(3*4,4)
|
748
|
-
GDD[4] = group_divisible_design(3*4,K=[4],G=[3])
|
782
|
+
GDD[4] = group_divisible_design(3*4, K=[4], G=[3])
|
749
783
|
if 5 in block_sizes:
|
750
784
|
# GDD[5] = GDD_from_BIBD(3*5,4)
|
751
|
-
GDD[5] = group_divisible_design(3*5,K=[4],G=[3])
|
785
|
+
GDD[5] = group_divisible_design(3*5, K=[4], G=[3])
|
752
786
|
if 7 in block_sizes:
|
753
787
|
# It is obtained from a PBD_4_7(22) by removing a point only contained
|
754
788
|
# in sets of size 4
|
755
789
|
GDD[7] = PBD_4_7(22)
|
756
790
|
x = set(range(22)).difference(*[S for S in GDD[7] if len(S) != 4]).pop()
|
757
|
-
relabel = sum((S for S in GDD[7] if x in S),[]) # the groups must be 012,345,...
|
758
|
-
relabel = [xx for xx in relabel if xx != x]+[x]
|
759
|
-
GDD[7].relabel({v:i for i,v in enumerate(relabel)})
|
791
|
+
relabel = sum((S for S in GDD[7] if x in S), []) # the groups must be 012,345,...
|
792
|
+
relabel = [xx for xx in relabel if xx != x] + [x]
|
793
|
+
GDD[7].relabel({v: i for i, v in enumerate(relabel)})
|
760
794
|
GDD[7] = [S for S in GDD[7] if 21 not in S]
|
761
795
|
|
762
796
|
PBD = []
|
@@ -767,7 +801,7 @@ def PBD_4_7_from_Y(gdd, check=True):
|
|
767
801
|
PBD.append([3*B[x//3]+(x % 3) for x in B_GDD])
|
768
802
|
|
769
803
|
# The groups
|
770
|
-
group_PBD = {gs:PBD_4_7(3*gs+1) for gs in group_sizes}
|
804
|
+
group_PBD = {gs: PBD_4_7(3*gs+1) for gs in group_sizes}
|
771
805
|
for G in gdd.groups():
|
772
806
|
gs = len(G)
|
773
807
|
for B in group_PBD[gs]:
|
@@ -776,6 +810,6 @@ def PBD_4_7_from_Y(gdd, check=True):
|
|
776
810
|
|
777
811
|
return PairwiseBalancedDesign(3*gdd.num_points()+1,
|
778
812
|
blocks=PBD,
|
779
|
-
K=[4,7],
|
813
|
+
K=[4, 7],
|
780
814
|
check=check,
|
781
815
|
copy=False)
|
Binary file
|