Prolog - Multiplication by recursive addition - prolog

I am trying to recursively do addition to multiply two numbers in swi-prolog. I am currently learning Prolog and I do not want to use any library like clpfd.
mult(A, B, C) :- A < B, mult(B, A, C). % always make the first number bigger
mult(A, B, C) :- B > 0, B1 is B - 1, mult(A, B1, A + C). % keep adding
mult(A, B, C) :- B == 0, C is 0. % base case
'C' is supposed to be the result.
This is trying to replicate the following algorithm in Java:
int product(int x, int y)
{
# first prolog line
if (x < y)
return product(y, x);
# second prolog line
else if (y != 0)
return (x + product(x, y - 1));
# third prolog line
else
return 0;
}
However, no matter how I vary the input, the result will always be 'false'. I was able to step through my instructions with :- trace., but I cannot find out how to fix this.

The problem is the last literal of your second clause: mult(A, B1, A + C).
What you really want is the result of A*B1 to add that to A.
So try replacing this line with:
mult(A, B, C) :- B > 0, B1 is B - 1, mult(A, B1, C1), C is A + C1.

Related

Increment a variable by constant in recursive rules in prolog

Here's the line of code written in prolog to make an lcm (Least Common Multiple) rule:
lcm(A, B, A) :-
A > B,
A mod B =:= 0,
!.
lcm(A, B, B) :-
B > A,
B mod A =:= 0,
!.
lcm(A, B, X) :-
A < B,
ImproveB is B + B,
lcm(A, ImproveB, X).
lcm(A, B, X) :-
A > B,
ImproveA is A + A,
lcm(ImproveA, B, X).
I noticed that there's a bug in these lines of code.
For example, the case is lcm(16,10,X) which operated as below:
lcm(16,10,X).
lcm(32,10,X).
lcm(64,10,X).
lcm(128,10,X).
...
It will double the larger number and not increment it by the expected constant. The expected operation is as below:
lcm(16,10,X).
lcm(32,10,X).
lcm(48,10,X).
lcm(64,10,X).
lcm(80,10,X).
since 80 mod 10 is 0, so the result of X is 80
So, how to handle this situation?
To solve the problem, the constant value to be added must be passed as an extra argument (which does not change). Also, to reduce the number of clauses, you can fix the order of the arguments so that the first one is the maximum and the second one is the minimum:
lcm(A, B, C) :-
Min is min(A, B),
Max is max(A ,B),
lcm_loop(Max, Min, Max, C).
lcm_loop(A, B, K, C) :-
( A mod B =:= 0
-> C = A
; A1 is A + K,
lcm_loop(A1, B, K, C) ).

Counting the number of valuations via Quine algorithm in Prolog

My logic teacher said in passing that Quines algorithm
can be also used to count valuations. Unfortunately I
cannot get my head around how this is done in Prolog?
The program would for example give, using
the syntax from the answer in Quines algorithm:
?- sat_count(X+Y, C).
C = 3
Since the truth table for the disjunction X+Y
has 3 rows that valuate to true:
X Y X+Y
0 0 0
0 1 1
1 0 1
1 1 1
Point of departure is Quines algorithm with its core predicate eval/2 which has the following specification. The source code of the Quine algorithm and the solution to the question can be found here.
/**
* eval(A, R):
* The predicate succeeds in R with a partial evaluated
* Boolean formula. The predicate starts with the leaves
* and calls simp after forming new nodes.
*/
% eval(+Formula, -Formula)
We first experimented with a labeling predicate, that
will list all valuations without counting them. The predicate
has a fast fail feature, if the partially evaluated formula
is false (0) then labeling needs not to proceed, otherwise we
simply probe the boolean values:
/**
* labeling(L, A):
* The predicate labels the variables from the list L in the formula A.
*/
% labeling(+List, +Formula)
labeling(_, A) :- A == 0, !, fail.
labeling([X|L], A) :- value(X), eval(A, B), labeling(L, B).
labeling([], A) :- A == 1.
Here is an example run:
?- labeling([X,Y], X+Y).
X = 0,
Y = 1 ;
X = 1,
Y = 0 ;
X = 1,
Y = 1
From the labeling predicate we derived a counting predicate
using findall/3 from the ISO core standard. Instead of
succeeding at the end we return 1, inbetween we sum the counts.
This does the job and also profits from fast failing:
/**
* count(L, A, N):
* The predicate silently labels the variables from the list L in the
* formula A and succeeds in N with the count of the solutions.
*/
% count(+List, +Formula, -Integer)
count(_, A, C) :- A == 0, !, C = 0.
count([X|L], A, D) :-
findall(C, (value(X), eval(A, B), count(L, B, C)), R),
sum(R, 0, D).
count([], A, 1) :- A == 1.
Here is an example run:
?- count([X,Y], X+Y, C).
C = 3
The implementation might profit from some optimizations that we didn't implement. For example assigning values to a variable that does not anymore occure in the formula could be optimized away.

