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