名称: hoare-logic-verifier 描述: ‘使用Hoare逻辑验证程序。当需要:(1) 证明程序正确性,(2) 设计验证软件,(3) 验证循环不变量时使用。’ 版本: 1.0.0 标签:
- 验证
- hoare-logic
- 程序证明
- 正确性 难度: 中级 语言:
- python
- coq
- why3 依赖项:
- operational-semantics-definer
Hoare逻辑验证器
使用Floyd-Hoare逻辑验证程序正确性。
何时使用
- 证明程序正确性
- 开发验证软件
- 验证循环不变量
- 静态验证
该技能的作用
- 指定合约 - 前后条件和循环不变量
- 生成验证条件 - 需要证明的公式
- 检查健全性 - 证明验证条件有效
- 处理循环 - 不变量推断
关键概念
| 概念 | 描述 |
|---|---|
| 前条件 | 执行前的状态 |
| 后条件 | 执行后的状态 |
| 不变量 | 每次循环迭代前后为真 |
| 最弱前条件 | 确保后条件的最小条件 |
| 验证条件 | 用于证明正确性的公式 |
验证条件生成
{P} while b do c {Q}
验证条件:
1. P ⇒ I (初始化)
2. I ∧ b ⇒ wp(c, I) (保持)
3. I ∧ ¬b ⇒ Q (有用性)
提示
- 从简单程序开始,逐步增加复杂度
- 首先手动验证循环不变量
- 使用后果来加强或弱化条件
- 对复杂条件考虑使用SMT求解器
- 小心处理除法(非零)
常见模式
交换
{ x = a ∧ y = b }
t := x;
x := y;
y := t;
{ x = b ∧ y = a }
线性搜索
{ ∃i. A[i] = k ∧ 0 ≤ i < n }
i := 0;
while i < n do
if A[i] = k then break;
i := i + 1
{ (i < n ⇒ A[i] = k) ∧ (i = n ⇒ ∀j. 0≤j<n ⇒ A[j] ≠ k) }
相关技能
separation-logician- 堆验证invariant-generator- 自动不变量推断loop-termination-prover- 证明终止
经典参考文献
| 参考文献 | 为何重要 |
|---|---|
| Hoare, “计算机程序设计的公理基础” (CACM 1969) | 原始Hoare逻辑论文(图灵奖) |
| Apt & Olderog, “程序验证” (1981) | 全面综述 |
| Floyd, “为程序赋予意义” (1967) | Hoare逻辑的前身 |
| Nielson & Nielson, “Hoare逻辑” (1999) | 形式化处理 |
| Gupta等人, “C程序设计的实用指南” (1991) | 可验证的C编码 |
权衡与限制
方法权衡
| 方法 | 优点 | 缺点 |
|---|---|---|
| 标准Hoare | 简单直观 | 无法处理堆/指针 |
| 分离逻辑 | 处理指针、堆 | 更复杂 |
| 动态逻辑 | 循环作为公式 | 更难使用 |
何时不使用Hoare逻辑
- 并发程序:使用并发分离逻辑
- 指针密集代码:使用分离逻辑替代
- 自动化验证:考虑模型检查
- 大型代码库:考虑符号执行+测试
复杂度考虑
- 验证条件生成:程序大小的O(n)
- SMT求解:对复杂公式昂贵;一般不可判定
- 不变量推断:一般NP困难
限制
- 循环不变量:必须手动提供(寻找不可判定)
- 框架问题:难以指定不变内容;使用分离逻辑
- 部分正确性:标准Hoare逻辑证明部分正确性(无终止)
- 可扩展性:手动证明努力随程序大小增长
- 并发性:需要扩展(并发分离逻辑)
研究工具与成果
基于Hoare逻辑的验证工具:
| 工具 | 语言 | 学习内容 |
|---|---|---|
| Dafny | C#/Boogie | 验证程序 |
| Verifiable C (VST) | Coq | C验证 |
| Frama-C | C | 静态分析 |
| Why3 | Why3 | 验证平台 |
| ESC/Java | Java | 扩展静态检查 |
| Spec# | C# | 基于合约的验证 |
交互式定理证明器
- Coq - 证明助手,用于C的VST
- Isabelle/HOL - 通用目的
- Lean - 功能验证
- Agda - 依赖类型
研究前沿
1. 验证条件生成
- 目标:自动化证明努力
- 方法:生成验证条件,用SMT消解
- 论文:“VCGen傻瓜指南”(多种)
- 工具:Boogie, Why3
2. 循环不变量推断
- 目标:自动发现不变量
- 方法:抽象解释、学习
- 论文:“不变量生成” (Sankaranarayanan)
- 工具:抽象解释工具
3. 分离逻辑
- 目标:处理堆和指针
- 方法:局部推理、框架规则
- 论文:“分离逻辑” (O’Hearn, Reynolds)
- 工具:Verifiable C, Smallfoot
4. 并发验证
- 目标:验证并发程序
- 方法:并发分离逻辑
- 论文:“并发分离逻辑” (O’Hearn)
- 工具:Verifast, Grain
实现陷阱
| 陷阱 | 实际后果 | 解决方案 |
|---|---|---|
| 错误不变量 | 不健全证明 | 验证每个验证条件 |
| 缺失框架 | 不完整规范 | 使用分离逻辑 |
| 除零错误 | 运行时错误 | 添加前条件 |
| 溢出 | 不健全性 | 使用有界整数 |
“循环不变量”挑战
寻找不变量不可判定:
# 什么不变量证明这个?
i = 0
sum = 0
while i < n:
sum = sum + i
i = i + 1
# 答案:sum = i*(i-1)/2
# 另一个有效不变量:0 <= i <= n AND sum >= 0
# 但这太弱,无法证明最终结果!
这就是为什么验证需要人类洞察力!