Solucan deliği düğümleriyle en kısa yolu nasıl bulabilirim?


25

örnek

Bu kodla yapmak istediklerimin bir örneği. Yeşil düğümden kırmızı düğüme sorunsuz bir şekilde, hatta A * 'ya kolayca ulaşmak için atlama noktası aramayı kullanabileceğinizi biliyorum. Fakat bunu çözgü ile nasıl hesaplarsınız.

Resimde, mavi yoldan giderken yeşil düğümden kırmızı düğüme geçmenin sadece 8 hamle yaptığını görebilirsiniz. Mavi yol, konumunuzu anında bir mor düğümden diğerine hareket ettirir. Ortada 2 hamle yapan alan, gitmek için hareket etmeniz gereken iki çözgü bölgesi arasındaki bir nokta.

Mavi yola çıkmak açıkça daha hızlı, çünkü sarı yola kadar sadece yarıya (kabaca) ilerlemeniz gerekiyor, fakat bunu programlı olarak nasıl yaparım?

Bu sorunu çözmek amacıyla, kullanabileceğiniz grafiğin etrafında çok sayıda mor "çözgü" olduğunu varsayalım ve her bir mor noktanın nereye çarpacağını ve grafiğin neresinde olduklarını tam olarak biliyoruz.

Bazı mor çözgüler iki yönlüdür ve bazıları değildir, anlam ifade eder, bazen bir çözgü sadece bir taraftan girebilir, ancak çözgü sonrasında geri dönemezsiniz.

Çözümü düşündüm ve yalnızca her çözgü noktasına (tek yönlü noktaları eksi) ve bu noktalar ile bunlara yakın olan noktalar arasındaki farkı kontrol ederek sorunu hesaplayabileceğim sonucuna vardım. .

Programın bir şekilde, ilk sıçramadan yürümek yerine ikinci çözgü almanın daha faydalı olduğunu bulması gerekiyordu. Böylece, 6 nokta hareket ettirmek, sonra çarpmak, sonra geriye kalan 8 adımı yürüyerek (aynı zamanda hiç çözgü kullanmamaktan daha hızlı) hareket ettirmek yerine 6 hamle, sonra iki hamle ikinci çözgüye gider.

EDIT: Mavi yolun 8 yerine 12 hamle yapacağını fark ettim, ancak soru aynı kalıyor.


4
Mavi yol 12 olmamalı mı (son mordan kırmızıya giden ikisi dahil)?
BlueRaja - Danny Pflughoeft 9:17

5
Mavi aslında 12 (7 + 3 + 2) harekettir, hayır mı?
Daniel Jour

Maalesef berbat, teşekkürler çocuklar! @DanielJour and Blue
Jeff smith

Mesafeleri modellemenin "doğru" yolu, topolojiyi kullanmak ve bunu daha yüksek boyutlu bir yüzey olarak modellemektir. Böyle bir cevabın burada uygun olup olmadığını merak ediyorum.
Geeky

Yanıtlar:


49

Çoğu yol bulma algoritması, ızgaralarla değil, grafiklerle tanımlanır. Bir grafikte, diğer iki uzak düğüm arasındaki bağlantı gerçekten bir sorun değildir.

Ancak, sezgisel bilgilerinize dikkat etmeniz gerekiyor. Solucan deliklerinde, iki düğüm arasındaki minimum mesafe artık öklid mesafesi değildir ve mesafe üçgen eşitsizliğini karşılamaz. Böyle bir sezgisel tarama A * için kabul edilemez. Bu nedenle A * 'yı kolayca kullanamazsınız.

Elbette, bir sezgisel kullanmayan Dijkstra gibi yol bulma algoritmaları da işe yarayacaktır. Bu daha geniş kapsamlı bir arama gibi ve solucan deliklerinizi fazladan çaba göstermeden seçecek. Ancak, Dijkstra A * 'dan daha iyi düğümleri iyi bir buluşsal buluşla ziyaret edecek. (Dijkstra, A * 'ya eşittir heuristic(x) = 0.)

Tüm giden solucan deliklerini doğrudan hedefe solucan deliği olarak gören bir buluşsal yöntem kullanırsanız, A * işe yarayacağını düşünüyorum: buluşsal yöntem mesafeyi küçümseyebilir, ancak bunu asla abartmamak gerekir. Yani buluşsal buluş:

