Çok iyi cevaplar var. Tartışmaya katkıda bulunmaya çalışacağım.
Prolog'da bildirimsel, mantıksal programlama konusunda, Richard O'Keefe'nin "The Prolog El Sanatları" adlı harika kitabı var . Verimsiz programlar yazmanıza izin veren bir programlama dili kullanarak verimli programlar yazmakla ilgilidir. Bu kitapta, çeşitli algoritmaların verimli uygulamaları tartışılırken ("Programlama Yöntemleri" bölümünde), yazar aşağıdaki yaklaşımı benimsemiştir:
- sorunu ingilizce olarak tanımlayabilir
- mümkün olduğunca bildirici olan bir çalışma çözümü yazınız; genellikle, bu tam olarak sorunuzda ne var demektir, sadece doğru Prolog
- oradan, uygulamayı daha hızlı hale getirmek için uygulamayı geliştirmek
En aydınlatıcı (benim için) gözlem, yolumdan geçerken bunları yapabildim:
Evet, uygulamanın son hali, yazarın başladığı “bildirici” şartnameden çok daha verimli. Hala çok açıklayıcı, özlü ve anlaşılması kolaydır. Arada olan, nihai çözümün, başlangıç çözümünün kayıtsız olduğu sorunun özelliklerini yakalamasıdır.
Başka bir deyişle, bir çözümü uygularken, sorunla ilgili bilgimizden olabildiğince faydalandık. Karşılaştırmak:
Tüm öğelerin artan düzende olacağı bir listenin permitasyonunu bulun
için:
İki sıralı listeyi birleştirmek sıralı bir listeye neden olur. Zaten sıralanmış olan alt listeler olabileceğinden, bunları uzunluk 1 olan alt listeler yerine başlangıç noktası olarak kullanın.
Küçük bir kenara: Verdiğiniz gibi bir tanım çekici çünkü çok genel. Ancak, permütasyonların bir birleşimsel sorun olduğu gerçeğini bilerek yok saydığı duygusundan kaçamam. Bu zaten bildiğimiz bir şey ! Bu bir eleştiri değil, sadece bir gözlem.
Asıl soruya gelince: nasıl ilerlenir? Bir yolu, bilgisayara bildirdiğimiz sorun hakkında çok fazla bilgi vermektir.
Sorunu gerçekten çözmek için bildiğim en iyi girişim Alexander Stepanov, "Programlamanın Öğeleri" ve "Matematikten Jenerik Programlamaya" ortak yazılan kitaplarda sunulmuştur . Ne yazık ki bu kitaplardaki her şeyi özetleme (hatta tamamen anlama) görevine bağlı değilim. Bununla birlikte, buradaki yaklaşım, girdinin tüm ilgili özelliklerinin önceden bilinmesi şartıyla, verimli (veya hatta optimal) kütüphane algoritmalarını ve veri yapılarını tanımlamaktır. Nihai sonuç:
- Her iyi tanımlanmış dönüşüm, zaten var olan kısıtlamaların (bilinen özellikler) iyileştirilmesidir;
- Mevcut kısıtlamalara dayanarak bilgisayarın hangi dönüşümün optimal olduğuna karar vermesine izin veriyoruz.
Neden henüz tam olarak yaşanmadığına gelince, bilgisayar bilimi gerçekten genç bir alan ve hala çoğunun yeniliğini gerçekten takdir etmekle başa çıkıyoruz.
PS
"Uygulamayı ayrıntılandırmak" derken neyi kastettiğimin tadına varmak için: örneğin, Prolog'da bir listenin son unsurunu elde etmenin kolay sorununu alın. Kanonik bildirimsel çözüm şöyledir:
last(List, Last) :-
append(_, [Last], List).
Burada, bildirimsel anlamı append/3
şudur:
List1AndList2
olduğu birleştirilmesi List1
veList2
İkinci argüman için append/3
sadece bir elementli bir listeye sahip olduğumuz ve ilk argüman dikkate alınmadığı için (alt çizgi), listenin önünü ( List1
bağlamında append/3
) ayıran ve talep eden orijinal listenin bir bölümünü alıyoruz . Geri ( List2
bağlamında append/3
) gerçekten sadece bir element içeren bir liste: yani, bu son element.
SWI-Prolog tarafından sağlanan fiili uygulama , ancak, diyor ki:
last([X|Xs], Last) :-
last_(Xs, X, Last).
last_([], Last, Last).
last_([X|Xs], _, Last) :-
last_(Xs, X, Last).
Bu hala hoş bir şekilde beyan edicidir. Yukarıdan aşağıya doğru okuyun, diyor ki:
Bir listenin son elemanı sadece en az bir elemanın listesi için anlamlıdır. Kuyruğun bir çifti için son eleman ve bir listenin başı, öyleyse: kuyruk, boşken veya boş olmayan kuyruğun sonuncusu.
Bu uygulamanın sağlanmasının nedeni Prolog'un yürütme modelini çevreleyen pratik meseleler üzerinde çalışmaktır . İdeal olarak, hangi uygulamanın kullanıldığı fark yaratmamalıdır. Benzer şekilde şöyle diyebilirdik:
last(List, Last) :-
reverse(List, [Last|_]).
Bir listenin son elemanı, ters çevrilmiş listenin ilk elemanıdır.
Neyin iyi olduğu konusundaki sonuçsuz tartışmaları doldurmak istiyorsanız, bildirimdeki Prolog, Yığın Akışı üzerindeki Prolog etiketindeki bazı soru ve cevapları inceleyin .