From 7a566659011b142f2fa52957491a824ee54b41c5 Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 14 Feb 2024 14:12:45 -0500 Subject: [PATCH 1/8] Added methods to generate covering arrays and a main CA function to call them based on inputted paramters. Added methods include direct implementation of optimal arrays in the database of small combinatorial designs, methods that create a CA(N,t=2,k,v=2), for either k or N inputted and a recursive method that removes columns from a larger array. Added required documentation and reference for new methods. --- src/doc/en/reference/references/index.rst | 22 +- src/sage/combinat/designs/covering_array.py | 193 ++++++++- src/sage/combinat/designs/database.py | 450 +++++++++++++++++++- 3 files changed, 654 insertions(+), 11 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 7921aea3bf5..a8fec99e887 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -1780,8 +1780,8 @@ REFERENCES: With an appendix by Ernst Kani. Canad. Math. Bull. 48 (2005), no. 1, 16--31. -.. [Colb2004] C.J. Colbourn. “Combinatorial aspects of covering arrays”. - Matematiche (Catania) 59 (2004), pp. 125–172. +.. [Colb2004] C.J. Colbourn. *Combinatorial aspects of covering arrays*. + Matematiche (Catania) 59 (2004), pp. 125-172. .. [Col2004] Pierre Colmez, Invariant `\mathcal{L}` et derivees de valeurs propres de Frobenius, preprint, 2004. @@ -3686,6 +3686,10 @@ REFERENCES: .. [Kas2018] András Kaszanyitzky. *The GraftalLace Cellular Automata*. Preprint, :arxiv:`1805.11532`. +.. [Kat1973] G. Katona. *Two applications (for search theory and truth + functions) of Sperner type theorems*. Periodica Math., + 3:19-26, 1973. + .. [Kat1991] Nicholas M. Katz, *Exponential sums and differential equations*, Princeton University Press, Princeton NJ, 1991. @@ -3983,6 +3987,9 @@ REFERENCES: .. [KS] Sheldon Katz and Stein Arild Stromme, "Schubert", A Maple package for intersection theory and enumerative geometry. +.. [KS1973] D. Kleitman and J. Spencer. *Families of k-independent sets*. + Discrete Math, 6:255-262, 1973. + .. [KS1998] Maximilian Kreuzer and Harald Skarke, *Classification of Reflexive Polyhedra in Three Dimensions*, :arxiv:`hep-th/9805190` @@ -4985,6 +4992,9 @@ REFERENCES: :doi:`10.1007/s00453-006-1225-y`, http://www.cs.uoi.gr/~stavros/C-Papers/C-2004-SODA.pdf +.. [Nur2004] K. Nurmela. *Upper bounds for covering arrays by tabu search*. + Discrete Applied Math., 138 (2004), 143-152. + .. [NWS2002] Newman, M.E.J., Watts, D.J. and Strogatz, S.H. *Random graph models of social networks*. Proc. Nat. Acad. Sci. USA 99:1 (2002), 2566-2572. :doi:`10.1073/pnas.012582999` @@ -5729,8 +5739,8 @@ REFERENCES: .. [SloaHada] \N.J.A. Sloane's Library of Hadamard Matrices, at https://neilsloane.com/hadamard/ -.. [SMC2006] \G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, "Covering - arrays of higher strength from permutation vectors". J. Combin. +.. [SMC2006] \G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, *Covering + arrays of higher strength from permutation vectors*. J. Combin. Designs, 14 (2006) pp. 202-213. .. [SMMK2013] \T. Suzaki, K. Minematsu, S. Morioka, and E. Kobayashi, @@ -6414,8 +6424,8 @@ REFERENCES: .. [Wat2010] Watkins, David S. Fundamentals of Matrix Computations, Third Edition. Wiley, Hoboken, New Jersey, 2010. -.. [WC2007] \R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: - Constructions and Existence". J. Math. Crypt. 1 (2007), +.. [WC2007] \R.A. Walker II, and C.J. Colbourn, *Perfect Hash Families: + Constructions and Existence*. J. Math. Crypt. 1 (2007), pp.125-150 .. [Web2007] James Webb. *Game theory: decisions, interaction and diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index 1596c708152..c353944531b 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -16,12 +16,16 @@ .. csv-table:: :class: contentstable - :widths: 30, 70 + :widths: 50, 50 :delim: | :meth:`~sage.combinat.designs.designs_pyx.is_covering_array` | Check that an input list of lists is a `CA(N;t,k,v)`. - :meth:`~sage.combinat.designs.covering_array.CA_relabel` | Return a relabelled version of the CA. - :meth:`~sage.combinat.designs.covering_array.CA_standard_label` | Return a version of the CA relabelled to symbols `(0,\dots,n-1)`. + :meth:`~sage.combinat.designs.covering_array.CA_relabel` | Return a relabelled version of the `CA`. + :meth:`~sage.combinat.designs.covering_array.CA_standard_label` | Return a version of the `CA` relabelled to symbols `(0,\dots,n-1)`. + :meth:`~sage.combinat.designs.covering_array.truncate_columns` | Return an array with `k` columns from a larger one. + :meth:`~sage.combinat.designs.covering_array.Kleitman_Spencer_Katona` | Return a `CA(N; 2, k, 2)` using N as input. + :meth:`~sage.combinat.designs.covering_array.column_Kleitman_Spencer_Katona` | Return a `CA(N; 2, k, 2)` using k as input. + :meth:`~sage.combinat.designs.covering_array.covering_array` | Return a `CA` with given parameters. REFERENCES: @@ -50,3 +54,186 @@ from .orthogonal_arrays import OA_relabel, OA_standard_label CA_relabel = OA_relabel CA_standard_label = OA_standard_label + +def truncate_columns(array, k): + r""" + Return a covering array with `k` columns, obtained by removing excess + columns from a larger covering array. + + INPUT: + + - ``array`` -- the array to be truncated. + + - ``k`` -- the number of columns desired. Must be less than the + number of columns in ``array``. + + EXAMPLES:: + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: from sage.combinat.designs.covering_array import truncate_columns + sage: from sage.combinat.designs.database import ca_11_2_5_3 + sage: C = ca_11_2_5_3() + sage: D = truncate_columns(C,7) + Traceback (most recent call last): + ... + ValueError: array only has 5 columns + sage: E = truncate_columns(C,4) + sage: is_covering_array(E,parameters=True) + (True, (11, 2, 4, 3)) + + """ + oldk = len(array[0]) + + if oldk == k: + return array + + elif oldk < k: + raise ValueError("array only has {} columns".format(oldk)) + + else: + result = [] + for row in array: + result.append(row[:k]) + return result + +def Kleitman_Spencer_Katona(N): + r""" + Return a `CA(N; 2, k, 2)` where `k = \binom {N-1}{\lceil \frac{N}{2} \rceil}`. + + INPUT: + + - ``N`` -- the number of rows in the array, must be an integer greater + than 3 since any smaller would not produce enough columns for a + strength 2 array. + + This construction is referenced in [Colb2004]_ from [KS1973]_ and [Kat1973]_ + + **Construction** + + Take all distinct binary `N`-tuples of weight `\frac{N}{2}` that have a 0 + in the first position and place them as columns in an array. + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_array import Kleitman_Spencer_Katona + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: C = Kleitman_Spencer_Katona(2) + Traceback (most recent call last): + ... + ValueError: N must be greater than 3 + sage: C = Kleitman_Spencer_Katona(5) + sage: is_covering_array(C,parameters=True) + (True, (5, 2, 4, 2)) + + """ + from math import ceil + from itertools import combinations + + if N < 4: + raise ValueError("N must be greater than 3") + + result = [] + for p in combinations(range(N-1), ceil(N/2)): + S = [0]*N + for i in p: + S[i] = 1 + result.append(S) + return(list(map(list, zip(*result)))) + +def column_Kleitman_Spencer_Katona(k): + r""" + Return a covering array with `k` columns using the Kleitman Spencer Katona + method. + + See :func:`~sage.combinat.designs.covering_array.Kleitman_Spencer_Katona` + + INPUT: + + - ``k`` -- the number of columns in the array, must be an integer + greater than 3 since any smaller is a trivial array for strength 2. + + EXAMPLES:: + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: from sage.combinat.designs.covering_array import column_Kleitman_Spencer_Katona + sage: C = column_Kleitman_Spencer_Katona(20) + sage: is_covering_array(C,parameters=True) + (True, (8, 2, 20, 2)) + sage: column_Kleitman_Spencer_Katona(25000) + Traceback (most recent call last): + ... + AssertionError: not implemented for k > 24310 + + """ + assert k <= 24310, "not implemented for k > 24310" + + kdict = {3:4,4:5,10:6,15:7,35:8,56:9,126:10,210:11,462:12,792:13, + 1716:14,3003:15,6435:16,11440:17,24310:18} + + for ki in kdict: + if k <= ki: + N = kdict[ki] + break + return truncate_columns(Kleitman_Spencer_Katona(N), k) + +def covering_array(strength, number_columns, levels): + r""" + Build a `CA(N; t, k, v)` using direct constructions, where `N` is the + smallest size known. + + INPUT: + + - ``strength`` (integer) -- the parameter `t` of the covering array, + such that in any selection of `t` columns of the array, every `t` + -tuple appears at least once. + + - ``levels`` (integer) -- the parameter `v` which is the number of + unique symbols that appear in the covering array. + + - ``number_columns`` (integer) -- the number of columns desired for + the covering array. + + EXAMPLES:: + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: from sage.combinat.designs.covering_array import covering_array + sage: C1 = covering_array(2, 7, 3) + sage: is_covering_array(C1,parameters=True) + (True, (12, 2, 7, 3)) + sage: C2 = covering_array(2, 11, 2) + sage: is_covering_array(C2,parameters=True) + (True, (7, 2, 11, 2)) + sage: C3 = covering_array(2, 8, 7) + sage: is_covering_array(C3,parameters=True) + (True, (49, 2, 8, 7)) + sage: C4 = covering_array(3, 9, 3) + Traceback (most recent call last): + ... + ValueError: CAs and OAs only implemented for strength 2 + sage: C5 = covering_array(2, 50, 7) + No direct construction known and/or implemented for a CA(N; 2, 50, 7) + + """ + from sage.combinat.designs.orthogonal_arrays import orthogonal_array + + if strength != 2: + raise ValueError("CAs and OAs only implemented for strength 2") + + elif levels == 2: + return column_Kleitman_Spencer_Katona(number_columns) + + elif 3 <= levels <= 6: + import sage.combinat.designs.database as DB + for i in DB.CA_constructions[(strength, levels)]: + if number_columns <= i[1]: + CA = "ca_{}_{}_{}_{}".format(i[0], strength, i[1], levels) + f = getattr(DB, CA) + return truncate_columns(f(), number_columns) + + elif orthogonal_array(number_columns, levels, existence=True): + return orthogonal_array(number_columns, levels) + + else: + print("No direct construction known and/or implemented for a CA(N; {}, {}, {})".format( + strength, number_columns, levels)) + return \ No newline at end of file diff --git a/src/sage/combinat/designs/database.py b/src/sage/combinat/designs/database.py index 5eb2b90802a..1e87ebac538 100644 --- a/src/sage/combinat/designs/database.py +++ b/src/sage/combinat/designs/database.py @@ -12,6 +12,8 @@ This module implements: +- {LIST_OF_CA_CONSTRUCTIONS} + - {LIST_OF_OA_CONSTRUCTIONS} - {LIST_OF_MOLS_CONSTRUCTIONS} @@ -5033,6 +5035,449 @@ def BIBD_56_11_2(): k, ', '.join('`{}`'.format(q) for q in sorted(EDS[k]) if EDS[k][q] is not False)) for k in sorted(EDS)) +def ca_11_2_5_3(): + r""" + Return a CA with the given parameters, This CA is proven to be optimal. + + Data obtained from https://zenodo.org/records/1476059 + + EXAMPLES:: + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: from sage.combinat.designs.database import ca_11_2_5_3 + sage: C = ca_11_2_5_3() + sage: is_covering_array(C,2,3) + True + + """ + return [[0, 0, 1, 0, 1], + [0, 0, 2, 1, 0], + [0, 1, 0, 1, 2], + [0, 2, 1, 2, 2], + [1, 0, 0, 2, 1], + [1, 1, 1, 2, 0], + [1, 1, 2, 0, 2], + [1, 2, 2, 1, 1], + [2, 0, 2, 2, 2], + [2, 1, 1, 1, 1], + [2, 2, 0, 0, 0]] + +def ca_12_2_7_3(): + r""" + Return a CA with the given parameters, This CA is proven to be optimal. + + Data obtained from https://zenodo.org/records/1476059 + + EXAMPLES:: + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: from sage.combinat.designs.database import ca_12_2_7_3 + sage: C = ca_12_2_7_3() + sage: is_covering_array(C,2,3) + True + + """ + return [[0, 0, 0, 2, 2, 0, 0], + [0, 0, 2, 1, 1, 1, 1], + [0, 1, 0, 0, 0, 1, 2], + [0, 2, 1, 2, 0, 2, 1], + [1, 0, 2, 0, 0, 2, 0], + [1, 1, 1, 1, 2, 0, 1], + [1, 1, 1, 2, 1, 1, 0], + [1, 2, 0, 1, 1, 2, 2], + [2, 0, 1, 0, 1, 0, 2], + [2, 1, 2, 2, 2, 2, 2], + [2, 2, 0, 0, 2, 1, 1], + [2, 2, 2, 1, 0, 0, 0]] + +def ca_13_2_9_3(): + r""" + Return a CA with the given parameters, This CA is proven to be optimal. + + Data obtained from https://zenodo.org/records/1476059 + + EXAMPLES:: + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: from sage.combinat.designs.database import ca_13_2_9_3 + sage: C = ca_13_2_9_3() + sage: is_covering_array(C,2,3) + True + + """ + return [[0, 0, 0, 2, 0, 2, 2, 2, 0], + [0, 0, 2, 0, 1, 1, 1, 2, 1], + [0, 1, 1, 1, 2, 0, 1, 2, 0], + [0, 1, 2, 1, 0, 1, 2, 0, 2], + [0, 2, 2, 2, 2, 1, 0, 1, 0], + [1, 0, 1, 0, 2, 1, 2, 0, 0], + [1, 0, 2, 1, 2, 2, 0, 2, 2], + [1, 1, 0, 0, 0, 0, 0, 1, 1], + [1, 2, 0, 2, 1, 0, 1, 0, 2], + [2, 0, 2, 1, 1, 0, 2, 1, 0], + [2, 1, 1, 2, 1, 2, 0, 0, 1], + [2, 2, 0, 1, 2, 1, 2, 2, 1], + [2, 2, 1, 0, 0, 2, 1, 1, 2]] + +def ca_14_2_10_3(): + r""" + Return a CA with the given parameters, This CA is proven to be optimal. + + Data obtained from https://zenodo.org/records/1476059 + + EXAMPLES:: + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: from sage.combinat.designs.database import ca_14_2_10_3 + sage: C = ca_14_2_10_3() + sage: is_covering_array(C,2,3) + True + + """ + return [[0, 0, 0, 0, 2, 2, 2, 1, 1, 0], + [0, 0, 0, 2, 1, 0, 0, 2, 1, 1], + [0, 0, 1, 1, 1, 2, 1, 0, 2, 2], + [0, 1, 0, 2, 0, 1, 2, 0, 1, 2], + [0, 2, 2, 2, 1, 2, 2, 1, 0, 0], + [1, 0, 2, 1, 0, 1, 1, 1, 1, 1], + [1, 1, 1, 2, 1, 1, 1, 2, 2, 0], + [1, 1, 2, 0, 0, 2, 2, 2, 2, 1], + [1, 1, 2, 1, 0, 0, 0, 0, 0, 0], + [1, 2, 0, 1, 2, 0, 1, 2, 2, 2], + [2, 0, 0, 0, 1, 0, 1, 2, 0, 2], + [2, 1, 2, 2, 2, 2, 0, 1, 2, 2], + [2, 2, 1, 0, 2, 1, 0, 0, 0, 1], + [2, 2, 1, 1, 0, 0, 2, 1, 1, 0]] + +def ca_15_2_20_3(): + r""" + Return a CA with the given parameters, This CA is proven to be optimal. + + Data obtained from [Nur2004]_ + + EXAMPLES:: + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: from sage.combinat.designs.database import ca_15_2_20_3 + sage: C = ca_15_2_20_3() + sage: is_covering_array(C,2,3) + True + + """ + return [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [0, 0, 0, 0, 0, 1, 1, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], + [0, 1, 1, 1, 1, 0, 1, 2, 2, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2], + [0, 2, 2, 2, 2, 2, 2, 0, 1, 0, 0, 0, 0, 1, 2, 2, 0, 1, 1, 1], + [1, 0, 1, 1, 1, 2, 2, 0, 1, 0, 1, 1, 2, 0, 0, 1, 1, 0, 1, 2], + [1, 1, 2, 2, 2, 1, 0, 1, 0, 2, 1, 1, 0, 0, 2, 1, 2, 2, 1, 0], + [1, 2, 0, 1, 2, 0, 2, 1, 0, 2, 0, 2, 2, 1, 0, 2, 1, 0, 2, 1], + [1, 2, 1, 0, 2, 2, 1, 2, 0, 1, 2, 1, 1, 0, 1, 2, 0, 2, 0, 1], + [1, 2, 1, 2, 0, 2, 1, 1, 2, 2, 1, 0, 1, 2, 0, 0, 2, 1, 0, 0], + [2, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 2, 0, 2, 2, 0, 1, 0, 1, 2], + [2, 1, 0, 2, 1, 2, 0, 2, 2, 2, 1, 2, 2, 0, 1, 2, 0, 1, 2, 0], + [2, 1, 2, 0, 1, 1, 2, 0, 2, 1, 0, 1, 1, 2, 1, 0, 2, 0, 2, 1], + [2, 1, 2, 1, 0, 1, 2, 2, 1, 1, 2, 0, 2, 1, 0, 0, 1, 2, 0, 0], + [2, 2, 1, 1, 1, 1, 0, 1, 0, 0, 2, 2, 1, 2, 2, 1, 0, 1, 0, 2]] + +def ca_19_2_6_4(): + r""" + Return a CA with the given parameters, This CA is proven to be optimal. + + Data obtained from https://zenodo.org/records/1476059 + + EXAMPLES:: + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: from sage.combinat.designs.database import ca_19_2_6_4 + sage: C = ca_19_2_6_4() + sage: is_covering_array(C,2,4) + True + + """ + return [[0, 0, 0, 2, 0, 0], + [0, 0, 1, 0, 1, 1], + [0, 1, 3, 1, 2, 1], + [0, 2, 2, 3, 0, 2], + [0, 3, 3, 2, 3, 3], + [1, 0, 3, 1, 1, 2], + [1, 1, 0, 3, 1, 3], + [1, 1, 2, 0, 3, 0], + [1, 2, 1, 2, 2, 0], + [1, 3, 1, 3, 0, 1], + [2, 0, 2, 3, 2, 3], + [2, 1, 1, 2, 3, 2], + [2, 2, 0, 1, 3, 1], + [2, 2, 3, 0, 0, 3], + [2, 3, 2, 1, 1, 0], + [3, 0, 3, 3, 3, 0], + [3, 1, 1, 1, 0, 3], + [3, 2, 2, 2, 1, 1], + [3, 3, 0, 0, 2, 2]] + +def ca_21_2_7_4(): + r""" + Return a CA with the given parameters, This CA is proven to be optimal. + This CA is also uniform. + + Data obtained from https://zenodo.org/records/1476059 + + EXAMPLES:: + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: from sage.combinat.designs.database import ca_21_2_7_4 + sage: C = ca_21_2_7_4() + sage: is_covering_array(C,2,4) + True + + """ + return [[0, 0, 1, 0, 0, 0, 0], + [0, 0, 3, 1, 1, 1, 1], + [0, 1, 1, 2, 2, 2, 2], + [0, 1, 2, 3, 0, 1, 3], + [0, 2, 0, 3, 3, 0, 2], + [0, 3, 1, 3, 3, 3, 1], + [1, 0, 0, 3, 2, 3, 3], + [1, 1, 3, 1, 3, 3, 0], + [1, 2, 1, 2, 1, 0, 3], + [1, 2, 3, 2, 0, 2, 1], + [1, 3, 2, 0, 1, 1, 2], + [2, 0, 3, 0, 3, 2, 3], + [2, 1, 2, 1, 2, 0, 1], + [2, 2, 1, 1, 0, 3, 2], + [2, 2, 2, 3, 1, 2, 0], + [2, 3, 0, 2, 3, 1, 0], + [3, 0, 2, 2, 3, 3, 2], + [3, 1, 0, 0, 1, 3, 1], + [3, 2, 1, 0, 2, 1, 0], + [3, 3, 0, 1, 0, 2, 3], + [3, 3, 3, 3, 2, 0, 2]] + +def ca_29_2_7_5(): + r""" + Return a CA with the given parameters, This CA is proven to be optimal. + + Data obtained from https://zenodo.org/records/1476059 + + EXAMPLES:: + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: from sage.combinat.designs.database import ca_29_2_7_5 + sage: C = ca_29_2_7_5() + sage: is_covering_array(C,2,5) + True + + """ + return [[0, 2, 2, 3, 0, 0, 0], + [1, 4, 3, 4, 2, 3, 0], + [2, 3, 0, 0, 4, 2, 0], + [3, 0, 1, 2, 3, 4, 0], + [4, 1, 4, 1, 1, 1, 0], + [0, 0, 2, 4, 1, 2, 1], + [1, 2, 4, 0, 2, 4, 1], + [1, 3, 1, 2, 1, 0, 1], + [2, 1, 2, 2, 4, 3, 1], + [3, 3, 3, 1, 0, 1, 1], + [4, 4, 0, 3, 3, 0, 1], + [0, 1, 3, 0, 3, 0, 2], + [1, 0, 3, 3, 4, 1, 2], + [2, 2, 1, 4, 3, 1, 2], + [2, 4, 4, 2, 0, 2, 2], + [3, 2, 0, 1, 1, 3, 2], + [4, 3, 2, 4, 2, 4, 2], + [0, 3, 4, 3, 3, 3, 3], + [1, 1, 0, 4, 0, 4, 3], + [2, 0, 4, 1, 2, 0, 3], + [3, 1, 1, 3, 2, 2, 3], + [3, 4, 2, 0, 1, 1, 3], + [4, 2, 3, 2, 4, 2, 3], + [0, 0, 0, 2, 2, 1, 4], + [0, 4, 1, 1, 4, 4, 4], + [1, 1, 2, 1, 3, 2, 4], + [2, 2, 3, 3, 1, 4, 4], + [3, 3, 4, 4, 4, 0, 4], + [4, 0, 1, 0, 0, 3, 4]] + +def ca_37_2_4_6(): + r""" + Return a CA with the given parameters, This CA is proven to be optimal. + + Data obtained from https://zenodo.org/records/1476059 + + EXAMPLES:: + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: from sage.combinat.designs.database import ca_37_2_4_6 + sage: C = ca_37_2_4_6() + sage: is_covering_array(C,2,6) + True + + """ + return [[0, 0, 1, 0], + [0, 0, 2, 1], + [0, 1, 0, 2], + [0, 2, 0, 5], + [0, 3, 3, 3], + [0, 4, 4, 4], + [0, 5, 5, 5], + [1, 0, 0, 4], + [1, 1, 1, 5], + [1, 2, 3, 1], + [1, 3, 4, 0], + [1, 4, 5, 3], + [1, 5, 2, 2], + [2, 0, 0, 3], + [2, 1, 4, 1], + [2, 2, 5, 4], + [2, 3, 1, 2], + [2, 4, 2, 5], + [2, 5, 3, 0], + [3, 0, 5, 2], + [3, 1, 3, 4], + [3, 2, 2, 0], + [3, 3, 0, 5], + [3, 4, 1, 1], + [3, 5, 4, 3], + [4, 0, 3, 5], + [4, 1, 2, 3], + [4, 2, 4, 2], + [4, 3, 5, 1], + [4, 4, 0, 0], + [4, 5, 1, 4], + [5, 0, 4, 5], + [5, 1, 5, 0], + [5, 2, 1, 3], + [5, 3, 2, 4], + [5, 4, 3, 2], + [5, 5, 0, 1]] + +def ca_39_2_5_6(): + r""" + Return a CA with the given parameters, This CA is proven to be optimal. + + Data obtained from https://zenodo.org/records/1476059 + + EXAMPLES:: + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: from sage.combinat.designs.database import ca_39_2_5_6 + sage: C = ca_39_2_5_6() + sage: is_covering_array(C,2,6) + True + + """ + return [[0, 0, 1, 1, 0], + [1, 5, 2, 2, 0], + [2, 4, 5, 4, 0], + [3, 2, 0, 3, 0], + [4, 3, 4, 5, 0], + [5, 1, 3, 0, 0], + [0, 4, 4, 3, 1], + [1, 3, 5, 0, 1], + [2, 2, 1, 2, 1], + [3, 0, 3, 5, 1], + [4, 1, 2, 1, 1], + [5, 5, 0, 4, 1], + [0, 5, 5, 5, 2], + [1, 1, 1, 3, 2], + [2, 3, 0, 1, 2], + [3, 4, 2, 0, 2], + [4, 2, 3, 4, 2], + [5, 0, 4, 2, 2], + [0, 1, 0, 4, 3], + [0, 3, 3, 2, 3], + [1, 0, 2, 4, 3], + [2, 2, 4, 0, 3], + [3, 5, 4, 1, 3], + [4, 0, 5, 3, 3], + [5, 4, 1, 5, 3], + [0, 0, 0, 0, 4], + [1, 2, 0, 5, 4], + [1, 4, 3, 1, 4], + [2, 1, 4, 4, 4], + [3, 1, 5, 2, 4], + [4, 5, 1, 0, 4], + [5, 3, 2, 3, 4], + [0, 2, 2, 0, 5], + [1, 1, 4, 5, 5], + [2, 0, 2, 5, 5], + [2, 5, 3, 3, 5], + [3, 3, 1, 4, 5], + [4, 4, 0, 2, 5], + [5, 2, 5, 1, 5]] + +def ca_41_2_6_6(): + r""" + Return a CA with the given parameters, This CA is proven to be optimal. + This CA is also uniform. + + Data obtained from https://zenodo.org/records/1476059 + + EXAMPLES:: + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: from sage.combinat.designs.database import ca_41_2_6_6 + sage: C = ca_41_2_6_6() + sage: is_covering_array(C,2,6) + True + + """ + return [[0, 0, 0, 0, 0, 0], + [1, 1, 4, 5, 4, 0], + [2, 3, 3, 5, 2, 0], + [3, 0, 2, 3, 3, 0], + [3, 5, 5, 2, 1, 0], + [4, 2, 1, 4, 5, 0], + [5, 4, 4, 1, 1, 0], + [0, 0, 1, 1, 1, 1], + [1, 2, 5, 1, 2, 1], + [2, 4, 4, 3, 5, 1], + [2, 5, 2, 4, 0, 1], + [3, 1, 3, 0, 4, 1], + [4, 4, 0, 5, 3, 1], + [5, 3, 1, 2, 0, 1], + [0, 1, 2, 2, 2, 2], + [1, 3, 1, 3, 4, 2], + [1, 5, 4, 0, 3, 2], + [2, 0, 5, 5, 1, 2], + [3, 3, 0, 1, 5, 2], + [4, 4, 3, 2, 0, 2], + [5, 2, 3, 4, 3, 2], + [0, 2, 3, 3, 1, 3], + [0, 5, 1, 5, 5, 3], + [1, 4, 2, 1, 0, 3], + [2, 2, 0, 2, 4, 3], + [3, 3, 5, 4, 3, 3], + [4, 0, 4, 4, 2, 3], + [5, 1, 5, 0, 5, 3], + [0, 3, 4, 2, 3, 4], + [1, 1, 0, 4, 1, 4], + [2, 2, 2, 0, 5, 4], + [3, 4, 1, 0, 2, 4], + [4, 1, 5, 3, 0, 4], + [4, 5, 3, 1, 4, 4], + [5, 0, 2, 5, 4, 4], + [0, 4, 5, 4, 4, 5], + [1, 0, 3, 2, 5, 5], + [2, 1, 1, 1, 3, 5], + [3, 2, 4, 5, 0, 5], + [4, 3, 2, 0, 1, 5], + [5, 5, 0, 3, 2, 5]] + +# Make dictionary with keys (t, v) and values (N, k) which are the +# smallest N and largest k such that a CA(N; t, k, v) can be made using +# the database. +CA_constructions = { + (2,3) : ((11,5), (12,7), (13,9), (14,10), (15,20)), + (2,4) : ((19,6), (21,7)), + (2,5) : ((29,7),), + (2,6) : ((37,4), (39,5), (41,6)) +} + +# Add this data to the module's doc. +LIST_OF_CA_CONSTRUCTIONS = ", ".join(":func:`CA({},{},{},{}) `".format(N,t,k,v,N,t,k,v) + for (t,v) in CA_constructions for (N,k) in CA_constructions[(t,v)]) + __doc__ = __doc__.format( LIST_OF_OA_CONSTRUCTIONS=LIST_OF_OA_CONSTRUCTIONS, LIST_OF_MOLS_CONSTRUCTIONS=LIST_OF_MOLS_CONSTRUCTIONS, @@ -5041,6 +5486,7 @@ def BIBD_56_11_2(): LIST_OF_DF=LIST_OF_DF, LIST_OF_DM=LIST_OF_DM, LIST_OF_QDM=LIST_OF_QDM, - LIST_OF_EDS=LIST_OF_EDS) -del LIST_OF_OA_CONSTRUCTIONS, LIST_OF_MOLS_CONSTRUCTIONS, LIST_OF_VMT_VECTORS,LIST_OF_DF, LIST_OF_DM, LIST_OF_QDM, LIST_OF_EDS, LIST_OF_BIBD + LIST_OF_EDS=LIST_OF_EDS, + LIST_OF_CA_CONSTRUCTIONS=LIST_OF_CA_CONSTRUCTIONS) +del LIST_OF_OA_CONSTRUCTIONS, LIST_OF_MOLS_CONSTRUCTIONS, LIST_OF_VMT_VECTORS,LIST_OF_DF, LIST_OF_DM, LIST_OF_QDM, LIST_OF_EDS, LIST_OF_BIBD, LIST_OF_CA_CONSTRUCTIONS del PolynomialRing, ZZ, a, From 231b4c765955bef13b5b241380395bc64bbf075c Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 16 Feb 2024 10:59:39 -0500 Subject: [PATCH 2/8] Fixed formatting issues --- src/sage/combinat/designs/covering_array.py | 4 ++++ src/sage/combinat/designs/database.py | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index c353944531b..a41d1f4d68b 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -55,6 +55,7 @@ CA_relabel = OA_relabel CA_standard_label = OA_standard_label + def truncate_columns(array, k): r""" Return a covering array with `k` columns, obtained by removing excess @@ -96,6 +97,7 @@ def truncate_columns(array, k): result.append(row[:k]) return result + def Kleitman_Spencer_Katona(N): r""" Return a `CA(N; 2, k, 2)` where `k = \binom {N-1}{\lceil \frac{N}{2} \rceil}`. @@ -140,6 +142,7 @@ def Kleitman_Spencer_Katona(N): result.append(S) return(list(map(list, zip(*result)))) + def column_Kleitman_Spencer_Katona(k): r""" Return a covering array with `k` columns using the Kleitman Spencer Katona @@ -176,6 +179,7 @@ def column_Kleitman_Spencer_Katona(k): break return truncate_columns(Kleitman_Spencer_Katona(N), k) + def covering_array(strength, number_columns, levels): r""" Build a `CA(N; t, k, v)` using direct constructions, where `N` is the diff --git a/src/sage/combinat/designs/database.py b/src/sage/combinat/designs/database.py index 1e87ebac538..7f15c84861c 100644 --- a/src/sage/combinat/designs/database.py +++ b/src/sage/combinat/designs/database.py @@ -5035,6 +5035,7 @@ def BIBD_56_11_2(): k, ', '.join('`{}`'.format(q) for q in sorted(EDS[k]) if EDS[k][q] is not False)) for k in sorted(EDS)) + def ca_11_2_5_3(): r""" Return a CA with the given parameters, This CA is proven to be optimal. @@ -5062,6 +5063,7 @@ def ca_11_2_5_3(): [2, 1, 1, 1, 1], [2, 2, 0, 0, 0]] + def ca_12_2_7_3(): r""" Return a CA with the given parameters, This CA is proven to be optimal. @@ -5090,6 +5092,7 @@ def ca_12_2_7_3(): [2, 2, 0, 0, 2, 1, 1], [2, 2, 2, 1, 0, 0, 0]] + def ca_13_2_9_3(): r""" Return a CA with the given parameters, This CA is proven to be optimal. @@ -5119,6 +5122,7 @@ def ca_13_2_9_3(): [2, 2, 0, 1, 2, 1, 2, 2, 1], [2, 2, 1, 0, 0, 2, 1, 1, 2]] + def ca_14_2_10_3(): r""" Return a CA with the given parameters, This CA is proven to be optimal. @@ -5149,6 +5153,7 @@ def ca_14_2_10_3(): [2, 2, 1, 0, 2, 1, 0, 0, 0, 1], [2, 2, 1, 1, 0, 0, 2, 1, 1, 0]] + def ca_15_2_20_3(): r""" Return a CA with the given parameters, This CA is proven to be optimal. @@ -5180,6 +5185,7 @@ def ca_15_2_20_3(): [2, 1, 2, 1, 0, 1, 2, 2, 1, 1, 2, 0, 2, 1, 0, 0, 1, 2, 0, 0], [2, 2, 1, 1, 1, 1, 0, 1, 0, 0, 2, 2, 1, 2, 2, 1, 0, 1, 0, 2]] + def ca_19_2_6_4(): r""" Return a CA with the given parameters, This CA is proven to be optimal. @@ -5215,6 +5221,7 @@ def ca_19_2_6_4(): [3, 2, 2, 2, 1, 1], [3, 3, 0, 0, 2, 2]] + def ca_21_2_7_4(): r""" Return a CA with the given parameters, This CA is proven to be optimal. @@ -5253,6 +5260,7 @@ def ca_21_2_7_4(): [3, 3, 0, 1, 0, 2, 3], [3, 3, 3, 3, 2, 0, 2]] + def ca_29_2_7_5(): r""" Return a CA with the given parameters, This CA is proven to be optimal. @@ -5298,6 +5306,7 @@ def ca_29_2_7_5(): [3, 3, 4, 4, 4, 0, 4], [4, 0, 1, 0, 0, 3, 4]] + def ca_37_2_4_6(): r""" Return a CA with the given parameters, This CA is proven to be optimal. @@ -5351,6 +5360,7 @@ def ca_37_2_4_6(): [5, 4, 3, 2], [5, 5, 0, 1]] + def ca_39_2_5_6(): r""" Return a CA with the given parameters, This CA is proven to be optimal. @@ -5406,6 +5416,7 @@ def ca_39_2_5_6(): [4, 4, 0, 2, 5], [5, 2, 5, 1, 5]] + def ca_41_2_6_6(): r""" Return a CA with the given parameters, This CA is proven to be optimal. @@ -5464,6 +5475,7 @@ def ca_41_2_6_6(): [4, 3, 2, 0, 1, 5], [5, 5, 0, 3, 2, 5]] + # Make dictionary with keys (t, v) and values (N, k) which are the # smallest N and largest k such that a CA(N; t, k, v) can be made using # the database. @@ -5478,6 +5490,7 @@ def ca_41_2_6_6(): LIST_OF_CA_CONSTRUCTIONS = ", ".join(":func:`CA({},{},{},{}) `".format(N,t,k,v,N,t,k,v) for (t,v) in CA_constructions for (N,k) in CA_constructions[(t,v)]) + __doc__ = __doc__.format( LIST_OF_OA_CONSTRUCTIONS=LIST_OF_OA_CONSTRUCTIONS, LIST_OF_MOLS_CONSTRUCTIONS=LIST_OF_MOLS_CONSTRUCTIONS, From eb849d5e6b7e78f4615a6f622261b031dc435fc3 Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 16 Feb 2024 11:05:03 -0500 Subject: [PATCH 3/8] Formatting issues part 2 --- src/sage/combinat/designs/covering_array.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index a41d1f4d68b..045965f9b77 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -240,4 +240,4 @@ def covering_array(strength, number_columns, levels): else: print("No direct construction known and/or implemented for a CA(N; {}, {}, {})".format( strength, number_columns, levels)) - return \ No newline at end of file + return From 327eaf5595f39b63949ae75030400eab7d8a93ba Mon Sep 17 00:00:00 2001 From: Aaron Date: Tue, 11 Jun 2024 20:04:00 -0400 Subject: [PATCH 4/8] Added an in_database function, it now allows to check the database more generally so it does not need to be changed if things are added. Also edited some functions to produce the same output more efficiently. Fixed some formatting and punctuation errors. --- src/sage/combinat/designs/covering_array.py | 109 ++++++++++++-------- src/sage/combinat/designs/database.py | 22 ++-- 2 files changed, 79 insertions(+), 52 deletions(-) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index 045965f9b77..0f5e4edf470 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -25,6 +25,7 @@ :meth:`~sage.combinat.designs.covering_array.truncate_columns` | Return an array with `k` columns from a larger one. :meth:`~sage.combinat.designs.covering_array.Kleitman_Spencer_Katona` | Return a `CA(N; 2, k, 2)` using N as input. :meth:`~sage.combinat.designs.covering_array.column_Kleitman_Spencer_Katona` | Return a `CA(N; 2, k, 2)` using k as input. + :meth:`~sage.combinat.designs.covering_array.database_check` | Check if CA can be made from the database of combinatorial designs. :meth:`~sage.combinat.designs.covering_array.covering_array` | Return a `CA` with given parameters. REFERENCES: @@ -92,15 +93,12 @@ def truncate_columns(array, k): raise ValueError("array only has {} columns".format(oldk)) else: - result = [] - for row in array: - result.append(row[:k]) - return result + return [row[:k] for row in array] def Kleitman_Spencer_Katona(N): r""" - Return a `CA(N; 2, k, 2)` where `k = \binom {N-1}{\lceil \frac{N}{2} \rceil}`. + Return a `CA(N; 2, k, 2)` where `k = \binom {N-1}{\lceil N/2 \rceil}`. INPUT: @@ -112,7 +110,7 @@ def Kleitman_Spencer_Katona(N): **Construction** - Take all distinct binary `N`-tuples of weight `\frac{N}{2}` that have a 0 + Take all distinct binary `N`-tuples of weight `N/2` that have a 0 in the first position and place them as columns in an array. EXAMPLES:: @@ -128,24 +126,23 @@ def Kleitman_Spencer_Katona(N): (True, (5, 2, 4, 2)) """ - from math import ceil from itertools import combinations - + from sage.arith.misc import integer_ceil if N < 4: raise ValueError("N must be greater than 3") - result = [] - for p in combinations(range(N-1), ceil(N/2)): + col_list = [] + for p in combinations(range(N-1), integer_ceil(N/2)): S = [0]*N for i in p: S[i] = 1 - result.append(S) - return(list(map(list, zip(*result)))) + col_list.append(S) + return [[col_list[j][i] for j in range(len(col_list))] for i in range(N)] def column_Kleitman_Spencer_Katona(k): r""" - Return a covering array with `k` columns using the Kleitman Spencer Katona + Return a covering array with `k` columns using the Kleitman-Spencer-Katona method. See :func:`~sage.combinat.designs.covering_array.Kleitman_Spencer_Katona` @@ -165,19 +162,60 @@ def column_Kleitman_Spencer_Katona(k): sage: column_Kleitman_Spencer_Katona(25000) Traceback (most recent call last): ... - AssertionError: not implemented for k > 24310 + ValueError: not implemented for k > 24310 """ - assert k <= 24310, "not implemented for k > 24310" + kdict = [(3, 4), (4, 5), (10, 6), (15, 7), (35, 8), (56, 9), + (126, 10), (210, 11), (462, 12), (792, 13), (1716, 14), + (3003, 15), (6435, 16), (11440, 17), (24310, 18)] - kdict = {3:4,4:5,10:6,15:7,35:8,56:9,126:10,210:11,462:12,792:13, - 1716:14,3003:15,6435:16,11440:17,24310:18} + if k > kdict[-1][0]: + raise ValueError("not implemented for k > {}".format(kdict[-1][0])) - for ki in kdict: + for (ki, N) in kdict: if k <= ki: - N = kdict[ki] - break - return truncate_columns(Kleitman_Spencer_Katona(N), k) + return truncate_columns(Kleitman_Spencer_Katona(N), k) + + +def database_check(number_columns, strength, levels): + r""" + Check if the database can be used to build a CA with the given parameters. + If so return the CA, if not return False. + + INPUT: + + - ``strength`` (integer) -- the parameter `t` of the covering array, + such that in any selection of `t` columns of the array, every + `t`-tuple appears at least once. + + - ``levels`` (integer) -- the parameter `v` which is the number of + unique symbols that appear in the covering array. + + - ``number_columns`` (integer) -- the number of columns desired for + the covering array. + + EXAMPLES:: + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: from sage.combinat.designs.covering_array import database_check + sage: C = database_check(6, 2, 3) + sage: is_covering_array(C, parameters=True) + (True, (12, 2, 6, 3)) + sage: database_check(6, 3, 3) + False + + """ + import sage.combinat.designs.database as DB + + if (strength, levels) in DB.CA_constructions: + for i in DB.CA_constructions[(strength, levels)]: + if number_columns <= i[1]: + CA = "ca_{}_{}_{}_{}".format(i[0], strength, i[1], levels) + f = getattr(DB, CA) + return truncate_columns(f(), number_columns) + return False + else: + return False def covering_array(strength, number_columns, levels): @@ -188,8 +226,8 @@ def covering_array(strength, number_columns, levels): INPUT: - ``strength`` (integer) -- the parameter `t` of the covering array, - such that in any selection of `t` columns of the array, every `t` - -tuple appears at least once. + such that in any selection of `t` columns of the array, every + `t`-tuple appears at least once. - ``levels`` (integer) -- the parameter `v` which is the number of unique symbols that appear in the covering array. @@ -210,32 +248,21 @@ def covering_array(strength, number_columns, levels): sage: C3 = covering_array(2, 8, 7) sage: is_covering_array(C3,parameters=True) (True, (49, 2, 8, 7)) - sage: C4 = covering_array(3, 9, 3) - Traceback (most recent call last): - ... - ValueError: CAs and OAs only implemented for strength 2 - sage: C5 = covering_array(2, 50, 7) + sage: C4 = covering_array(2, 50, 7) No direct construction known and/or implemented for a CA(N; 2, 50, 7) """ from sage.combinat.designs.orthogonal_arrays import orthogonal_array - if strength != 2: - raise ValueError("CAs and OAs only implemented for strength 2") - - elif levels == 2: + if levels == 2 and strength == 2: return column_Kleitman_Spencer_Katona(number_columns) - elif 3 <= levels <= 6: - import sage.combinat.designs.database as DB - for i in DB.CA_constructions[(strength, levels)]: - if number_columns <= i[1]: - CA = "ca_{}_{}_{}_{}".format(i[0], strength, i[1], levels) - f = getattr(DB, CA) - return truncate_columns(f(), number_columns) + in_database = database_check(number_columns, strength, levels) + if in_database: + return in_database - elif orthogonal_array(number_columns, levels, existence=True): - return orthogonal_array(number_columns, levels) + if orthogonal_array(number_columns, levels, strength, existence=True) == True: + return orthogonal_array(number_columns, levels, strength) else: print("No direct construction known and/or implemented for a CA(N; {}, {}, {})".format( diff --git a/src/sage/combinat/designs/database.py b/src/sage/combinat/designs/database.py index 7f15c84861c..6fa69f8751e 100644 --- a/src/sage/combinat/designs/database.py +++ b/src/sage/combinat/designs/database.py @@ -5038,7 +5038,7 @@ def BIBD_56_11_2(): def ca_11_2_5_3(): r""" - Return a CA with the given parameters, This CA is proven to be optimal. + Return a CA with the given parameters. This CA is proven to be optimal. Data obtained from https://zenodo.org/records/1476059 @@ -5066,7 +5066,7 @@ def ca_11_2_5_3(): def ca_12_2_7_3(): r""" - Return a CA with the given parameters, This CA is proven to be optimal. + Return a CA with the given parameters. This CA is proven to be optimal. Data obtained from https://zenodo.org/records/1476059 @@ -5095,7 +5095,7 @@ def ca_12_2_7_3(): def ca_13_2_9_3(): r""" - Return a CA with the given parameters, This CA is proven to be optimal. + Return a CA with the given parameters. This CA is proven to be optimal. Data obtained from https://zenodo.org/records/1476059 @@ -5125,7 +5125,7 @@ def ca_13_2_9_3(): def ca_14_2_10_3(): r""" - Return a CA with the given parameters, This CA is proven to be optimal. + Return a CA with the given parameters. This CA is proven to be optimal. Data obtained from https://zenodo.org/records/1476059 @@ -5156,7 +5156,7 @@ def ca_14_2_10_3(): def ca_15_2_20_3(): r""" - Return a CA with the given parameters, This CA is proven to be optimal. + Return a CA with the given parameters. This CA is proven to be optimal. Data obtained from [Nur2004]_ @@ -5188,7 +5188,7 @@ def ca_15_2_20_3(): def ca_19_2_6_4(): r""" - Return a CA with the given parameters, This CA is proven to be optimal. + Return a CA with the given parameters. This CA is proven to be optimal. Data obtained from https://zenodo.org/records/1476059 @@ -5224,7 +5224,7 @@ def ca_19_2_6_4(): def ca_21_2_7_4(): r""" - Return a CA with the given parameters, This CA is proven to be optimal. + Return a CA with the given parameters. This CA is proven to be optimal. This CA is also uniform. Data obtained from https://zenodo.org/records/1476059 @@ -5263,7 +5263,7 @@ def ca_21_2_7_4(): def ca_29_2_7_5(): r""" - Return a CA with the given parameters, This CA is proven to be optimal. + Return a CA with the given parameters. This CA is proven to be optimal. Data obtained from https://zenodo.org/records/1476059 @@ -5309,7 +5309,7 @@ def ca_29_2_7_5(): def ca_37_2_4_6(): r""" - Return a CA with the given parameters, This CA is proven to be optimal. + Return a CA with the given parameters. This CA is proven to be optimal. Data obtained from https://zenodo.org/records/1476059 @@ -5363,7 +5363,7 @@ def ca_37_2_4_6(): def ca_39_2_5_6(): r""" - Return a CA with the given parameters, This CA is proven to be optimal. + Return a CA with the given parameters. This CA is proven to be optimal. Data obtained from https://zenodo.org/records/1476059 @@ -5419,7 +5419,7 @@ def ca_39_2_5_6(): def ca_41_2_6_6(): r""" - Return a CA with the given parameters, This CA is proven to be optimal. + Return a CA with the given parameters. This CA is proven to be optimal. This CA is also uniform. Data obtained from https://zenodo.org/records/1476059 From 3ec03bfebf331167b836368352336224143ed799 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer <109538917+aadwyer@users.noreply.github.com> Date: Fri, 19 Jul 2024 11:59:05 -0400 Subject: [PATCH 5/8] Update covering_array.py Changed ValueError to NotImplementedError --- src/sage/combinat/designs/covering_array.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index dd929ea7845..f956f9808f9 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -161,7 +161,7 @@ def column_Kleitman_Spencer_Katona(k): sage: column_Kleitman_Spencer_Katona(25000) Traceback (most recent call last): ... - ValueError: not implemented for k > 24310 + NotImplementedError: not implemented for k > 24310 """ kdict = [(3, 4), (4, 5), (10, 6), (15, 7), (35, 8), (56, 9), @@ -169,7 +169,7 @@ def column_Kleitman_Spencer_Katona(k): (3003, 15), (6435, 16), (11440, 17), (24310, 18)] if k > kdict[-1][0]: - raise ValueError("not implemented for k > {}".format(kdict[-1][0])) + raise NotImplementedError("not implemented for k > {}".format(kdict[-1][0])) for (ki, N) in kdict: if k <= ki: From f08c3f1e4d0fa5f1779363490dcc81795536f1ce Mon Sep 17 00:00:00 2001 From: Aaron Dwyer <109538917+aadwyer@users.noreply.github.com> Date: Fri, 19 Jul 2024 11:59:21 -0400 Subject: [PATCH 6/8] Update src/sage/combinat/designs/database.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Köppe --- src/sage/combinat/designs/database.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/combinat/designs/database.py b/src/sage/combinat/designs/database.py index f7fc59041f8..919ffb6f24c 100644 --- a/src/sage/combinat/designs/database.py +++ b/src/sage/combinat/designs/database.py @@ -5480,10 +5480,10 @@ def ca_41_2_6_6(): # smallest N and largest k such that a CA(N; t, k, v) can be made using # the database. CA_constructions = { - (2,3) : ((11,5), (12,7), (13,9), (14,10), (15,20)), - (2,4) : ((19,6), (21,7)), - (2,5) : ((29,7),), - (2,6) : ((37,4), (39,5), (41,6)) + (2,3): ((11,5), (12,7), (13,9), (14,10), (15,20)), + (2,4): ((19,6), (21,7)), + (2,5): ((29,7),), + (2,6): ((37,4), (39,5), (41,6)) } # Add this data to the module's doc. From 3d0533d13ca0c50a43f41b7aa5d4d9684899aec2 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer <109538917+aadwyer@users.noreply.github.com> Date: Thu, 1 Aug 2024 18:54:53 -0400 Subject: [PATCH 7/8] Update src/sage/combinat/designs/covering_array.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matthias Köppe --- src/sage/combinat/designs/covering_array.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index f956f9808f9..43a7a846757 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -260,7 +260,7 @@ def covering_array(strength, number_columns, levels): if in_database: return in_database - if orthogonal_array(number_columns, levels, strength, existence=True) == True: + if orthogonal_array(number_columns, levels, strength, existence=True) is True: return orthogonal_array(number_columns, levels, strength) else: From 0aa6f448c12f0a97fd313b6995339c55915efb82 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Sat, 3 Aug 2024 15:27:27 -0400 Subject: [PATCH 8/8] Changed the elifs in truncate columns --- src/sage/combinat/designs/covering_array.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index 43a7a846757..9582a627d22 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -88,11 +88,10 @@ def truncate_columns(array, k): if oldk == k: return array - elif oldk < k: + if oldk < k: raise ValueError("array only has {} columns".format(oldk)) - else: - return [row[:k] for row in array] + return [row[:k] for row in array] def Kleitman_Spencer_Katona(N):