arithmetic operations on list elements in prolog - list

I got this task in Prolog and I don't know how to approach it.
I have to write predicate expression(List,Outcome,Result) which builds an arithmetic expression using every element from List. It gives a Result which must be equal to Outcome before backtracking.
For example:
?- expression([1, 2, 3, 4], 2, X).
X = 1+ (2+ (3-4))
or
?- expression([1, 2, 3, 4, 5], 2, X).
X = 1+ ((2-3)*4+5)
I've tried something like this:
operation(A, B, A + B).
operation(A, B, A - B).
operation(A, B, A * B).
operation(A, B, A div B).
expression([],_,_).
expression([A,B,D|List],Outcome,Result) :-
operation(A,B,C),
operation(C,D,Result),
Outcome is Result.
And this works for list of three elements, but I want to use it for different sizes of list. I assume I have to use recursion, but how? And how to add the possibility of using parentheses?

Each expression is a tree. Its leaves' fringe is always the same list - the given 1st argument. Its structure reflects parenthesization. Then for each tree its nodes - when "viewed from above" - form a list of arithmetic binary operators. For each tree you need to consider all combinations of these operators.
expression( List, Result, Xpr ) :-
tree( List, T, Nodes ), % N elts in List, N-1 in Nodes
combinations( Nodes, [+,-,*,/] ), % or whatever ops you want to use
evaluate( T, Result ),
parenthesized( T, Xpr ).
combinations( Nodes, Ops ) :- % use_module( library( lambda )).
maplist( \X^(member(X, Ops)), Nodes ).
All that's left is to implement what's left to implement.

Related

Comparing list elements to a predicate

I need to construct a a predicate compare_to_predicate/3. It takes in a given predicate and list of numbers and proceeds to compare every element in the list using that predicate.
The given predicates are
- is_odd
- is_even
- greater_than(X)
For example:
?- compare_to_predicate([8,13,1,500], [is_odd], X).
X = [13, 1].
?- compare_to_predicate([8,13,1,500], [greater_than, 10], X).
X = [13, 500].
What I have come up with thus far is:
is_odd(X):- 1 is mod(X,2).
is_even(X):- 0 is mod(X,2).
greater_than(X,Y):- X<Y.
compare_to_predicate([],_,[]).
compare_to_predicate([H|Tail],Functor,[H|X]):- Term =.. [Functor,H], Term, compare_to_predicate(Tail,Functor,X).
I have a number of issues:
1)
?- compare_to_predicate([2,10,8,300],is_even,X).
will produce
X = [2, 10, 8, 300].
but
compare_to_predicate([2,10,8,301],is_even,X).
will produce
false.
I assume it has to do with the predicate encountering a number that will not return true on is_even and then terminating the whole compare_to_predicate with a false. In that case is the solution to somehow make it ignore odd numbers instead of evaluating them? If so, how would I do that?
2)
It seems that the given predicate I pass into compare_to_predicate has to have the type List as seen in
?- compare_to_predicate([8,13,1,500], [is_odd], X).
and
?- compare_to_predicate([8,13,1,500], [greater_than, 10], X).
I am currently simply passing a normal predicate into the Term. I'm not quite sure on how I'm supposed to do that.
It seems that compare_to_predicate([H|Tail],[Functor],[H|X]):- Term =.. [Functor,H], Term, compare_to_predicate(Tail,[Functor],X)
did the trick here. Finally:
3)
?- compare_to_predicate([8,13,1,500], [greater_than, 10], X).
It seems I need to make compare_to_predicate able to take in predicates with different arity as shown here. Is the solution supposed to be something like this?
(Term =.. [Functor,A]; Term=.. [Functor,A,B]).
Any help will be appreciated.
You kind of need to decide what compare_to_predicate/3 is supposed to do with values that fail the goal. I see basically three ways this can go:
It can behave as a filter, and the third argument is unified with the values in the first argument that pass.
It can behave as a for-all, and the third argument is unified with the whole list if they all pass and fails otherwise (your current behavior)
It can behave like an for-each that just applies the predicate to each item in the list and discards the result. There is no meaningful value for the third parameter in this case.
By the way, the term surgery you're doing with =../2 is not necessary; call/N will do the right thing if you do something like call(greater(10), 20), so you can just allow the user to call your predicate like this: compare_to_predicate([1,2,3,4], greater(2), X) and use call to build the goal.
Doing the first one is pretty straightforward:
filter([], _, []).
filter([X|Xs], P, Result) :-
filter(Xs, P, Xs1),
(call(P, X) -> Result = [X|Xs1] ; Result = Xs1).
Doing the second one is also pretty straightforward:
forall([], _, []).
forall([X|Xs], P, [X|Xs]) :- call(P, X), forall(Xs, P, Xs).
Doing the third one is not terribly hard:
foreach([], _).
foreach([X|Xs], G) :- once(call(G, X) ; true), foreach(Xs, G).

