Prolog why my function always evaluates to true - prolog

I have the folowing code
isInRange(Point1,Point2,Range):-
manhatan2(Point1,Point2,Manhatan),
Range>Manhatan.
manhatan2 computes the manhatan distance between 2 points give in as a 2 element list [X,Y]
I don't understand why isInRange always evaluates to true
isInRange([0,0],[0,10],9) evaluates to true
isInRange([0,0],[0,10],100) also evaluates to true
I am pretty sure i did the manhatan function right.Have tested it with many values
Can anyone help me understand what is wrong with my code ?
%Edit starts here
So i traced the damn thing and here is more code i use
modul(A,B,R):-A<B,R is B-A.
modul(A,B,R):-A>B,R is A-B.
extractFromList([H|_],X,R):- X is 0,R is H.
extractFromList([_|T],X,R):- X1 is X-1,extractFromList(T,X1,R).
manhatan(X1,Y1,X2,Y2,R):- modul(X1,X2,R1),modul(Y1,Y2,R2),R is R1+R2.
manhatan2(P1,P2,R):-
extractFromList(P1,0,X1),
extractFromList(P1,1,Y1),
extractFromList(P2,0,X2),
extractFromList(P2,1,Y2),
manhatan(X1,Y1,X2,Y2,R).
The extract fromFromList extracts the Xth element from the given list
modul should return |A-B|
Tracing isInRange([0,0],[0,10],100) everthing whent as i whanted.
Tracing isInRange([0,0],[0,10],9) stoped when comparing the manhatan with the range and
started redoing modul(0,10,_GXXX) evaluating _GXXX to -10 and thus the Manhatan < Range condition evaluated to true thus all isInRange evaluating to true
Why does it do that ?
Why does it redo the modul computation in this way ?

The short answer:
The following code does what you want:
manhattan(L1,L2,Result) :- manhattan(L1,L2,0,Result).
manhattan([],[],Res,Res).
manhattan([H1|T1],[H2|T2],Acc,Res) :-
AccNew is Acc + abs(H1-H2),
manhattan(T1,T2,AccNew,Res).
isInRange(P1, P2, Range) :-
manhattan(P1, P2, Distance),
Range > Distance.
Longer answer:
I tried your code and it doesn't behave as you describe it.
For me, isInRange always fails, because 'modul' fails if A==B.
You should change the test on the first case to A =< B.
Or, even better, use the builtin 'abs' function.
I assume that in your previous version you didn't have a test in the second case.
In that case Prolog will try the second case when the first case leads to failure (for example because Range > Manhatan fails).
Adding the test in the second case in one way to solve this problem.

Related

Prolog: Chaining multiple rules

