Apa perbedaan teknis utama antara Prolog dan miniKanren, sehubungan dengan pemrograman logika? [Tutup]


124

Ketika saya ingin membaca tentang logika pemrograman, saya selalu menemukan dua cara "utama" untuk melakukannya saat ini:

  • miniKanren , sebuah bahasa mini yang diperkenalkan di The Reasoned Schemer dan populer saat ini karena core.logic .
  • Prolog , bahasa pemrograman logika "besar" pertama.

Yang saya minati sekarang: Apa perbedaan teknis utama di antara keduanya? Apakah mereka sangat mirip dalam pendekatan dan implementasi, atau apakah mereka mengambil pendekatan yang sama sekali berbeda untuk pemrograman logika? Dari cabang matematika manakah mereka berasal, dan apa dasar teoretisnya?


3
Sedih melihat pertanyaan ini ditutup. Seperti yang ditunjukkan oleh jawaban yang sangat meyakinkan dan jumlah suara positif yang besar, ini adalah pertanyaan yang sangat berguna. Saya memilih untuk membuka kembali ....
nealmcb

Pertanyaan @nealmcb yang dulunya sesuai topik dengan banyak suara positif mungkin tidak lagi, jumlah suara positif tidak menentukan valid atau tidaknya.
Tiago Martins Peres 李大仁

Jawaban:


281

Pertama, izinkan saya memuji Anda atas ikon pw0n1e Anda yang bagus.

Ini adalah pertanyaan yang sulit untuk dijawab, terutama karena ada begitu banyak varian dari miniKanren dan Prolog. miniKanren dan Prolog sebenarnya adalah rumpun bahasa, yang membuatnya sulit untuk membandingkan fitur-fiturnya, atau bahkan bagaimana keduanya digunakan dalam praktik. Karena itu, harap perhatikan semua yang akan saya katakan dengan hati-hati: jika saya mengatakan bahwa Prolog menggunakan pencarian pertama yang mendalam, ketahuilah bahwa banyak implementasi Prolog mendukung strategi pencarian lain, dan bahwa strategi pencarian alternatif juga dapat dikodekan di meta tingkat penerjemah. Meski begitu, miniKanren dan Prolog memiliki filosofi desain yang berbeda, dan membuat pertukaran yang berbeda.

Prolog adalah salah satu dari dua bahasa klasik untuk pemrograman kecerdasan buatan simbolik (bahasa klasik lainnya adalah Lisp). Prolog unggul dalam mengimplementasikan sistem berbasis aturan simbolik di mana pengetahuan deklaratif dikodekan dalam logika orde pertama. Bahasa ini dioptimalkan untuk ekspresif dan efisiensi untuk jenis aplikasi ini, terkadang dengan mengorbankan kemurnian logis. Misalnya, secara default Prolog tidak menggunakan "pemeriksaan terjadi" dalam penyatuan. Dari sudut pandang matematika / logika, versi penyatuan ini salah. Namun, pemeriksaan terjadi mahal, dan dalam banyak kasus kurangnya pemeriksaan terjadi tidak menjadi masalah. Ini adalah keputusan desain yang sangat pragmatis, seperti penggunaan pencarian mendalam-pertama Prolog, dan penggunaan cut (!) untuk mengontrol kemunduran. Saya yakin keputusan ini mutlak diperlukan saat menjalankan perangkat keras tahun 1970-an, dan saat ini sangat berguna saat menangani masalah besar, dan saat menangani ruang pencarian yang besar (seringkali tak terbatas!).

Prolog mendukung banyak fitur "ekstra-logis" atau "non-logis", termasuk pemotongan, assertdan retract, proyeksi variabel untuk penggunaan aritmatikais, Dan seterusnya. Banyak dari fitur ini memudahkan untuk mengekspresikan aliran kontrol yang kompleks, dan untuk memanipulasi database fakta global Prolog. Salah satu fitur yang sangat menarik dari Prolog adalah kode Prolog itu sendiri disimpan dalam basis data fakta global, dan dapat ditanyakan pada saat dijalankan. Ini membuatnya mudah untuk menulis meta-interpreter yang mengubah perilaku kode Prolog di bawah interpretasi. Misalnya, dimungkinkan untuk menyandikan pencarian luas-pertama di Prolog menggunakan meta-interpreter yang mengubah urutan pencarian. Ini adalah teknik yang sangat kuat yang tidak dikenal di luar dunia Prolog. 'The Art of Prolog' menjelaskan teknik ini secara rinci.

