0.084 saniyede C99 - 3x3 kartı
Düzenleme: Kodumu refactored ve sonuçları üzerinde biraz daha derin analiz yaptım.
Diğer Düzenlemeler: Simetrilerle budama eklendi. Bu 4 algoritma konfigürasyonu yapar: simetrili veya simetrik olmayan X, alfa-beta budama ile veya olmadan
En Uzak Düzenlemeler: Karma tablo kullanarak not ekleme, sonunda imkansızı gerçekleştirme: 3x3'lük bir tahta çözme!
Birincil özellikler:
- Alfa-beta budama ile minimax'ın doğrudan uygulanması
- çok az bellek yönetimi (geçerli hareketlerin dll'sini korur; ağaç aramada dal başına O (1) güncelleme)
- simetrilerle budama ile ikinci dosya. Halen dal başına O (1) güncellemeleri gerçekleştirmektedir (teknik olarak O (S), burada S simetri sayısıdır. Bu kare tahtalar için 7 ve kare olmayan tahtalar için 3'tür)
- üçüncü ve dördüncü dosyalar not ekler. Hashtable'ın boyutu (
#define HASHTABLE_BITWIDTH
) üzerinde kontrolünüz var . Bu boyut duvar sayısından büyük veya ona eşit olduğunda, çarpışma ve O (1) güncellemelerini garanti etmez. Daha küçük hashtable'lar daha fazla çarpışma yaşar ve biraz daha yavaş olur.
-DDEBUG
çıktılar için derleme
Potansiyel iyileştirmeler:
ilk düzenlemede sabitlenen küçük bellek sızıntısını düzelt
Alfa / beta budama 2. düzenlemeye eklendi
erik simetriler 3 düzenlemek ilave (simetri olduğunu not değil o ayrı optimizasyon kalabilmeleri için memoization tarafından ele.)
memoization 4 düzenlemek katma
- şu anda hafızada her duvar için bir gösterge biti kullanılmaktadır. 3x4 kartında 31 duvar vardır, bu nedenle bu yöntem zaman kısıtlamalarından bağımsız olarak 4x4 kartlarını işleyemedi. iyileştirme, X'in en az duvar sayısı kadar büyük olduğu X-bit tamsayılarını taklit etmek olacaktır.
kod
Organizasyon eksikliğinden dolayı, dosya sayısı kontrolden çıktı. Tüm kodlar bu Github Deposuna taşındı . Not düzenlemesine, bir makefile ve test komut dosyası ekledim.
Sonuçlar
Karmaşıklık Hakkında Notlar
Noktalara ve kutulara kaba kuvvet yaklaşımları karmaşıklıkta çok hızlı bir şekilde patlar .
R
Satırlar ve C
sütunlar içeren bir tahta düşünün . Orada R*C
kareler, R*(C+1)
dikey duvarlar ve C*(R+1)
yatay duvarlar. Bu toplam W = 2*R*C + R + C
.
Lembik bizden oyunu minimax ile çözmemizi istediğinden, oyun ağacının yapraklarına geçmemiz gerekiyor. Şimdilik budamayı görmezden gelelim, çünkü önemli olan büyüklük emirleri.
W
İlk hamle için seçenekler var . Bunların her biri için, bir sonraki oyuncu herhangi oynayabilir W-1
vb duvarların da .. Bu da bize bir arama-yer verir SS = W * (W-1) * (W-2) * ... * 1
ya SS = W!
. Faktörler çok büyük, ama bu sadece başlangıç. SS
, arama alanındaki yaprak düğümlerinin sayısıdır . Analizimizle daha ilgili olan, alınması gereken toplam karar sayısıdır (yani ağaçtaki şube sayısı B
). İlk dal tabakasının W
seçenekleri vardır. Bunların her biri için bir sonraki seviye W-1
vb.
B = W + W*(W-1) + W*(W-1)*(W-2) + ... + W!
B = SUM W!/(W-k)!
k=0..W-1
Bazı küçük masa boyutlarına bakalım:
Board Size Walls Leaves (SS) Branches (B)
---------------------------------------------------
1x1 04 24 64
1x2 07 5040 13699
2x2 12 479001600 1302061344
2x3 17 355687428096000 966858672404689
Bu sayılar saçma hale geliyor. En azından kaba kuvvet kodunun neden 2x3'lük bir tahtada sonsuza kadar durduğunu açıklıyorlar. 2x3'lük bir tahtanın arama alanı 2x2'den 742560 kat daha büyüktür . 2x2'nin tamamlanması 20 saniye alırsa, muhafazakar bir ekstrapolasyon 2x3 için 100 günden fazla yürütme süresini tahmin eder . Açıkçası budamak gerekir.
Budama Analizi
Alfa-beta algoritmasını kullanarak çok basit budama ekleyerek başladım. Temel olarak, ideal bir rakibin mevcut fırsatlarına asla vermeyeceğini araştırmayı durdurur. "Hey bak - rakibim her kareyi almama izin verirse çok kazanıyorum!" Diye düşündü.
Diğer anlamları: düzenlemek I ayrıca budama dayalı simetrik panoları ekledi. Bir güne kadar not ekleme yaklaşımını kullanmıyorum, sadece bir gün not ekleme ve bu analizi ayrı tutmak istemem durumunda. Bunun yerine şu şekilde çalışır: Çoğu çizginin ızgara üzerinde başka bir yerde "simetrik bir çifti" vardır. En fazla 7 simetri vardır (yatay, dikey, 180 rotasyon, 90 rotasyon, 270 rotasyon, diyagonal ve diğer diyagonal). Tüm 7 kare tahtalar için geçerlidir, ancak son 4 kare olmayan tahtalar için geçerli değildir. Her duvar, bu simetrilerin her biri için "çifti" ne işaret eder. Eğer bir dönüşe girerken, tahta yatay olarak simetrikse, her yatay çiftten sadece birinin oynanması gerekir.
düzenlemek edit Memoization! Her duvar, bir gösterge biti olarak rahatça ayarladığım benzersiz bir kimlik alır; nth duvarın kimliği var 1 << n
. O zaman, bir tahtanın karması, oynanan tüm duvarların sadece VEYA'sıdır. Bu, her dalda O (1) zamanda güncellenir. Hashtable'ın boyutu a olarak ayarlanır #define
. Tüm testler 2 ^ 12 boyutunda yapıldı, çünkü neden olmasın? Hashtabı indeksleyen bitlerden daha fazla duvar olduğunda (bu durumda 12 bit), en az anlamlı olan 12 maskelenir ve endeks olarak kullanılır. Çarpışmalar, her hashtable dizininde bağlantılı bir listeyle işlenir. Aşağıdaki tablo, karma boyutun performansı nasıl etkilediğine dair hızlı ve kirli analizimdir. Sonsuz RAM'li bir bilgisayarda, masanın boyutunu her zaman duvar sayısına ayarlayacağız. 3x4'lük bir tahta 2 ~ 31 uzunluğunda bir hashtable'a sahip olacaktır. Ne yazık ki bu lüksümüz yok.
Tamam, budamaya geri dön .. Ağacın üstündeki aramayı durdurarak, yapraklara inmeden çok zaman kazanabiliriz . 'Budama Faktörü', ziyaret etmek zorunda olduğumuz tüm şubelerin kesiridir. Kaba kuvvet 1 budama faktörüne sahiptir. Ne kadar küçükse o kadar iyidir.