Prolog can somebody explain this recursion - prolog

Can someone explain how the following Prolog recursion works ?
findRoute(A,A,_).
findRoute(A,C,Path) :-
nextCnvZone(A,B),
\+ member(B,Path),
findRoute(B,C,[B|Path]).
I can understand the second part but could not understand the first part i.e what is the first findRoute(A,A,_). doing ?

It is the part that stop the recursion, i.e. when the first parameter equals the second the recursion stops, and returns true through all of the recursion levels if it made it to that level.
In general, it has the rule that the first parameter equals the second. (check if true in case both variables are given, assign the value of the second to the first if the second is variable and the first is given, etc.)
?- findRoute(1, 1, 5).
true
?- findRoute(1, 2, 5).
false
?- findRoute(1, X, 5).
X = 1
?- findRoute(X, 2, 5).
X = 2

Related

Simple Prolog predicate - statement is always evaluated as false

I've just started Prolog and truly wonder why the following lines, specifically the 'is' part, always produces false:
highest(L) :-
path(_,_,Z),
Z >= L,
L is Z.
highestWrap :-
highest(0).
highestWrap is called.
Thanks in advance and have a beautiful day!
Unless there is a path with length 0, this will not work, and even then, it will likely not yield what you want: it will just say true.
In Prolog variables can only be set once, that means that if L is set to 0, then it remains 0, unless you backtrack over that assignment.
Here it thus means that you call highest(0), next you instruct Prolog to call path(_, _, Z) and this can result in zero, one or more solutions. In case there are no path(_, _, Z)s, then the call will fail. But in case there are, then Z will (if I make correct assumptions about the predicate), have a numerical value, for example 7.
Now the condition Z >= L of course holds in that case (if Z is 7), so that is nog the problem. But now you specify L is Z. That thus means that you call 0 is 7. The is/2 [swi-doc] predicate aims to solve the expression of the second argument (that expression is 7 in the example, so there is not much to solve), and then aims to unify it with the term on the left side. But since 0 is not equal to 7 that fails.
If you want to obtain the highest path, you can for example make use of the aggregate [swi-doc] library:
:- use_module(library(aggregate)).
highest(L) :-
aggregate(Max(Z), path(_,_,Z), Max(L)).
You can then call it with higest(X) to unify X with the highest value for Z in a call to path(_, _, Z).

Algorithmically pick which rule to apply?

Let say I have the following rules :
?- assert(test(5,2) :- true).
true.
?- assert(test(5,3) :- true).
true.
?- assert(test(5,4) :- true).
true.
?- test(5,K).
K = 2 ;
K = 3 ;
K = 4.
?- findall(K,test(5,K), L).
L = [2, 3, 4].
I can find all the solutions. But I want something different.
In this scenario "5" is the condition and the second term K is a SCORE.
I want to find all the rules that match "5", but be able to pick which one to execute,
based on the SCORE. Currently the max score "4".
Ideally I want to get the list of all the matching rules and pick randomly one with higher score.
This means I need to get back the rules as a structure, so that I can pick algorithmically one of them.
How can I do that ?
I want to simulate Production system (IF-THEN rules), where every rule have a score. The head of the rule should play the IF part.
The THEN part should not be executed until rule is selected based on the score !
If I've understood your problem correctly, the starting point for you would be using clause/2 predicate in conjunction with findall to get all possible scores, then find maximum and call your test/2 predicate with its value:
findall(Score, clause(test(5, Score), Body), Scores),
max_member(MaxScore, Scores),
test(5, MaxScore).
PS: I am assuming that you use Swi-Prolog.

Predicate about a list of lists