Upaya luar biasa telah dilakukan untuk meningkatkan implementasi Prolog, yang sebagian besar didasarkan pada Warren Abstract Machine (WAM). WAM menggunakan model efek samping di mana nilai-nilai secara destruktif ditetapkan ke variabel logika, dengan efek samping ini dibatalkan saat dilacak kembali. Banyak fitur yang dapat ditambahkan ke Prolog dengan memperluas instruksi WAM. Satu kelemahan dari pendekatan ini adalah bahwa makalah implementasi Prolog mungkin sulit dibaca tanpa pemahaman yang kuat tentang WAM. Di sisi lain, pelaksana Prolog memiliki model yang sama untuk membahas masalah implementasi. Telah ada banyak penelitian dalam Prolog paralel, yang berpuncak pada Andorra Prolog pada tahun 1990-an. Setidaknya beberapa dari ide ini terus hidup di Ciao Prolog. (Ciao Prolog penuh dengan ide menarik, banyak di antaranya jauh melampaui standar Prolog.)

Prolog memiliki sintaks gaya "pencocokan pola" berbasis penyatuan yang indah yang menghasilkan program yang sangat ringkas. Prologers menyukai sintaks mereka, sama seperti Lisper menyukai ekspresi-s mereka. Prolog juga memiliki pustaka predikat standar yang besar. Karena semua teknik yang telah digunakan untuk membuat WAM cepat, ada implementasi Prolog yang sangat mumpuni dan matang. Hasilnya, banyak sistem berbasis pengetahuan besar telah ditulis seluruhnya di Prolog.

miniKanren dirancang sebagai bahasa pemrograman logika minimal, dengan implementasi yang kecil, mudah dimengerti, dan mudah diretas. miniKanren awalnya tertanam dalam Skema, dan telah di-porting ke lusinan bahasa host lainnya selama dekade terakhir. Implementasi miniKanren yang paling populer adalah 'core.logic' di Clojure, yang sekarang memiliki banyak ekstensi seperti Prolog dan sejumlah pengoptimalan. Baru-baru ini inti dari implementasi miniKanren telah disederhanakan lebih jauh, menghasilkan "kernel mikro" kecil yang disebut "microKanren." miniKanren kemudian dapat diimplementasikan di atas inti mikroKanren ini. Porting microKanren atau miniKanren ke bahasa host baru telah menjadi latihan standar bagi pemrogram yang mempelajari miniKanren. Hasil dari,

Implementasi standar miniKanren dan microKanren tidak mengandung mutasi atau efek samping lainnya, dengan satu pengecualian: beberapa versi miniKanren menggunakan persamaan pointer untuk perbandingan variabel logika. Saya menganggap ini sebagai "efek jinak", meskipun banyak penerapan bahkan menghindari efek ini dengan melewatkan penghitung melalui penerapan. Juga tidak ada database fakta global. Filosofi implementasi miniKanren terinspirasi oleh pemrograman fungsional: mutasi dan efek harus dihindari, dan semua konstruksi bahasa harus menghormati ruang lingkup leksikal. Jika Anda melihat dengan cermat implementasinya, Anda bahkan mungkin melihat beberapa monad. Implementasi pencarian didasarkan pada penggabungan dan manipulasi aliran lambat, sekali lagi tanpa menggunakan mutasi. Pilihan implementasi ini menghasilkan trade-off yang sangat berbeda dengan di Prolog. Di Prolog, pencarian variabel adalah waktu yang konstan, tetapi pengulangan memerlukan efek samping yang dibatalkan. Dalam pencarian variabel miniKanren lebih mahal, tetapi backtracking "gratis". Faktanya, tidak ada kemunduran di miniKanren, karena cara penanganan aliran.

Salah satu aspek menarik dari implementasi miniKanren adalah bahwa kode tersebut secara inheren aman untuk thread dan - setidaknya dalam teori - dapat diparalelkan secara sepele. Tentu saja, memparalelkan kode tanpa membuatnya lebih lambat bukanlah hal yang sepele, mengingat setiap utas atau proses harus diberikan pekerjaan yang cukup untuk menutupi overhead paralelisasi. Meski demikian, ini adalah bidang implementasi miniKanren yang saya harap akan mendapat perhatian dan eksperimen lebih.

