Prolog, check divisibility in Peano arithmetic - prolog

I need to check if first given term (for example s(s(nul)) (or 2)) is dividable by the second term, (for example s(nul) (or 1)).
What I want to do is multiply given term by two and then check if that term is smaller or equal to the other term (if it is equal - problem is solved).
So far I got this:
checkingIfDividable(X,X).
checkingIfDividable(X,Y) :-
X > Y,
multiplication(X,Y).
/* multiplication by two should occur here.
I can't figure it out. This solution does not work!*/
multiplication(Y):-
YY is Y * 2,
checkingIfDividable(X,YY).
I can't seem to figure out how to multiply a term by 2. Any ideas?

If a = n*b, n > 0, it is also a = n*b = (1+m)*b = b + m*b, m >= 0.
So if a is dividable by b, and a = b+x, then x is also dividable by b.
In Peano encoding, n = 1+m is written n = s(m).
Take it from here.

Related

The way of thinking in multiply 2 natural numbers (problem solving”)

Prove the correctness of the following recursive algorithm to multiply two natural numbers, for all integer constants c ≥ 2.
function multiply(y,z) comment Return the product yz.
1. if z = 0 then return(0) else
2. return(multiply(cy, z/c) + y · (z mod c))
I saw this algorithm in “Algorithm Design Manual”.
I know why it works correctly, but I want to know how this algorithm came to be. Is that a good way to think of multiply two natural number with a constant c?
(multiply(cy, z/c) + y · (z mod c))
When c is the base of your representation (like decimal), then this is how multiplication can be done "manually". It's the "shift and add" method.
In c-base cy is a single shift of y to the left (i.e. adding a zero at the right); and z/c is a single shift of z to the right: the right most digit is lost.
That lost digit is actually z mod c, which is multiplied with y separately.
Here is an example with c = 10, where the apostrophe signifies the value of variables in a recursive call.
We perform the multiplication with y for each separate digit of z (retrieved with z mod c). Each next product found in this way is written shifted one more place to the left. Usually the 0 is not padded at the right of this shifted product, but it is silently assumed:
354 y
x 29 z
----
3186 y(z mod c) = 354·9 = 3186
+ 708 y'(z' mod c) = yc(z/c mod c) = 3540·2 = 7080
------
10266
So the algorithm just relies on the mathematical basis for this "shift and add" method in a given c-base.

Defining a mathematical language in prolog

