Skip to content

循环不变式 Hoare 规则

Hoare while rule · Loop invariant rule

以初始化、一次迭代保持和退出蕴含,把任意多轮循环的部分正确性压缩为有限 Hoare 义务。

条目类型
定理

形式陈述

考虑命令 while B do C。若断言 I 满足

PI,{IB} C {I},I¬BQ,

则可在部分正确性语义下推出

{P} while B do C {Q}.

中间的 Hoare 三元组 要求每次循环体若终止,都会在下一次判断 guard 前重新建立 I。第一项把调用者状态带入不变式,第三项说明退出时不变式足以得到目标;三项缺一不可。省略外层 consequence 时,常见的核心规则把前置写成 I、后置写成 I¬B

可靠性证明按实际执行的迭代次数归纳。零轮执行时,初态满足 I 且 guard 为假;执行 k+1 轮时,先由保持义务得到下一循环头仍满足 I,再应用 k 轮归纳假设。这个证明只讨论有限终止轨迹,因此不会从不变式推出循环一定退出。

直觉

循环可以跑一百万轮,但证明不必抄写一百万次状态变换。循环不变式是每次回到同一控制点时仍成立的摘要;保持义务把所有可能的一轮压缩成一个通用步骤。它像在螺旋楼梯每层同一位置设置检查门:只要入口过关,而且从一扇门走到下一扇门总能恢复同一条件,就能覆盖任意有限层数。

有证明价值的不变式通常同时记录已处理部分、未处理部分与守恒量。恒真式容易初始化和保持,却往往无法在退出时推出任何有用结论;把最终后置原样当不变式又常常太强,在第一轮之前便不成立。规则把“是真的”和“足够强”分成可定位的义务。

不变式中的每个合取项承担不同角色。一个合取项可能负责防止数组越界,另一个记录结果的代数含义;保持证明要恢复全部合取,退出证明却可能只使用其中一部分。删除“看似辅助”的界限条件,有时仍能通过代数保持,却使退出状态无法被收紧到目标。

例子与边界

在数学整数上计算前 n 个正整数之和:

text
i := 0
s := 0
while i < n do
    i := i + 1
    s := s + i

前置为 n0,取不变式

I0in2s=i(i+1).

初始化后 i=s=0,两部分都成立。保持时设旧值为 i,s;guard 给 i+1n,而两条赋值后的值为 i=i+1s=s+i+1,于是

2s=i(i+1)+2i+2=(i+1)(i+2)=i(i+1).

退出时 inin 合得 i=n,从而 2s=n(n+1)。每一步都可复算,没有把目标公式当作“显然保持”。

若只保留 2s=i(i+1) 而删除 in,初始化和代数保持仍成立,但退出只给 in,规则本身不能推出 i=n。若把 body 顺序改成先 s:=s+i、再 i:=i+1,新值满足 2s=i(i+1)+2i=i(i+3),也不再等于 (i+1)(i+2);保持义务会精确捕获这次 off-by-one 改动。

不变式只要求在循环头成立;两条赋值之间代数关系可以暂时失效。带 continue 的程序必须在每条回边恢复 Ibreak 和异常则需要各自的退出后置。若把更新写成 i := i,三项部分正确性义务仍可能成立,但循环在 i<n 时永不终止,说明这条规则没有隐藏的进展承诺。

推论与应用

循环规则把无限展开变成初始化、保持和退出三类 验证条件,因此是自动验证器处理用户注解的核心接口。求解器能够检查给定不变式,却不会自动保证候选足够强;抽象解释、插值和模板合成产生的候选仍须回到这三项语义义务接受检验。

若要总正确性,还需在 IB 下给出落在良基集合中的变式,并证明每次循环体都终止且严格下降。数组边界、整数溢出和异常路径也必须反映在断言语言里。数学整数上的保持证明不能直接搬到会回绕的机器整数上,否则看似下降的计数器可能从最小值跳回最大值。

嵌套循环可以在内层使用依赖外层索引的不变式,再在外层把内层完整规格当作一条命令使用。直接把两个循环的所有控制点揉成一个巨型断言并非更强;分层规则能让每个不变式只承担自己循环头的事实,同时通过顺序规则传递中间后置。

参考资料
  • C. A. R. Hoare, “An Axiomatic Basis for Computer Programming,” Communications of the ACM 12(10), 1969, pp. 576–580, 583。
  • Robert W. Floyd, “Assigning Meanings to Programs,” in Mathematical Aspects of Computer Science, AMS, 1967, pp. 19–32。
  • Glynn Winskel, The Formal Semantics of Programming Languages, MIT Press, 1993, Ch. 7。
  • Krzysztof R. Apt, Frank S. de Boer, and Ernst-Rüdiger Olderog, Verification of Sequential and Concurrent Programs, 3rd ed., Springer, 2009, Chs. 3–4。
关系图谱9 个相邻概念 · 2 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组
类型化关系

被这些条目使用