Skip to content

Commit

Permalink
sagemathgh-37372: Strength 2 Covering Array constructions
Browse files Browse the repository at this point in the history
    
This patch aims to add functionality to the covering arrays module that
was recently added to SageMath. It adds methods that create many
covering arrays of strength 2 that can later be used for recursive
constructions as well.

Specifically: added methods to generate covering arrays and a main CA
function to call them based on inputted parameters.
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.

This fixes sagemath#37371
    
URL: sagemath#37372
Reported by: Aaron Dwyer
Reviewer(s): Aaron Dwyer, Matthias Köppe, Sebastian Raaphorst
  • Loading branch information
Release Manager committed Aug 4, 2024
2 parents 0f34773 + 0aa6f44 commit 872d407
Show file tree
Hide file tree
Showing 3 changed files with 697 additions and 11 deletions.
22 changes: 16 additions & 6 deletions src/doc/en/reference/references/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1828,8 +1828,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. 125172.
.. [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.
Expand Down Expand Up @@ -3778,6 +3778,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.
Expand Down Expand Up @@ -4086,6 +4090,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`
Expand Down Expand Up @@ -5137,6 +5144,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`
Expand Down Expand Up @@ -5913,8 +5923,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,
Expand Down Expand Up @@ -6617,8 +6627,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
Expand Down
223 changes: 220 additions & 3 deletions src/sage/combinat/designs/covering_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@
.. 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.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:
Expand Down Expand Up @@ -49,3 +54,215 @@
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

if oldk < k:
raise ValueError("array only has {} columns".format(oldk))

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 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 `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 itertools import combinations
from sage.arith.misc import integer_ceil
if N < 4:
raise ValueError("N must be greater than 3")

col_list = []
for p in combinations(range(N-1), integer_ceil(N/2)):
S = [0]*N
for i in p:
S[i] = 1
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
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):
...
NotImplementedError: 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)]

if k > kdict[-1][0]:
raise NotImplementedError("not implemented for k > {}".format(kdict[-1][0]))

for (ki, N) in kdict:
if k <= ki:
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):
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(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 levels == 2 and strength == 2:
return column_Kleitman_Spencer_Katona(number_columns)

in_database = database_check(number_columns, strength, levels)
if in_database:
return in_database

if orthogonal_array(number_columns, levels, strength, existence=True) is True:
return orthogonal_array(number_columns, levels, strength)

else:
print("No direct construction known and/or implemented for a CA(N; {}, {}, {})".format(
strength, number_columns, levels))
return
Loading

0 comments on commit 872d407

Please sign in to comment.