I'm trying to create a predicate that receives a list of lists and returns a list of lists containing all the unitary lists (lists whose length is 1) from the first list, however it is not working. This is what I created:
elimina_listas_nao_unitarias_lista_de_listas([[A]|T],N_List):-
length([A], 1),
N_List is [H|N_List_T],
elimina_listas_nao_unitarias_lista_de_listas(T, N_List_T).
elimina_listas_nao_unitarias_lista_de_listas([[A]|T], N_List):-
length([A], X),
X > 1,
elimina_listas_nao_unitarias_lista_de_listas(T, N_List2).
Thi is what it should do:
elimina_listas_nao_unitarias_lista_de_listas([[1,2],[1,2,3],[3]], [3])
elimina_listas_nao_unitarias_lista_de_listas([[1,2],[1,2,3],[3,4,5]], [])
It is retuning false currently everytime
Let's take a look at your first rule. The first goal always succeeds, since you are asking if a list with a single element is of length 1. Just try it at the prompt:
?- length([A], 1).
true
Instead, you probably want to have a variable without the brackets in the head of the first list (e.g. [L|Ls]) and ensure that it is a list of length 1:
?- length(L,1).
L = [_A]
The same goes for the first list in the head of your second rule and its first goal. In your second goal you are trying to evaluate [H|N_List_T] as an arithmetic expression with is/2 such that N_List holds the value. Besides the fact that this doesn't make sense, you can try that at the prompt and see how this goal can't succeed:
?- N_List is [H|N_List_T].
ERROR!!
TYPE ERROR- string must contain a single character to be evaluated as an arithmetic expression: expected evaluable term, got [_131245|_131246]
Instead, you want to unify the two terms:
?- N_List = [H|N_List_T].
N_List = [H|N_List_T]
However, you can get rid of this goal entirely if you write [H|N_List_T] as the second argument in the head of the rule. Additionally, you might want the unitary list L in the head of the second list instead of the variable H. Furthermore you are missing a case, namely the first list being []. In that case the second list is empty as well, since the empty list clearly does not contain any unitary lists. Finally, I would note that it might enhance the readability of your code if you picked a somewhat simpler and more declarative name, say listas_unitarias/2. Putting all this together, you might end up with a predicate like this:
listas_unitarias([],[]).
listas_unitarias([L|Ls],[L|Ss]) :-
length(L,1),
listas_unitarias(Ls,Ss).
listas_unitarias([L|Ls],Ss) :-
length(L,X),
dif(X,1),
listas_unitarias(Ls,Ss).
Your second example query yields the desired result
?- listas_unitarias([[1,2],[1,2,3],[3,4,5]],U).
U = []
For your first example query the result is slightly different:
?- listas_unitarias([[1,2],[1,2,3],[3]], U).
U = [[3]] ? ;
no
The only unitary list is in a list itself. That would make more sense, since the first argument might contain more than one such list. Consider the following case:
?- listas_unitarias([[1],[2,3],[4],[]],U).
U = [[1],[4]] ? ;
no
However, if you meant to get the unitary lists one at a time, the predicate would look slightly different:
listas_unitarias2([L|_Ls],L) :-
length(L,1).
listas_unitarias2([_L|Ls],U) :-
listas_unitarias2(Ls,U).
As would the results of the queries:
?- listas_unitarias2([[1,2],[1,2,3],[3]], U).
U = [3] ? ;
no
?- listas_unitarias2([[1],[2,3],[4],[]],U).
U = [1] ? ;
U = [4] ? ;
no
Especially your second example query: It would fail instead of producing the empty list as a solution:
?- listas_unitarias2([[1,2],[1,2,3],[3,4,5]],U).
no
?- listas_unitarias2([[1,2],[1,2,3],[3,4,5]],[]).
no
EDIT: As pointed out by #false in the comments the combined use of length/2 and dif/2 in the third rule doesn't terminate for [_,_|_] so the query
?- listas_unitarias([[1],[_,_|_],[2],[3,4]],U).
U = [[1],[2]] ? ;
U = [[1],[2]] ? ;
...
does not terminate as well. However, it is reasonable to expect termination in this case, since a list headed by two elements certainly can't be unitary. So, instead of using length/2 you might consider describing the four cases that cover all possibilities. 1) If the first list is empty so is the second list. 2) If the head of the first list is [] it's not in the second list. 3) If the head of the first list is [A] it is in the second list. 4) If the head of the first list has at least two elements it's not in the second list.
listas_unitarias([],[]). % case 1)
listas_unitarias([[]|Ls],Ss) :- % case 2)
listas_unitarias(Ls,Ss).
listas_unitarias([[A]|Ls],[[A]|Ss]) :- % case 3)
listas_unitarias(Ls,Ss).
listas_unitarias([[_,_|_]|Ls],Ss) :- % case 4)
listas_unitarias(Ls,Ss).
With this version the above query terminates after finding the only solution:
?- listas_unitarias([[1],[_,_|_],[2],[3,4]],U).
U = [[1],[2]]
The other queries from above yield the same results:
?- listas_unitarias([[1,2],[1,2,3],[3,4,5]],U).
U = []
?- listas_unitarias([[1,2],[1,2,3],[3]], U).
U = [[3]]
?- listas_unitarias([[1],[2,3],[4],[]],S).
S = [[1],[4]]

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.

Prolog calls wrong rule. Does not backtrack correctly

