Python 2
Table jusqu'à n = 64, vérifié optimal avec force brute jusqu'à n = 32:
4 4 0001
8 4 00010001
12 6 000001010011
16 8 0000010011101011
20 10 00010001011110011010
24 12 000101001000111110110111
28 14 0001011000010011101011111011
32 14 00001101000111011101101011110010
36 18 001000101001000111110011010110111000
40 20 0010101110001101101111110100011100100100
44 18 00010000011100100011110110110101011101101111
48 24 001011011001010111111001110000100110101000000110
52 26 0011010111000100111011011111001010001110100001001000
56 28 00100111111101010110001100001101100000001010100111001011
60 30 000001101101100011100101011101111110010010111100011010100010
64 32 0001100011110101111111010010011011100111000010101000001011011001
où 0représente -1. Si nn'est pas divisible par 4, alors m = 1est optimal. Généré à l'aide de ce code (ou de petites variantes de celui-ci) mais avec plus d'essais pour plus n:
from random import *
seed(10)
trials=10000
def calcm(x,n):
m=1
y=x
while 1:
y=((y&1)<<(n-1))|(y>>1)
if bin(x^y).count('1')!=n/2:
return m
m+=1
def hillclimb(x,n,ns):
bestm=calcm(x,n)
while 1:
cands=[]
for pos in ns:
xx=x^(1<<pos)
m=calcm(xx,n)
if m>bestm:
bestm=m
cands=[xx]
elif cands and m==bestm:
cands+=[xx]
if not cands:
break
x=choice(cands)
return x,bestm
def approx(n):
if n<10: return brute(n)
bestm=1
bestx=0
for trial in xrange(1,trials+1):
if not trial&16383:
print bestm,bin((1<<n)|bestx)[3:]
if not trial&1:
x=randint(0,(1<<(n/2-2))-1)
x=(x<<(n/2)) | (((1<<(n/2))-1)^x)
ns=range(n/2-2)
if not trial&7:
adj=randint(1,5)
x^=((1<<adj)-1)<<randint(0,n/2-adj)
else:
x=randint(0,(1<<(n-2))-1)
ns=range(n-2)
x,m=hillclimb(x,n,ns)
if m>bestm:
bestm=m
bestx=x
return bestm,bestx
def brute(n):
bestm=1
bestx=0
for x in xrange(1<<(n-2)):
m=calcm(x,n)
if m>bestm:
bestm=m
bestx=x
return bestm,bestx
for n in xrange(4,101,4):
m,x=approx(n)
print n,m,bin((1<<n)|x)[3:]
L'approche est une simple recherche aléatoire avec escalade, profitant d'un schéma remarqué pour les petits n. Le motif est que pour une optimisation m, la seconde moitié de la première ligne a souvent une petite distance d'édition par rapport à la négation (au niveau du bit) de la première moitié. Les résultats pour le code ci-dessus sont bons pour les petits nmais commencent à se détériorer peu de temps après que la force brute soit devenue impossible; Je serais heureux de voir une meilleure approche.
Quelques observations:
- Quand
nest impair, m = 1est optimal car un nombre impair de uns et de négatifs ne peut pas s'additionner à zéro. (Orthogonal signifie que le produit scalaire est nul.)
- Quand
n = 4k + 2, m = 1est optimal car pour que m >= 2nous ayons besoin d'avoir exactement des n/2inversions de signe parmi {(a1,a2), (a2,a3), ... (a{n-1},an), (an,a1)}, et un nombre impair d'inversion de signe impliquerait a1 = -a1.
- Le produit scalaire de deux rangées
iet jdans une matrice circulante est déterminé par abs(i-j). Par exemple, si row1 . row2 = 0alors row4 . row5 = 0. C'est parce que les paires d'éléments pour le produit scalaire sont les mêmes, juste tournées.
- Par conséquent, pour vérifier l'orthogonalité mutuelle, il suffit de comparer les lignes successives à la première ligne.
- Si nous représentons une ligne comme une chaîne binaire avec
0à la place de -1, nous pouvons vérifier l'orthogonalité de deux lignes en prenant xor au niveau du bit et en comparant le popcount avec n/2.
- Nous pouvons fixer arbitrairement les deux premiers éléments de la première ligne, car (1) la négation d'une matrice n'affecte pas si les produits scalaires sont égaux à zéro, et (2) nous savons qu'il doit y avoir au moins deux éléments adjacents avec le même signe et deux éléments adjacents avec signe différent, afin que nous puissions tourner pour placer la paire souhaitée au début.
- Une solution
(n0, m0)donnera automatiquement des solutions (k * n0, m0)arbitraires k > 1, en concaténant (à plusieurs reprises) la première ligne à elle-même. Une conséquence est que l'on peut facilement obtenir m = 4pour tout ndivisible par 4.
Il est naturel de conjecturer que n/2c'est une limite supérieure stricte pour mquand n > 4, mais je ne sais pas comment cela serait prouvé.