Nxnxn kübik kafes içinde simetri altında benzersiz olan tüm m noktaları kümelerini oluşturmak için algoritma


10

Oldukça hesaplama açısından karmaşık olacak bir algoritma uyguluyorum ve gereksiz iş yapmadığımdan emin olmak istiyorum.

Bir nxnxn kübik kafes vardır, örneğin n = 2 ise bu (0,0,0), (0,1,0), (1,0,0), (1,1,0), (0, 1,1), (0,0,1), (1,0,1), (1,1,1).

Bu kafesden, m noktalarının tüm setlerini tekrar tekrar üreteceğim, şöyle bir şey:

solve(set_of_points) {
     if set_of_points.size = m, finish

     do some useful computation here

     for each point in lattice not in set_of_points:
         solve(set_of_points + new_point);
}

Bu daha sonra boş bir set_of_points ile başlayarak çağrılabilir.

Sorunun doğası öyle ki aslında m noktalarının her permütasyonuna ihtiyacım yok , sadece küpün doğal simetrileri altında benzersiz olanlara.

Örneğin, 2x2x2'lik bir küp alın ve tüm 1 nokta setlerini istediğimizi varsayalım. Yukarıdaki temel algoritma altında 8 farklı 1 nokta seti vardır.

Bununla birlikte, küpün simetrilerini kullanarak bunu 1 benzersiz 1 nokta setine indirebiliriz, çünkü orijinal 8'in tamamı küpün simetrileri altında eşdeğerdir (hepsi bu durumda 'köşelerdir').

Küp 2x2x2 ve m = 2 ise, temel algoritmada 28 set vardır, ancak bu simetri altında sadece 3'e düşer (örn. {(0,0,0), (1,0,0)}, {(0) , 0,0), (1,1,0)}, {(0,0,0), (1,1,1)})

Açıkçası 3 nokta kümesinde hesaplama yapmak 28'den çok daha iyidir, bu yüzden sorum şu anda oluşturulmuş bir kümeye simetrik olarak eşdeğer nokta kümeleri oluşturmamaya nasıl devam edebilirim? Veya bu mümkün değilse, en azından set sayısını nasıl biraz azaltabilirim.

(Not - m = 1 ise bu nispeten kolaydır - sadece diğer köşelerden daha yakın olan noktaları (0,0,0) seçin, sınırlarda biraz fuding yapın. gerçek bir sorun olmak için)


1
Simetrik olarak eşdeğer olarak hangi işlemleri dahil edersiniz: Merkezden aynalar? Merkezden Nokta Tersleme? Her üç 4 dönüş ekseni merkezden mi?
BmyGuest

Herhangi bir izometri hile yapar
rbennett485

Eğer hala etrafta olsaydın, m puan kümesinde tekrarlamaya izin verilir mi? Örneğin, m = 3 için, {(0,0,0), (1,1,1), (0,0,0)} geçerli bir seçim olarak kabul edilir mi?
blackpen

@blackpen no, 3 benzersiz puan olması gerekiyor
rbennett485

Yanıtlar:


1

Temel konsept:

(1) (0,0,0) noktasını sadece 000 olarak görebiliriz. Kafesteki her nokta şimdi basit bir sıraya girmektedir. İlk nokta 000, sonra 001, sonra 010 011 100 101 110 ve 111'dir. Bu, bunları nokta setine eklemeyi denemenizdir.

(2) Benzer şekilde, {(0,0,0), (0,0,1), (0,1,0)} kümesi sadece 000001010 olarak ve {(0,0,0) kümesi olarak görülebilir , (0,1,0), (0,0,1)} ifadesi 000010001 olarak görülebilir. İki farklı kümenin sırası aynı olamaz ve 000001010'u sayısal veya alfabetik olarak 000010001'den küçük olarak kolayca görüntüleyebilirsiniz. Buna set değeri diyelim. Her olası N noktası kümesinin artık bir set değeri vardır ve şimdi tüm olası N noktaları kümeleri basit bir sıralı listeye girmektedir.

