2012-11-15 69 views
4

如何執行rule1成功iff rule2返回兩個或更多結果如果返回兩個或多個結果,則判斷成功

rule1(X) :- 
    rule2(X, _). 

如何計算結果,然後設置何時成功的最小值?

+1

應該很容易使用[findall/3]進行編碼(http://stackoverflow.com/questions/1468150/how-do-i-find-all-solutions-to-a-goal-in-prolog)。 – ShiDoiSi

回答

2

你可以使用庫(aggregate)計算解決方案

:- use_module(library(aggregate)). 

% it's useful to declare this for modularization 
:- meta_predicate at_least(0, +). 

at_least(Predicate, Minimum) :- 
     aggregate_all(count, Predicate, N), 
     N >= Minimum. 

例如:

?- at_least(member(_,[1,2,3]),3). 
true. 

?- at_least(member(_,[1,2,3]),4). 
false. 

編輯這裏是一個更有效的方式,使用SWI-Prolog的設施global variables

at_least(P, N) :- 
    nb_setval(at_least, 0), 
    P, 
    nb_getval(at_least, C), 
    S is C + 1, 
    (S >= N, ! ; nb_setval(at_least, S), fail). 

用這個定義,P叫做只是 N次。 (筆者爲大家介紹服務謂詞M/2,顯示它返回什麼)

m(X, L) :- member(X, L), writeln(x:X). 

?- at_least(m(X,[1,2,3]),2). 
x:1 
x:2 
X = 2. 

編輯佔@false評論,我想

?- call_nth(m(X,[1,2,3]),2). 
x:1 
x:2 
X = 2 ; 
x:3 
false. 

與call_nth從here

從實際角度來看,我認爲nb_setval(vs nb_setarg)遭受了全局和局部變量之間的通常折衷。即對於某些任務可能會很輕易地知道接受條件的限制。如果這不是必需的,nb_setarg它更乾淨。

底線:更好的方法是使用call_nth,雙重否定解決不當變量實例化的'技巧'。

+1

您對全局變量的使用不正確。你在查詢中產生意外的替換('X = 2')。 – false

5

我該如何計算結果,然後爲什麼時候設置最小值?

目前尚不清楚你的結果是什麼意思。所以我會做一些猜測。結果可能是:

解決方案。例如,目標member(X,[1,2,1])有兩個解決方案。不是三個。在這種情況下,請考慮使用setof/3或類似的謂詞。無論如何,在解決您遇到的問題之前,您應該首先了解setof/3

答案。目標member(X,[1,2,1])有三個答案。目標member(X,[Y,Z])有兩個答案,但無限多的解決方案。

所以,如果你想確保至少有答案一定數目,定義:

 
at_least(Goal, N) :- 
    \+ \+ call_nth(Goal, N). 

call_nth/2defined in another SO-answer

請注意,其他SO答案不正確:它們要麼不終止,要麼產生意外的實例化。

+2

感謝您解釋解決方案和答案的區別。 – CapelliC

+2

@chac:這個區別是[tag:clpfd]的關鍵! – false