passagemath-graphs 10.5.43__cp39-cp39-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.
Files changed (258) hide show
  1. passagemath_graphs-10.5.43.dist-info/METADATA +293 -0
  2. passagemath_graphs-10.5.43.dist-info/RECORD +258 -0
  3. passagemath_graphs-10.5.43.dist-info/WHEEL +5 -0
  4. passagemath_graphs-10.5.43.dist-info/top_level.txt +2 -0
  5. passagemath_graphs.libs/libgcc_s-69c45f16.so.1 +0 -0
  6. passagemath_graphs.libs/libgmp-8e78bd9b.so.10.5.0 +0 -0
  7. passagemath_graphs.libs/libstdc++-1f1a71be.so.6.0.33 +0 -0
  8. sage/all__sagemath_graphs.py +39 -0
  9. sage/combinat/abstract_tree.py +2552 -0
  10. sage/combinat/all__sagemath_graphs.py +34 -0
  11. sage/combinat/binary_tree.py +5306 -0
  12. sage/combinat/cluster_algebra_quiver/all.py +22 -0
  13. sage/combinat/cluster_algebra_quiver/cluster_seed.py +5208 -0
  14. sage/combinat/cluster_algebra_quiver/interact.py +125 -0
  15. sage/combinat/cluster_algebra_quiver/mutation_class.py +625 -0
  16. sage/combinat/cluster_algebra_quiver/mutation_type.py +1556 -0
  17. sage/combinat/cluster_algebra_quiver/quiver.py +2262 -0
  18. sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py +2468 -0
  19. sage/combinat/designs/MOLS_handbook_data.py +570 -0
  20. sage/combinat/designs/all.py +58 -0
  21. sage/combinat/designs/bibd.py +1655 -0
  22. sage/combinat/designs/block_design.py +1071 -0
  23. sage/combinat/designs/covering_array.py +269 -0
  24. sage/combinat/designs/covering_design.py +534 -0
  25. sage/combinat/designs/database.py +5614 -0
  26. sage/combinat/designs/design_catalog.py +122 -0
  27. sage/combinat/designs/designs_pyx.cpython-39-aarch64-linux-gnu.so +0 -0
  28. sage/combinat/designs/designs_pyx.pxd +21 -0
  29. sage/combinat/designs/designs_pyx.pyx +993 -0
  30. sage/combinat/designs/difference_family.py +3951 -0
  31. sage/combinat/designs/difference_matrices.py +279 -0
  32. sage/combinat/designs/evenly_distributed_sets.cpython-39-aarch64-linux-gnu.so +0 -0
  33. sage/combinat/designs/evenly_distributed_sets.pyx +661 -0
  34. sage/combinat/designs/ext_rep.py +1064 -0
  35. sage/combinat/designs/gen_quadrangles_with_spread.cpython-39-aarch64-linux-gnu.so +0 -0
  36. sage/combinat/designs/gen_quadrangles_with_spread.pyx +339 -0
  37. sage/combinat/designs/group_divisible_designs.py +361 -0
  38. sage/combinat/designs/incidence_structures.py +2357 -0
  39. sage/combinat/designs/latin_squares.py +548 -0
  40. sage/combinat/designs/orthogonal_arrays.py +2243 -0
  41. sage/combinat/designs/orthogonal_arrays_build_recursive.py +1780 -0
  42. sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-39-aarch64-linux-gnu.so +0 -0
  43. sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +966 -0
  44. sage/combinat/designs/resolvable_bibd.py +781 -0
  45. sage/combinat/designs/steiner_quadruple_systems.py +1306 -0
  46. sage/combinat/designs/subhypergraph_search.cpython-39-aarch64-linux-gnu.so +0 -0
  47. sage/combinat/designs/subhypergraph_search.pyx +530 -0
  48. sage/combinat/designs/twographs.py +306 -0
  49. sage/combinat/finite_state_machine.py +14874 -0
  50. sage/combinat/finite_state_machine_generators.py +2006 -0
  51. sage/combinat/graph_path.py +448 -0
  52. sage/combinat/interval_posets.py +3908 -0
  53. sage/combinat/nu_tamari_lattice.py +269 -0
  54. sage/combinat/ordered_tree.py +1446 -0
  55. sage/combinat/posets/all.py +46 -0
  56. sage/combinat/posets/cartesian_product.py +493 -0
  57. sage/combinat/posets/d_complete.py +182 -0
  58. sage/combinat/posets/elements.py +273 -0
  59. sage/combinat/posets/forest.py +30 -0
  60. sage/combinat/posets/hasse_cython.cpython-39-aarch64-linux-gnu.so +0 -0
  61. sage/combinat/posets/hasse_cython.pyx +174 -0
  62. sage/combinat/posets/hasse_diagram.py +3678 -0
  63. sage/combinat/posets/incidence_algebras.py +796 -0
  64. sage/combinat/posets/lattices.py +5119 -0
  65. sage/combinat/posets/linear_extension_iterator.cpython-39-aarch64-linux-gnu.so +0 -0
  66. sage/combinat/posets/linear_extension_iterator.pyx +292 -0
  67. sage/combinat/posets/linear_extensions.py +1039 -0
  68. sage/combinat/posets/mobile.py +275 -0
  69. sage/combinat/posets/moebius_algebra.py +776 -0
  70. sage/combinat/posets/poset_examples.py +2131 -0
  71. sage/combinat/posets/posets.py +9169 -0
  72. sage/combinat/rooted_tree.py +1070 -0
  73. sage/combinat/shard_order.py +239 -0
  74. sage/combinat/tamari_lattices.py +384 -0
  75. sage/combinat/yang_baxter_graph.py +923 -0
  76. sage/databases/all__sagemath_graphs.py +1 -0
  77. sage/databases/knotinfo_db.py +1230 -0
  78. sage/ext_data/all__sagemath_graphs.py +1 -0
  79. sage/ext_data/graphs/graph_plot_js.html +330 -0
  80. sage/ext_data/kenzo/CP2.txt +45 -0
  81. sage/ext_data/kenzo/CP3.txt +349 -0
  82. sage/ext_data/kenzo/CP4.txt +4774 -0
  83. sage/ext_data/kenzo/README.txt +49 -0
  84. sage/ext_data/kenzo/S4.txt +20 -0
  85. sage/graphs/all.py +42 -0
  86. sage/graphs/asteroidal_triples.cpython-39-aarch64-linux-gnu.so +0 -0
  87. sage/graphs/asteroidal_triples.pyx +299 -0
  88. sage/graphs/base/all.py +1 -0
  89. sage/graphs/base/boost_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  90. sage/graphs/base/boost_graph.pxd +106 -0
  91. sage/graphs/base/boost_graph.pyx +3045 -0
  92. sage/graphs/base/c_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  93. sage/graphs/base/c_graph.pxd +106 -0
  94. sage/graphs/base/c_graph.pyx +5096 -0
  95. sage/graphs/base/dense_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  96. sage/graphs/base/dense_graph.pxd +26 -0
  97. sage/graphs/base/dense_graph.pyx +757 -0
  98. sage/graphs/base/graph_backends.cpython-39-aarch64-linux-gnu.so +0 -0
  99. sage/graphs/base/graph_backends.pxd +5 -0
  100. sage/graphs/base/graph_backends.pyx +797 -0
  101. sage/graphs/base/overview.py +85 -0
  102. sage/graphs/base/sparse_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  103. sage/graphs/base/sparse_graph.pxd +90 -0
  104. sage/graphs/base/sparse_graph.pyx +1653 -0
  105. sage/graphs/base/static_dense_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  106. sage/graphs/base/static_dense_graph.pxd +5 -0
  107. sage/graphs/base/static_dense_graph.pyx +1032 -0
  108. sage/graphs/base/static_sparse_backend.cpython-39-aarch64-linux-gnu.so +0 -0
  109. sage/graphs/base/static_sparse_backend.pxd +27 -0
  110. sage/graphs/base/static_sparse_backend.pyx +1580 -0
  111. sage/graphs/base/static_sparse_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  112. sage/graphs/base/static_sparse_graph.pxd +37 -0
  113. sage/graphs/base/static_sparse_graph.pyx +1304 -0
  114. sage/graphs/bipartite_graph.py +2709 -0
  115. sage/graphs/centrality.cpython-39-aarch64-linux-gnu.so +0 -0
  116. sage/graphs/centrality.pyx +965 -0
  117. sage/graphs/cographs.py +519 -0
  118. sage/graphs/comparability.cpython-39-aarch64-linux-gnu.so +0 -0
  119. sage/graphs/comparability.pyx +813 -0
  120. sage/graphs/connectivity.cpython-39-aarch64-linux-gnu.so +0 -0
  121. sage/graphs/connectivity.pxd +157 -0
  122. sage/graphs/connectivity.pyx +4813 -0
  123. sage/graphs/convexity_properties.cpython-39-aarch64-linux-gnu.so +0 -0
  124. sage/graphs/convexity_properties.pxd +16 -0
  125. sage/graphs/convexity_properties.pyx +827 -0
  126. sage/graphs/digraph.py +4410 -0
  127. sage/graphs/digraph_generators.py +1921 -0
  128. sage/graphs/distances_all_pairs.cpython-39-aarch64-linux-gnu.so +0 -0
  129. sage/graphs/distances_all_pairs.pxd +12 -0
  130. sage/graphs/distances_all_pairs.pyx +2938 -0
  131. sage/graphs/domination.py +1363 -0
  132. sage/graphs/dot2tex_utils.py +100 -0
  133. sage/graphs/edge_connectivity.cpython-39-aarch64-linux-gnu.so +0 -0
  134. sage/graphs/edge_connectivity.pyx +1215 -0
  135. sage/graphs/generators/all.py +1 -0
  136. sage/graphs/generators/basic.py +1769 -0
  137. sage/graphs/generators/chessboard.py +538 -0
  138. sage/graphs/generators/classical_geometries.py +1611 -0
  139. sage/graphs/generators/degree_sequence.py +235 -0
  140. sage/graphs/generators/distance_regular.cpython-39-aarch64-linux-gnu.so +0 -0
  141. sage/graphs/generators/distance_regular.pyx +2846 -0
  142. sage/graphs/generators/families.py +4749 -0
  143. sage/graphs/generators/intersection.py +565 -0
  144. sage/graphs/generators/platonic_solids.py +262 -0
  145. sage/graphs/generators/random.py +2623 -0
  146. sage/graphs/generators/smallgraphs.py +5741 -0
  147. sage/graphs/generators/world_map.py +724 -0
  148. sage/graphs/generic_graph.py +26395 -0
  149. sage/graphs/generic_graph_pyx.cpython-39-aarch64-linux-gnu.so +0 -0
  150. sage/graphs/generic_graph_pyx.pxd +34 -0
  151. sage/graphs/generic_graph_pyx.pyx +1626 -0
  152. sage/graphs/genus.cpython-39-aarch64-linux-gnu.so +0 -0
  153. sage/graphs/genus.pyx +623 -0
  154. sage/graphs/graph.py +9362 -0
  155. sage/graphs/graph_coloring.cpython-39-aarch64-linux-gnu.so +0 -0
  156. sage/graphs/graph_coloring.pyx +2284 -0
  157. sage/graphs/graph_database.py +1122 -0
  158. sage/graphs/graph_decompositions/all.py +1 -0
  159. sage/graphs/graph_decompositions/bandwidth.cpython-39-aarch64-linux-gnu.so +0 -0
  160. sage/graphs/graph_decompositions/bandwidth.pyx +428 -0
  161. sage/graphs/graph_decompositions/clique_separators.cpython-39-aarch64-linux-gnu.so +0 -0
  162. sage/graphs/graph_decompositions/clique_separators.pyx +595 -0
  163. sage/graphs/graph_decompositions/cutwidth.cpython-39-aarch64-linux-gnu.so +0 -0
  164. sage/graphs/graph_decompositions/cutwidth.pyx +753 -0
  165. sage/graphs/graph_decompositions/fast_digraph.cpython-39-aarch64-linux-gnu.so +0 -0
  166. sage/graphs/graph_decompositions/fast_digraph.pxd +13 -0
  167. sage/graphs/graph_decompositions/fast_digraph.pyx +212 -0
  168. sage/graphs/graph_decompositions/graph_products.cpython-39-aarch64-linux-gnu.so +0 -0
  169. sage/graphs/graph_decompositions/graph_products.pyx +462 -0
  170. sage/graphs/graph_decompositions/modular_decomposition.cpython-39-aarch64-linux-gnu.so +0 -0
  171. sage/graphs/graph_decompositions/modular_decomposition.pxd +27 -0
  172. sage/graphs/graph_decompositions/modular_decomposition.pyx +1536 -0
  173. sage/graphs/graph_decompositions/slice_decomposition.cpython-39-aarch64-linux-gnu.so +0 -0
  174. sage/graphs/graph_decompositions/slice_decomposition.pxd +18 -0
  175. sage/graphs/graph_decompositions/slice_decomposition.pyx +1080 -0
  176. sage/graphs/graph_decompositions/tree_decomposition.cpython-39-aarch64-linux-gnu.so +0 -0
  177. sage/graphs/graph_decompositions/tree_decomposition.pxd +17 -0
  178. sage/graphs/graph_decompositions/tree_decomposition.pyx +1996 -0
  179. sage/graphs/graph_decompositions/vertex_separation.cpython-39-aarch64-linux-gnu.so +0 -0
  180. sage/graphs/graph_decompositions/vertex_separation.pxd +5 -0
  181. sage/graphs/graph_decompositions/vertex_separation.pyx +1963 -0
  182. sage/graphs/graph_editor.py +82 -0
  183. sage/graphs/graph_generators.py +3301 -0
  184. sage/graphs/graph_generators_pyx.cpython-39-aarch64-linux-gnu.so +0 -0
  185. sage/graphs/graph_generators_pyx.pyx +95 -0
  186. sage/graphs/graph_input.py +812 -0
  187. sage/graphs/graph_latex.py +2064 -0
  188. sage/graphs/graph_list.py +367 -0
  189. sage/graphs/graph_plot.py +1749 -0
  190. sage/graphs/graph_plot_js.py +338 -0
  191. sage/graphs/hyperbolicity.cpython-39-aarch64-linux-gnu.so +0 -0
  192. sage/graphs/hyperbolicity.pyx +1702 -0
  193. sage/graphs/hypergraph_generators.py +364 -0
  194. sage/graphs/independent_sets.cpython-39-aarch64-linux-gnu.so +0 -0
  195. sage/graphs/independent_sets.pxd +13 -0
  196. sage/graphs/independent_sets.pyx +402 -0
  197. sage/graphs/isgci.py +1033 -0
  198. sage/graphs/isoperimetric_inequalities.cpython-39-aarch64-linux-gnu.so +0 -0
  199. sage/graphs/isoperimetric_inequalities.pyx +453 -0
  200. sage/graphs/line_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  201. sage/graphs/line_graph.pyx +627 -0
  202. sage/graphs/lovasz_theta.py +77 -0
  203. sage/graphs/matching.py +1633 -0
  204. sage/graphs/matching_covered_graph.py +3566 -0
  205. sage/graphs/orientations.py +1504 -0
  206. sage/graphs/partial_cube.py +459 -0
  207. sage/graphs/path_enumeration.cpython-39-aarch64-linux-gnu.so +0 -0
  208. sage/graphs/path_enumeration.pyx +2040 -0
  209. sage/graphs/pq_trees.py +1129 -0
  210. sage/graphs/print_graphs.py +201 -0
  211. sage/graphs/schnyder.py +865 -0
  212. sage/graphs/spanning_tree.cpython-39-aarch64-linux-gnu.so +0 -0
  213. sage/graphs/spanning_tree.pyx +1457 -0
  214. sage/graphs/strongly_regular_db.cpython-39-aarch64-linux-gnu.so +0 -0
  215. sage/graphs/strongly_regular_db.pyx +3340 -0
  216. sage/graphs/traversals.cpython-39-aarch64-linux-gnu.so +0 -0
  217. sage/graphs/traversals.pxd +9 -0
  218. sage/graphs/traversals.pyx +1871 -0
  219. sage/graphs/trees.cpython-39-aarch64-linux-gnu.so +0 -0
  220. sage/graphs/trees.pxd +15 -0
  221. sage/graphs/trees.pyx +310 -0
  222. sage/graphs/tutte_polynomial.py +713 -0
  223. sage/graphs/views.cpython-39-aarch64-linux-gnu.so +0 -0
  224. sage/graphs/views.pyx +794 -0
  225. sage/graphs/weakly_chordal.cpython-39-aarch64-linux-gnu.so +0 -0
  226. sage/graphs/weakly_chordal.pyx +562 -0
  227. sage/groups/all__sagemath_graphs.py +1 -0
  228. sage/groups/perm_gps/all__sagemath_graphs.py +1 -0
  229. sage/groups/perm_gps/partn_ref/all__sagemath_graphs.py +1 -0
  230. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-39-aarch64-linux-gnu.so +0 -0
  231. sage/groups/perm_gps/partn_ref/refinement_graphs.pxd +38 -0
  232. sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +1666 -0
  233. sage/knots/all.py +6 -0
  234. sage/knots/free_knotinfo_monoid.py +507 -0
  235. sage/knots/gauss_code.py +291 -0
  236. sage/knots/knot.py +682 -0
  237. sage/knots/knot_table.py +284 -0
  238. sage/knots/knotinfo.py +2880 -0
  239. sage/knots/link.py +4682 -0
  240. sage/sandpiles/all.py +13 -0
  241. sage/sandpiles/examples.py +225 -0
  242. sage/sandpiles/sandpile.py +6365 -0
  243. sage/topology/all.py +22 -0
  244. sage/topology/cell_complex.py +1214 -0
  245. sage/topology/cubical_complex.py +1977 -0
  246. sage/topology/delta_complex.py +1806 -0
  247. sage/topology/filtered_simplicial_complex.py +744 -0
  248. sage/topology/moment_angle_complex.py +823 -0
  249. sage/topology/simplicial_complex.py +5161 -0
  250. sage/topology/simplicial_complex_catalog.py +86 -0
  251. sage/topology/simplicial_complex_examples.py +1692 -0
  252. sage/topology/simplicial_complex_homset.py +205 -0
  253. sage/topology/simplicial_complex_morphism.py +836 -0
  254. sage/topology/simplicial_set.py +4102 -0
  255. sage/topology/simplicial_set_catalog.py +55 -0
  256. sage/topology/simplicial_set_constructions.py +2954 -0
  257. sage/topology/simplicial_set_examples.py +865 -0
  258. sage/topology/simplicial_set_morphism.py +1464 -0