(3) Her izomorfik nokta seti grubunun, en düşük set değerine sahip tam olarak bir üyesi vardır. Aslında "yararlı hesaplama" yaptığımız tekler bunlar.

(4) İşte önemli çalışmalara ihtiyaç duyacağınız kısım. Solve (set_of_points + new_point) komutunu çalıştırmadan önce, herhangi bir izomorfizmin set_of_points + new_point için set değerini düşürüp düşürmeyeceğini görmek istersiniz. Herhangi bir izomorfizma ayarlanan değeri düşürürse, bu izomorfik setin en düşük değer üyesi DEĞİLDİR. Bu yeni nokta üzerinde herhangi bir çalışma yapmayı atlıyoruz. Bu çözümün içinde yapacağımız tüm özyinelemeli çalışmaları da atlıyoruz (set_of_points, candidate_point).

solve(set_of_points,new_point) {
 set_of_points = set_of_points + new_point
 do some useful computation here
 if set_of_points.size = m, compute how many isomophisms exist, apply that multiple, finish
 for(candidate_point = new_point+1 to last_point) { /skips point-permutations for free!/
  if ISOMORPH_TESTS_CANNOT_LOWER_VALUE_OF(set_of_points+candidate_point) {
   solve(set_of_points,candidate_point);
  }
 }
}

1

yukarıdaki cevabın gösterimini alarak.

ilk önce döndürme işlevi tarafından önerilen simetriyi tanımlayalım (yön, zaman_sayısı)

çözüm:

(1) her biri için bayrak = 0 olan tüm permütasyon kümesinin karmasını oluşturun. örneğin n = 2 için, m = 2000.001 = 0 000.010 = 0 000.011 = 0 vb.

(2) başlangıç ​​kümesinden başlayın, örneğin i = 000,001

(3) döndürme işlevini (veya istediğiniz başka bir simetriyi) kullanarak set i'yi her yöne döndürün, döndürme işlevi, dönmenin her bir permütasyonu için 24 kez çağrılmalıdır.

resim açıklamasını buraya girin

açıklama: 1-6 arasında herhangi bir sayı önünüzde olabilir ve her sayı 4 kez döndürülebilir, bu nedenle 6 * 4 = 24

(4) kombinasyondan yinelenen her set için, karma bayrağını 1 olarak ayarlayın (zaten simetrik sete sahiptir)

(5) i'yi bir sonraki sete güncelleyin, örneğin i = 000,010

(6) karma içindeki i işareti zaten işaretliyse, (5) 'e gidin, aksi takdirde (3)' e gidin

tüm karma 1 olarak işaretlendiğinde yapılır.


Bu yaklaşımı oldukça seviyorum, ama orijinal sorun için bu kadar yararlı olmazdı (size ne olduğunu söylemedim!). Bunun hala her nokta kümesinin oluşturulmasını gerektirmesi ve her setle yapmak zorunda olduğum iş çok küçüktü, bu yüzden muhtemelen tasarruf ettiği kadar ek yük ekleyecekti. Her set için çok fazla hesaplama yapan uygulamalar için bu kullanışlı olacaktır
rbennett485

1

Not: Burada sadece ayna simetrileri hakkında düşünüyorum, dönme simetrileri hakkında değil.

Her biri n birim uzunluğunda (hiper) bir d küpümüz olduğunu varsayalım (Rubik küpü d = 3, n = 3 olacaktır ).

Saf bir algoritma n ^ d nokta kombinasyonları oluşturur ve her birinde diğerleriyle simetri çatışması olup olmadığını kontrol eder.

Nokta kombinasyonunu n ^ d bit uzunluğunda vektör olarak temsil edersek, bit vektörünün tüm simetrilerini true ile işaretlemek için bir harita (bit vektörü -> boole) kullanabiliriz . Daha sonra haritada zaten işaretliyse bir kombinasyonu atlayabiliriz.

Bu yaklaşım çok alan verimsizdir: 2 ^ (n ^ d) girişli bir harita alır , yani bu çok bitli bir bitmap. (Rubik küpü için 2 ^ 27 = 128Mbit = 16 Mbayt olacaktır.)

