passagemath-graphs 10.5.43__cp312-cp312-macosx_14_0_arm64.whl → 10.6.1rc2__cp312-cp312-macosx_14_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/METADATA +5 -6
  2. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/RECORD +132 -130
  3. sage/combinat/abstract_tree.py +188 -17
  4. sage/combinat/cluster_algebra_quiver/interact.py +1 -2
  5. sage/combinat/cluster_algebra_quiver/mutation_type.py +518 -519
  6. sage/combinat/cluster_algebra_quiver/quiver.py +233 -205
  7. sage/combinat/designs/covering_design.py +2 -6
  8. sage/combinat/designs/database.py +11 -10
  9. sage/combinat/designs/designs_pyx.cpython-312-darwin.so +0 -0
  10. sage/combinat/designs/designs_pyx.pyx +2 -2
  11. sage/combinat/designs/evenly_distributed_sets.cpython-312-darwin.so +0 -0
  12. sage/combinat/designs/evenly_distributed_sets.pyx +4 -4
  13. sage/combinat/designs/gen_quadrangles_with_spread.cpython-312-darwin.so +0 -0
  14. sage/combinat/designs/latin_squares.py +53 -20
  15. sage/combinat/designs/orthogonal_arrays.py +2 -1
  16. sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-312-darwin.so +0 -0
  17. sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +22 -21
  18. sage/combinat/designs/resolvable_bibd.py +191 -157
  19. sage/combinat/designs/subhypergraph_search.cpython-312-darwin.so +0 -0
  20. sage/combinat/designs/subhypergraph_search.pyx +4 -4
  21. sage/combinat/designs/twographs.py +2 -2
  22. sage/combinat/finite_state_machine.py +6 -6
  23. sage/combinat/posets/bubble_shuffle.py +247 -0
  24. sage/combinat/posets/d_complete.py +3 -3
  25. sage/combinat/posets/elements.py +3 -3
  26. sage/combinat/posets/hasse_cython.cpython-312-darwin.so +0 -0
  27. sage/combinat/posets/hasse_cython.pyx +1 -1
  28. sage/combinat/posets/hasse_diagram.py +16 -22
  29. sage/combinat/posets/hochschild_lattice.py +158 -0
  30. sage/combinat/posets/incidence_algebras.py +14 -16
  31. sage/combinat/posets/lattices.py +51 -53
  32. sage/combinat/posets/linear_extension_iterator.cpython-312-darwin.so +0 -0
  33. sage/combinat/posets/linear_extensions.py +10 -12
  34. sage/combinat/posets/moebius_algebra.py +4 -4
  35. sage/combinat/posets/poset_examples.py +70 -23
  36. sage/combinat/posets/posets.py +294 -103
  37. sage/databases/knotinfo_db.py +2 -1
  38. sage/graphs/asteroidal_triples.cpython-312-darwin.so +0 -0
  39. sage/graphs/asteroidal_triples.pyx +24 -3
  40. sage/graphs/base/boost_graph.cpython-312-darwin.so +0 -0
  41. sage/graphs/base/boost_graph.pxd +3 -3
  42. sage/graphs/base/c_graph.cpython-312-darwin.so +0 -0
  43. sage/graphs/base/c_graph.pyx +1 -1
  44. sage/graphs/base/dense_graph.cpython-312-darwin.so +0 -0
  45. sage/graphs/base/dense_graph.pxd +5 -3
  46. sage/graphs/base/dense_graph.pyx +44 -0
  47. sage/graphs/base/graph_backends.cpython-312-darwin.so +0 -0
  48. sage/graphs/base/sparse_graph.cpython-312-darwin.so +0 -0
  49. sage/graphs/base/static_dense_graph.cpython-312-darwin.so +0 -0
  50. sage/graphs/base/static_sparse_backend.cpython-312-darwin.so +0 -0
  51. sage/graphs/base/static_sparse_backend.pyx +8 -5
  52. sage/graphs/base/static_sparse_graph.cpython-312-darwin.so +0 -0
  53. sage/graphs/base/static_sparse_graph.pyx +86 -15
  54. sage/graphs/bipartite_graph.py +59 -36
  55. sage/graphs/centrality.cpython-312-darwin.so +0 -0
  56. sage/graphs/centrality.pyx +82 -9
  57. sage/graphs/cographs.py +1 -1
  58. sage/graphs/comparability.cpython-312-darwin.so +0 -0
  59. sage/graphs/comparability.pyx +64 -26
  60. sage/graphs/connectivity.cpython-312-darwin.so +0 -0
  61. sage/graphs/convexity_properties.cpython-312-darwin.so +0 -0
  62. sage/graphs/convexity_properties.pyx +52 -9
  63. sage/graphs/digraph.py +439 -95
  64. sage/graphs/digraph_generators.py +174 -102
  65. sage/graphs/distances_all_pairs.cpython-312-darwin.so +0 -0
  66. sage/graphs/dot2tex_utils.py +1 -1
  67. sage/graphs/edge_connectivity.cpython-312-darwin.so +0 -0
  68. sage/graphs/generators/basic.py +1 -1
  69. sage/graphs/generators/distance_regular.cpython-312-darwin.so +0 -0
  70. sage/graphs/generators/distance_regular.pyx +1 -1
  71. sage/graphs/generators/families.py +37 -27
  72. sage/graphs/generators/random.py +2 -2
  73. sage/graphs/generators/smallgraphs.py +3 -3
  74. sage/graphs/generic_graph.py +558 -86
  75. sage/graphs/generic_graph_pyx.cpython-312-darwin.so +0 -0
  76. sage/graphs/generic_graph_pyx.pyx +58 -11
  77. sage/graphs/genus.cpython-312-darwin.so +0 -0
  78. sage/graphs/genus.pyx +3 -4
  79. sage/graphs/graph.py +291 -8
  80. sage/graphs/graph_coloring.cpython-312-darwin.so +0 -0
  81. sage/graphs/graph_database.py +67 -12
  82. sage/graphs/graph_decompositions/bandwidth.cpython-312-darwin.so +0 -0
  83. sage/graphs/graph_decompositions/clique_separators.cpython-312-darwin.so +0 -0
  84. sage/graphs/graph_decompositions/clique_separators.pyx +24 -3
  85. sage/graphs/graph_decompositions/cutwidth.cpython-312-darwin.so +0 -0
  86. sage/graphs/graph_decompositions/fast_digraph.cpython-312-darwin.so +0 -0
  87. sage/graphs/graph_decompositions/fast_digraph.pyx +1 -1
  88. sage/graphs/graph_decompositions/graph_products.cpython-312-darwin.so +0 -0
  89. sage/graphs/graph_decompositions/graph_products.pyx +67 -21
  90. sage/graphs/graph_decompositions/modular_decomposition.cpython-312-darwin.so +0 -0
  91. sage/graphs/graph_decompositions/slice_decomposition.cpython-312-darwin.so +0 -0
  92. sage/graphs/graph_decompositions/slice_decomposition.pyx +34 -8
  93. sage/graphs/graph_decompositions/tree_decomposition.cpython-312-darwin.so +0 -0
  94. sage/graphs/graph_decompositions/vertex_separation.cpython-312-darwin.so +0 -0
  95. sage/graphs/graph_generators.py +45 -32
  96. sage/graphs/graph_generators_pyx.cpython-312-darwin.so +0 -0
  97. sage/graphs/graph_generators_pyx.pyx +15 -15
  98. sage/graphs/graph_latex.py +1 -1
  99. sage/graphs/graph_list.py +52 -9
  100. sage/graphs/graph_plot.py +7 -0
  101. sage/graphs/hyperbolicity.cpython-312-darwin.so +0 -0
  102. sage/graphs/hyperbolicity.pyx +2 -0
  103. sage/graphs/independent_sets.cpython-312-darwin.so +0 -0
  104. sage/graphs/isoperimetric_inequalities.cpython-312-darwin.so +0 -0
  105. sage/graphs/isoperimetric_inequalities.pyx +42 -6
  106. sage/graphs/line_graph.cpython-312-darwin.so +0 -0
  107. sage/graphs/line_graph.pyx +153 -37
  108. sage/graphs/matching_covered_graph.py +84 -60
  109. sage/graphs/orientations.py +3 -18
  110. sage/graphs/path_enumeration.cpython-312-darwin.so +0 -0
  111. sage/graphs/path_enumeration.pyx +2 -2
  112. sage/graphs/spanning_tree.cpython-312-darwin.so +0 -0
  113. sage/graphs/strongly_regular_db.cpython-312-darwin.so +0 -0
  114. sage/graphs/strongly_regular_db.pyx +15 -15
  115. sage/graphs/traversals.cpython-312-darwin.so +0 -0
  116. sage/graphs/traversals.pyx +13 -12
  117. sage/graphs/trees.cpython-312-darwin.so +0 -0
  118. sage/graphs/tutte_polynomial.py +1 -1
  119. sage/graphs/views.cpython-312-darwin.so +0 -0
  120. sage/graphs/weakly_chordal.cpython-312-darwin.so +0 -0
  121. sage/graphs/weakly_chordal.pyx +50 -8
  122. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-312-darwin.so +0 -0
  123. sage/knots/free_knotinfo_monoid.py +3 -3
  124. sage/knots/knotinfo.py +102 -82
  125. sage/knots/link.py +72 -39
  126. sage/topology/cubical_complex.py +4 -5
  127. sage/topology/delta_complex.py +4 -4
  128. sage/topology/simplicial_complex.py +0 -1
  129. sage/topology/simplicial_complex_catalog.py +6 -0
  130. sage/topology/simplicial_complex_examples.py +4 -16
  131. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/WHEEL +0 -0
  132. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/top_level.txt +0 -0
