ERROR: "Out of global stack" when processing Prolog list of pairs - prolog

In SWI-Prolog, I have a list whose elements are pairs of the form Key-ValuesList. For instance, one such list may look like:
[1-[a,b],2-[],3-[c]]
I would like to transform this list into a nested list of pairs of the form Key-[Value], where Value is an element in ValuesList. The above example would be transformed into:
[[1-[a],2-[],3-[c]], [1-[b],2-[],3-[c]]]
My current solution is the following:
% all_pairs_lists(+InputList, -OutputLists).
all_pairs_lists([], [[]]).
all_pairs_lists([Key-[]|Values], CP) :-
!,
findall([Key-[]|R], (all_pairs_lists(Values,RCP), member(R,RCP)), CP).
all_pairs_lists([Key-Value|Values], CP) :-
findall([Key-[V]|R], (all_pairs_lists(Values,RCP), member(V,Value), member(R,RCP)), CP).
Using this predicate, a call of the form
all_pairs_lists([1-[a,b],2-[],3-[c]],OutputLists).
Binds the variable OutputLists to the desired result mentioned above. While it appears correct, this implementation causes an "Out of global stack" error when InputList has very long lists as values.
Is there a less stack consuming approach to doing this? It would seem like quite a common operation for this type of data structure.

Well, to sum it up, you're doing it wrong.
In Prolog, when we want to express a relation instead of a function (several results possible instead of one), we don't use findall/3 and member/2 directly. We rather state what the relation is and then maybe once it's done if we need a list of results we use findall/3.
Here what it means is that we want to express the following relation:
Take a list of Key-Values and return a list of Key-[Value] where Value is a member of the Values list.
We could do so as follows:
% The base case: handle the empty list
a_pair_list([], []).
% The case where the Values list is empty, then the resulting [Value] is []
a_pair_list([Key-[]|List], [Key-[]|Result]) :-
a_pair_list(List, Result).
% The case where the Values list is not empty, then Value is a member of Values.
a_pair_list([Key-[Not|Empty]|List], [Key-[Value]|Result]) :-
member(Value, [Not|Empty]),
a_pair_list(List, Result).
Once this relation is expressed, we can already obtain all the info we wish:
?- a_pair_list([1-[a, b], 2-[], 3-[c]], Result).
Result = [1-[a], 2-[], 3-[c]] ;
Result = [1-[b], 2-[], 3-[c]] ;
false.
The desired list is now just a fairly straight-forward findall/3 call away:
all_pairs_lists(Input, Output) :-
findall(Result, a_pair_list(Input, Result), Output).
The important thing to remember is that it's way better to stay away from extra logical stuff: !/0, findall/3, etc... because it's often leading to less general programs and/or less correct ones. Here since we can express the relation stated above in a pure and clean way, we should. This way we can limit the annoying use of findall/3 at the strict minimum.

As #Mog already explained clearly what the problem could be, here a version (ab)using of the basic 'functional' builtin for list handling:
all_pairs_lists(I, O) :-
findall(U, maplist(pairs_lists, I, U), O).
pairs_lists(K-[], K-[]) :- !.
pairs_lists(K-L, K-[R]) :- member(R, L).
test:
?- all_pairs_lists([1-[a,b],2-[],3-[c]],OutputLists).
OutputLists = [[1-[a], 2-[], 3-[c]], [1-[b], 2-[], 3-[c]]].

Related

List with if - plus and minus