Yalnızca kanonik gösterimleri, yani n ^ d bit imzasız bir sözcük olarak temsil edilirse, en küçük tamsayı değerine sahip bit vektörlerini hatırlayabiliriz . Noktaların yeni bir permütasyonunu ürettiğimizde, tüm simetrilerini üretiriz ve sadece simetriyi en küçük sayısal değere sahip olup olmadığını kontrol ederiz. Bu, sadece 2 ^ n bit (Rubik küpü için sadece 1 bayt) ile bir harita depolamamıza izin verecektir , çünkü 2 ^ d simetrilerimiz var. Her adımda bu 2 ^ d simetrileri üretmemizi sağlar, bu yüzden O (2 ^ (d ^ n + d)) = O (2 ^ (d ^ n) * 2 ^ d) zaman harcarız . Hala fakir.

Bu fikri bir önceki paragraftan 1 boyutlu duruma uygulayabiliriz. D uzunluğundaki bir vektördeki tüm kombinasyonları oluşturmak için , tüm s'den başlayarak, bir ikili sayı d bit uzunluğunu artırabiliriz 0. Vektörümüzü iki d / 2- uzun segmente bölelim, örneğin sol ve sağ. 1Sol segmentteki her bit için sadece 1sağ bölümün simetrik konumunda biti olan kombinasyonları görmemiz gerektiğini fark edebiliriz . Aksi takdirde biz zaten simetrik bir kombinasyon önce, bit pozisyonları takas edildiğinde oluşturulan olurdu ve 0önce gelen 1. Bu şekilde, sağ yarıdaki (r) her bit konumu ve sol yarıdaki simetrik konum için(l) sadece 3 kombinasyon üretmemiz gerekir: (l = 0, r = 0); (l = l, r = l); (l = l, r = 0) . Bu nedenle sadece üretmek gerekir 2 ^ (d / 2) uzunluğu, bir vektörün permütasyon d her permütasyon için 3 kombinasyonları, sonuçta.

D boyutlu bir küp n ^ (d-1) vektörlerinden oluşturulabilir. Yukarıdaki hile bize saf yaklaşımdan daha ucuz vektörler veriyor. Bir küp oluşturmak için O (n ^ (d-1) * 2 ^ (d / 2)) süresine ihtiyacımız var.

Küpe 1 boyutlu vektörlerimizin boyutu boyunca bakarsak, bu boyut boyunca simetriyi kontrol etmek zorunda olmadığımızı görebiliriz: küpleri oluştururken, dahil olan her vektör için simetrileri ortadan kaldırırız.

Biz bakarsak Şimdi karşısında bu boyutta, aynı numarayı yeniden kullanabilirsiniz.

Karşıdan karşıya baktığımızda, örneğin belirli bir düzlem yapan vektörlerin ilk parçalarına bakıyoruz. Bu bitler 1 boyutlu bir bit vektörünü temsil eder. Bitlerinin çoğu kombinasyonunu yukarıda açıklandığı gibi simetri nedenlerinden çıkarabiliriz. Dolayısıyla, bir küpün belirli bir 1-b vektörünü (örneğin en solda en üstte) seçersek, belirli bir bitin değerine bağlı olarak aynı düzlemin (ör. Üst) birçok vektörünü elimine edebiliriz. Böylece, düzlem üzerinde ayna-simetrik bir pozisyondaki bir vektör için, tüm kombinasyonların bu bit setine (veya unset) sahip olmasını sağlamaktan kaçınabiliriz, böylece belirli bir düzlem için üretmemiz gereken vektörlerin sayısı büyük ölçüde azalır. Elimine edilen her bit, aynadan yansıtılan pozisyondaki olası vektörlerin sayısını yarıya indirir. Bu bize her boyut boyunca simetrik muadili olmayan bir dizi uçak verir.

Bu hile, üçüncü bir boyutta aşağıdaki düzlemlerin permütasyonlarının oluşumunu daha da sınırlamak için uygulanabilir.

Tam bir algoritma olmasa da, umarım bu yardımcı olur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.