Reputation: 425
I'm trying to solve a problem in SWI-Prolog. I have a list of suitable elements (constants) obtained with.
suitables(L) :- setof(X, isSuitable(X), L).
Each element from above has a score via a functor, and I need all the subsets that have a score > 10. I know how to get the score sum:
scoreSum([], 0).
scoreSum([H,T], Tot) :- getScore(H,F),scoreSum(T, Rest), Tot is F+Rest.
And the condition can be expressed like this:
cond(L) :- scoreSum(L, R), R > 10.
How do I get all the subsets matching the given condition? I can get the subsets based on the answer here, but how do I iterate over that result to get only the subsets matching the condition?
Upvotes: 2
Views: 1669
Reputation: 425
I think I found the solution I needed, although I'm not sure if it's efficient or the recommended way. Provided the following functors:
isSuitable(X) :- ...
scoreSum([], 0).
scoreSum([H,T], Tot) :- getScore(H,F),scoreSum(T, Rest), Tot is F+Rest.
And the condition:
cond(L) :- scoreSum(L, R), R > 10.
I can get only the sets that meet the given condition:
suitables(L) :- setof(X, isSuitable(X), S), setof(R, (powerset(S, R), cond(R)),L).
Where powerset gives me all the subsets of the given set:
powerset([], []).
powerset([_|T], P) :- powerset(T,P).
powerset([H|T], [H|P]) :- powerset(T,P).
So instead of getting all the combinations, I've based on this question to get all sets of the list.
Upvotes: 0
Reputation: 10102
Provided scoreSum/2
starts with 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.
However, it is rather unusual to represent such sets explicitly, simply because Prolog can generate them so efficiently.
Upvotes: 2