Prolog, Dynamic Programming, Fibonacci series - prolog

I should preface this by saying this is a homework problem that I am having issues with, and Im not sure if that sort of thing is allowed around here, but I dont know where else to turn to. This is the question I've been asked:
In the sample code for this question, you can see a Fibonacci predicate fibSimple/2 which calculates the Fibonacci of X, a natural number. The problem with the naive recursive solution, is that you end up recalculating the same recursive case several times. See here for an explanation.
For example, working out the fib(5) involves working out the solution for fib(2) three separate times. A Dynamic Programming approach can solve this problem. Essentially, it boils down to starting with fib(2), then calculating fib(3), then fib(4) etc.... until you reach fib(X). You can store these answers in a list, with fib(X) ending up as the first item in the list.
Your base cases would look like the following:
fib(0,[0]).
fib(1,[1,0]).
Note the way that fib(1) is defined as [1,0]. fib(1) is really 1 but we are keeping a list of previous answers.
Why do we do this? Because to calculate fib(X), we just have to calculate fib(X-1) and add the first two elements together and insert them at the front of the list. For example, from the above, it is easy to calculate fib(2,Ans). fib(2) in this case would be [1,1,0]. Then fib(3) would be [2,1,1,0], fib(4) would be [3,2,1,1,0] etc....
Complete the fib/2 predicate as outlined above - the base cases are shown above. You need to figure out the one line that goes after the base cases to handle the recursion.
This is the sample code they provided
fibSimple(0,0). % fib of 0 is 0
fibSimple(1,1). % fib of 1 is 1
fibSimple(N,X) :- N>1,fibSimple(N-1,A), fibSimple(N-2,B), X is A+B.
fib(0,[0]).
fib(1,[1,0]).
I've had a few attempts at this, and while I'm fairly certain my attempt will end up being hopelessly wrong, this is what I have most recently tried
fib(X,[fib(X-2)+fib(X-1) | _]).
My reasoning to this is that if you can get the answer to the last 2, and add them together making them the first or "head" of the list, and then the underscore representing the rest.
My 2 issues are:
1) I don't know/think this underscore will do what I want it to do, and am lost in where to go from here
and
2) I don't know how to even run this program as the fib\2 predicate requires 2 parameters. And lets say for example I wanted to run fib\2 to find the fibonacci of 5, I would not know what to put as the 2nd parameter.

