I'm currently stuck on a loop invariant proof in my home assignment. The algorithm that I need to prove correctness of, is:
Multiply(a,b)
x=a
y=0
WHILE x>=b DO
x=x-b
y=y+1
IF x=0 THEN
RETURN(y)
ELSE
RETURN(-1)
I've tried to look at several examples of loop invariants and I have some sense of idea of how its supposed to work out. However in this algorithm above, I have two exit conditions, and I'm a bit lost on how to approach this in a loop invariant proof. In particular its the termination part I'm struggling with, around the IF and ELSE statements.
So far what I've constructed is simply by looking at the termination of the algorithm in which case if x = 0 then it returns the value of y containing the value of n (number of iterations in the while loop), where as if x is not 0, and x < b then it returns -1. I just have a feeling I need to prove this some how.
I hope someone can help share some light on this for me, as the similar cases I've found in here, have not been sufficient.
Thanks alot in advance for your time.
Provided that the algorithm terminates (for this let's assume a>0 and b>0, which is sufficient), one invariant is that at every iteration of your while loop, you have x + by = a.
Proof:
at first, x = a and y = 0 so that's ok
If x + by = a, then (x - b) + (y + 1)b = a, which are the values of x and y for your next iteration
Illustration:
Multiply(a,b)
x=a
y=0
// x + by = a, is true
WHILE x>=b DO
// x + by = a, is true
x=x-b // X = x - b
y=y+1 // Y = y + 1
// x + by = a
// x - b + by + b = a
// (x-b) + (y+1)b = a
// X + bY = a, is still true
// x + by = a, will remain true when you exit the loop
// since we exited the loop, x < b
IF x=0 THEN
// 0 + by = a, and 0 < b
// y = a/b
RETURN(y)
ELSE
RETURN(-1)
This algorithm returns a/b when b divides a, and -1 otherwise. Multiply does not quite sound like an appropriate name for it...
We can't prove correctness without a specification of exactly what the function is supposed to do, which I can't find in your question. Even the name of the function doesn't help: as noted already, your function returns a/b most of the time when b divides a, and -1 otherwise. Multiply is an inappropriate name for it.
Furthermore, if b=0 and a>=b the "algorithm" doesn't terminate so it isn't even an algorithm.
As Alex M noted, a loop invariant for the loop is x + by = a. At the moment the loop exits, we also have x < b. There are no other guarantees on x because (presumably) a could be negative. If we had a guarantee that a and b are positive, then we could guarantee that 0<=x<b at the moment the loop exits, which would mean that it implements the division with remainder algorithm (at the end of the loop, y is quotient and x is remainder, and it terminates by an "infinite descent" type argument: a decreasing sequence of positive integers x must terminate). Then you could conclude that if x=0, b divides a evenly, and the quotient is returned, otherwise -1 is returned.
But that is not a proof, because we are lacking a specification for what the algorithm is supposed to do, and a specification on restrictions on its inputs. (Are a and b any positive integers? Negative and 0 not allowed?)
Related
I am struggling to find a good loop invariant for the following function, which returns a^b where a is a real number and b is a natural number:
power <- function(a, b){
c <- 1
while(b > 0){
if(b %% 2 == 1){
c <- c * a
}
b <- floor(b / 2)
a <- a * a
}
return c
}
I've ran through the loop with a couple of examples, and I see that it has 2 kinds of cases; when b is even or odd. I also understand that on the kth iteration, a = a_0^(2^k), but I am struggling to find a proper invariant as there is no real iterating variable to use.
For the invariant to be useful, it will have to have c = a_0^b_0 as a special case after the while loop terminates, which occurs when b = 0.
For the invariant to be true, we have to get a_0^b_0 on the left hand side before the first iteration. We already know the left hand side has a c in it, and before the first iteration c = 1, so multiplication seems like a good idea.
Whatever we multiply by must end up being 1 after the loop terminates, which (as before) occurs when b = 0. Getting something to equal 1 when b is 0 suggests we want b to be an exponent, and the desired a_0^b_0 on the left hand side also suggests b should be an exponent.
Putting this all together, the invariant will either be c * a_0^b = a_0^b_0 or c * a^b = a_0^b_0. I will leave it to you to determine which one of those is correct, and to prove that it is in fact invariant.
I am just a beginner of programming, and sorry in advance for bothering you by a (presumably) basic question.
I would like to perform the following task:
(I apologize for inconvenience; I don't know how to input a TeX-y formula in Stack Overflow ). I am primarily considering an implementation on MATLAB or Scilab, but language does not matter so much.
The most naive approach to perform this, I think, is to form an n-nested for loop, that is (the case n=2 on MATLAB is shown for example),
n=2;
x=[x1,x2];
for u=0:1
y(1)=u;
if x(1)>0 then
y(1)=1;
end
for v=0:1
y(2)=v;
if x(2)>0 then
y(2)=1;
end
z=Function(y);
end
end
However, this implementation is too laborious for large n, and more importantly, it causes 2^n-2^k abundant evaluations of the function, where k is a number of negative elements in x. Also, naively forming a k-nested for loop with knowledge of which element in x is negative, e.g.
n=2;
x=[-1,2];
y=[1,1];
for u=0:1
y(1)=u;
z=Function(y);
end
doesn't seem to be a good way; if we want to perform the task for different x, we have to rewrite a code.
I would be grateful if you provide an idea to implement a code such that (a) evaluates the function only 2^k times (possible minimum number of evaluations) and (b) we don't have to rewrite a code even if we change x.
You can evaluate Function on y in Ax easily using recursion
function eval(Function, x, y, i, n) {
if(i == n) {
// break condition, evaluate Function
Function(y);
} else {
// always evaluate y(i) == 1
y(i) = 1;
eval(Function, x, y, i + 1, n);
// eval y(i) == 0 only if x(i) <= 0
if(x(i) <= 0) {
y(i) = 0;
eval(Function, x, y, i + 1, n);
}
}
}
Turning that into efficient Matlab code is another problem.
As you've stated the number of evaluations is 2^k. Let's sort x so that only the last k elements are non-positive. To evaluate Function index y using the reverse of the permutation of the sort of x: Function(y(perm)). Even better the same method allows us to build Ax directly using dec2bin:
// every column of the resulting matrix is a member of Ax: y_i = Ax(:,i)
function Ax = getAx(x)
n = length(x);
// find the k indices of non-positives in x
is = find(x <= 0);
k = length(is);
// construct Y (last k rows are all possible combinations of [0 1])
Y = [ones(n - k, 2 ^ k); (dec2bin(0:2^k-1)' - '0')];
// re-order the rows in Y to get Ax according to the permutation is (inverse is)
perm([setdiff(1:n, is) is]) = 1:n;
Ax = Y(perm, :);
end
Now rewrite Function to accept a matrix or iterate over the columns in Ax = getAx(x); to evaluate all Function(y).
Can you please help me understand what ports in r if x = 0,1,2,3
y <-- 0
z <-- 1
r <-- z
while y < x {
Multiply z by 2;
Add z to r;
Increase y; }
In every looping step z is multiplied by 2, so you have the values 2,4,8,16... (or generally 2^n).
r is initially 1, and if you add z, you get 3,7,15,31 (generally 2^(n+1) - 1)
For x = 0 the loop will be skipped, so r stays 1
For x = 1 the loop will... uhm... loop one time, so you get 3
etc.
Apparently, the algorithm computes the sum of the powers of two from 0 to x and uses r as an accumulator for this. On termination, r holds the value 2^(x+1)-1.
I've just started with a Design Analysis and Algorithms course and we've begin with simple algorithms.
There is a division algorithm which I can't make any sense of.
function divide(x,)
Input: 2 integers x and y where y>=1
Output: quotient and remainder of x divided by y
if x=0: return (q,r)=(0,0)
(q,r)=divide(floor (x/2), y)
q=2q, r=2r
if x is odd: r=r+1
if r>=y: r=r-y, q=q+1
return(q,r)
* floor is lower bound
We were supposed to try this algo for 110011%101 ( binary values )...I tried something and I got a weird answer...converted into decimal values and it was wrong.
So I tried it using simple decimal values instead of binary first.
x=25, y=5
This is what I'm doing
1st: q=x,r= 12,5
2nd: q=x,r= 6,5
3rd: q=x,r= 3,5
4th: q=x,r= 1,5
5th: q=x,r= 0,5
How will this thing work? Everytime I will run it, the last value of last x will be 0(condition) it will stop and return q=0,r=0
Can someone guide me where I'm going wrong...
Thanks
I implemented your algorithm (with obvious correction in the arg list) in Ruby:
$ irb
irb(main):001:0> def div(x,y)
irb(main):002:1> return [0,0] if x == 0
irb(main):003:1> q,r = div(x >> 1, y)
irb(main):004:1> q *= 2
irb(main):005:1> r *= 2
irb(main):006:1> r += 1 if x & 1 == 1
irb(main):007:1> if r >= y
irb(main):008:2> r -= y
irb(main):009:2> q += 1
irb(main):010:2> end
irb(main):011:1> [q,r]
irb(main):012:1> end
=> nil
irb(main):013:0> div(25, 5)
=> [5, 0]
irb(main):014:0> div(25, 2)
=> [12, 1]
irb(main):015:0> div(144,12)
=> [12, 0]
irb(main):016:0> div(144,11)
=> [13, 1]
It's working, so you must not be tracking the recursion properly when you're trying to hand-trace it. I find it helpful to write the logic out on a new sheet of paper for each recursive call and place the old sheet of paper on top of a stack of prior calls. When I get to a return statement on the current sheet, wad it up, throw it away, and write the return value in place of the recursive call on the piece of paper on top of the stack. Carry through with the logic on this sheet until you get to another recursive call or a return. Keep repeating this until you run out of sheets on the stack - the return from the last piece of paper is the final answer.
The function has a recursive structure, which might be why it's a bit tricky. I'm assuming there's a typo in your function declaration where divide(x,) should be divide(x, y). Given that the desired result is x/y with the remainder, let's continue. The first line in the function definition claims that IF the numerator is 0, return 0 with a remainder of 0. This makes sense: while b != 0 and a = 0, a / b = 0 for all integers. Then we set the result to a recursive call with half the original numerator and the current denominator. At some point, "half the original numerator" turns into 0 and the base case is reached. There's a bit of computation at the end of each recursive call in what seems to be tail recursion. Because we divided by 2 on each deepning, multiply by 2 to get the original result and add 1 to the remainder if it's odd. It's hard to visualize in text alone so step through it on paper with a given problem.
Mathematically, the division algorithm (it's called that) states that the remainder must be less than or equal to 5 when you input 25,5.
The algorithm gives 0, 5. This might mean to NOT consider the remainder when the quotient is 0 or there needs to be a check on the size of the remainder.
function divide(x,) Input: 2 integers x and y where y>=1 Output: quotient and remainder of x divided by y
if x=0: return (q,r)=(0,0)
(q,r)=divide(floor (x/2), y)
q=2q, r=2r
if x is odd: r=r+1
if r>=y: r=r-y, q=q+1
return(q,r)
* floor is lower bound
If I remember correctly, this is one of the most basic ways of doing integral division in a simple ALU. It's nice because you can run all the recursive divisions in parallel, since each division is based on just looking at one less bit of the binary.
To understand what this does, simply walk through it on paper, as Chris Zhang suggested. Here's what divide(25,5) looks like:
(x,y)=(25,5)
divide(12, 5)
divide(6,5)
divide(3,5)
divide(1,5)
divide(0,5) // x = 0!
return(0,0)
(q,r)=(2*0,2*0)
x is odd, so (q,r)=(0,1)
r < y
return(0,1)
(q,r)=(2*0,2*1)
x is odd, so (q,r)=(0,3)
r < y
return(0,3)
(q,r)=(2*0,2*3)
x is even
r >= y, so (q,r)=(1,1)
return(1,1)
(q,r)=(2*1,2*1)
x is even
r < y
return(2,2)
(q,r)=(2*2,2*2)
x is odd, so (q,r)=(4,5)
r >= y, so (q,r)=(5,0)
return(5,0)
As you can see, it work - it gives you a q of 5 and an r of 0. The part you noticed, that you'll always eventually have a 0 term is what Chris properly calls "the base case" - the case that makes the recursive call unfold.
This algorithm works with any base number for the division and the multiplication. It uses the same principle as the following: "123 / 5 = (100 + 20 + 3) / 5 = 20 + 4 + r3 = 24r3", just done in binary.
Given N integer intervals [lo_i,hi_i].
From each interval chose a number such that bitwise OR of them become given number X.(It doesn't matter if the result has more 1 bits than X; i.e. if the generated number is Y, (X&Y)==X should hold)
I guess this problem is NP complete, though I haven't found an NP hard problem easily reducible to this.
But for those sets that contain 2^(mostSignificantDigit) - 1, I would do as a heuristic: Firstly, try the number 1...1 (mostSignificantDigit-1 ones), secondly a number with the most significant bit and as many other bits as possible set. This heuristic is only bad in the case that you would have required a number from the set with the most significant bit set and a few different less significant bits.
With this heuristic, you can also pick amongst those sets the largest number 1....1 as a further heuristic.
Let's generalize the problem a little. I'm going to write bitwise operators like OR and AND and SR (shift right).
Given a natural number X, intervals [lo_1, hi_1], ..., [lo_N, hi_N] consisting of natural numbers, and a bit b in {0, 1}, determine whether there exist natural numbers y_1 in [lo_1, hi_1], ..., y_N in [lo_N, hi_N] such that, letting Y = y_1 OR ... OR y_N, it holds that (X AND Y) = X and that there exists i such that x_i <= hi_i - b.
The base case for my recursive algorithm is when lo_1 = hi_1 = lo_2 = ... = hi_n = 0. There exists a solution if and only if X = 0 and b = 0.
Inductively, prepare a subproblem by letting X' = X SR 1 and lo_i' = lo_i SR 1 and hi_i' = hi_i SR 1. Let Odd(i) be true if and only if hi_i AND 1 = 1. Let Odd+(i) be true if and only if Odd(i) and lo_i < hi_i. If X AND 1 = 0:
If there exists i such that Odd+(i), then let b' = 0. Otherwise, let b' = b.
If X AND 1 = 1:
If there exist distinct i and j such that Odd+(i) and Odd(j), then let b' = 0. If there exists no j such that Odd(j), then let b' = 1. Otherwise, let b' = b.
Return the answer for the subproblem.