This is My First Logic Programming Language course so this is a really Dumb Question But I cannot for the life of me figure out how does this power predicate work I've tried making a search tree to trace it But I still cannot understand how is it working
mult(_ , 0 ,0).
mult(X , Y, Z):-
Y > 0,
Y1 is Y - 1,
mult(X,Y1,Z1),
Z is Z1 + X.
exp2(_ ,0 , 1).
exp2(X,Y,Z):-
Y > 0,
Y1 is Y - 1,
exp2(X , Y1 , Z1),
mult(X,Z1,Z).
I so far get that I'm going to call the exp2 predicate till I reach the point where the Y is going to be Zero then I'm going to start multiplying from there, but At the last call when it's at exp2(2 , 1 , Z) what is the Z value and how does the predicate work from there?
Thank you very much =)
EDIT: I'm really sorry for the Late reply I had some problems and couldn't access my PC
I'll walk through mult/3 in more detail here, but I'll leave exp2/3 to you as an exercise. It's similar..
As I mentioned in my comment, you want to read a Prolog predicate as a rule.
mult(_ , 0 ,0).
This rule says 0 is the result of multiplying anything (_) by 0. The variable _ is an anonymous variable, meaning it is not only a variable, but you don't care what its value is.
mult(X, Y, Z) :-
This says, Z is the result of multiplying X by Y if....
Y > 0,
Establish that Y is greater than 0.
Y1 is Y - 1,
And that Y1 has the value of Y minus 1.
mult(X, Y1, Z1),
And that Z1 is the result of multiplying X by Y1.
Z is Z1 + X.
And Z is the value of Z1 plus X.
Or reading the mult(X, Y, Z) rule altogether:
Z is the result of multiplying X by Y if Y is greater than 0, and Y1 is Y-1, and Z1 is the result of multiplying X by Y1, and Z is the result of adding Z1 to X.
Now digging a little deeper, you can see this is a recursive definition, as in the multiplication of two numbers is being defined by another multiplication. But what is being multiplied is important. Mathematically, it's using the fact that x * y is equal to x * (y - 1) + x. So it keeps reducing the second multiplicand by 1 and calling itself on the slightly reduced problem. When does this recursive reduction finally end? Well, as shown above, the second rule says Y must be greater than 0. If Y is 0, then the first rule, mult(_, 0, 0) applies and the recursion finally comes back with a 0.
If you are not sure how recursion works or are unfamiliar with it, I highly recommend Googling it to understand it. That is, indeed, a concept that applies to many computer languages. But you need to be careful about learning Prolog via comparison with other languages. Prolog is fundamentally different in it's behavior from procedural/imperative languages like Java, Python, C, C++, etc. It's best to get used to interpreting Prolog rules and facts as I have described above.
Say you want to compute 2^3 as assign result to R.
For that you will call exp2(2, 3, R).
It will recursively call exp2(2, 2, R1) and then exp2(2, 1, R2) and finally exp(2, 0, R3).
At this point exp(_, 0, 1) will match and R3 will be assigned to 1.
Then when call stack unfolds 1 will be multiplied by 2 three times.
In Java this logic would be encoded as follows. Execution would go pretty much the same route.
public static int Exp2(int X, int Y) {
if (Y == 0) { // exp2(_, 0, 1).
return 1;
}
if (Y > 0) { // Y > 0
int Y1 = Y - 1; // Y1 is Y - 1
int Z1 = Exp2(X, Y1); // exp2(X, Y1, Z1);
return X * Z1; // mult(X, Z1, Z).
}
return -1; // this should never happen.
}
Related
So I drew a simple function in prolog that counts how many of a variable are in a matrix.
And it goes like this :
:-use_module(library(lists)).
:-use_module(library(clpfd)).
countOccurrences([],Y,0).
countOccurrences([X|T], Y, Z):-
countOccur(X, Y, N),
Acc #=N + Z,
countOccurrences(T, Y, Acc).
countOccur([],X,0).
countOccur([X|T],X,Y):- countOccur(T,X,Z), Y is 1+Z.
countOccur([X1|T],X,Z):- X1\=X,countOccur(T,X,Z).
countOccur seems to be working fine and returns the right value. The problem is countOccurences is returning the right absolute value but negative. I Just dont seem to understand why that is happening.
Can someone enlighten me ?
An input of [[a,a,a,a]] looking for a does countOccurrences of a in [] and sets Acc = 0 and then countOccur of a in [a,a,a,a] sets N=4 then Acc #= N + Z becomes 0 #= 4 + Z and so the result must be Z = -4.
I have:
:-use_module(library(clpr)).
comp(X, Y, Z):-
{X = Y * Z, Y = Z, Y > 0, Z > 0}.
Which with the query:
?-comp(X,3,Z).
Yields:
X = 9.0,
Z = 3.0
as expected. But why doesn't
comp(9,Y,Z).
also give me values for Y and Z? What I get is instead:
{Z>0.0,Y=Z,9-Y*Z=0.0},
{9-Y*Z=0.0},
{9-Y*Z=0.0}
Thanks!
Probably a weakness of the used CLP(R) that quadratic case doesn't work so well. After Y = Z, it is evident that X = Y**2, and then with X = 9 and Y > 0, you should easily get Y = 3. Which CLP(R) do you use?
A CLP(R) need not only support linear equalities and inequalities. Using for example Gröbner Basis algorithm a CLP(R) could do more, even algebraically. Some computer algebra system can do that easily.
So I guess its not a problem of Prolog per se, rather of the library. Strictly speaking CLP(X) only indicates a domain X. For the domain R of real numbers there is wide variety of potential equation and inequation solvers.
Better with constraints over finite domains using this module:
:-use_module(library(clpfd)).
comp(X, Y, Z):-
X #= Y * Z, Y #= Z, Y #> 0, Z #> 0.
With
comp(9,Y,Z).
I get:
Y = Z, Z = 3
(I'm not sur if return is the right word to describe it, but that's the best one I could find.)
I am trying to write a small program in prolog that uses the function add to do multiplications. When I run add by itself or even when it is called by the function test the result is "Z = the sum" ex: if I run add(2,3,Z) it will display Z=5.
My problem is that I can't get it to do the same thing when I call mult. The only solution that I found is to use write, but that's not the same thing. I tried a lot of stuff but most of it wasn't even compiling and the rest didn't change anything. Does anybody know how I could make it do that ("Z = the product")? What would be the way to make it do that (return) for a program in general?
Thank You
add(X,Y,Z) :-
Z is X + Y.
mult(X,Y,Z1):-
multiply(X,Y,0).
multiply(_,0,_):-
write(0).
multiply(0,_,Z):-
write(Z).
multiply(X,Y,Z):-
X > 0,
add(Y,Z,Z1),
X1 is X - 1,
multiply(X1,Y,Z1).
multiply(X,Y,Z):-
Y < 0,
X1 is abs(X),
Y1 is abs(Y),
multiply(X1,Y1,Z).
multiply(X,Y,Z):-
Y1 is Y * -1,
add(Y1,Z,Z1),
X1 is X + 1,
multiply(X1,Y,Z1).
test(X,Y,Z1):-
add(X,Y,Z1).
I managed to get it working by adding a 4th parameter. I don't know if it is the right way to do it but it works.
mult(X,Y,Z):-
multiply(X,Y,0,Z).
multiply(_,0,_,Z):-
Z is 0.
multiply(0,_,Z1,Z):-
Z is Z1.
multiply(X,Y,Z1,Z):-
X > 0,
add(Y,Z1,Z2),
X1 is X - 1,
multiply(X1,Y,Z2,Z).
multiply(X,Y,Z1,Z):-
Y < 0,
X1 is abs(X),
Y1 is abs(Y),
multiply(X1,Y1,Z1,Z).
multiply(X,Y,Z1,Z):-
Y1 is Y * -1,
add(Y1,Z1,Z2),
X1 is X + 1,
multiply(X1,Y,Z2,Z).
We try to translate a very simple program in pseudo-code to Predicate Logic.
The program is straightforward and does not contain loops. (sequential)
It only consists of assignments of variables and if-else statements.
Unfortunately we do not have any good information provided to solve the problem. It would be great if someone has some
examples "conversions" of simple 5liner code snippets or
links to sources for free information, which describe the topic on the surface level. ( We only do predicate and prepositional logic and do not want to dive much deeper in the logic space. )
Kind regards
UPDATE:
After enough research I found the solution and can share it inc. examples.
The trick is to think of the program state as a set of all our arbitrary variables inc. a program counter which stands for the current instruction to be executed.
x = input;
x = x*2;
if (y>0)
x = x∗y ;
else
x = y;
We will form the Predicate P(x,i,y,pc).
From here we can build promises e.g.:
∀i∀x∀y(P (x, i, y, 1) => P (i, i, y, 2))
∀i∀x∀y(P (x, i, y, 2) => P (x ∗ 2, i, y, 3))
∀i∀x∀y(P (x, i, y, 3) ∧ y > 0 =⇒ P (x ∗ y, i, y, 4))
∀i∀x∀y(P (x, i, y, 3) ∧ ¬y > 0 =⇒ P (y, i, y, 4))
By incrementing the Program counter we make sure that the promises follow in order. Now we are able to define make a proof when given a premise for the Input e.g. P(x,4,7,1).
So I'm trying to find the direction that the blank tile in the 8 tile puzzle will be sliding,
I am using X/Y to determine the tiles.
Here's the code I have.
mandist( X /Y , X1 / Y1 , D, Direction):-
D is abs(X - X1 )+ abs(Y - Y1 ),
Y is Y1 ->(
( X is X1 +1 -> Direction ='left')
;
( X1 is X +1 -> Direction = 'right'))
; X is X1 ->(
( Y1 is Y +1 -> Direction ='up')
;
( Y is Y1 +1 -> Direction ='down')).
The problem I'm getting is that when calling the mandist predicate it isn't giving me the results I had hoped for.
I am sure the problem is with the if statement, I have wrote some psuedocode so you can understand what I'm trying to do,
if(Y == Y1){
// Change the X Axis
if(X == X1 +1){
This is a left move
}
else{
This is a right move
}
}else if (X == X1){
// Change the Y Axis
if(Y == Y1 + 1){
This is an up move
}
else{
This is a down move
}
}
Example:
move([1/1, 3/1, 1/3, 2/3, 3/3, 1/2, 2/2, 3/2,2,1], X, Direction)
This then calls the mandist predicate
With D set to 1, so it ensures its a legal move
Here is the unexpected result:
mandist(1/1, X,1, Direction).
Direction = up ;
false
I am also expecting it to say Direction = right because position 1/1 is the very bottom left of the 3x3 grid and the only moves from the bottom left are either up or right
1/3 2/3 3/3
1/2 2/2 3/2
1/1 2/1 3/1
Based on your question, you probably want to write the following clause:
mandist(X/Y,XD/Y,D,right) :-
XD is X+D.
mandist(X/Y,X/YD,D,up) :-
YD is Y+D.
mandist(X/Y,XD/Y,D,left) :-
XD is X-D.
mandist(X/Y,X/YD,D,down) :-
YD is Y-D.
Given you write this to the file, it will generate:
?- mandist(1/1,X,1,Direction).
X = 2/1,
Direction = right ;
X = 1/2,
Direction = up ;
X = 0/1,
Direction = left ;
X = 1/0,
Direction = down.
Furthermore it can validate whether two coordinates are located in a certain direction given D us instantiated:
?- mandist(1/1,1/2,1,Direction).
Direction = up ;
false.
However it will not work with:
?- mandist(1/1,1/2,D,Direction).
ERROR: is/2: Arguments are not sufficiently instantiated
There is however a way to do this. Please updated your question if that is a requirement.
EDIT:
Since there are bounds, you can simply add them to the clauses. If you can assume that the first pair of coordinates are valid, it is simply:
mandist(X/Y,XD/Y,D,right) :-
XD is X+D,
XD < 4.
mandist(X/Y,X/YD,D,up) :-
YD is Y+D,
YD < 4.
mandist(X/Y,XD/Y,D,left) :-
XD is X-D,
XD > 0.
mandist(X/Y,X/YD,D,down) :-
YD is Y-D,
YD > 0.