Skip to content

Commit 15f7fbb

Browse files
authored
Merge pull request #5 from Aaron-Dwyer/covering_array
Covering array
2 parents 833fd2e + 220a3ac commit 15f7fbb

File tree

2 files changed

+72
-77
lines changed

2 files changed

+72
-77
lines changed

src/sage/combinat/designs/covering_array.py

+70-77
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,11 @@
1212
1313
REFERENCES:
1414
15-
.. [Colb2004] C.J. Colbourn. “Combinatorial aspects of covering arrays”.
16-
Matematiche (Catania) 59 (2004), pp. 125–172.
15+
- [Colb2004]_
1716
17+
- [Sher2006]_
1818
19-
.. [Sher2006] G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn,
20-
"Covering arrays of higher strength from permutation
21-
vectors". J. Combin. Designs, 14 (2006) pp. 202-213.
22-
23-
.. [Wal2007] R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families:
24-
Constructions and Existence". J. Math. Crypt. 1 (2007),
25-
pp.125-150
19+
- [Wal2007]_
2620
2721
AUTHORS:
2822
@@ -47,23 +41,24 @@
4741

4842
from sage.rings.finite_rings.finite_field_constructor import GF
4943
from sage.structure.sage_object import SageObject
50-
from sage.structure.richcmp import richcmp
51-
44+
from sage.structure.richcmp import richcmp, richcmp_method
5245

46+
@richcmp_method
5347
class CoveringArray(SageObject):
5448
r"""
5549
Covering Array (CA)
5650
5751
INPUT:
5852
59-
- ``Array`` -- The N by k array itself stored as a tuple of tuples.
60-
The N and k parameters are derived from this inputted array
53+
- ``array`` -- The `N` by `k` array itself stored as a tuple of
54+
tuples. The `N` and `k` parameters are derived from this inputted
55+
array.
6156
62-
- ``SymbolSet`` -- The collection of symbols that is used in
63-
``Array``. If left blank, then a symbol set will be assumed by
64-
checking for each unique entry in the given ``Array``. In such a
65-
case it will be stored as a list of symbols but any appropriate
66-
object may be used as long as it has `len()` as a method
57+
- ``symbol_set`` -- The collection of symbols that is used in
58+
``array``. If left blank, then a symbol set will be assumed by
59+
checking for each unique entry in the given ``array``. In such a
60+
case it will be stored as a tuple of symbols but any appropriate
61+
object may be used as long as it has ``len()`` as a method.
6762
6863
EXAMPLES::
6964
@@ -74,7 +69,7 @@ class CoveringArray(SageObject):
7469
....: ('b', 'a', 'a', 'a'),
7570
....: ('b', 'b', 'b', 'b'))
7671
sage: CoveringArray(C)
77-
A 5 by 4 Covering Array with entries from ['a', 'b']
72+
A 5 by 4 Covering Array with entries from ('a', 'b')
7873
7974
sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
8075
....: (1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
@@ -89,8 +84,8 @@ class CoveringArray(SageObject):
8984
....: (0, 1, 0, 1, 1, 0, 0, 1, 0, 0),
9085
....: (1, 0, 0, 0, 0, 0, 0, 1, 1, 1),
9186
....: (0, 1, 0, 0, 0, 1, 1, 1, 0, 1))
92-
sage: CoveringArray(C,[0, 1])
93-
A 13 by 10 Covering Array with entries from [0, 1]
87+
sage: CoveringArray(C,(0, 1))
88+
A 13 by 10 Covering Array with entries from (0, 1)
9489
9590
sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
9691
....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),
@@ -109,12 +104,12 @@ class CoveringArray(SageObject):
109104
....: (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),
110105
....: (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0))
111106
sage: CoveringArray(C)
112-
A 7 by 15 Covering Array with entries from [0, 1]
107+
A 7 by 15 Covering Array with entries from (0, 1)
113108
"""
114109

