参考文献:
形式化方法是基于严格数学基础,对计算机硬件和软件系统进行描述、开发和验证的技术.其数学基础建立在形式语言、语义和推理证明三位一体的形式逻辑系统之上.
形式化方法已经成功应用于各种硬件设计,特别是芯片的设计.由于软件系统的复杂性和不确定性远远超出硬件系统,形式化方法在软件开发中应用程度并不高.
形式化方法是基于严格数学基础,对计算机软(硬)件系统进行形式规约、开发和验证的技术.
形式化方法与其他软件开发方法[4]的主要区别在于:其描述软件及其性质的语言是无歧义的,构造和验证软件的方法是严格的.
形式化方法的发展已有较长的历史,人们主要从两个角度出发推动形式化方法的提出和早期发展,即,为程序设计提供数学基础的理论研究角度以及为软件开发提供严格质量保证的软件工程角度.
形式语言是由符号化字母表以及递归的语法规则完全定义和生成所有表达式或语句的语言. 形式逻辑的语言都是形式语言,如命题逻辑、谓词逻辑和布尔代数.
直接使用程序设计语言及其语义难以描述和证明软件从需求文档到程序代码的开发过程各阶段创建的不同抽象层次的制品及其正确性,人们开始研究高层抽象的形式规约语言的设计,形成了以形式规约语言为基础的形式化开发方法.
建立了形式规约之后,如何从形式规约开发得到正确的系统成为关键.**形式验证,包括如何证明不同抽象层次的规约间等价或者满足精化关系、如何验证形式规约(所要求的性质)及其模型之间的满足关系,**是形式化方法保证软件开发正确性必须解决的科学问题和实际应用问题.
在研究验证自动化过程中,发现了相关大量的不可判定问题、NP 完全问题以及状态爆炸等否定性的结果.但相应的这些问题也不断的推动着各种规约技术的发展。工具的自动化水平和可扩展能力得到了显著的提高。形式验证在硬件验证中获得了巨大的成功,也不断地进入嵌入式软件、安全攸关软件等高安全等级软件的开发.
形式化方法在计算机软/硬件开发和质量保证上发挥了重要作用,与人工智能相结合的程序综合、大数据以及与形式推理相结合的软件自动化重回热点前沿.此外,形式化方法在网络安全、量子计算、生物计算等方向的交叉应用也受到了广泛关注.
形式化方法是由形式规约语言(包括形式语义与模型理论)、形式规约(包括精化与综合)、形式验证、形式化工具等形成的一个整体.
形式规约是由形式规约语言严格描述的系统模型或者系统需要满足的性质.前者是模型规约,后者是性质规约.
形式规约语言是指由严格的递归语法规则所定义的语言,满足语法规则的句子称为合式或良定义规约(well-formed specification).
模型规约语言利用数学结构描述系统的状态变化或者事件轨迹,它直接定义所描述系统模型的结构、功能行为甚至非功能行为(如时间).
模型规约给出了系统开发过程中不同抽象层次的模型,有相应的逻辑推理系统支持其分解和组合,完成不同层次间规约的转换和精化.主要包括如下几类。
代数规约语言:一个代数规约由一些表述类子(sort)的符号、类子之间的运算符(operation symbol)以及在多类等式逻辑(many-sorted equality logic)中的等式公理组成.代数规约的优点是具有非常好的数学基础,任意操作序列的计算结果可以自动得到、自动执行,
结构化规约语言:数据类型的规约和程序结构
进程代数(演算):为了设计开发并发和分布式系统,出现了 CCS[15]、CSP[13]、ACP[79]等进程代数(演算).CCS 和 CSP 都最大限度地将并发通信系统的数据状态和数据计算功能抽象掉,集中描述通信和同步以及二者之间的关系,是基于事件的规约语言.CCS 规约是一个 CCS 语法定义的表达式,语义是通过结构操作语义来定义表达式描述的通信进程的行为演化.这样定义的 CCS 表达式的状态迁移规则构成了推导 CCS 表达式之间各种等价关系的形式系统,这些等价关系可以表示成不同的互模拟(bisimulation)关系.
为了处理并发系统的其他特征,如信息安全、移动、实时、混成、概率和随机,这些并发模型均进行了各
种扩充.例如,为了处理实时系统,Reed和Roscoe扩充CSP到实时系统,建立了Timed CSP[23];为了处理混成系统,
何积丰和周巢尘等人将 CSP 扩充到混成系统,建立了混成 CSP。再如:为了处理移动计算,Milner 提出了mu-
演算,后被 Cardelli 和 Gordon进一步扩充为Ambient-calculus;为了处理信息安全,Abadi 等人将mu-演算改进
成 spi-演算;等等.Milner 试图使用范畴论统一这些并发计算模型,提出了 Bigraph 理论.
基于迁移系统的规约:**迁移系统可以自然地表示系统的行为.典型的基于迁移系统的规约语言有 Petri 网[12]和 Statecharts[87]等.**基于迁移系统的规约语言往往有图形化表示,称为可视化规约语言.
为了对非功能性需求建模,人们对标记迁移系统进行了各种扩充.以自动机为例,其后续扩展包括:时间自动机[21]、混成自动机[88]、概率时间自动机[89]、随机混成自动机[90],等等.而且这些模型不再局限于计算机领域,已经广泛应用于控制、生物、物理、化学等诸多领域.
性质规约语言基于程序逻辑系统,通过逻辑公式来描述一组性质以定义所期望的系统行为.
系统需要满足的性质可以分成两类[91]:安全性质,即不好的事情从不发生;活性,即好的事情一定能够发生.Alpern 和 Schneider 证明,任何性质均可以表示成这两种性质的交[92].
顺序程序设计早期的程序逻辑是 Floyd-Hoare 逻辑系统设计与验证学习笔记——霍尔逻辑(Floyd-Hoare Logic) - 知乎 (zhihu.com)
形式语义学起源于对程序设计语言语义的研究.使用数学结构来定义程序语言语义的研究,后扩展到各类形式规约语言,形成了形式语义学.
形式语义学(理论)研究形式规约语言语义的数学基础和构建方法,提供研究形式语言表达能力、可靠性和完备性的数学手段.依据使用的数学结构和语义表示方法的不同,形式语义研究方法可以分为 4 类,即操作语义、指称语义、代数语义和公理语义.
操作语义(operational semantics)使用抽象解释器(有时也称为抽象机或者抽象函数)定义语言语义,着重模
拟数据加工过程中计算机系统的操作.
指称语义:指称语义(denotational semantics)将语言的基本语法成分解释成为数学对象(称为指称),用数学对象上的运算来定义语言的语义.
例如,针对 Timed CSP,人们扩充了迹语义模型和失效-发散-迹语义模型,分别提出了带时间戳的迹语义模型和带时间戳的失效-发散-迹语义模型[23,125].
代数语义(algebraic semantics)用代数结构来定义计算机语言(特别是代数规约语言)的语义,是在抽象数据类型的基础上发展起来的.代数语义与代数规约的关系密切,主要用于解决基于代数规约的形式化开发中程序正确性的推理,抽象程度比较高.
公理语义(axiomatic semantics)直接使用形式逻辑来描述程序的语义,其基本思路是,在已有的形式逻辑系
统的基础上增加所有程序必须满足的基本命题(程序公理).
形式规约和开发方法遵循软件开发方法的基本原理,包括关注点分离和逐步精化.在形式规约和验证的基础上,软件形式化构造活动包括针对形式规约多视角建模、不同抽象层上规约间的精化以及程序综合等.
形式规约可以从不同的角度用不同/相同的规约语言来描述系统,即所谓的多维视角规约方式,如图 2 所示.例如,一个系统(需求)规约可包括数据模型规约、数据功能规约、交互通信协议规
约以及动态的状态迁移行为模型.
程序综合(program synthesis)是指使用指定的编程语言自动生成符合程序规约的技术.
形式化方法最显著的作用是能够对形式规约进行验证.形式验证常见的有两种形式:一种是推理“系统模型规约是否满足其性质规约”,这时,模型规约偏向操作型,性质往往是说明型的;另一种是推理“系统的一个模型规约是否与另一模型规约有精化或等价关系”.形式验证方法主要包括演绎式的定理证明和算法式的模型检验.
基于定理证明的形式验证将“系统满足其规约”这一论断作为逻辑命题,通过一组推理规则,以演绎推理的方式对该命题开展证明.基于定理证明的验证大部分是以程序逻辑为理论基础的,但是程序逻辑并非唯一的验证方法,例如,我们可以基于程序的操作语义直接表达程序执行的安全性、正确性等各种性质并证明相关定理。
Floyd-Hoare逻辑[10,93]是一种经典的基于定理证明的验证系统,其验证对象是顺序程序.Owicki 和 Gries 提出一种通用的并发程序验证方法[96]。Jones 在此方法的基础上进行扩充,提出了 Rely-Guarantee 方法[98],解决了可组合性问题.
按照证明方式和自动化程度的不同,基于定理证明的验证又可以分为两类,即基于自动定理证明器的自动验证和基于人机交互的半自动验证。
定理证明中,形式验证把待证明的性质直接作为了一个数学定理来证明,也称为演绎式验证.与演绎式相对应的一种方式是模型检验[175177].模型检验分别由 Clarke 和 Emerson、Queille 和 Sifakis 在 1980 年代初各自独立提出[19,176],其基本思想是**:检验一个结构是否满足一个公式要比证明公式在所有结构下均被满足容易得多,进而面向并发系统创立了在有穷状态模型上检验公式可满足性的验证新形式[178].**
模型检验通过自动遍历系统模型的有穷状态空间来检验系统的语义模型与其性质规约之间的满足关系,.模型检验中最常见的是时序模型检验或逻辑模型检验,其系统规约大多是基于模型的规约,使用操作语义描述系统行为,形式模型使用自动机、标记迁移系统等;待检验的性质是用时序逻辑描述的基于性质的规约.如果系统模型不满足性质,模型检验算法会给出系统行为不满足性质规约的反例,用户可以根据反例进行分析和调试;如果模型检验未发现反例,则系统一定满足所检验的性质.
模型检验的核心是有穷状态空间上的遍历策略和算法,主要有显式方法和隐式方法.显式方法是通过状态计算来遍历状态空间,隐式方法是通过不动点计算来遍历状态空间.两者的本质都是有穷状态空间的穷尽搜索.因而,模型检验的关键问题就是如何应对系统状态爆炸,在可表示的状态空间和有效的时间内完成搜索.对于这个问题,主要有 3 类途径:
(1) 结构化方法:利用定义系统的语法表达(模型)结构来缓解状态空间爆炸问题,典型的方法有对称模型检验、On-the-fly 的状态空间搜索、偏序模型检验、参数化模型检验等等;
(2) 符号化方法:将模型的迁移结构的状态和迁移编码为逻辑公式,这种符号化编码能够有效压缩表示状态集合的数据结构,状态变迁的操作也相应高效.符号化的编码方法常常基于 BDD、命题公式
或者无量词的一阶约束等等;
(3) 抽象方法:**将复杂系统的状态空间结构归约为较小的同态映像,后者是前者的一个上近似(over-approximation),从而把原系统的验证转化成模型检验可以处理的问题,例如谓词抽象方法等.**而作为一种更一般化的方法,抽象解释是一种基于序集合上单调函数对程序形式语义进行可靠近似的理论,为程序自动分析提供了一个通用的框架。
软件系统属于无穷状态系统,即使状态有穷,其状态空间规模也往往远超当前计算机可处理的范围.在硬件系统模型检验取得巨大成功的时候,软件模型检验所面临的挑战依然严峻.
当模型检验抽象得到反例时,首先检验反例路径是否是可行的,这通常通过基于反例路径的编码约束求解得到.如果不是可行的,即反例的路径公式是不可满足的,基于语法的精化就可以通过加减合适的谓词进行抽象精化.
在软件模型检验中,利用静态分析、符号执行等方法抽取程序模型,以及基于路径的模型检验等静态和动态结合的方法,也是有效提高模型检验扩展性的重要途径[3].近年来,将模型检验与定理证明有效地结合也是一个有前景的方向.
形式化方法在工业界硬件系统设计应用上十分成功.软件形式化方法的应用比硬件要早,但比在工业界的影响要小很多,其主要原因是软件系统的复杂性远高于硬件,相应的软件系统形式化工具水平也远低于硬件形式化工具,特别是在形式验证工具方面.
由于形式化方法本身是有开销的,故在应用中合理考量其应用的经济性是必须的.形式化方法在安全攸关的系统(航空、航天、核、铁路等领域)中往往得到较多的应用,一些软件安全性保证标准。
根据形式化程度的不同,形式化方法应用首先要确定是在整个系统应用亦或在关键部分应用.确定了应用的系统范围或边界之后,可在相关部分中不同程度地应用形式化方法.
近 10 多年以来,基于交互式定理证明的形式化方法在可验证的系统软件上取得显著的突破.这有 3 方面的因素:一是基础软件在整个信息系统体系中的价值日益提高,这在一定程度上使得重量级的形式化方法在其上应用的成本变得有可能接受;二是系统软件与应用软件相比,其核心部分的边界和功能比较稳定而不多变,一次验证完成后可以为社区共享;三是形式验证工具的自动化能力有了明显改善,并且系统软件也可以作为形式化方法发展的磨刀石.
形式化方法不仅能够保证系统软件自身的可靠性和安全性,它反过来也能为系统结构的优化提供重要启发和支持.
具有数学基础的方法或者建立方法的数学基础是工程方法走向成熟、理性的必由之路.从应用上看,不断增加软件开发的机械化和自动化程度,提高软件的质量和生产率、尽可能减低成本是工程实践的愿景.尽管形式化方法对于提高软件质量的作用已经形成共识,但其对大规模软件生产率和成本的影响还没有明确的认识,对形式化方法的认可度和应用度的进展仍然缓慢.在已有的形式化方法的规模应用中,使用者大多是有良好形式化方法素养/培训的人员,甚至是方法、技术和工具本身的研发者.一些软件工程实践表明:除了把程序视作形式规约以外,工程师们并不愿意大量编写形式规约,认为形式化方法本身比较复杂,在某种程度上增加了软件系
统的设计复杂度.因此,形式化方法的首要挑战是发展形式化方法的应用形态,包括技术形态和工具形态,提高形式化方法的易用性、有效性和扩展性,降低形式化方法的应用门槛.
程序设计语言和程序正确性是形式化方法发展的最初源泉.面向程序设计语言和代码,研究和运用形式化方法、技术与工具是一个重要的方向.人们在实际的程序设计语言上开展了很多验证技术的研究,围绕程序代码的形式验证技术的发展趋势将会明显,验证将成为程序设计环境的一部分,如同程序测试、代码推荐的功能一般.程序设计语言与规约语言的融合将成为趋势.形式化方法的许多思想和方法在程序设计语言的设计中有重要的影响.许多新型程序设计语言设计之初的想法和应用源自于形式化方法.Rust 语言[236]的成功是形式化方法研究对系统开发提供支持的代表性案例,它主要面向系统编程:一方面,语言支持并发以及手工内存分配和释放;另一方面,语言借鉴类型系统、线性逻辑和并发分离逻辑的思想,在语言中引入内存所有权(ownership)以及所有权传递(ownership transfer)的概念,避免了内存错误以及并发程序中常见的数据竞争错误.目前,Rust 语言受
到了工业界和学术界的广泛关注,已有多个使用 Rust 开发的较有影响力的系统,包括浏览器、操作系统和其他各种工具.与这一趋势相伴,对可视化编程机制以及领域相关特性的支持,将进一步推动新型语言的可用性和可行性.
近 10 年来,形式化方法进入一个振兴的阶段.无论是轻量级的形式化方法与主流方法的结合,还是重量级的形式化方法在工业级软件上的应用,都取得了较大的进步和成功[237].在这些成功应用的后面,工具起到了决定性的作用.系统一旦使用了形式规约语言建模,它就能用工具进行语义分析.工具也缓解了问题规模带来的压力.因此,构建更加可用和鲁棒的工具支持大规模规约的并行语义分析和验证,构建可复用的形式规约库和方法社区,推动形式化方法工具和可复用库设施的进步,包括工具的集成、工具的无形化、规约与验证资产,毫无疑问都会是形式化方法努力的方向.
规约、开发和验证的系统与环境的形态变化是形式化方法发展的驱动力.形式化方法的目标在于高质量的描述、开发和确认软件系统,因而软/硬件的形态进步和地位的变化对形式化方法有着直接的影响.例如,形式化方法发展的一条重要线索是从顺序程序到并行程序、混成系统、信息物理融合系统乃至人机物融合系统,而人机物融合社会中混成系统对形式化方法的基础、方法、技术和工具都形成了全面的挑战[238,239].
软件正在成为社会基础设施,而形式化方法在计算机系统基础软/硬件的可靠性中发挥了十分重要的作用,这正是人们最能认识到的形式化方法在关键的信息基础设施中发挥作用的应用点.在软件基础设施方面,全栈的可验证软件将会持续地进展,并有可能在实用主流操作系统中逐渐地渗透.例如,为了保证云服务基础设施的
可靠性,Amazon 利用 TLA+方法对其 S3 云存储服务的关键算法进行了形式验证,发现了不少缺陷[240].2017 年,Linux 基金会宣称,将对一些 Linux 内核模块进行形式验证以提高系统的安全性[241].基于形式化方法的信息安全性研究毫无疑问是一个方向[242].面向未来的软件基础设施,区块链和智能合约的正确性及信息安全性验证正蓬勃展开[243,244].
在软件定义一切的时代,形式化方法将定义软件.形式化方法如何与其他软件开发方法、领域特定的融合显得尤为重要.对应于软件定义时代的软件形态的特征变化、质量的需求变化,形式化方法需要在基础概念、规约、开发和验证技术与工具上适应更为复杂开放、动态多变、持续演化的软件形态.例如,在人机物融合下,需要准确、恰当地处理非形式化需求到形式规约、形式化抽象到非形式化场景和现实世界的边界建模,大量非功能规约包括社会化人因的规约,自主自适应自组织等新型软件结构和行为的规约、推理与验证等等.在形式化方法的发展中,数学与形式化方法有着密切的互动,数学为形式化模型和推理提供了基础,而形式化方法也促进了数学的发展.形式化方法可以机械、高效、准确无误地写出复杂数学问题的可靠证明,甚至帮助解决一些长期悬而未决的数学难题,例如四色定理[245]、罗宾斯猜想(Robbins conjecture)[246]、开普勒猜想(Keplerconjecture)[247](该原始证明超过 300 多页,正式发表的证明也近 130 页,其正确性无法保证[248])等等.形式化(工程)数学[249]对于构建高可信智能制造软件环境也具有重要价值.
形式化方法和人工智能有着密切的联系.定理证明和约束求解是符号主义流派人工智能的重要内容.如何利用人工智能的其他成果提高形式化方法的水平是一个值得关注的方向,例如基于机器学习帮助构建形式规约、发现不变式或者推荐证明策略辅助形式验证、辅助规约精化和程序综合等等.程序综合与机器学习交叉,
出现了基于深度学习和框架生成相结合的程序综合方法.另一方面,机器学习软件也是程序,研究它们的形式化方法是非常有价值的[250,251].例如,概率程序设计的形式语义、验证和调试、大数据处理程序的验证、深度学习程序的形式规约与鲁棒性验证、利用形式化方法建立更好的训练方法、研究机器学习的可解释性,都是值得探索的课题.
在新的计算模型方面,量子程序设计[252]的理论成为了形式化方法发展的新内容.形式化方法已经应用到了量子程序设计语言的语义分析、关键性质的推理,也出现了量子计算的程序逻辑和模型检验方法.由于量子程序和传统程序相比有很大的不同,特别是由于量子叠加和纠缠的存在,建立系统的量子计算的形式化方法并开发有效的验证技术才刚刚起步.
计算思维的渗透性也带动了形式化方法与其他学科的交叉融合,例如在生物研究领域,计算建模和分析已经成为一种重要方法[253],例如 Naïve T cell differentiation 的时序行为建模和分析[254].这些研究有力地促进了混成系统形式化方法的发展,也促进了医疗生命科学的发展,并为医工结合交叉提供了一个明确的方向[255].
教育是形式化方法持续发展的重要推手.受限于可用性和可扩展性,形式化方法学习曲线长,高强度运用需要较高的门槛,严重制约了形式化方法在软件开发中的广泛应用.而计算系统的可信愈来愈重要,ACM 和 IEEE制定的计算机科学和软件工程课程计划都包含了程序正确性的内容[256,257].我国的形式化方法教育现状调查结果指出,需要加强专业教育中形式化方法认知[258].形式化方法的轻量级运用已经能够显著提高人们对系统需求和设计的理解,而且程序就是一种形式规约,可以机械化自动地处理(编译或执行).形式化方法对于软件开发人员而言实际上都在接触,只是形式化程度不同而已.因而在计算思维养成过程中,在程序设计、数据结构等基础课增加形式化概念的讨论,在离散数学、算法、软件工程等后续专业课程突出形式化方法与主流方法的关系和结合,对于形式化方法的推广和水平提高是非常重要的.