Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I find all solutions to a goal in Prolog?

I have predicate P1 that returns values one after the other like this:

-? P1(ARGUMENTS, RETURN).
-? RETURN = 1;
-? RETURN = 2;
-? RETURN = 3;
-? fail.

I also have another predicate called P2:

P2(ARGUMENTS, LIST) :- P1(ARGUMENTS, RETURN),... % SOMEHOW HERE I NEED TO INSERT ALL VALUES OF RETURN TO LIST.

How do find all of the values of RETURN and assign them to LIST?

like image 910
Asterisk Avatar asked Sep 23 '09 19:09

Asterisk


People also ask

How do I get all the solutions in Prolog?

An all-solutions predicate like findall/3 might do the trick: list_parents(P, L) :- findall(Parent, parent(Parent, P), L). Simply put, findall/3 finds all bindings for Parent in the 'backtrack-able' goal parent(Parent, P) , and puts all bindings of Parent into the list L .

How does Findall work Prolog?

Prolog findall is a predicate function of the programming language to work with list, goal, and template. It is a metapredicate that works with a list of the templates and achieves the required goal. It is a built-in function to collect a list of the items using a template and bind the list to get a required goal.

What does Setof do in Prolog?

setof. The built-in Prolog predicate setof(+Template, +Goal, -Set) binds Set to the list of all instances of Template satisfying the goal Goal .


1 Answers

Use findall to accomplish this:

P2(ARGUMENTS, LIST) :- findall(X, P1(ARGUMENTS, X), LIST).

This is related to the bagof function mentioned in the question linked to by Anders Lindahl. There is a good explanation on the relationship between the two functions (and a third function setof) here:

To illustrate the differences consider a little example:

listing(p).

p(1,3,5).
p(2,4,1).
p(3,5,2).
p(4,3,1).
p(5,2,4).

Try the following goals. (The answer displays have been modified to save space.)

?- bagof(Z,p(X,Y,Z),Bag).
Z = _G182 X = 1 Y = 3 Bag = [5] ;
Z = _G182 X = 2 Y = 4 Bag = [1] ;
Z = _G182 X = 3 Y = 5 Bag = [2] ;
Z = _G182 X = 4 Y = 3 Bag = [1] ;
Z = _G182 X = 5 Y = 2 Bag = [4] ;
No

?- findall(Z,p(X,Y,Z),Bag).
Z = _G182 X = _G180 Y = _G181 Bag = [5, 1, 2, 1, 4] ;
No

?- bagof(Z,X^Y^p(X,Y,Z),Bag).
Z = _G182 X = _G180 Y = _G181 Bag = [5, 1, 2, 1, 4] ;
No

?- setof(Z,X^Y^p(X,Y,Z),Bag).
Z = _G182 X = _G180 Y = _G181 Bag = [1, 2, 4, 5] ;
No

The predicates bagof and setof yield collections for individual bindings of the free variables in the goal. setof yields a sorted version of the collection without duplicates. To avoid binding variables, use an existential quantifier expression. For example the goal bagof(Z,X^Y^p(X,Y,Z),Bag) asks for "the Bag of Z's such that there exists an X and there exists a Y such that p(X,Y,Z)". findall acts like bagof with all free variables automatically existentially quantified. In addition findall returns an empty list [] there is no goal satisfaction, whereas bagof fails.

like image 172
Pesto Avatar answered Jan 02 '23 23:01

Pesto