从相关程序到反例与归纳证书
本练习把三种证据接起来:依赖闭包说明为何可以缩小程序;一份重放输入说明断言确实失败;初始、保持和目标义务说明某个转移系统所有可达状态都安全。每份证据回答不同问题,不能互相替代。
配套:Python复算脚本、一次完整输出。脚本只用标准库,运行 python foundations-program-evidence-checker.py 即打印JSON;显式检查在 python -O 下仍启用。它不是一般源语言解析器或SMT后端;程序以固定语法对象输入,路径求解明确枚举
任务一:给返回值建立完整相关性
模型是无循环结构化顺序程序,纯且总定义的数学整数表达式、每条读取有定义、无异常/堆/并发/I/O,唯一末尾返回。观察只包括返回值。
0 input x, y
1 a := x + 1
2 junk := y * y
3 r := 0
4 if x > 0:
5 if y == a:
6 r := 1
else:
7 r := 2
8 junk := junk + 1
9 return r
10 exit
- 列出4、5、6、7的反身后支配集合
- 从每条分支出边的后支配集合差发出控制边
- 列出所有定义到使用边,对9说明为何有三个
r来源 - 从9反向闭合,重建可执行切片;不能把互斥分支拼成顺序赋值
复算与检查点
四个后支配集合分别为 {4,8,9,10}、{5,8,9,10}、{6,8,9,10}、{7,8,9,10}。控制边恰为4→5(T)、5→6(T)、5→7(F)。数据边为0→1(x)、0→2(y)、0→4(x)、0→5(y)、1→5(a)、2→8(junk)、3→9(r)、6→9(r)、7→9(r)。
反向闭包保留 {0,1,3,4,5,6,7,9},删除2和8;余下if结构不变。有限域25组输入上原程序和切片返回值逐一一致;对全部数学整数输入的保证来自静态切片中的语义对应证明。
迁移:把8改成 r:=junk,重新构图。切片应保留0、2、8、9,返回
任务二:从符号路径生成可重放错误
回到原程序,检查规格“返回值不等于1”。
- 用
代表输入,手算a的符号值 - 列出全部终端路径条件及返回表达式
- 在
内数出各路径包含的输入数量 - 从具体种子
开始,采用最深未覆盖前缀优先、字典序首个模型,运行混合执行
复算与检查点
a=2,两个判断均真,6将 r 写为1。
混合执行依次运行
迁移一:把6改成 r:=a-y。真路径有
迁移二:原程序输入域缩成
任务三:把乐观候选变成归纳事实
给定
- 每轮采用同一当前合取,列出初始或保持失败见证
- 解释为什么候选删除后要重新检查其余候选
- 对最终合取分别检查初始化、一步保持和蕴涵
- 枚举32个候选子集,核验所有归纳子集均包含于最终保留集合
复算与检查点
先因初态0删除
迁移:新增2→3。接下来先删
任务四:分开base与任意状态窗口
另取
- 按k归纳页约定,base检查深度0到
,step检查 个安全前态后的一步错误 - 给出
的step反例,并判断它是否可达 - 证明
两个义务均通过 - 添加2→2,构造对任意
都失败的step窗口
复算与检查点
加入2→2后,对任意
迁移:将初态改成2。原图的
验收清单
- 每条边有类型、方向及正文中可复算的来源
- 切片准则包含观察位置和值,静态结论不借用单次轨迹
- 反例输入满足完整路径条件并在原程序重放
- 有限域枚举、无界语义证明和工具求解结果分别标注
- 候选最终集合经过初始化与保持,安全目标另行检查
- k归纳的base含I,step不含I;任意状态的失败不冒充可达错误
- 改变程序、初态或输入域后重新计算证据