So I have this mathematical language, it goes like this:
E -> number
[+,E,E,E] //e.g. [+,1,2,3] is 1+2+3 %we can put 2 to infinite Es here.
[-,E,E,E] //e.g. [-,1,2,3] is 1-2-3 %we can put 2 to infinite Es here.
[*,E,E,E] //e.g. [*,1,2,3] is 1*2*3 %we can put 2 to infinite Es here.
[^,E,E] //e.g. [^,2,3] is 2^3
[sin,E] //e.g. [sin,0] is sin 0
[cos,E] //e.g. [cos,0] is cos 0
and I want to write the set of rules that finds the numeric value of a mathematical expression written by this language in prolog.
I first wrote a function called "check", it checks to see if the list is written in a right way according to the language we have :
check1([]).
check1([L|Ls]):- number(L),check1(Ls).
check([L|Ls]):-atom(L),check1(Ls).
now I need to write the function "evaluate" that takes a list that is an expression written by this language, and a variable that is the numeric value corresponding to this language.
example:
?-evaluate([*,1,[^,2,2],[*,2,[+,[sin,0],5]]]],N) -> N = 40
so I wrote this:
sum([],0).
sum([L|Ls],N):- not(is_list(L)),sum(Ls,No),N is No + L.
min([],0).
min([L|Ls],N):-not(is_list(L)), min(Ls,No),N is No - L.
pro([],0).
pro([X],[X]).
pro([L|Ls],N):-not(is_list(L)), pro(Ls,No), N is No * L.
pow([L|Ls],N):-not(is_list(L)), N is L ^ Ls.
sin_(L,N):-not(is_list(L)), N is sin(L).
cos_(L,N):-not(is_list(L)), N is cos(L).
d([],0).
d([L|Ls],N):- L == '+' ,sum(Ls,N);
L == '-',min(Ls,N);
L == '*',pro(Ls,N);
L == '^',pow(Ls,N);
L == 'sin',sin_(Ls,N);
L == 'cos',cos_(Ls,N).
evaluate([],0).
evaluate([L|Ls],N):-
is_list(L) , check(L) , d(L,N),L is N,evaluate(Ls,N);
is_list(L), not(check(L)) , evaluate(Ls,N);
not(is_list(L)),not(is_list(Ls)),check([L|Ls]),d([L|Ls],N),
L is N,evaluate(Ls,N);
is_list(Ls),evaluate(Ls,N).
and it's working for just a list and returning the right answer , but not for multiple lists inside the main list, how should my code be?
The specification you work with looks like a production rule that describes that E (presumably short for Expression) might be a number or one of the 6 specified operations. That is the empty list [] is not an expression. So the fact
evaluate([],0).
should not be in your code. Your predicate sum/2 almost works the way you wrote it, except for the empty list and a list with a single element, that are not valid inputs according to your specification. But the predicates min/2 and pro/2 are not correct. Consider the following examples:
?- sum([1,2,3],X).
X = 6 % <- correct
?- sum([1],X).
X = 1 % <- incorrect
?- sum([],X).
X = 0 % <- incorrect
?- min([1,2,3],X).
X = -6 % <- incorrect
?- pro([1,2,3],X).
X = 6 ? ; % <- correct
X = 0 % <- incorrect
Mathematically speaking, addition and multiplication are associative but subtraction is not. In programming languages all three of these operations are usually left associative (see e.g. Operator associativity) to yield the mathematically correct result. That is, the sequence of subtractions in the above query would be calculated:
1-2-3 = (1-2)-3 = -4
The way you define a sequence of these operations resembles the following calculation:
[A,B,C]: ((0 op C) op B) op A
That works out fine for addition:
[1,2,3]: ((0 + 3) + 2) + 1 = 6
But it doesn't for subtraction:
[1,2,3]: ((0 - 3) - 2) - 1 = -6
And it is responsible for the second, incorrect solution when multiplying:
[1,2,3]: ((0 * 3) * 2) * 1 = 0
There are also some other issues with your code (see e.g. #lurker's comments), however, I won't go into further detail on that. Instead, I suggest a predicate that adheres closely to the specifying production rule. Since the grammar is describing expressions and you want to know the corresponding values, let's call it expr_val/2. Now let's describe top-down what an expression can be: It can be a number:
expr_val(X,X) :-
number(X).
It can be an arbitrarily long sequence of additions or subtractions or multiplications respectively. For the reasons above all three sequences should be evaluated in a left associative way. So it's tempting to use one rule for all of them:
expr_val([Op|Es],V) :-
sequenceoperator(Op), % Op is one of the 3 operations
exprseq_op_val(Es,Op,V). % V is the result of a sequence of Ops
The power function is given as a list with three elements, the first being ^ and the others being expressions. So that rule is pretty straightforward:
expr_val([^,E1,E2],V) :-
expr_val(E1,V1),
expr_val(E2,V2),
V is V1^V2.
The expressions for sine and cosine are both lists with two elements, the first being sin or cos and the second being an expression. Note that the argument of sin and cos is the angle in radians. If the second argument of the list yields the angle in radians you can use sin/1 and cos/2 as you did in your code. However, if you get the angle in degrees, you need to convert it to radians first. I include the latter case as an example, use the one that fits your application.
expr_val([sin,E],V) :-
expr_val(E,V1),
V is sin(V1*pi/180). % radians = degrees*pi/180
expr_val([cos,E],V) :-
expr_val(E,V1),
V is cos(V1*pi/180). % radians = degrees*pi/180
For the second rule of expr_val/2 you need to define the three possible sequence operators:
sequenceoperator(+).
sequenceoperator(-).
sequenceoperator(*).
And subsequently the predicate exprseq_op_val/3. As the leading operator has already been removed from the list in expr_val/2, the list has to have at least two elements according to your specification. In order to evaluate the sequence in a left associative way the value of the head of the list is passed as an accumulator to another predicate exprseq_op_val_/4
exprseq_op_val([E1,E2|Es],Op,V) :-
expr_val(E1,V1),
exprseq_op_val_([E2|Es],Op,V,V1).
that is describing the actual evaluation. There are basically two cases: If the list is empty then, regardless of the operator, the accumulator holds the result. Otherwise the list has at least one element. In that case another predicate, op_val_args/4, delivers the result of the respective operation (Acc1) that is then recursively passed as an accumulator to exprseq_op_val_/4 alongside with the tail of the list (Es):
exprseq_op_val_([],_Op,V,V).
exprseq_op_val_([E1|Es],Op,V,Acc0) :-
expr_val(E1,V1),
op_val_args(Op,Acc1,Acc0,V1),
exprseq_op_val_(Es,Op,V,Acc1).
At last you have to define op_val_args/4, that is again pretty straightforward:
op_val_args(+,V,V1,V2) :-
V is V1+V2.
op_val_args(-,V,V1,V2) :-
V is V1-V2.
op_val_args(*,V,V1,V2) :-
V is V1*V2.
Now let's see how this works. First your example query:
?- expr_val([*,1,[^,2,2],[*,2,[+,[sin,0],5]]],V).
V = 40.0 ? ;
no
The simplest expression according to your specification is a number:
?- expr_val(-3.14,V).
V = -3.14 ? ;
no
The empty list is not an expression:
?- expr_val([],V).
no
The operators +, - and * need at least 2 arguments:
?- expr_val([-],V).
no
?- expr_val([+,1],V).
no
?- expr_val([*,1,2],V).
V = 2 ? ;
no
?- expr_val([-,1,2,3],V).
V = -4 ? ;
no
The power function has exactly two arguments:
?- expr_val([^,1,2,3],V).
no
?- expr_val([^,2,3],V).
V = 8 ? ;
no
?- expr_val([^,2],V).
no
?- expr_val([^],V).
no
And so on...

Quadratic equation solving in Prolog

I have wrote a code to solve equation with like terms (eg:- x^2+5*x+6=0). Here 'x' has two values. I can take two values by entering ';'. But I need to get the all possible answers when I run the program at once. Is it possible in prolog?
Well for a quadratic equation, if the discriminant is zero, then
there is only one solution, so you can directly compute one or two
solutions, and return them in a list.
The discriminat is the expression under the square root. So the
classical prolog code for a real number solution reads as follows:
solve(A*_^2+B*_+C=0,L) :- D is B^2-4*A*C,
(D < 0 -> L = [];
D =:= 0 -> X is (-B)/(2*A), L = [X];
S is sqrt(D), X1 is (-B-S)/(2*A),
X2 is (-B+S)/(2*A), L=[X1,X2]).
Here is an example run:
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.0)
?- solve(1*x^2+5*x+6=0,L).
L = [-3.0, -2.0].