def wormhole_heuristic(x):
  return min(euclidean_distance(x, g) for g in [goal, wormholes...])

Çok kesin bir sezgisel buluş için solucan deliği bitiş noktasından hedefe veya bir sonraki solucan deliğine olan mesafeyi (tekrarlı olarak) ekleyebilirsiniz. Bir ön hesaplama olarak, tüm solucan deliklerini ve (iki düğüm arasındaki mesafenin öklid mesafeleri olduğu hedefi içeren, tamamen bağlantılı) alt metinde yol bulma işlemini gerçekleştirebilirsiniz. Solucan deliği sayısı, şebekenizdeki ulaşılabilir hücre sayısından çok daha azsa, bu faydalı olabilir. Yeni buluşsal buluş:

def wormhole_heuristic(x):
  direct = euclidean_distance(x, goal)
  via_wormhole = min(euclidean_distance(x, w) + wormhole_path_distance(w, goal) for w in wormholes)
  return min(direct, via_wormhole)

@Caleth'in yorumlarda belirttiği gibi, bunların hepsi çok ayarlanabilir ve son solucan deliği çıkışı ile hedef arasındaki mesafeyi ekleyerek solucan deliği ağında tam bir yol bulmadan ilk solucan deliği bulgusunu geliştirebiliriz. Hangi solucan deliği çıkışının en son kullanılacağını bilmediğimiz ve aşırıya kaçmamamız gerektiğinden, hedefe en yakın çıkışı varsaymalıyız:

def wormhole_heuristic(x):
  direct = euclidean_distance(x, goal)
  to_next_wormhole = min(euclidean_distance(x, w) for w in wormholes)
  from_last_wormhole = min(euclidean_distance(w.exit, goal) for w in wormholes)
  via_wormhole = to_next_wormhole + from_last_wormhole
  return min(direct, via_wormhole)

10
Dijkstra'nın sadece A * ile olduğunudijkstra_heuristic(x) = 0
Caleth

[* Solucan delikleri, hedef] ile ne demek istediğinizi anlamıyorum, bunu açıklar mısınız?
Jeff Smith,

1
"En yakın solucan deliği çıkışına öklid mesafesi", wormhole_path_distancealtyazı araştırmasından daha ucuz bir tahmindir ve "tüm çıkışlar hedefte" olandan daha düşük bir tahmindir .
Caleth

3
@Caleth kesinlikle! Burada çok fazla ince ayar potansiyeli var, örneğin n = 3 atlayışlarına bakmaya karar verebiliriz. Altyazı araması tüm asiklik solucan deliği atlayışlarının kapatılmasına karşılık gelir. İleriye bakmak için öneriniz n = 1 atlama, temelde sıfır ekstra maliyete sahip olduğu için çok şık :)
09:17

1
Basitlik sarsıntısı için, yalnızca bir solucan deliği (iki düğüm) olduğunu varsayalım, o zaman bu düzlem 1-solucan deliğini simetri ekseni olarak bu iki nokta arasındaki eşitlik çizgisine sahip simetrik bir düzlemi kopyalayarak 2 ayna düzlemine dönüştürebilirsiniz. Şimdi iki uçağınız var, onlara gerçek uçak (solucan deliğini almazsınız) ve hayali uçak (solucan deliğini aldınız) diyelim. Şimdi, Z koordinatını tanıtıyoruz. Bu koordinat, gerçek düzlemdeki her nokta için 0 olacak ve hayali düzlemin her noktası için dist (solucan deliği, nokta) olacaktır. Bundan sonra, 3 boyutlu boşluk için A * uygulayın.
lilezek

5

Koordinatlı bir ızgarada 6 köşeli bir grafiğiniz var:

A ( 0,0)
B ( 4,7)
C ( 7,4)
D (10,4)
E (16,2)
F (16,0)

Bu köşeler üzerinde tam bir grafik oluşturabilir ve MAX( ABS( x1 - x2 ), ABS( y1 - y2 ) )standart kenarlar için maliyetin ve solucan deliklerinin maliyeti için her kenara bir maliyet atayabilirsiniz .

Bu size masrafları verecektir (bir bitişiklik matrisi olarak):

   A  B  C  D  E  F
