def regular_symmetric_hadamard_matrix_with_constant_diagonal(n,e,existence=False): r""" Return a Regular Symmetric Hadamard Matrix with Constant Diagonal. A Hadamard matrix is said to be *regular* if its rows all sum to the same value. For `\epsilon\in\{-1,+1\}`, we say that `M` is a `(n,\epsilon)-RSHCD` if `M` is a regular symmetric Hadamard matrix with constant diagonal `\delta\in\{-1,+1\}` and row sums all equal to `\delta \epsilon \sqrt(n)`. For more information, see [HX10]_ or 10.5.1 in [BH12]_. For the case `n=324`, see :func:`RSHCD_324` and [CP16]_. INPUT: - ``n`` (integer) -- side of the matrix - ``e`` -- one of `-1` or `+1`, equal to the value of `\epsilon` EXAMPLES:: sage: from sage.combinat.matrices.hadamard_matrix import regular_symmetric_hadamard_matrix_with_constant_diagonal sage: regular_symmetric_hadamard_matrix_with_constant_diagonal(4,1) [ 1 1 1 -1] [ 1 1 -1 1] [ 1 -1 1 1] [-1 1 1 1] sage: regular_symmetric_hadamard_matrix_with_constant_diagonal(4,-1) [ 1 -1 -1 -1] [-1 1 -1 -1] [-1 -1 1 -1] [-1 -1 -1 1] Other hardcoded values:: sage: for n,e in [(36,1),(36,-1),(100,1),(100,-1),(196, 1)]: ....: print regular_symmetric_hadamard_matrix_with_constant_diagonal(n,e) 36 x 36 dense matrix over Integer Ring 36 x 36 dense matrix over Integer Ring 100 x 100 dense matrix over Integer Ring 100 x 100 dense matrix over Integer Ring 196 x 196 dense matrix over Integer Ring sage: for n,e in [(324,1),(324,-1)]: # not tested - long time, tested in RSHCD_324 ....: print regular_symmetric_hadamard_matrix_with_constant_diagonal(n,e) # not tested - long time 324 x 324 dense matrix over Integer Ring 324 x 324 dense matrix over Integer Ring From two close prime powers:: sage: print regular_symmetric_hadamard_matrix_with_constant_diagonal(64,-1) 64 x 64 dense matrix over Integer Ring Recursive construction:: sage: print regular_symmetric_hadamard_matrix_with_constant_diagonal(144,-1) 144 x 144 dense matrix over Integer Ring REFERENCE: .. [BH12] \A. Brouwer and W. Haemers, Spectra of graphs, Springer, 2012, http://homepages.cwi.nl/~aeb/math/ipm/ipm.pdf .. [HX10] \W. Haemers and Q. Xiang, Strongly regular graphs with parameters `(4m^4,2m^4+m^2,m^4+m^2,m^4+m^2)` exist for all `m>1`, European Journal of Combinatorics, Volume 31, Issue 6, August 2010, Pages 1553-1559, http://dx.doi.org/10.1016/j.ejc.2009.07.009. """ if existence and (n,e) in _rshcd_cache: return _rshcd_cache[n,e] from sage.graphs.strongly_regular_db import strongly_regular_graph def true(): _rshcd_cache[n,e] = True return True M = None if abs(e) != 1: raise ValueError if n<0: if existence: return False raise ValueError elif n == 4: if existence: return true() if e == 1: M = J(4)-2*matrix(4,[[int(i+j == 3) for i in range(4)] for j in range(4)]) else: M = -J(4)+2*I(4) elif n == 36: if existence: return true() if e == 1: M = strongly_regular_graph(36, 15, 6, 6).adjacency_matrix() M = J(36) - 2*M else: M = strongly_regular_graph(36,14,4,6).adjacency_matrix() M = -J(36) + 2*M + 2*I(36) elif n == 100: if existence: return true() if e == -1: M = strongly_regular_graph(100,44,18,20).adjacency_matrix() M = 2*M - J(100) + 2*I(100) else: M = strongly_regular_graph(100,45,20,20).adjacency_matrix() M = J(100) - 2*M elif n == 196 and e == 1: if existence: return true() M = strongly_regular_graph(196,91,42,42).adjacency_matrix() M = J(196) - 2*M elif n == 324: if existence: return true() M = RSHCD_324(e) elif ( e == 1 and n%16 == 0 and is_square(n) and is_prime_power(sqrt(n)-1) and is_prime_power(sqrt(n)+1)): if existence: return true() M = -rshcd_from_close_prime_powers(int(sqrt(n))) # Recursive construction: the kronecker product of two RSHCD is a RSHCD else: from itertools import product for n1,e1 in product(divisors(n)[1:-1],[-1,1]): e2 = e1*e n2 = n//n1 if (regular_symmetric_hadamard_matrix_with_constant_diagonal(n1,e1,existence=True) and regular_symmetric_hadamard_matrix_with_constant_diagonal(n2,e2,existence=True)): if existence: return true() M1 = regular_symmetric_hadamard_matrix_with_constant_diagonal(n1,e1) M2 = regular_symmetric_hadamard_matrix_with_constant_diagonal(n2,e2) M = M1.tensor_product(M2) break if M is None: from sage.misc.unknown import Unknown _rshcd_cache[n,e] = Unknown if existence: return Unknown raise ValueError("I do not know how to build a {}-RSHCD".format((n,e))) assert M*M.transpose() == n*I(n) assert set(map(sum,M)) == {e*sqrt(n)} return M
def regular_symmetric_hadamard_matrix_with_constant_diagonal( n, e, existence=False): r""" Return a Regular Symmetric Hadamard Matrix with Constant Diagonal. A Hadamard matrix is said to be *regular* if its rows all sum to the same value. For `\epsilon\in\{-1,+1\}`, we say that `M` is a `(n,\epsilon)-RSHCD` if `M` is a regular symmetric Hadamard matrix with constant diagonal `\delta\in\{-1,+1\}` and row sums all equal to `\delta \epsilon \sqrt(n)`. For more information, see [HX10]_ or 10.5.1 in [BH12]_. For the case `n=324`, see :func:`RSHCD_324` and [CP16]_. INPUT: - ``n`` (integer) -- side of the matrix - ``e`` -- one of `-1` or `+1`, equal to the value of `\epsilon` EXAMPLES:: sage: from sage.combinat.matrices.hadamard_matrix import regular_symmetric_hadamard_matrix_with_constant_diagonal sage: regular_symmetric_hadamard_matrix_with_constant_diagonal(4,1) [ 1 1 1 -1] [ 1 1 -1 1] [ 1 -1 1 1] [-1 1 1 1] sage: regular_symmetric_hadamard_matrix_with_constant_diagonal(4,-1) [ 1 -1 -1 -1] [-1 1 -1 -1] [-1 -1 1 -1] [-1 -1 -1 1] Other hardcoded values:: sage: for n,e in [(36,1),(36,-1),(100,1),(100,-1),(196, 1)]: # long time ....: print(repr(regular_symmetric_hadamard_matrix_with_constant_diagonal(n,e))) 36 x 36 dense matrix over Integer Ring 36 x 36 dense matrix over Integer Ring 100 x 100 dense matrix over Integer Ring 100 x 100 dense matrix over Integer Ring 196 x 196 dense matrix over Integer Ring sage: for n,e in [(324,1),(324,-1)]: # not tested - long time, tested in RSHCD_324 ....: print(repr(regular_symmetric_hadamard_matrix_with_constant_diagonal(n,e))) 324 x 324 dense matrix over Integer Ring 324 x 324 dense matrix over Integer Ring From two close prime powers:: sage: regular_symmetric_hadamard_matrix_with_constant_diagonal(64,-1) 64 x 64 dense matrix over Integer Ring (use the '.str()' method to see the entries) From a prime power and a conference matrix:: sage: regular_symmetric_hadamard_matrix_with_constant_diagonal(676,1) # long time 676 x 676 dense matrix over Integer Ring (use the '.str()' method to see the entries) Recursive construction:: sage: regular_symmetric_hadamard_matrix_with_constant_diagonal(144,-1) 144 x 144 dense matrix over Integer Ring (use the '.str()' method to see the entries) REFERENCE: .. [BH12] \A. Brouwer and W. Haemers, Spectra of graphs, Springer, 2012, http://homepages.cwi.nl/~aeb/math/ipm/ipm.pdf .. [HX10] \W. Haemers and Q. Xiang, Strongly regular graphs with parameters `(4m^4,2m^4+m^2,m^4+m^2,m^4+m^2)` exist for all `m>1`, European Journal of Combinatorics, Volume 31, Issue 6, August 2010, Pages 1553-1559, :doi:`10.1016/j.ejc.2009.07.009` """ if existence and (n, e) in _rshcd_cache: return _rshcd_cache[n, e] from sage.graphs.strongly_regular_db import strongly_regular_graph def true(): _rshcd_cache[n, e] = True return True M = None if abs(e) != 1: raise ValueError sqn = None if is_square(n): sqn = int(sqrt(n)) if n < 0: if existence: return False raise ValueError elif n == 4: if existence: return true() if e == 1: M = J(4) - 2 * matrix(4, [[int(i + j == 3) for i in range(4)] for j in range(4)]) else: M = -J(4) + 2 * I(4) elif n == 36: if existence: return true() if e == 1: M = strongly_regular_graph(36, 15, 6, 6).adjacency_matrix() M = J(36) - 2 * M else: M = strongly_regular_graph(36, 14, 4, 6).adjacency_matrix() M = -J(36) + 2 * M + 2 * I(36) elif n == 100: if existence: return true() if e == -1: M = strongly_regular_graph(100, 44, 18, 20).adjacency_matrix() M = 2 * M - J(100) + 2 * I(100) else: M = strongly_regular_graph(100, 45, 20, 20).adjacency_matrix() M = J(100) - 2 * M elif n == 196 and e == 1: if existence: return true() M = strongly_regular_graph(196, 91, 42, 42).adjacency_matrix() M = J(196) - 2 * M elif n == 324: if existence: return true() M = RSHCD_324(e) elif (e == 1 and n % 16 == 0 and not sqn is None and is_prime_power(sqn - 1) and is_prime_power(sqn + 1)): if existence: return true() M = -rshcd_from_close_prime_powers(sqn) elif (e == 1 and not sqn is None and sqn % 4 == 2 and True == strongly_regular_graph(sqn - 1, (sqn - 2) // 2, (sqn - 6) // 4, existence=True) and is_prime_power(ZZ(sqn + 1))): if existence: return true() M = rshcd_from_prime_power_and_conference_matrix(sqn + 1) # Recursive construction: the kronecker product of two RSHCD is a RSHCD else: from itertools import product for n1, e1 in product(divisors(n)[1:-1], [-1, 1]): e2 = e1 * e n2 = n // n1 if (regular_symmetric_hadamard_matrix_with_constant_diagonal( n1, e1, existence=True) and regular_symmetric_hadamard_matrix_with_constant_diagonal( n2, e2, existence=True)): if existence: return true() M1 = regular_symmetric_hadamard_matrix_with_constant_diagonal( n1, e1) M2 = regular_symmetric_hadamard_matrix_with_constant_diagonal( n2, e2) M = M1.tensor_product(M2) break if M is None: from sage.misc.unknown import Unknown _rshcd_cache[n, e] = Unknown if existence: return Unknown raise ValueError("I do not know how to build a {}-RSHCD".format( (n, e))) assert M * M.transpose() == n * I(n) assert set(map(sum, M)) == {ZZ(e * sqn)} return M