Turn a tuple into a list

I've searched and strangely didn't find much on this . How can I turn a tuple of unknown length into a list in prolog?
For example:
List=[1,2,3,4], Tuple=(1,2,3,4).
When you are stuck with term conversion, it is often a good idea to get an understanding of what a term actually denotes.
You can use write_canonical/1 to get the canonical form of a term.
In your case:
?- Tuple = (1,2,3,4), write_canonical(Tuple).
','(1,','(2,','(3,4)))
Tuple = (1, 2, 3, 4).
This makes it clear that we are actually talking about compound terms of the form (A,B)—written in prefix notation as ','(A,B)—whose arguments are either integers or again such compound terms. Such terms are also called "and lists" in Prolog, and Prolog goals also have such a shape. Note in particular that these are not really "tuples", certainly not in a "first class citizen" sense, only compound terms much like any other compound terms.
Thus, we only need to reason about these 2 possible cases:
integer
term of the form (A,B).
Further, when describing lists, always consider using dcg notation for convenience.
For example:
tuple_list(I) --> { integer(I) }, [I].
tuple_list((A,B)) --> tuple_list(A), tuple_list(B).
Now we have:
?- Tuple = (1,2,3,4), phrase(tuple_list(Tuple), Ls).
Tuple = (1, 2, 3, 4),
Ls = [1, 2, 3, 4].
This solves your task of converting from such terms to lists.
However, the most general query yields no answers:
?- phrase(tuple_list(Tuple), Ls).
ERROR: Out of local stack
I leave generalizing tuples_list//1 so that it works in all directions as an exercise.
You have got two useful answers already. As mentioned, you generally don't use a "tuple" in the notation (1, 2, 3, 4): this is not a flat data structure as in say Haskell, it is a nested data structure. The Prolog way would be to use a term with arity 4, for example, quadruple(1, 2, 3, 4). The name of course doesn't matter, but usually, you use a descriptive name of some sort.
Then, to convert the arguments of a term to a list, you use the "univ" operator =.. like this:
Term =.. [Name|Arguments]
so:
?- foo(1, 2, 3, 4) =.. [foo|Args].
Args = [1, 2, 3, 4].
In the special case of tuples with two elements (pairs), the functor -/2 is commonly used. The dash is also an infix operator, so you can write 1-a instead of -(1, a). Quite a few library predicates that work on pairs expect them as -/2, for example:
?- keysort([1-c, 2-a, -(0, b), 1-a], S).
S = [0-b, 1-c, 1-a, 2-a].
tuples in Prolog are rarely used, but a quick conversion could be
list_tuple([A,B|L], (A,R)) :- list_tuple([B|L], R).
list_tuple([A,B], (A,B)). % I don't think unary tuples make sense...
?- list_tuple([1,2,3,4],T).
T = (1, 2, 3, 4) ;
false.
this doesn't work very well on 'backward mode'
?- list_tuple(L,(1,2,3,4)).
L = [1, 2, 3, 4] ;
L = [1, 2, (3, 4)] ....
you can try to place a cut to get it deterministic, I've provided clauses in order as required...
Using SWI-Prolog, "tuples" and lists can be converted using the built-in library predicate comma_list/2.
comma_list(C, [1, 2, 3]).
% C = (1, 2, 3).
comma_list((1, 2, 3), L).
% L = [1, 2, 3].
comma_list((a, foo(bar), C), [a, B, c]).
% C = c,
% B = foo(bar).
See the documentation for more usage examples.
It can be a bit tricky to search for because the documentation doesn't necessarily refer to terms like (1, 2, 3) as a "tuple", but it describes them as a "nested term over the ,/2 functor". Also provided is semicolon_list/2 which will perform the same operations with the ;/2 functor instead.