Prolog - summing up predicate results

Let's say i have the following predicate:
func1(X,B,R)
I provide it with a certain X and B and in return it gives me 5 different results for R.
EDIT:
The X and B do not specify a range. rather, X specify an integer (say 120) and B specifies all integers (starting from 1) whose cubic is less than X.
What func1 does is calculating R as the result the remainder.
In this case where X=120:
B = 1, R = 119 (120-1^3)
B = 2, R = 112 (120-2^3)
B = 3, R = 93 (120-3^3)
B = 4, R = 56 (120-4^3)
It would not calculate B=5 since 5^3 = 125 which is greater than 120, so it stops here.
How can i make a predicate such as:
func2(R,S)
That would accept all of the results given by R, sum them up and store them in S?
Thanks!
To start with, since the values of B are totally derivable from the value of X, I wouldn't include both as arguments in func1. I'll introduce a predicate func3/2 which is true if the second argument is derivable from the first (i.e., func3(X, B) is true if B is derivable from X):
func1(X, R) :-
func3(X, B),
...
What will happen if you query func1(120, R) is you'd get one or more results for R. Then you can use findall/3 as I indicated in my comment:
func2(X, S) :-
findall(R, func1(X, R), Rs),
sumlist(Rs, S).
To define func3/2 the cleanest approach would be to use CLP(FD):
:- use_module(library(clpfd)).
func3(X, B) :-
B #>= 0,
(X - B^3) #>= 0,
label([B]).
Here's an example of what func3 does:
?- func3(120, B).
B = 1 ;
B = 2 ;
B = 3 ;
B = 4.
A much less desirable way to do this if you can't use CLP(FD) would be to use between and define the upper limit of B to be the greatest integer not exceeding the cube root of X:
func3(X, B) :-
Limit is floor(exp(log(X) / 3)),
between(1, Limit, B).
Which yields the same result as above.

How to print all the facts in prolog

I am a beginner and I am using SWI Prolog to write a rule to print all the facts about addition of two numbers.The following is the code:
addition(X,Y,Z) :- Z is X+Y.
add(X,Y):-
between(X,Y,A),
addition(X,A,Z),
writeln(addition(X,A,Z)),
X1 is X+1,
add(X1,Y).
And the following is the output:
1 ?- add(1,2).
addition(1,1,2)
addition(2,2,4)
addition(1,2,3)
addition(2,2,4)
false.
As you can see the output addition(2,2,4) is repeating and addition(2,1,3) is missing. What am I doing wrong here??
addition/3 is a "rule", or a "predicate", not a fact. Anyway, you have defined it as:
% addition(X, Y, Z)
% Z is the sum of the integers X and Y
Now you want to apply this predicate to (and I am guessing here) each pair X and Y such that X is between A and B and Y is between A and B:
% add(A, B, Addition)
% Add all numbers X and Y that are between A and B
add(A, B, addition(X, Y, Z)) :-
between(A, B, X),
between(A, B, Y),
addition(X, Y, Z).
You will notice that you don't need recursion (or iteration): you can use the fact that between/3 is non-deterministic and will create choice points that will be evaluated on backtracking.
You can now call it like this:
?- add(1, 2, A).
A = addition(1, 1, 2) ;
A = addition(1, 2, 3) ;
A = addition(2, 1, 3) ;
A = addition(2, 2, 4).
You can press the ; or space to backtrack and evaluate the next solution.
The third argument to add/3 is unified with the term addition/3 in the head of add/3. It happens to have the same name as the predicate addition/3, but it could have been called anything.
If you insist on printing it out from a single call, you could use forall/2:
?- forall(add(1, 2, A), format('~q', [A])).

