【形式化方法:VDM++系列】4.VDM实战1——铁路费用计算

又有将近2个月没更新博客了啊!winter holiday简直玩儿疯了的说!结果假期前学习的形式化方法已经忘了大半!面对期末作业,大脑一片空白。于是,赶快复习了一下之前学习的姿势!

这次的主要任务是完成一个费用计算程序。

1.问题



Make a model to calculate train fare from a station to another station by using functions and the following table.

使用函数计算两个车站之前的铁路费用。基础数据如下:

values
vFareSet = {
mk_FareRecord("Tokyo", "Shinagawa", 220),
mk_FareRecord("Tokyo", "Shinjuku", 180),
mk_FareRecord("Shinjuku", "Shinagawa", 190)
}

函数开头如下:

static public Calculate_fare : set of FareRecord * Station * Station -> nat
Calculate_fare(aSetOfFare, aDeparture, anArrival) == is not yet specified;


2.解法



首先必须明确问题要求,仔细观察函数的输入输出,Calculate_fare函数有3个输入参数,分别是费用记录集合(set of FareRecord),始发车站,终点车站;输出为一个整数,即2个车站间的费用;函数内容尚未定义,现在需要我们定义函数体完成费用的计算。

计算费用的业务逻辑是:根据始发站和终点站查找费用记录集合,如果在费用纪录集合中找到始发站和终点站都相同的纪录,就返回该记录的费用。用SQL语言可以很简单的解释该逻辑:

select fare_num from fareRecord
where fareRecord.aDeparture=aDeparture and fareRecord.anArrival=anArrival

明确了业务逻辑就可以打开Overture工具开始码了!

上图展示了Overture工具默认建立的vdm类,它包类定义,类型定义,值定义,初始化变量,操作定义,函数定义,测试用例定义。这里我们需要定义type,value和functions

(1)定义类型

需要定义的类型有:fareRecord类型,Station类型。

定义Station类型与String等价,定义FareRecord类型为结构体类型,包含3个子元素

(2)定义值

(3)定义函数

注意:红线部分所展示的函数体与之前的SQL语句基本相同,let .. in set .. be st .. in .. 是VDM++独特的语法所在,需要仔细体会才能明白。

(4)定义函数的前置条件和后置条件

函数的前置条件是:对于要求的始发站和终点站应该包含于费用记录集合当中,对于费用记录集合中的2条记录,如果始发站和终点站相同,那么费用也应该相同。

函数的后置条件是:存在唯一一条记录,该记录的始发站,终点站与传入的始发站,终点站相同,该记录的结果与执行函数体得到的result相同。

至此,我们的需求定义完成。

代码如下:

class fareCaculate
types
public Station = seq of char
inv s == s<>"";

public FareRecord ::
    fDeparture : Station
    fArrival : Station
    fFare : nat
inv fr == fr.fDeparture <> fr.fArrival

functions
static public Calculate_fare : set of FareRecord * Station * Station -> nat
Calculate_fare(aSetOfFare, aDeparture, anArrival) ==
let wFareRecord in set aSetOfFare be st
{aDeparture, anArrival} = {wFareRecord.fDeparture, wFareRecord.fArrival}
in wFareRecord.fFare
pre
{aDeparture, anArrival} in set
{{e.fDeparture, e.fArrival} | e in set aSetOfFare} and
forall wFareRecord1, wFareRecord2 in set aSetOfFare &
wFareRecord1.fDeparture = wFareRecord2.fDeparture and
wFareRecord1.fArrival = wFareRecord2.fArrival =>
wFareRecord1.fFare = wFareRecord2.fFare
post
exists1 wFareRecord in set aSetOfFare &
{aDeparture, anArrival} = {wFareRecord.fDeparture, wFareRecord.fArrival} and
RESULT = wFareRecord.fFare;

end fareCaculate

3.测试



现在编写测试程序对上述需求进行测试。测试程序如下所示:

class Test is subclass of fareCaculate

values vFareSet = {
    mk_FareRecord("Tokyo","Shinagawa",220),
    mk_FareRecord("Tokyo","Shinjuku",180),
    mk_FareRecord("Shinjuku","Shinagawa",190)
};

functions
static public makeOrderMap : seq of bool +> map nat to bool
makeOrderMap(s) == {i |-> s(i) | i in set inds s};
public run : () -> seq of char * bool * map nat to bool
run() ==
let testcases = [t1(), t2(), t3()],
testResults = makeOrderMap(testcases)
in
mk_("The result of regression test = ",
forall i in set inds testcases & testcases(i), testResults);

public t1 : () -> bool
t1() ==
Calculate_fare(vFareSet, "Tokyo", "Shinagawa") = 220;
public t2 : () -> bool
t2() ==
Calculate_fare(vFareSet, "Tokyo", "Shinjuku") = 180;
public t3 : () -> bool
t3() ==
Calculate_fare(vFareSet, "Shinjuku", "Shinagawa") = 190;
end Test

测试结果如图所示:

测试全部返回true,表明需求定义正确。

至此,第一版的的铁路票价计算需求定义程序完成。

时间: 2024-07-28 12:58:52

【形式化方法:VDM++系列】4.VDM实战1——铁路费用计算的相关文章

【形式化方法:VDM++系列】3.基于VDM++的图书管理系统需求定义

