“循环可以跑一百万轮,但证明不必抄写一百万次状态变换。循环不变式是每次回到同一控制点时仍成立的摘要;保持义务把所有可能的一轮压缩成一个通用步骤。它像在螺旋楼梯每层同一位置设置检查门:只要入口过…”
形式陈述 ​
考虑循环 while B do C,其中
- **初始化:**进入第一次条件判断前,
成立; - **保持:**从任意满足
的状态执行一次 ,若该次执行正常终止,则得到的状态仍满足 ,即
这两项决定
因此恒真命题可以是合法的不变式,却通常不足以推出有意义的结果。若要证明总正确性,还需给出良基变式量或其他终止论证,排除循环永远执行的可能。
直觉
循环不变式是每个迭代边界都为真的状态摘要。它把“循环可能执行任意多轮”压缩成一次归纳:先证明起点成立,再证明任意一轮都保持。一个有证明价值的不变式通常同时描述已经处理的部分、尚未处理的部分,以及二者之间仍保持的关系。太弱的不变式虽然为真,却无法在退出时推出目标;太强的断言则可能根本无法初始化或保持。它不是对最终结果的愿望,而是每条循环路径执行后都必须重新建立的事实。
例子与边界
插入排序外层第
“数组最终会有序”不是有效不变式,因为循环中未必成立。只证明保持而忘记终止也不能得到总正确性;若循环可能无限执行,不变式最多证明部分正确性。修改多个变量时必须检查所有会回到循环头的分支,包括 continue;若异常直接离开循环,则应另行证明异常后置条件,只有被循环体捕获并继续迭代的异常路径才必须重建
推论与应用
循环不变式用于排序、图遍历、动态规划和数据结构操作的正确性证明。
它是 算法正确性 的基本证明工具,其初始化与保持正是一种 数学归纳法。更一般的归纳不变式把循环头看作状态集合上的切点:初始化对应初始状态纳入集合,保持对应循环回边下封闭;这一区分也解释了为何所有可达状态都满足的真性质,未必已经是可直接归纳证明的不变式。二分搜索的候选区间、图遍历的已访问集合和流算法的可行性都可写成不变式;在程序逻辑中,Hoare 三元组的 while 规则把“初始化、保持、退出推出后置条件”明确拆成独立验证义务,SMT 验证可以求解生成的逻辑条件,却不会替代不变式的语义选择。
高级动态结构常需跨多次公开操作的不变量。去摊还化在迁移期同时维护新旧版本与复制进度;Link–Cut Tree区分 represented forest 和 auxiliary splay,并在 access 后恢复 preferred-path 表示;Buffer Tree允许更新暂存在缓冲区,却保证批量下推后查询语义。它们说明不变量不只写在单个 for 循环顶部,还可覆盖后台队列、延迟工作和多层表示;终止/发布点仍须单独证明。
参考资料
- Thomas H. Cormen et al., Introduction to Algorithms, 4th ed., MIT Press, 2022, §2.1.
- C. A. R. Hoare, “An Axiomatic Basis for Computer Programming,” 1969.