Whats up?
I'm having some really weird problems with Prolog.
A recursive rule to replace an element in a list at a given index isn't always working.
My rule looks like this:
% Base rule - Stops when index is 1 and replaces the head with the element.
replaceAtIndex(1, _element, [_|_tail], [_element|_tail]).
% Recursive rule - Enter recursion for tail as long as index is larger than 1.
replaceAtIndex(_index, _element, [_head|_tail], [_head|_new_tail]):-
_index > 1,
_new_index is _index - 1,
replaceAtIndex(_new_index, _element, _tail, _new_tail).
When I use the debugger from within my program I see its always calling the second rule no matter what the index is, but when I execute the exact same command outside my program it works perfectly well. It reaches index 1 but calls the second rule, and does NOT backtrack and attempt the first rule and fails all the way back up...
The rule calling the replaceAtIndex looks like this:
level_replace_block_value(_x, _y, _value):-
current_level(_level_number, _width, _height, _blocks, _drawX, _drawY),
coordinates_to_index(_x, _y, _index),
_index_in_list is _index + 1, % the replaceAtIndex is not 0 terminated
replaceAtIndex(_index_in_list, _value, _blocks, _new_blocks),
retractall(current_level(_,_,_,_,_,_)),
assert(current_level(_level_number, _width, _height, _new_blocks, _drawX, _drawY),
graphics_update_block_value(_x, _y).
When I'm debugging its calling with index being 111.
When I'm replacing the _index_in_list with a constant 111 it works.
Anyone might have a clue why that happens?
Preserve logical-purity by using the builtin predicates same_length/2, length/2 and append/3!
replace_at(I,X,Xs0,Xs2) :-
same_length(Xs0,Xs2),
append(Prefix,[_|Xs1],Xs0),
length([_|Prefix],I),
append(Prefix,[X|Xs1],Xs2).
First, let's run the sample query that #magus used in a previous answer to this question:
?- replace_at(3,0,[1,2,3,4,5,6],Xs).
Xs = [1,2,0,4,5,6] ;
false.
Does it work when the list items are instantiated later?
?- replace_at(3,0,[A,B,C,D,E,F],Xs), A=1,B=2,C=3,D=4,E=5,F=6.
A = 1, B = 2, C = 3, D = 4, E = 5, F = 6, Xs = [1,2,0,4,5,6] ;
false.
Yes! What if the index isn't a concrete integer, but an unbound logical variable? Does that work?
?- replace_at(I,x,[_,_,_,_,_],Ys).
I = 1, Ys = [ x,_B,_C,_D,_E] ;
I = 2, Ys = [_A, x,_C,_D,_E] ;
I = 3, Ys = [_A,_B, x,_D,_E] ;
I = 4, Ys = [_A,_B,_C, x,_E] ;
I = 5, Ys = [_A,_B,_C,_D, x] ;
false.
It does! With monotone code, we get logically sound answers even with very general queries.
I suspect you misunderstand the direction in which backtracking will take place.
The first "base" rule will be tried first for any call to replaceAtIndex/4. If it fails, due to non-unifiability of the call with the "head" of the first rule, then the Prolog engine backtracks to the second rule. [Unification failure might result either from the first argument (index) differing from 1 or from the third argument not being a nonempty list.]
Backtracking never goes in the other direction. If the second rule is tried and fails, the call fails.
Of course things are complicated by the recursive definition. The success of applying the second rule entails a new call to replaceAtIndex/4, which as far as the Prolog engine is concerned must begin attempting to satisfy that goal by starting back at the first rule.
I'd suggest adding a cut to the first rule, since by construction the second rule will never succeed if the first rule does. But this is just an efficiency issue... why leave a choicepoint open that will never produce any further solutions?
replaceAtIndex(1, _element, [_|_tail], [_element|_tail]) :- !.
Added: I confirmed that your code works in Amzi! Prolog with a call like this:
?- replaceAtIndex(3, 0, [1,2,3,4,5,6], L).
L = [1, 2, 0, 4, 5, 6] ;
no
?-
But of course you also see success when the code is called in standalone/interpreted mode.
So I have to suspect the "index" argument being passed in is not an integer but rather a floating point number. Integer 1 will not unify with floating point 1.0, even if they are mathematically equal.
You can use the predicate is_integer/1 to test for this in Amzi! Prolog. The function integer(X) can be used to convert real 1.0 to an integer 1 by truncating the (nonexistent) fractional part.
Try _index_in_list set to 1. Wouldn't the first rule get called then?
Sure the reason why the second rule is getting called if your _index_in_list is 111 is because 111 is greater than 1 ? The first rule only deals with 1 - as the first parameter says.
When I'm replacing the _index_in_list with a constant 111 it
works.
What? You mean the first rule gets called? How can that be, the first param is 1.
replaceAtIndex(I, Value, List, Result) :-
RI is I-1,
findall(Before, (nth0(B, List, Before), B < RI), Before),
findall(After, (nth0(A, List, After), A > RI), After),
append([Before, [Value], After], Result).
?- replaceAtIndex(3,0,[1,2,3,4,5,6], L).
L = [1, 2, 0, 4, 5, 6].

Resources