我们能否使用循环不变量证明算法的正确性,我们在第一次迭代之后而不是之前证明它是真的?

时间:2014-06-24 20:14:40

标签: algorithm clrs loop-invariant

CLRS说

  

我们必须展示关于循环不变量的三件事:

     
      
  • 初始化:在循环的第一次迭代之前确实如此。
  •   
  • 维护:如果在循环迭代之前为真,则在下一次迭代之前保持为真。
  •   
  • 终止:当循环终止时,不变量为我们提供了一个有用的属性,可以帮助证明算法是正确的。
  •   

我的问题是我可以编辑这些步骤并将其改为:

  • 初始化:循环的第一次迭代后确实如此。
  • 维护:如果在循环迭代后为真,则在下一次迭代后仍然为真。
  • 终止:当循环终止时,不变量为我们提供了一个有用的属性,可以帮助证明算法是正确的。

说明:基本上我们使用数学归纳原理来证明正确性。使用"初始化"我们证明该属性在第一次迭代后保持不变。使用"维护"我们可以证明该属性适用于所有迭代,因为"初始化"和"维护"一起创造一个链。因此,该属性也在最后一次迭代后保留。

示例:

RANDOMIZE-IN-PLACE(A) 
1 n ← length[A] 
2 for i ← to n
3 do swap A[i] ↔ A[RANDOM(i, n)]

对于这个算法,已经在教科书中使用标准程序给出了证据(我没有在这里包括它,因为它太长了)。

我的建议:

  • 循环不变:在第2-3行的for循环的i th 迭代之后,对于每个可能的(i)-permutation,子数组A [1 .. i]包含这个(i) - 概率的概率(n - i)!/ n!。
  • 初始化:在1 st 迭代之后A [1]包含这种置换概率(n-1)!/ n!= 1 / n,这是真的。< / LI>
  • 维护:在(i-1) th 迭代后让它成立。在(i) th 迭代之后,A [1 ... i]包含概率[(n-i + 1)!/ n!] * [1 /(n-i + 1)的这种置换)] =(NI)!/ N!这就是我们想要的。
  • 终止:终止时,i = n,我们认为子阵A [1 .. n]是给定的n-置换概率(n - n)!/ n! = 1 / n!因此,RANDOMIZE-IN-PLACE产生均匀的随机排列。

我的解释在逻辑上是否合理?

非常感谢任何帮助。感谢。

1 个答案:

答案 0 :(得分:0)

除了事实之外,你必须做一个额外的步骤,它涵盖了从不运行的循环,你当然也可以证明在第一次迭代后不变量是真的,而不是证明它在真正的之前是真的。第一次迭代。

但我怀疑这通常会有多大意义

  • 首先,如前所述,您已经有一个特殊情况(如果完全没有执行循环会发生什么),这可能会导致您想要首先跳过的证明,类似于初始化
  • 其次,第一次迭代后不变量为真的证明很可能与Maintanance证明非常相似,因此您可能会编写两个非常相似的证明,只是为了跳过初始化,这可能是非常容易证明。

<强>类比

虽然这没有直接关系,但这个问题听起来很像试图优化以下(伪)代码:

int product(int[] values)
    product = 1
    for i = 0 to values.size - 1
        product *= values[i]
    return product

对此:

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

只是,您现在必须包含额外的检查,values数组是否为空(我在上面的代码中没有)