When there are many solutions to a problem, and when all those solutions are required to be collected together, this can be achieved by repeatedly backtracking and gradually building up a list of the solutions. The following built-in predicates are provided to automate this process.
Note that the Goal argument to the predicates listed
below is called as if by
call/1 at runtime. Thus if Goal
is complex and if performance is an issue, define an auxiliary
predicate, which can then be compiled, and let Goal
)(see Control). Set is a set of terms represented as a list of those terms, without duplicates, in the standard order for terms (see Term Compare). If there are no instances of Template such that Goal is satisfied then the predicate fails.
The variables appearing in the term Template should not appear anywhere else in the clause except within the term Goal. Obviously, the set to be enumerated should be finite, and should be enumerable by Prolog in finite time. It is possible for the provable instances to contain variables, but in this case the list Set will only provide an imperfect representation of what is in reality an infinite set.
If there are uninstantiated variables in Goal, which do not also appear in Template, then a call to this built-in predicate may backtrack, generating alternative values for Set corresponding to different instantiations of the free variables of Goal. (It is to cater for such usage that the set Set is constrained to be non-empty.) Two instantiations are different iff no renaming of variables can make them literally identical. For example, given the clauses:
likes(bill, cider). likes(dick, beer). likes(harry, beer). likes(jan, cider). likes(tom, beer). likes(tom, cider).
| ?- setof(X, likes(X,Y), S).
might produce two alternative solutions via backtracking:
S = [dick,harry,tom], Y = beer ? ; S = [bill,jan,tom], Y = cider ? ;
| ?- setof((Y,S), setof(X, likes(X,Y), S), SS).
would then produce:
SS = [(beer,[dick,harry,tom]),(cider,[bill,jan,tom])]
Variables occurring in Goal will not be treated as free if they are explicitly bound within Goal by an existential quantifier. An existential quantification is written:
meaning “there exists a Y such that Q is true”, where Y is some Prolog variable.
| ?- setof(X, Y^(likes(X,Y)), S).
would produce the single result:
S = [bill,dick,harry,jan,tom]
in contrast to the earlier example.
Note that in
iso execution mode, only outermost existential
quantification is accepted, i.e. if the Goal argument is
of form V1
^ ... ^ N
^ SubGoal. In
sicstus execution mode existential quantification is handled also
deeper inside Goal.
setof/3except that the list (or alternative lists) returned will not be ordered, and may contain duplicates. The effect of this relaxation is to save a call to
sort/2, which is invoked by
setof/3to return an ordered list.
bagof/3constructs is superfluous and discouraged.
findall/3succeeds exactly once, and that no variables in Goal get bound. Avoiding the management of universally quantified variables can save considerable time and space.
findall/3, except Bag is the list of solution instances appended with Remainder, which is typically unbound.