tags:

views:

362

answers:

1

Hi,

I had a quick question re. existential qualifier using setof in prolog (i.e. ^).

using SICStus it seems that (despite what a number of websites claim), S does indeed appear to be quantified in the code below (using the bog standard, mother of / child of facts, which i havent included here):

child(M,F,C) :- setof(X,(mother(S,X)),C).

i check the unification using:

child(M,F,C) :- setof(X-S,(mother(S,X)),C).

so the following code, with the existential operator seem to make no difference:

child(M,F,C) :- setof(X,S^(mother(S,X)),C).

Any ideas why this is? What would be a situation where you would need the unifier then?

thanks!

+1  A: 

Ok, I'm not sure I can explain it perfectly, but let me try.

It has to do with the fact that you are querying over a 2-ary relation, mother/2. In that case using X-S as the template has a similar effect on the result set C as using S^ in front of the goal. In X-S you are using both variables in the template, and therefore each possible binding of X and S is included in C. You get the same effect using S^ in front of the goal, as this is saying "ignore bindings of S when constructing the result".

But the difference between the two becomes clearer when you query over a 3-ary relation. The SWI manual has this example:

foo(a, b, c).
foo(a, b, d).
foo(b, c, e).
foo(b, c, f).
foo(c, c, g).

Now do similar queries as in your example

setof(X-Z, foo(X,Y,Z), C).

and

setof(Z, X^foo(X,Y,Z), C).

and you get different results.

It's not just checking unification, X-Z effectively changes your result set.

Hope that helps.

Edit: Maybe it clarifies things when I include the results of the two queries above. The first one goes like this:

?- setof(X-Z, foo(X,Y,Z), C).   
Y = b
C = [a-c, a-d] ;
Y = c
C = [b-e, b-f, c-g] ;
No

The second one yields:

?- setof(Z, X^foo(X,Y,Z), C).
Y = b
C = [c, d] ;
Y = c
C = [e, f, g] ;
No
ThomasH
Thanks - thats helpful, whats sort of stumping me though is the actual use of ^ it seems that whenever you need a particular variable to be unified, you can just include it in the result template (ie. in our case, change it from X to X-Z) - so where would you need use the ^ operator, but not then include it in the template?
oneAday
@oneAday Uhm, I don't know if the query results I've included in my answer clarify things. The simple answer is: With ^ you basically say "ignore this variable". Using it in the template says "I'm interested in it", and makes it part of your result set. It all depends on whether you are interested or not. If you are **not** interested then a result like "a-c" forces you to decompose that term, in order to get to the "c".
ThomasH
Ok, i think i get it - thanks. I guess the point is, you want / need it to be instanciated, but dont require it for the output.many thanks for your help
oneAday
Indeed, using ^ will disregard alternative bindings for X on backtracking, while __setof(Z, foo(_,Y,Z), C)__, which is another way of saying you are not interested in the first parameter, will still regard alternative values of it on backtracking, and you get **3** possible results for C - just try it.
ThomasH