I wrote this mini pseudo code that solves the equation using the Euler method:
// y'= x^2 - 5y
int n = 10; // count of steps
double h = 0.5; // step
double x = 0;
double y = 1;
for (int i = 0; i < n; i++) {
y += h * (x * x - 5 * y);
x += h;
}
write << y; //result
Now I am trying to write this in Prolog language
loop2(N,H,X,Y) :-
N > 0,
write(Y), nl,
Y is Y + H * (X * X - 5 * Y),
X is X + H,
S is N - 1,
loop2(S, H, X, Y).
Here I solved the example on a piece of paper and should get 62.5
But in Prolog my Output =
?- loop2(10, 0.5, 0, 1).
1
false.
X is X + H becomes 0 is 0 + 0.5 and it is not, so case closed as far as Prolog is concerned, it has found your logical code is false, and reports that to you. You did tell it to writeln(Y) before that, so you still see 1 while it was trying.
You need to use new variable names for the results of calculations like you have used S is N - 1, e.g. Xnext is X + H.
The way you have shaped the countdown, S will eventually become 0 and then N > 0 will be false and the whole thing will fail then. You can probably get away with using this to write the values before it eventually fails, but a more normal way to end recursion is to have
loop2(0,_,_,_).
loop2(N,H,X,Y) :-
...
which says that when the call to loop2 happens, the top one is found first, if the first position is 0, then it succeeds. That ends the recursion and the whole thing succeeds.
Related
I've been given the following function written in pseudocode:
P:
{
int x, y, z;
read (x, y, z);
while (x != y) {
x = x - y;
z = z + y
};
write z;
}
Given that f(x,y,z) is the function calculated by P, I would like to know if the function "g(x,y,z)=1 if f(x,y,z) is not a total function or g(x,y,z)=0 otherwise", is computable.
My first guess is: yes, it is computable (for example for x=y).
Is there a more rigorous general approach to prove that?
P does not change the value of y, and the only way it changes the value of x is to subtract y from x until x = y. If subtracting y from x does not eventually result in x = y, then the loop continues forever. We know that subtracting y from x repeatedly can only cause x = y if initially x = cy for natural numbers c >= 1. So, g(x,y,z) = 1 because f(x,y,z) is not a total function; it is undefined when x != cy for any natural number c >= 1. Even if what you meant is that g(x,y,z) = 1 whenever f(x,y,z) is defined, it is still computable, since g(x,y,z) is the function:
g(x,y,z) = { 1, if x = cy for some natural number c >= 1 }
{ 0, otherwise }
The condition x = cy for some natural number c >= 1 is itself computable since this is equivalent to "x >= y" and "GCD(x, y) = y".
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.
}
(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).
Would it be possible to do "pow" with "add" predicate (or just X is Y + Z )?
I make this:
pow(0,1,1).
pow(_,0,1).
pow(X,Y,Z) :- Y1 is Y - 1, pow(X,Y1,Z1), Z is Z1 * X.
But I want also make it with " + " (just for practise) like 3^2 = 3 * 3 = 3 + 3 + 3
You can write the multiplication (mul/3) in terms of addition. Like:
pow(0,1,1).
pow(_,0,1).
pow(X,Y,Z) :-
Y > 1,
Y1 is Y - 1,
pow(X,Y1,Z1),
mul(Z1,X,Z). %% originally: Z is Z1 * X.
mul(0,_,0).
mul(I,A,R) :-
I > 0,
I1 is I-1,
mul(I1,A,R1),
R is R1 + A.
Usually a basic exercise is to write addition, multiplication, and power predictates with the Peano number representation. In that case addition is written with the successor functor.
Ok, by far, I guess many people know the famous fast inverse square root (see more on Writing your own square root function and 0x5f3759df)
Here is the code
float FastInvSqrt(float x) {
float xhalf = 0.5f * x;
int i = *(int*)&x; // evil floating point bit level hacking
i = 0x5f3759df - (i >> 1); // what the fuck?
x = *(float*)&i;
x = x*(1.5f-(xhalf*x*x)); // one Newton Method iteration
return x;
}
Ok, i do NOT need to know more how magic 0x5f3759df is.
What I don't understand is why x*(1.5f-(xhalf*x*x)) is a Newton Method iteration?
I tried analyse but just can't get it.
So let's assume r is the real number and x is the inverse sqrt of r.
1 / (x^2) = r, then f(x) = r*(x^2)-1 and f'(x) = 2 * r * x
So one iteration should be x1 = x - f(x)/f'(x) = x / 2 + 1 / (2 * r * x), right?
How comes x * (1.5 - ((r / 2) * x * x))? (note I replaced xhalf with r / 2 here)
Edit
Ok f(x) = x^2 - 1/r is another form, let me calculate
f(x) = x^2 - 1 / r
f'(x) = 2 * x
So x1 = x - (f(x)/f'(x)) = x - (x^2 -(1 / r))/(2*x) = x / 2 + 1 / (2 * r * x), still it is quite different from the formula used in the code, right?
Wikipedia says function is (using your variable names):
f(x) = 1/x2 - r
Then we have:
f'(x) = -2/x3
And iteration is:
x - f(x)/f'(x) =
x - (1/x2 - r)/(-2 / x3) =
x + x3 /2 * (1/x2 - r) =
x + x/2 - r/2 * x3 =
x * (1.5 - r/2 * x * x)
And this is what you see in code.
Newton's method is defined in terms of the iteration
xi+1 = xi - f(xi) / f'(xi)
(where f'(x) is the first derivative of f(x)). To find the inverse root of r, one needs to find the zero of the function f(x) = x - 1/sqrt(r) (or, equivalently, f(x) = x2 - 1/r). Simply take the derivative, plug it in to the definition of the iteration step, simplify, and you have your answer.
Actually, the exact form used in the code comes from using a third equivalent form:
f(x) = x-2 - r
See this article for the detailed steps of the derivation. It's also derived in the Wikipedia article on fast inverse square root.