Sự khác biệt kỹ thuật chính giữa Prolog và miniKanren đối với lập trình logic là gì? [đóng cửa]


124

Khi tôi muốn đọc về lập trình logic, tôi luôn vấp phải hai cách "chính" để làm điều đó ngày nay:

  • miniKanren , một ngôn ngữ nhỏ được giới thiệu trong The Reasoned Schemer và phổ biến ở thời điểm hiện tại do core.logic .
  • Prolog , ngôn ngữ lập trình logic "lớn" đầu tiên.

Điều tôi quan tâm bây giờ: Sự khác biệt chính về kỹ thuật giữa hai loại này là gì? Chúng rất giống nhau về cách tiếp cận và triển khai hay chúng có những cách tiếp cận hoàn toàn khác nhau đối với lập trình logic? Họ đến từ những nhánh nào của toán học, và cơ sở lý thuyết là gì?


3
Thật buồn khi thấy câu hỏi này bị đóng lại. Như đã chứng minh bằng câu trả lời rất hợp lý và số lượng lớn ủng hộ, đây là một câu hỏi hoàn toàn hữu ích. Tôi đã bỏ phiếu để mở lại ....
nealmcb

@nealmcb các câu hỏi từng là chủ đề với nhiều lượt ủng hộ có thể không còn nữa, số lượng lượt ủng hộ không phải là điều xác định nó hợp lệ hay không.
Tiago Martins Peres 李大仁

Câu trả lời:


281

Đầu tiên, cho phép tôi khen ngợi bạn về biểu tượng pw0n1e đẹp của bạn.

Đây là một câu hỏi khó trả lời, phần lớn là do có rất nhiều biến thể của cả miniKanren và Prolog. miniKanren và Prolog thực sự là họ ngôn ngữ, điều này gây khó khăn cho việc so sánh các tính năng của chúng hoặc thậm chí cách chúng được sử dụng trong thực tế. Vì lý do này, hãy thận trọng với mọi điều tôi sắp nói: nếu tôi nói rằng Prolog sử dụng tìm kiếm theo chiều sâu, hãy lưu ý rằng nhiều triển khai Prolog hỗ trợ các chiến lược tìm kiếm khác và các chiến lược tìm kiếm thay thế cũng có thể được mã hóa theo meta -cấp độ thông dịch viên. Tuy nhiên, miniKanren và Prolog có các triết lý thiết kế khác nhau và thực hiện các đánh đổi khác nhau.

Prolog là một trong hai ngôn ngữ cổ điển để lập trình trí tuệ nhân tạo tượng trưng (ngôn ngữ cổ điển khác là Lisp). Prolog vượt trội trong việc triển khai các hệ thống dựa trên quy tắc tượng trưng trong đó kiến ​​thức khai báo được mã hóa theo logic bậc nhất. Ngôn ngữ được tối ưu hóa để diễn đạt và hiệu quả cho các loại ứng dụng này, đôi khi phải trả giá bằng sự thuần túy logic. Ví dụ, theo mặc định Prolog không sử dụng "kiểm tra xảy ra" trong hợp nhất. Từ quan điểm toán học / logic, phiên bản hợp nhất này không chính xác. Tuy nhiên, việc kiểm tra xảy ra rất tốn kém, và trong hầu hết các trường hợp, việc thiếu kiểm tra xảy ra không phải là vấn đề. Đây là một quyết định thiết kế rất thực dụng, cũng như việc Prolog sử dụng tìm kiếm theo chiều sâu và sử dụng phương pháp cắt (!) để kiểm soát backtracking. Tôi chắc chắn rằng những quyết định này là hoàn toàn cần thiết khi chạy trên phần cứng của những năm 1970 và ngày nay rất hữu ích khi giải quyết các vấn đề lớn và khi xử lý không gian tìm kiếm khổng lồ (thường là vô hạn!).

