Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
trac #16237: Merged with 6.2
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanncohen committed May 7, 2014
2 parents 2b1d88b + 5602e14 commit 82ec7cf
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 22 deletions.
2 changes: 1 addition & 1 deletion src/sage/combinat/designs/incidence_structures.py
Expand Up @@ -90,7 +90,7 @@ def IncidenceStructureFromMatrix(M, name=None):
for i in range(b):
B = []
for j in range(v):
if M[i, j] != 0:
if M[j, i] != 0:
B.append(j)
blocks.append(B)
return IncidenceStructure(range(v), blocks, name=nm)
Expand Down
125 changes: 104 additions & 21 deletions src/sage/combinat/matrices/hadamard_matrix.py
Expand Up @@ -26,7 +26,7 @@
This particular case is sometimes called the Sylvester construction.
The Hadamard conjecture (possibly due to Paley) states that a Hadamard
matrix of order `n` exists if and only if `n=2` or `n` is a multiple
matrix of order `n` exists if and only if `n= 1, 2` or `n` is a multiple
of `4`.
The module below implements the Paley constructions (see for example
Expand Down Expand Up @@ -57,77 +57,140 @@
def H1(i, j, p):
"""
Returns the i,j-th entry of the Paley matrix, type I case.
The Paley type I case corresponds to the case `p \cong 3 \bmod{4}`
for a prime `p`.
.. TODO::
This construction holds more generally for prime powers `q`
congruent to `3 \bmod{4}`. We should implement these but we
first need to implement Quadratic character for `GF(q)`.
EXAMPLES::
sage: sage.combinat.matrices.hadamard_matrix.H1(1,2,3)
-1
1
"""
if i == 0:
if i == 0 or j == 0:
return 1
if j == 0:
return -1
# what follows will not be executed for (i, j) = (0, 0).
if i == j:
return 1
return kronecker_symbol(i - j, p)
return -1
return -kronecker_symbol(i - j, p)


def H2(i, j, p):
"""
Returns the i,j-th entry of the Paley matrix, type II case.
The Paley type II case corresponds to the case `p \cong 1 \bmod{4}`
for a prime `p` (see [Hora]_).
.. TODO::
This construction holds more generally for prime powers `q`
congruent to `1 \bmod{4}`. We should implement these but we
first need to implement Quadratic character for `GF(q)`.
EXAMPLES::
sage: sage.combinat.matrices.hadamard_matrix.H1(1,2,5)
sage: sage.combinat.matrices.hadamard_matrix.H2(1,2,5)
1
"""
if i == 0 and j == 0:
return 0
if i == 0 or j == 0:
return 1
if j == 0:
return -1
if i == j:
return 0
return kronecker_symbol(i - j, p)

def normalise_hadamard(H):
"""
Return the normalised Hadamard matrix corresponding to ``H``.
The normalised Hadamard matrix corresponding to a Hadamard matrix `H` is a
matrix whose every entry in the first row and column is +1.
EXAMPLES::
sage: H = sage.combinat.matrices.hadamard_matrix.normalise_hadamard(hadamard_matrix(4))
sage: H == hadamard_matrix(4)
True
"""
Hc1 = H.column(0)
Hr1 = H.row(0)
for i in range(H.ncols()):
if Hc1[i] < 0:
H.rescale_row(i, -1)
for i in range(H.nrows()):
if Hr1[i] < 0:
H.rescale_col(i, -1)
return H

def hadamard_matrix_paleyI(n):
"""
Implements the Paley type I construction.
The Paley type I case corresponds to the case `p \cong 3 \bmod{4}` for a
prime `p` (see [Hora]_).
EXAMPLES::
We note that this method returns a normalised Hadamard matrix ::
sage: sage.combinat.matrices.hadamard_matrix.hadamard_matrix_paleyI(4)
[ 1 -1 -1 -1]
[ 1 1 1 -1]
[ 1 -1 1 1]
[ 1 1 -1 1]
[ 1 1 1 1]
[ 1 -1 -1 1]
[ 1 1 -1 -1]
[ 1 -1 1 -1]
"""
p = n - 1
if not(is_prime(p) and (p % 4 == 3)):
raise ValueError("The order %s is not covered by the Paley type I construction." % n)
return matrix(ZZ, [[H1(i, j, p) for i in range(n)] for j in range(n)])

H = matrix(ZZ, [[H1(i, j, p) for i in range(n)] for j in range(n)])
# normalising H so that first row and column have only +1 entries.
return normalise_hadamard(H)

def hadamard_matrix_paleyII(n):
"""
Implements the Paley type II construction.
The Paley type II case corresponds to the case `p \cong 1 \bmod{4}` for a
prime `p` (see [Hora]_).
EXAMPLES::
sage: sage.combinat.matrices.hadamard_matrix.hadamard_matrix_paleyI(12).det()
sage: sage.combinat.matrices.hadamard_matrix.hadamard_matrix_paleyII(12).det()
2985984
sage: 12^6
2985984
We note that the method returns a normalised Hadamard matrix ::
sage: sage.combinat.matrices.hadamard_matrix.hadamard_matrix_paleyII(12)
[ 1 1 1 1 1 1| 1 1 1 1 1 1]
[ 1 1 1 -1 -1 1|-1 -1 1 -1 -1 1]
[ 1 1 1 1 -1 -1|-1 1 -1 1 -1 -1]
[ 1 -1 1 1 1 -1|-1 -1 1 -1 1 -1]
[ 1 -1 -1 1 1 1|-1 -1 -1 1 -1 1]
[ 1 1 -1 -1 1 1|-1 1 -1 -1 1 -1]
[-----------------+-----------------]
[ 1 -1 -1 -1 -1 -1|-1 1 1 1 1 1]
[ 1 -1 1 -1 -1 1| 1 -1 -1 1 1 -1]
[ 1 1 -1 1 -1 -1| 1 -1 -1 -1 1 1]
[ 1 -1 1 -1 1 -1| 1 1 -1 -1 -1 1]
[ 1 -1 -1 1 -1 1| 1 1 1 -1 -1 -1]
[ 1 1 -1 -1 1 -1| 1 -1 1 1 -1 -1]
"""
N = Integer(n/2)
p = N - 1
if not(is_prime(p) and (p % 4 == 1)):
raise ValueError("The order %s is not covered by the Paley type II construction." % n)
S = matrix(ZZ, [[H2(i, j, p) for i in range(N)] for j in range(N)])
return block_matrix([[S + 1, S - 1], [S - 1, -S - 1]])

H = block_matrix([[S + 1, S - 1], [1 - S, S + 1]])
# normalising H so that first row and column have only +1 entries.
return normalise_hadamard(H)

def hadamard_matrix(n):
"""
Expand All @@ -140,6 +203,8 @@ def hadamard_matrix(n):
2985984
sage: 12^6
2985984
sage: hadamard_matrix(1)
[1]
sage: hadamard_matrix(2)
[ 1 1]
[ 1 -1]
Expand All @@ -154,8 +219,26 @@ def hadamard_matrix(n):
[ 1 -1 -1 1 -1 1 1 -1]
sage: hadamard_matrix(8).det() == 8^4
True
We note that the method `hadamard_matrix()` returns a normalised Hadamard matrix
(the entries in the first row and column are all +1) ::
sage: hadamard_matrix(12)
[ 1 1 1 1 1 1| 1 1 1 1 1 1]
[ 1 1 1 -1 -1 1|-1 -1 1 -1 -1 1]
[ 1 1 1 1 -1 -1|-1 1 -1 1 -1 -1]
[ 1 -1 1 1 1 -1|-1 -1 1 -1 1 -1]
[ 1 -1 -1 1 1 1|-1 -1 -1 1 -1 1]
[ 1 1 -1 -1 1 1|-1 1 -1 -1 1 -1]
[-----------------+-----------------]
[ 1 -1 -1 -1 -1 -1|-1 1 1 1 1 1]
[ 1 -1 1 -1 -1 1| 1 -1 -1 1 1 -1]
[ 1 1 -1 1 -1 -1| 1 -1 -1 -1 1 1]
[ 1 -1 1 -1 1 -1| 1 1 -1 -1 -1 1]
[ 1 -1 -1 1 -1 1| 1 1 1 -1 -1 -1]
[ 1 1 -1 -1 1 -1| 1 -1 1 1 -1 -1]
"""
if not(n % 4 == 0) and (n != 2):
if not(n % 4 == 0) and (n > 2):
raise ValueError("The Hadamard matrix of order %s does not exist" % n)
if n == 2:
return matrix([[1, 1], [1, -1]])
Expand All @@ -181,7 +264,7 @@ def hadamard_matrix(n):

def hadamard_matrix_www(url_file, comments=False):
"""
Pulls file from Sloanes database and returns the corresponding Hadamard
Pulls file from Sloane's database and returns the corresponding Hadamard
matrix as a Sage matrix.
You must input a filename of the form "had.n.xxx.txt" as described
Expand Down

0 comments on commit 82ec7cf

Please sign in to comment.