Prolog: Check predicate against every item in the list - recursion

Basically, I want to be able to check to see if at least one value in a list satisfies some predicate.
What I have so far:
need(x,y).
check_list(X,[H|T]) :-
need(H,X).
And so this works fine so long as I only have one value in the list. I'm not sure how to make it check the other values. When I try and use recursion I eventually find an element that satisfies the second predicate but it then goes back up the stack which will eventually cause it to be false.How can I make it 'break' essentially?

The backtracking you are seeing during recursion is Prolog attempting to find more ways for the predicate to succeed. This is a fundamental Prolog behavior and is what makes it useful. It seeks to find all of the solutions.
In your case, you only want to confirm one solution to the problem of, An element in the list that meets a specific criterion. For this, you could use a cut:
check_list(X, [H|_]) :-
need(X, H), !. % Don't backtrack after success
check_list(X, [_|T]) :-
check_list(X, T).
Or you could use once/1 which is specifically designed to handle cases where you only want a single solution:
check_list(X, [H|_]) :-
need(X, H).
check_list(X, [_|T]) :-
check_list(X, T).
check_list_once(X, L) :- once(check_list(X, L)).

Here is an example of what you can do.
I want to check is numbers are odd.
is_even(X) :-
X mod 2 =:= 0.
check_list(L, CL) :-
include(is_even, L, CL).
with result
?- check_list([1,2,3,4,5], L).
L = [2, 4].
?- check_list([1,3,5], L).
L = [].

You can use simple recursion:
need(x,y).
check_list(X,[H|T]) :-
( need(H,X) -> true;
check_list(X,T) ).
You can see in the examples below that this definition is deterministic:
?- check_list(y,[1,2,3]).
false.
?- check_list(y,[x,2,3]).
true.
?- check_list(y,[1,2,x]).
true.
?- check_list(Y,[1,2,x]).
Y = y.
?- check_list(Y,[1,2,3]).
false.
?- check_list(Y,[1,x,3]).
Y = y.
?- check_list(Y,[1,X,3]).
Y = y,
X = x.
?- check_list(Y,[1,2,3]), Y = x.
false.
?- check_list(Y,[1,2,3]), Y = y.
false.
?- check_list(Y,[1,2,3]).
false.
?- check_list(Y,[1,2,x]), Y = y.
Y = y.
Though if you want your queries to have uninstantiated variables e.g check_list(Y,[1,2,x]). and you add another fact need(x,z). Then:
?- check_list(Y,[1,2,x]).
Y = y.
Returns only one result and not Y = z. You could use if_/3 from library reif if you want a better definition of check_list/3.

Related

Prolog arithmetic on tuples