- -- -- -- -- -- --
A  -  7  7 10 16 16
B  7  -  0  6 12 12
C  7  0  -  3  9  9
D 10  6  3  -  0  6
E 16 12  9  0  -  2
F 16 12  9  6  2  -

Tek yönlü çözgü varsa, yalnızca grafikte (veya bitişik matris) yalnızca o yöne giden ancak tam tersi yönde olmayan kenarlar oluşturun.

Daha sonra kullanabilirsiniz Dijkstra'nın algoritması bir ile öncelik kuyruğuna .

Başlatın Ave öncelik sırasına üzerine her bitişik kenarına itmek:

Biçim: (yol: maliyet)

queue     = [ (A-B : 7), (A-C : 7), (A-D : 10), (A-E : 16), (A-F : 16) ]

Maddeler kuyruğa bastırıldığı için - her bir köşe için minimum maliyeti takip edin ve mevcut minimum maliyetten daha düşük maliyetli olması durumunda yalnızca sıraya giden yolları itin.

min-costs = { A: 0, B: 7, C: 7, D: 10, E: 16, F: 16 }

İlk öğeyi sıradan kaldırın ve maliyeti hala minimum maliyetle aynıysa, bu yol tarafından oluşturulan tüm bileşik yolları ve bitişik kenarlarını öncelik sırasına geri getirin (bileşik yollar mevcut minimumdan daha düşük maliyete sahipse):

Kaldır: (A-B : 7)

  • Dene (A-B-A : 14)- daha yüksek maliyet olarak reddet
  • Dene (A-B-C : 7)- Aynı maliyetle reddet
  • Dene (A-B-D : 13)- daha yüksek maliyet olarak reddet
  • Dene (A-B-E : 19)- daha yüksek maliyet olarak reddet
  • Dene (A-B-F : 19)- daha yüksek maliyet olarak reddet

Kaldır (A-C : 7)

  • Dene (A-C-A : 14)- daha yüksek maliyet olarak reddet
  • Dene (A-C-B : 7)- Aynı maliyetle reddet
  • Dene (A-C-D : 10)- Aynı maliyetle reddet
  • Dene (A-C-E : 16)- Aynı maliyetle reddet
  • Dene (A-C-F : 16)- Aynı maliyetle reddet

Kaldır (A-D : 10)

  • Dene (A-D-A : 20)- daha yüksek maliyet olarak reddet
  • Dene (A-D-B : 16)- daha yüksek maliyet olarak reddet
  • Dene (A-D-C : 13)- daha yüksek maliyet olarak reddet
  • Deneyin (A-D-E : 10)- kuyruğa yerleştirin
  • Dene (A-D-F : 16)- Aynı maliyetle reddet

Şimdi sıra şöyle görünecek:

queue     = [ (A-D-E : 10), (A-E : 16), (A-F : 16) ]
min-costs = { A: 0, B: 7, C: 7, D: 10, E: 10, F: 16 }

Kaldır (A-D-E : 10)

  • Dene (A-D-E-A : 26)- daha yüksek maliyet olarak reddet
  • Dene (A-D-E-B : 22)- daha yüksek maliyet olarak reddet
  • Dene (A-D-E-C : 19)- daha yüksek maliyet olarak reddet
  • Dene (A-D-E-D : 10)- Aynı maliyetle reddet
  • Deneyin (A-D-E-F : 12)- kuyruğa yerleştirin

Sonra sıra:

queue     = [ (A-D-E-F : 12), (A-E : 16), (A-F : 16) ]
min-costs = { A: 0, B: 7, C: 7, D: 10, E: 10, F: 12 }

Kaldır (A-D-E-F : 12), hedef düğüme 12 pahasına ulaştığını bul.

Not: yolları (A-B-C-D-E-F), (A-C-D-E-F)ve (A-D-E-F)tüm 12 aynı minimum maliyeti var.


0

Tüm köşeleri içeren bir matris kurun ve Floyd-Wallenstein-Algoritmasını veya Bellman-Ford-Algoritmasını kullanın. Her ikisi de, tüm noktalar arasında mümkün olan en kısa yolları içeren bir matris ile sonuçlanacaktır. İki nokta bağlayan en kısa yolu bulmak için daha sonra matris boyunca yineleme yapabilirsiniz. (senin problemin asimetrik TSP ile aynı).

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.