I should create a list with integer.It should be ziga_arnitika(L,ML).Which take L list (+) integer and will return the list ML only (-) integer the even numbers of list L.
Warning:The X mod Y calculates X:Y.
Example: ziga_arnitika([3,6,-18,2,9,36,31,-40,25,-12,-5,-15,1],ML).
ML =[-18,-40,-12]
i know for example with not list to use if but not with lists,what i did is..:
something(12) :-
write('Go to L).
something(10) :-
write('Go to Ml).
something(other) :-
Go is other -10,
format('Go to list ~w',[ML]).
You want to compute a list with elements satisfying some properties from a given list. Lists in Prolog have a very simple representation. The empty list is represent by []. A non-empty list is a sequence of elements separated by a comma. E.g. [1,2,3]. Prolog also provides handy notation to split a list between its head (or first element) and its tail (a list with the remaining arguments):
?- [1,2,3] = [Head| Tail].
Head = 1,
Tail = [2, 3].
Walking a list (from its first element to its last element) can be done easily using a simple recursive predicate. The trivial case is when a list is empty:
walk([]).
If a list is not empty, we move to the list tail:
walk([Head| Tail]) :- walk(Tail).
However, if you try this predicate definition in virtually any Prolog system, it will warn you that Head is a singleton variable. That means that the variable appears once in a predicate clause. You can solve the warning by replacing the variable Head with an anonymous variable (which we can interpret as "don't care" variable). Thus, currently we have:
walk([]).
walk([_| Tail]) :- walk(Tail).
We can try it with our example list:
?- walk([1,2,3]).
true.
Prolog being a relational language, what happens if we call the walk/1 predicate with a variable instead?
?- walk(List).
List = [] ;
List = [_4594] ;
List = [_4594, _4600] ;
List = [_4594, _4600, _4606]
...
Now back to the original problem: constructing a list from elements of other list. We want to process each element of the input list and, if it satisfies some property, adding it to the output list. We need two arguments. The simple case (or base case) is again when the input list is empty:
process([], []).
The general case (or recursive case) will be:
process([Head| Tail], [Head| Tail2]) :-
property(Head),
process(Tail, Tail2).
assuming a predicate property/1 that is true when its argument satisfies some property. In your case, being a even, negative integer. But not all elements will satisfy the property. To handle that case, we need a third clause that will skip an element that doesn't satisfy the property:
process([Head| Tail], List) :-
\+ property(Head),
process(Tail, List).
The \+/1 predicate is Prolog standard negation predicate: it's true when its argument is false.
Let's try our process/2 predicate it by defining a property/1 predicate that is true if the argument is the integer zero:
property(0).
A sample call would then be:
?- process([1,0,2,0,0,3,4,5], List).
List = [0, 0, 0] ;
false
We have successfully written a predicate that extracts all the zeros from a list. Note that our query have a single solution. If we type a ; to ask for the next solution at the prompt, the Prolog top-level interpreter will tell us that there are no more solutions (the exact printout depends on the chosen Prolog system; some will print e.g. no instead of falsebut the meaning is the same).
Can you now solve your original question by defining a suitable property/1 predicate?
Update
You can combine the two recursive clauses in one by writing for example:
process([Head| Tail], List) :-
( % condition
property(Head) ->
% then
List = [Head| Tail2],
process(Tail, Tail2)
; % else
process(Tail, List)
).
In this case, we use the Prolog standard if-then-else control construct. Note, however, that this construct does an implicit cut in the condition. I.e. we only take the first solution for the property/1 predicate and discard any other potential solutions. The use of this control construct also prevents using the process/2 predicate in reverse (e.g. calling it with an unbound first argument and a bound second argument) or using it to generate pairs of terms that satisfy the relation (e.g. calling it with both arguments unbound). These issues may or may not be significant depending on the property that you're using to filter the list and on the details of the practical problem that you're solving. More sophisticated alternatives are possible but out of scope for this introductory answer.

Prolog - Domain error: 'acyclic_term ' expected

What I have to do is, write a predicate Multiplication/3, whose first argument is an integer, second argument is a list, and the third argument is the result of multiplying the integer with the list, for example:
?-Multiplication(3,[2,7,4],Result).
should return
Result = [6,21,12].
Here's my code:
Multiplication(X,[],Result).
Multiplication(X,[Head|Tail],Result) :-
Y is X*Head,
append([Result], [Y], L),
append([],L,Result), // HERE
Multiplication(X,Tail,Result).
And I get the following error:
Domain error: 'acyclic_term ' expected, found '#(lists:append([],S_1,S_1),[S_1=[S_1,1]])'
on the second append call.
If anyone knows why I receive the error, how to fix it or another way to solve this, I'm open to ideas.
Your two goals append([Result], [Y], L), append([],L,Result) are exactly the same as:
L = [Result,Y], L = Result.
or even simpler:
L = [L,Y]
which would result either in silent failure or an infinite term. Instead, your Prolog produces an error, so that you can correct your program.
In your original code:
Multiplication(X,[Head|Tail],Result) :-
Y is X*Head,
append([Result], [Y], L),
append([],L,Result), // HERE
Multiplication(X,Tail,Result).
You're getting a "cycle" because you're appending Result to something to get L, then appending something to L to get Result. That's not good. You also have a capitalized predicate name, which is a syntax error. (I assume that, since you ran your code, it wasn't capitalized in the original version.)
You're new proposed solution is overly complicated. Why do you need the 4th argument? Also, your base case for return (which is return(X, [], Result) doesn't make sense, as it has to singleton variables. The use of append/3 is overkill since recursion handles the iteration through the list elements for you.
Starting from the top, you have a common pattern in Prolog where you want to run a query on corresponding elements of two or more lists. A simple recursive solution would look something like this:
multiplication(_, [], []). % Multiplying anything by the empty list is the empty list
multiplication(M, [X|Xs], [XX|XXs]) :-
XX is M * X,
multiplication(M, Xs, XXs).
Another way to implement this kind of pattern in Prolog is with maplist/3. You can first define the query on corresponding elements:
multiply(X, Y, Product) :- Product is X * Y.
Then use maplist/3:
multiplication(M, List, Result) :-
maplist(multiply(M), List, Result).
Maplist will do a call(multiply(M), ...) on each corresponding pair of elements of List and Result.
I edited the code and came up with this:
multiplication(X,[],Result,Result).
multiplication(X,[Head|Tail],List,Result) :-
Y is X*Head,
append(List, [Y], L),
multiplication(X,Tail,L,Result).
return(X,[],Result).
return(X,L,Result) :-
multiplication(X,L,_,Result).
and the query:
return(2,[1,2],Result).
After the first run, it seems to return Result as it should be, but it runs forever.

Prolog - Using Bagof

I've been stuck on a past paper question while studying for my exams.
The question is:
https://gyazo.com/ee2fcd88d67068e8cf7d478a98f486a0
I figured I've got to use findall/bagof/setof because I need to collect a set of solutions. Furthermore, setof seems appropriate because the list needs to be presented in descending order.
My solution so far is:
teams(List) :-
setof((Team, A),
(Team^team(Team, _, Wins, Draws, _), A is Wins*3 + Draws*1),
List).
However the problem is I don't quite get the answers all in one list. I'm very likely using Team^ incorrectly. I'd really appreciate pointers on how I can get a list of ordered tuples in terms of points. The output it gives me is:
X = [(queenspark,43)] ? ;
X = [(stirling,26)] ? ;
X = [(clyde,25)] ? ;
X = [(peterhead,35)] ? ;
X = [(rangers,63)] ? ;
Also, it's not really apparent what kind of order, if any it's in, so I'm also lost as to how setof is ordering.
Whats the best way to approach this question using setof?
Thanks.
Firstly, I would suggest to change (Team,A) to a pair representation A-Team with the A being in front since this is the total score of the team and thus the key you want to use for sorting. Then you would like to prefix the variables that should not be in the list with a ^ in front of the query you want to aggregate. See the following example:
?- setof(A-Team, P^Wins^Draws^L^(team(Team, P, Wins, Draws, L), A is Wins*3 + Draws*1), List).
List = [25-clyde,26-stirling,35-peterhead,43-queenspark,63-rangers]
Since you asked, consider the following query with the pair ordering flipped to Team-A for comparison reasons:
?- setof(Team-A,P^Wins^Draws^L^(team(Team,P,Wins,Draws,L), A is Wins*3 + Draws*1),List).
List = [clyde-25,peterhead-35,queenspark-43,rangers-63,stirling-26]
Now the resulting list is sorted with respect to the teamnames. So A-Team is the opportune choice. You could then use the predicate lists:reverse/2 to reverse the order to a descending list and then define an auxilary predicate pair_second/2 that you can use with apply:maplist/3 to get rid of the leading scores in the pairs:
:- use_module(library(lists)).
:- use_module(library(apply)).
% team(+Name, +Played, +Won, +Drawn, +Lost)
team(clyde,26,7,4,15).
team(peterhead,26,9,8,9).
team(queenspark,24,12,7,5).
team(rangers,26,19,6,1).
team(stirling,25,7,5,13).
pair_second(A-B,B). % 2nd argument is 2nd element of pair
teams(Results) :-
setof(A-Team,
P^Wins^Draws^L^(team(Team, P, Wins, Draws, L), A is Wins*3 + Draws*1),
List),
reverse(List,RList),
maplist(pair_second,RList,Results). % apply pair_second/2 to RList
If you query the predicate now you get the desired results:
?- teams(T).
T = [rangers,queenspark,peterhead,stirling,clyde]
Concerning your question in the comments: Yes, of course that is possible. You can write a predicate that describes a relation between a list of pairs and a list than only consists of the second element of the pairs. Let's call it pairlist_namelist/2:
pairlist_namelist([],[]).
pairlist_namelist([S-N|SNs],[N|Ns]) :-
pairlist_namelist(SNs,Ns).
Then you can define teams/1 like so:
teams(Results) :-
setof(A-Team,
P^Wins^Draws^L^(team(Team, P, Wins, Draws, L), A is Wins*3 + Draws*1),
List),
reverse(List,RList),
pairlist_namelist(RList,Results).
In this case, besides maplist/3, you don't need pair_second/2 either. Also you don't need to include :- use_module(library(apply)). The example query above yields the same result with this version.

Check if all numbers in a list are different in prolog

I want to create a rule in prolog that checks if there's a repeated number in a list.
For example:
for [1,2,3,4] it will return true.
for [1,2,3,3] it will return false because the 3 is repeated
I came up with this rule but it doesn't work
Different([]).
Different([H|T]):-
Member(H,T),
Different(T).
Any ideas?
a compact definition could be
all_diff(L) :- \+ (select(X,L,R), memberchk(X,R)).
i.e. all elements are different if we can't peek one and find it in the rest...
edit
Let's (marginally) improve efficiency: it's useless to check if X is member of the prefix sublist, so:
all_diff(L) :- \+ (append(_,[X|R],L), memberchk(X,R)).
The simplest way to check that all list members are unique is to sort list and check that length of the sorted list is equal of length of the original list.
different(X) :-
sort(X, Sorted),
length(X, OriginalLength),
length(Sorted, SortedLength),
OriginalLength == SortedLength.
Your solution doesn't work because of wrong syntax (facts and predicates should not begin with a capital letter) and a logic error. List is unique if head H is not a member of a tail T of a list and tail T is unique:
different([]).
different([H|T]):-
\+member(H,T),
different(T).
If all numbers in that list are integers, and if your Prolog implementation offers clpfd, there's no need to write new predicates of your own---simply use the predefined predicate all_different/1!
:- use_module(library(clpfd)).
Sample use:
?- all_different([1,2,3,4]).
true.
?- all_different([1,2,3,3]).
false.
Very Simple Answer...
The code:
unique([]).
unique([_,[]]).
unique([H|T]):-not(member(H,T)),unique(T).
Tests:
?-unique([1,2,3,4]).
true.
?-unique([1,2,3,3]).
false.
?-unique([a,b,12,d]).
true
?-unique([a,b,a]).
false
A neat way I came up with is the following:
If all members of a list are different from each other, then if I tell prolog to choose all pairs (I,J) such that I,J are members of the list and also I is equal to J, then for each element in the list it will only be able to find one such pair, which is the element with itself.
Therefore, if we can put all such pairs in a list, then the length of this list should be of the same length of the original list.
Here's my prolog code:
all_diff(L) :-
findall((I,J), (member(I, L), member(J, L), I == J), List),
length(L, SupposedLength),
length(List, CheckThis),
SupposedLength == CheckThis.
The rule provided in the question is very close to a correct answer with minimal library usage. Here's a working version that required only one change, the addition of \+ in the third row:
uniqueList([]).
uniqueList([H|T]):-
\+(member(H,T)),
uniqueList(T).
Explanation of the code for Prolog beginners: The member(H,L) predicate checks if element H is a member of the list L. \+ is Prolog's negation function, so the above code amounts to:
uniqueList([H|T]) returns true if: (H doesn't have a copy in T) and uniqueList(T)
Whereas the code by the original asker didn't work because it amounted to:
uniqueList([H|T]) returns true if: (H has a copy in T) and uniqueList(T)
*I renamed Different() to uniqueList() because it reads better. Convention is to reserve capital letters for variables.
This isn't very efficient, but for each number you can check if it appears again later. Like so:
Different([H|T]):-
CheckSingle(H, [T]),
Different([T]).
Checksingle(_,[]).
Checksingle(Elem, [H, T]):-
Elem != H,
Checksingle(Elem, [T]).

Do you really need to convert Truths to values in Prolog?

I wrote a bubble sort in Prolog (code below). It works but it smells. I'm quite new to prolog. Here's the problematic part:
% Problem: convert the true value to something
% I can actually use.
sorted_value(X,X) :- sorted(X).
sorted_value(X,[]) :- not(sorted(X)).
It's weird I need to use this function to convert a True value to something (in this case, []) and False to another thing in order to use them. Isn't there a cleaner way?
% Bubble Sort a list.
% is the list sorted?
sorted([]).
sorted([Head|[]]).
sorted([First|[Second|Rest]]) :-
min(First,Second,First),
sorted([Second|Rest]).
% swap all pairs in the list that
% needs to be swapped
bubble_sort_list([], []).
bubble_sort_list([Head|[]],[Head]).
bubble_sort_list([First|[Second|Rest]], [One|Solution]) :-
min(First,Second, One),
max(First,Second,Two),
bubble_sort_list([Two|Rest],Solution).
% Problem: convert the true value to something
% I can actually use.
sorted_value(X,X) :- sorted(X).
sorted_value(X,[]) :- not(sorted(X)).
% Repeatedly call bubble_sort until
% the list is sorted
bubble_sort_helper([],List, Solution) :-
bubble_sort_list(List, SortedList),
sorted_value(SortedList, Value),
bubble_sort_helper(Value,SortedList, Solution).
bubble_sort_helper(A,List,List).
% this is what you call.
buuble_sort(List,Solution) :-
bubble_sort_helper([],List,Solution).
Every predicate call either succeeds (possibly several times) or fails. If you think declaratively and really describe what a sorted list is, there would only rarely seem to be a need to explicitly represent the truth value itself in a program. Rather, it would typically suffice to place a predicate call like "ascending(List)" in a Prolog program to describe the case of a sorted list. There seems to be no advantage to instead call a predicate like "ascending(List, T)" and then use T to distinguish the cases. Why not use the implicit truth value of the predicate itself directly? If you really need to reify the truth value, you can for example do it like this to avoid calling ascending/1 twice:
ascending(Ls, T) :-
( ascending(Ls) -> T = true
; T = false
).
Notice how the truth of ascending/1 is used to distinguish the cases.

Resources