Skip to content

Commit b5f7acc

Browse files
author
Release Manager
committed
gh-35059: Add Hadamard matrices up to order 1000 <!-- ^^^^^ Please provide a concise, informative and self-explanatory title. Don't put issue numbers in there, do this in the PR body below. For example, instead of "Fixes #1234" use "Introduce new method to calculate 1+1" --> ### 📚 Description Added new construction for (non skew) Hadamard matrices of order up to 1000. The only orders <1000 for which no construction is known are 668, 716, 892. In particular, the following has been changed: - Added more Williamson type matrices (the way these matrices are stored has been changed to be more compact) - Implemented a function to construct non-skew Supplementary difference Sets, as well as a function to construct Hadamard matrices from these sets - Added Miyamoto construction Note that only commits starting from 15e1b50 are new, the previous ones where created in #34985. <!-- Describe your changes here in detail --> <!-- Why is this change required? What problem does it solve? --> <!-- If it resolves an open issue, please link to the issue here. For example "Closes #1337" --> ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> <!-- If your change requires a documentation PR, please link it appropriately --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> - [x] I have made sure that the title is self-explanatory and the description concisely explains the PR. - [x] I have linked an issue or discussion. - [x] I have created tests covering the changes. - [x] I have updated the documentation accordingly. ### ⌛ Dependencies <!-- List all open pull requests that this PR logically depends on --> <!-- - #xyz: short description why this is a dependency - #abc: ... --> URL: #35059 Reported by: MatteoCati Reviewer(s): david joyner, Dima Pasechnik
2 parents 2b03a1a + 56cfec2 commit b5f7acc

File tree

3 files changed

+542
-71
lines changed

3 files changed

+542
-71
lines changed

