理论计算机科学
关于计算和计算机械的数学理论,也称为计算理论或计算机科学的数学基础。理论计算机科学主要包括:①自动机论与形式语言理论②程序理论③形式语义学④算法分析和计算复杂性理论
学科的产生 在几千年的数学发展史中,人们研究了各种各样的计算,创立了许许多多的算法,但以计算或算法本身的性质为研究对象的数学理论却是到20世纪30年代才发展起来的。当时为了要解决数学基础的某些理论问题,即是否有的问题不是算法可解的,数理逻辑学家提出了几种不同的(后来证明是彼此等价的)算法定义,从而建立了算法理论(即可计算性理论)。30年代前期,K.哥德尔和S.C.克林尼等人创立了递归函数论,将数论函数的算法可计算性刻划为递归性。30年代中期,A.M.图灵和E.L.波斯特彼此独立地提出了理想计算机的概念,将问题的算法可解性刻划为在具有严格定义的理想计算机上的可解性。30年代发展起来的算法理论,对在40年代后期出现的存储程序型计算机的设计思想是有影响的。图灵提出的理想计算机(称为图灵机)中的一种通用机就是存储程序型的。
学科内容
在这些领域中,自动机理论和形式语言理论是50年代发展起来的。前者的历史还可以上溯到30年代,因为图灵机就是一类自动机(无限自动机)。50年代以来一些学者开始考虑与现实的计算机更相似的理想计算机,J.诺伊曼在50年代初提出了有自繁殖功能的计算机的概念。王浩在50年代中期提出了一种图灵机的变种,这是一种比原来的图灵机更接近现实机器的机器。他还提出一种存储带上的内容不能清除的机器,并证明这种机器是与图灵机等价的。60年代前期,又有人提出具有随机存取存储器的计算机(简称RAM)以及多带图灵机等。
形式语言理论
导源于数理语言学中的乔姆斯基理论。在这种理论中,形式语言分为四种:①0型语言;②1型语言;③2型语言;④3型语言。相应地存在着0型、1型、2 型、3型四种形式文法。1型语言又名上下文有关语言,2型语言又名上下文无关语言,3型语言又名正则语言。其中2型语言最受人注意。60年代中期,还发现了这四类语言与四类自动机之间的对应关系(见表)
在上表中,左边所列的语言恰好是右边与之对应的自动机所能识别的语言(见形式语言理论)。
程序设计理论
包括程序正确性证明和程序验证,它的一些基本概念和方法是40年代后期诺伊曼和图灵等人提出的。诺伊曼等在一篇论文中提出借助于证明来验证程序正确性的方法。后来图灵又证明了一个子程序的正确性。他的方法是:设有一给定的程序,且有变量X1,X2,…,Xn以及输入谓词P(X1,…,Xn)与输出谓词Q(X1,…,Xn)。如果能证明下列事实:若在程序执行前谓词P(X1,…,Xn)成立,则在程序执行后,谓词Q(X1,…,Xn)成立,程序的正确性得证。
图灵的这一结果长期未引起注意,一直到P.瑙尔在1963年和E.F.费洛伊德在1966年重新提出这一方法后,才引起计算机科学界的重视。此后,有不少理论工作者在从事这方面的研究。但正如E.W.戴克斯特拉在70年代中期曾指出的,实际有效的方法是边设计边验证,在设计完毕时证明或验证的过程也同时结束。J.T.施瓦兹和M.戴维斯70年代后期提出了一种他们称之为“正确程序技术”的软件技术。这种方法是先选定成千种基本程序模块,并借助已知的各种验证方法(包括程序正确性证明)来保证这些基本程序的正确性。然后再提出一组能保持正确性的程序组合规则。这样,就可以通过不断的组合,生成各种各样的程序。
有人指出,程序正确性证明技术所发展出来的“循环不变式”,即一个程序中的某一循环的入口或出口点上所附的谓词,有些文献中称作“归纳断言”,可以用来供程序研究用。也就是说,不像过去那样,对一个给定的程序找出其若干个循环不变式,然后借助这些不变式来证明这个程序的正确性;而是在编制这个程序之前,根据对这一程序的要求,找出若干个循环不变式,然后根据这些不变式来生成这个程序。
自动程序设计的概念也是从40年代提出的。图灵在1947年的一篇论文中,提出借助定理证明的方法来设计程序。他的想法大致如下:设要求设计一个程序,使成为计算一个给定的递归函数F(X)的程序,并令F(n)=m(这里n是任一自然数,m是自然数),需要找到一个证明F(n)=m的构造性证明。在有了这样一个构造性证明以后,就可以从这个证明中提取出F(X)的求值算法,然后生成所需要的程序。图灵的这一思想长时间不为人所知。1969年又有人独立地提出了这一想法。
程序语言的形式语法的研究,从50年代中期起有了较大的发展。而形式语义的研究自60年代以来虽有不少研究工作者从事这方面的工作,提出几种不同的语义理论,主要是操作语义学、指称语义学或称数学语义学、公理语义学和代数语义学,但仍没有一种公认在软件技术中够用的形式语义学,因而需要提出一种更适于用到实际计算中的新的语义学。
在程序正确性证明和形式语义学中应用的程序逻辑,是60年代末发展起来的。这是谓词逻辑的一种扩充。原来的谓词逻辑中是没有时间概念的,所考虑的推理关系是在同一时间里的关系。程序是一种过程,一个程序的输入谓词与输出谓词之间的逻辑关系就不是同一时间里的关系。因此,在有关程序性质的推理中,原来的谓词逻辑不够用,需要有一种新的逻辑。
60年代末,E.恩格勒等人创立了算法逻辑。C.A.R.霍尔也创立了一种程序逻辑。这种逻辑是在原来的逻辑上增加一个程序算子而得到的。例如,可以将程序作为一种新的算子置于一个谓词公式的前面,如表达式
{S}P(X1,…,Xn)表示在程序S执行完毕时,谓词P(X1,…,Xn)成立(这里的)X1,…,Xn是程序S 中的变量)。
算法分析和计算复杂性理论
关于算法的复杂性的研究。关于这一领域的名称曾有争论。一般认为,各类具体算法的复杂性的研究称作算法分析,而一般算法复杂性的研究称作计算复杂性理论。计算复杂性理论原是可计算理论的一支,是以各种可计算函数(即递归函数)的计算复杂性(在早期称作“计算难度”)为其研究对象的。可计算性分为理论可计算性和实际可计算性两种。作为可计算性理论一支的计算复杂性理论,是以前者的复杂程度为其研究对象的;而作为计算机科学一个领域的复杂性理论,则是以后者的复杂程度为其研究对象的。
这一分支的基本问题是要弄清楚实际可计算函数类的结构和一些性质。实际可计算性是一个直观的概念。如何对这一概念进行精确的描述,是一个并不容易的问题。60年代中期以来,有关的研究工作者一般是以计算时间多项式有界的函数作为实际可计算的函数。这实际上是一个论题,而不是一个可以在数学中加以证明或否证的命题。有人指出,在有关的多项式次数较高时(如n的情形),很难说是实际可计算的。
另一个带根本性的问题是:确定性机器与非确定性机器的解题能力的比较问题。人们早已知道,确定性图灵机与非确定性图灵机的解题能力是相等的。因为非确定性机器虽比确定性机器效率高,而如果计算时间没有限制,则确定性机器总可以用穷举的方法来模拟非确定性机器。因此,二者的解题能力是一样的。但在计算时间多项式有界时,二者的解题能力是否相等,这就是有名的P=? NP问题。
关于计算和算法(包括程序)的研究,对串行计算的性质研究较多,而对并行计算性质的研究则还很不够(特别是对异步的并行计算更是如此)。因此,关于并行计算的研究很可能将成为计算机理论的研究重点。
程序正确性证明
http://www.doc88.com/p-14560508880.html
程序算法的正确性和效率
1、算法的正确性判定
研究计算机算法的目的是为了有效地求出问题的解,用计算机语言描述的算法要在计算机上运行,这引出了对算法效率的分析和讨论。例如在象棋比赛中,对任意给出的一种棋局,可以设计一种算法判断这一棋局的输赢,算法需要从开局起对所有棋子可能进行的移动、移动前后的每一对策作检查,做出应走的棋步。计算步骤是有穷的,但在计算机上运算这一算法需要很长的时间。这就说明计算机只能运行在有穷步内终止的算法。
设计出算法后,应证明该算法对所有可能的合法输入都能计算出正确的结果,这一工作称为算法确认。算法确认与描述实现这一算法的手段无关,例如可以用不同计算机语言来实现这一算法。用算法语言描述构成的程序在计算机上运行,也应证明该程序是正确的,这一工作称为程序证明。
对程序的测试包括调试和作时空分布图。调试程序是在抽象数据集上执行程序,确定是否会产生错误的结果,如果出现错误,进行修改,再做测试。调试只能指出程序有错误,而不能指出程序不存在错误。程序的正确性证明是计算机科学一个重要的研究领域。作时空分布图是用各种给定的测试数据,去调试已经证明是正确的程序,测定一个算法得出运算结果所用去的时间和空间,给出时空分布图,验证对算法所作的分析是否正确,找出算法最优化的有效逻辑位置,优化算法的效率。
2、算法的最优性
求解一个问题,如果规定了算法所允许的运算类型,则所有可能的算法构成了解决这个问题的一个算法类,判断一个算法是否最优的依据,是该算法的平均性态分析。若在选择的算法类中,如果一个算法比所有的算法执行的基本运算少,此算法应该是最优的。
判断一个算法是否最优,并不需要对算法类中的每一个算法逐个进行分析,可以根据这个算法类的特性,确定所需运算次数的下界,在算法类中所有运算次数等于这个下界的算法是最优的,这也说明最优算法不是惟一的。需要做两件工作确定解决一个问题至少需要多少次运算:① 设计一个有效率的算法A,分析A并找到一个函数F,使对尺度为n的输入,A最多做F(n)次基本运算;② 对某一函数G,证明一个定理,表明对所考虑的算法类中的任何一个算法,存在一个尺度为n的输入,使算法至少要做G(n)次基本运算。
若函数F与G相等,则算法A是最优的;若不相等,则可能存在一个更好的算法或更好的下界。
3、分析算法
(1) 分析算法的两个主要内容
要分析一个算法首先要确定使用哪些算法以及执行这些算法所用的时间。运算可以分为两类,一类是基本运算,包括加、减、乘、除四种基本的整数算术运算以及浮点算术、比较、对变量赋值和过程调用等。这些运算所用的时间不同,但都是花费一个固定量的时间。另一类运算由一些基本运算的任意长序列组成,以两个字符串的比较运算为例,可以看做是一系列字符比较指令运算,而字符比较指令可以使用移位和位比较指令。比较两个字符的运算时间是固定的,是某一个常数值,而比较两个字符串的运算时间值则与字符串的长度相关。
其次是确定能反映出算法在各种情况下工作的测试数据集,设计和编制出能够产生最优、最差运算结果的输入数据配置,这些数据配置能够代表可能出现的典型情况。数据配置的设计是创造性的工作,应能最大限度地适应算法,反映算法运行的环境和功能要求。
(2) 分析算法的两个阶段
对一个算法作出分析分为两个阶段,即事前分析和事后测试。
事前分析(priori analysis),求出该算法的一个时间界限函数,用于对计算时间的渐进表示,假定某一算法的计算时间是f(n),其中变量n表示输入或输出量,它可以是两者之和,也可以是它们之一的一种测度,例如数组的维数、图的边数等,f(n)与机器和语言有关。g(n)是在事前分析中确定的某个形式很简单的函数,是独立于机器和语言的函数,例如nm、logN、2n、n!等。给出定义:
若存在两个正常数c和n0,对于所有的n≥n0,下式成立
|f(n)| ≤ c| g(n)|
记作
f(n)= O(g(n))
因此,当讲一个算法具有O(g(n))的计算时间时,指的是若该算法用n值不变的同一类数据在某台机器上运行时,所用的时间是小于| g(n)|的一个常数倍,所以g(n)是计算时间f(n)的一个上界函数,f(n)的数量级就是g(n),在确定f(n)的数量级时总是试图求出最小的g(n),使得f(n)= O(g(n))。
事后测试(posteriori testing),收集该算法的执行时间和实际占用空间的统计资料,是在对算法进行设计、确认、事前分析、编码和调试后要做的工作,即作时空性能分布图,事后测试的结果与所用机器相关。要确定算法的精确计算时间,必须了解时钟的精确度以及计算机所用操作系统的工作方式。为避免因所用机器不同而出现误差,有两种可以选用的方法:一种方法是增加输入规模,直到得到算法所需的可靠的时间总量;第二种方法是取足够大的算法重复因子r,将该算法执行r次,然后用总的时间去除以r。
例如,对于事前分析为O(g(n))时间的算法,选择按输入不断增大其规模的数据集,用这些数据集在计算机上运行算法程序,得出算法所使用的时间,画出这一数量级的时间曲线,并与事前分析所得出的曲线比较。
一。什么是程序的正确性?
设P是一个抽象问题,x是P的一个输入实例,对于具体的输入x,我们所期望的正确解用f(
x)来表示,这里f是某种函数关系,它表明了问题P的输入和正确输出之间的对应关系。
设Q是一个用来解决问题P的确定性程序,Q的输入和对应的输出之间的关系用函数g表示,
换句话说,对于输入x,程序Q给出的输出是g(x)。
注意,上一句中强调的“确定性程序”说明对于同样的输入该程序只能得到同样的输出,
也就是相当于该程序没有side effect,这也是我们可以把一个程序的输入输出之间的关系
看作一个函数关系的必要条件(否则同一个x就对应了多个不同的g(x)了)。
在上述定义的条件下,我们说程序Q是正确的,当且仅当函数f = g。
二。为什么需要引入正确性的证明?
根据程序正确性的定义,要判断两个程序相等,也就是判断两个函数相等。有两种基本方
法:
1。外延相等(Extensional Equality):
在Zermelo-Fraenkel set theory里有一条Axiom of extension,该公理内容如下:
\forall A, \forall B, A = B \leftrightarrow (\forall C, C \in A \leftrightarr
ow C \in B)
该公理的意思是说,两个集合外延相等当且仅当它们内部的元素一一对应相等,这条公里
也可以看作是对“两个集合相等”的定义。因为一个函数就是一个关系,即一个二元对的
集合,所以根据该公理我们可以定义两个函数外延相等:
设f, g为函数,则
(\forall x, f(x) = g(x)) \leftrightarrow f = g
(注:我们可用一个特殊的符号表示“无定义”,这样当x使得f(x)无定义的时候根据f(x
)=g(x)可知g(x)也无定义。)
换句话说,两个函数外延相等是指他们的函数图像相等。
数学中通常采用的函数相等性定义都是指外延相等,但在计算机科学中外延相等有时候并
不合理。例如f是冒泡排序的函数,g是快速排序的函数,f和g对于输入的n各元素输出都是
这n个元素从小到大的排列,从外延性上看函数f和g是相等的,但是在程序设计中不能把他
们当作同一个函数,因为他们的运行效率不同。
外延相等的另一个重要的缺陷是,很难证明两个函数外延相等,因为根据定义,必须对所
有的输入x都有f(x)=g(x)才能说f=g,但实际问题中可取的输入可能是无穷多的,不可能对
无穷多的输入一一验证。
通常我们采用测试数据来验证程序,就是在无穷多的输入中取几个特定的输入x,并对f(x
)和g(x)做验证。假设测试数据的样本空间为集合W,
\forall x \in W, f(x) = g(x)
仅仅是f=g的必要条件而不是充分条件。所以这种验证方法只能找出程序可能的错误,却无
法证明程序的正确性。
2。内涵相等(Intensional Equality):
在集合论中,两个集合内涵相等定义如下:
\forall A, \forall B, A = B \leftrightarrow (\forall C, A \in C \leftrightarro
w B \in C)
该定义的意思是,两个集合内涵相等当且仅当它们属于同样的集合。如果把“属于某个集
合”看作是“满足某个性质”,则两个集合内涵相等当且仅当它们满足同样的性质。
所以两个函数相等,可以定义为:
设f和g为函数,P为一个谓词,则
(\forall P, \forall x, P(f(x)) = P(g(x))) \leftrightarrow f = g
换句话说,f和g相等当且仅当它们对于同一个输入x的输出f(x)和g(x)都满足或都不满足相
同的性质P,这里P是任意一个谓词。
事实上,Hoare的公理化证明就是利用内涵相等来证明一个程序的正确性。顺便说一下,利
用数学归纳法对一个包含无限子命题的命题的证明实际上也是利用了这种内涵相等的概念
。
三。Hoare公理化证明的优点:
简单来说就是:化无限为有限,不需要对所有的输入进行一一验证,而只需要证明程序的
输入和输出之间满足某个特定的性质,从而利用内涵性证明程序的正确性。
四。Hoare公理化证明的缺点:
1。Hoare提出的那几条公理并不完备,对于复杂的程序,要构造一个完备的公理系统非常
复杂,需要很多公理;
2。即使完整地构造了Hoare的程序公理系统,要证明这个公理系统的完备性和一致性也非
常复杂,我不知道是否有人做过这件事了。
3。在公理系统内定理的形式化证明本身也是一个很复杂的问题,目前尚无非常有效的算法
来进行定理自动证明。
--
这个世界的一切都值得怀疑,除了正在怀疑着的自我
形式化(一)程序正确性证明
首先要明确什么是程序的正确性这个概念。对于FG,程序的正确性分为两种,一种是完全正确性,指的是程序P一定停机,如果P执行前F断言为真,那么执行P后G断言也为真。还有一种是部分正确性,指的是,如果P停机,那么P执行前F为真,执行后G为真。也就是完全正确性还要多一个一定停机的证明。
我主要看了一下部分正确性证明。也就是如果停机,那么执行前的断言为真,执行后的断言也一定要是真。这个的证明方法,最出名的是归纳断言法和公理化方法。提出者分别是Floyd和hoare。这两种方法的细节可以参考《软件开发的形式化方法》这本书。我这里只交代一下我所学到的精髓。
归纳断言法的核心思想就是找出证明程序正确性的一些逻辑表达式,或者叫检验条件。通过证明这些检验条件为真,证明整个程序为真。具体是这么做的,把程序插入断点,这些断点只插在开头,结尾,以及循环开始处。接着在这些断点处建立断言,其实就是程序处于这些位置的时候具有的性质,也是一些逻辑表达式。有了这些断点和断言以后,这些断点就把程序分割成了一段一段的通路。这些通路通过是有条件的,记做R。那么每条通路就可以得出一个检验条件,形式为P(X,Y)^R(X,Y)->Q(X,Y'),也就是通路开头的断言并上通过通路需要的条件蕴含通路末尾的断言。注意通路末尾的断言中Y因为通路的运算转变成了Y‘。有了这些检验条件后,只需要根据各种显而易见的公理,事实(比如gcd(y1,y2)=gcd(y1,y2-y1))证明这些检验条件永真即可证明程序的部分正确性。X表示的是程序的输入,Y表示程序的中间变量,Z表示程序的输出。程序开头的断言描述的输入要满足的条件,是关于X的逻辑表达式。程序中间断点的断言是描述中间变量Y和输入X之间的关系,以及中间变量自己要满足的逻辑表达式。程序结尾处的断点的断言是描述输出Z与输出X之间的关系的逻辑表达式。
公理化方法是归纳断言法的扩展,区别就在于通过引入了1条赋值公理和4条推理规则规范了归纳断言法中检验条件的抽取,这里检验条件被称为逻辑表达式LOG。本质都是一样的,都是希望把程序的部分正确性演化为一些逻辑表达式的正确。这就是形式化的方法的引入。这里再明确一个概念:不变式。不变式就是指形如{W(X)} Q {U(X,Y)},描述了程序的一个动态的需要保持的性质,它与断言的区别在于,断言描述的式程序处于某个断点处的性质,而不变式是程序整个过程中都要保持的性质(逻辑表达式)。其中,W(X)和U(X,Y)是断言,Q是一段程序。证明Q的正确性就要证明这个不变式的正确性。这个不变式可以利用1条赋值公理和4条推理规则划分为更小的不定式,然后这些不定式最后通过赋值公理转化为LOG逻辑表达式。最终这些逻辑表达式的证明就跟归纳断言法的一样了。你注意观查会发现公理化方法得出的逻辑表达式和归纳断言法得出的检验条件是一样的。只是公理化方法得出这些逻辑表达式的过程严密了一些。
总结,程序部分正确性的证明,实际上就是设置断点,然后在断点处用断言(逻辑表达式)描述程序的性质,相当于程序在该点处应该具有的性质,然后描述断点之间的通路,也就是小程序片段(分到最后应该就是赋值表达式,这点可以从公理化方法中看出,最后由不变式转化为条件逻辑表达式必然用到赋值公理)执行需要的条件。假设通路开始的性质为真,执行通路的条件为真,那么就一定要求通路结束处的性质为真。这样一段通路一段通路的证明下去,最后就合成了整个程序的部分正确性。
形式化(二)软件规格规约方法及语言
什么是软件规格?软件规格就是对软件所要满足的需求的描述,包括需求规格,功能规格,性能规格以及设计规格。其中需求规格是描述用户对该软件的要求的,功能规格和性能规格是描述“做什么”的问题,以及速度,资源的限制。设计规格解决“怎么做”的问题。
软件规格分为形式化和非形式化两种。我们研究形式化的软件规格,形式化的软件规格其语法和语意均为精确的无二意的。通过形式化的软件规格,我们可以做软件的自动生成,也是以后程序正确性证明工作的基础。现在不清楚对于测试用例的自动生成有没有作用。
把软件规格形式化的方法叫做软件规格规约方法。描述形式化的软件规格的语言叫做软件规格语言。
软件规约方法主要包括两个方面的工作,一个是过程的抽象,一个是数据的抽象。过程的抽象也就是我们不关心具体任务完成的过程,只是对任务要完成的功能进行精确描述。过程抽象可以采用的方法有前后断言法和HOS法。他们都是基于一阶谓词演算来刻画输入和输出之间的关系的。前后断言法是先描述接口,然后用前后断言描述功能。前后断言就是指输入定义域上的关系(前断言),输入定义域和输出值域笛卡尔积上的关系(后断言)。这样就完全规范了程序的过程的功能性,要完成什么工作。绝对没有歧义。至于具体的过程却不关心。HOS方法更简单一些,它通过一些条件以及递归表达式来描述软件过程,写起来很像程序。刚才描述的过程的抽象,那么数据的抽象我们如何做呢?主要有两种方法,一种是代数方法,通过抽象代数中的公理化方法来刻画抽象数据类型中运算的性质。第二种方法是模型方法,这种方法就是《数据结构》课本上给出的那种ADT,就是利用已有的抽象数据类型来构造出待定义的抽象数据类型,用抽象模型(抽象方法的定义)来刻画待定义的抽象数据类型中的运算功能。这里我重点讲一下代数方法,模型方法可以参考《数据结构》。代数方法产生的抽象数据类型的规约ADT-SP由两部分组成,一部分是语法部分Syntax,一部分是公理部分Axiom。Syntax描述程序中所有的用到的已知和待定义的类型名,以及定义域和值域上以及定义域和值域笛卡尔积上的运算符。注意只是描述这些运算从定义域到值域的映射,比如integer->integer。还需要另外一部分Axiom部分描述这些运算应该满足的公理,比如POP(new Stack)=false,就是弹空栈要出错之类的。这样有了过程抽象,也有了数据抽象,就可以得出形式化的软件规格了。
如何书写这些形式化的软件规格呢?这就需要我们采用软件规格语言来写。具体分为两类:面向模型和面向性质的。面向模型的包括:VDM,Z,petri网,自动机。面向性质的包括:代数规约,时序逻辑等。我的理解是面向模型的方法是要构建模型,由小模型一点一点描述出整个软件的模型,通过模型来描述这个软件的规格。面向性质则是用代数,逻辑的表达式来描述软件要满足的性质,通过性质的描述来说明这个软件的规格。后面我会重点介绍应用比较多的Z语言。
最后有个问题就是,软件规格描述出来了,如何确保这个软件规格是正确合适的?我认为通过两个性质来保证,一个是一致性,一个是完备性。一致性就是说,在我们描述的规格中,每一个合法输入都有输出与之对应,并且满足前后断言法那种后断言描述的输入与输出要保持的关系。这是保证我们的规格是正确的,没有错误在里面。完备性是指我们的规格可以导出所有用户的要求。就是说我们把用户的要求用输入X输出Y之间的谓词表达式来表示这些要求。Ri(X,Y)表示一条要求,那么SS是Ri的集合,就是所有的用户要求。我们说的完备性就是SS中的每一条Ri都可以由我们规格中描述的X与Y的关系推导出。
形式化规约语言的分类及特点
Z,VDM,和Larch是较早发展起来的形式规约语言,它们重点研究顺序性系统的行为描述.采用的方法是:用集合,关系,函数等数学概念来描述系统的状态,状态的迁移用前后断言(条件)来表示.同时,另一类方法如:CSP,CCS,Statecharts,时序逻辑则重点描述并发系统的行为,它们用序列,树结构,及事件的偏序集合来描述系统行为.另外,形式规约语言RAISE能够描述具有大规模状态空间的系统,LOTOS能够处理大型复杂并发系统.
并行程序设计
目前并行程序设计的状况是:①并行软件的发展落后于并行硬件;②和串行系统的应用软件相比,现今的并行系统应用软件甚少且不成熟;③并行软件的缺乏是发展并行计算的主要障碍;④而且这种状态仍在继续.
其原因是:①并行程序设计不但包含了串行程序设计,而且还包含了更多的富有挑战性的问题;②串行程序设计仅有一个普遍被接受的冯*诺依曼模型,而并行计算模型虽有好多,但没有一个被共同认可;③并行程序设计对环境工具的要求远比串行程序设计先进得多;④串行程序设计比较适合于自然习惯,且人们在过去积累了大量的编程知识和宝贵的软件财富.
并行程序设计:对于所希望的应用,很多并行代码似乎不存在的;即使有,也常不能用于用户的并行机上.因为并行代码原来都是为不同的并行结构写的.
它的问题是:至今并行算法范例不能被很好地理解和广泛地接受;并行程序设计是建立在不同的计算模型上的,而它们没有能像冯*诺依曼模型那样被普遍的接受和认可.绝大部分被使用的并行程序设计语言都是Fortran和C的推广,他们都不能够充分地表达不同并行结构的特点,既不成熟也不通用.并行程序设计工具依赖于具体的并行结构和计算机代的更迭,既不通用也不稳定,在某个并行平台上开发的并行程序很难移植到别的或将来的并行机上.
目前并行编程类型逐渐汇聚于两类:用于PVP,SMP和DSW的共享变量的单地址空间模型和用于MPP和机群的消息传递的多地址空间模型.
并行编程模型逐渐汇聚于三类标准模型:数据并行(如:HPF),消息传递(如:MPI和PVM),和共享变量(如OpenMp).
现在人们希望高性能的并行机应是具有单一系统映像的巨大的工作站,使得很多用户都能利用增强处理能力和储存容量来运行多个串行作业,这就是所谓的串行程序并行系统SPPS.
当我们在实际的并行机上设计并行程序时,绝大部分均是采用扩展Fortran和C语言的办法,目前有三种扩展的办法:一是库函数法:除了串行语言所包含的库函数外,一组新的支持并行性和交互操作的库函数(如MPI消息传递库和POSIXPthreads多线程库)引入到并行程序设计中。二是新语言结构法:采用某些新的语言结构来帮助并行程序设计以支持并行性和交互操作(如Fortran 90 中的聚集数组操作); 三是编译制导法:程序设计语言保持不变,但是将称之为编译制导的格式注释引入到并行程序中.
本文介绍了什么是程序的完全正确性、部分正确性、终止性,并通过实例,介绍了利用不变式断言法和计数器方法分别证明程序的部分正确性和终止性的具体方法步骤。