Prolog hỗ trợ nhiều tính năng "bổ sung logic" hoặc "phi logic", bao gồm cắt assertretractchiếu các biến số học bằng cách sử dụngis, và kể từ đó trở đi. Nhiều tính năng trong số này giúp dễ dàng hơn trong việc diễn đạt luồng điều khiển phức tạp và thao tác với cơ sở dữ liệu toàn cầu của Prolog. Một tính năng rất thú vị của Prolog là bản thân mã Prolog được lưu trữ trong cơ sở dữ liệu toàn cầu về dữ kiện và có thể được truy vấn tại thời điểm chạy. Điều này làm cho việc viết các trình thông dịch meta sửa đổi hành vi của mã Prolog theo cách diễn giải là trở nên tầm thường. Ví dụ: có thể mã hóa tìm kiếm theo chiều rộng trong Prolog bằng cách sử dụng trình thông dịch meta thay đổi thứ tự tìm kiếm. Đây là một kỹ thuật cực kỳ mạnh mẽ mà không được biết đến nhiều bên ngoài thế giới Prolog. 'The Art of Prolog' mô tả chi tiết kỹ thuật này.

Nỗ lực to lớn đã được dành để cải thiện việc triển khai Prolog, hầu hết trong số đó dựa trên Máy trừu tượng Warren (WAM). WAM sử dụng một mô hình hiệu ứng phụ, trong đó các giá trị được gán một cách triệt tiêu cho các biến logic, với những tác động phụ này sẽ được hoàn tác khi bẻ khóa lại. Nhiều tính năng có thể được thêm vào Prolog bằng cách mở rộng hướng dẫn của WAM. Một nhược điểm của phương pháp này là các tài liệu triển khai Prolog có thể khó đọc nếu không có hiểu biết vững chắc về WAM. Mặt khác, người triển khai Prolog có một mô hình chung để thảo luận về các vấn đề triển khai. Đã có rất nhiều nghiên cứu về Prolog song song, đỉnh cao là Andorra Prolog vào những năm 1990. Ít nhất một số ý tưởng trong số này vẫn tồn tại trong Ciao Prolog. (Ciao Prolog chứa đầy những ý tưởng thú vị, nhiều ý tưởng trong số đó vượt xa tiêu chuẩn của Prolog.)

Prolog có cú pháp kiểu "khớp mẫu" dựa trên thống nhất tuyệt đẹp, dẫn đến các chương trình rất ngắn gọn. Người mở đầu yêu thích cú pháp của họ, giống như Lispers yêu thích biểu thức s của họ. Prolog cũng có một thư viện lớn các vị từ chuẩn. Do tất cả các kỹ thuật đã được đưa vào làm cho WAM nhanh chóng, có những triển khai Prolog rất có khả năng và trưởng thành. Kết quả là, nhiều hệ thống dựa trên tri thức lớn đã được viết hoàn toàn bằng Prolog.

miniKanren được thiết kế như một ngôn ngữ lập trình logic tối thiểu, với cách triển khai nhỏ gọn, dễ hiểu và dễ hack. miniKanren ban đầu được nhúng trong Scheme và đã được chuyển sang hàng chục ngôn ngữ chủ khác trong thập kỷ qua. Việc triển khai miniKanren phổ biến nhất là 'core.logic' trong Clojure, hiện có nhiều phần mở rộng giống Prolog và một số tối ưu hóa. Gần đây, cốt lõi của việc triển khai miniKanren đã được đơn giản hóa hơn nữa, dẫn đến một "hạt nhân siêu nhỏ" được gọi là "microKanren." miniKanren sau đó có thể được thực hiện trên đầu của lõi microKanren này. Việc chuyển microKanren hoặc miniKanren sang một ngôn ngữ máy chủ mới đã trở thành một bài tập tiêu chuẩn cho các lập trình viên học miniKanren. Kết quả là,