The idea is as follows: Suppose I have a list P = [(1,0),(4,3)] or similar. I want to evaluate the polynomial that's defined by this list in the manner: 1X^0 + 4X^3.
To do this, I've written the following:
evaluate(P,X,Y) :- evaluate(P,X,Y,0).
evaluate([],_,S,S).
evaluate([P1,P2|Ps],X,Y,S) :-
S1 is S+P1*X^P2,
evaluate(Ps,X,Y,S1).
Which is supposed to succeed when Y is the sum of the polynomial P, given x=X.
The problem is that when I try and run this code, I get the error:
is/2: Arithmetic: `(',')/2' is not a function
But I have no idea where this is coming from or how to fix it.
I did try splitting the S1 is up in to its segments, but doing that didn't help.
EDIT: Ok, I found out that it's about the way the list is written down. How do I work with tuples in this way within the bounds of Prolog?
Your problem is that your data structure for each item in the list is a tuple as you noted and where you access the values of tuple in the list is not correct.
This
evaluate([P1,P2|Ps],X,Y,S) :-
should be
evaluate([(P1,P2)|Ps],X,Y,S) :-
Notice the parenthesis around P1,P2.
When I run with the change I get
?- evaluate([(1,0),(4,3)],5,Y).
Y = 501.
Also it is common to put the output arguments at the end,
evaluate_01(P,X,Y,0).
as
evaluate_01(P,X,0,Y).
and then change the other predicates as necessary.
evaluate_02(P,X,Y) :- evaluate_02(P,X,0,Y).
evaluate_02([],_,S,S).
evaluate_02([(P1,P2)|Ps],X,S,Y) :-
S1 is S+P1*X^P2,
evaluate_02(Ps,X,S1,Y).
As an interesting option, this can be done with maplist/3 and sumlist/2:
evaluate_poly(Poly, X, R) :-
maplist(evaluate_term(X), Poly, EvaluatedTerms),
sumlist(EvaluatedTerms, R).
evaluate_term(X, (Coeff, Power), TermValue) :-
TermValue is Coeff * (X ^ Power).

Permutation predicate in Prolog

I have written the following in Prolog (I am using version 7.4.0-rc1), trying to define a predicate insertPermutation/2 which is true if and only if both arguments are lists, one a permutation of the other.
delete(X,[X|T],T). % Base case, element equals head.
delete(X,[A|B],[A|C]) :- delete(X,B,C). % And/or repeat for the tail.
insert(X,Y,Z) :- delete(X,Z,Y). % Inserting is deletion in reverse.
insertPermutation([],[]). % Base case.
insertPermutation([H|T],P) :- insertPermutation(Q,T), insert(H,Q,P). % P permutation of T, H inserted.
I have already been made aware that delete is not a good name for the above helper predicate. We are required to write these predicates, and we cannot use the built-in predicates. This is why I wrote the above code in this way, and I chose the name I did (because I first wrote it to delete an element). It is true if and only if the third argument is a list, equal to the list in the second argument with the first instance of the first argument removed.
The insertPermutation predicate recursively tests if P equals a permutation of the tail of the first list, with the head added in any position in the permutation. This way it works to the base case of both being empty lists.
However, the permutation predicate does not behave the way I want it to. For instance, to the query
?- insertPermutation([1,2,2],[1,2,3]).
Prolog does not return false, but freezes. To the query
?- insertPermutation(X,[a,b,c]).
Prolog responds with
X = [a, b, c] ;
X = [b, a, c] ;
X = [c, a, b] ;
X = [a, c, b] ;
X = [b, c, a] ;
X = [c, b, a] ;
after which it freezes again. I see these problems are related, but not how. Can someone point out what case I am missing?
Edit: Two things, this is homework, and I need to solve this problem using an insert predicate. I wrote this one.
The answer is to change the last line
% P permutation of T, H inserted.
insertPermutation([H|T],P) :-
insertPermutation(Q,T),
insert(H,Q,P).
% P permutation of T, H inserted.
insertPermutation(P,[H|T]) :-
insertPermutation(Q,T),
insert(H,Q,P).
The use cases only needed to check if the first element is a permutation of the latter, not the other way around (or vice versa). Anti-climatic, but the answer to my problem.

Why does this Prolog code not run?

I have written the following code to replace all occurrences of a given element in a list, with another specified value. Here's my code:
substitute(X, Y, [], []).
substitute(X, Y, [X|T], [Y|R]) :- substitute(X, Y, T, R).
substitute(X, Y, [H|T], [H|R]) :- H\= X, substitute(X, Y, T, R).
I am trying to call it like this in GNU Prolog:
substitute(2, 3, [2, 2, 2], []).
which results in:
no
What is wrong here? I don't see anything wrong. I am comparing the head of my given list to see if it matches X. If it matches, I replace it in the output list by Y and I recurse on the tail.
In the second case, if the head doesn't match to X, then I recurse on the tail and check if an element of the tail is same as X and then the recursion replaces it as per the 2nd definition. Then at the end of the tail, when an empty list is encountered, the recursion moves to the base case and terminates. I am not sure, why I am not able to run this code. Help please.

Trying to understand a recursive prolog procedure?

This was given as an example in a professor's lecture:
append([ ], A, A).
append([A|B], C, [A|D]) :- append(B,C,D).
Build a list:
?- append([a],[b],Y).
Y = [ a,b ]
Break a list into constituent parts:
?- append(X,[b],[a,b]).
X = [ a ]
?- append([a],Y,[a,b]).
Y = [ b ]
I've spent 3 hours trying to grasp it and can't. Hadn't had any trouble with any prolog concepts preceding this slide. There is no further explanation provided, no other information. This is all. If someone could walk me through how this procedure works, I would love them til death do us part.
The first thing to understand is the :- operator.
this_will_be_true :- if_this_is_true
Basically, whatever is on the right of :- is a precondition. A good example is:
sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y).
This basically means that X and Y are siblings if there exists a parent Z such that Z is the parent of both X and Y.
append([ ], A, A).
This line basically means that appending something to an empty list returns the something. It's the base case in the recursion.
append([A|B], C, [A|D]) :- append(B,C,D).
This line means that appending C to an existing list with A and B returns a list with A and D given that appending C to B returns D.
Build a list:
?- append([a],[b],Y).
Y = [ a,b ]
So, what's going on here is that Prolog returns the only possible value of Y that satisfies the two rules given the two initial values. Let's think about how this happens. This would need to first be evaluated by the second rule. So [A|B] is [a] and C is [b].
So with [A|B] we have to go back to the first rule because B is empty list (it is [ ]). The first rule basically states that we can write [a] as [a|[ ]] and they are the same thing. So now we can go back to the second rule. A is a, B is [ ], and C is [b].
So now let's check the precondition of append(B, C, D). This is append([ ], [b], D). Once again, using the first rule, we can see that D is also [b].
So Y, by the second rule definition, is [A|D]. Now that we know D is [b], we know that Y is [a, b].
I'll only do one of the breaking apart since they're basically the same thing.
?- append(X,[b],[a,b]).
X = [ a ]
So here, Prolog is going to return the only possible value of X so that the statement returns true. Let's take a look at the second rule. So we know that [a, b] is [A|D]. This means that A is a and D is [b]. We also know that C is [b]. So now, we need to look at the precondition to figure out what B is. append(B, C, D) translates to append(B, [b], [b]). Now, using the first rule, we know that B has to be [ ]. So now we know that [A|B] is [a|[ ]] which is the same as [a]. Therefore, X must be [a].
I hope this was a detailed enough explanation.
Below is my own understanding.
Your code describes the append operation of List.
At first here's an abbrevation that helps you to understand what is a list in prolog and what's the meaning of |:
[X1|[...[Xn|[]] = [X1,...Xn]
And append(A, B, C) means appending list B to A results in C.
Append A to empty list results in A:
append([ ], A, A).
If you want to append Y to X, say append(X, Y, _). Unless X is [], prolog would not know anything to do. You have to tell the rules to prolog by saying:
append([A|B], C, [A|D]) := append(B, C, D)
Then prolog will try to split X into form [A|B]. Then Y would be A|D where D is the list defined by C appended to B. append(B, C, D) is the way we tell prolog about this fact.

tail recursion sum, power, gcd in prolog?

how can I accomplish this:
Give a tail-recursive definition for each of the following predicates.
power(X,Y,Z): XY=Z.
gcd(X,Y,Z): The greatest common divisor of X and Y is Z.
sum(L,Sum): Sum is the sum of the elements in L.
so far I have done this but not sure if that's correct
power(_,0,1) :- !.
power(X,Y,Z) :- Y1 is Y - 1,power(X,Y1,Z1),Z is X * Z1.
sum(void,0).
sum(t(V,L,R),S) :- sum(L,S1),sum(R,S2), S is V + S1 + S2.
These are not tail recursive. You can write tail recursive variants by using an accumulator, see this answer.
Your sum is over a tree, which is unusual, normally one would use a list. In Prolog [] is the empty list and [X|R] is the pattern for a nonempty list with the head X and the tail R.

Resources