Prolog List, check additions to list

I have created a predicate that will check whether all the items in a list satisfy a condition.
For this example, the predicate checks that all elements are in multiples of two Check_Multiples/1, which works quite well.
How would I check to see what item could be added to the beginning or the end of the list, and still satisfy the predicate?
I am trying to make the return a list.
For example:
[2,4,6]
should return [8] as (as the predicate does not allow 0)
[6,8,10]
should return [4,12]
The following code should do the trick, given that Check_Multiples checks if every element of the list is a multiple of two in an ascending order. I'm guessing that was a condition, otherwise if lists such as [4, 6, 4, 4, 8] were allowed you could just check if every element modulus 2 is equal to 0.
additionsToList([H|T], ResultList) :-
Check_Multiples([H|T]),
firstElement(H, First),
lastElement(T, Last),
append([First],[Last], Z),
flatten(Z, ResultList).
firstElement(2, []).
firstElement(First, X) :-
X is First-2.
lastElement([H|[]], X) :-
X is H+2.
lastElement([_|T], X) :-
lastElement(T, X).

Prolog Calling predicates within predicates correctly

I have two predicates in Prolog, the first one does return a correct dot product of two lists(vectors w/e) ... the second is when you take a list times a list of lists(matrix) which will return a list. The second one fails when I try to pass anything such as ([1,2],[[3,4],[5,6],[7,8]], X). Anyone well versed in Prolog see my mistake? I am kinda stuck since tracing and prolog itself just returns a fail all the time.
getDotProd([],[],0.0).
getDotProd([H1|T1],[H2|T2], N):-
getDotProd(T1,T2,N1),
N is N1 + (H1 * H2).
vecTimesMatrix(_,[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
N is getDotProd(List, MH, _),
vecTimesMatrix(List, Mtail, N).
Updated Code thus far now:
getDotProd([],[],0.0).
getDotProd([H1|T1],[H2|T2], N):-
getDotProd(T1,T2,N1),
N is N1 + (H1 * H2).
vecTimesMatrix([],[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
getDotProd(List, MH, N),
vecTimesMatrix(List, Mtail, N).
Your remaining problem is in your vecTimesMatrix predicate:
vecTimesMatrix([],[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
getDotProd(List, MH, N),
vecTimesMatrix(List, Mtail, N).
Issues:
In the second clause, the first argument is given as [List] which would imply a list of a single element (List). Subsequent calls to getDotProd and vecTimesMatrix in the clause indicate that this should simply be List.
In the second clause, the third argument is shown simply as a list of one argument: [N]. So the third argument never "builds" a list. Additionally, the recursive call to vecTimesMatrix has N as its third argument, and that argument had already been instantiated by the prior query to getDotProd as the dot product of the vector List and the vectory MH. Logically, the recursive call should be saying that the vector product of List with Mtail is the tail of the final product.
The base case assumes that the first argument reduces to [], but this is not so. List always remains as-is throughout the recursive process. So instead of [] you should have _ (it will keep its value, but you don't care about it in the base case).
The base case has as a second argument [[]], but that's not the correct form for an empty list. That's actually a list consisting of one element, that element being the empty list. In reality, even though the second argument is a "list of lists", the empty list is still [].
Putting it all together (and renaming predicates per de facto conventions using underscores rather than camel case):
get_dot_prod([], [], 0.0). % Dot product of empty vectors is 0.0
% (Dot prod of vectors of unequal length
% is not defined and will fail)
get_dot_prod([H1|T1], [H2|T2], N) :- % N is dot product of [H1|T1] [H2|T2] if...
get_dot_prod(T1, T2, N1), % N1 is dot product of T1 T2, and
N is N1 + (H1 * H2). % N is N1 + (H1*H2) [evaluated]
vec_times_matrix(_, [], []). % Product of any vector with
% empty matrix is empty
vec_times_matrix(List, [MH|Mtail], [N|Ntail]):-
% [N|Ntail] is List x [MH|Mtail] if...
get_dot_prod(List, MH, N), % N is dot product of List and MH, and
vec_times_matrix(List, Mtail, Ntail). % Ntail is List x Mtail
This will yield:
| ?- vec_times_matrix([1,2],[[1,0],[0,1]], M).
M = [1.0,2.0] ? a
no
| ?- vec_times_matrix([1,2],[[1,0],[0,1],[1,1]], M).
M = [1.0,2.0,3.0] ? a
(1 ms) no
I added the comments in the code above to illustrate, in a simple way, how to think of the prolog predicate logic, which aids in defining them. As was pointed out already, the prolog "predicate" doesn't act as a "function". It describes a logical relation between entities which will either succeed or fail.
Once you learn to think how prolog thinks (relationally), you'll find it more enjoyable. :)
There are several problems in your code. First, you define both getDotProd/4 and getDotProd/3 predicates. The first one is a typo. I.e. you base case for the getDotProd/3 predicate have a duplicated argument and it should be:
getDotProd([], [], 0).
Second, in the second predicate, vecTimesMatrix/3, you have a goal, a call to the built-in predicate is/2, that will cause an exception:
N is getDotProd(List, MH, _)
You cannot define your own functions on standard Prolog. You need to replace that goal with:
getDotProd(List, MH, N)
There are other problems but this should help you progress.

Prolog length of a list

How can I calculate the length of a list
?- size_sub([[b,a,g], [9,3,7,4], [6]], X).
X = [3, 4, 1].
?- size_sub([[c,g,e,w], [7]], X).
X = [4, 1].
?- size_sub([], X).
X = [].
Ok you need to start with the base case which is the last answer
so size_sub([],X). is true if X=[] so first you write that as a rule.
size_sub([],[]).
Then you need to do the inductive step a list that is one longer than the previous. I am going to assume that you have a size/2 function for determining the size of a single list (if not please comment).
So the inductive step is going to operate on the length of the first parameter so N->N+1. We would represent this by striping off the head of the list syntax will be [H|T] now the second parameter (your answer) is going to be the length of H with the result of calling size_sub on T. As we cannot specify rules in the parameters in the header we will use N to represent the length of H and T2 to represent the result of size_sub on T.
So the first part of the rule becomes size_sub([H|T],[N|T2]):-
now we follow it with the predicates that will assert the values for N and T2.
size(H,N),
size_sub(T,T2).
putting that all together you get
size_sub([],[]).
size_sub([H|T],[N|T2]):-
size(H,N),
size_sub(T,T2).
size/2 is a far simpler case and following the same process of base + inductive you should be able to create the rules for it. Please comment if you need further help.
** EDIT - Request for size/2 definition **
To define size/2
Start with the base case, the empty list has a size of 0.
size([],0).
Now the inductive step. The size of list of length(N+1) is the size of a list of length(N). So lets define our list as [_|T] I've defined the list using _ to represent the head because we never use it so we can just use the anonymous variable. Lets use N to represent the length of T, and M to be N+1.
so
size([_|T],M):-
now lets define N
size(T,N),
and finally assert that M is equal to N + 1
M is N+1.
so putting everything together
size([],0).
size([_|T],N):-
size(T,M),
N is M+1.
size_sub([],[]).
size_sub([H|T],[N|T2]):-
size(H,N),
size_sub(T,T2).
To map length/2 over a list of lists, we can use the meta-predicate maplist/3 like this:
size_sub(Xss,Ls):-
maplist(length,Xss,Ls).