Sequence of Fibonnaci Numbers - Prolog

While attempting to learn Prolog I came across a good exercise which was to write a program that displays the Nth Fibonacci number. After some work I got it working and then decided to see if I could write a program that displays a range of Fibonacci numbers according to the input.
For instance the input:
?- fib_sequence(2,5,Output).
Gives the output:
?- Output = [1,1,2,3]
I am having difficulty, however, in finding a good starting point. This is what I have so far:
fib(0, 0).
fib(1, 1).
fib(N, F) :- X is N - 1, Y is N - 2, fib(X, A), fib(Y, B), F is A + B.
fib_sequence(A,B,R) :- fib(A,Y) , fib(B,Z).
I know I must assign a value to R, but I'm not sure how to assign multiple values. Any help is greatly appreciated.
Observe that your fib_sequence cannot be done in a single predicate clause: you need at least two to keep things recursive - one to produce an empty list when A is greater than B (i.e. we've exhausted the range from A to B), and another one to prepend X from fib(A,X) to a list that you are building, increment A by 1, and call fib_sequence recursively to produce the rest of the sequence.
The first predicate clause would look like this:
fib_sequence(A,B,[]) :- A > B.
The second predicate clause is a bit harder:
fib_sequence(A,B,[H|T]) :-
A =< B /* Make sure A is less than or equal to B */
, fib(A, H) /* Produce the head value from fib(A,...) */
, AA is A + 1 /* Produce A+1 */
, fib_sequence(AA, B, T). /* Produce the rest of the list */
Prolog has some helper builtin to handle numeric sequences, then as an alternative to dasblinkenlight' answer, here is an idiomatic 'query':
fib_sequence(First, Last, Seq) :-
findall(F, (between(First,Last,N), fib(N,F)), Seq).
note that it will not work out-of-the-box with your fib/2, because there is a bug: I've added a condition that avoid the endless loop you would experience trying to backtrack on fib/2 solutions:
fib(N, F) :- N > 1, % added sanity check
X is N - 1, Y is N - 2, fib(X, A), fib(Y, B), F is A + B.
Here's yet another approach. First, I redid fib a little so that it only recursively calls itself once instead of twice. To do this, I created a predicate that returns the prior the last two Fibonacci values instead of the last one:
fib(N, F) :-
fib(N, F, _).
fib(N, F, F1) :-
N > 2,
N1 is N-1,
fib(N1, F1, F0),
F is F0 + F1.
fib(1, 1, 0).
fib(2, 1, 1).
For getting the sequence, I chose an algorithm with the Fibonacci calculation built-in so that it doesn't need to call fib O(n^2) times. It does, however, need to reverse the list when complete:
fib_sequence(A, B, FS) :-
fib_seq_(A, B, FSR),
reverse(FSR, FS).
fib_sequence_(A, B, []) :-
A > B.
fib_sequence_(A, B, [F]) :-
A =:= B,
fib(A, F, _).
fib_sequence_(A, B, [F1,F0]) :-
1 is B - A,
fib(B, F1, F0).
fib_sequence_(A, B, [F2,F1,F0|FT] ) :-
B > A,
B1 is B - 1,
fib_sequence_(A, B1, [F1,F0|FT]),
F2 is F1 + F0.
Here's one more way, to do it without the reverse, but the reverse method above still appears to be a little faster in execution.
fib_sequence_dl(A, B, F) :-
fib_sequence_dl_(A, B, F, [_,_|[]]).
fib_sequence_dl_(A, B, [], _) :-
A > B, !.
fib_sequence_dl_(A, B, [F], _) :-
A =:= B,
fib(A, F, _), !.
fib_sequence_dl_(A, B, [F0,F1|T], [F0,F1|T]) :-
1 is B - A,
fib(B, F1, F0), !.
fib_sequence_dl_(A, B, F, [F1,F2|T]) :-
A < B,
B1 is B - 1,
fib_sequence_dl_(A, B1, F, [F0,F1|[F2|T]]),
F2 is F0 + F1.

Resources