2009-04-07 31 views
5

Có cách nào dễ dàng để thực hiện truy vấn trong prolog chỉ trả lại mỗi kết quả một lần?kết quả duy nhất từ ​​prolog

ví dụ tôi đang cố gắng một cái gì đó như:

deadly(Xn) :- scary(X), Xn is X - 1, Xp is X + 1, not(safe(Xn)), safe(Xp). 
deadly(Xp) :- scary(X), Xn is X - 1, Xp is X + 1, not(safe(Xp)), safe(Xn). 

deadly(X). 

và nhận

X = 5 

X = 5 

X = 5 

X = 5 

.... 

Không hữu ích cho tôi.

Trả lời

1

Thật khó để nói mà không cần thêm mã của bạn, nhưng có thể bạn đang tìm kiếm toán tử cắt (!). Nếu bạn muốn đăng một định nghĩa của foo, tôi (hoặc người khác theo dõi) có thể cung cấp câu trả lời chi tiết/cụ thể.

+0

mỗi khi tôi đã sử dụng! nó đã hoàn toàn ngừng đánh giá và tôi muốn mọi giá trị mà prolog là tìm kiếm, nhưng chỉ một lần cho mỗi giá trị. (Tôi sẽ cố gắng và cắt giảm trường hợp của tôi) – BCS

+1

Đó là vấn đề khi nào và ở đâu để sử dụng nó. Nói "không bao giờ quay trở lại đây một lần nữa" có một ý nghĩa cực kỳ khác nhau đến trước hoặc sau khi bắt giữ dữ liệu đầu tiên. – MarkusQ

3

Nếu tôi nhớ chính xác có một giải pháp dự đoán (hoặc tương tự, đã lâu rồi kể từ khi tôi lập trình Prolog) thu thập các giải pháp duy nhất trong danh sách.

Chỉnh sửa:setof/3 là thứ tôi đang nghĩ tới. Cảm ơn, Kaarel.

+0

findall/3, bagof/3, setof/3 – Kaarel

4

Một điều bạn có thể làm là áp dụng setof/3 cho biến vị ngữ tạo các giải pháp. Nhưng lưu ý rằng setof/3 được triển khai bằng cách áp dụng sort/2 cho kết quả được phân phối bởi bagof/3 (ít nhất đây là trường hợp trong SWI-Prolog). Vì vậy, nếu trình tạo giải pháp của bạn tiếp tục mãi mãi, thì setof/3 sẽ không bao giờ được áp dụng ...

Vì vậy, tôi sẽ cố gắng lập trình sao cho các bản sao không được tạo ra, tức là bằng cách sử dụng cắt (!) .

+0

Nếu tôi nhớ không chính xác, setof chỉ hữu ích nếu truy vấn có kích thước giải pháp hữu hạn và nó biết rằng nó đã hoàn tất. Nếu không, nó chỉ có thể tiếp tục nhận được một 5, nói rằng, Không, đã nhận được điều đó, và nhìn lại, và nhận được KHÁC 5 ... vòng lặp vô hạn. –

+0

Cảm ơn. Tôi đã cập nhật câu trả lời một chút. – Kaarel

3

Cách tiếp cận khác là ghi nhớ các giải pháp.

:- dynamic seen/1. 

% Call this always before calling deadly_wrapper/1 
clear_seen :- 
    retractall(seen(_)). 

% This wrapper calls deadly/1 but remembers 
% the solution using assert/1, and fails 
% if the solution has been "seen" before. 
deadly_wrapper(X) :- 
    deadly(X), 
    (
     seen(X) 
    -> 
     fail 
    ; 
     assert(seen(X)) 
    ). 


% This is for testing. 
deadly(1). 
deadly(1). 
deadly(1). 
deadly(5). 
deadly(1). 
deadly(1). 

Trong trường hợp Prolog của bạn hỗ trợ tabling, thì nó trở nên đơn giản hơn. tập tin Ví dụ:

:- table deadly/1. 

deadly(1). 
deadly(1). 
deadly(5). 
deadly(1). 
deadly(5). 

Ví dụ thực hiện với XSB:

$ xsb 
[xsb_configuration loaded] 
[sysinitrc loaded] 

XSB Version 3.2 (Kopi Lewak) of March 15, 2009 
[x86_64-unknown-linux-gnu; mode: optimal; engine: slg-wam; 
scheduling: local; word size: 64] 

| ?- [deadly_tab]. 
[Compiling ./deadly_tab] 
[deadly_tab compiled, cpu time used: 0.0100 seconds] 
[deadly_tab loaded] 

yes 
| ?- deadly(X). 

X = 5; 

X = 1; 

no 
| ?- 
+0

Tôi sẽ nói "ghi nhớ", thay vì "ghi nhớ". –

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