Because this is homework I will only sketch the solution - but it should answer the questions you asked.
A predicate differs from a function in that it has no return value. Prolog just tells you if it can derive it (*). So if you just ask if fib(5) is true the best you can get is "yes". But what are the Fibonacci numbers from 1 to 5 then? That's where the second argument comes in. Either you already know and check:
?- fib(5, [5, 3, 2, 1, 1, 0]).
true ; <--- Prolog can derive this fact. With ; I see more solutions.
false <--- no, there are no other solutions
Or you leave the second argument as a variable and Prolog will tell you what values that variable must have such that it can derive your query:
?- fib(5, X).
X = [5, 3, 2, 1, 1, 0] ;
false.
So the second argument contains the result you are looking for.
You can also ask the other queries like fib(X,Y) "which numbers and their fibonacci hostories can we derive?" or fib(X, [3 | _]) "which number computes the the fibonacci number 3?". In the second case, we used the underscore to say that the rest of the list does not matter. (2)
So what do we do with fib(X,[fib(X-2)+fib(X-1) | _]).? If we add it to the clauses for 0 and 1 you were given we can just query all results:
?- fib(X,Y).
X = 0,
Y = [1] ; <-- first solution X = 0, Y = [1]
X = 1,
Y = [1, 0] ; <-- second solution X = 1, Y = [1, 0]
Y = [fib(X-2)+fib(X-1)|_2088]. <-- third solution
The third solution just says: a list that begins with the term fib(X-2)+fib(X-1) is a valid solution (the _2088 as just a variable that was not named by you). But as mentioned in the beginning, this term is not evaluated. You would get similar results by defining fib(X, [quetzovercaotl(X-1) | _]).
So similar to fibSimple you need a rule that tells Prolog how to derive new facts from facts it already knows. I have reformatted fibSimple for you:
fibSimple(N,X) :-
N>1,
fibSimple(N-1,A),
fibSimple(N-2,B),
X is A+B.
This says if N > 1 and we can derive fibSimple(N-1,A) and we can derive fibSimple(N-2,B) and we can set X to the result of A + B, then we derive fibSimple(N, X). The difference to what you wrote is that fibSimple(N-1,A) occurs in the body of the rule. Again the argument N-1 does not get evaluated. What actually happens is that the recursion constructs the terms 3-1 and (3-1)-1) when called with the query fib(3,X). The actual evaluation happens in the arithmetic predicates is and <. For example, the recursive predicate stops when it tries to evaluate (3-1)-1 > 1 because 1>1 is not true. But we also do not hit the base case fibSimple(1, 1) because the term (3-1)-1 is not the same as 1 even though they evaluate to the same number.
This is the reason why Prolog does not find the Fibonacci number of 3 in the simple implementation:
?- fibSimple(3, X).
false.
The arithmetic evaluation is done by the is predicate: the query X is (3-1) -1 has exactly the solution X = 1. (3)
So fibSimple must actually look like this: (4)
fibSimple(0,1).
fibSimple(1,1).
fibSimple(N,X) :-
N>1,
M1 is N -1, % evaluate N - 1
M2 is N -2, % evaluate N - 2
fibSimple(M1,A),
fibSimple(M2,B),
X is A+B.
For fib you can use this as a template where you only need one recursive call because both A and B are in the history list. Be careful with the head of your clause: if X is the new value it can not also be the new history list. For example, the head could have the form fib(N, [X | Oldhistory]).
Good luck with the homework!
(1) This is a little simplified - Prolog will usually give you an answer substitution that tells you what values the variables in your query have. There are also some limited ways to deal with non-derivability but you don't need that here.
(2) If you use the arithmetic predicates is and > these two queries will not work with the straightforward implementation. The more declarative way of dealing with this is arithmetic constraints.
(3) For this evaluation to work, the right hand side of is may not contain variables. This is where you would need the arithmetic constraints from (2).
(4) Alternatively, the base cases could evaluate the arithmetic terms that were passed down:
fibSimple(X, 0) :-
0 is X.
fibSimple(X, 1) :-
1 is X.
fibSimple(N,X) :-
N>1,
fibSimple(N-1,A),
fibSimple(N-2,B),
X is A+B.
But this is less efficient because a single number takes much less space than the term 100000 - 1 - 1 -1 .... -1.

Related

Prolog - confused about return results of recursive rule