Right-angled triangle prolog construction

I'm to ask a question, which answers are solving this task:
Which right-angled triangles can be constructed by choosing three sides out of six segments of length being integers from 1 to 6
So, I'm thinking this is essential:
between(1,6,X),
between(1,6,Y),
between(1,6,Z),
Then we have to make sure it fits Pythagoras statement, so I'm trying this, adding to the above sentence:
(X^2 = Y^2 + Z^2 ;
Y^2 = X^2 + Z^2 ;
Z^2 = X^2 + Y^2)
Also I have been trying to replace X^2 with X*X, but it returns false every time. Why is that?
From my understanding, I need it to work like this:
Choose three sides from range 1-6, and make sure they fit Pythagoras statement. (Is triangle disparity also required here? I mean X>Y+Z,Y>X+Z,Z>X+Y ?
Check the prolog manual regarding the different comparators, etc. They mean and do various things. =:=/2 is specifically evaluates arithmetic expressions on either side and checks for equality of results. =/2 is not an equality operator; it performs prolog unification. It's important to know the difference. In your example, limiting all results to maximum of 6, then permutations of 3,4,5 are the only positive integer solutions to the right triangle.
?- between(1,6,X), between(1,6,Y), between(1,6,Z), Z^2 =:= X^2 + Y^2.
X = 3,
Y = 4,
Z = 5 ;
X = 4,
Y = 3,
Z = 5 ;
false.

Calculating product by addition

This is an algorithm question that I've been struggling with. I figured I could get some insight here. I need to make the following function in Haskell:
Declare the type and define a function that takes two numbers as input and finds their product by addition. That is, add the first number, as many times as second number, to itself.
My problem is that this is basically just multiplying two numbers together, but it says that I need to do it with addition. Does anyone have any clue on how to do this?
This is all I can come up with (it's not right): (x + x) * y
Thank you
if a is the first number and b the second
sum $ take a $ cycle [b]
should do ot
mult (x, y):
sum = 0
for 1 to y:
sum = sum + x
return sum
This is just the algorithm. I do not know Haskell. So the lambda expression in the other answer may be more appropriate. Also, I use an intermediate variable.
PS: forget the previous embarrassing recursive algorithm
Work it out by induction.
We know the answer to one simple (the simplest) problem: multiplying anything by 0 yields 0. So we write:
mul x 0 = 0
Now, the inductive step: we can build a solution to a bigger problem, if we know a solution to the smaller problem; that way we can always reduce any big problem to the smallest problem, for which we know the solution. So, for any y, the solution for y+1 can be found by adding x to the solution for y: mul x (y+1) = x + (mul x y). In Haskell we can't write (y+1) on the left hand side, so we write equivalently:
mul x y = x + (mul x (y-1))
This function will keep adding x until y is zero.
Try this also
multiply::(Num a,Eq a) => a -> a -> a
multiply a 0 = 0
multiply a b = a + multiply a (b - 1)
main = print $ multiply 5 7

Resources