Các triển khai tiêu chuẩn của miniKanren và microKanren không chứa đột biến hoặc các tác dụng phụ khác, với một ngoại lệ duy nhất: một số phiên bản của miniKanren sử dụng bình đẳng con trỏ để so sánh các biến logic. Tôi coi đây là một "hiệu ứng lành tính", mặc dù nhiều cách triển khai thậm chí tránh được hiệu ứng này bằng cách chuyển một bộ đếm thông qua việc triển khai. Cũng không có cơ sở dữ liệu thực tế toàn cầu. Triết lý triển khai của miniKanren được lấy cảm hứng từ lập trình chức năng: nên tránh đột biến và các hiệu ứng và tất cả các cấu trúc ngôn ngữ phải tôn trọng phạm vi từ vựng. Nếu bạn xem xét kỹ lưỡng việc triển khai, bạn thậm chí có thể phát hiện ra một vài monads. Việc triển khai tìm kiếm dựa trên việc kết hợp và thao tác các luồng lười biếng, một lần nữa mà không sử dụng đột biến. Những lựa chọn triển khai này dẫn đến sự đánh đổi rất khác so với trong Prolog. Trong Prolog, tra cứu biến là thời gian không đổi, nhưng theo dõi ngược lại yêu cầu hoàn tác các tác dụng phụ. Trong miniKanren, tra cứu biến số đắt hơn, nhưng theo dõi ngược lại là "miễn phí". Trên thực tế, không có backtracking trong miniKanren, do cách các luồng được xử lý.

Một khía cạnh thú vị của việc triển khai miniKanren là mã vốn dĩ an toàn theo luồng và --- ít nhất là về lý thuyết --- có thể song song hóa một cách đáng kể. Tất nhiên, song song mã mà không làm cho nó chậm hơn không phải là chuyện nhỏ, vì mỗi luồng hoặc quy trình phải được thực hiện đủ công việc để bù đắp cho chi phí của quá trình song song. Tuy nhiên, đây là một lĩnh vực triển khai miniKanren mà tôi hy vọng sẽ nhận được nhiều sự quan tâm và thử nghiệm hơn.

miniKanren sử dụng kiểm tra xảy ra để hợp nhất và sử dụng tìm kiếm xen kẽ hoàn chỉnh thay vì tìm kiếm theo chiều sâu. Tìm kiếm xen kẽ sử dụng nhiều bộ nhớ hơn tìm kiếm theo chiều sâu, nhưng có thể tìm thấy câu trả lời trong một số trường hợp mà tìm kiếm theo chiều sâu sẽ phân kỳ / lặp lại mãi mãi. miniKanren không hỗ trợ một vài nhà khai thác ngoài logic --- conda, conduproject, ví dụ. condacondu có thể được sử dụng để mô phỏng quá trình cắt của Prolog, và projectcó thể được sử dụng để lấy giá trị liên kết với một biến logic.

Sự hiện diện của conda ,conduproject--- và khả năng dễ dàng sửa đổi chiến lược tìm kiếm --- cho phép các lập trình viên sử dụng miniKanren như một ngôn ngữ giống như Prolog được nhúng. Điều này đặc biệt đúng đối với người dùng 'core.logic' của Clojure, bao gồm nhiều phần mở rộng giống như Prolog. Việc sử dụng miniKanren "thực dụng" này dường như chiếm phần lớn việc sử dụng miniKanren trong ngành công nghiệp. Các lập trình viên muốn thêm hệ thống lý luận dựa trên kiến ​​thức vào một ứng dụng hiện có được viết bằng Clojure hoặc Python hoặc JavaScript thường không quan tâm đến việc viết lại toàn bộ ứng dụng của họ trong Prolog. Nhúng một ngôn ngữ lập trình logic nhỏ trong Clojure hoặc Python hấp dẫn hơn nhiều. Có lẽ, một triển khai Prolog nhúng sẽ hoạt động tốt cho mục đích này.

