Bir algoritmanın Landau notasyonunu (Big O veya Theta notasyonu) bulan programatik olarak?


11

Algoritmalarımın olabildiğince optimize edildiğinden emin olmak için elimle Landau (Big O, Theta ...) gösterimini aramak için kullanıyorum, ancak işlevler gerçekten büyük ve karmaşık hale geldiğinde, yol alıyor elle yapmak için çok fazla zaman. aynı zamanda insan hatalarına da yatkındır.

Codility (kodlama / algo egzersizleri) için biraz zaman geçirdim ve size sunulan çözümünüz için Landau notasyonu vereceğini fark ettim (hem Zaman hem de Bellek kullanımında).

Bunu nasıl yaptığını merak ediyordum ... Nasıl yapardın?

Sözcüksel Analiz veya kodun ayrıştırılmasının yanı sıra başka bir yol var mı?

Bu soru çoğunlukla PHP ve / veya JavaScript ile ilgilidir, ancak herhangi bir dile ve teoriye açığım.


4
Bu yanıtı SO'dan kontrol edin . Aradığın gibi geliyor.
Deco

2
Her bir algoritma için bu sorunu çözen bir program oluşturabilirseniz, "Turing'i çürüten adam" olarak ünleneceksiniz.
user281377

1
Çalışma sürelerine karar vermenin genel olarak imkansız olduğuna dair kanıtlar için buraya ve buraya bakın - oradaki cevaplar aslında istediğinden daha fazlasını kanıtlıyor.
Alex ten Brink

Yanıtlar:


13

Bunu nasıl yaptığını merak ediyordum ... Nasıl yapardın?

Aslında farklı O büyüklükleri için programı çalıştırarak, zaman ve mekan kullanımını ölçerek ve eğrileri sonuçlara yerleştirerek Big O ölçümlerini tahmin ettiklerini hayal ediyorum .

Bu yaklaşımla ilgili sorun , maliyet fonksiyonları N büyüdükçe şekil değiştirmenin yanlış olabilmesidir; örn 1000 N + N^1.5.

Sözcüksel Analiz veya kodun ayrıştırılmasının yanı sıra başka bir yol var mı?

Sözcüksel analiz ve ayrıştırma yeterli değildir. Ayrıca, algoritmanın davranışı hakkında bazı akıl yürütmeler yapmanız gerekir. Ve bunu daha önce bilinmeyen bir algoritma için otomatik olarak yapmak zordur.


6
"bunu daha önce bilinmeyen bir algoritma için otomatik olarak yapmak zordur" - Daha doğrusu: Durdurma Problemini çözmeye eşdeğerdir.
Jörg W Mittag

Hmm ... tam olarak değil. Durdurma Problemini çözmek, daha önce bilinmeyen tüm algoritmalar için bunu yapabilmekle eşdeğerdir .
Stephen C

2
Evet üzgünüm. Bunu bir algoritma için yapmak, sonlandırmayı kanıtlamaya eşdeğerdir (veya daha doğrusu ima eder).
Jörg W Mittag

1
Bunun pratiklikleri şunlardır: 1) bazı algoritmalar için sonlandırmayı kanıtlamak veya çürütmek imkansızdır, ancak 2) çoğu algoritmanın bu teorik engelleri yoktur, ancak 3) teoremdeki son teknoloji , bunu zaten yapabilmek ... nispeten basit durumlar dışında. Bu yüzden bunu farklı bir şekilde yaptıklarını hayal ettiğim ifadem. Ama açıkçası, kodlarına bakmadan bunu gerçekten nasıl yaptıklarından emin olamayız.
Stephen C

3

Kodu analiz etmeden yapamazlar.

Aşağıda yapay karmaşıklık "şişirme / söndürme" örnekleri, sadece program çalışma zamanını ölçmenin Big-O'yu güvenilir bir şekilde tahmin etmek için yeterli olmadığını kanıtlamaktadır.

