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.
- passagemath_graphs-10.6.1rc1.dist-info/METADATA +292 -0
- passagemath_graphs-10.6.1rc1.dist-info/RECORD +260 -0
- passagemath_graphs-10.6.1rc1.dist-info/WHEEL +5 -0
- passagemath_graphs-10.6.1rc1.dist-info/top_level.txt +2 -0
- passagemath_graphs.libs/libgcc_s-69c45f16.so.1 +0 -0
- passagemath_graphs.libs/libgmp-8e78bd9b.so.10.5.0 +0 -0
- passagemath_graphs.libs/libstdc++-1f1a71be.so.6.0.33 +0 -0
- sage/all__sagemath_graphs.py +39 -0
- sage/combinat/abstract_tree.py +2723 -0
- sage/combinat/all__sagemath_graphs.py +34 -0
- sage/combinat/binary_tree.py +5306 -0
- sage/combinat/cluster_algebra_quiver/all.py +22 -0
- sage/combinat/cluster_algebra_quiver/cluster_seed.py +5208 -0
- sage/combinat/cluster_algebra_quiver/interact.py +124 -0
- sage/combinat/cluster_algebra_quiver/mutation_class.py +625 -0
- sage/combinat/cluster_algebra_quiver/mutation_type.py +1555 -0
- sage/combinat/cluster_algebra_quiver/quiver.py +2290 -0
- sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py +2468 -0
- sage/combinat/designs/MOLS_handbook_data.py +570 -0
- sage/combinat/designs/all.py +58 -0
- sage/combinat/designs/bibd.py +1655 -0
- sage/combinat/designs/block_design.py +1071 -0
- sage/combinat/designs/covering_array.py +269 -0
- sage/combinat/designs/covering_design.py +530 -0
- sage/combinat/designs/database.py +5615 -0
- sage/combinat/designs/design_catalog.py +122 -0
- sage/combinat/designs/designs_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/designs_pyx.pxd +21 -0
- sage/combinat/designs/designs_pyx.pyx +993 -0
- sage/combinat/designs/difference_family.py +3951 -0
- sage/combinat/designs/difference_matrices.py +279 -0
- sage/combinat/designs/evenly_distributed_sets.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/evenly_distributed_sets.pyx +661 -0
- sage/combinat/designs/ext_rep.py +1064 -0
- sage/combinat/designs/gen_quadrangles_with_spread.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/gen_quadrangles_with_spread.pyx +339 -0
- sage/combinat/designs/group_divisible_designs.py +361 -0
- sage/combinat/designs/incidence_structures.py +2357 -0
- sage/combinat/designs/latin_squares.py +581 -0
- sage/combinat/designs/orthogonal_arrays.py +2244 -0
- sage/combinat/designs/orthogonal_arrays_build_recursive.py +1780 -0
- sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +967 -0
- sage/combinat/designs/resolvable_bibd.py +815 -0
- sage/combinat/designs/steiner_quadruple_systems.py +1306 -0
- sage/combinat/designs/subhypergraph_search.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/subhypergraph_search.pyx +530 -0
- sage/combinat/designs/twographs.py +306 -0
- sage/combinat/finite_state_machine.py +14874 -0
- sage/combinat/finite_state_machine_generators.py +2006 -0
- sage/combinat/graph_path.py +448 -0
- sage/combinat/interval_posets.py +3908 -0
- sage/combinat/nu_tamari_lattice.py +269 -0
- sage/combinat/ordered_tree.py +1446 -0
- sage/combinat/posets/all.py +46 -0
- sage/combinat/posets/bubble_shuffle.py +247 -0
- sage/combinat/posets/cartesian_product.py +493 -0
- sage/combinat/posets/d_complete.py +182 -0
- sage/combinat/posets/elements.py +273 -0
- sage/combinat/posets/forest.py +30 -0
- sage/combinat/posets/hasse_cython.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/posets/hasse_cython.pyx +174 -0
- sage/combinat/posets/hasse_diagram.py +3672 -0
- sage/combinat/posets/hochschild_lattice.py +158 -0
- sage/combinat/posets/incidence_algebras.py +794 -0
- sage/combinat/posets/lattices.py +5117 -0
- sage/combinat/posets/linear_extension_iterator.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/posets/linear_extension_iterator.pyx +292 -0
- sage/combinat/posets/linear_extensions.py +1037 -0
- sage/combinat/posets/mobile.py +275 -0
- sage/combinat/posets/moebius_algebra.py +776 -0
- sage/combinat/posets/poset_examples.py +2178 -0
- sage/combinat/posets/posets.py +9360 -0
- sage/combinat/rooted_tree.py +1070 -0
- sage/combinat/shard_order.py +239 -0
- sage/combinat/tamari_lattices.py +384 -0
- sage/combinat/yang_baxter_graph.py +923 -0
- sage/databases/all__sagemath_graphs.py +1 -0
- sage/databases/knotinfo_db.py +1231 -0
- sage/ext_data/all__sagemath_graphs.py +1 -0
- sage/ext_data/graphs/graph_plot_js.html +330 -0
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/graphs/all.py +42 -0
- sage/graphs/asteroidal_triples.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/asteroidal_triples.pyx +320 -0
- sage/graphs/base/all.py +1 -0
- sage/graphs/base/boost_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/boost_graph.pxd +106 -0
- sage/graphs/base/boost_graph.pyx +3045 -0
- sage/graphs/base/c_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/c_graph.pxd +106 -0
- sage/graphs/base/c_graph.pyx +5096 -0
- sage/graphs/base/dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/dense_graph.pxd +28 -0
- sage/graphs/base/dense_graph.pyx +801 -0
- sage/graphs/base/graph_backends.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/graph_backends.pxd +5 -0
- sage/graphs/base/graph_backends.pyx +797 -0
- sage/graphs/base/overview.py +85 -0
- sage/graphs/base/sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/sparse_graph.pxd +90 -0
- sage/graphs/base/sparse_graph.pyx +1653 -0
- sage/graphs/base/static_dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/static_dense_graph.pxd +5 -0
- sage/graphs/base/static_dense_graph.pyx +1032 -0
- sage/graphs/base/static_sparse_backend.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/static_sparse_backend.pxd +27 -0
- sage/graphs/base/static_sparse_backend.pyx +1583 -0
- sage/graphs/base/static_sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/static_sparse_graph.pxd +37 -0
- sage/graphs/base/static_sparse_graph.pyx +1375 -0
- sage/graphs/bipartite_graph.py +2732 -0
- sage/graphs/centrality.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/centrality.pyx +1038 -0
- sage/graphs/cographs.py +519 -0
- sage/graphs/comparability.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/comparability.pyx +851 -0
- sage/graphs/connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/connectivity.pxd +157 -0
- sage/graphs/connectivity.pyx +4813 -0
- sage/graphs/convexity_properties.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/convexity_properties.pxd +16 -0
- sage/graphs/convexity_properties.pyx +870 -0
- sage/graphs/digraph.py +4754 -0
- sage/graphs/digraph_generators.py +1993 -0
- sage/graphs/distances_all_pairs.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/distances_all_pairs.pxd +12 -0
- sage/graphs/distances_all_pairs.pyx +2938 -0
- sage/graphs/domination.py +1363 -0
- sage/graphs/dot2tex_utils.py +100 -0
- sage/graphs/edge_connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/edge_connectivity.pyx +1215 -0
- sage/graphs/generators/all.py +1 -0
- sage/graphs/generators/basic.py +1769 -0
- sage/graphs/generators/chessboard.py +538 -0
- sage/graphs/generators/classical_geometries.py +1611 -0
- sage/graphs/generators/degree_sequence.py +235 -0
- sage/graphs/generators/distance_regular.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/generators/distance_regular.pyx +2846 -0
- sage/graphs/generators/families.py +4759 -0
- sage/graphs/generators/intersection.py +565 -0
- sage/graphs/generators/platonic_solids.py +262 -0
- sage/graphs/generators/random.py +2623 -0
- sage/graphs/generators/smallgraphs.py +5741 -0
- sage/graphs/generators/world_map.py +724 -0
- sage/graphs/generic_graph.py +26867 -0
- sage/graphs/generic_graph_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/generic_graph_pyx.pxd +34 -0
- sage/graphs/generic_graph_pyx.pyx +1673 -0
- sage/graphs/genus.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/genus.pyx +622 -0
- sage/graphs/graph.py +9645 -0
- sage/graphs/graph_coloring.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_coloring.pyx +2284 -0
- sage/graphs/graph_database.py +1177 -0
- sage/graphs/graph_decompositions/all.py +1 -0
- sage/graphs/graph_decompositions/bandwidth.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/bandwidth.pyx +428 -0
- sage/graphs/graph_decompositions/clique_separators.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/clique_separators.pyx +616 -0
- sage/graphs/graph_decompositions/cutwidth.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/cutwidth.pyx +753 -0
- sage/graphs/graph_decompositions/fast_digraph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/fast_digraph.pxd +13 -0
- sage/graphs/graph_decompositions/fast_digraph.pyx +212 -0
- sage/graphs/graph_decompositions/graph_products.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/graph_products.pyx +508 -0
- sage/graphs/graph_decompositions/modular_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/modular_decomposition.pxd +27 -0
- sage/graphs/graph_decompositions/modular_decomposition.pyx +1536 -0
- sage/graphs/graph_decompositions/slice_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/slice_decomposition.pxd +18 -0
- sage/graphs/graph_decompositions/slice_decomposition.pyx +1106 -0
- sage/graphs/graph_decompositions/tree_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/tree_decomposition.pxd +17 -0
- sage/graphs/graph_decompositions/tree_decomposition.pyx +1996 -0
- sage/graphs/graph_decompositions/vertex_separation.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/vertex_separation.pxd +5 -0
- sage/graphs/graph_decompositions/vertex_separation.pyx +1963 -0
- sage/graphs/graph_editor.py +82 -0
- sage/graphs/graph_generators.py +3314 -0
- sage/graphs/graph_generators_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_generators_pyx.pyx +95 -0
- sage/graphs/graph_input.py +812 -0
- sage/graphs/graph_latex.py +2064 -0
- sage/graphs/graph_list.py +410 -0
- sage/graphs/graph_plot.py +1756 -0
- sage/graphs/graph_plot_js.py +338 -0
- sage/graphs/hyperbolicity.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/hyperbolicity.pyx +1704 -0
- sage/graphs/hypergraph_generators.py +364 -0
- sage/graphs/independent_sets.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/independent_sets.pxd +13 -0
- sage/graphs/independent_sets.pyx +402 -0
- sage/graphs/isgci.py +1033 -0
- sage/graphs/isoperimetric_inequalities.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/isoperimetric_inequalities.pyx +489 -0
- sage/graphs/line_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/line_graph.pyx +743 -0
- sage/graphs/lovasz_theta.py +77 -0
- sage/graphs/matching.py +1633 -0
- sage/graphs/matching_covered_graph.py +3590 -0
- sage/graphs/orientations.py +1489 -0
- sage/graphs/partial_cube.py +459 -0
- sage/graphs/path_enumeration.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/path_enumeration.pyx +2040 -0
- sage/graphs/pq_trees.py +1129 -0
- sage/graphs/print_graphs.py +201 -0
- sage/graphs/schnyder.py +865 -0
- sage/graphs/spanning_tree.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/spanning_tree.pyx +1457 -0
- sage/graphs/strongly_regular_db.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/strongly_regular_db.pyx +3340 -0
- sage/graphs/traversals.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/traversals.pxd +9 -0
- sage/graphs/traversals.pyx +1872 -0
- sage/graphs/trees.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/trees.pxd +15 -0
- sage/graphs/trees.pyx +310 -0
- sage/graphs/tutte_polynomial.py +713 -0
- sage/graphs/views.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/views.pyx +794 -0
- sage/graphs/weakly_chordal.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/weakly_chordal.pyx +604 -0
- sage/groups/all__sagemath_graphs.py +1 -0
- sage/groups/perm_gps/all__sagemath_graphs.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_graphs.py +1 -0
- sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_graphs.pxd +38 -0
- sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +1666 -0
- sage/knots/all.py +6 -0
- sage/knots/free_knotinfo_monoid.py +507 -0
- sage/knots/gauss_code.py +291 -0
- sage/knots/knot.py +682 -0
- sage/knots/knot_table.py +284 -0
- sage/knots/knotinfo.py +2900 -0
- sage/knots/link.py +4715 -0
- sage/sandpiles/all.py +13 -0
- sage/sandpiles/examples.py +225 -0
- sage/sandpiles/sandpile.py +6365 -0
- sage/topology/all.py +22 -0
- sage/topology/cell_complex.py +1214 -0
- sage/topology/cubical_complex.py +1976 -0
- sage/topology/delta_complex.py +1806 -0
- sage/topology/filtered_simplicial_complex.py +744 -0
- sage/topology/moment_angle_complex.py +823 -0
- sage/topology/simplicial_complex.py +5160 -0
- sage/topology/simplicial_complex_catalog.py +92 -0
- sage/topology/simplicial_complex_examples.py +1680 -0
- sage/topology/simplicial_complex_homset.py +205 -0
- sage/topology/simplicial_complex_morphism.py +836 -0
- sage/topology/simplicial_set.py +4102 -0
- sage/topology/simplicial_set_catalog.py +55 -0
- sage/topology/simplicial_set_constructions.py +2954 -0
- sage/topology/simplicial_set_examples.py +865 -0
- 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
|