115-
def __init__(self, Array, SymbolSet=None):
110+
def __init__(self, array, symbol_set=None):
116111
r"""
117-
Constructor function
112+
Constructor function.
118113
119114
EXAMPLES::
120115
@@ -125,7 +120,7 @@ def __init__(self, Array, SymbolSet=None):
125120
....: ('b', 'a', 'a', 'a'),
126121
....: ('b', 'b', 'b', 'b'))
127122
sage: CoveringArray(C)
128-
A 5 by 4 Covering Array with entries from ['a', 'b']
123+
A 5 by 4 Covering Array with entries from ('a', 'b')
129124
130125
sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
131126
....: (1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
@@ -140,8 +135,8 @@ def __init__(self, Array, SymbolSet=None):
140135
....: (0, 1, 0, 1, 1, 0, 0, 1, 0, 0),
141136
....: (1, 0, 0, 0, 0, 0, 0, 1, 1, 1),
142137
....: (0, 1, 0, 0, 0, 1, 1, 1, 0, 1))
143-
sage: CoveringArray(C,[0, 1])
144-
A 13 by 10 Covering Array with entries from [0, 1]
138+
sage: CoveringArray(C,(0, 1))
139+
A 13 by 10 Covering Array with entries from (0, 1)
145140
146141
sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
147142
....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),
@@ -160,35 +155,35 @@ def __init__(self, Array, SymbolSet=None):
160155
....: (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),
161156
....: (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0))
162157
sage: CoveringArray(C)
163-
A 7 by 15 Covering Array with entries from [0, 1]
158+
A 7 by 15 Covering Array with entries from (0, 1)
164159
"""
165160
#From the array input, grab the dimensions of the array
166-
N = len(Array)
167-
self.__n = N
168-
k = len(Array[0])
169-
self.__k = k
161+
N = len(array)
162+
self._n = N
163+
k = len(array[0])
164+
self._k = k
170165

171-
#Array input is a tuple of tuples, the first thing to do is to
166+
#array input is a tuple of tuples, the first thing to do is to
172167
#sort the tuples lexicographically increasing
173-
L = list(Array)
168+
L = list(array)
174169
L.sort()
175-
SortedArray = tuple(L)
176-
self.__array = SortedArray
170+
self._array = tuple(L)
177171

178-
for row in Array:
179-
assert len(row) == len(Array[0]), "Not all rows have same length"
172+
for row in array:
173+
assert len(row) == len(array[0]), "Not all rows have same length"
180174

181175
#If no symbol set is given, then it may be assumed from what
182176
#symbols are in the array by flattening the array and counting
183177
#the number of unique entries.
184-
if SymbolSet is None:
185-
SymbolSet = list({x for l in Array for x in l})
186-
SymbolSet.sort()
187-
self.__sset=SymbolSet
178+
if symbol_set is None:
179+
symbol_set = list({x for l in array for x in l})
180+
symbol_set.sort()
181+
symbol_set = tuple(symbol_set)
182+
self._sset = symbol_set
188183

189-
def numrows(self):
184+
def number_rows(self):
190185
r"""
191-
Return the number of rows, `N`, of the covering array
186+
Return the number of rows, `N`, of the covering array.
192187
193188
EXAMPLES::
194189
@@ -199,14 +194,14 @@ def numrows(self):
199194
....: (0, 1, 1, 1),
200195
....: (0, 0, 0, 0))
201196
sage: CA = CoveringArray(C,GF(2))
202-
sage: CA.numrows()
197+
sage: CA.number_rows()
203198
5
204199
"""
205-
return self.__n
200+
return self._n
206201

207-
def numcols(self):
202+
def number_columns(self):
208203
r"""
209-
Returns the number of columns, `k`, of the covering array
204+
Return the number of columns, `k`, of the covering array.
210205
211206
EXAMPLES::
212207
@@ -217,12 +212,12 @@ def numcols(self):
217212
....: (0, 1, 1, 1),
218213
....: (0, 0, 0, 0))
219214
sage: CA = CoveringArray(C,GF(2))
220-
sage: CA.numcols()
215+
sage: CA.number_columns()
221216
4
222217
"""
223-
return self.__k
218+
return self._k
224219

225-
def symbolset(self):
220+
def symbol_set(self):
226221
r"""
227222
Return the symbol set of the array.
228223
@@ -235,13 +230,13 @@ def symbolset(self):
235230
....: (0, 1, 1, 1),
236231
....: (0, 0, 0, 0))
237232
sage: CA = CoveringArray(C,GF(2))
238-
sage: CA.symbolset()
233+
sage: CA.symbol_set()
239234
Finite Field of size 2
240235
sage: CA = CoveringArray(C)
241-
sage: CA.symbolset()
242-
[0, 1]
236+
sage: CA.symbol_set()
237+
(0, 1)
243238
"""
244-
return self.__sset
239+
return self._sset
245240

