操作系统形式化验证实践教程(1) - 证明第一个定理

形式化方法分为三个主要部分:系统建模(System Modeling)、形式规约(Formal Specification)和形式化验证(Formal Verification)。
其中系统建模用形式化的模型来描述系统及其行为模式。建模完成后,需要用形式规约来精确描述建模出来的需求。有了规约,如何检验是否符合规约呢?这就需要形式化验证方法。

形式化验证方法主要分为两类:一类是以穷尽搜索为基础的模型检测,另一类是以逻辑推理为基础的演绎逻辑。相对于前者,后者既可以验证有穷的状态系统,也可以使用归纳法来处理无限状态的问题。

演绎逻辑在早期发展很快,但是后来在大规模软件验证上成本较高,所以发展一直不快。但是,最近十几年,以seL4为代表的操作系统和CompCert为代表的编译器的正确性证明的完成,给形式化验证带来了重要的突破性进展。
这也带来了两大流派:seL4所使用的Isabelle/HOL工具和CompCert所使用的Coq工具。
Isabelle是基于Standard ML语言开发的,支持生成Standard ML, ocaml, Haskell和Scala语言的代码。而Coq是基于ocaml语言的。

波澜壮阔的操作系统级的验证全景,我们后面会徐徐展开。做为一个落地的教程,我们千里之行始于足下,先从Isabelle/HOL工具的使用开始说起。

Isabelle/HOL简介

Isabelle/HOL可以通过下面的网址下载和安装:https://www.cl.cam.ac.uk/research/hvg/Isabelle/installation.html。支持Linux/mac/Windows平台。

HOL是High Order Logic,即高阶逻辑的缩写。

废话不多说,Isabelle封装在jEdit中,有完整的集成开发环境。我们安装好了之后直接打开看一眼:

有几点不跟普通编程语言的不同之处:

  • HOL的代码以theory组织在一起
  • theory之下有函数fun,值value, 有公式lemma, theorem等
  • 当我们把光标放到lemma或theorem中时,发现系统可以自动帮我们做一些推理的验证
  • HOL代码中大量使用非ASCII符号,可能给用惯了ASCII字符的程序员们带来一定的不适应,但是可读性绝对比用ASCII表示要上一个层次

自动证明第一个定理

同其它编程语言类似,HOL也有自己的数据类型系统。我们先从最简单的布尔类型开始。

HOL支持bool来表示布尔类型。用True表示真值,False表示假值。
取反为¬\lnot¬, 取交为∧\land∧,取并为∨\lor∨。

下面我们写一个求布尔交的函数。
交函数的输入为两个bool,输出也是一个bool.
我们用"bool ⇒ bool ⇒ bool"来描述这个函数的类型。
“⇒”的输入方法是用TeX值:<\Rightarrow>.
HOL语句要用字符串符号""来括起来,原理我们后面再讲。
代码逻辑上,除了输入为True和True返回True之外,其它都返回False:

fun conj2 :: "bool ⇒ bool ⇒ bool" where
"conj2 True True = True"|
"conj2 _ _ = False"

下面高光时刻来了,我们来用Isabelle/HOL证明我们学习之旅中的第一个定理False与另一个布尔值取conj2操作,结果一定为False。

lemma conj_02: "conj2 False m = False"apply(induction m)apply(auto)done

apply(induction m)和apply(auto)的作用是让HOL自动帮我们推断证明。
把光标放到apply(auto)语句,我们从output窗口看到:

proof (prove)
goal (2 subgoals):1. conj2 False True = False2. conj2 False False = False

如图所示:

趁热打铁,我们再写一个练习下:

fun not2 :: "bool ⇒ bool" where
"not2 True = False" |
"not2 False = True"
lemma not02 : "not2 x = (¬ x)"apply(induction x)apply(auto)done

从有限到无限

恭喜大家,已经学会证明有限情况下的定理证明了。但是这还不够,我们还要能证明无限的情况。
下面我们就从有限的布尔类型,前进到自然数类型nat和整数类型int.

自然数的定义带着浓浓的数学归纳法的味道。这里用到了求后继函数Suc:自然数nat = 0 或 Suc nat。也就是说,自然数定义为0,Suc(0), Suc(Suc(0))…