src/doc/en/reference/references/index.rst

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2069,10 +2069,15 @@ REFERENCES:
20692069
*Ten New Orders for Hadamard Matrices of Skew Type*,
20702070
Publikacije Elektrotehničkog fakulteta. Serija Matematika 2 (1992): 47-59.
20712071
2072-
.. [Djo1994] \D. Đoković.
2072+
.. [Djo1994a] \D. Đoković.
20732073
*Five New Orders for Hadamard Matrices of Skew Type*,
20742074
Australasian Journal of Combinatorics 10 (1994): 259-264.
20752075
2076+
.. [Djo1994b] \D. Đoković.
2077+
*Two Hadamard matrices of order 956 of Goethals-Seidel type*,
2078+
Combinatorica 14(3) (1994): 375-377.
2079+
:doi:`10.1007/BF01212983`
2080+
20762081
.. [Djo2008a] \D. Đoković.
20772082
*Skew-Hadamard matrices of orders 188 and 388 exist*,
20782083
International Mathematical Forum 3 no.22 (2008): 1063-1068.
@@ -2083,6 +2088,11 @@ REFERENCES:
20832088
Journal of Combinatorial Designs 16 (2008): 493-498.
20842089
:arxiv:`0706.1973`
20852090
2091+
.. [Djo2008c] \D. Đoković.
2092+
*Hadamard matrices of order 764 exist*,
2093+
Combinatorica 28(4) (2008): 487-489.
2094+
:doi:`10.1007/s00493-008-2384-z`
2095+
20862096
.. [Djo2023a] \D. Đoković.
20872097
*Skew-Hadamard matrices of order 276*.
20882098
:arxiv:`10.48550/ARXIV.2301.02751`
@@ -4148,6 +4158,11 @@ REFERENCES:
41484158
of a genus 2 Jacobian*, Mathematics of Computation 88 (2019),
41494159
889-929. :doi:`10.1090/mcom/3358`.
41504160
4161+
.. [Lon2013] \S. London,
4162+
*Constructing New Turyn Type Sequences, T-Sequences and Hadamard Matrices*.
4163+
PhD Thesis, University of Illinois at Chicago, 2013.
4164+
https://hdl.handle.net/10027/9916
4165+
41514166
.. [LOS2012] \C. Lecouvey, M. Okado, M. Shimozono.
41524167
"Affine crystals, one-dimensional sums and parabolic Lusztig
41534168
`q`-analogues". Mathematische Zeitschrift. **271** (2012). Issue 3-4.
@@ -4523,6 +4538,11 @@ REFERENCES:
45234538
.. [Mit2008] \A. Mitra. *On the construction of M-sequences via primitive polynomials with a fast identification method*,
45244539
International Journal of Electronics and Communication Engineering 2(9) (2008): 1991-1996.
45254540
4541+
.. [Miy1991] \M. Miyamoto.
4542+
*A construction of Hadamard matrices*,
4543+
Journal of Combinatorial Theory, Series A 57(1) (1991): 86-108.
4544+
:doi:`10.1016/0097-3165(91)90008-5`
4545+
45264546
.. [MKO1998] Hans Munthe--Kaas and Brynjulf Owren.
45274547
*Computations in a free Lie algebra*. (1998).
45284548
`Downloadable from Munthe-Kaas's website

src/sage/combinat/designs/difference_family.py

Lines changed: 204 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,8 +1618,8 @@ def is_supplementary_difference_set(Ks, v, lmbda):
16181618
16191619
EXAMPLES::
16201620
1621-
sage: from sage.combinat.designs.difference_family import supplementary_difference_set, is_supplementary_difference_set
1622-
sage: S1, S2, S3, S4 = supplementary_difference_set(17)
1621+
sage: from sage.combinat.designs.difference_family import supplementary_difference_set_from_rel_diff_set, is_supplementary_difference_set
1622+
sage: S1, S2, S3, S4 = supplementary_difference_set_from_rel_diff_set(17)
16231623
sage: is_supplementary_difference_set([S1, S2, S3, S4], 16, 16)
16241624
True
16251625
sage: is_supplementary_difference_set([S1, S2, S3, S4], 16, 14)
@@ -1629,7 +1629,7 @@ def is_supplementary_difference_set(Ks, v, lmbda):
16291629
16301630
.. SEEALSO::
16311631
1632-
:func:`supplementary_difference_set`
1632+
:func:`supplementary_difference_set_from_rel_diff_set`
16331633
"""
16341634
from sage.groups.additive_abelian.additive_abelian_group import AdditiveAbelianGroup
16351635

@@ -1651,7 +1651,7 @@ def is_supplementary_difference_set(Ks, v, lmbda):
16511651

16521652
return True
16531653

1654-
def supplementary_difference_set(q, existence=False, check=True):
1654+
def supplementary_difference_set_from_rel_diff_set(q, existence=False, check=True):
16551655
r"""Construct `4-\{2v; v, v+1, v, v; 2v\}` supplementary difference sets where `q=2v+1`.
16561656
16571657
The sets are created from relative difference sets as detailed in Theorem 3.3 of [Spe1975]_. this construction
@@ -1682,40 +1682,40 @@ def supplementary_difference_set(q, existence=False, check=True):
16821682
16831683
EXAMPLES::
16841684
1685-
sage: from sage.combinat.designs.difference_family import supplementary_difference_set
1686-
sage: supplementary_difference_set(17) #random
1685+
sage: from sage.combinat.designs.difference_family import supplementary_difference_set_from_rel_diff_set
1686+
sage: supplementary_difference_set_from_rel_diff_set(17) #random
16871687
([0, 2, 5, 6, 8, 10, 13, 14],
16881688
[0, 1, 2, 6, 7, 9, 10, 14, 15],
16891689
[0, 1, 2, 6, 11, 12, 13, 15],
16901690
[0, 2, 6, 9, 11, 12, 13, 15])
16911691
16921692
If existence is ``True``, the function returns a boolean::
16931693
1694-
sage: supplementary_difference_set(7, existence=True)
1694+
sage: supplementary_difference_set_from_rel_diff_set(7, existence=True)
16951695
False
1696-
sage: supplementary_difference_set(17, existence=True)
1696+
sage: supplementary_difference_set_from_rel_diff_set(17, existence=True)
16971697
True
16981698
16991699
TESTS::
17001700
17011701
sage: from sage.combinat.designs.difference_family import is_supplementary_difference_set
1702-
sage: is_supplementary_difference_set(supplementary_difference_set(17), 16, 16)
1702+
sage: is_supplementary_difference_set(supplementary_difference_set_from_rel_diff_set(17), 16, 16)
17031703
True
1704-
sage: is_supplementary_difference_set(supplementary_difference_set(9), 8, 8)
1704+
sage: is_supplementary_difference_set(supplementary_difference_set_from_rel_diff_set(9), 8, 8)
17051705
True
1706-
sage: supplementary_difference_set(7)
1706+
sage: supplementary_difference_set_from_rel_diff_set(7)
17071707
Traceback (most recent call last):
17081708
...
17091709
ValueError: There is no s for which m-1 is an odd prime power
1710-
sage: supplementary_difference_set(8)
1710+
sage: supplementary_difference_set_from_rel_diff_set(8)
17111711
Traceback (most recent call last):
17121712
...
17131713
ValueError: q must be an odd prime power
1714-
sage: supplementary_difference_set(8, existence=True)
1714+
sage: supplementary_difference_set_from_rel_diff_set(8, existence=True)
17151715
False
1716-
sage: supplementary_difference_set(7, existence=True)
1716+
sage: supplementary_difference_set_from_rel_diff_set(7, existence=True)
17171717
False
1718-
sage: supplementary_difference_set(1, existence=True)
1718+
sage: supplementary_difference_set_from_rel_diff_set(1, existence=True)
17191719
False
17201720
17211721
.. SEEALSO::
@@ -1823,7 +1823,7 @@ def get_fixed_relative_difference_set(rel_diff_set, as_elements=False):
18231823
`\{td | d\in R\}= R`.
18241824
18251825
In addition, the set returned by this function will contain the element `0`. This is needed in the
1826-
construction of supplementary difference sets (see :func:`supplementary_difference_set`).
1826+
construction of supplementary difference sets (see :func:`supplementary_difference_set_from_rel_diff_set`).
18271827
18281828
INPUT:
18291829
@@ -1929,12 +1929,12 @@ def is_fixed_relative_difference_set(R, q):
19291929
def skew_supplementary_difference_set(n, existence=False, check=True):
19301930
r"""Construct `4-\{n; n_1, n_2, n_3, n_4; \lambda\}` supplementary difference sets where `S_1` is skew and `n_1 + n_2 + n_3 + n_4 = n+\lambda`.
19311931
1932-
These sets are constructed from available data, as described in [Djo1994]_. The set `S_1 \subset G` is
1932+
These sets are constructed from available data, as described in [Djo1994a]_. The set `S_1 \subset G` is
19331933
always skew, i.e. `S_1 \cap (-S_1) = \emptyset` and `S_1 \cup (-S_1) = G \setminus \{0\}`.
19341934
19351935
The data is taken from:
19361936
1937-
* `n = 103, 151`: [Djo1994]_
1937+
* `n = 103, 151`: [Djo1994a]_
19381938
* `n = 67, 113, 127, 157, 163, 181, 241`: [Djo1992a]_
19391939
* `n = 37, 43`: [Djo1992b]_
19401940
* `n = 39, 49, 65, 93, 121, 129, 133, 217, 219, 267`: [Djo1992c]_
@@ -2155,6 +2155,88 @@ def skew_supplementary_difference_set(n, existence=False, check=True):
21552155
267: [1, 4, 16, 64, 67, 91, 97, 121, 217, 223, 256],
21562156
}
21572157

2158+
if existence:
2159+
return n in indices
2160+
2161+
if n not in indices:
2162+
raise ValueError(f'Skew SDS of order {n} not yet implemented.')
2163+
2164+
S1, S2, S3, S4 = _construction_supplementary_difference_set(n, H_db[n], indices[n], cosets_gens[n], check=False)
2165+
2166+
if check:
2167+
lmbda = len(S1) + len(S2) + len(S3) + len(S4) - n
2168+
assert is_supplementary_difference_set([S1, S2, S3, S4], n, lmbda)
2169+
assert _is_skew_set(S1, n)
2170+
2171+
return S1, S2, S3, S4
2172+
2173+
2174+
def _construction_supplementary_difference_set(n, H, indices, cosets_gen, check=True):
2175+
r"""Construct `4-\{n; n_1, n_2, n_3, n_4; \lambda\}` supplementary difference sets where `n_1 + n_2 + n_3 + n_4 = n+\lambda`.
2176+
2177+
This construction is described in [Djo1994a]_.
2178+
2179+
Let H be a subgroup of Zmod(n) of order `t`. We construct the `2s = n/t` cosets
2180+
`\alpha_0, .., \alpha_{2s-1}` by using the elements contained in a sequence `A`:
2181+
`\alpha_{2i} = a_iH` and `\alpha_{2i+1} = -\alpha_{2i}`.
2182+
2183+
Then, we use four indices sets `J_1, J_2, J_3, J_4` to construct the four
2184+
supplementary difference sets: `S_i = \bigcup_{j\in J__i} \alpha_i`. Note that
2185+
if `J_i` contains the value `-1`, this function will add `0` to the set `S_i`.
2186+
2187+
To construct a coset `\alpha_{2i}` by listing it directly, replace the `2i`-th
2188+
element of the list `A` with the desired set.
2189+
2190+
INPUT:
2191+
2192+
- ``n`` -- integer, the parameter of the supplementary difference set.
2193+
2194+
- ``H`` -- list of integers, the set `H` used to construct the cosets.
2195+
2196+
- ``indices`` -- list containing four list of integers, which are the sets
2197+
`J_1, J_2, J_3, J_4` described above.
2198+
2199+
- ``cosets_gen`` -- list containing integers or list of integers, is the set `A`
2200+
described above.
2201+
2202+
- ``check`` -- boolean (default True). If true, check that the sets
2203+
are supplementary difference sets. Setting this parameter to False may speed
2204+
up the computation considerably.
2205+
2206+
OUTPUT:
2207+
2208+
The function returns the 4 sets (containing integers modulo `n`).
2209+
2210+
TESTS::
2211+
2212+
sage: from sage.combinat.designs.difference_family import is_supplementary_difference_set, _construction_supplementary_difference_set
2213+
sage: H = [1, 10, -11]
2214+
sage: cosets_gen = [1, 2, 3, 5, 6, 9]
2215+
sage: indices = [[0, 3, 5, 7, 9, 10], [0, 5, 6, 7, 8], [1, 2, 6, 7, 9], [2, 6, 8, 9, 10]]
2216+
sage: _construction_supplementary_difference_set(37, H, indices, cosets_gen)
2217+
([1, 10, 26, 35, 17, 22, 34, 7, 33, 32, 24, 18, 31, 14, 29, 9, 16, 12],
2218+
[1, 10, 26, 34, 7, 33, 5, 13, 19, 32, 24, 18, 6, 23, 8],
2219+
[36, 27, 11, 2, 20, 15, 5, 13, 19, 32, 24, 18, 31, 14, 29],
2220+
[2, 20, 15, 5, 13, 19, 6, 23, 8, 31, 14, 29, 9, 16, 12])
2221+
sage: H = [1, 16, 22]
2222+
sage: cosets_gen = [1, 2, 3, 4, 6, 8, [13]]
2223+
sage: indices = [[1, 3, 5, 6, 8, 10, 12], [0, 1, 5, 8, 12, 13], [1, 3, 4, 7, 9, 12, 13], [0, 1, 2, 3, 7, 8]]
2224+
sage: _construction_supplementary_difference_set(39, H, indices, cosets_gen)
2225+
([38, 23, 17, 37, 7, 34, 36, 30, 12, 4, 25, 10, 6, 18, 15, 8, 11, 20, 13],
2226+
[1, 16, 22, 38, 23, 17, 36, 30, 12, 6, 18, 15, 13, 26],
2227+
[38, 23, 17, 37, 7, 34, 3, 9, 27, 35, 14, 29, 33, 21, 24, 13, 26],
2228+
[1, 16, 22, 38, 23, 17, 2, 32, 5, 37, 7, 34, 35, 14, 29, 6, 18, 15])
2229+
sage: H = [1, 4, 11, 16, 21, -2, -8]
2230+
sage: cosets_gen = [1, 3, 7]
2231+
sage: indices = [[1, 2, 4], [1, 2, 4], [0, 2, 3], [3, 4, -1]]
2232+
sage: sets = _construction_supplementary_difference_set(43, H, indices, cosets_gen, check=False)
2233+
sage: is_supplementary_difference_set(sets, 43, 35)
2234+
True
2235+
2236+
.. SEEALSO::
2237+
2238+
:func:`skew_supplementary_difference_set`
2239+
"""
21582240
def generate_set(index_set, cosets):
21592241
S = []
21602242
for idx in index_set:
@@ -2164,17 +2246,11 @@ def generate_set(index_set, cosets):
21642246
S += cosets[idx]
21652247
return S
21662248

2167-
if existence:
2168-
return n in indices
2169-
2170-
if n not in indices:
2171-
raise ValueError(f'Skew SDS of order {n} not yet implemented.')
2172-
21732249
Z = Zmod(n)
2174-
H = list(map(Z, H_db[n]))
2250+
H = list(map(Z, H))
21752251

21762252
cosets = []
2177-
for el in cosets_gens[n]:
2253+
for el in cosets_gen:
21782254
if isinstance(el, list):
21792255
even_coset = [Z(x) for x in el]
21802256
else:
@@ -2183,22 +2259,118 @@ def generate_set(index_set, cosets):
21832259
cosets.append(even_coset)
21842260
cosets.append(odd_coset)
21852261

2186-
S1 = generate_set(indices[n][0], cosets)
2187-
S2 = generate_set(indices[n][1], cosets)
2188-
S3 = generate_set(indices[n][2], cosets)
2189-
S4 = generate_set(indices[n][3], cosets)
2262+
S1 = generate_set(indices[0], cosets)
2263+
S2 = generate_set(indices[1], cosets)
2264+
S3 = generate_set(indices[2], cosets)
2265+
S4 = generate_set(indices[3], cosets)
21902266

21912267
if check:
21922268
lmbda = len(S1) + len(S2) + len(S3) + len(S4) - n
21932269
assert is_supplementary_difference_set([S1, S2, S3, S4], n, lmbda)
2194-
assert _is_skew_set(S1, n)
21952270

21962271
return S1, S2, S3, S4
21972272

2273+
2274+
def supplementary_difference_set(n, existence=False, check=True):
2275+
r"""Construct `4-\{n; n_1, n_2, n_3, n_4; \lambda\}` supplementary difference sets where `n_1 + n_2 + n_3 + n_4 = n+\lambda`.
2276+
2277+
These sets are constructed from available data, as described in [Djo1994a]_.
2278+
2279+
The data for `n=191` is taken from [Djo2008c]_, and data for `n=239` is from [Djo1994b]_.
2280+
Additional SDS are constructed using :func:`skew_supplementary_difference_set`.
2281+
2282+
INPUT:
2283+
2284+
- ``n`` -- integer, the parameter of the supplementary difference set.
2285+
2286+
- ``existence`` -- boolean (default False). If true, only check whether the
2287+
supplementary difference sets can be constructed.
2288+
2289+
- ``check`` -- boolean (default True). If true, check that the sets are
2290+
supplementary difference sets before returning them. Setting this parameter
2291+
to False may speed up the computation considerably.
2292+
2293+
OUTPUT:
2294+
2295+
If ``existence`` is false, the function returns the 4 sets (containing integers
2296+
modulo `n`), or raises an error if data for the given ``n`` is not available.
2297+
If ``existence`` is true, the function returns a boolean representing whether
2298+
skew supplementary difference sets can be constructed.
2299+
2300+
EXAMPLES::
2301+
2302+
sage: from sage.combinat.designs.difference_family import supplementary_difference_set
2303+
sage: S1, S2, S3, S4 = supplementary_difference_set(191) # long time
2304+
2305+
If existence is ``True``, the function returns a boolean ::
2306+
2307+
sage: supplementary_difference_set(191, existence=True)
2308+
True
2309+
sage: supplementary_difference_set(17, existence=True)
2310+
False
2311+
2312+
TESTS::
2313+
2314+
sage: from sage.combinat.designs.difference_family import is_supplementary_difference_set
2315+
sage: S1, S2, S3, S4 = supplementary_difference_set(191, check=False)
2316+
sage: is_supplementary_difference_set([S1, S2, S3, S4], 191, len(S1)+len(S2)+len(S3)+len(S4)-191) # long time
2317+
True
2318+
sage: S1, S2, S3, S4 = supplementary_difference_set(37, check=False)
2319+
sage: supplementary_difference_set(7)
2320+
Traceback (most recent call last):
2321+
...
2322+
ValueError: SDS of order 7 not yet implemented.
2323+
sage: supplementary_difference_set(7, existence=True)
2324+
False
2325+
sage: supplementary_difference_set(127, existence=True)
2326+
True
2327+
"""
2328+
2329+
indices = {
2330+
191: [[1, 7, 9, 10, 11, 13, 17, 18, 25, 26, 30, 31, 33, 34, 35, 36, 37],
2331+
[1, 4, 7, 9, 11, 12, 13, 14, 19, 21, 22, 23, 24, 25, 26, 29, 36, 37],
2332+
[0, 3, 4, 5, 7, 8, 9, 16, 17, 19, 24, 25, 29, 30, 31, 33, 35, 37],
2333+
[1, 3, 4, 5, 8, 11, 14, 18, 19, 20, 21, 23, 24, 25, 28, 29, 30, 32, 34, 35]],
2334+
239: [[0, 1, 2, 3, 4, 5, 6, 7, 14, 18, 19, 21, 24, 25, 29, 30],
2335+
[0, 1, 3, 7, 9, 12, 15, 18, 20, 22, 26, 28, 29, 30, 31, 32, 33],
2336+
[2, 3, 4, 5, 8, 9, 10, 11, 13, 17, 19, 21, 22, 24, 27, 31, 32],
2337+
[0, 1, 2, 3, 6, 7, 8, 11, 13, 15, 17, 18, 19, 22, 25, 26, 27, 32, 33]],
2338+
}
2339+
2340+
cosets_gens = {
2341+
191: [1, 2, 3, 4, 6, 8, 9, 11, 12, 13, 16, 17, 18, 19, 22, 32, 36, 38, 41],
2342+
239: [1, 2, 3, 4, 5, 6, 7, 8, 9, 13, 14, 15, 18, 21, 28, 35, 42],
2343+
}
2344+
2345+
H_db = {
2346+
191: [1, 39, 184, 109, 49],
2347+
239: [1, 10, 24, 44, 98, 100, 201],
2348+
}
2349+
2350+
if existence:
2351+
return n in indices or skew_supplementary_difference_set(n, existence=True)
2352+
2353+
sets = None
2354+
if n in indices:
2355+
sets = _construction_supplementary_difference_set(n, H_db[n], indices[n], cosets_gens[n], check=False)
2356+
elif skew_supplementary_difference_set(n, existence=True):
2357+
sets = skew_supplementary_difference_set(n, check=False)
2358+
2359+
if sets is None:
2360+
raise ValueError(f'SDS of order {n} not yet implemented.')
2361+
2362+
S1, S2, S3, S4 = sets
2363+
if check:
2364+
lmbda = len(S1) + len(S2) + len(S3) + len(S4) - n
2365+
assert is_supplementary_difference_set([S1, S2, S3, S4], n, lmbda)
2366+
2367+
return S1, S2, S3, S4
2368+
2369+
21982370
def _is_skew_set(S, n):
21992371
r"""Check if `S` is a skew set over the set of integers modulo `n`.
22002372
2201-
From [Djo1994]_, a set `S \subset G` (where `G` is a finite abelian group of order `n`) is of skew
2373+
From [Djo1994a]_, a set `S \subset G` (where `G` is a finite abelian group of order `n`) is of skew
22022374
type if `S_1 \cap (-S_1) = \emptyset` and `S_1 \cup (-S_1) = G\setminus \{0\}`.
22032375
22042376
INPUT:

0 commit comments

Comments
 (0)