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".
Related
In an ILP, given two variables x and y, is it possible to define a variable z where
z = (x==y)?
Meaning, if x equals y then z = 1.
Else, z = 0.
x and y are integer variables bounded between (1, M).
If you know that x <= y, then you can use z in {0,1}, x+Mz >= y, x+z <= y.
If you don't know which of x and y is minimum, you can do it with more work, by adding a variable minxy which takes the value of the minimum. You need to introduce another new variable (which I call a) to do this.
Introduce a variable a that's 0 if x<=y, 1 if y<=x (it could be either 0 or 1 if x==y):
a in {0,1}, x-y <= Ma, y-x <= M(1-a)
Introduce a variable minxy that's the minimum of x and y:
minxy <= x
minxy <= y
minxy >= x - Ma
minxy >= y - M(1-a)
Then you can define your z:
minxy + Mz >= x + y - minxy
minxy + z <= x + y - minxy
(Noting that max(x,y) is x + y - minxy).
In an ILP, How can I write a constraint "X is not in the interval [Y, Y+10]" ?
Is it even possible?
You didn't say, but I'm assuming x and y are non-negative integers and that the range you indicate to avoid is inclusive of endpoints...
You have an "or" condition there, so you will need to introduce a helper or "indicator" variable to handle the or condition, call it z, and a (constant) parameter for a reasonable upper bound on y, call it M:
z ∈ {0, 1} # 0 if below y, 1 if above y+10
M > reasonable_upper_bound(y)
Then 2 constraints based on that info to either constrain x to the lower set of values or the upper, excluding the interval (of disinterest):
x <= (y - 1) + z * M
x >= (y + 10 + 1) - (1 - z) * M
Truth Table:
z=0 z=1
x <= y-1 ~M
x >= ~0 y + 11
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.
I recently came up across this:
func main() {
x, y := 0, 1
x, y = y, x+y
fmt.Println(y)
}
What I thought was that:
x, y = y, x+y
Is identical to:
x = y
y = x+y
Which would result to final values x = 1, y = 2
However the final values I get is x = 1, y = 1
Why is that?
Thanks.
This is how it's specified:
The assignment proceeds in two phases. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in left-to-right order.
Assignment first evaluates all expressions on the right side and then assigns the results to the variables on the left side.
Your
x, y = y, x+y
is basically equivalent to this
tmp1 := y
tmp2 := x+y
x = tmp1
y = tmp2
You can even use this fact to swap 2 variables in one line, like this:
a, b = b, a
This is a follow up question for: Subtraction operation using only increment, loop, assign, zero
We're only allowed to use the following operations:
incr(x) - Once this function is called it will assign x + 1 to x
assign(x, y) - This function will assign the value of y to x (x = y)
zero(x) - This function will assign 0 to x (x = 0)
loop X { } - operations written within brackets will be executed X times
For example, addition can be implemented as follows:
add(x, y) {
loop x
{ y = incr(y) }
return y
}
How do I implement the relational operators using these four operations? The relational operations are:
eq(x, y) - Is x equal to y?
lt(x, y) - Is x lesser than y?
gt(x, y) - Is x greater than y?
We also have their opposites:
ne(x, y) - Is x not equal to y?
gte(x, y) - Is x greater than or equal to y?
lte(x, y) - Is x lesser than or equal to y?
Any help will be appreciated.
The set of natural numbers N is closed under addition and subtraction:
N + N = N
N - N = N
This means that the addition or subtraction of two natural numbers is also a natural number (considering 0 - 1 is 0 and not -1, we can't have negative natural numbers).
However, the set of natural numbers N is not closed under relational operations:
N < N = {0, 1}
N > N = {0, 1}
This means that the result of comparing two natural numbers is either truthfulness (i.e. 1) or falsehood (i.e. 0).
So, we treat the set of booleans (i.e. {0, 1}) as a restricted set of the natural numbers (i.e. N).
false = 0
true = incr(false)
The first question we must answer is “how do we encode if statements so that we may branch based on either truthfulness or falsehood?” The answer is simple, we use the loop operation:
isZero(x) {
y = true
loop x { y = false }
return y
}
If the loop condition is true (i.e. 1) then the loop executes exactly once. If the loop condition is false (i.e. 0) then the loop doesn't execute. We can use this to write branching code.
So, how do we define the relational operations? Turns out, everything can be defined in terms of lte:
lte(x, y) {
z = sub(x, y)
z = isZero(z)
return z
}
We know that x ≥ y is the same as y ≤ x. Therefore:
gte(x, y) {
z = lte(y, x)
return z
}
We know that if x > y is true then x ≤ y is false. Therefore:
gt(x, y) {
z = lte(x, y)
z = not(z)
return z
}
We know that x < y is the same as y > x. Therefore:
lt(x, y) {
z = gt(y, x)
return z
}
We know that if x ≤ y and y ≤ x then x = y. Therefore:
eq(x, y) {
l = lte(x, y)
r = lte(y, x)
z = and(l, r)
return z
}
Finally, we know that if x = y is true then x ≠ y is false. Therefore:
ne(x, y) {
z = eq(x, y)
z = not(z)
return z
}
Now, all we need to do is define the following functions:
The sub function is defined as follows:
sub(x, y) {
loop y
{ x = decr(x) }
return x
}
decr(x) {
y = 0
z = 0
loop x {
y = z
z = incr(z)
}
return y
}
The not function is the same as the isZero function:
not(x) {
y = isZero(x)
return y
}
The and function is the same as the mul function:
and(x, y) {
z = mul(x, y)
return z
}
mul(x, y) {
z = 0
loop x { z = add(y, z) }
return z
}
add(x, y) {
loop x
{ y = incr(y) }
return y
}
That's all you need. Hope that helps.