有了这个定义,我们可以重新定义一个加法了:

fun add2 ::"nat ⇒ nat ⇒nat" where
"add2 0 n = n" |
"add2 (Suc m) n = Suc(add2 m n)"

首先是0和n进行add2等于n,然后是m的后继与n进行add2操作,等于m与n进行add2操作后再求后继。

这么说有点抽象,我们来看例子。

第一个例子:add2 0 1,根据定义,这个就等于1。这个容易理解。
第二个例子:add2 1 2。1是Suc 0,于是这个式子为Suc(add2 0 2),add2 0 2根据第一条定义式结果为2。
第三个例子:add2 2 3。2是Suc 1,于是式子为Suc(add2 1 3),再递推为Suc(Suc(add2 0 3),结果为5.

这样,通过这样一种递推关系,我们重新定义了加法。

那么,这个我们新定义的加法,归纳出来的加法,跟真实的加法是不是一致呢?我们写个定理去进行自动证明:

lemma add_02: "add2 m n = m+n"apply(induction m)apply(auto)done

下面是证明的结果:

proof (prove)
goal (2 subgoals):1. add2 0 n = 0 + n2. ⋀m. add2 m n = m + n ⟹ add2 (Suc m) n = Suc m + n

根据两个初始条件,有两个子目标需要证明:
第一个是初始条件,add2 0 n = 0+n。
第二个是基于后继的递推条件。

皮亚诺公理

上面的证明方法叫做归纳原理,也叫做皮亚诺第五公理。
我们来从头看下这5条公理:

  1. 0是一个自然数
  2. 任何自然数n都有一个自然数Suc(n)作为它的后继
  3. 0不是任何自然数的后继
  4. 后继函数是单一的,即,如果Suc(m)=Suc(n),则m=n.
  5. 令Q为关于自然数的一个性质。如果
  • 0具有性质Q
  • 并且 如果自然数n具有性质Q,则Suc(n)也具有性质Q
  • 那么所有自然数n都有性质Q

在此基础上,我们可以定义加法和乘法。

  • 加法:对于任何自然数n和m:

    • n + 0 = n
    • 并且 n + Suc(m) = Suc(n + m)
  • 乘法:对任何自然数n和m:
    • n * 0 = 0
    • n * Suc(m) = (n * m) + n

乘法的定理证明如下:

fun mul2 ::"nat ⇒ nat ⇒nat" where
"mul2 0 n = 0" |
"mul2 (Suc m) n = n * m + n"lemma add_02: "mul2 m n = m * n"apply(induction m)apply(auto)done

求值

在过程中,难免有些值我们希望看到输出结果,这时可以通过value语句来实现。

例:

value "Suc(0)"

输出结果为:

"1":: "nat"

1为结果的值,nat是类型。

调用我们自己定义的函数也没有问题:

value "add2 1 (Suc 4)"

输出结果为:

"6":: "nat"

恭喜你,我们已经在定理证明的世界里证明了第一个定理。
后面的路很长,坡也有点陡,我们继续前进。

操作系统形式化验证实践教程(1) - 证明第一个定理相关推荐

  1. 操作系统形式化验证实践教程(11) - 结构化证明语言Isar(转载)

    操作系统形式化验证实践教程(11) - 结构化证明语言Isar 结构化证明语言Isar基本语法 apply方法和by方法虽然可以完成功能,但是看起来更像是命令式语言.使用Isar语言,还可以写得更加形 ...

  2. 操作系统形式化验证实践教程(11) - 结构化证明语言Isar

    操作系统形式化验证实践教程(11) - 结构化证明语言Isar 结构化证明语言Isar基本语法 apply方法和by方法虽然可以完成功能,但是看起来更像是命令式语言.使用Isar语言,还可以写得更加形 ...

  3. 操作系统形式化验证实践教程(7) - C代码的自动验证

    操作系统形式化验证实践教程(7) - C代码的自动验证 上一节教程不知道大家看晕了没有,其实虽然细节很多还没有讲清楚,但是从结构上大家可以看到,其实是很模式化的工作. 那么能不能让这个模式化的工作自动 ...

  4. 操作系统形式化验证实践教程(7) - C代码的自动验证(转载)

    操作系统形式化验证实践教程(7) - C代码的自动验证 上一节教程不知道大家看晕了没有,其实虽然细节很多还没有讲清楚,但是从结构上大家可以看到,其实是很模式化的工作. 那么能不能让这个模式化的工作自动 ...

  5. 操作系统形式化验证实践教程(10) - 一阶直觉逻辑

    操作系统形式化验证实践教程(10) - 一阶直觉逻辑 前面我们用了九讲的篇幅把seL4验证操作系统的地图给大家迅速过了一遍,基础好的同学已经可以基于前面的知识开始自己的工作了. 对于只学过离散数学,而 ...

  6. linux内核形式化验证,聪明人的笨功夫 -- MesaTEE安全形式化验证实践

    各类TEE(例如TPM和Intel SGX)提供了强大的可信计算硬件基础,但他们并不直接保证软件的安全性.诸如缓冲区溢出等内存安全问题为攻击者提供了侵入TEE的可乘之机.因此,软件内存安全保护极其重要 ...

  7. 大学计算机实践教程在线阅读,第一部分 实验免费阅读_大学计算机基础实践教程免费全文_百度阅读...

    第2章 Windows 7操作系统基础实验 实验一 Windows 7的启动和退出 一.实验目的: 掌握Windows 7操作系统的启动和退出操作. 二.实验内容: 1.Windows 7的启动. ( ...

  8. 第一不完全性定理证明标号分类 拆解汉译 知识背景——哥德尔原著英译拆解汉译之一

    第一不完全性定理证明标号分类 拆解汉译 知识背景--哥德尔原著英译拆解汉译之一 哥德尔原著中的第一不完全性定理证明的全过程,已经艰难地旅行了一趟.不是浮光掠影,却依然处在似懂非懂之中.静坐沉思,常自叹 ...

  9. 零知识证明实践教程,第一部分

    本文和其他博客文章的区别: 现今存在很多讲解零知识证明的文章,但是它们都是只涉及到很浅层的概念理解和直观感受上面,没有深入到零知识证明的细节,导致读者只知道什么是零知识证明,而不清楚怎么构造一个零知识 ...

  10. 零知识证明实践教程,第三部分

    本文是零知识证明简单实践教程的第三部分, 第一部分见:零知识证明第一部分, 第二部分见:零知识证明第二部分. 下面这个图片是我们在第二部分所使用的merkle树来构造prover的承诺.同时我们也提出 ...

最新文章

  1. python 正则表达式方法_Python正则表达式一: 基本使用方法
  2. c#获取应用程序目录
  3. 【数据库】数据库常见操作指令
  4. [问题已处理]-[jenkins]-Jenkins 反向代理有误
  5. android 获取phone实例,Android ContentProvider获取手机联系人实例
  6. 【Java】存储单元的设计与模拟
  7. RabbitMQ学习之集群镜像模式配置
  8. 京东集团副总裁王楠:数智化是打造国际消费中心城市的必由之路
  9. 易天40G QSFP+光模块的规格参数
  10. itest听力答案2020_itest答案.doc
  11. 学编程脚本 android,Android开发之--脚本编程
  12. 文件系统 - 文件类型 - 二进制/文本类型
  13. android端使用百度地图
  14. 理论篇:关注点分离(Separation of concerns, SoC)
  15. android 屏幕截图检测,Android 屏幕截图
  16. java 版本区别,java SE是什么,下载JDK时各个名称的含义
  17. 如何通过看电影学英语来源
  18. R语言作图——Pie chart(饼图)
  19. flex布局自动换行并解决最后一行对齐
  20. 简单实用的jQuery分页插件twbs-pagination

热门文章

  1. Highcharts 隐藏右下角的官网链接
  2. TOGAF 企业连续系列
  3. java网络通信技术示例:简单的聊天小程序
  4. Mysql个人学习笔记
  5. 汉王数据导入java环境,怎样把u盆内容导入汉王门禁考勤管理软件
  6. Vue使用Monaco Editor实现diff代码对比功能
  7. 发布javaweb网站教程(简单易懂)
  8. 用php照片艺术化,不满足简单修图?这些应用能让照片充满艺术感
  9. 深入解析互联网协议的原理
  10. 推荐一款在线文件对比工具