@@ -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); KTS15
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 designs.resolvable_balanced_incomplete_block_design(v,k,existence=True) is True:
97
- ....: _ = designs.resolvable_balanced_incomplete_block_design(v,k)
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
- (v*(v-1))/(k*(k-1)) < v):
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
- else:
140
- if existence:
141
- return Unknown
142
- raise NotImplementedError("I don't know how to build a ({},{},1)-RBIBD!".format(v,3))
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],k=3,lambd=1,copy=False)
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
- for i in list(range(t))+list(range(2*t,3*t))+list(range(4*t,5*t)))
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 = lambda v,x : (v+x[0],x[1]) if len(x) == 2 else x
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],k=3,lambd=1,copy=False)
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
- for i in range(t)]
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 = lambda v,x: (v+x[0],x[1])
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],k=3,lambd=1,copy=False)
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([[2*B[x//2]+x % 2 for x in BB] for BB in classs])
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 ({},{},1)-RBIBD!".format(v,4))
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 exists
448
- a `(v,\{4,7\})`-PBD. This is proved in Proposition IX.4.5 from [BJL99]_,
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, y+j) for x,y in A] for i in range(9) for j in range(3)]
495
- B = [[(x+i, y+i+j) for x,y in B]+[27+j] for i in range(9) for j in range(3)]
496
- C = [[(x+i+j,y+2*i+j) for x,y in C]+[30+j] for i in range(9) for j in range(3)]
497
- D = [[(x+i, y+i) for x,y in D]+[33] for i in range(9)]
498
-
499
- blocks = [[int(x) if not isinstance(x,tuple) else (x[1] % 3)*9+(x[0] % 9) for x in S]
500
- for S in A+B+C+D+[list(range(27,34))]]
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, y+j) for x,y in A] for i in range(13) for j in range(3)]
510
- B = [[(x+i, y+j) for x,y in B] for i in range(13) for j in range(3)]
511
- C = [[(x+i, y+j) for x,y in C]+[39+j] for i in range(13) for j in range(3)]
512
- D = [[(x+i, y+j) for x,y in D]+[42+j] for i in range(13) for j in range(3)]
513
- E = [[(x+i, y+i) for x,y in E]+[45] for i in range(13)]
514
-
515
- blocks = [[int(x) if not isinstance(x,tuple) else (x[1] % 3)*13+(x[0] % 13) for x in S]
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),( 5,1)]
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, y+j) for x,y in A] for i in range(17) for j in range(3)]
528
- B = [[(x+i, y+j) for x,y in B] for i in range(17) for j in range(3)]
529
- C = [[(x+i, y+j) for x,y in C] for i in range(17) for j in range(3)]
530
- D = [[(x+i, y+j) for x,y in D]+[51+j] for i in range(17) for j in range(3)]
531
- E = [[(x+i, y+j) for x,y in E]+[54+j] for i in range(17) for j in range(3)]
532
- F = [[(x+i, y+i) for x,y in F]+[57] for i in range(17)]
533
-
534
- blocks = [[int(x) if not isinstance(x,tuple) else (x[1] % 3)*17+(x[0] % 17) for x in S]
535
- for S in A+B+C+D+E+F+[list(range(51,58))]]
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, y+j) for x,y in A] for i in range(21) for j in range(3)]
548
- B = [[(x+i, y+j) for x,y in B] for i in range(21) for j in range(3)]
549
- C = [[(x+i, y+j) for x,y in C] for i in range(21) for j in range(3)]
550
- D = [[(x+i, y+j) for x,y in D] for i in range(21) for j in range(3)]
551
- E = [[(x+i, y+j) for x,y in E]+[63+j] for i in range(21) for j in range(3)]
552
- F = [[(x+3*i+j, y+ii+j) for x,y in F]+[66+j] for i in range( 7) for j in range(3) for ii in range(3)]
553
- H = [[(x+i, y+i) for x,y in H]+[69] for i in range(21)]
554
-
555
- blocks = [[int(x) if not isinstance(x,tuple) else (x[1] % 3)*21+(x[0] % 21)
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 import transversal_design
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) if i not in S] + S)})
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
- PBD_4_7(3*u+1,existence=True) is True):
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)