接前文:http://www.cnblogs.com/Kassadin/p/4091040.html 1.Before We Start: 在开始图书管理系统需求定义之前,需要先进行一些说明. 1.1 输入,输出定义 输入:用户需求文字说明 输出:基于VDM++的需求规格说明文档 任何问题只有明确它的输入和输出,才会有一个明确的预期,才有可能获得预期的结果.在这里明确问题的输入输出更加重要.特别需要指出的是,VDM++作为一种形式化方法语言,它主要用于需求分析,而不是代码实现.虽然它的产出是一段

【形式化方法:VDM++系列】1.前言

1.前言 今天开始上课学习软件需求分析与VDM++,经过一节课的学习,我又增长了见识. 软件需求工程在软件工程中处于十分核心的地位:需求分析的好坏直接决定软件工程的成败.这一点是我之前对需求工程的理解和认识,然而今天的学习又进一步扩展了我的认识. 2.需求分析的发展阶段 说起需求分析,首先想到的是用例,然后就是各种各样的用例图,功能描述:接下来我会想到产品原型,业务流程描述等等:然而这些其实都只是需求工程的某一阶段的一小部分.实际上,需求分析大致可划分为以下3个阶段: (1)上世纪70年代兴起的

【形式化方法:VDM++系列】2.VDMTools环境的搭建

接前文:http://www.cnblogs.com/Kassadin/p/3975853.html 上次讲了软件需求分析的演化过程,本次进入正题——VDM开发环境的搭建 (自从发现能打游戏以来,居然有将近1个月没有写博客了!真是越来越颓废了..) 其实VDM++已经学习了很多,近几天应该会逐渐更新. 1.VDM开发环境介绍 需要使用的环境主要有2个:(1)VDMTools (2)Overture Tool 官方网站:[VDMTools]http://www.vdmtools.jp/en/ [O

《软件工程 ——理论、方法与实践》知识概括第五章 软件工程中的形式化方法

第5章 软件工程中的形式化方法    从广义上讲,形式化方法(Formal Method)是指将离散数学的方法用于解决软件工程领域的问题,主要包括建立精确的数学模型以及对模型的分析活动.狭义的讲,形式化方法是运用形式化语言,进行形式化的规格描述.模型推理和验证的方法.将形式化方法运用于软件工程实践当中的只要目的是保证软件的正确性. 软件生命周期中的形式化转化策略:常用转化策略.直接转化策略和运用半形式化表示的中间转化策略. 进行模型化的过程中涉及到三种系统模型:现实世界.模型表示和计算机系统.

软件工程——理论、方法与实践 之 软件工程中的形式化方法

软件工程——理论.方法与实践 之 软件工程中的形式化方法 从广义上讲,形式化方法是指将离散数学的方法用于解决软件工程领域的问题,主要包括建立精确的数学模型以及对模型的分析活动.狭义的讲,形式化方法是运用形式化语言,进行形式化的规格描述.模型推理和验证的方法.形式化方法运用于软件工程实践当中主要目的是保证软件的正确性.软件开发实际上就是把现实世界的需求映射成软件额模型化过程.该过程包括:形式规约.形式证明我与检验.程序求精三方面的活动. 形式化规格说明是对软件系统对象,对象的操作方法,以及对象行为

软件工程中的形式化方法

软件的设计过程就是一个建立形式规约的过程.软件开发实际上就是把现实世界的需求映射成软件的模型化方法.软件规格说明是对软件系统对象,对象的操作方法,以及对象行为的描述.形式证明与验证技术主要包括模型检测和定理证明.程序求精是将自动推理和形式化方法相结合,从抽象的形式规约推演出具体的面向计算机的程序代码的全过程.模态(Modal)逻辑是经典命题逻辑和一阶谓词逻辑的扩展形式.Kripke结构.1.一阶线性时态逻辑(FOLTL)是一阶谓词逻辑的扩展.2.计算树逻辑(CTL)是一种离散.分支时间.命题时态

软件工程中的形式化方法读后感

形式化方法是指将离散数学的方法用于解决软件工程领域的问题,主要包括建立精确的数学模型以及对模型的分析活动.狭义的讲,形式化方法是运用形式化语言,进行形式化的规格描述.模型推理和验证的方法.形式化方法运用于软件工程实践当中主要目的是保证软件的正确性.软件开发实际上就是把现实世界的需求映射成软件额模型化过程.该过程包括:形式规约.形式证明我与检验.程序求精三方面的活动. 其通过模态来对可能世界中的命题进行描述与演算,分为:Kripke结构..一阶线性时态逻辑..计算树逻辑.模型的三个主要组成部分是输

软件工程概论第五章--软件工程中的形式化方法

形式化方法指的是将离散数学的方法用于解决软件工程领域的问题,主要是建立精确的数学模型以及对模型的分析活动.在软件开发过程中运用数学模型有很多优点,例如能够解决规格说明的二义性,提高精确性,还能使软件相关问题的本质可以在不同抽象层次被展示出来.本章介绍形式化方法主要从形式化方法基本概念.时态逻辑.模型检验.Z语言.Petri网几个方面讲述. 形式化方法基本概念主要讲了形式规范.形式证明与验证.程序求精,形式规范说明是对软件系统对象,对象的操作方法,以及对象行为的描述.形式证明与验证主要包括模型检测

第五章、软件过程中的形式化方法

1. 广义上讲,形式化方法是指将离散数学中的方法用于解决软件工程领域的问题. 狭义上讲.形式化方法是运用形式化语言进行形式化的规格描述,模型推理和验证的方法.        形式化的方法运用于软件工程的目的主要是为了确保软件的正确性.