Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 我们能用循环不变量证明算法的正确性吗?在循环不变量中,我们在第一次迭代之后而不是之前证明算法是正确的?_Algorithm_Clrs_Loop Invariant - Fatal编程技术网

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

Algorithm 我们能用循环不变量证明算法的正确性吗?在循环不变量中,我们在第一次迭代之后而不是之前证明算法是正确的?,algorithm,clrs,loop-invariant,Algorithm,Clrs,Loop Invariant,CLRS说 我们必须展示循环不变量的三个方面: 初始化:在循环的第一次迭代之前为真 维护:如果在循环迭代前为真,则在下一次迭代前仍为真 终止:当循环终止时,不变量为我们提供了一个有用的属性,有助于证明算法是正确的 我的问题是,我是否可以编辑这些步骤并将其改为: 初始化:循环第一次迭代后为真 维护:如果循环迭代后为真,则下一次迭代后仍为真 终止:当循环终止时,不变量为我们提供了一个有用的属性,有助于证明算法是正确的 说明:基本上我们用数学归纳的原理来证明正确性。使用“初始化”,我们证明该属

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次迭代之后,对于每个可能的(i)置换,子数组A[1..i]包含此(i)置换,概率为(n-i)/n
  • 初始化:在第一次迭代后,A[1]以概率(n-1)包含此置换/n=1/n,这是真的
  • 维护:在第(i-1)次迭代后让它成为真。在第(i)次迭代之后,[1…i]以概率[(n-i+1)!/n!]*[1/(n-i+1)]=(n-i)/N这就是我们想要的
  • 终止:在终止时,i=n,我们得到子阵A[1..n]是一个给定的n-置换,概率为(n-n)/n!=1/n!。因此,随机化就地产生均匀的随机排列
我的解释合乎逻辑吗


任何帮助都将不胜感激。谢谢。

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

然而,我怀疑这是否有多大意义

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

类比

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

为此:

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

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

您必须在证明中添加一个额外的步骤:存在第一次迭代。(有些循环永远不会执行主体。)是的,你说得对,谢谢:)剩下的证据呢?剩下的证据在我看来没问题。我不知道为什么原来的公式对你不起作用。由于处理元素的子数组将是空的,初始化步骤将非常简单。我不确定如何使这些概率循环不变量工作。我不久前卖掉了我的CLR副本,所以我无法检查,但听起来有点可疑。
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