?- 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
Related
I am new to Prolog and for the following program:
place(Store,2,a).
place(Store,1,b).
place(Store,3,d).
place(Store,4,c).
placeSort(S,List):- findall(L,place(S,N,L),List).
output: List = [a, b, d, c].
By using placeSort(S,List) , I can find all the elements(a,b,c,d) that contains S (Store).
However what I want to achieve here is to sort the Position of a,b,c,d by using N, however I dont know how to do so as using sort will just sort it out by alphabetical order
placeSort(S,NewList):- findall(L,place(S,N,L),List),sort(List,NewList).
output: List = [a, b, c, d].
what I want to achieve : List = [b,a,d,c]
**I know by using placeSort(S,NewList):- findall([N,L],place(S,N,L),List),sort(List,NewList).
it will return a list of lists sorted by numbers.
output : List = [[1, b], [2, a], [3, d], [4, c]].
but im not sure how to take away the numbers and just take the alphabets instead.
Any help would be greatly appreciated.
SWI-Prolog offers the interesting builtin order_by/2, filling the gap traditional Prolog suffers when compared to SQL, with library(solutionsequences):
?- order_by([asc(X)],place(P,X,W)).
X = 1,
W = b ;
X = 2,
W = a ;
...
So you can avoid full list construction.
The easiest way to do this is to use setof/3 (which sorts by term) and pick a term form that works for you on your sort. In this case, you can collect terms of the form N-X where they satisfy, place(_, N, X):
setof(N-X, place(S,N,X), OrderedList). % Assuming `S` is bound
This will result in:
OrderedList = [1-b, 2-a, 3-d, 4-c]
Then you can use maplist/3 to get your list by defining a simple mapping:
foo(_-X, X).
maplist(foo, OrderedList, List).
This will then give you just the elements you want.
Your complete predicate would look like:
foo(_-X, X).
placeSort(S, List) :-
setof(N-X, place(S,N,X), OrderedList),
maplist(foo, OrderedList, List).
Obviously, you'd choose sensible names for your facts, predicates, and variables. My names (foo, List, OrderedList, S, N, X) are not sufficient, in my opinion, for an application but I am not familiar with your actual problem domain, so this is just for illustration purposes.
As an aside, note that in your facts Store is a variable, so that's not particularly meaningful in the facts. I kept your use of S in your predicate, but it's unclear to me how you really intend to use it.
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
I have a predict which gets first N elements:
nfirst(N, _, Lnew) :- N =< 0, Lnew = [].
nfirst(_, [], []).
nfirst(N, [X|Y], [X|Y1]) :- N1 is N - 1, nfirst(N1, Y, Y1).
It works:
% nfirst(3,[1,2,3,4,5,6],X).
% X = [1, 2, 3]
I need a predict for divide list like below:
% divide([a,b,c,d,e,f,g,h],[3,2,1,2],X).
% X = [[a,b,c],[d,e],[f],[g,h]]
The best way is using nfirst.
Very similar question to the one I answered here. Again, the trick is to use append/3 plus length/2 to "bite off" a chunk of list, per my comment above:
split_at(N, List, [H|[T]]) :- append(H, T, List), length(H, N).
If you run that, you'll see this:
?- split_at(4, [1,2,3,4,5,6,7,8], X).
X = [[1, 2, 3, 4], [5, 6, 7, 8]] ;
So this is the backbone of your program, and now you just need the usual recursive stuff around it. First, the base case, which says, if I'm out of list, I should be out of split locations, and thus out of result:
divide([], [], []).
Note that explicit base cases like this make your program more correct than something like divide([], _, _) because they will cause you to fail if you get too many split locations for your list size.
Now the recursive case is not difficult, but because split_at/3 puts two things together in a list (probably a bad choice, you could make split_at/4 as an improvement) you have to take them out, and it clouds the logic a bit here while making (IMO) a nicer API on its own.
divide(List, [Split|Splits], [Chunk|Rest]) :-
split_at(Split, List, [Chunk, Remainder]),
divide(Remainder, Splits, Rest).
This should be fairly straightforward: we're just taking a Split location, using it to chop up the List, and repeating the processing on what's left over. It seems to work as you expect:
?- divide([a,b,c,d,e,f,g,h],[3,2,1,2],X).
X = [[a, b, c], [d, e], [f], [g, h]] ;
false.
Hope this helps! Compare to the other answer, it may illuminate things.
I'm new in Prolog and trying to do some programming with Lists
I want to do this :
?- count_occurrences([a,b,c,a,b,c,d], X).
X = [[d, 1], [c, 2], [b, 2], [a, 2]].
and this is my code I know it's not complete but I'm trying:
count_occurrences([],[]).
count_occurrences([X|Y],A):-
occurrences([X|Y],X,N).
occurrences([],_,0).
occurrences([X|Y],X,N):- occurrences(Y,X,W), N is W + 1.
occurrences([X|Y],Z,N):- occurrences(Y,Z,N), X\=Z.
My code is wrong so i need some hits or help plz..
Here's my solution using bagof/3 and findall/3:
count_occurrences(List, Occ):-
findall([X,L], (bagof(true,member(X,List),Xs), length(Xs,L)), Occ).
An example
?- count_occurrences([a,b,c,b,e,d,a,b,a], Occ).
Occ = [[a, 3], [b, 3], [c, 1], [d, 1], [e, 1]].
How it works
bagof(true,member(X,List),Xs) is satisfied for each distinct element of the list X with Xs being a list with its length equal to the number of occurrences of X in List:
?- bagof(true,member(X,[a,b,c,b,e,d,a,b,a]),Xs).
X = a,
Xs = [true, true, true] ;
X = b,
Xs = [true, true, true] ;
X = c,
Xs = [true] ;
X = d,
Xs = [true] ;
X = e,
Xs = [true].
The outer findall/3 collects element X and the length of the associated list Xs in a list that represents the solution.
Edit I: the original answer was improved thanks to suggestions from CapelliC and Boris.
Edit II: setof/3 can be used instead of findall/3 if there are free variables in the given list. The problem with setof/3 is that for an empty list it will fail, hence a special clause must be introduced.
count_occurrences([],[]).
count_occurrences(List, Occ):-
setof([X,L], Xs^(bagof(a,member(X,List),Xs), length(Xs,L)), Occ).
Note that so far all proposals have difficulties with lists that contain also variables. Think of the case:
?- count_occurrences([a,X], D).
There should be two different answers.
X = a, D = [a-2]
; dif(X, a), D = [a-1,X-1].
The first answer means: the list [a,a] contains a twice, and thus D = [a-2]. The second answer covers all terms X that are different to a, for those, we have one occurrence of a and one occurrence of that other term. Note that this second answer includes an infinity of possible solutions including X = b or X = c or whatever else you wish.
And if an implementation is unable to produce these answers, an instantiation error should protect the programmer from further damage. Something along:
count_occurrences(Xs, D) :-
( ground(Xs) -> true ; throw(error(instantiation_error,_)) ),
... .
Ideally, a Prolog predicate is defined as a pure relation, like this one. But often, pure definitions are quite inefficient.
Here is a version that is pure and efficient. Efficient in the sense that it does not leave open any unnecessary choice points. I took #dasblinkenlight's definition as source of inspiration.
Ideally, such definitions use some form of if-then-else. However, the traditional (;)/2 written
( If_0 -> Then_0 ; Else_0 )
is an inherently non-monotonic construct. I will use a monotonic counterpart
if_( If_1, Then_0, Else_0)
instead. The major difference is the condition. The traditional control constructs relies upon the success or failure of If_0 which destroys all purity. If you write ( X = Y -> Then_0 ; Else_0 ) the variables X and Y are unified and at that very point in time the final decision is made whether to go for Then_0 or Else_0. What, if the variables are not sufficiently instantiated? Well, then we have bad luck and get some random result by insisting on Then_0 only.
Contrast this to if_( If_1, Then_0, Else_0). Here, the first argument must be some goal that will describe in its last argument whether Then_0 or Else_0 is the case. And should the goal be undecided, it can opt for both.
count_occurrences(Xs, D) :-
foldl(el_dict, Xs, [], D).
el_dict(K, [], [K-1]).
el_dict(K, [KV0|KVs0], [KV|KVs]) :-
KV0 = K0-V0,
if_( K = K0,
( KV = K-V1, V1 is V0+1, KVs0 = KVs ),
( KV = KV0, el_dict(K, KVs0, KVs ) ) ).
=(X, Y, R) :-
equal_truth(X, Y, R).
This definition requires the following auxiliary definitions:
if_/3, equal_truth/3, foldl/4.
If you use SWI-Prolog, you can do :
:- use_module(library(lambda)).
count_occurrences(L, R) :-
foldl(\X^Y^Z^(member([X,N], Y)
-> N1 is N+1,
select([X,N], Y, [X,N1], Z)
; Z = [[X,1] | Y]),
L, [], R).
One thing that should make solving the problem easier would be to design a helper predicate to increment the count.
Imagine a predicate that takes a list of pairs [SomeAtom,Count] and an atom whose count needs to be incremented, and produces a list that has the incremented count, or [SomeAtom,1] for the first occurrence of the atom. This predicate is easy to design:
increment([], E, [[E,1]]).
increment([[H,C]|T], H, [[H,CplusOne]|T]) :-
CplusOne is C + 1.
increment([[H,C]|T], E, [[H,C]|R]) :-
H \= E,
increment(T, E, R).
The first clause serves as the base case, when we add the first occurrence. The second clause serves as another base case when the head element matches the desired element. The last case is the recursive call for the situation when the head element does not match the desired element.
With this predicate in hand, writing count_occ becomes really easy:
count_occ([], []).
count_occ([H|T], R) :-
count_occ(T, Temp),
increment(Temp, H, R).
This is Prolog's run-of-the-mill recursive predicate, with a trivial base clause and a recursive call that processes the tail, and then uses increment to account for the head element of the list.
Demo.
You have gotten answers. Prolog is a language which often offers multiple "correct" ways to approach a problem. It is not clear from your answer if you insist on any sort of order in your answers. So, ignoring order, one way to do it would be:
Sort the list using a stable sort (one that does not drop duplicates)
Apply a run-length encoding on the sorted list
The main virtue of this approach is that it deconstructs your problem to two well-defined (and solved) sub-problems.
The first is easy: msort(List, Sorted)
The second one is a bit more involved, but still straight forward if you want the predicate to only work one way, that is, List --> Encoding. One possibility (quite explicit):
list_to_rle([], []).
list_to_rle([X|Xs], RLE) :-
list_to_rle_1(Xs, [[X, 1]], RLE).
list_to_rle_1([], RLE, RLE).
list_to_rle_1([X|Xs], [[Y, N]|Rest], RLE) :-
( dif(X, Y)
-> list_to_rle_1(Xs, [[X, 1],[Y, N]|Rest], RLE)
; succ(N, N1),
list_to_rle_1(Xs, [[X, N1]|Rest], RLE)
).
So now, from the top level:
?- msort([a,b,c,a,b,c,d], Sorted), list_to_rle(Sorted, RLE).
Sorted = [a, a, b, b, c, c, d],
RLE = [[d, 1], [c, 2], [b, 2], [a, 2]].
On a side note, it is almost always better to prefer "pairs", as in X-N, instead of lists with two elements exactly, as in [X, N]. Furthermore, you should keep the original order of the elements in the list, if you want to be correct. From this answer:
rle([], []).
rle([First|Rest],Encoded):-
rle_1(Rest, First, 1, Encoded).
rle_1([], Last, N, [Last-N]).
rle_1([H|T], Prev, N, Encoded) :-
( dif(H, Prev)
-> Encoded = [Prev-N|Rest],
rle_1(T, H, 1, Rest)
; succ(N, N1),
rle_1(T, H, N1, Encoded)
).
Why is it better?
we got rid of 4 pairs of unnecessary brackets in the code
we got rid of clutter in the reported solution
we got rid of a whole lot of unnecessary nested terms: compare .(a, .(1, [])) to -(a, 1)
we made the intention of the program clearer to the reader (this is the conventional way to represent pairs in Prolog)
From the top level:
?- msort([a,b,c,a,b,c,d], Sorted), rle(Sorted, RLE).
Sorted = [a, a, b, b, c, c, d],
RLE = [a-2, b-2, c-2, d-1].
The presented run-length encoder is very explicit in its definition, which has of course its pros and cons. See this answer for a much more succinct way of doing it.
refining joel76 answer:
count_occurrences(L, R) :-
foldl(\X^Y^Z^(select([X,N], Y, [X,N1], Z)
-> N1 is N+1
; Z = [[X,1] | Y]),
L, [], R).
I'm trying to make a Prolog predicate iscontained/2: iscontained(List, Search) where it returns true. if the Search is listed within the given List, false. if not. And if it is a variable that is inputted, then it just returns that it equals each element in the list.
Example:
?- iscontained([a, b, c], a).
true.
?- iscontained([a, b, c], d).
false.
?- iscontained([a, b, c], A).
A = a;
A = b;
A = c;
false.
I need a shove in the right direction, not asking for a hand out, unless you know a quick way to do it. Any help is appreciated, thanks.
Please note that the frequently proposed member/2 predicate admits solutions that are no lists at all:
?- member(e,[e|nonlist]).
true.
This is not a big problem in many situations, but should be mentioned nevertheless.
A natural, symmetric definition that only admits lists uses DCGs:
... --> [] | [_], ... .
iscontained(Es, E) :-
phrase((...,[E],...), Es).
The ... is a non-terminal which denotes an arbitrary sequence.
While this is entirely overkill for this tiny example, it gives you a template for more interesting patterns. Like
iscontainedtwice(Es, E) :-
phrase((...,[E],...,[E],...), Es).
You will need to consider two cases. I'll leave the body of the rules up to you.
iscontained([A|Xs],A)
iscontained([X|Xs],A)
[edited to remove reference to the empty list: the empty list contains nothing: if encountered, the predicate fails.]
Now that you certainly already came up with a solution, I'd like to mention one thing:
The classical version:
member(Item, [Item|_List]).
member(Item, [_Head|List]) :- member(Item, List).
leaves a choice point after having found the last element possible, ie:
?- member(A, [1, 2, 3]).
A = 1;
A = 2;
A = 3;
false.
while
member2(Item, [Head|List]) :-
member2(List, Item, Head).
member2(_List, Item, Item).
member2([Head|List], Item, _PreviousHead) :-
member2(List, Item, Head).
treats the empty list at the same time as the last element and allows optimization:
?- member2(A, [1, 2, 3]).
A = 1;
A = 2;
A = 3.
That's the version used in SWI-Prolog (and certainly Jekejeke Prolog and maybe others). Its author is Gertjan van Noord.
That's just meant as a reminder that, while the exercise of coming up yourself with a member/2 implementation is excellent, it should not lead you not use the built-ins afterwards, they're often fine tuned and more efficient!