bagof only gives one item, though multiple items fit - prolog

This code works as expected:
?- bagof(R,member(r(R),[r(a),r(b),r(c),r(d)]),Rs).
Rs = [a, b, c, d].
but a similar call, the one I really want, does not:
?- bagof(R,member(r(_,R),[r(_,a), r(_,b), r(_,c), r(_,d)]),Rs).
Rs = [a]
; gives me more answers -- but I want [a,b,c,d]. What's my fix?

bagof/3 and _ do not flock together directly. Same is true for setof/3.
So either give all those anonymous variables a name and declare them as a local variable, use an auxiliary predicate, or use library(lambda):
?- bagof(R,R+\member(r(_,R),[r(_,a), r(_,b), r(_,c), r(_,d)]),Rs).
Rs = [a,b,c,d].

You need to existentially qualify the arguments that you're not interested in instead of using anonymous variables:
?- bagof(R,A^A1^A2^A3^A4^member(r(A,R),[r(A1,a), r(A2,b), r(A3,c), r(A4,d)]),Rs).
Rs = [a, b, c, d].
This is necessary as bagof/3 (and setof/3) will return a bag (set) of solutions for each instantiation of the free variables (i.e. the variables in the goal that are not in the template). In alternative, you can use the findall/3 predicate (which ignores free variables):
?- findall(R,member(r(A,R),[r(A1,a), r(A2,b), r(A3,c), r(A4,d)]),Rs).
Rs = [a, b, c, d].
But note that findall/3 returns an empty list when there are no solutions while bagof/3 (and setof/3) fail when there are no solutions.
Another alternative to avoid a long list of existentially qualified variables in calls to bagof/3 and setof/3 is to introduce an auxiliary predicate with a single clause whose head only lists the arguments you're interested in. For example:
r(R) :-
member(r(_,R),[r(_,a), r(_,b), r(_,c), r(_,d)]).
?- bagof(R, r(R), Rs).
Rs = [a, b, c, d].

Paulo contributed library(yall), autoloaded in SWI-Prolog. Yall (Yet Another Lambda Library) solves your problem easily:
?- bagof(R, {R}/member(r(_,R),[r(_,a), r(_,b), r(_,c), r(_,d)]),Rs).
Rs = [a, b, c, d].

Related

extending a list of lists by a single element

I am trying to solve the following question in ProLog. I am a beginner.
Define a predicate extend such that if Xss and Yss are lists of
lists then extend(X, Xss, Yss) holds if Yss can be obtained by adding the
element X to the end of every element in Xss, e.g
?- extend(g, [[e], [b, c, f], [k, h]], Yss).
Yss = [[e, g], [b, c, f, g], [k, h, g]]
I have attempted this with the following, but there is an error message :
extend(X, [], []).
extend(X, [[Firstxss,_] | Restxss], Yss) :-
Firstxss is [Firstxss,_|X],
Yss is [Yss | [Firstxss,_]],
Xss is Restxss,
extend(X, Xss, Yss).
I have input the following :
?- extend(g, [[e], [b, c, f], [k, h]], Yss).
and it returns :
false.
I think I have a valid input and I do not understand why it is returning as false.
Since you want to do the same thing with every element of the outer list, this is quite a beautiful task for maplist/3. You can use append/3 to extend a list by an additional element like so:
?- append([1,2],[element],Z).
Z = [1, 2, element].
However, you'll want to have append/3 with two lacking arguments in maplist/3, therefore it would be opportune to have the first argument appended to the second argument. To realize that, you could write an auxiliary predicate that calls append/3 with the first two arguments flipped, e.g:
flippedappend(X,Y,Z) :-
append(Y,X,Z).
Building on this, you could define the actual relation like so:
x_lists_extended(X,Xss,Yss) :-
maplist(flippedappend([X]),Xss,Yss).
Your example query yields the desired result:
?- x_lists_extended(g, [[e], [b, c, f], [k, h]], Yss).
Yss = [[e, g], [b, c, f, g], [k, h, g]].
Note that you can also use this predicate the other way around:
?- x_lists_extended(X, Xss, [[e, g], [b, c, f, g], [k, h, g]]).
X = g,
Xss = [[e], [b, c, f], [k, h]] ;
false.
First, you have a singleton variable X here:
extend(X, [], []).
It would be better to say extend(_, [], []) because you never refer to X again. It's important to understand why this is the case. In Prolog, all the action happens because of relationships the variables are in. If the variable only appears in one place, it's not participating in any relationships, so it should be replaced with _. (If you make such a change and the code appears to be nonsense, stop and study it, because it always means you have misunderstood something.)
Second, is/2 is for evaluating arithmetic expressions. There's no math going on in this: Firstxss is [Firstxss,_|X] so you have confused it with =. This is really a double whammy though, because = does not mean assign in Prolog, it means unify. So there is no real situation in Prolog where you are going to have X = X+1 or anything like that, which is exactly the kind of thing yo'ure doing here, trying to reuse a variable for different purposes.
What does Firstxss mean in this clause? It looks like it is the first item in a nested list in the second argument in the head: in other words, if you called extend(g, [[e], [b, c, f], [k, h]], Yss), then Firstxss = e. The value of Firstxss can never change. It can only be rebound in a recursive call. So when you immediately say Firstxss is [Firstxss,_|X], what Prolog sees is b = [b,_|<another var>]. This does not unify and your predicate fails at this point. Say it advanced, somehow. You make the same mistake on the next line with Yss.
It would help to think about your problem relationally. You have the wrong base case too. What is your base case? It's the case where you have reached the end of the list, and what should you do? Append X. So this is your base case:
extend(X, [], [X]).
Now think about what you want to do in the other cases: you have a head and a tail. How do you extend? You extend the tail, and your result is the head appended to the extended tail. Try and write this clause yourself, it is not that difficult!
Once you have that, the machinery for extending nested lists is simple: you test the head to see if it is a list. If it is, recur on the head as well as the tail! Like so:
extend(X, [Y|Ys], Result) :-
(is_list(Y) -> extend(X, Y, Y1) ; Y1 = Y),
... % use Y1 as Y in building the result

