Kısıtlanmış veya tahmin edilebilir bir girdiniz varsa durdurma sorununu çözmek mümkün müdür?


18

Durma problemi genel durumda çözülemez. İzin verilen girdileri kısıtlayan tanımlı kurallar bulmak mümkündür ve durdurma sorunu bu özel durum için çözülebilir mi?

Örneğin, döngülere izin vermeyen bir dilin, programın durup durmayacağını söylemek çok kolay olacaktır.

Şu anda çözmeye çalıştığım sorun, programın geçerliliğini kontrol eden bir komut dosyası denetleyicisi yapmaya çalışıyorum. Senaryo yazarlarından tam olarak ne beklediğimi bilirsem durma problemi çözülebilir, bu da çok öngörülebilir girdiler anlamına gelir. Bu tam olarak çözülemezse, bunu çözmek için iyi yaklaşım teknikleri nelerdir?

Yanıtlar:


10

Sezgisel cevap, sınırsız döngüleriniz yoksa ve özyinelemeniz yoksa ve gitmediyseniz, programlarınızın sonlandırılmasıdır. Bu tam olarak doğru değil, fesih yapmamak için başka yollar da var, ancak çoğu pratik vaka için yeterince iyi. Elbette bunun tersi yanlış, bu yapılarda sonlandırılmamış programlara izin vermeyen diller var, ancak sofistike tip sistemler gibi diğer kısıtlamaları kullanıyorlar.

özyineleme

Komut dosyası dillerinde sık karşılaşılan bir kısıtlama, özyinelemeyi dinamik olarak önlemektir: A çağrıları B çağrıları C çağrıları… çağırırsa, A çağrıları yaparsa, yorumlayıcı (veya sizin durumunuzda denetleyici), özyineleme gerçekten sonlanabilse bile bir hata verir veya sinyal verir. İki somut örnek:

  • C önişlemcisi, bir makroyu genişletirken bir makroyu olduğu gibi bırakır. En yaygın kullanım, bir işlevin etrafına sarıcı tanımlamaktır:

    #define f(x) (printf("calling f(%d)\n", (x)), f(x))
    f(3);
    

    Bu,

    (printf("calling f(%d)\n", (3)), f(3))
    

    Karşılıklı özyineleme de ele alınır. Bunun bir sonucu, C ön işlemcisinin her zaman sonlandırılmasıdır, ancak yüksek çalışma zamanı karmaşıklığına sahip makrolar oluşturmak mümkündür.

    #define f0(x) x(x)x(x)
    #define f1(x) f0(f0(x))
    #define f2(x) f1(f1(x))
    #define f3(x) f2(f2(x))
    f3(x)
    
  • Unix kabukları takma adları yinelemeli olarak genişletir, ancak yalnızca zaten genişletilmiş bir takma adla karşılaşana kadar. Yine, birincil amaç benzer şekilde adlandırılmış bir komut için bir takma ad tanımlamaktır.

    alias ls='ls --color'
    alias ll='ls -l'
    

nn

Özyinelemeli çağrıların sona erdiğini kanıtlamak için, bir özyinelemeli çağrıdan diğerine her zaman azalan bir pozitif tamsayı bulmak gibi daha genel teknikler vardır, ancak bunların tespit edilmesi oldukça zordur. Çıkarmak yerine, çoğu zaman doğrulamak zordur.

döngüler

formn

Özellikle, döngüler için (artı koşullu gibi makul dil yapıları), tüm ilkel özyinelemeli işlevleri yazabilir veya tersini yapabilirsiniz. İlkel özyinelemeli işlevleri sözdizimsel olarak tanıyabilirsiniz (belirsiz bir şekilde yazıldıysa), çünkü while while döngüsü veya goto veya özyineleme veya başka bir hile kullanmazlar. İlkel özyinelemeli işlevlerin sona erdirilmesi garanti edilir ve çoğu pratik görev ilkel özyinelemenin ötesine geçmez.


4

Bkz. Terminatör ve AProVe . Buluşsal yöntemlere güvenme eğilimindedirler ve çalıştıkları programların sınıfını açıkça tanımlayıp tanımlamadıklarından emin değilim. Yine de, en son teknoloji olarak kabul edilirler, bu yüzden sizin için iyi bir başlangıç ​​noktası olmalıdırlar.


4

Evet, mümkün olabilir. Bu tür problemleri çözmenin yaygın bir yolu , girişin bir parçası olarak koda bağlı olarak ekstra (monoton) hesaplanamayan bir parametre düşünmektir . Bu parametreye sahip olan sorunun karmaşıklığı ciddi şekilde azaltılabilir.

Parametreyi hesaplayamıyoruz, ancak ele aldığınız giriş örneklerinin küçük parametre değerlerine sahip olduğunu biliyorsanız, küçük bir sayıya düzeltebilir ve algoritmayı kullanabilirsiniz.

Bu ve benzeri hileler, durma ve benzeri problemlerin kararsızlığıyla başa çıkmak için resmi yöntemlerde kullanılır. Ancak karar vermek istediğiniz şey karmaşıksa, algoritmalarınızın karmaşıklığının, algoritmayı bu örneklerde çalıştırmaktan daha iyi olması olası değildir.

Diğer soru ile ilgili olarak, girdileri yeterince kısıtlarsanız, durma problemi kolay olabilir. Örneğin, girdilerin polinom zaman algoritmaları olduğunu biliyorsanız, onlar için durma problemine karar vermek çok önemlidir (çünkü her polinom zaman algoritması durur).

Biçimsel yöntemlerde ortaya çıkan problemler genellikle kararsızdır, pratikte bu problemlerle nasıl başa çıktıklarına dair literatürü kontrol etmek isteyebilirsiniz.


4

Resmi olarak katı bir cevap değil, ama işte gidiyor:

Sonsuza kadar durup durmayacağını belirleme sorunu. Sonlu koleksiyonlarda birer birer veya bir sayı aralığı arasında döngü yapmak sorun yaratmaz. DÜZENLEME: Açıkçası, bu yalnızca yinelenen toplama veya aralığın yinelenen (veya en azından büyümesi yasak olan) değişmesi yasaklanmışsa (örneğin değişmezlik yoluyla) işe yarayacaktır.

Maksimum yığın derinliğine izin vermek veya her yinelemede negatif olmayan bir parametrenin azalmasını zorlamak gibi sonlu yapmak için yapay bir kural ayarlamazsanız özyineleme muhtemelen uygun değildir.

Keyfi gotolar genellikle kötüdür. Geriye-gitlerin sonsuz olabilecek döngülere yol açması muhtemeldir.

Whiles ve do-whiles ifadeleri bir sorundur, çünkü yürütme sırasında değişmesi garanti edilemeyen veya değişmeyen bir koşula bağlıdırlar. Kısıtlamanın olası (ama muhtemelen çok tatmin edici olmayan) bir yolu, mümkün olan en fazla sayıda yineleme sağlamaktır.


2

Senaryo dilinizin bir tanımını ve senaryonun yazarlarından "beklemek" ile ne demek istediğinizi belirtmelisiniz.

Ö(nω)

Aaron R. Bradley, Zohar Manna ve Henny B. Sipma'nın bir polinom programı sınıfı için de benzer bir sonuç var. Ancak AFAIK (burada yanlış olabilirim) çalışma zamanı iki kat daha fazladır (esasen Groebner bazını hesaplamak için gereken süre).

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.