I'm playing around with recursion in Prolog, and I'm confused. I am trying to write rules that can determine if a number is even or odd. I know that there are other stackoverflow questions about this, but I don't care about having a working solution, I am more interested in knowing why mine doesn't work.
Here are my rules:
even(0).
even(N) :- N>0, N1 is N-1, odd(N1).
odd(N) :- N>0, N1 is N-1, even(N1).
When I query even(0), I get returned 2 results. The first result is true, the 2nd is false. This also happens with odd(1), even(2), odd(3), etc. Why am I getting 2 return results? Shouldn't I just get 1?
When you query even(0), it succeeds as you have seen. But you've also seen it prompts you for more results because it left a choicepoint, which is a place in the logic where Prolog decides it can come back and explore other alternatives for a potentially successful query. Upon going back to the choicepoint and attempting to find more solutions, it does not find more, so it comes back "false" since it found no more solutions. So it did just find one solution, but the choice point caused backtracking after which it found no additional solutions. This is the case with your other successful queries as well.
You'll note that if you make a more general query, it gives an error (example taken from GNU Prolog):
| ?- even(N).
N = 0 ? ;
uncaught exception: error(instantiation_error,(>)/2)
| ?-
This is because you are using specific arithmetic expression operators that require that the variables be instantiated. These are relational operators like (>)/2 and the is/2 operator. You can make the solution more relational by using the CLP(FD) operators which are designed for reasoning with integers:
even(0).
even(N) :-
N #> 0,
N1 #= N-1,
odd(N1).
odd(N) :-
N #> 0,
N1 #= N-1,
even(N1).
Then you get a more general solution, which is more complete and more useful:
| ?- even(N).
N = 0 ? ;
N = 2 ? ;
N = 4 ? ;
N = 6 ? ;
...
| ?- odd(N).
N = 1 ? ;
N = 3 ? ;
N = 5 ? ;
N = 7 ?
...
If you know there is at most one answer, or if you only care about the first possible answer, you can use once/1 (examples taken from SWI Prolog here):
2 ?- even(2).
true ;
false.
3 ?- once(even(2)).
true.
4 ?- even(N).
N = 0 ;
N = 2 ;
N = 4 ;
...
5 ?- once(even(N)).
N = 0.
6 ?-
As expected, once(even(N)) terminates after finding the first solution.
The return values you have are correct. The point is how Prolog is evaluating predicates. When you query i.e.
even(2)
Prolog firstly evaluate that this predicate is Yes / true. When going through next possibility it return No / false, because it cannot find any more.
To check what exactly is performed under the hood go to:
https://swish.swi-prolog.org
on the left side type rules (i.e. odd/even) and on the query window type like 'odd(2)', but just before running click 'solutions'->'debug(trace)'. It will let you go step by step of what Prolog is doing.
Also please take a look at the successor example in tutorial below.
http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse9
from a link above, try such code for a reversed example:
numeral(0).
numeral(succ(X)) :- numeral(X).
Now evaluating numeral(0) for the first time return succ(0), another time succ(succ(0)) etc.
Each time next evaluation brings another possible solution for a query.
What Prolog does is a "depth-first search", which means Prolog walks through a decision tree until it either finds a solution and succeeds OR it fails. In either case a process called "backtracking" kicks in. Along the way, going through the tree of choices, Prolog keeps track of where it has MULTIPLE possible routes that could potentially satisfy the goal. Such a point in the decision tree is called a "choice point".
This means Prolog will
search ->
succeed or fail ->
go back to the last choice point ->
repeat until all possible paths have been tried
Given your program:
even(0).
even(N) :- N>0, N1 is N-1, odd(N1).
odd(N) :- N>0, N1 is N-1, even(N1).
We can clearly see TWO ways to satisfy even(0).. The first is the fact even(0) and the second is the recursive rule even(N). Prolog reads top to bottom, left to right so the first encounter is even(0). which is true, and the second is even(N). which goes through N-1 making the result N1 = -1, then goes through odd(N) making the result N1 = -2, which in unequal to even(0). so it fails and then calls even(N) again. Your specific version of Prolog likely sees that it is an infinitely recursive predicate and doesn't even try to satisfy it even though it's a valid declarative path , but not a valid procedural path.
If you know that the mode is (+), you can place a cut,
to suppress the unnecessary choice point:
even(0) :- !.
even(N) :- N > 0, N1 is N-1, odd(N1).
odd(N) :- N > 0, N1 is N-1, even(N1).
The above is better than wrapping a query with
once/1 since it allows the Prolog interpreter to
use last call optimization. There is now no more
problem with an extra choice point:
?- even(3).
false.
?- even(4).
true.
But if the mode is not fixed, you have to be more careful
with cuts. Probably write a separate carefully crafted
predicate for each mode.
CLP(FD) itself seems not to help, it cannot avoid the need
to place cuts, but can sometimes avoid the need to code
different variants for different modes.

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.

Prolog Loops until True

