Çarpışma tespiti her zaman O (n ^ 2) midir?


14

Fizik motoru, örneğin birbirine yakın olan nesneleri gruplayarak ve tüm nesneler yerine bu grup içindeki çarpışmaları kontrol ederek bu karmaşıklığı azaltabilir mi? (örneğin, uzak nesneler, hızına ve diğer nesnelerden uzaklığına bakarak bir gruptan çıkarılabilir).

Değilse, çarpışma küreler (3B olarak) veya disk (2B'de) için önemsiz mi? Bir çift döngü yapmalı mıyım yoksa bunun yerine bir çift dizisi mi oluşturmalıyım?

EDIT: mermi ve box2d gibi fizik motoru için, çarpışma algılama hala O (N ^ 2)?


12
İki kelime: Uzamsal bölümleme
MichaelHouse


1
Emin ol. Her ikisinin de O (n log (n)) algoritması olan SAP ( Sweep ve Prune ) (diğerleri arasında) uygulamaları olduğuna inanıyorum . Daha fazla bilgi edinmek için "Geniş Faz Çarpışma Tespiti" ni arayın.
MichaelHouse

2
@ Byte56 Sweep ve Prune, yalnızca her test ettiğinizde sıralamanız gerektiğinde O (n günlüğü (n)) karmaşıklığına sahiptir. Nesnelerin sıralı bir listesini tutmak istersiniz ve her eklediğinizde, onu doğru yere O (log (n)) sıralayın, böylece O (log (n) + n) = O (n) elde edersiniz. Nesneler hareket etmeye başladığında çok karmaşıklaşıyor!
MartinTeeVarga

1
@ sm4, hareketler sınırlıysa, o zaman birkaç çeşit kabarcık sıralaması bununla ilgilenebilir (sadece taşınan nesneleri işaretleyin ve sıralanana kadar dizide ileri veya geri hareket ettirin. diğer hareket nesnelerine dikkat edin
mandal ucube

Yanıtlar:


14

Mekansal bölünme her zaman en kötü durumda O (N ^ 2) 'dir ve bilişimdeki karmaşıklık budur.

Ancak doğrusal zaman O (N) 'de çalışan algoritmalar vardır . Hepsi bir çeşit süpürme hattına dayanıyor.

Temel olarak, nesnelerinizin bir koordinatla sıralanması gerekir. Diyelim ki X. Çarpışma tespitinden önce her seferinde sıralama yaparsanız, karmaşıklık O (N * logN) olacaktır. Hile, yalnızca sahneye nesne eklediğinizde ve daha sonra sahnede bir şey değiştiğinde sıralamaktır. Hareket sonrası sıralama önemsiz değildir. Harekete geçen ve hala doğrusal zamanda çalışan bir algoritma için aşağıdaki bağlantılı makaleye bakın .

Sonra soldan sağa doğru süpürürsünüz. Tarama çizginiz bir nesnenin başlangıcından her geçtiğinde, onu geçici bir listeye koyarsınız. Tarama çizginiz nesneden her çıktığında, listeden çıkarırsınız. Çarpışmaları yalnızca bu geçici listenin içinde değerlendirirsiniz.

Saf tarama çizgisi en kötü durumda O (N ^ 2) 'dir (tüm nesnelerin soldan sağa tüm haritayı kaplamasını sağlarsınız), ancak daha akıllı hale getirerek O (N) yapabilirsiniz (aşağıdaki bağlantıya bakın). Gerçekten iyi bir algoritma oldukça karmaşık olacaktır.

Süpürme çizgisinin nasıl çalıştığı basit bir diyagramdır:

Süpürme hattı algoritması

Çizgi soldan sağa doğru gider. Nesneler X koordinatlarına göre sıralanır.

  • Birinci durum: İlk iki nesne kontrol edilir. Nothing Else Matters.
  • İkinci durum: İlk nesne kontrol edildi ve listeden kayboldu. İki ve üç kontrol edilir.
  • Üçüncü örnek: Bu nesne çarpışıyor olsa bile kontrol etmiyoruz.
  • Dördüncü durum: Çünkü bu durumda kontrol ediyoruz!

Bunun gibi algoritmalar O (C * N) = O (N) karmaşıklığına sahiptir.

Kaynak: İki yıllık hesaplamalı geometri dersleri.

Çarpışma tespitinde buna genellikle Sweep ve Prune denir , ancak süpürme hattı algortit ailesi diğer birçok alanda yararlıdır.

Bu sorunun kapsamı dışında olduğunu düşündüğüm, ancak yine de ilginç olduğunu düşündüğüm diğer okumalar: AABB Ekleme ve Çıkarma ile Verimli Büyük Ölçekli Süpürme ve Budama Yöntemleri - Bu makale, eksene hizalanmış sınırlama kutuları (AABB) kullanan gelişmiş bir Süpürme ve Budama algoritması sunar. ) hareketi dikkate alan sıralama ile. Makalede sunulan algoritma doğrusal zamanda çalışır.


Şimdi bunun teoride en iyi algoritma olduğuna dikkat edin . Bu kullanıldığı anlamına gelmez. Uygulamada, uzamsal bölmeli O (N ^ 2) algoritması, tipik durumda (O (N'ye yakın)) daha iyi performans hızına ve bellek için bazı ekstra gereksinimlere sahip olacaktır. Bunun nedeni, O (C * N) C sabitinin çok yüksek olabilmesidir! Genellikle yeterli belleğe sahip olduğumuz ve tipik durumlarda uzayda eşit olarak yayılmış nesneler bulunduğundan - bu algoritma DAHA İYİ performans gösterir. Fakat O (N) asıl sorunun cevabıdır.


box2d / bullet bunu kullanıyor mu?
jokoon

3
"Süpürme ve kurulama" buna normalde fizik denir. Güzel bir şey, simülasyon ilerledikçe sıralamayı güncel tutabilmenizdir. Ayrıca, grafiğinizdeki süpürme çizgisi uygulama açısından biraz kapalıdır (teori için iyi) - sadece kutu başlangıç ​​/ bitişlerini yineleyeceksiniz, bu yüzden sadece gerçek potansiyel çarpışmaları kontrol edersiniz. Doğrudan kullanılmaktansa, daha yetenekli uzamsal bölümleme ağaçları oluşturmak için kullanılan bu yöntemi gördüm.
Sean Middleditch

3
Teknik olarak aslında O (N ^ 2) ikili çarpışmalar olabileceğinden, süpürme ve budamanın her zaman O (N) olduğunu söylemek tamamen doğru değildir . Aksine, algoritmanın çekirdek karmaşıklığı O (N + c) 'dir, burada c algoritma tarafından bulunan çarpışmaların sayısıdır - çok sayıda dışbükey gövde algoritması olduğu gibi çıktıya duyarlıdır . (Referans: en.wikipedia.org/wiki/Output-sensitive_algorithm )
Steven Stadnicki

1
Taleplerinizi bazı yayınlarla veya en azından algoritma adlarıyla desteklemelisiniz.
sam hocevar

1
@SamHocevar Sabit değerlerin ayrıntılı dökümü ile doğrusal zamanda çalışan gerçekten gelişmiş bir Süpürme ve Prune algoritmasına bir bağlantı ekledim. Algoritmaların "Süpürme ve Kurulama" olarak adlandırılması, onunla hiç çalışmadım çünkü benim için yeniydi. Bu algoritmaları harita seçiminde kullandım (diğer nesnelerle 1 nokta çarpışmasıdır), bu yüzden sadece bilgiyi uyguladım.
MartinTeeVarga

8

No Çarpışma tespiti değil , her zaman O (N ^ 2).

Örneğin, 10x10 boyutunda nesnelerle 100x100 alanımız olduğunu varsayalım. Bu alanı 10x10 hücrelerinde bir ızgara ile bölebiliriz.

Her nesne en fazla 4 ızgara hücresinde olabilir (bir bloğa tam olarak sığabilir veya "hücreler arasında" olabilir). Her hücredeki nesnelerin bir listesini tutabiliriz.

Sadece bu hücrelerdeki çarpışmaları kontrol etmemiz gerekiyor. Izgara hücresi başına maksimum sayıda nesne varsa (aynı blokta asla 4'ten fazla nesne yoksa), her nesne için çarpışma algılama O (1) ve tüm nesneler için çarpışma algılama O (N) olur.

O (N ^ 2) karmaşıklığını önlemenin tek yolu bu değildir. Diğer kullanım durumları için daha yeterli olan - genellikle ağaç tabanlı veri yapılarını kullanan başka yöntemler vardır.

Açıkladığım algoritma bir tür Uzay bölümlemesidir , ancak başka uzay bölümleme algoritmaları da vardır. O (N ^ 2) zamansal karmaşıklığını önleyen bazı algoritmalar için bkz . Alan bölümleme veri yapılarının türleri .

Hem Box2D hem de Bullet, kontrol edilen çift sayısını azaltmak için mekanizmaları destekler.

Gönderen kılavuzda , bölüm 4.15:

Bir fizik adımında çarpışma işleme, dar faz ve geniş faza ayrılabilir. Dar fazda, şekil çiftleri arasındaki temas noktalarını hesaplıyoruz. N şeklimiz olduğunu hayal edin. Kaba kuvvet kullanarak, N * N / 2 çiftleri için dar fazı gerçekleştirmemiz gerekir.

B2BroadPhase sınıfı, çift yönetimi için dinamik bir ağaç kullanarak bu yükü azaltır. Bu, dar faz çağrılarının sayısını büyük ölçüde azaltır.

Normalde geniş faz ile doğrudan etkileşime girmezsiniz. Bunun yerine, Box2D dahili olarak geniş bir faz oluşturur ve yönetir. Ayrıca, b2BroadPhase, Box2D'nin simülasyon döngüsü göz önünde bulundurularak tasarlanmıştır, bu nedenle diğer kullanım durumları için uygun değildir.

Gönderen Bullet Wiki :

Sadece çiftlerin tam listesini döndüren naif O (n ^ 2) algoritmasını geliştiren çeşitli geniş fazlı algoritmalar vardır. Bu optimize edilmiş geniş fazlar bazen daha da çarpışmasız çiftleri ortaya çıkarır, ancak bu genel olarak iyileştirilmiş yürütme süreleri ile dengelenir. Farklı performans özelliklerine sahiptirler ve hiçbiri her durumda diğerlerinden daha iyi performans göstermez.

Dinamik AABB Ağacı

Bu, Bullet'teki btDbvtBroadphase tarafından uygulanır.

Adından da anlaşılacağı gibi, bu dinamik bir AABB ağacı . Bu geniş fazın kullanışlı bir özelliği, yapının dünyanın boyutlarına ve içeriğine dinamik olarak uyum sağlamasıdır. Çok iyi optimize edilmiş ve çok iyi bir genel amaçlı geniş faz. Birçok nesnenin hareket halinde olduğu dinamik dünyaları ele alır ve nesne ekleme ve kaldırma SAP'den daha hızlıdır.

Süpürme ve Kurulama (SAP)

Bullet'te bu AxisSweep sınıf aralığıdır. Bu aynı zamanda, önceden bilinen sabit bir dünya boyutu gerektirmesi sınırlaması ile iyi bir genel amaçlı geniş fazdır. Bu geniş faz, çoğu nesnenin hareketinin çok az olduğu veya hiç hareket etmediği tipik dinamik dünyalar için en iyi performansa sahiptir. Hem btAxisSweep3 hem de bt32AxisSweep3, performansı artırmak için her bir eksenin başlangıç ​​ve bitiş noktalarını kayan nokta sayıları yerine tamsayı olarak hesaplar.

Aşağıdaki bağlantı, geniş faza genel bir giriş ve ayrıca Süpürme ve Kurulama algoritmasının bir açıklamasıdır ("Sırala ve Süpür" olarak adlandırılmasına rağmen):

http://www.ziggyware.com/readarticle.php?article_id=128

Ayrıca wikipedia sayfasına bir göz atın:

http://en.wikipedia.org/wiki/Sweep_and_prune


Benzer sorulara ve dış kaynaklara bazı bağlantılar bunu harika bir cevap haline getirecektir.
MichaelHouse

3
Bu yanlış. Hala O (N ^ 2) alıyorsunuz. Çok daha hızlı olacak, N ^ 2/100 gibi bir şey, ama yine de N ^ 2. Bir kanıt olarak, tüm nesnelerin bir hücrede olduğunu düşünün.
MartinTeeVarga

4
@ sm4 Bu, en kötü durum O (N ^ 2) 'dir, bu da tüm nesnelerin bir hücrede olması durumunda olur. Bununla birlikte, bir fizik motorlarında, nesneler tipik olarak değil bir hücre olması. Örneğimde, hiçbir nesne aynı hücreyi 3'ten fazla nesneyle paylaşamaz. Bir fizik motorunda "normal" nesneler için olan budur (ve "normal" ile "sadece bir sensör değil" demek istiyorum).
luiscubal

Bence algoritmanız sadece 4 hücreyi değil, etraftaki 8 hücreyi kontrol etmeyi gerektiriyor.
jokoon

6
@luiscubal Karmaşıklık her zaman "en kötü durum" dur. Teoride "garantili" karmaşıklık arıyorsunuz. Bu, O (N ^ 2) olan quicksort ve O (N * logN) olan birleştirmeortu ile aynıdır. Quicksort gerçek veriler üzerinde daha iyi performans gösterir ve daha az mekansal gereksinime sahiptir. Ancak mergesort daha iyi karmaşıklığı garanti etti. Bir şeyi kanıtlamanız gerekiyorsa, mergesort kullanın. Bir şeyi sıralamanız gerekirse, hızlı sıralama kullanın.
MartinTeeVarga

2

O (N ^ 2), N nesneniz varsa, en kötü durumda N ^ 2 çarpışma hesaplamasıyla neyin çarpıştığını bulmaktır . Diyelim ki 3 nesneniz var. "Kim kimi vuruyor" bulmak için şunları bulmalısınız:

o1 hitting o2?  o1 hitting o3?
o2 hitting o1?  o2 hitting o3?
o3 hitting o1?  o3 hitting o2?

Bu 6 çarpışma kontrolü veya N * (N-1) kontrolü. Asimptotik analizde polinomu ve yaklaşık olarak O (N ^ 2) değerini genişletiriz. 100 nesneniz varsa, bu 100 * 99 olurdu, bu da 100 * 100'e yeterince yakındır.

Örneğin, alanı bir oktree kullanarak bölerseniz, gövdeler arasındaki ortalama karşılaştırma sayısı azalır. Tüm nesnelerin çok küçük bir alanda toplanması mümkünse (parçacıkların aynı alanda toplanabileceği bir tür parçacık akışı simülasyonu yapıyorsanız), O (N ^ 2) hala simülasyondaki noktalar (hangi noktalarda yavaşlama göreceksiniz).

Yani, O'nun (N ^ 2) tüm noktası, sahnedeki diğer tüm bedenleri kontrol eden her bir vücudun doğasından kaynaklanmaktadır. Bu sadece hesaplamanın doğasıdır. Yine de bu kadar ucuza pek çok şey yardımcı olabilir. Bir sahne grafiği bile ( yalnızca aynı odadaki nesneler arasında algılama ), yapılacak çarpışma hesaplamalarının sayısını önemli ölçüde azaltacaktır, ancak yine de O (M ^ 2) olacaktır (burada M, odadaki nesnelerin sayısıdır) çarpışmanın tespit edilmesi). Küresel sınırlayıcı hacimler ilk kontrolü çok hızlı yapar ( if( distance( myCenter, hisCenter ) > (myRadius+hisRadius) ) then MISS), bu nedenle çarpışma algılaması O (N ^ 2) olsa bile sınırlayıcı küre hesaplamaları çok hızlı gerçekleşir.


Kaba kuvvet kontrolünü referans olarak almaya gerek yoktur: akıllı algoritmalara bakılmaksızın, N nesnenin her biri diğer tüm nesnelerle çarpışarak O (N ^ 2) işlerinin işlenmesini gerektiren O (N ^ 2) çarpışmalarını verebilir. İyi algoritmalar ancak daha az çarpışma olduğunda daha iyisini yapabilir.
Lorenzo Gatti
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.