2014-11-08 54 views
2

我正試圖解決SWI-Prolog中的一個問題。我有一個合適的元素(常量)列表獲得。Prolog找到所有匹配條件的子集

suitables(L) :- setof(X, isSuitable(X), L). 

從上面的每一個元素都有通過仿函數的得分,我需要所有具有得分> 10的子集,我知道如何獲得的分數總和:

scoreSum([], 0). 
scoreSum([H,T], Tot) :- getScore(H,F),scoreSum(T, Rest), Tot is F+Rest. 

然後,條件可以這樣表示:

cond(L) :- scoreSum(L, R), R > 10. 

如何獲得所有符合給定條件的子集?我可以根據回答here獲得子集,但是如何迭代該結果以僅獲取與條件匹配的子集?

回答

0

我想我找到了我需要的解決方案,但我不確定它是否有效或推薦的方式。提供了以下函子:

isSuitable(X) :- ... 

scoreSum([], 0). 
scoreSum([H,T], Tot) :- getScore(H,F),scoreSum(T, Rest), Tot is F+Rest. 

而且條件:

cond(L) :- scoreSum(L, R), R > 10. 

我只能得到滿足給定的條件組:

suitables(L) :- setof(X, isSuitable(X), S), setof(R, (powerset(S, R), cond(R)),L). 

凡冪給我的所有子集給定集:

powerset([], []). 
powerset([_|T], P) :- powerset(T,P). 
powerset([H|T], [H|P]) :- powerset(T,P). 

因此,我沒有得到所有的組合,我根據this question獲得所有的列表。

+0

調用這個關係'powerset/2'有點用詞不當。 Powerset將是:'powerset(M,P): - bagof(S,seq_subseq(M,S),P)。' – false 2014-11-08 21:05:54

+0

是的,你是對的。我會改變代碼。謝謝你的幫助。 – nowxue 2014-11-08 21:10:21

2

提供scoreSum/2開始與scoreSum([H|T], Tot) :- ...

seq_subseq([], []). 
seq_subseq([_|Es], Fs) :- 
    seq_subseq(Es, Fs). 
seq_subseq([E|Es], [E|Fs]) :- 
    seq_subseq(Es, Fs). 

possiblesubset(S) :- 
    suitables(L), 
    seq_subseq(L, S), 
    cond(S). 

?- setof(S, possiblesubset(S), Subs). 

?- setof(S, (suitables(L), seq_subseq(L,S), cond(S)), Subs). % No L^ needed ; there is only one L. 

然而,這是相當不尋常的明確表示這樣的集合,只是因爲Prolog的能如此有效地生成它們。

+1

嗨@false,謝謝你的回答。我對prolog非常陌生,請您詳細說明一下,「只是因爲Prolog能夠如此高效地生成這些集合,所以明確表示這樣的集合是非常不尋常的」。我怎樣才能讓序言生成它們?我建議的解決方案好嗎? – nowxue 2014-11-08 20:55:10

+1

以上加上你的定義是一個正確的解決方案。但是很少有這樣的集合是明確生成的。也就是說,Subs中的列表可能非常大。另一方面,'possiblesubset(S)'很容易直接調用**而不需要**一次生成整個集合。 – false 2014-11-08 20:58:22