Python 2
Tabloya kadar n = 64
, kaba kuvvet ile optimal doğrulanmış 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
nerede 0
temsil eder -1
. Eğer n
4 ile bölünebilir değildir o zaman m = 1
en uygunudur. Bu kod (veya kodun küçük varyasyonları) kullanılarak oluşturuldu ancak daha yüksek deneme sürümleriyle daha fazla deneme yapıldı 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:]
Yaklaşım, küçükler için fark edilen bir desenden yararlanarak, tepeye tırmanma ile basit rastgele aramadır n
. Desen, optimal için m
, ilk sıranın ikinci yarısının, genellikle ilk yarının (bitsel) negatifinden küçük düzenleme mesafesine sahip olmasıdır. Yukarıdaki kodun sonuçları küçükler için iyidir, n
ancak kaba kuvvet uygulanamaz hale geldikten kısa bir süre sonra bozulmaya başlar; Daha iyi bir yaklaşım görmekten mutlu olurum.
Bazı gözlemler:
- Ne zaman
n
garip, m = 1
birler ve negatif olanların bir tek sayı sıfıra kadar ekleyin çünkü en uygunudur. (Ortogonal nokta ürününün sıfır olduğu anlamına gelir.)
- Ne zaman
n = 4k + 2
, m = 1
en uygunudur, çünkü m >= 2
bizim için tam olarak n/2
ters kayıt yapmamız gerekir {(a1,a2), (a2,a3), ... (a{n-1},an), (an,a1)}
ve tek sayıda ters kayıt yapılması gerekir a1 = -a1
.
- İki sıralı
i
ve j
bir sirkülasyon matrisindeki nokta çarpımı ile belirlenir abs(i-j)
. Örneğin, eğer row1 . row2 = 0
öyleyse row4 . row5 = 0
. Bunun nedeni, nokta ürününün eleman çiftlerinin aynı, sadece döndürülmüş olmasıdır.
- Sonuç olarak, karşılıklı dikliği kontrol etmek için, sadece ilk satıra göre ardışık satırları kontrol etmemiz gerekir.
- Biz bir ikili dizi olarak bir satır temsil ederse
0
yerine -1
, biz bitsel xor alıp birlikte popcount karşılaştırarak iki satır ortogonalliğini kontrol edebilirsiniz n/2
.
- İlk sıranın ilk iki öğesini keyfi olarak düzeltebiliriz, çünkü (1) Bir matrisi olumsuzlamak nokta ürünlerinin sıfıra eşit olup olmadığını etkilemez ve (2) Aynı işaret ve iki bitişik en az iki bitişik öğe olması gerektiğini biliyoruz. farklı işaretli bitişik elemanlar, böylece istenen çifti başında yerleştirmek için döndürebiliriz.
- Bir çözüm , ilk satırı kendine (tekrar tekrar) birleştirerek keyfi
(n0, m0)
olarak otomatik olarak çözümler verecektir . Bunun bir sonucu, 4 ile bölünebilir herhangi bir şey için kolayca elde edebiliriz .(k * n0, m0)
k > 1
m = 4
n
Ne zaman n/2
için sıkı bir üst sınır olduğu varsayımı doğaldır , ancak bunun nasıl kanıtlanacağını bilmiyorum.m
n > 4