问题
CLRS says that
We must show three things about a loop invariant:
- Initialization: It is true prior to the first iteration of the loop.
- Maintenance: If it is true before an iteration of the loop, it remains true before the next iteration.
- Termination: When the loop terminates, the invariant gives us a useful property that helps show that the algorithm is correct.
My question is can I edit the steps and make them these instead:
- Initialization: It is true after the first iteration of the loop.
- Maintenance: If it is true after an iteration of the loop, it remains true after the next iteration.
- Termination: When the loop terminates, the invariant gives us a useful property that helps show that the algorithm is correct.
Explanation: Basically we use Principle Of Mathematical Induction to prove correctness. Using "Initialization" we prove that the property holds after the 1st iteration. Using "Maintenance" we can show that the property holds for all iterations since "Initialization" and "Maintenance" together create a chain. And hence the property holds after the last iteration too.
Example:
RANDOMIZE-IN-PLACE(A)
1 n ← length[A]
2 for i ← to n
3 do swap A[i] ↔ A[RANDOM(i, n)]
For this algorithm, there is already a proof given in the textbook using the standard procedure (I didn't include it here since it is too long).
My suggestion:
- Loop Invariant: Just after the ith iteration of the for loop of lines 2-3, for each possible (i)-permutation, the subarray A[1 .. i] contains this (i)-permutation with probability (n - i)!/n!.
- Initialization: After 1st iteration A[1] contains this permutation with probability (n-1)!/n!=1/n which is true.
- Maintenance: Let it be true after (i-1)th iteration. After (i)th iteration, A[1...i] contains this permutation with probability [(n-i+1)!/n!]*[1/(n-i+1)]=(n-i)!/n! which is what we want.
- Termination: At termination, i = n, and we have that the subarray A[1 .. n] is a given n-permutation with probability (n - n)!/n! = 1/n!. Thus, RANDOMIZE-IN-PLACE produces a uniform random permutation.
Is my explanation logically sound?
Any help would be greatly appreciated. Thanks.
回答1:
Apart from the fact, that you have to make an additional step, which covers the loop never running at all, you can of course also prove that the invariant is true after the first iteration instead of proving that it is true before the first iteration.
However I doubt that this will often make much sense
- First, as already stated you have already a special case (what happens if the loop isn't executed at all) which probably results in a proof, which is similar to the Initialization, that you wanted to skip in the first place
- Secondly, the proof that the invariant is true after the first iteration, is very likely to be very similar to the Maintanance proof, so you are likely to write two very similar proofs, just to skip the Initialization, which is likely to be quite an easy proof.
Analogy
Although this is not directly related, this question sounds a lot like trying to optimize the following (pseudo)code:
int product(int[] values)
product = 1
for i = 0 to values.size - 1
product *= values[i]
return product
To this:
int product(int[] values)
product = values[0] // to make the code quicker, start with the first item already
for i = 1 to values.size - 1 // start the loop at the second item
product *= values[i]
return product
just, that you now have to include the additional check, whether the values
array is empty (which I did not in the above code)
来源:https://stackoverflow.com/questions/24395469/can-we-prove-correctness-of-algorithms-using-loop-invariants-in-which-we-prove-t