@@ -0,0 +1,966 @@
1
+ # sage_setup: distribution = sagemath-graphs
2
+ # sage.doctest: needs sage.rings.finite_rings sage.schemes
3
+ # cython: cdivision=True
4
+ r"""
5
+ Orthogonal arrays (find recursive constructions)
6
+
7
+ This module implements several functions to find recursive constructions of
8
+ :mod:`Orthogonal Arrays <sage.combinat.designs.orthogonal_arrays>`.
9
+
10
+ The main function of this module, i.e. :func:`find_recursive_construction`,
11
+ queries all implemented recursive constructions of designs implemented in
12
+ :mod:`~sage.combinat.designs.orthogonal_arrays_build_recursive` in order to
13
+ obtain an `OA(k,n)`.
14
+
15
+ :func:`find_recursive_construction` is called by the
16
+ :func:`~sage.combinat.designs.orthogonal_arrays.orthogonal_array` function.
17
+
18
+ .. csv-table::
19
+ :class: contentstable
20
+ :widths: 30, 70
21
+ :delim: |
22
+
23
+ :func:`find_recursive_construction` | Find a recursive construction of an `OA(k,n)` (calls all others ``find_*`` functions)
24
+ :func:`find_product_decomposition` | Find `n_1n_2=n` to obtain an `OA(k,n)` by the product construction
25
+ :func:`find_wilson_decomposition_with_one_truncated_group` | Find `rm+u=n` to obtain an `OA(k,n)` by Wilson's construction with one truncated column.
26
+ :func:`find_wilson_decomposition_with_two_truncated_groups` | Find `rm+r_1+r_2=n` to obtain an `OA(k,n)` by Wilson's construction with two truncated columns.
27
+ :func:`find_construction_3_3` | Find a decomposition for construction 3.3 from [AC07]_.
28
+ :func:`find_construction_3_4` | Find a decomposition for construction 3.4 from [AC07]_.
29
+ :func:`find_construction_3_5` | Find a decomposition for construction 3.5 from [AC07]_.
30
+ :func:`find_construction_3_6` | Find a decomposition for construction 3.6 from [AC07]_.
31
+ :func:`find_q_x` | Find integers `q,x` such that the `q-x` construction yields an `OA(k,n)`.
32
+ :func:`find_thwart_lemma_3_5` | Find the values on which Lemma 3.5 from [Thwarts]_ applies.
33
+ :func:`find_thwart_lemma_4_1` | Find a decomposition for Lemma 4.1 from [Thwarts]_.
34
+ :func:`find_three_factor_product` | Find `n_1n_2n_3=n` to obtain an `OA(k,n)` by the three-factor product from [DukesLing14]_
35
+ :func:`find_brouwer_separable_design` | Find `t(q^2+q+1)+x=n` to obtain an `OA(k,n)` by Brouwer's separable design construction.
36
+ :func:`find_brouwer_van_rees_with_one_truncated_column` | Find `rm+x_1+...+x_c=n` such that the Brouwer-van Rees constructions yields a `OA(k,n)`.
37
+
38
+ REFERENCES:
39
+
40
+ .. [AC07] Concerning eight mutually orthogonal latin squares
41
+ Julian R. Abel, Nicholas Cavenagh
42
+ Journal of Combinatorial Designs
43
+ Vol. 15, n.3, pp. 255-261
44
+ 2007
45
+
46
+ Functions
47
+ ---------
48
+ """
49
+
50
+ from sage.misc.cachefunc import cached_function
51
+ from sage.combinat.designs.orthogonal_arrays import orthogonal_array
52
+ from sage.rings.integer cimport smallInteger
53
+ from sage.arith.misc import prime_powers
54
+
55
+
56
+ @cached_function
57
+ def find_recursive_construction(k, n):
58
+ r"""
59
+ Find a recursive construction of an `OA(k,n)` (calls all others ``find_*`` functions).
60
+
61
+ This determines whether an `OA(k,n)` can be built through the following
62
+ constructions:
63
+
64
+ - :func:`~sage.combinat.designs.orthogonal_arrays.wilson_construction`
65
+ - :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.construction_3_3`
66
+ - :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.construction_3_4`
67
+ - :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.construction_3_5`
68
+ - :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.construction_3_6`
69
+ - :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.construction_q_x`
70
+ - :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.thwart_lemma_3_5`
71
+ - :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.thwart_lemma_4_1`
72
+ - :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.three_factor_product`
73
+ - :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.brouwer_separable_design`
74
+
75
+ INPUT:
76
+
77
+ - ``k``, ``n`` -- integers
78
+
79
+ OUTPUT:
80
+
81
+ Return a pair ``f,args`` such that ``f(*args)`` returns the requested `OA`
82
+ if possible, and ``False`` otherwise.
83
+
84
+ EXAMPLES::
85
+
86
+ sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_recursive_construction
87
+ sage: from sage.combinat.designs.orthogonal_arrays import is_orthogonal_array
88
+ sage: count = 0
89
+ sage: for n in range(10,150):
90
+ ....: k = designs.orthogonal_arrays.largest_available_k(n)
91
+ ....: if find_recursive_construction(k,n):
92
+ ....: count = count + 1
93
+ ....: f,args = find_recursive_construction(k,n)
94
+ ....: OA = f(*args)
95
+ ....: assert is_orthogonal_array(OA,k,n,2,verbose=True)
96
+ sage: count
97
+ 56
98
+ """
99
+ assert k > 3
100
+
101
+ for find_c in [find_product_decomposition,
102
+ find_wilson_decomposition_with_one_truncated_group,
103
+ find_wilson_decomposition_with_two_truncated_groups,
104
+ find_construction_3_3,
105
+ find_construction_3_4,
106
+ find_construction_3_5,
107
+ find_construction_3_6,
108
+ find_q_x,
109
+ find_thwart_lemma_3_5,
110
+ find_thwart_lemma_4_1,
111
+ find_three_factor_product,
112
+ find_brouwer_separable_design,
113
+ find_brouwer_van_rees_with_one_truncated_column]:
114
+ res = find_c(k,n)
115
+ if res:
116
+ return res
117
+ return False
118
+
119
+
120
+ cpdef find_product_decomposition(int k, int n):
121
+ r"""
122
+ Find `n_1n_2=n` to obtain an `OA(k,n)` by the product construction.
123
+
124
+ If Sage can build a `OA(k,n_1)` and a `OA(k,n_2)` such that `n=n_1\times
125
+ n_2` then a `OA(k,n)` can be built by a product construction (which
126
+ correspond to Wilson's construction with no truncated column). This
127
+ function look for a pair of integers `(n_1,n_2)` with `n1 \leq n_2`, `n_1
128
+ \times n_2 = n` and such that both an `OA(k,n_1)` and an `OA(k,n_2)` are
129
+ available.
130
+
131
+ INPUT:
132
+
133
+ - ``k``, ``n`` -- integers
134
+
135
+ OUTPUT:
136
+
137
+ A pair ``f,args`` such that ``f(*args)`` is an `OA(k,n)` or ``False`` if no
138
+ product decomposition was found.
139
+
140
+ EXAMPLES::
141
+
142
+ sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_product_decomposition
143
+ sage: f,args = find_product_decomposition(6, 84)
144
+ sage: args
145
+ (None, 6, 7, 12, (), False)
146
+ sage: _ = f(*args)
147
+ """
148
+ cdef int n1,n2
149
+ for n1 in range(2, n):
150
+ n2 = n/n1 # n2 is decreasing along the loop
151
+ if n2 < n1:
152
+ break
153
+ if n%n1: # we want to iterate only through divisors of n1... it seems
154
+ # faster to use that rather than calling the divisors function
155
+ continue
156
+ if is_available(k, n1) and is_available(k, n2):
157
+ from sage.combinat.designs.orthogonal_arrays import wilson_construction
158
+ return wilson_construction, (None,k,n1,n2,(),False)
159
+ return False
160
+
161
+ cpdef find_wilson_decomposition_with_one_truncated_group(int k, int n):
162
+ r"""
163
+ Find `rm+u=n` to obtain an `OA(k,n)` by Wilson's construction with one truncated column.
164
+
165
+ This function looks for possible integers `m,t,u` satisfying that `mt+u=n` and
166
+ such that Sage knows how to build a `OA(k,m)`, `OA(k,m+1)`, `OA(k+1,t)` and a
167
+ `OA(k,u)`.
168
+
169
+ INPUT:
170
+
171
+ - ``k``, ``n`` -- integers
172
+
173
+ OUTPUT:
174
+
175
+ A pair ``f,args`` such that ``f(*args)`` is an `OA(k,n)` or ``False`` if no
176
+ decomposition with one truncated block was found.
177
+
178
+ EXAMPLES::
179
+
180
+ sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_wilson_decomposition_with_one_truncated_group
181
+ sage: f,args = find_wilson_decomposition_with_one_truncated_group(4,38)
182
+ sage: args
183
+ (None, 4, 5, 7, (3,), False)
184
+ sage: _ = f(*args)
185
+
186
+ sage: find_wilson_decomposition_with_one_truncated_group(4,20)
187
+ False
188
+ """
189
+ cdef int r,u,m
190
+ # If there exists a TD(k+1,t) then k+1 < t+2, i.e. k <= t
191
+ for r in range(max(1,k),n-1):
192
+ u = n%r
193
+ # We ensure that 1<=u, and that there can exists a TD(k,u), i.e k<u+2
194
+ # (unless u == 1)
195
+ if u == 0 or (u>1 and k >= u+2):
196
+ continue
197
+
198
+ m = n // r
199
+ # If there exists a TD(k,m) then k<m+2
200
+ if k >= m+2:
201
+ break
202
+
203
+ if (is_available(k, m) and is_available(k, m + 1) and
204
+ is_available(k + 1, r) and is_available(k, u)):
205
+ from sage.combinat.designs.orthogonal_arrays import wilson_construction
206
+ return wilson_construction, (None,k,r,m,(u,),False)
207
+
208
+ return False
209
+
210
+ cpdef find_wilson_decomposition_with_two_truncated_groups(int k, int n):
211
+ r"""
212
+ Find `rm+r_1+r_2=n` to obtain an `OA(k,n)` by Wilson's construction with two truncated columns.
213
+
214
+ Look for integers `r,m,r_1,r_2` satisfying `n=rm+r_1+r_2` and `1\leq r_1,r_2<r`
215
+ and such that the following designs exist : `OA(k+2,r)`, `OA(k,r1)`,
216
+ `OA(k,r2)`, `OA(k,m)`, `OA(k,m+1)`, `OA(k,m+2)`.
217
+
218
+ INPUT:
219
+
220
+ - ``k``, ``n`` -- integers
221
+
222
+ OUTPUT:
223
+
224
+ A pair ``f,args`` such that ``f(*args)`` is an `OA(k,n)` or ``False`` if no
225
+ decomposition with two truncated blocks was found.
226
+
227
+ EXAMPLES::
228
+
229
+ sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_wilson_decomposition_with_two_truncated_groups
230
+ sage: f,args = find_wilson_decomposition_with_two_truncated_groups(5,58)
231
+ sage: args
232
+ (None, 5, 7, 7, (4, 5), False)
233
+ sage: _ = f(*args)
234
+ """
235
+ cdef int r,m_min,m_max,m,r1_min,r1_max,r1,r2,r1_p_r2
236
+ for r in [1] + list(range(k+1, n-2)):
237
+ # as r*1+1+1 <= n and because we need
238
+ # an OA(k+2,r), necessarily r=1 or r >= k+1
239
+ if not is_available(k+2,r):
240
+ continue
241
+ m_min = (n - (2*r-2))/r
242
+ m_max = (n - 2)/r
243
+ if m_min > 1:
244
+ m_values = list(range(max(m_min, k - 1), m_max + 1))
245
+ else:
246
+ m_values = [1] + list(range(k - 1, m_max + 1))
247
+ for m in m_values:
248
+ r1_p_r2 = n-r*m # the sum of r1+r2
249
+ # it is automatically >= 2 since m <= m_max
250
+ if (r1_p_r2 > 2*r-2 or
251
+ not is_available(k,m ) or
252
+ not is_available(k,m+1) or
253
+ not is_available(k,m+2)):
254
+ continue
255
+
256
+ r1_min = r1_p_r2 - (r-1)
257
+ r1_max = min(r-1, r1_p_r2)
258
+ if r1_min > 1:
259
+ r1_values = range(max(k - 1, r1_min), r1_max + 1)
260
+ else:
261
+ r1_values = [1] + list(range(k-1, r1_max + 1))
262
+ for r1 in r1_values:
263
+ if not is_available(k,r1):
264
+ continue
265
+ r2 = r1_p_r2-r1
266
+ if is_available(k,r2):
267
+ assert n == r*m+r1+r2
268
+ from sage.combinat.designs.orthogonal_arrays import wilson_construction
269
+ return wilson_construction, (None,k,r,m,(r1,r2),False)
270
+ return False
271
+
272
+ cpdef find_construction_3_3(int k, int n):
273
+ r"""
274
+ Find a decomposition for construction 3.3 from [AC07]_.
275
+
276
+ INPUT:
277
+
278
+ - ``k``, ``n`` -- integers
279
+
280
+ .. SEEALSO::
281
+
282
+ :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.construction_3_3`
283
+
284
+ OUTPUT:
285
+
286
+ A pair ``f,args`` such that ``f(*args)`` returns the requested OA.
287
+
288
+ EXAMPLES::
289
+
290
+ sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_construction_3_3
291
+ sage: find_construction_3_3(11,177)[1]
292
+ (11, 11, 16, 1)
293
+ sage: find_construction_3_3(12,11)
294
+ """
295
+ cdef int mm,nn,i
296
+ for mm in range(k-1, n//2+1):
297
+ if not(is_available(k, mm) and is_available(k, mm + 1)):
298
+ continue
299
+
300
+ for nn in range(2, n//mm+1):
301
+ i = n-nn*mm
302
+ if i <= 0:
303
+ continue
304
+
305
+ if is_available(k + i, nn) and is_available(k, mm + i):
306
+ from sage.combinat.designs.orthogonal_arrays_build_recursive import construction_3_3
307
+ return construction_3_3, (k, nn, mm, i)
308
+
309
+ cpdef find_construction_3_4(int k, int n):
310
+ r"""
311
+ Find a decomposition for construction 3.4 from [AC07]_.
312
+
313
+ INPUT:
314
+
315
+ - ``k``, ``n`` -- integers
316
+
317
+ .. SEEALSO::
318
+
319
+ :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.construction_3_4`
320
+
321
+ OUTPUT:
322
+
323
+ A pair ``f,args`` such that ``f(*args)`` returns the requested OA.
324
+
325
+ EXAMPLES::
326
+
327
+ sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_construction_3_4
328
+ sage: find_construction_3_4(8,196)[1]
329
+ (8, 25, 7, 12, 9)
330
+ sage: find_construction_3_4(9,24)
331
+ """
332
+ cdef int mm,nn,i,r,s
333
+ for mm in range(k-1,n/2+1):
334
+ if (not is_available(k,mm+0) or
335
+ not is_available(k,mm+1) or
336
+ not is_available(k,mm+2)):
337
+ continue
338
+
339
+ for nn in range(2, n//mm+1):
340
+ i = n-nn*mm
341
+ if i<=0:
342
+ continue
343
+
344
+ for s in range(1,min(i,nn)):
345
+ r = i-s
346
+ if (is_available(k + r + 1, nn) and
347
+ is_available(k, s) and
348
+ (is_available(k, mm + r) or is_available(k, mm + r + 1))):
349
+ from sage.combinat.designs.orthogonal_arrays_build_recursive import construction_3_4
350
+ return construction_3_4, (k, nn, mm, r, s)
351
+
352
+ cpdef find_construction_3_5(int k, int n):
353
+ r"""
354
+ Find a decomposition for construction 3.5 from [AC07]_.
355
+
356
+ INPUT:
357
+
358
+ - ``k``, ``n`` -- integers
359
+
360
+ .. SEEALSO::
361
+
362
+ :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.construction_3_5`
363
+
364
+ OUTPUT:
365
+
366
+ A pair ``f,args`` such that ``f(*args)`` returns the requested OA.
367
+
368
+ EXAMPLES::
369
+
370
+ sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_construction_3_5
371
+ sage: find_construction_3_5(8,111)[1]
372
+ (8, 13, 6, 9, 11, 13)
373
+ sage: find_construction_3_5(9,24)
374
+ """
375
+ cdef int mm,i,nn,r,s,t
376
+ for mm in range(2, n//2+1):
377
+ if (mm+3 >= n or
378
+ not is_available(k,mm+1) or
379
+ not is_available(k,mm+2) or
380
+ not is_available(k,mm+3)):
381
+ continue
382
+
383
+ for nn in range(2, n//mm+1):
384
+ i = n-nn*mm
385
+ if i<=0:
386
+ continue
387
+
388
+ if not is_available(k+3,nn):
389
+ continue
390
+
391
+ # Enumerate all r,s,t<nn such that r+s+t=i and r<=s
392
+ for s in range(min(i+1,nn)):
393
+ for r in range(max(0,i-nn-s), min(s+1,i-s+1,nn)):
394
+ t = i - r - s
395
+ if ((nn-r-1)*(nn-s) < t and
396
+ (r==0 or is_available(k,r)) and
397
+ (s==0 or is_available(k,s)) and
398
+ (t==0 or is_available(k,t))):
399
+ from sage.combinat.designs.orthogonal_arrays_build_recursive import construction_3_5
400
+ return construction_3_5, (k,nn,mm,r,s,t)
401
+
402
+ cpdef find_construction_3_6(int k, int n):
403
+ r"""
404
+ Find a decomposition for construction 3.6 from [AC07]_.
405
+
406
+ INPUT:
407
+
408
+ - ``k``, ``n`` -- integers
409
+
410
+ .. SEEALSO::
411
+
412
+ :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.construction_3_6`
413
+
414
+ OUTPUT:
415
+
416
+ A pair ``f,args`` such that ``f(*args)`` returns the requested OA.
417
+
418
+ EXAMPLES::
419
+
420
+ sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_construction_3_6
421
+ sage: find_construction_3_6(8,95)[1]
422
+ (8, 13, 7, 4)
423
+ sage: find_construction_3_6(8,98)
424
+ """
425
+ cdef int mm,nn,i
426
+
427
+ for mm in range(k-1,n/2+1):
428
+ if (not is_available(k,mm+0) or
429
+ not is_available(k,mm+1) or
430
+ not is_available(k,mm+2)):
431
+ continue
432
+
433
+ for nn in range(2, n//mm+1):
434
+ i = n-nn*mm
435
+ if i<=0:
436
+ continue
437
+
438
+ if (is_available(k+i,nn) and
439
+ smallInteger(nn).is_prime_power()):
440
+ from sage.combinat.designs.orthogonal_arrays_build_recursive import construction_3_6
441
+ return construction_3_6, (k,nn,mm,i)
442
+
443
+ cpdef find_q_x(int k, int n):
444
+ r"""
445
+ Find integers `q,x` such that the `q-x` construction yields an `OA(k,n)`.
446
+
447
+ See the documentation of :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.construction_q_x` to find out what
448
+ hypotheses the integers `q,x` must satisfy.
449
+
450
+ .. WARNING::
451
+
452
+ For efficiency reasons, this function checks that Sage can build an
453
+ `OA(k+1,q-x-1)` and an `OA(k+1,q-x+1)`, which is stronger than checking
454
+ that Sage can build a `OA(k,q-x-1)-(q-x-1).OA(k,1)` and a
455
+ `OA(k,q-x+1)-(q-x+1).OA(k,1)`. The latter would trigger a lot of
456
+ independent set computations in
457
+ :func:`sage.combinat.designs.orthogonal_arrays.incomplete_orthogonal_array`.
458
+
459
+ INPUT:
460
+
461
+ - ``k``, ``n`` -- integers
462
+
463
+ .. SEEALSO::
464
+
465
+ :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.construction_q_x`
466
+
467
+ EXAMPLES::
468
+
469
+ sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_q_x
470
+ sage: find_q_x(10,9)
471
+ False
472
+ sage: find_q_x(9,158)[1]
473
+ (9, 16, 6)
474
+ """
475
+ cdef int q,x
476
+
477
+ # n = (q-1)*(q-x) + x + 2
478
+ # = q^2 - q*x - q + 2*x + 2
479
+ for q in range(max(3,k+2),n):
480
+ # n-q**2+q-2 = 2x-qx
481
+ # = x(2-q)
482
+ x = (n-q**2+q-2)/(2-q)
483
+ if (x < q and
484
+ 0 < x and
485
+ n == (q-1)*(q-x)+x+2 and
486
+ is_available(k+1,q-x-1) and
487
+ is_available(k+1,q-x+1) and
488
+ # The next is always True, because q is a prime power
489
+ # is_available(k+1,q) and
490
+ is_available(k, x+2 ) and
491
+ smallInteger(q).is_prime_power()):
492
+ from sage.combinat.designs.orthogonal_arrays_build_recursive import construction_q_x
493
+ return construction_q_x, (k,q,x)
494
+ return False
495
+
496
+ cpdef find_thwart_lemma_3_5(int k, int N):
497
+ r"""
498
+ Find the values on which Lemma 3.5 from [Thwarts]_ applies.
499
+
500
+ OUTPUT:
501
+
502
+ A pair ``(f,args)`` such that ``f(*args)`` returns an `OA(k,n)` or ``False``
503
+ if the construction is not available.
504
+
505
+ .. SEEALSO::
506
+
507
+ :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.thwart_lemma_3_5`
508
+
509
+ EXAMPLES::
510
+
511
+ sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_thwart_lemma_3_5
512
+ sage: from sage.combinat.designs.designs_pyx import is_orthogonal_array
513
+
514
+ sage: f,args = find_thwart_lemma_3_5(7,66)
515
+ sage: args
516
+ (7, 9, 7, 1, 1, 1, 0, False)
517
+ sage: OA = f(*args)
518
+ sage: is_orthogonal_array(OA,7,66,2)
519
+ True
520
+
521
+ sage: f,args = find_thwart_lemma_3_5(6,100)
522
+ sage: args
523
+ (6, 8, 10, 8, 7, 5, 0, True)
524
+ sage: OA = f(*args)
525
+ sage: is_orthogonal_array(OA,6,100,2)
526
+ True
527
+
528
+ Some values from [Thwarts]_::
529
+
530
+ sage: kn = ((10,1046), (10,1048), (10,1059), (11,1524),
531
+ ....: (11,2164), (12,3362), (12,3992), (12,3994))
532
+ sage: for k,n in kn:
533
+ ....: print("{} {} {}".format(k,n,find_thwart_lemma_3_5(k,n)[1]))
534
+ 10 1046 (10, 13, 79, 9, 1, 0, 9, False)
535
+ 10 1048 (10, 13, 79, 9, 1, 0, 11, False)
536
+ 10 1059 (10, 13, 80, 9, 1, 0, 9, False)
537
+ 11 1524 (11, 19, 78, 16, 13, 13, 0, True)
538
+ 11 2164 (11, 27, 78, 23, 19, 16, 0, True)
539
+ 12 3362 (12, 16, 207, 13, 13, 11, 13, True)
540
+ 12 3992 (12, 19, 207, 16, 13, 11, 19, True)
541
+ 12 3994 (12, 19, 207, 16, 13, 13, 19, True)
542
+
543
+ sage: for k,n in kn: # not tested -- too long
544
+ ....: assert designs.orthogonal_array(k,n,existence=True) is True
545
+ """
546
+ from sage.combinat.designs.orthogonal_arrays_build_recursive import thwart_lemma_3_5
547
+ cdef int n,m,a,b,c,d,NN,na,nb,nc
548
+
549
+ for n in prime_powers(k+2,N-2): # There must exist a OA(k+3,n) thus n>=k+2
550
+ # At least 3 columns are nonempty thus n<N-2
551
+
552
+ # we look for (m,n,a,b,c,d) with N = mn + a + b + c (+d) and
553
+ # 0 <= a,b,c,d <= n
554
+ # hence we have N/n-4 <= m <= N/n
555
+
556
+ # 1. look for m,a,b,c,d with complement=False
557
+ # (we restrict to a >= b >= c)
558
+ for m in range(max(k-1,(N+n-1)/n-4), N/n+1):
559
+ if not (is_available(k,m+0) and
560
+ is_available(k,m+1) and
561
+ is_available(k,m+2)):
562
+ continue
563
+
564
+ NN = N - n*m
565
+ # as a >= b >= c and d <= n we can restrict the start of the loops
566
+ for a in range(max(0, (NN-n+2)/3), min(n, NN)+1): # (NN-n+2)/3 <==> ceil((NN-n)/3)x
567
+ if not is_available(k,a):
568
+ continue
569
+ for b in range(max(0, (NN-n-a+1)/2), min(a, n+1-a, NN-a)+1):
570
+ if not is_available(k,b):
571
+ continue
572
+ for c in range(max(0, NN-n-a-b), min(b, n+1-a-b, NN-a-b)+1):
573
+ if not is_available(k,c):
574
+ continue
575
+
576
+ d = NN - (a + b + c) # necessarily 0 <= d <= n
577
+ if d == 0:
578
+ return thwart_lemma_3_5, (k,n,m,a,b,c,0,False)
579
+ elif (k+4 <= n+1 and
580
+ is_available(k, d ) and
581
+ is_available(k,m+3)):
582
+ return thwart_lemma_3_5, (k,n,m,a,b,c,d,False)
583
+
584
+ # 2. look for m,a,b,c,d with complement=True
585
+ # (we restrict to a >= b >= c)
586
+ for m in range(max(k-2,N/n-4), (N+n-1)/n):
587
+ if not (is_available(k,m+1) and
588
+ is_available(k,m+2) and
589
+ is_available(k,m+3)):
590
+ continue
591
+
592
+ NN = N - n*m
593
+ for a in range(max(0, (NN-n+2)/3), min(n, NN)+1):
594
+ # (NN-n+2)/3 <==> ceil((NN-n)/3)
595
+ if not is_available(k,a):
596
+ continue
597
+ na = n-a
598
+ for b in range(max(0, (NN-n-a+1)/2), min(a, NN-a)+1):
599
+ nb = n-b
600
+ if na+nb > n+1 or not is_available(k,b):
601
+ continue
602
+ for c in range(max(0, NN-n-a-b), min(b, NN-a-b)+1):
603
+ nc = n-c
604
+ if na+nb+nc > n+1 or not is_available(k,c):
605
+ continue
606
+
607
+ d = NN - (a + b + c) # necessarily d <= n
608
+ if d == 0:
609
+ return thwart_lemma_3_5, (k,n,m,a,b,c,0,True)
610
+ elif (k+4 <= n+1 and
611
+ is_available(k, d ) and
612
+ is_available(k,m+4)):
613
+ return thwart_lemma_3_5, (k,n,m,a,b,c,d,True)
614
+
615
+ return False
616
+
617
+ cpdef find_thwart_lemma_4_1(int k, int n):
618
+ r"""
619
+ Find a decomposition for Lemma 4.1 from [Thwarts]_.
620
+
621
+ INPUT:
622
+
623
+ - ``k``, ``n`` -- integers
624
+
625
+ .. SEEALSO::
626
+
627
+ :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.thwart_lemma_4_1`
628
+
629
+ OUTPUT:
630
+
631
+ A pair ``f,args`` such that ``f(*args)`` returns the requested OA.
632
+
633
+ EXAMPLES::
634
+
635
+ sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_thwart_lemma_4_1
636
+ sage: find_thwart_lemma_4_1(10,408)[1]
637
+ (10, 13, 28)
638
+ sage: find_thwart_lemma_4_1(10,50)
639
+ False
640
+ """
641
+ cdef int p,i,imax,nn,mm
642
+
643
+ # n = nn*mm+4(nn-2)
644
+ # <=> n+8 = nn(mm+4)
645
+ #
646
+ # nn is a prime power dividing n+8
647
+ for p,imax in smallInteger(n+8).factor():
648
+ nn = 1
649
+ for i in range(1,imax+1):
650
+ nn *= p
651
+ mm = (n+8)/nn-4
652
+ if (k+4 > nn+1 or
653
+ mm <= 1 or
654
+ nn % 3 == 2 or
655
+ not is_available(k,nn-2) or
656
+ not is_available(k,mm+1) or
657
+ not is_available(k,mm+3) or
658
+ not is_available(k,mm+4)):
659
+ continue
660
+
661
+ from sage.combinat.designs.orthogonal_arrays_build_recursive import thwart_lemma_4_1
662
+ return thwart_lemma_4_1,(k,nn,mm)
663
+
664
+ return False
665
+
666
+ cpdef find_three_factor_product(int k, int n):
667
+ r"""
668
+ Find `n_1n_2n_3=n` to obtain an `OA(k,n)` by the three-factor product from [DukesLing14]_.
669
+
670
+ INPUT:
671
+
672
+ - ``k``, ``n`` -- integers
673
+
674
+ .. SEEALSO::
675
+
676
+ :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.three_factor_product`
677
+
678
+ OUTPUT:
679
+
680
+ A pair ``f,args`` such that ``f(*args)`` returns the requested OA.
681
+
682
+ EXAMPLES::
683
+
684
+ sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_three_factor_product
685
+ sage: find_three_factor_product(10,648)[1]
686
+ (9, 8, 9, 9)
687
+ sage: find_three_factor_product(10,50)
688
+ False
689
+ """
690
+ cdef int n1,n2,n3
691
+
692
+ # we want to write n=n1*n2*n3 where n1<=n2<=n3 and we can build:
693
+ # - a OA(k-1,n1)
694
+ # - a OA( k ,n2)
695
+ # - a OA( k ,n3)
696
+ for n1 in smallInteger(n).divisors()[1:-1]:
697
+ if not is_available(k-1,n1):
698
+ continue
699
+ for n2 in smallInteger(n/n1).divisors():
700
+ n3 = n/n1/n2
701
+ if (n2<n1 or
702
+ n3<n2 or
703
+ not is_available(k,n2) or
704
+ not is_available(k,n3)):
705
+ continue
706
+ from sage.combinat.designs.orthogonal_arrays_build_recursive import three_factor_product
707
+ return three_factor_product,(k-1,n1,n2,n3)
708
+
709
+ return False
710
+
711
+ cpdef find_brouwer_separable_design(int k, int n):
712
+ r"""
713
+ Find `t(q^2+q+1)+x=n` to obtain an `OA(k,n)` by Brouwer's separable design construction.
714
+
715
+ INPUT:
716
+
717
+ - ``k``, ``n`` -- integers
718
+
719
+ The assumptions made on the parameters `t,q,x` are explained in the
720
+ documentation of
721
+ :func:`~sage.combinat.designs.orthogonal_arrays_build_recursive.brouwer_separable_design`.
722
+
723
+ EXAMPLES::
724
+
725
+ sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_brouwer_separable_design
726
+ sage: find_brouwer_separable_design(5,13)[1]
727
+ (5, 1, 3, 0)
728
+ sage: find_brouwer_separable_design(5,14)
729
+ False
730
+ """
731
+ from sage.combinat.designs.orthogonal_arrays_build_recursive import brouwer_separable_design
732
+ cdef int q, x, baer_subplane_size, max_t, min_t, t, e1, e2, e3, e4
733
+
734
+ for q in prime_powers(2, n):
735
+ baer_subplane_size = q**2 + q + 1
736
+ if baer_subplane_size > n:
737
+ break
738
+ # x <= q^2+1
739
+ # <=> n-t(q^2+q+1) <= q^2+1
740
+ # <=> n-q^2-1 <= t(q^2+q+1)
741
+ # <=> (n-q^2-1)/(q^2+q+1) <= t
742
+
743
+ min_t = (n - q**2 - 1) / baer_subplane_size
744
+ max_t = min(n / baer_subplane_size, q**2 - q + 1)
745
+
746
+ for t in range(min_t, max_t + 1):
747
+ x = n - t * baer_subplane_size
748
+ e1 = int(x != q**2 - q - t)
749
+ e2 = int(x != 1)
750
+ e3 = int(x != q**2)
751
+ e4 = int(x != t + q + 1)
752
+
753
+ # i)
754
+ if (x == 0 and
755
+ is_available(k, t) and is_available(k, t + q)):
756
+ return brouwer_separable_design, (k, t, q, x)
757
+
758
+ # ii)
759
+ elif (x == t + q and
760
+ is_available(k + e3, t) and
761
+ is_available(k, t + q) and
762
+ is_available(k + 1, t + q + 1)):
763
+ return brouwer_separable_design, (k, t, q, x)
764
+
765
+ # iii)
766
+ elif (x == q**2 - q + 1 - t and
767
+ is_available(k, x) and
768
+ is_available(k + e2, t + 1)
769
+ and is_available(k + 1, t + q)):
770
+ return brouwer_separable_design, (k, t, q, x)
771
+
772
+ # iv)
773
+ elif (x == q**2 + 1 and
774
+ is_available(k, x) and
775
+ is_available(k + e4, t + 1) and
776
+ is_available(k + 1, t + q + 1)):
777
+ return brouwer_separable_design, (k, t, q, x)
778
+
779
+ # v)
780
+ elif (0 < x < q**2 - q + 1 - t and (e1 or e2) and
781
+ is_available(k, x) and
782
+ is_available(k + e1, t) and
783
+ is_available(k + e2, t + 1) and
784
+ is_available(k + 1, t + q)):
785
+ return brouwer_separable_design, (k, t, q, x)
786
+
787
+ # vi)
788
+ elif (t + q < x < q**2 + 1 and (e3 or e4) and
789
+ is_available(k, x) and
790
+ is_available(k + e3, t) and
791
+ is_available(k + e4, t + 1) and
792
+ is_available(k + 1, t + q + 1)):
793
+ return brouwer_separable_design, (k, t, q, x)
794
+
795
+ return False
796
+
797
+ # Associates to n the list of k,x with x>1 such that there exists an
798
+ # OA(k,n+x)-OA(k,x). Useful in find_brouwer_separable_design
799
+ from sage.combinat.designs.database import QDM as __QDM
800
+ cdef dict _QDM = __QDM
801
+ cdef dict ioa_indexed_by_n_minus_x = {}
802
+ for x in _QDM.itervalues():
803
+ for (n, _, _, u), (k, _) in x.items():
804
+ if u > 1:
805
+ if n not in ioa_indexed_by_n_minus_x:
806
+ ioa_indexed_by_n_minus_x[n] = []
807
+ ioa_indexed_by_n_minus_x[n].append((k, u))
808
+
809
+
810
+ def int_as_sum(int value, list S, int k_max):
811
+ r"""
812
+ Return a tuple `(s_1, s_2, \ldots, s_k)` of less then `k_max` elements of `S` such
813
+ that `value = s_1 + s_2 + \ldots + s_k`. If there is no such tuples then the
814
+ function returns ``None``.
815
+
816
+ INPUT:
817
+
818
+ - ``value`` -- integer
819
+
820
+ - ``S`` -- list of integers
821
+
822
+ - ``k_max`` -- integer
823
+
824
+ EXAMPLES::
825
+
826
+ sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import int_as_sum
827
+ sage: D = int_as_sum(21,[5,12],100)
828
+ sage: for k in range(20,40):
829
+ ....: print("{} {}".format(k, int_as_sum(k,[5,12],100)))
830
+ 20 (5, 5, 5, 5)
831
+ 21 None
832
+ 22 (12, 5, 5)
833
+ 23 None
834
+ 24 (12, 12)
835
+ 25 (5, 5, 5, 5, 5)
836
+ 26 None
837
+ 27 (12, 5, 5, 5)
838
+ 28 None
839
+ 29 (12, 12, 5)
840
+ 30 (5, 5, 5, 5, 5, 5)
841
+ 31 None
842
+ 32 (12, 5, 5, 5, 5)
843
+ 33 None
844
+ 34 (12, 12, 5, 5)
845
+ 35 (5, 5, 5, 5, 5, 5, 5)
846
+ 36 (12, 12, 12)
847
+ 37 (12, 5, 5, 5, 5, 5)
848
+ 38 None
849
+ 39 (12, 12, 5, 5, 5)
850
+ """
851
+ cdef int i,j,v,vv,max_value
852
+ cdef dict D,new_D,last_D
853
+ last_D = D = {value:tuple()}
854
+ max_value = max(S)
855
+
856
+ if k_max * max_value < value:
857
+ return None
858
+
859
+ # The answer for a given k can be easily deduced from the answer
860
+ # for k-1. That's how we build the list, incrementally starting
861
+ # from k=0
862
+ for j in range(k-1,-1,-1):
863
+ new_D = {}
864
+ for i in S:
865
+ for v in last_D:
866
+ vv = v-i
867
+ if vv == 0:
868
+ return D[v] + (i,)
869
+ if (vv > 0 and # The new integer i is too big
870
+ vv <= j*max_value and # The new integer i is too small
871
+ vv not in D and # We had it in D already
872
+ vv not in new_D): # We had it in new_D already
873
+ new_D[vv] = D[v]+(i,)
874
+ if not new_D:
875
+ break
876
+ D.update(new_D)
877
+ last_D = new_D
878
+
879
+ return None
880
+
881
+
882
+ cpdef find_brouwer_van_rees_with_one_truncated_column(int k, int n):
883
+ r"""
884
+ Find `rm+x_1+...+x_c=n` such that the Brouwer-van Rees constructions yields a `OA(k,n)`.
885
+
886
+ Let `n=rm+\sum_{1\leq i\leq c}` such that `c\leq r`. The
887
+ generalization of Wilson's construction found by Brouwer and van
888
+ Rees (with one truncated column) ensures that an `OA(k,n)` exists
889
+ if the following designs exist: `OA(k+1,r)`, `OA(k,m)`,
890
+ `OA(k,\sum_{1\leq i\leq c} u_i)`, `OA(k,m+x_1)-OA(k,x_1)`, ...,
891
+ `OA(k,m+x_c)-OA(k,x_c)`.
892
+
893
+ For more information, see the documentation of
894
+ :func:`~sage.combinat.designs.orthogonal_arrays.wilson_construction`.
895
+
896
+ INPUT:
897
+
898
+ - ``k``, ``n`` -- integers
899
+
900
+ EXAMPLES::
901
+
902
+ sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_brouwer_van_rees_with_one_truncated_column
903
+ sage: find_brouwer_van_rees_with_one_truncated_column(5,53)[1]
904
+ (None, 5, 7, 7, [[(2, 1), (2, 1)]])
905
+ sage: find_brouwer_van_rees_with_one_truncated_column(6,96)[1]
906
+ (None, 6, 7, 13, [[(3, 1), (1, 1), (1, 1)]])
907
+ """
908
+ cdef list available_multipliers
909
+ cdef int kk,uu,r,m,remainder,max_multiplier
910
+ cdef tuple values
911
+
912
+ # We write n=rm+remainder
913
+ for m in range(2, n//2):
914
+ if not is_available(k,m):
915
+ continue
916
+
917
+ # List of x such that a OA(k,m+x)-OA(k,x) exists
918
+ #
919
+ # This is the list of integers that can be used as multipliers
920
+ # for the points of the truncated column
921
+ available_multipliers = []
922
+ if is_available(k,m+1):
923
+ available_multipliers.append(1)
924
+ for kk,uu in ioa_indexed_by_n_minus_x.get(m,[]):
925
+ if kk>=k:
926
+ available_multipliers.append(uu)
927
+
928
+ # We stop if there is no multiplier, or if 1 is the only
929
+ # multiplier (those cases are handled by other functions)
930
+ if (not available_multipliers or
931
+ (len(available_multipliers) == 1 and available_multipliers[0] == 1)):
932
+ continue
933
+
934
+ max_multiplier = max(available_multipliers)
935
+ for r in range(2, n//m+1):
936
+ remainder = n-r*m
937
+ if (remainder > r*max_multiplier or
938
+ not is_available(k+1,r) or
939
+ not is_available(k,remainder)):
940
+ continue
941
+
942
+ values = int_as_sum(remainder, available_multipliers, r)
943
+ if values is not None:
944
+ from sage.combinat.designs.orthogonal_arrays import wilson_construction
945
+ return (wilson_construction,
946
+ (None,k,r,m,[[(x,1) for x in values]]))
947
+
948
+ return False
949
+
950
+ from sage.combinat.designs.designs_pyx cimport _OA_cache, _OA_cache_size
951
+ cdef int is_available(int k, int n) except -1:
952
+ r"""
953
+ Return whether Sage can build an OA(k,n)
954
+
955
+ INPUT:
956
+
957
+ - ``k``, ``n`` -- integers
958
+ """
959
+ if n >= _OA_cache_size:
960
+ return orthogonal_array(k,n,existence=True) is True
961
+ if k <= _OA_cache[n].max_true:
962
+ return True
963
+ elif k >= _OA_cache[n].min_unknown:
964
+ return False
965
+ else:
966
+ return orthogonal_array(k,n,existence=True) is True