246241
def is_covering_array(self,strength):
247242
r"""
@@ -319,14 +314,13 @@ def is_covering_array(self,strength):
319314
True
320315
"""
321316
tupledict = {}
322-
a = [ttuple for ttuple in itertools.product(self.symbolset(),
317+
a = [ttuple for ttuple in itertools.product(self._sset,
323318
repeat=strength)]
324319
for item in a:
325320
tupledict.update({item:0})
326-
for comb in itertools.combinations(range(self.numcols()),
327-
strength):
321+
for comb in itertools.combinations(range(self._k), strength):
328322
wdict=copy.deepcopy(tupledict)
329-
for row in self.__array:
323+
for row in self._array:
330324
wdict[tuple([row[ti] for ti in comb])] += 1
331325
if 0 in wdict.values():
332326
return False
@@ -434,12 +428,12 @@ def levels(self):
434428
sage: CA.levels()
435429
2
436430
"""
437-
return len(self.__sset)
431+
return len(self._sset)
438432

439433
def array_representation(self):
440434
r"""
441435
Return the covering array as a tuple of tuples, the output is
442-
such that each row of the array is sorted in lexicographic order
436+
such that each row of the array is sorted in lexicographic order.
443437
444438
EXAMPLES::
445439
@@ -454,11 +448,11 @@ def array_representation(self):
454448
((0, 0, 0, 0), (0, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1),
455449
(1, 1, 1, 0))
456450
"""
457-
return self.__array
451+
return self._array
458452

459453
def _repr_(self):
460454
r"""
461-
Returns a string that describes self
455+
Return a string that describes self.
462456
463457
EXAMPLES::
464458
@@ -469,7 +463,7 @@ def _repr_(self):
469463
....: ('b', 'a', 'a', 'a'),
470464
....: ('b', 'b', 'b', 'b'))
471465
sage: CoveringArray(C)
472-
A 5 by 4 Covering Array with entries from ['a', 'b']
466+
A 5 by 4 Covering Array with entries from ('a', 'b')
473467
474468
sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
475469
....: (1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
@@ -484,8 +478,8 @@ def _repr_(self):
484478
....: (0, 1, 0, 1, 1, 0, 0, 1, 0, 0),
485479
....: (1, 0, 0, 0, 0, 0, 0, 1, 1, 1),
486480
....: (0, 1, 0, 0, 0, 1, 1, 1, 0, 1))
487-
sage: CoveringArray(C,[0, 1])
488-
A 13 by 10 Covering Array with entries from [0, 1]
481+
sage: CoveringArray(C,(0, 1))
482+
A 13 by 10 Covering Array with entries from (0, 1)
489483
490484
sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
491485
....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),
@@ -504,14 +498,14 @@ def _repr_(self):
504498
....: (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),
505499
....: (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0))
506500
sage: CoveringArray(C)
507-
A 7 by 15 Covering Array with entries from [0, 1]
501+
A 7 by 15 Covering Array with entries from (0, 1)
508502
"""
509503
return 'A {} by {} Covering Array with entries from {}'.format(
510-
self.numrows(), self.numcols(), self.symbolset())
504+
self._n, self._k, self._sset)
511505

512506
def pp(self):
513507
r"""
514-
Prints the covering array in a format easy for users to read
508+
Prints the covering array in a format easy for users to read.
515509
516510
EXAMPLES::
517511
@@ -533,12 +527,12 @@ def pp(self):
533527
(1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0)
534528
(1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)
535529
"""
536-
for i in self.__array:
530+
for i in self._array:
537531
print(str(i))
538532

539533
def __hash__(self):
540534
r"""
541-
Hashs the tuple of tuples and all tuples inside
535+
Hashs the tuple of tuples and all tuples inside.
542536
543537
EXAMPLES::
544538
@@ -554,11 +548,10 @@ def __hash__(self):
554548
sage: hash(CA)
555549
4367534393624660384
556550
"""
557-
return hash((self.array_representation(), tuple(self.symbolset())))
558-
551+
return hash((self.array_representation(),
552+
tuple(self.symbol_set())))
559553

560-
'''
561-
def _richcmp_(self, other, op):
554+
def __richcmp__(self, other, op):
562555
r"""
563556
Do the comparison.
564557
@@ -595,5 +588,5 @@ def _richcmp_(self, other, op):
595588
sage: CA1 < CA2
596589
False
597590
"""
598-
return richcmp(self.array_representation(), other.array_representation(), op)
599-
'''
591+
return richcmp(self.array_representation(),
592+
other.array_representation(), op)

src/sage/combinat/designs/design_catalog.py

+2
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,5 @@
119119

120120
lazy_import('sage.combinat.designs.gen_quadrangles_with_spread',
121121
('generalised_quadrangle_with_spread', 'generalised_quadrangle_hermitian_with_ovoid'))
122+
123+
lazy_import('sage.combinat.designs.covering_array', 'CoveringArray')

0 commit comments

Comments
 (0)