findall/3 creates new, unrelated variables in its resulting list

?- permutation([A,B,C],Z).
Z = [A, B, C] ;
Z = [A, C, B] ;
Z = [B, A, C] ;
Z = [B, C, A] ;
Z = [C, A, B] ;
Z = [C, B, A] ;
false.
Makes sense. I can work on a permutation of [A,B,C] and that permutation contains the same elements as in [A,B,C], so everything I do to those elements will apply to my original list.
Now:
?- findall(X, permutation([A,B,C], X), Z).
Z = [[_G1577, _G1580, _G1583], [_G1565, _G1568, _G1571], [_G1553, _G1556, _G1559], [_G1541, _G1544, _G1547], [_G1529, _G1532, _G1535], [_G1517, _G1520, _G1523]].
Why?? Why is findall/3 giving me lists which contain completely unrelated variables, instead of A,B,C? The lists in Z are not even related to each other, so really the result I get is just 6 random lists of length 3, which is totally not what I queried.
With this behavior we get ridiculous results like this:
?- findall(X, permutation([A,B,C],X), Z), A = 1.
A = 1,
Z = [[_G1669, _G1672, _G1675], [_G1657, _G1660, _G1663], [_G1645, _G1648, _G1651], [_G1633, _G1636, _G1639], [_G1621, _G1624, _G1627], [_G1609, _G1612, _G1615]].
Which makes no sense from a logical standpoint.
I understand that findall/3 is not really a relational, pure logic predicate but I don't see how this justifies the behavior shown here.
My questions are therefore:
Why was this behavior chosen for the predicate?
Are there common situations where this behavior is actually preferable to the one I want?
How to implement a version of findall/3 with the behavior I want?
Why was this behavior chosen for the predicate?
findall/3 is a highly primitive built-in predicate that is relatively easy to implement and that does not address all the nitty-gritty details you are interested in. At least it is reentrant - thus can be used recursively.
Historically, DEC10 Prolog did not document findall/3. That is, neither in 1978 nor 1984. The 1984 version did however provide setof/3 which internally uses a findall-like predicate. Implementing it in ISO-Prolog (without findall/3) is relatively tricky since you have to handle errors and nesting. Many implementations rely on implementation specific primitives.
Are there common situations where this behavior is actually preferable to the one I want?
Findall succeeds if there is no solution whereas both setof/3 and bagof/3 simply fail. This might be a reason to prefer it. At least some more sophisticated constructs than those are needed which are most probably built based on findall.
It gets pretty messy in the presence of constraints. In fact, it is so messy, that as of the current point in time I am still unaware of an implementation that would deal in a reasonable manner with clpfd-constraints in this very situation. Think of:
?- findall(A, (A in 1..3 ; A in 5..7), As).
Here, SWI copies constraints, where SICStus does not copy them permitting you thus to use it as building-block for a more sophisticated implementation.
How to implement a version of findall/3 with the behavior I want?
First, consider setof/3 and bagof/3 (here). Maybe you are happy with them already - as long as no constraints are involved...
A solution to your last question.
?- setof(X,permutation([A,B,C],X),Z).
Z = [[A, B, C], [A, C, B], [B, A, C], [B, C, A], [C, A, B], [C, B, A]].
If we look at the description of findall at sicstus we see
findall(?Template,:Goal,?Bag) ISO
Bag is a list of instances of Template in all proofs of Goal found by Prolog. The order of the list corresponds to the order in which the proofs are found. The list may be empty and all variables are taken as being existentially quantified. This means that each invocation of findall/3 succeeds exactly once, and that no variables in Goal get bound. Avoiding the management of universally quantified variables can save considerable time and space.
So I guess the existential quantifying creates this unwanted behaviour of findall.
?- findall(X, permutation([A,B,C],X), Z), A = 1.
In this query Prolog will find all permutation of the elements on the list [A,B,C], but since Prolog can not instantiate the variables A, B, C, the result will be this that you are getting, the anonymous variable:
Z = [[_G1669, _G1672, _G1675], [_G1657, _G1660, _G1663], [_G1645, _G1648, _G1651], [_G1633, _G1636, _G1639], [_G1621, _G1624, _G1627], [_G1609, _G1612, _G1615]].
On the other hand, if you first instantiate the variables A, B and C, you will get a different result:
?- A=1, B=2, C=3, findall(X, permutation([A,B,C],X), Z).
A = 1,
B = 2,
C = 3,
Z = [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
This didn't happend before in your query findall(X, permutation([A,B,C],X), Z), A = 1. because Prolog will first try to solve the condition findall(X, permutation([A,B,C],X), Z) and then A = 1

Split list on given element

I have a list C and I want to split the list using the element c in the list.
The expected results are as example:
?- split([a,c,a,a,c,a,a,a],X).
X = [[a],[a,a],[a,a,a]].
Can anybody help? Thanks in advance.
I can remove the c in the list now and here is my codes.
split([],[]).
split([H|T],[H|S]) :- H=a,split(T,S).
split([H|T],S) :- H=c,split(T,S).
Your "remove c" predicate would look better like this:
remove_c([c|T], S) :-
remove_c(T, S).
remove_c([a|T], [a|S]) :-
remove_c(T, S).
This still only works for lists that have only c and a in them.
If you want to "split", this means you at least need another argument, to collect the a's between the c's. For example:
split_on_c(List, Split) :-
split_on_c_1(List, Split, []).
split_on_c_1([], [Acc], Acc).
split_on_c_1([c|Rest], [Acc|Split], Acc) :-
split_on_c_1(Rest, Split, []).
split_on_c_1([a|Rest], Split, Acc) :-
split_on_c_1(Rest, Split, [a|Acc]).
Again, this expects lists of a and c only. It could also be done in different ways, but this is a start.
While learning a language you need to get accomplished to common abstractions already established (in simpler terms, use libraries). What about
split(In, Sep, [Left|Rest]) :-
append(Left, [Sep|Right], In), !, split(Right, Sep, Rest).
split(In, _Sep, [In]).
to be used like
?- split([a,c,a,a,c,a,a,a],c,R).
R = [[a], [a, a], [a, a, a]].
Use the meta-predicate splitlistIf/3 together with reified term equality
(=)/3, like this:
Here is the query the OP gave in the question:
?- splitlistIf(=(c),[a,c,a,a,c,a,a,a],Xs).
Xs = [[a],[a,a],[a,a,a]].
Note that above code is monotone, so the following query gives reasonable results:
?- splitlistIf(=(X),[Y,X,Y,Y,X,Y,Y,Y],Xs), Y = a, X = c.
X = c,
Y = a,
Xs = [[a],[a, a],[a, a, a]].

Prolog findall/3

Say I have a predicate pred containing several facts.
pred(a, b, c).
pred(a, d, f).
pred(x, y, z).
Can I use findall/3 to get a list of all facts which can be pattern matched?
for example, if I have
pred(a, _, _)
I would like to obtain
[pred(a, b, c), pred(a, d, f)]
Just summing up what #mbratch said in the comment section:
Yes, but you have to make sure that you either use named variables or construct a simple helper predicate that does that for you:
Named variables:
findall(pred(a,X,Y),pred(a,X,Y),List).
Helper predicate:
special_findall(X,List):-findall(X,X,List).
?-special_findall(pred(a,_,_),List).
List = [pred(a, b, c), pred(a, d, f)].
Note that this doesn't work:
findall(pred(a,_,_),pred(a,_,_),List).
Because it is equivalent to
findall(pred(a,A,B),pred(a,C,D),List).
And thus doesn't unify the Variables of Template with those of Goal.

existential qualifier in prolog, using setof / bagof

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!
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

Resources