2010-11-16 45 views
6

Tôi đang học prolog và tôi đang đọc một cuốn sách có tên là Lập trình Prolog cho Trí tuệ nhân tạo. Khi thực hành tôi muốn tìm hiểu cách mở rộng một trong những ví dụ trong cuốn sách này. Ai đó có thể giúp đỡ?Lấy danh sách các giải pháp trong Prolog

Giả sử bạn có những sự kiện này:

parent(pam, bob). %pam is a parent of bob 
parent(george, bob). %george is a parent of bob 

Làm thế nào tôi sẽ viết một vị prolog rằng sẽ cung cấp cho tôi một danh sách các Bobs cha mẹ? Ví dụ:

list_parents(bob, L). 

L = [pam, george] ; 
L = [george, pam] ; 
true. 

Trả lời

2

Hãy thử điều này:

parent(pam, bob). %pam is a parent of bob 
parent(george, bob). %george is a parent of bob 
list_parents(A, Es, [X|Xs]) :- parent(X, A), \+ member(X, Es), list_parents(A, [X|Es], Xs). 
list_parents(A, Es, []). 

Đó là một phương pháp hiệu quả, một phương pháp tốt hơn sẽ cần một "giải pháp" bậc cao vị.

list_parents (X, Ys): - giải pháp (cha mẹ, [X, W], 1, Ys)

+1

tôi đăng một câu hỏi theo dõi câu trả lời của bạn liên quan đến việc "giải pháp" vị ngữ: https://stackoverflow.com/questions/47233986/higher-order- giải pháp-predicate – mrsteve

12

Một all-giải pháp predicate như findall/3 thể làm như lừa:

list_parents(P, L) :- 
    findall(Parent, parent(Parent, P), L). 

Simply đặt, findall/3 tìm tất cả các ràng buộc cho Parent trong mục tiêu 'backtrack-possible' parent(Parent, P) và đặt tất cả các liên kết của Parent vào danh sách L. Lưu ý rằng thao tác này sẽ không xóa các mục trùng lặp, nhưng bạn có thể thực hiện sort/2 đến L trước khi trả lại để tạo một bộ. Thực hiện điều này:

?- list_parents(bob, L). 
L = [pam, george]. 

Nếu bạn không có findall/3 trong việc thực hiện PROLOG của bạn, bạn có thể làm nó bằng tay như thế này:

list_parents(P, L) :- 
    list_parents(P, [], L). 

list_parents(P, Acc, L) :- 
    parent(Parent, P), 
    \+ member(Parent, Acc), !, 
    list_parents(P, [Parent|Acc], L). 
list_parents(_, L, L). 

Phiên bản này sẽ gửi các cuộc gọi đến list_parents/2 tắt để một ắc-phiên bản, list_parents/3. Sau đó, cố gắng thu thập các ràng buộc Parent, miễn là chúng tôi chưa thấy chúng trước đây (do đó kiểm tra \+ member) và trả về danh sách không có các liên kết Parent mới tích lũy vào danh sách Acc. Thực hiện điều này sẽ cho chúng ta những kết quả tương tự như tùy chọn đầu tiên:

?- list_parents(bob, L). 
L = [pam, george]. 
+1

'findall', đó là những gì tôi đã cố gắng để Google cho –

+0

cá mập, triển khai tìm kiếm của bạn không tính đến các yếu tố lặp đi lặp lại. Nếu bạn có điều này trong cơ sở dữ liệu: 'cha mẹ (hannah, carl). cha mẹ (hannah, carl). cấp độ gốc (bob, carl) .' đầu ra quy tắc của bạn [hannah, bob]. Nhưng nếu bạn thử với findall bạn nhận được [hannah, hannah, bob] –

Các vấn đề liên quan