miniKanren menggunakan pemeriksaan terjadi untuk penyatuan, dan menggunakan pencarian interleaving lengkap daripada pencarian kedalaman-pertama. Pencarian interleaving menggunakan lebih banyak memori daripada pencarian mendalam-pertama, tetapi dapat menemukan jawaban dalam beberapa kasus di mana pencarian kedalaman-pertama akan menyimpang / berulang selamanya. miniKanren tidak mendukung operator ekstra-logis --- beberapa conda, condudan project, misalnya. condadan condudapat digunakan untuk mensimulasikan potongan Prolog, dan projectdapat digunakan untuk mendapatkan nilai yang terkait dengan variabel logika.

Kehadiran conda, condudanproject--- dan kemampuan untuk dengan mudah mengubah strategi pencarian --- memungkinkan pemrogram untuk menggunakan miniKanren sebagai bahasa mirip Prolog yang disematkan. Ini terutama berlaku untuk pengguna 'core.logic' Clojure, yang menyertakan banyak ekstensi mirip Prolog. Penggunaan miniKanren yang "pragmatis" ini tampaknya merupakan mayoritas dari penggunaan miniKanren dalam industri. Pemrogram yang ingin menambahkan sistem penalaran berbasis pengetahuan ke aplikasi yang sudah ada yang ditulis dalam Clojure atau Python atau JavaScript umumnya tidak tertarik untuk menulis ulang seluruh aplikasi mereka di Prolog. Menyematkan bahasa pemrograman logika kecil di Clojure atau Python jauh lebih menarik. Implementasi Prolog yang disematkan akan bekerja dengan baik untuk tujuan ini, mungkin.

Selain penggunaan miniKanren sebagai bahasa pemrograman logika tertanam pragmatis yang mirip dengan semangat Prolog, miniKanren digunakan untuk penelitian dalam pemrograman "relasional". Artinya, dalam menulis program yang berperilaku sebagai hubungan matematika daripada fungsi matematika. Misalnya, dalam Skema appendfungsi bisa menambahkan dua daftar, mengembalikan daftar baru: panggilan fungsi (append '(a b c) '(d e))mengembalikan daftar (a b c d e). Namun, kita juga bisa memperlakukan appendsebagai relasi tiga tempat daripada sebagai fungsi dua argumen. Panggilan (appendo '(a b c) '(d e) Z)kemudian akan mengasosiasikan variabel logika Zdengan daftar (a b c d e). Tentu saja hal-hal menjadi lebih menarik ketika kita menempatkan variabel logika di posisi lain. Panggilan (appendo X '(d e) '(a b c d e))terkait Xdengan (a b c), saat panggilan(appendo X Y '(a b c d e))asosiasi Xdan Ydengan pasangan daftar yang, jika ditambahkan, sama dengan (a b c d e). Misalnya X= (a b)dan Y= (c d e)adalah salah satu pasangan nilai tersebut. Kami juga dapat menulis (appendo X Y Z), yang akan menghasilkan jauh lebih banyak tiga kali lipat dari daftar X, Ydan Zsehingga menambahkan Xuntuk Ymenghasilkan Z.

Versi relasional ini appenddapat dengan mudah diekspresikan dalam Prolog, dan memang ditampilkan di banyak tutorial Prolog. Dalam praktiknya, program Prolog yang lebih kompleks cenderung menggunakan setidaknya beberapa fitur ekstra-logis, seperti cut, yang menghambat kemampuan untuk memperlakukan program yang dihasilkan sebagai relasi. Sebaliknya, miniKanren secara eksplisit dirancang untuk mendukung gaya pemrograman relasional ini. Versi yang lebih baru dari miniKanren memiliki dukungan untuk pemecahan kendala simbolik ( symbolo, numbero,absento, kendala ketidaksetaraan, pemrograman logika nominal) untuk mempermudah penulisan program non-sepele sebagai relasi. Dalam praktiknya saya tidak pernah menggunakan fitur ekstra-logis miniKanren, dan saya menulis semua program miniKanren saya sebagai relasi. Program relasional yang paling menarik adalah interpreter relasional untuk subset Skema. Penerjemah ini memiliki banyak kemampuan menarik, seperti menghasilkan sejuta program Skema yang mengevaluasi daftar (I love you), atau menghasilkan quine (program yang mengevaluasi diri mereka sendiri).

miniKanren membuat sejumlah trade-off untuk mengaktifkan gaya pemrograman relasional ini, yang sangat berbeda dari trade-off yang dibuat Prolog. Seiring waktu, miniKanren telah menambahkan lebih banyak batasan simbolis, benar-benar menjadi bahasa Pemrograman Batasan Logika yang berorientasi secara simbolis. Dalam banyak kasus, batasan simbolis ini membuatnya praktis untuk menghindari penggunaan operator ekstra-logis seperti condudan project. Dalam kasus lain, batasan simbolis ini tidak cukup. Dukungan yang lebih baik untuk batasan simbolis adalah salah satu bidang aktif penelitian miniKanren, bersama dengan pertanyaan yang lebih luas tentang bagaimana menulis program yang lebih besar dan lebih kompleks sebagai relasi.

Singkatnya, baik miniKanren maupun Prolog memiliki fitur, implementasi, dan kegunaan yang menarik, dan menurut saya ide-ide dari kedua bahasa itu layak dipelajari. Ada juga bahasa pemrograman logika lain yang sangat menarik, seperti Mercury, Curry, dan Gödel, yang masing-masing memiliki pemrograman logika sendiri.

Saya akan mengakhiri dengan beberapa sumber miniKanren:

Situs web miniKanren utama: http://minikanren.org/

Wawancara yang saya berikan tentang pemrograman relasional dan miniKanren, termasuk perbandingan dengan Prolog: http://www.infoq.com/interviews/byrd-relational-programming-minikanren

Bersulang,

--Akan


9
Maaf jika saya terpesona sekarang. Saya baru saja memulai eksperimen pikiran pertama dalam logika dan pemrograman berbasis kendala dan itulah jawaban yang saya dapatkan. :) Sebenarnya, seperti yang Anda sebutkan dalam jawaban Anda, juga, saya memiliki kecurigaan yang kuat bahwa perhitungan logika adalah kandidat yang tepat untuk diterapkan sebagai Monad; ternyata ini lebih merupakan MonadPlus dan memang ada makalah dan implementasi referensi oleh kolega Anda, Friedman! Jadi saya membaca itu dan memainkannya sekarang, ada pemikiran tentang itu?
Profpatsch


