循环不变量
概述
循环不变量(Loop Invariant)是在循环的每次迭代前后都保持为真的断言。它是证明循环程序正确性的核心工具,需要满足三个条件:初始化(initiation)——循环前为真;保持(maintenance)——若迭代前为真则迭代后仍为真;终止(termination)——循环终止时结合不变量可推出期望结果。
定义
循环不变量的三个条件
设 为循环
while $B$ do $S$的候选循环不变量。 必须同时满足以下三个条件:条件一:初始化(Initiation)
在循环开始执行前(即第一次测试循环条件之前), 为真。
条件二:保持(Maintenance)
若某次迭代开始时 为真且循环条件 为真,则该次迭代执行 后 仍然为真。
即: 是循环体的不变量——执行循环体不会破坏 的真值。
条件三:终止(Termination)
若循环终止(即 变为假),则结合 和 可以推出期望的终结断言 。
这三个条件共同保证了:若循环前 为真,则循环终止后 为真(部分正确性)。
循环不变量与数学归纳法的关系
循环不变量的三个条件与数学归纳法(Mathematical Induction)存在精确的对应关系:
循环不变量条件 数学归纳法对应 含义 初始化 基础步(Base Case) 证明循环开始前 为真,对应 为真 保持 归纳步(Inductive Step) 假设第 次迭代前 为真,证明第 次迭代前 仍为真 终止 归纳结论的应用 循环结束时,由不变量 和终止条件 推出结果 这种对应关系不是巧合——循环本质上是对归纳过程的计算展开。每次循环迭代对应归纳中的一步递推,不变量就是那个”对所有 都成立”的命题 。
因此,掌握 数学归纳法 是理解和使用循环不变量的前提。
应用示例
示例 1:求最大值程序
max := a[1] i := 2 while i ≤ n do if a[i] > max then max := a[i] i := i + 1循环不变量:
max等于 中的最大值。
- 初始化: 时,
max,确实是 到 的最大值。✓- 保持:若
max是 到 的最大值,则执行循环体后max是 到 的最大值,且 增 1。✓- 终止:循环终止时 ,不变量给出
max是 到 的最大值。✓示例 2:线性搜索程序
i := 1 while (i ≤ n) ∧ (x ≠ a[i]) do i := i + 1循环不变量: 不在 中。
- 初始化: 时, 到 为空集, 不在空集中。✓
- 保持:若 不在 到 中,且 ,则 不在 到 中, 增 1 后不变量保持。✓
- 终止:循环终止时,要么 ( 不在数组中),要么 (找到了 )。✓
示例 3:整数除法程序
q := 0; r := a while r ≥ b do r := r - b q := q + 1循环不变量: 且 。
- 初始化: 时,,且 (假设 )。✓
- 保持:若 且 ,则 ,有 。✓
- 终止:循环终止时 ,结合 ,得 为商、 为余数。✓
核心性质
| 性质 | 描述 | 说明 |
|---|---|---|
| 归纳对应 | 初始化=基础步,保持=归纳步 | 循环不变量证明本质上是归纳法 |
| 非唯一性 | 同一循环可能有多个有效不变量 | 选择”足够强”的不变量是关键 |
| 不蕴含终止 | 不变量保持不保证循环终止 | 终止性需要单独证明(如度量函数递减) |
| 后向构造 | 通常从期望结果反推不变量 | 结合终止条件和后条件 构造 |
| 强化策略 | 不变量可能需要比直觉更强的断言 | 弱不变量无法在终止时推出 |
| 循环体依赖 | 不变量必须对循环体的每条路径都保持 | 条件分支中的所有路径都需验证 |
关系网络
graph TB A["循环不变量"] --> B["三个条件"] A --> C["应用场景"] B --> B1["初始化 Initiation<br/>循环前为真"] B --> B2["保持 Maintenance<br/>迭代后仍为真"] B --> B3["终止 Termination<br/>推出期望结果"] C --> C1["求最大值程序"] C --> C2["线性搜索程序"] C --> C3["整数除法程序"] A -.-> D["程序正确性<br/>循环不变量的应用领域"] A -.-> E["Hoare三元组<br/>循环规则的要素"] A -.-> F["数学归纳法<br/>理论基础"] D --- A E --- A F --- A
- 应用领域:程序正确性 使用循环不变量作为证明循环程序正确性的核心工具
- 形式化框架:Hoare三元组 的循环规则中,循环不变量是必须找到的关键断言
- 理论基础:数学归纳法 提供了循环不变量三条件的数学基础
章节扩展
第5章 — 5.5节内容
循环不变量是 Rosen 第5章 5.5 节中程序验证部分的核心概念:
- 循环不变量的定义:三个条件(初始化、保持、终止)的精确表述
- 与数学归纳法的对应:初始化对应基础步,保持对应归纳步
- 构造策略:如何从期望结果反推合适的循环不变量
- 典型应用:求最大值、线性搜索、整数除法等程序的验证
- 终止性证明:使用度量函数(如循环计数器递减)证明循环终止
- 常见陷阱:不变量过弱(无法推出结果)、不变量过强(无法证明保持性)
循环不变量是连接离散数学(归纳法)与计算机科学(程序验证)的桥梁概念。
补充
学术背景
循环不变量的概念最早由 Floyd(1967) 在 “Assigning Meanings to Programs” 中以归纳断言(inductive assertion)的形式提出。Floyd 的方法是在程序控制流图的边上标注断言,其中循环处的断言就是循环不变量。
Dijkstra 在其 1976 年的名著 “A Discipline of Programming” 中进一步发展了循环不变量理论,并提出了卫式命令(guarded commands)语言。Dijkstra 强调:程序的正确性应该在编写程序的同时就建立,而不是事后验证。他提倡”先写不变量,再写循环”的程序设计方法论。
在实践中,循环不变量不仅是形式化验证的工具,也是算法设计和程序构造的思维工具。优秀的程序员在编写循环时,往往会在心中(或注释中)明确循环不变量,以此指导代码的正确实现。
来源:
- Rosen, K. H. Discrete Mathematics and Its Applications, 8th ed., Section 5.5
- Floyd, R. W. (1967). “Assigning Meanings to Programs.” Mathematical Aspects of Computer Science, 19, 19-32.
- Dijkstra, E. W. (1976). A Discipline of Programming. Prentice-Hall.