So I am an absolute beginner in Prolog. I am learning recursion at the moment and this is what I got until now on my task.
dance(start).
dance(forward(T)) :- dance(T).
dance(backward(T)) :- dance(T).
count(start,0,0).
count(forward(X),succ(Y),Z) :- count(X,Y,Z).
count(backward(X),Y,succ(Z)) :- count(X,Y,Z).
greater(succ(0),0).
greater(succ(Y),succ(Z)):-greater(Y,Z).`
Summary of what this is supposed to do: There can be dances starting with the "start" and then either forward or backward addition per recursion. In count, I managed to be able to count the amount of forward and backward in a given sequence and save them in the "succ" notation and in greater I want to compare two of such "succ" numbers. And greater shall be true if the first argument is larger (consists of more "succs" than the second argument.
Now my task is to write a new rule "more(X)" which is true if the sequence X (build from dance) has more forward than backward in it. I think I have all the subtasks I need for it but now I am helpless with chaining them together because until now I only had 2 rules with the same amount of parameters but in this case, I got one with one, two, and three parameters. The solution should be something like this
more(X):-greater(Y,Z)
but how do I get my "succ" umbers from "count" to "greater" and the given sequence X to "count"? I do have to change some of the rules otherwise count is never called, right?
So it should be more like more(X):-greater(count(X,Y,Z)) ?
But like this, I would have to change the greater rules to be able to "get" this type of parameter.
Example query ?- more(backward(forward(start))).
false.
?- more(forward(start)).
true.
Your dance/1 and count/3 predicates seems correct.
If you want "greater" where greater(X, Y) means that X is greater than Y, you'd write:
greater(succ(_), 0).
greater(succ(X), succ(Y)) :- greater(X, Y).
Your solution checks if X is exactly one greater than Y.
Note that nothing is greater than 0.
If you implement more/1 in terms of count/3 and greater/2, you'd write:
more(X) :-
count(X, Forward, Backward),
greater(Forward, Backward).
So it should be more like more(X):-greater(count(X,Y,Z)) ?
No, you are writing that as if it is Python and greater(count(X,Y,Z)) will call greater(...) on the return from count. Prolog predicates are not function calls, and count(...) does not return anything in that way.
The result of the count is Y and Z. (These names you are using could be clearer). Do the count, and then after, use the Y and Z for something else.
count(X,Y,Z),
greater(Y,Z)
The comma being AND; "this code works if count of X is Y and Z AND Y is greater than Z".

Prolog : Find the kth element of this list : What's the difference between those 2 implementations?

I am playing with some beginner problems in prolog.
"Find the k'th element of a list" .
I wrote that:
kth(X,[X|_],1).
kth(X,[H|R],K):- kth(X,R,K-1).
It was wrong. Most test-cases resulted into false.
The suggested solution was:
element_at(X,[X|_],1).
element_at(X,[_|L],K) :-
K > 1,
K1 is K - 1,
element_at(X,L,K1).
Where did my code go wrong? I am interpeting my code as : "if you are looking for the first element it the the head. If you are looking for the kth element in [H|R] it is the (k-1)th element in R ."
even when I tried to include X>1 in my code, it did not work .
This K1 is K-1 instead of simply writing K-1 inside the function seems like it played a huge role. Can you help me understand?
With is you evaluate an arithmetic expression on the right side, unifying it with the left side. In your solution you just apply the term K-1 in each step. Without it ever being evaluated, 2-1, 3-1-1, 4-1-1-1 and so on (length depending on the initial K) will not be unifiable with 1 in the base case, and therefore result in false.

Prolog sequences

Good Day,
I have a task (not homework), but test preparation question. Given a value of n where n > 0. I need to find out what 3**n value is. I do have something that works.
% expo
expo([],[]).
expo([X|T], [Y|Result]):-
number(X),
Y is 3 ^ X,
expo(T,Result).
expo([ThrowAway|Tail], [ThrowAway|Result]):-
expo(Tail,Result).
last([X]):-
write("M = "),
write(X).
last([Y|Tail]):-
last(Tail).
do_list(N) :-
findall(Num, between(0, N, Num), L),
expo(L, E),
last(E).
When I run this at the console:
do_list(4).
M = 81
true.
So it does give me what I want. But is a recursive solution necessary? I just want to generate a sequence of numbers and use those numbers as my exponent which I have done, but I had to create two lists to this.
Ideally, I'd like to do:
do_list(4, M).
M = 81
true.
Is this possible to do this without two lists? Is it possible without recursion? I'm new to Prolog, so it's taking me a little getting used to "thinking" in Prolog.
TIA,
coson
If you want to do something in all elements of a list then yes most of the times you need recursion (except from cases like when you use predicates like fundall/3 which does the recursion ...).
If you want to return your result in an argument and not just print it then you need for the above predicate two lists (one is the input and the other one is the output).
Though I don't understand why not just writing:
find_pow(Input,Output):-Output is 3^Input.
From what I understood you calculate 3^i for every i<=n and keep last element which could be done independently. So if I understood corrctly what you're trying to do, this could be done without using lists and recursion (if you use predefined pow function ^ else if you write a predicate that computes the power 3^n then you would use recursion... ).
Example:
?- find_pow(4,X).
X = 81.

Not able to reach base case in fibonacci sequence

I'm quite new to Prolog, and this way of thinking is kind of messing with my mind. I'm currently using SWI-Prolog to run and debug my code. I have implemented a tail recursive algorithm to solve the N'th fibonnaci-number. I have tried debugging step by step, and I cannot explain why my implementation is skipping the base case. Where am I thinking wrong?
fib(0, A,_, A). %Base case, when we reach N = 0, return.
%Tail recursion. Use N as counter, iterate until base value (N=0) is reached.
fib(N, A, B, F) :-
Nnew is N - 1,
Sum is (A + B),
fib(Nnew, B, Sum, F).
fib(N, F) :-
fib(N, 0, 1, F). %set start values for when fib(N,F). is called
My implementation is working great (and fast) if I want to calculate the nth fib number. For example, if I run ?- fib(5,F)., I get F = 5 back. Great. If I want to check ?- fib(5,5). I get True back, which is correct. Great.
But, if I input a false statement, for example: ?- fib(5,4). then the program is looping forever. What happens is that N passes 0, ignores the base case(?), and continues on to be decremented. Why is the base case skipped? In my eyes, fib(0,A,_,A). is satisfied. Where am I wrong?
You should add the condition N>0 to the second clause of your predicate fib/3, otherwise the predicate fib/3 will continue trying with the negative numbers if the base-case fails. Lets see the case when you consult ?- fib(0,1):
This case will unified the second clause fib(0,0,1,1), where Nnew will be instantiated to the value -1. From here Nnew will be infinitely decremented, and the base-case will never be unified.
Any other false case, like ?- fib(5,4) will try to decrement N until the base case is unified, and that won't happen unless after 5 iteration, the sum of the fibonacci numbers are equal to 4. So, there's is no point on try with more attempts.

Sum of a list in prolog

I'm reading 'the art of prolog' book and I found an exercise that reads 'Define the relation sum(ListOfIntegers,Sum) which holds if Sum is the sum of the ListOfIntegers, without using any auxiliary predicate' .I came up with this solution:
sum([],Sum).
sum([0|Xs], Sum):-sum(Xs, Sum).
sum([s(X)|Xs], Sum):-sum([X|Xs],s(Sum)).
Which does not work exactly as I would want it to.
?- sum([s(s(0)),s(0),s(s(s(0)))],X).
true ;
false.
I was expecting X to be
s(s(s(s(s(s(0))))))
I thought that the problem is that I have to 'initialize' Sum to 0 in the first 'iteration' but that would be very procedural and unfortunately I'm not quite apt in prolog to make that work.
Any ideas or suggestions?
Your first clause should read
sum([], 0).
With that change, the vacuous true return goes away and you're left with one problem: the third clause reverses the logic of summation. It should be
sum([s(X)|Xs], s(Sum)) :- sum([X|Xs], Sum).
because the number of s/1 terms in the left argument to sum/2 should be equal to the number of them in the right argument.
The best way to localize the problem is to first simplify your query:
?- sum([0],S).
true.
?- sum([],S).
true.
Even for those, you get as an answer that any S will do. Like
?- sum([],s(s(0))).
true.
Since [] can only be handled by your fact, an error must lie in that very fact.
You stated:
sum([], Sum).
Which means that the sum of [] is just anything. You probably meant 0.
Another error hides in the last rule... After fixing the first error, we get
?- sum([0],Sum).
Sum = 0.
?- sum([s(0)],Sum).
false.
Here, the last clause is responsible. It reads:
sum([s(X)|Xs], Sum):-sum([X|Xs],s(Sum)).
Recursive rules are relatively tricky to read in Prolog. The simplest way to understand them is to look at the :- and realize that this should be an arrow ← (thus a right-to-left arrow) meaning:
provided, that the goals on the right-hand side are truewe conclude what is found on the left-hand side
So, compared to informal writing, the arrows points into the opposite direction!
For our query, we can consider the following instantiation substituting Xs with [] and X with 0.
sum([s(0)| [] ], Sum) :- sum([0| []],s(Sum)).
So this rule now reads right-to-left: Provided, sum([0],s(Sum)) is true, ... However, we do know that only sum([0],0) holds, but not that goal. Therefore, this rule never applies! What you intended was rather the opposite:
sum([s(X)|Xs], s(Sum)):-sum([X|Xs],Sum).
I'm not really following your logic, what with all the seemingle extraneous s(X) structures floating about.
Wouldn't it be easier and simpler to do something like this?
First, define your solution in plain english, thus:
The sum of an empty list is 0.
The sum of a non-empty list is obtained by adding the head of the list to the sum of the tail of the list.
From that definition, the prolog follows directly:
sum( [] , 0 ) . % the sum of an empty list is 0.
sum( [X|Xs] , T ) :- % the sum of an non-empty list is obtained by:
sum( Xs , T1 ) , % - first computing the sum of the tail
T is X + T1 % - and then, adding that the to head of the list
. % Easy!

Resources