Ngoài việc sử dụng miniKanren như một ngôn ngữ lập trình logic nhúng thực dụng tương tự như tinh thần của Prolog, miniKanren đang được sử dụng để nghiên cứu trong lập trình "quan hệ". Đó là, trong việc viết các chương trình hoạt động như các quan hệ toán học hơn là các hàm toán học. Ví dụ, trong Scheme, appendhàm có thể nối hai danh sách, trả về một danh sách mới: lệnh gọi hàm (append '(a b c) '(d e))trả về danh sách (a b c d e). Tuy nhiên, chúng ta cũng có thể coi appendlà một quan hệ ba vị trí hơn là một hàm hai đối số. Sau đó, lệnh gọi (appendo '(a b c) '(d e) Z)sẽ liên kết biến logic Zvới danh sách (a b c d e). Tất nhiên mọi thứ trở nên thú vị hơn khi chúng ta đặt các biến logic ở các vị trí khác. Cuộc gọi (appendo X '(d e) '(a b c d e))liên kết Xvới các cộng sự(a b c) , trong khi cuộc gọi(appendo X Y '(a b c d e))XYvới các cặp danh sách, khi được thêm vào, bằng (a b c d e). Ví dụ X= (a b)Y= (c d e)là một trong những cặp giá trị như vậy. Chúng tôi cũng có thể viết (appendo X Y Z), mà sẽ tạo ra vô cùng nhiều gấp ba danh sách X, YZnhư vậy mà phụ thêm Xđể Ysản xuấtZ .

Phiên bản quan hệ này của appendcó thể dễ dàng được thể hiện trong Prolog và thực sự được hiển thị trong nhiều hướng dẫn Prolog. Trong thực tế, các chương trình Prolog phức tạp hơn có xu hướng sử dụng ít nhất một vài tính năng bổ sung logic, chẳng hạn như cắt, ngăn cản khả năng coi chương trình kết quả là một quan hệ. Ngược lại, miniKanren được thiết kế rõ ràng để hỗ trợ kiểu lập trình quan hệ này. Các phiên bản mới hơn của miniKanren có hỗ trợ giải quyết ràng buộc tượng trưng (symbolo , numbero,absento, các ràng buộc bất bình đẳng, lập trình logic danh nghĩa) để giúp viết các chương trình không tầm thường dưới dạng quan hệ dễ dàng hơn. Trong thực tế, tôi không bao giờ sử dụng bất kỳ tính năng logic nào của miniKanren, và tôi viết tất cả các chương trình miniKanren của mình dưới dạng quan hệ. Các chương trình quan hệ thú vị nhất là các trình thông dịch quan hệ cho một tập hợp con của Đề án. Những người phiên dịch này có nhiều khả năng thú vị, chẳng hạn như tạo ra một triệu chương trình Đề án đánh giá danh sách (I love you), hoặc tạo ra các câu hỏi tầm thường (các chương trình tự đánh giá).

miniKanren thực hiện một số đánh đổi để kích hoạt kiểu lập trình quan hệ này, rất khác với kiểu đánh đổi mà Prolog thực hiện. Theo thời gian miniKanren đã thêm nhiều ràng buộc biểu tượng hơn, thực sự trở thành một ngôn ngữ Lập trình Logic Ràng buộc theo định hướng biểu tượng. Trong nhiều trường hợp, những ràng buộc tượng trưng này làm cho nó thực tế để tránh sử dụng các toán tử phụ logic như conduproject. Trong các trường hợp khác, những ràng buộc tượng trưng này là không đủ. Hỗ trợ tốt hơn cho các ràng buộc tượng trưng là một lĩnh vực tích cực của nghiên cứu miniKanren, cùng với câu hỏi rộng hơn là làm thế nào để viết các chương trình lớn hơn và phức tạp hơn dưới dạng quan hệ.

Tóm lại, cả miniKanren và Prolog đều có các tính năng, cách triển khai và cách sử dụng thú vị, và tôi nghĩ rất đáng để học hỏi ý tưởng từ cả hai ngôn ngữ. Ngoài ra còn có các ngôn ngữ lập trình logic rất thú vị khác, chẳng hạn như Mercury, Curry và Gödel, mỗi ngôn ngữ có nhiệm vụ riêng về lập trình logic.

Tôi sẽ kết thúc với một số tài nguyên miniKanren:

Trang web miniKanren chính: http://minikanren.org/

Một cuộc phỏng vấn tôi đã đưa ra về lập trình quan hệ và miniKanren, bao gồm cả so sánh với Prolog: http://www.infoq.com/interviews/byrd-relational-programming-minikanren

Chúc mừng,

--Sẽ


9
Xin lỗi nếu tôi bị thổi bay ngay bây giờ. Tôi vừa mới bắt đầu thử nghiệm suy nghĩ đầu tiên trong lập trình dựa trên logic và ràng buộc và đó là câu trả lời mà tôi nhận được. :) Trên thực tế, như bạn đã đề cập trong câu trả lời của mình, tôi cũng có một sự nghi ngờ mạnh mẽ về tính toán logic là một ứng cử viên hoàn hảo để thực hiện như một Đơn nguyên; hóa ra nó giống một MonadPlus hơn và thực sự có một tài liệu và tài liệu tham khảo được thực hiện bởi đồng nghiệp Friedman của bạn! Vì vậy, tôi đang đọc nó và chơi với nó bây giờ, bất kỳ suy nghĩ nào về nó?
Profpatsch

