Prolog - Recursive Function Abs / Create new list - prolog

I want a function that given a Point, and a List of points it calculates:
the absolute value of (Point - PointofList), for every point of the list.
I have this code so far, but I seem to be failing on the recursive part.
absL((X,Y),[],Result) :- Result.
absL((X,Y),[(X2,Y2)|Z], R) :- ABSX is abs(X-X2),
ABSY is abs(Y-Y2),
append([(ABSX,ABSY)], NL, R),
absL((X,Y),Z,NL).

You have defined the base case wrong.
When there are no more points in the list of points, the resulting list should be an empty list, but you are just leaving an uninstantiated variable:
So, your base case should read:
absL((_,_),[],[]).
I left the first argument with a structure using unnamed variables because the coordinates for the given point are not needed for the base case.
Your recursive clause is a bit more complex than it should. You really don't need to use append/3 to build the resulting list. You can build the list directly in the head of the clause:
absL((X,Y),[(X2,Y2)|Z], [(ABSX,ABSY)|NL]) :-
ABSX is abs(X-X2),
ABSY is abs(Y-Y2),
absL((X,Y),Z,NL).
The recursive step will add the new distance before the recursive call and just insert this values when unifying the third argument at return of the recursive call.

this clause absL((X,Y),[],Result) :- Result. attempt to call Result, at least in Prologs that accept such syntax.
since #gusbro already shows the required correction, I'll show an alternative:
absL((X,Y), L_In, L_Out) :-
maplist(absPoint((X,Y), L_In, L_Out).
absPoint((X, Y), (X2,Y2), (ABSX, ABSY)) :-
ABSX is abs(X-X2),
ABSY is abs(Y-Y2).

Related

Build a list with abs() in prolog

I am attempting to write a predicate for the following task.
Write a predicate distances(Bs, B, Ds) where Bs and Ds are lists of variables such that
the ith element of the Ds is the absolute difference between the variable B and the ith element of Bs
know this is incorrect but it what I believe I roughly should be trying to do
distances([],_,[]).
distances([H|T],B,A) :-abs(H - B,A),distances(T,B,A)
Do I need to return the result of the abs predicate into the recusive call to distance?
I can use abs to calculate the correct value for each entry in the list but how do I then put that information into a list which can then be returned?
A predicate does not return. A predicate succeeds, fails, (gets stuck in an infinite loop, or raises an error). One uses unification to provide results. In fact here your third parameters Ds should probably provide the result.
We thus can unify the absolute value D to the head of the list of the third parameter, and recurse on the tail Ds:
distances([], _, []).
distances([H|T], B, [D|Ds]) :-
abs(H - B, D),
distances(T, B, Ds).

How to call a list of list in prolog

How to call a list of list in Prolog for exemple I have this list :
list([[1,2,3],[4,5],[6,7]]).
I want to call my list in the element_at function :
element_at(X,[X|_],1).
element_at(X,[_|L],K) :-
element_at(X,L,K1),
K is K1 + 1.
When i call
element_at(X,list,2)
I don't have a result.
I don't have a result.
Well, you do have a result: failure. But you expected success. Here is a very general method how you can locate such errors in Prolog yourself:
If you encounter unexpected failure, simply generalize your program.
In your particular case, element_at(X,list,2) fails. Maybe it should be 3 in place of 2? Or maybe another number? There is an easy way of guessing in Prolog: Simply replace 3 by a variable! By the same token, you can remove goals in your definition. I will use * to mark those.
Here is a generalization of your program that still fails — and thus there must be an error in the remaining part:
:- op(950, fy, *).
*(_).
?- element_at(X, list, _/*2*/).
element_at(X,[_/*X*/|_],_/*1*/).
element_at(X,[_|L],K) :-
* element_at(X,L,K1),
* K is K1 + 1.
We retrieve a value from our knowledge base by a call to a predicate,
list(L)
so the whole query at the prompt is
list(L), element_at(X, L, 2).
Or define it in a source file,
my_query(X) :- list(L), element_at(X, L, 2).

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.

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

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]]].

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