I'm pretty new to Prolog but I'm trying to get this program to give me the first set of twin primes that appears either at or above N.
twins(M) :-
M2 is M + 2,
twin_prime(M, M2),
write(M),
write(' '),
write(M2).
M3 is M + 1,
twins(M3).
However, I'm not completely sure how to go about getting it to loop and repeat until it's true. I've tried using the repeat/0 predicate but I just get stuck in an infinite loop. Does anyone have any tips I could try? I'm pretty new to Prolog.
You're on the right track using tail recursion and #Jake Mitchell's solution works swell. But here are some tips that might help clarify a few basic concepts in Prolog:
First, it seems like your predicate twins/1 is actually defining a relationship between 2 numbers, namely, the two twin primes. Since Prolog is great for writing very clear, declarative, relational programs, you might make the predicate more precise and explicit by making it twin_primes/2. (That this should be a binary predicate is also pretty clear from your name for the predicate, since one thing cannot be twins...)
One nice bonus of explicitly working with a binary predicate when describing binary relations is that we no longer have to fuss with IO operations to display our results. We'll simply be able to query twin_primes(X,Y) and have the results returned as Prolog reports back on viable values of X and Y.
Second, and more importantly, your current definition of twins/1 wants to describe a disjunction: "twins(M) is true if M and M + 2 are both prime or if M3 is M + 3 and twins(M3) is true". The basic way of expressing disjunctions like this is by writing multiple clauses. A single clause of the form <Head> :- <Body> declares that the Head is true if all the statements composing the Body are true. Several clauses with the same head, like <Head> :- <Body1>. <Head> :- <Body2>. ..., declare that Head is true if Body1 is true or if Body2 is true. (Note that a series of clauses defining rules for a predicate are evaluated sequentially, from top to bottom. This is pretty important, since it introduces non-declarative elements into the foundations of our programs, and it can be exploited to achieve certain results.)
In fact, you are only a small step from declaring a second rule for twins/1. You just tried putting both clause-bodies under the same head instance. Prolog requires the redundant measure of declaring two different rules in cases like this. Your code should be fine (assuming your definition of twin_prime/2 works), if you just change it like so:
twins(M) :-
M2 is M + 2,
twin_prime(M, M2),
write(M),
write(' '),
write(M2).
twins(M) :-
\+twin_prime(M, M2), %% `\+` means "not"
M3 is M + 1,
twins(M3).
Note that if you take advantage of Prolog's back-tracking, you often don't actually need to effect loops through tail recursion. For example, here's an alternative approach, taking into account some of what I advised previously and using a quick (but not as in "efficient" or "fast") and dirty predicate for generating primes:
prime(2).
prime(P) :-
between(2,inf,P),
N is (P // 2 + 1),
forall(between(2,N,Divisor), \+(0 is P mod Divisor)).
twin_primes(P1, P2) :-
prime(P1),
P2 is P1 + 2,
prime(P2).
twin_primes/2 gets a prime number from prime/1, then calculates P2 and checks if it is prime. Since prime/1 will generate an infinite number of primes on backtracking, twin_primes/2 will just keep asking it for numbers until it finds a satisfactory solution. Note that, if called with two free variables, this twin_primes/2 will generate twin primes:
?- twin_primes(P1, P2).
P1 = 3,
P2 = 5 ;
P1 = 5,
P2 = 7 ;
P1 = 11,
P2 = 13 ;
P1 = 17,
P2 = 19 ;
P1 = 29,
P2 = 31 ;
But it will also verify if two numbers are twin primes if queried with specific values, or give you the twin of a prime, if it exists, if you give a value for P1 but leave P2 free:
?- twin_primes(3,Y). Y = 5.
There's a handy if-then-else operator that works well for this.
twin_prime(3,5).
twin_prime(5,7).
twin_prime(11,13).
next_twin(N) :-
A is N+1,
B is N+2,
(twin_prime(N,B) ->
write(N),
write(' '),
write(B)
;
next_twin(A)).
And a quick test:
?- next_twin(5).
5 7
true.
?- next_twin(6).
11 13
true.

Categorise List in Prolog

Alright so I am coding a parser for arithmetic equations. I get the input in a list, e.g. "10+20" = [49,48,43,50,48] and then I convert all the digits to there corresponding numbers e.g. [49,48,43,50,48] = [1,0,43,2,0] and from there I want to put integers > 10 back together.
Converting from ascii -> digits I use a maplist and number_codes to convert.
One approach I had was to just traverse the list and if it's 0-9 store it in a variable and then check the next number, 0-9 append it to the other variable and so on until I hit an operator. I can't seem to simply append digits as it were. Here's my current code.
expression(L) :-
maplist(chars, L, Ls).
chars(C, N) :-
(
C >= "0", "9" >= C -> number_codes(N, [C]);
N is C
).
Not sure if there's a simple way to add to my code (as far as I know, maplist only gives back a list of equal length to the list passed in but I could be mistaken).
Any help is appreciated :)
Yes, maplist only 'gives back' a list of equal length. Moreover, maplist applies a predicate only to one element (basically it's context-free). Therefore, it is not possible to do what you want (combine digits between operators to a single number) with maplist and you would have to write the recursion yourself.
However, you can do something way easier than all this converting back and forth:
expression(L, E):-
string_to_atom(L,A),
atom_to_term(A,E,[]).
Which works like this:
2 ?- expression("1+2",E).
E = 1+2.
3 ?- expression("1+2",E), X is E.
E = 1+2, X = 3.
4 ?- expression("1+2",E), X+Y = E.
E = 1+2, X = 1, Y = 2.
5 ?- expression("1+2+3",E), X+Y = E.
E = 1+2+3, X = 1+2, Y = 3.
Naturally, if you want a list with all the numbers involved you will have to do something recursive but this is kinda trivial imho.
If however you still want to do the converting, I suggest checking Definite Clause Grammars; it will simplify the task a lot.
I answered some time ago with an expression parser.
It will show you how to use DCG for practical tasks, and I hope you will appreciate the generality and simplicity of such approach.
Just a library predicate is required from SWI-Prolog, number//1, easily implemented in Sicstus. Let me know if you need more help on that.

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