4
Tôi nghi ngờ bạn cũng sẽ thấy thú vị về giấy và mã microKanren : webyrd.net/scheme-2013/papers/HemannMuKanren2013.pdfgithub.com/jasonhemann/microKanren
William E. Byrd

5
Ngoài ra, tôi tổ chức một cuộc truy vấn miniKanren hàng tuần trên Google Hangouts, Chủ nhật lúc 3 giờ chiều theo giờ miền Đông (GMT -5: 00). Tôi luôn tweet liên kết từ tài khoản Twitter @webyrd của mình, nếu bạn muốn tham gia cùng chúng tôi. Các hangout được ghi lại trước đó tại: youtube.com/playlist?list=PLO4TbomOdn2cks2n5PvifialL8kQwt0aW
William E. Byrd

2
Tôi nghĩ về cơ bản nó giống với đơn nguyên tìm kiếm như trong bài báo '05. Ngoài ra, hãy xem 'Nhúng Prolog trong Haskell' của Seres và Spivey: spivey.oriel.ox.ac.uk/~mike/silvija/seres_haskell99.pdf
William E. Byrd

1
@ WilliamE.Byrd - Câu trả lời tuyệt vời! Giả sử có một, triển khai miniKanren tốt nhất có thể được nhúng trong chương trình C / C ++ là gì? Ngoài ra, miniKanren có bản chất tự nhiên của Prolog không? Có nghĩa là, khả năng để một biến trong một biểu thức không có xung quanh và động cơ cốt lõi sẽ tạo ra tất cả các giá trị có thể có cho biến không bao gồm các quan hệ hiện tại được khai báo bởi chương trình?
Robert Oschler

4

Câu trả lời dự kiến:

AFAIK, "The Reasoned Schemer" đã giới thiệu lập trình logic cơ bản theo cú pháp Scheme-y và kiểu lập trình hàm, đặc biệt thêm các mục tiêu hằng số "#u" (fail) và "#s" (suceeed) vào các giá trị boolean "#t "và" #f ". Nó sử dụng cách tiếp cận tương tự để lập trình logic như Prolog: Hợp nhất và tìm kiếm backtracking. Tôi sẽ xem liệu tôi có thời gian để lấy cuốn sách đó từ giá sách của mình vào cuối tuần không. Nhánh toán học là một dạng logic bậc nhất bị hạn chế, trong trường hợp này là các mệnh đề Horn, và Phép phân giải. Xem: Logic tính toán: Ký ức về quá khứ và thách thức đối với tương lai của John Alan Robinson và Những năm đầu lập trình logic của Robert Kowalski cho một khởi đầu lạnh lùng.


3
Hai trích dẫn này có liên quan gì đến Kanren, hoặc MiniKanren?
false

2
Xem câu hỏi cuối cùng: "Họ đến từ những ngành nào của toán học, và cơ sở lý thuyết là gì?"
Frank Shearar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.