void lets_trick_runtime(int n) {
   if (n == 10 || n == 25 || n == 118) {
      // unfair speed-up
      do_precalculated_solution_in_constant_time(n);
      return;
   }
   if (n == 11 || n == 26 || n == 119) {
      // unfair slow-down
      do_some_fake_processing_in_n_cube_time(n);
      return;
   }
   // fair solution
   do_general_solution_in_quadratic_time(n);
}

Yukarıdaki için çalışma zamanı tahmini , "adil" ikinci dereceden zaman yerine, nönceden hesaplanmış bir çözümün olduğu değerler için sabit zaman ve unfair slow-downbaşladığında değerler için kübik zaman gibi sahte tahminler vermeye yatkın olacaktır .


Ancak, "haksız" vakaları kontrol ederlerse, yine de en kötü durumun Big-O karmaşıklığını tahmin ettiğini varsayabilirler.
Yam Marcovic

1

Bunun mümkün olmadığını düşünüyorum.

Sabit sayıda farklı giriş boyutuyla bazı testler gerçekleştirirseniz, çok iyi ölçtüğünüz çalışma zamanlarına yaklaşan bir polinomu kolayca hesaplayabilirsiniz. Böylece, olası her program için bir polinom ile sonuçlanırsınız, bu da P = NP(evet!;) Anlamına gelir .

Sembolik manipülasyon ile yapmaya çalışırsanız, sonunda halting problem. Programınızın durup durmayacağına karar veremeyeceğiniz için, hangi çalışma zamanı karmaşıklığına sahip olacağına karar veremezsiniz.

Ancak, daha sonraki yöntemin mümkün olduğu çok özel durumlar olabilir. Ama bu davalar belki o kadar küçük ki, çaba harcanırsa sorgulanabilir.


1
+1, ancak durdurma sorununun nadir görüleceği düşünülse de.
Yam Marcovic

0

Bunu nasıl yaparım? Hemen hemen tüm problemleri çözme şeklimde oturmak ve çözmek istemiyorum . Ben simüle ediyorum.

Birçok sorun için, çeşitli boyutlar kullanarak algoritmanızı birçok kez çalıştırmak ve daha sonra bu sonuçlara bir regresyon eğrisi yerleştirmek yeterli olabilir. Bu, algoritmanızın (eğrinin kesişme noktası) bazı "sabit" genel gider maliyetlerini ve sorun boyutunuz arttıkça nasıl ölçeklendiğini hızlı bir şekilde tanımlar.

Özellikle karmaşık çözümleri yakalamak için biraz müdahaleye ihtiyaç duyulacaktır, ancak özellikle sadece bir top parkı tahmini arıyorsanız, bu şekilde elde edebilmeniz ve tahmininizin gerçek sonuçlarınızdan nasıl farklı olduğunu görebilmeniz ve bunun kabul edilebilir bir yaklaşım.

Bu yöntemle aklımdaki en büyük zayıflık, algoritmanız gerçekten zayıf bir şekilde ölçeklenirse , bu ilk "bir sürü kez çalıştır" adımının çirkinleşeceği yönündedir. Ama açıkçası, durum bu, tek başına geri çekilip şeyleri yeniden düşünmek isteyebileceğinizin bir göstergesi olmalı.


0

Sezgim, bu soruna genel bir çözümün imkansız olduğu; olduğu gibi, algoritmaları çalıştırmadan çalışma süresiyle ilgili a priori gerçekleri iddia etmek (sözcüksel analize başvuruyorsunuz). Bununla birlikte, (muhtemelen büyük) bir algoritma sınıfı için bazı sezgisel algoritmanın mümkün olduğunu (her zaman yaptığımızdan beri), ancak bunu yapmak için genel bir algoritma , iyi olmadığı bilinen Entscheidungsproblem'in çözülmesine eşdeğer olacaktır. mümkün (bkz. Church, Turing, vd.). Düşündüğümden ~% 99.9 eminim…

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.