From d0788d79031f664a52f31d7c6c8d4e108a653866 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Thu, 8 Aug 2024 14:00:15 +0100 Subject: [PATCH 1/5] starting to implement generalised PaleyII symmetric conference matrices --- src/sage/combinat/matrices/hadamard_matrix.py | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/sage/combinat/matrices/hadamard_matrix.py b/src/sage/combinat/matrices/hadamard_matrix.py index c08812c5a83..51fe5f5a600 100644 --- a/src/sage/combinat/matrices/hadamard_matrix.py +++ b/src/sage/combinat/matrices/hadamard_matrix.py @@ -306,10 +306,10 @@ def hadamard_matrix_paleyII(n): True """ q = n//2 - 1 - if not (n % 2 == 0 and is_prime_power(q) and (q % 4 == 1)): - raise ValueError("The order %s is not covered by the Paley type II construction." % n) + # if not (n % 2 == 0 and is_prime_power(q) and (q % 4 == 1)): + # raise ValueError("The order %s is not covered by the Paley type II construction." % n) - H = symmetric_conference_matrix_paley(q+1) + H = symmetric_conference_matrix(q+1) tr = { 0: matrix(2, 2, [ 1, -1, -1, -1]), 1: matrix(2, 2, [ 1, 1, 1, -1]), @@ -363,6 +363,10 @@ def hadamard_matrix_miyamoto_construction(n, existence=False, check=True): True sage: hadamard_matrix_miyamoto_construction(64, existence=True) False + sage: hadamard_matrix_miyamoto_construction(4*65, existence=True) + True + sage: is_hadamard_matrix(hadamard_matrix_miyamoto_construction(4*65, check=False)) + True sage: hadamard_matrix_miyamoto_construction(64) Traceback (most recent call last): ... @@ -377,14 +381,16 @@ def hadamard_matrix_miyamoto_construction(n, existence=False, check=True): q = n // 4 if existence: - return is_prime_power(q) and q % 4 == 1 and hadamard_matrix(q-1, existence=True) is True + # return is_prime_power(q) and q % 4 == 1 and hadamard_matrix(q-1, existence=True) is True + return symmetric_conference_matrix(q+1, existence=True) and hadamard_matrix(q-1, existence=True) is True - if not (is_prime_power(q) and q % 4 == 1 and hadamard_matrix(q-1, existence=True)): + # if not (is_prime_power(q) and q % 4 == 1 and hadamard_matrix(q-1, existence=True)): + if not (symmetric_conference_matrix(q+1, existence=True) and hadamard_matrix(q-1, existence=True)): raise ValueError(f'The order {n} is not covered by Miyamoto construction.') m = (q-1) // 2 - C = symmetric_conference_matrix_paley(q + 1) + C = symmetric_conference_matrix(q + 1) neg = [i for i in range(2, m+2) if C[1, i] == -1] pos = [i for i in range(m+2, 2*m+2) if C[1, i] == 1] @@ -3262,7 +3268,7 @@ def true(nam): return M -def symmetric_conference_matrix(n, check=True): +def symmetric_conference_matrix(n, check=True, existence=False): r""" Try to construct a symmetric conference matrix. @@ -3279,6 +3285,8 @@ def symmetric_conference_matrix(n, check=True): - ``check`` -- boolean (default: ``True``); whether to check that output is correct before returning it. As this is expected to be useless, you may want to disable it whenever you want speed. + - ``existence`` -- boolean (default: ``False``); if true, only check that such + a matrix exists. EXAMPLES:: @@ -3299,9 +3307,11 @@ def symmetric_conference_matrix(n, check=True): """ from sage.graphs.strongly_regular_db import strongly_regular_graph as srg try: - m = srg(n-1, (n-2)/2, (n-6)/4, (n-2)/4) + m = srg(n-1, (n-2)/2, (n-6)/4, (n-2)/4, existence=existence) except ValueError: raise + if existence: + return m C = matrix([0]+[1]*(n-1)).stack(matrix([1]*(n-1)).stack(m.seidel_adjacency_matrix()).T) if check: assert (C == C.T and C**2 == (n-1)*I(n)) From 5953b5f13ece4f872c03d72b9fc7227566787490 Mon Sep 17 00:00:00 2001 From: Matteo Cati Date: Sat, 10 Aug 2024 12:14:57 +0200 Subject: [PATCH 2/5] Move conference matrix construction to new function --- src/sage/combinat/matrices/hadamard_matrix.py | 90 ++++++++++++++++++- 1 file changed, 87 insertions(+), 3 deletions(-) diff --git a/src/sage/combinat/matrices/hadamard_matrix.py b/src/sage/combinat/matrices/hadamard_matrix.py index 51fe5f5a600..f340543b7f1 100644 --- a/src/sage/combinat/matrices/hadamard_matrix.py +++ b/src/sage/combinat/matrices/hadamard_matrix.py @@ -306,10 +306,10 @@ def hadamard_matrix_paleyII(n): True """ q = n//2 - 1 - # if not (n % 2 == 0 and is_prime_power(q) and (q % 4 == 1)): - # raise ValueError("The order %s is not covered by the Paley type II construction." % n) + if not (n % 2 == 0 and is_prime_power(q) and (q % 4 == 1)): + raise ValueError("The order %s is not covered by the Paley type II construction." % n) - H = symmetric_conference_matrix(q+1) + H = symmetric_conference_matrix_paley(q+1) tr = { 0: matrix(2, 2, [ 1, -1, -1, -1]), 1: matrix(2, 2, [ 1, 1, 1, -1]), @@ -320,6 +320,85 @@ def hadamard_matrix_paleyII(n): return normalise_hadamard(H) +def hadamard_matrix_from_symmetric_conference_matrix(n, existence=False, check=True): + r"""Construct a Hadamard matrix of order `n` from a symmetric conference matrix + of order `n/2`. + + The construction is described in Theorem 4.3.24 of [IS2006]_. + The symmetric conference matrices are obtained from + :func:`sage.combinat.matrices.hadamard_matrix.symmetric_conference_matrix`. + + INPUT: + + - ``n`` -- integer; the order of the matrix to be constructed + - ``existence`` -- boolean (default: ``False``); if ``True``, only check if + the matrix exists + - ``check`` -- boolean (default: ``True``); if ``True``, check that the matrix + is a Hadamard before returning + + OUTPUT: + + If ``existence=False``, returns the Hadamard matrix of order `n`. It raises + an error if no data is available to construct the matrix of the given order, + or if `n` does not satisfies the constraints. + If ``existence=True``, returns a boolean representing whether the matrix + can be constructed or not. + + EXAMPLES: + + By default the function returns the Hadamard matrix :: + + sage: from sage.combinat.matrices.hadamard_matrix import hadamard_matrix_from_symmetric_conference_matrix + sage: hadamard_matrix_from_symmetric_conference_matrix(20) + 20 x 20 dense matrix over Integer Ring... + + If ``existence`` is set to True, the function returns True if the matrix exists, + False if the conference matrix does not exist, and Unknown if the conference + matrix cannot be constructed yet :: + + sage: hadamard_matrix_from_symmetric_conference_matrix(12, existence=True) + True + + TESTS:: + + sage: from sage.combinat.matrices.hadamard_matrix import is_hadamard_matrix + sage: is_hadamard_matrix(hadamard_matrix_from_symmetric_conference_matrix(60, check=False)) + True + sage: hadamard_matrix_from_symmetric_conference_matrix(64, existence=True) + False + sage: hadamard_matrix_from_symmetric_conference_matrix(4*787, existence=True) + True + sage: hadamard_matrix_from_symmetric_conference_matrix(64) + Traceback (most recent call last): + ... + ValueError: Cannot construct Hadamard matrix of order 64, a symmetric conference matrix of order 32 is not available in sage. + sage: hadamard_matrix_from_symmetric_conference_matrix(14) + Traceback (most recent call last): + ... + ValueError: No Hadamard matrix of order 14 exists. + """ + if n < 0 or n % 4 != 0: + raise ValueError(f'No Hadamard matrix of order {n} exists.') + + m = n//2 + exists = symmetric_conference_matrix(m, existence=True) + + if existence: + return exists + + if not exists: + raise ValueError(f'Cannot construct Hadamard matrix of order {n}, a symmetric conference matrix of order {m} is not available in sage.') + + C = symmetric_conference_matrix(m) + + H = block_matrix([[C + I(m), C - I(m)], + [C - I(m), -C - I(m)]]) + + if check: + assert is_hadamard_matrix(H) + return H + + def hadamard_matrix_miyamoto_construction(n, existence=False, check=True): r""" Construct Hadamard matrix using the Miyamoto construction. @@ -1824,6 +1903,11 @@ def report_name(nam): if existence: return report_name(name) M = regular_symmetric_hadamard_matrix_with_constant_diagonal(n, 1) + elif hadamard_matrix_from_symmetric_conference_matrix(n, existence=True) is True: + name = "Construction from symmetric conference matrix " + name + if existence: + return report_name(name) + M = hadamard_matrix_from_symmetric_conference_matrix(n, check=False) else: if existence: return Unknown From cc3ebd083c9bc9279457caad1a226ecec56889e9 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Mon, 2 Sep 2024 13:17:24 +0100 Subject: [PATCH 3/5] adjust doctest, add matrix of order 4.787 --- src/sage/combinat/matrices/hadamard_matrix.py | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/sage/combinat/matrices/hadamard_matrix.py b/src/sage/combinat/matrices/hadamard_matrix.py index f340543b7f1..14d258ab641 100644 --- a/src/sage/combinat/matrices/hadamard_matrix.py +++ b/src/sage/combinat/matrices/hadamard_matrix.py @@ -282,20 +282,20 @@ def hadamard_matrix_paleyII(n): [ 1 1| 1 1| 1 1| 1 1| 1 1| 1 1] [ 1 -1|-1 1|-1 1|-1 1|-1 1|-1 1] [-----+-----+-----+-----+-----+-----] - [ 1 -1| 1 -1| 1 1|-1 -1|-1 -1| 1 1] - [ 1 1|-1 -1| 1 -1|-1 1|-1 1| 1 -1] + [ 1 -1| 1 -1|-1 -1| 1 1| 1 1|-1 -1] + [ 1 1|-1 -1|-1 1| 1 -1| 1 -1|-1 1] [-----+-----+-----+-----+-----+-----] - [ 1 -1| 1 1| 1 -1| 1 1|-1 -1|-1 -1] - [ 1 1| 1 -1|-1 -1| 1 -1|-1 1|-1 1] + [ 1 -1|-1 -1| 1 -1|-1 -1| 1 1| 1 1] + [ 1 1|-1 1|-1 -1|-1 1| 1 -1| 1 -1] [-----+-----+-----+-----+-----+-----] - [ 1 -1|-1 -1| 1 1| 1 -1| 1 1|-1 -1] - [ 1 1|-1 1| 1 -1|-1 -1| 1 -1|-1 1] + [ 1 -1| 1 1|-1 -1| 1 -1|-1 -1| 1 1] + [ 1 1| 1 -1|-1 1|-1 -1|-1 1| 1 -1] [-----+-----+-----+-----+-----+-----] - [ 1 -1|-1 -1|-1 -1| 1 1| 1 -1| 1 1] - [ 1 1|-1 1|-1 1| 1 -1|-1 -1| 1 -1] + [ 1 -1| 1 1| 1 1|-1 -1| 1 -1|-1 -1] + [ 1 1| 1 -1| 1 -1|-1 1|-1 -1|-1 1] [-----+-----+-----+-----+-----+-----] - [ 1 -1| 1 1|-1 -1|-1 -1| 1 1| 1 -1] - [ 1 1| 1 -1|-1 1|-1 1| 1 -1|-1 -1] + [ 1 -1|-1 -1| 1 1| 1 1|-1 -1| 1 -1] + [ 1 1|-1 1| 1 -1| 1 -1|-1 1|-1 -1] TESTS:: @@ -358,6 +358,8 @@ def hadamard_matrix_from_symmetric_conference_matrix(n, existence=False, check=T sage: hadamard_matrix_from_symmetric_conference_matrix(12, existence=True) True + sage: hadamard_matrix_from_symmetric_conference_matrix(4*787, existence=True) + True TESTS:: From 6878c5154f7b7a2bc04544791eb17d6edd4a3434 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Mon, 2 Sep 2024 14:05:16 +0100 Subject: [PATCH 4/5] correct doctest --- src/sage/combinat/matrices/hadamard_matrix.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/sage/combinat/matrices/hadamard_matrix.py b/src/sage/combinat/matrices/hadamard_matrix.py index 14d258ab641..87d255128c2 100644 --- a/src/sage/combinat/matrices/hadamard_matrix.py +++ b/src/sage/combinat/matrices/hadamard_matrix.py @@ -282,20 +282,20 @@ def hadamard_matrix_paleyII(n): [ 1 1| 1 1| 1 1| 1 1| 1 1| 1 1] [ 1 -1|-1 1|-1 1|-1 1|-1 1|-1 1] [-----+-----+-----+-----+-----+-----] - [ 1 -1| 1 -1|-1 -1| 1 1| 1 1|-1 -1] - [ 1 1|-1 -1|-1 1| 1 -1| 1 -1|-1 1] + [ 1 -1| 1 -1| 1 1|-1 -1|-1 -1| 1 1] + [ 1 1|-1 -1| 1 -1|-1 1|-1 1| 1 -1] [-----+-----+-----+-----+-----+-----] - [ 1 -1|-1 -1| 1 -1|-1 -1| 1 1| 1 1] - [ 1 1|-1 1|-1 -1|-1 1| 1 -1| 1 -1] + [ 1 -1| 1 1| 1 -1| 1 1|-1 -1|-1 -1] + [ 1 1| 1 -1|-1 -1| 1 -1|-1 1|-1 1] [-----+-----+-----+-----+-----+-----] - [ 1 -1| 1 1|-1 -1| 1 -1|-1 -1| 1 1] - [ 1 1| 1 -1|-1 1|-1 -1|-1 1| 1 -1] + [ 1 -1|-1 -1| 1 1| 1 -1| 1 1|-1 -1] + [ 1 1|-1 1| 1 -1|-1 -1| 1 -1|-1 1] [-----+-----+-----+-----+-----+-----] - [ 1 -1| 1 1| 1 1|-1 -1| 1 -1|-1 -1] - [ 1 1| 1 -1| 1 -1|-1 1|-1 -1|-1 1] + [ 1 -1|-1 -1|-1 -1| 1 1| 1 -1| 1 1] + [ 1 1|-1 1|-1 1| 1 -1|-1 -1| 1 -1] [-----+-----+-----+-----+-----+-----] - [ 1 -1|-1 -1| 1 1| 1 1|-1 -1| 1 -1] - [ 1 1|-1 1| 1 -1| 1 -1|-1 1|-1 -1] + [ 1 -1| 1 1|-1 -1|-1 -1| 1 1| 1 -1] + [ 1 1| 1 -1|-1 1|-1 1| 1 -1|-1 -1] TESTS:: From 4d562209ed2488da9ac60604a9ff48324218da18 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Fri, 27 Sep 2024 10:00:13 +0100 Subject: [PATCH 5/5] added newline --- src/sage/combinat/matrices/hadamard_matrix.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/combinat/matrices/hadamard_matrix.py b/src/sage/combinat/matrices/hadamard_matrix.py index 87d255128c2..326eb32843b 100644 --- a/src/sage/combinat/matrices/hadamard_matrix.py +++ b/src/sage/combinat/matrices/hadamard_matrix.py @@ -321,7 +321,8 @@ def hadamard_matrix_paleyII(n): def hadamard_matrix_from_symmetric_conference_matrix(n, existence=False, check=True): - r"""Construct a Hadamard matrix of order `n` from a symmetric conference matrix + r""" + Construct a Hadamard matrix of order `n` from a symmetric conference matrix of order `n/2`. The construction is described in Theorem 4.3.24 of [IS2006]_.