5
Juga, saya mengatur pembukaan miniKanren mingguan di Google Hangouts, Minggu pukul 15.00 waktu Timur (GMT -5.00). Saya selalu men-tweet link dari akun Twitter @webyrd saya, jika Anda ingin bergabung dengan kami. Hangout yang direkam sebelumnya ada di: youtube.com/playlist?list=PLO4TbomOdn2cks2n5PvifialL8kQwt0aW
William E. Byrd

2
Saya pikir ini pada dasarnya adalah monad pencarian yang sama seperti pada makalah '05. Juga, lihat 'Menyematkan Prolog di Haskell' oleh Seres dan Spivey: spivey.oriel.ox.ac.uk/~mike/silvija/seres_haskell99.pdf
William E. Byrd

1
@ WilliamE.Byrd - Jawaban yang luar biasa! Dengan asumsi ada satu, implementasi miniKanren terbaik apa yang dapat disematkan dalam program C / C ++? Juga, apakah miniKanren memiliki sifat generatif Prolog? Artinya, kemampuan untuk meninggalkan variabel dalam ekspresi unground dan mesin inti akan menghasilkan semua kemungkinan nilai untuk variabel unground mengingat hubungan saat ini yang dideklarasikan oleh program?
Robert Oschler

4

Jawaban tentatif:

AFAIK, "The Reasoned Schemer" memperkenalkan pemrograman logika dasar dalam sintaks Skema-y dan gaya pemrograman fungsional, khususnya menambahkan tujuan konstan "#u" (gagal) dan "#s" (cukup) ke nilai boolean "#t "dan" #f ". Ini menggunakan pendekatan yang sama untuk pemrograman logika sebagai Prolog: pencarian Unification dan backtracking. Saya akan melihat apakah saya punya waktu untuk mengambil buku itu dari rak saya selama akhir pekan. Cabang matematika adalah bentuk terbatas logika orde pertama, dalam hal ini klausa Horn, dan Resolusi Unfication. Lihat: Logika Komputasi: Kenangan Masa Lalu dan Tantangan untuk Masa Depan oleh John Alan Robinson dan Tahun-tahun awal pemrograman logika oleh Robert Kowalski untuk awal yang dingin.


3
Apa hubungan kedua kutipan ini dengan Kanren, atau MiniKanren?
salah

2
Lihat pertanyaan terakhir: "Dari cabang matematika manakah asalnya, dan apa dasar teoretisnya?"
Frank Shearar
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.