在这种平方根边界查找算法中,如何获得循环不变性?


10

最初在math.SE上,但在那里没有答案。

考虑以下算法。

u := 0
v := n+1;
while ( (u + 1) is not equal to v) do
   x :=  (u + v) / 2;
   if ( x * x <= n) 
     u := x;
   else
     v := x;
   end_if
end_while 

其中u,v和n是整数,除法运算是整数除法。

  • 解释算法计算的结果。
  • 使用您对第一部分的回答作为算法的后置条件,建立循环不变式,并证明算法终止且正确。

在类中,后置条件被发现是和不变是0 ü 2Ñ < v 2Ü + 1 v。对于后置条件和不变式是如何获得的,我真的不太了解。我认为发布条件是u + 1 = v0u2n<(u+1)20u2n<v2,u+1vu+1=v...显然不是这样。所以我想知道如何获得后置条件和不变式。我也想知道如何通过使用后置条件来获得前置条件。


您是否熟悉Hoare逻辑,您是否希望得到一个答案?
拉斐尔

Answers:


8

吉尔斯(Gilles)是对的,因为一般的技术是去钓鱼以进行有趣的观察。

在这种情况下,您可能会发现该程序是二进制搜索的实例,因为它具有以下形状:

while i + 1 != k
  j := strictly_between(i, k)
  if f(j) <= X then i := j
  if f(j) > X then k := j

然后,您只需将特定的f,,X...插入到用于二进制搜索的一般不变式中。Dijkstra 对二进制搜索进行了很好的讨论


7

确实是while循环的后置条件(为什么您认为“显然”不是这种情况?)。while循环不包含a的情况总是如此:退出循环时,只能是因为循环条件(此处 u + 1 v)为假。当循环在这里退出时,并不是唯一的事情(如您在类中所见,该算法实际上计算出一些有趣的东西,因此 u = [这个有趣的事情] v = [这个有趣的事情]也是后置条件),但这是最明显的。ü+1个=vbreakü+1个vü=[这个有趣的东西]v=[这个有趣的东西]

现在,要找到其他有趣的属性,没有通用的配方。实际上,从某种形式上讲,没有通用的公式可以找到循环不变式。您能做的最好的事情就是应用一些仅在某些情况下有效的技术,或者通常是去钓鱼以获得有趣的观察结果(随着经验的积累,这种方法会越来越好)。

如果循环运行一些具有值的迭代,则每次迭代都会看到:ñ

  • 要么跳起来û + v / 2 ;üü+v/2
  • 跳至u + v / 2vü+v/2

特别地,小于v,并且永远不会超过v。此外,ü开始正和增大,而v开始于Ñ + 1和减小。所以,0 ü v ñ + 1是整个计划不变。üvüvñ+1个0üvñ+1个

不太明显的一件事是是否等于v。这很重要:如果uv变得相等,我们将得到x = u = v,循环将永远继续下去。因此,为了证明算法正确(即不会永远循环),需要证明uv永远不会相等。一旦确定了这种需求,就很容易证明(我将其保留为练习)u < v是循环不变式(请记住,uv是整数,因此等效于uüvüvX=ü=vüvü<vüv)。ü+1个v

由于在节目的结束,则分别获得了后置条件也可以被写ü 2Ñ < v 2(部分0 Ü 2是微不足道的)。我们想要一个涉及n的后置条件的原因是,我们希望将程序的结果与输入n绑定在一起。为什么要这样精确的条件?我们正在寻找尽可能精确的东西,并查看n在循环中出现的位置:v=ü+1个ü2ñ<v20ü2ñññ

  • 我们有 ;üXv
  • X2ñüXü2ñv不变);
  • X2>ñvXñ<v2ü不变)。

ü2ñ<v2所有的时间。换句话说,我们怀疑这是一个循环不变式。验证这是读者的一项练习(请记住,一开始要检查该属性是否正确)。

ü2ñü+1个2>ñüñ


“因此,您需要证明u和v相等才能证明算法正确”。我认为这句话缺少“ not”。
sepp2k 2012年

@KenLi既然这是您在Stack Exchange方面的问题,那么您是否需要任何特别的改进?
吉尔(Gilles)'“ SO-不要邪恶”
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.