15、行为建模与验证:以BART系统为例的深入剖析

行为建模与验证:以BART系统为例的深入剖析

1. 数据决策图(DDD)的实现

在处理数据决策图(DDD)的面向对象编程中,需要一个类层次结构来将DDD的数学概念、集合运算符、连接、同态和归纳同态进行转换。通过定义三个类(DDD、Hom和InductiveHom),提供了构建和处理DDD及同态的所有方法。为了设计一个易于使用的库接口,采用了C++重载运算符,以实现最直观的接口。

从理论角度看,归纳同态Φ由DDD Φ(1)和同态族Φ(e, x)定义。归纳同态具有共同的评估方法,因此定义了一个名为InductiveHom的类,其中包含归纳同态评估方法,并以抽象方法的形式给出归纳同态的组件:Φ(1)和Φ(e, x)。要构建归纳同态,只需定义InductiveHom类的派生类,实现抽象方法Φ(1)和Φ(e, x)即可。

接口的实现基于以下三个单元:
- DDD管理单元 :借助哈希表技术,实现内存共享,并保证DDD树结构的唯一性。
- HOM管理单元 :管理与同态相关的数据和评估方法。同样,通过哈希表保证同态的语法唯一性。使用派生类的概念来表示各种同态类型。
- 计算单元 :提供对DDD操作的评估,以及通过同态计算DDD的图像。为了加速这些计算,该单元使用操作缓存,避免在计算过程中对同一表达式进行两次评估。使用缓存结果可将集合操作的复杂度降低到多项式时间。由于归纳同态是用户定义的,无法表达其复杂度。

2. BART案例研究的输入
2.1 铁路系统模型

研究聚焦于单条铁路线上列车的行为。该线路非环形,有起点和终点,列车总是从起点进入,从终点离开,不考虑在其他点进出线路的可能性。因此,考虑的是不与其他线路共享任何部分的单向线路。对于双向线路,可以用两条单向线路来考虑,并连接这些双向线路以考虑共享路段,此时需要考虑新的进出线路策略。线路连接多个车站,列车必须在这些车站停车。线路和列车的物理特性已知,并使用模拟模型来表示,该模型可根据列车的当前位置、速度和特性计算可能的加速和减速。

2.2 UML模型

根据上述假设,提出了一个架构,首先使用UML类图进行草图设计,其中包含7个类:
- Extern data :存储现实世界的模拟模型,通过应用程序编程接口为其他类提供信息,用于生成决策所需的数据。
- Operator :代表启动系统的操作员,可以将系统设置为警报模式(所有列车必须停车),并将系统恢复到正常模式(列车可以运行)。
- Line Manager :管理一条线路,允许列车进入并确认列车离开轨道。
- Train :代表每列火车上的控制器,与处理运动控制和碰撞检查的监视器进行通信。
- Move controller :确保列车向前行驶并在车站停车。
- Anti collision system :检查当前情况是否会导致与前方列车发生碰撞,检测到紧急情况时指示Move controller,迫使列车停车。
- Comm :代表通信系统,有自己的寻址机制,为系统的任何组件(Extern data除外)分配唯一地址,处理所有类之间的通信(Extern data除外)。

以下是UML类图中各类之间的关系:
| 类名 | 关联类 | 关联关系 |
| ---- | ---- | ---- |
| Extern data | 无 | 提供数据给其他类 |
| Operator | 无 | 控制整个系统的模式 |
| Line Manager | Train | 允许列车进入和离开 |
| Train | Move controller, Anti collision system | 通信 |
| Move controller | Train | 控制列车运动 |
| Anti collision system | Train | 检查碰撞 |
| Comm | 其他类(除Extern data) | 处理通信 |

2.3 组件及其交互的规范
  • 组件 :Line Manager在线路起点添加列车,在列车到达终点时移除列车。当手动警报响起时,它会提醒列车(所有列车必须停车),并在警报结束时通知列车(系统可以重启)。Line Manager是唯一与所有其他组件通信的组件。每列火车都关联一个Move controller和一个Anti collision system。Move controller根据列车的位置、速度和到下一站的距离管理列车的运动。Anti collision system确保列车与轨道上的前一辆列车之间保持安全距离,检测到紧急情况时指示Move controller,迫使列车停车。每列火车中的嵌入式计算器根据Move controller的决策更新速度和位置。
  • 组件的激活 :考虑交错执行语义,在给定步骤中,只有一个组件执行一个动作。考虑所有可能的动作交错,研究所有可能的执行情况。列车及其关联组件(Anti collision system和Move controller的相应实例)在无限循环中执行。循环的一步在一个时间单位内执行,动作按以下顺序执行:
    1. Move controller通知计算器要应用于列车的速度修改。
    2. 计算器计算新的速度和位置,并将其传输给Move controller和Anti collision system。
    3. Anti collision system检查是否可能发生碰撞(即列车与前一辆列车是否太近,是否需要紧急停车)。
    4. 当检测到问题时,组件执行以下操作:
      • Anti collision system将问题通知Move controller。
      • Move controller命令Train立即停车。
      • Train尽快停车。
  • 组件的通信 :为了独立于位置约束,考虑将地址分配给进程而不是其物理位置的通信服务。对于管理列车监控的进程与列车本身之间的通信,需要为列车(计算器)、Move controller和Anti collision system分配地址。无论它们的物理位置如何,通信服务确保其地址不变。因此,Move controller和Anti collision system可以从一个中心迁移到另一个中心。假设通信既安全(不丢失消息)又快速,相对于要执行的动作而言。
2.4 系统的属性

系统必须验证以下关键属性:
- 每列火车在每个车站停车。
- 列车在指定条件下启动。
- 不可能发生碰撞。
- 遵守铁路各路段的速度限制。
- 资源足以确保系统的正确执行。

此外,还考虑了一些附加属性:
- 不会出现死锁情况。
- 同步和异步通信正确执行。
- 紧急情况得到正确处理。
- 列车在线路上的插入和移除顺序正确。

一旦完成可达状态的计算,就可以通过实现同态来验证相应的断言,从而验证这些属性。

3. 将方法应用于案例研究
3.1 LfP图

本节介绍描述BART系统的LfP图。完整模型过于复杂,这里选择了几个相关的图,从建模和分析的角度展示LfP的特点。
- 架构图 :图6.13展示了从图6.12的UML类图推导而来的LfP架构图。从UML图到LfP图的转换展示了如何解决一些UML问题。在图6.12中,通信系统使用类进行建模,而在LfP中,将其作为LfP媒体。与Extern data相关的关系也存在类似问题,UML中未明确说明通信机制,而LfP需要一个媒体(内联访问)。
- 声明部分
- 声明了一组常量,可在模型的任何地方使用,便于轻松更改某些参数。
- 声明了几种类型,可在模型的任何地方使用。
- LfP允许类和媒体的静态和动态实例化。Operator和Extern data是系统中唯一静态实例化的类,在这两种情况下,都不提供上下文,使用局部变量的默认值。内联访问也静态实例化,但Comm实例根据通过绑定器m out相关的类动态创建。因此,表达了一种明确的关联:每个Comm实例与Train、Anti collision system、Move controller或Line Manager类的给定实例相关联,并对其相关通道进行建模。
- 还表达了绑定器的特性:其大小和行为。绑定器以无特定顺序存储和读取消息。

以下是LfP架构图的部分代码:

-- Constants
define max_speed = 100;
define max_position = 100000;
define max_distance = 10000;
define max_train = 40;
define max_adr = max_train * 3;
define no_adr = 0;
define adr_lnmgr = 0;
-- Types
type t_speed is range 0 .. max_speed;
type t_position is range 0 .. max_position;
type t_distance is range -1 .. max_distance;
type t_trainid is circular
               range 0 .. max_train;
type t_adr is circular range 0 .. max_reg;
--Declaration of static classes instances
Operator : 1 with ();
Extern_data : 1 with ();
-- Declaration media instances
Inline_access : 1 with ();
Comm : using_binder out;
--Characteristics of binders
Inline_access: (server => 0, blocking, fifo,
                client => 0, blocking, fifo);
Comm: (r   => 0, blocking, fifo
       u   => 0, blocking, fifo
       in  => 5, blocking, bag
       out => 5, blocking, bag);
3.2 类Train

Train类的行为契约如图6.14所示。当创建Train实例时,它从begin状态开始,并自动进入线路的起点(触发in line)。在ready状态下,列车速度为0,位置设置为出发站的位置。由于列车必须始终能够处理get pos请求,因此该方法可以从所有运行状态(ready、moving和stopped)触发。输入弧中的值始终为该方法赋予最高优先级。

要离开ready状态,Train实例必须执行start方法,将当前速度设置为最小可能值,然后进入moving状态。除get pos外的所有方法具有相同的优先级(输入弧值为2)。accelerate方法在列车允许增加速度时触发(未达到速度限制且前方列车或车站前有足够空间让列车停车)。stable方法在达到速度限制但无需列车停车时激活。decelerate和fast decelerate的主要区别在于应用于列车的减速因子:decelerate对应于“正常”制动,而fast decelerate不考虑乘客舒适度和设备压力。

要离开moving状态,必须执行stop方法,该方法只有在当前速度设置为最小可能值时才能激活。当列车停车时,如果其位置对应于线路上的最后一站,可以退出线路(触发exit line),或者执行trigger check(确保没有乘客挡住车门)以返回可以移动到下一站的状态。

以下是Train类的部分代码:

-- Prototypes
procedure start (s:inout t_speed; p:inout t_position);
procedure stable (s:inout t_speed; p:inout t_position);
procedure decelerate (s:inout t_speed; p:inout t_position);
procedure fast_decelerate (s:inout t_speed; p:inout t_position);
procedure stop (s:inout t_speed; p:inout t_position);
procedure get_pos (p:inout t_position);
trigger in_line();
trigger check ();
trigger exit_line();
-- Instance variables
s : t_speed := 0;
p : t_position := 0;
t : t_trainid := 0;
mr, ar, oar : t_adr;
3.3 媒体Generic addressed comm

还展示了用于支持系统中所有类之间交互的通用通信媒体(图6.18)。如架构图所示,它有四个端口:reg为媒体实例分配地址,ureg释放地址并激活媒体实例的销毁,m in向媒体发送消息,m out从媒体检索消息。消息存储在变量stored m中。

当创建Comm实例时,它等待一个地址,该地址将用于选择要存储的消息(并由适当的客户端检索)。然后它进入ready状态,如果transition I触发,则可以插入消息(保护条件确保消息判别符等于与媒体实例关联的地址)。transition O从变量stored m中提取消息(如果该变量为空,则保护条件阻止)。当U触发时,媒体进入purge状态,在实例终止(transition terminate)之前,移除输入绑定器中剩余的所有消息(transition D)。

以下是媒体Comm的部分代码:

-- Media types
type set_msg is set of message_structure;
Type set_adr is set of t_adr_m;
-- Media variables
me : t_adr_m := in_adr;
stored_m : set_msg;
shared ext_adr : set_adr;
4. 使用DDD进行状态空间计算
4.1 基于DDD结构的状态编码

可达状态的计算需要状态的规范表示,以实现高效比较。同时,需要能够添加状态而不产生歧义。通过一些简单的原则,可以确保尽管状态具有动态特性,但不会出现歧义。
- 排序 :为了获得规范表示,关键是状态及其所有内部组件都按照定义的确定性顺序构建在组成DDD的赋值集(变量 := 值)上。例如,为了表示数据集,定义一个单一变量,为集合中的每个元素赋予不同的值。第一个值始终给出集合的大小。此外,对值进行排序。这样,两个集合的比较就变成了两个相应DDD的简单比较,无需使用复杂的算法。BART的状态由嵌套块组成,每个块的内容和在DDD中的位置都是确定性定义的。这种顺序定义了状态在所有嵌套级别上的语法。这种确定性顺序还有利于内存重用,库支持DDD结构中相同部分的共享。
- 动态性带来的问题 :在定义了赋值序列的确定性顺序后,为了计算可达状态集,需要能够添加所有状态而不产生歧义。避免的典型情况如图6.19所示。当状态静态定义且变量按确定性顺序排列时,这种歧义很容易解决。然而,当状态中存储的数据大小可以在DDD的任何位置动态变化时,歧义很可能发生,并且 + 操作将与状态的定义失去兼容性。

为了避免这个问题,在通过DDD表示动态结构时应用了以下准则:
- 每个大小可变的块必须以一个相同的变量作为前缀,该变量将包含一个不同的值,该值应取决于结构的大小和/或类型。
- 基本结构(如绑定器、集合、数组、向量或多重集)的实例由一个变量标识。这个相同的变量用于标识结构的元素。
- 由标量和/或基本结构组成的状态使用不同的变量,并且必须按照共同的唯一顺序构建。

动态块的前缀起到哨兵的作用,确保在所考虑的块级别不会出现歧义。如果块的大小不同,则在第一个变量处进行区分;如果仅值不同,则在块内部进行区分。例如,多重集结构总是以多重集的大小开头。图6.20和图6.21展示了表示多重集的两个DDD相加的两种情况。

4.2 BART状态的结构

本节介绍通过DDD对BART状态进行编码。使用lfp程序的状态描述,状态具有以下动态特性:
- 实例数量可变(Train、Anticollision System、Move Controller及其关联的媒体)。
- 实例支持栈操作,即传递参数、插入/删除局部变量和程序计数器PC的返回值。
- 全局绑定器在状态开始时的全局区域存储消息多重集。
- 局部绑定器存储接收到的消息,并与每个实例关联。
- 多重集实例变量存储地址。
- 消息是数据向量,其长度取决于消息类型。

在层次结构的顶部,BART状态的不同组件按以下顺序出现:
- 全局变量
- 全局绑定器(binder all)
- 实例
- 状态结束(特殊标记)

所有实例具有以下相同的结构:
- 实例开始(特殊标记)
- 局部媒体
- 局部绑定器
- 实例变量
- 程序计数器(PC)
- 栈(如果不在调用中则为空)
- 实例结束标记

局部媒体的结构很简单:
- 媒体ID(变量me)
- 消息存储(向量的多重集)
- 程序计数器(PC)

压入栈的块具有以下形状:
- 参数
- 局部变量
- PC的返回值

变量和结构的顺序是为了节省对状态的昂贵探索而选择的。数据分析有助于确定最佳的探索方向,从而确定变量在状态中出现的顺序。

实例按类分组并按以下顺序排列:
- Line Manager的实例
- Train类的实例
- Move Controller类的实例
- Anticollision System类的实例
- Operator的实例

与上述每个项目对应的是状态的一部分。构建状态的DDD包括将所有部分连接在一起。状态的语法被定义为允许在不改变实现模型的同态的情况下轻松更改类的顺序。在计算可达状态时,很难预先确定哪种顺序会带来更好的性能。一些实验可以帮助确定最佳顺序。

需要注意的是,在同一类的一组实例中没有定义顺序。由于顺序依赖于插入时未知的值,因此很难实现。但这在状态相加时不会造成问题,因为同一类的所有实例具有相同的结构。然而,这可能会导致表示的规范性问题。解决这个问题需要实现重新排序同态,假设可以在异构结构上找到全序,在BART中就是这种情况。

状态实现方面,DDD的变量由整数值标识,变量的值也是整数类型。为了帮助调试和编写高效的同态,定义了类型。这些类型嵌入在变量标识符的编码中:
- 变量(局部和全局)
- 程序计数器(PC)
- 变量块
- 数组
- 多重集
- 绑定器(局部和全局)
- 媒体
- 实例
- 标记

在同态代码中,可以使用掩码操作直接测试变量的类型。消息由一系列赋值定义,如图6.22所示。这些值表示消息的长度、目的地、操作码和参数。由于消息是使用宿主实例(绑定器或多重集)的变量构建的,因此没有定义消息类型。

多个C++类允许为各种类型的结构生成DDD。与每种类型的实例对应的类是从上述类派生而来的。这些类包含在DDD中出现的实例变量的显式列表。因此,在编写同态时,可以轻松引用特定的变量。一个主类包含所有组件,并允许生成整个BART状态。

4.3 同态

通过DDD验证LfP模型需要定义表示LfP操作语义的同态。需要同态来识别所有启用的转换,以便计算每个转换执行后获得的新状态集。
- 基本同态 :开发了一组基本同态来操作状态。这些低级同态用于实现消息传输、预条件评估和转换触发。为了实现实例之间的通信,实现了以下同态:
- 从全局绑定器到媒体的消息传输
- 从媒体到局部绑定器的消息传输
- 从实例到全局绑定器的消息传输
- 从局部绑定器到实例的消息传输

为了实现转换的触发,实现了以下同态:
- 栈操作
- 标量和数组的赋值
- 多重集的基本操作
- 使用消息参数的赋值
- 预条件评估(表达式评估)

大多数转换t通过两个同态实现:Test transition(t)将返回包含满足预条件的状态的DDD,Fire transition(t)将返回触发转换t后获得的DDD。可达状态集的计算通过一个循环进行,该循环评估每个转换的预条件。如果关联的DDD等于已经构建的DDD,则停止对一组状态的执行研究。研究转换的顺序允许考虑LfP中表达的转换之间的优先级。
- 预条件评估和触发 :状态可能包含同一类的多个实例。预条件评估同态(Test - transition(t))识别并标记给定转换的合格实例。如果关联的实例满足所研究转换的预条件,则表示标记的变量设置为1。如果多个实例可以执行相同的转换,则同态为每个相关实例生成一个状态,并将相应的标记设置为1。实现实际转换触发的同态(Fire - transition(t))必须找到值为1的标记,并根据转换的效果修改状态。这样的同态由前面在5.3中描述的基本同态组成。

当转换附加优先级时,预条件评估的复杂度会增加。这些转换的预条件还可能取决于局部绑定器中消息的存在和/或保护条件。保护条件是一个逻辑表达式,可能取决于全局变量和实例变量。可以使用同态上的运算符组合来实现具有优先级的选择。图6.23所示的算法展示了如何实现它们。

Select(T1, ... Tn) sorted by decreasing priority:
    currentpriority=priority(T1)
    test=null
    dddin=input_states
    foreach Ti in (T1, ... Tn)
        test_i=Test_transition(Ti)(dddin)
        test=test+test_i;
        result=result+Fire_transition(Ti)(test_i)
        if (priority(Ti)<currentpriority)
            dddin=dddin-test
            currentpriority=priority(Ti)

这种解决方案的优点是简单。然而,在复杂的替代方案中,对不同转换的连续评估(意味着对状态进行多次探索)的成本可能过高。不过,通过性能分析,检测瓶颈可以帮助确定哪些同态需要优化。

4.4 示例

这个示例详细说明了处理Train类中start和get pos方法开始情况所需的同态。这些方法可以从ready状态调用,并且需要分别接收train.start和train.get pos消息。transition b get pos的优先级(1)高于transition b start(2)。

基于这个示例,提出了两种不同策略的实现:
- 第一种实现 :依赖于图6.23中提出的算法。在这种情况下,只需要四个同态:
- b get pos的预条件评估 :过滤出Train类的实例处于ready状态(PC == ready)且局部绑定器中至少有一个train.get pos消息的状态。
- b start的预条件评估 :过滤出Train类的实例处于ready状态、实例变量Train.s == 0(无速度)且局部绑定器中至少有一个train.start消息的状态。
- b get pos的触发 :该同态以b get pos的预条件评估输出为输入,并执行以下操作。如果绑定器中有多个train.get pos消息,将为每个消息生成一个状态,并消耗相应的消息。对于每个新状态,将get pos方法的局部变量和PC的返回值压入栈中,将PC设置为get pos方法中的下一个状态。
- b start的触发 :该同态以b start的预条件评估输出为输入。如果绑定器中有多个train.start消息,将为每个消息生成一个状态,并消耗相应的消息。对于每个新状态,将start方法的局部变量和PC的返回值压入栈中,将PC设置为start方法中的下一个状态。

然后可以应用图6.23中的算法来实现分支。进行预条件评估的同态需要应用两次:一次用于实现测试(Test transition(Ti)),一次与触发同态组合以实现Fire transition(Ti)同态。

  • 第二种实现 :具有优先级的转换触发算法将输入状态集分解为满足每个优先级的预条件的状态集。这意味着预条件的评估必须进行两次:一次用于找到给定优先级的状态,以便从输入集中减去这些状态,一次用于触发转换。这种第二种方法通过一个同态实现整个替代方案,该同态同时考虑替代方案的所有优先级。一旦预条件无效,负责评估的同态必须返回null,以使正在构建的状态无效。探索状态的同态会创建新状态,并继续探索这些新状态,以寻找潜在的有效预条件。一旦有足够的信息使正在研究的预条件无效,所有探索都将被丢弃。无效条件包括:局部绑定器中没有所需的消息、保护条件不满足、优先级不够高。

以下步骤展示了如何在两次探索中实现这样的替代方案:
1. 步骤1 :标记状态中处于ready状态的所有Train类实例,并生成状态,以便每个新状态中只有一个标记设置。这一步需要扫描Train类的所有实例,如图6.24所示。这是一个基本的同态,应用于所有涉及逻辑表达式的预条件评估情况。这构成了对整个状态的第一次探索。
2. 步骤2和3 :步骤2和3是链式的,构成了对状态的第二次遍历。
- 步骤2 :从步骤1的输出开始,探索直到找到标记实例的局部绑定器,取消标记该实例,为局部绑定器中包含的每个消息生成一个状态。消息附加到每个生成状态的探索中,并从局部绑定器中消耗。图6.25展示了局部绑定器中有两条消息的情况。这些消息启用了所考虑的两个分支的触发。需要进行保护条件评估和优先级判断,以确定哪些状态是有效的。为每个考虑的消息创建一个状态,并在每个新状态中继续探索局部绑定器。每个新状态都需要从这一点开始进行探索,以确定它是否有效,即是否满足所有预条件。任何不满足预条件的消息都不被考虑。
- 步骤3 :这一步直接在步骤2中对局部绑定器的探索结束后进行。获取实例变量并评估附加到分支的保护条件。如果在步骤2中附加消息的预条件评估为正,并且相应的分支在其他有效分支中具有最高优先级,则状态有效,相应的转换可以触发。如果使用其他消息的其他预条件评估具有更高的优先级,则状态被丢弃,并通过返回空同态自动移除。图6.26展示了所有预条件都满足的情况。最后,只有优先级将决定哪些状态将存活,哪些状态将消失。

4.5 公平性

在实现中,公平性问题通过计算可达状态的算法来解决。在Bart的lfp模型中,时间没有表示,会计算出逻辑上正确但物理上不可能的可达状态。为了弥补这种计算状态的过量,并确保所有列车得到平等对待,决定将转换集分为两组:
- 涉及实时的转换,即对系统进行物理更改的转换,在本例中是列车位置的同时修改。
- 其他转换。

这种解决方案避免了使用全局时钟变量,否则会导致新状态的无休止计算。它允许在计算可达状态的方法上有一定的灵活性,而转换集的划分留给用户。

可达状态计算算法将从列车的当前位置计算所有可达状态,并忽略所有影响列车物理状态的转换。一旦计算出所有状态,就会在累积状态集上检查位置修改转换。只要可以产生新状态,就应用这些转换。然后,选择反映所有列车同时更新的状态用于下一次迭代。这个过滤过程对于避免考虑列车在不同时间的位置而生成无用状态至关重要。

以下是可达状态计算的算法:

dddin : DDD representing the initial state
T1 : All transitions except the transitions of T2
T2 : All transitions updating the position of a train
NewStates : DDD containning intermediate states computed
during an iteration
AccStates : Accumulated states
NewStates=dddin;
AccStates=null;
while (making_progress)
    making_progress=true;
    // compute intermediate states
    While(making_progress){
        NewStates=Apply_All_Transition(T1, NewStates, making_progress);
    }
    OldAccStates=AccStates;
    AccStates=AccStates+NewStates;
    making_progress=true;
    // update position of trains
    While(making_progress){
        NewStates=Apply_All_Transition(T2, NewStates, making_progress);
    }
    AccStates=AccStates+NewStates;
    // discard all states that do not update all train position
    NewStates=Filter(NewStates);
    making_progress=true;
    if (AccStates==OldAccStates) making_progress=false;
4.6 评估

模型的实现需要实现一百多个转换,并对一个可能包含最多(6×t + 4)个进程的状态进行详细计算,其中t是列车的最大数量。

  • 状态空间计算 :为了检查参数对结果大小的影响,使用不同的参数执行了状态空间计算。实验在一台2.2 GHz的奔腾4机器上进行,内存为512M。为了使结果适合可用内存,对模型添加了两个额外的假设:
    • 假设H1 :假设在更新列车位置之前,处理媒体与其关联实例之间的所有本地通信。这允许丢弃可能导致移动控制器做出错误决策的延迟异步通知消息的情况。这些特定情况可以在单独的实验中进行研究。这个假设比较弱,因为延迟消息可以被视为无效。包含在H1中的另一个假设是:LineManager只在列车位置更新前后尝试在铁路上插入下一辆列车。插入操作需要一个短的触发序列,不能与这些更新交错。同样,一个单独的实验可以研究列车插入和位置更新交错的影响。
    • 假设H2 :比H1更强,假设除了H1之外,在更新列车位置时,任何存储(绑定器、媒体、本地绑定器)中都没有消息。这个假设更强,限制了计算状态的数量,因为它也影响全局绑定器。它完全将模型与列车的物理表示分离,并产生人为的约束。结果显示了这个假设的影响,即使全局绑定器的大小很小时也是如此。包含这样的强假设可以简化模型,并有助于调试过程,同时仍然覆盖模型中的所有转换。

所有执行都使用相同的铁路和列车模型。物理模型为列车生成6个位置,并至少有2种潜在的碰撞检测情况,导致处理紧急情况。以下表格总结了一些实验结果:

实验情况 全局绑定器大小 本地存储大小 累积状态数 状态最大长度 DDD大小(共享) DDD大小(无共享) 时间(秒)
1列车,H1 3 1 10606 118 8343 250405 11
1列车,H1 4 1 40099 124 18872 853917 27
1列车,H1 5 1 74440 130 29222 1.54e+06 46
1列车,H1 3 2 48237 121 10708 994775 17
1列车,H1 3 3 62068 121 11320 1.25e+06 21
1列车,H1 3 4 63706 121 11165 1.28e+06 21
2列车,H2 3 1 286339 182 101600 1.03e+07 1430
2列车,H2 4 1 335827 182 122403 1.24e+07 1874
2列车,H2 5 1 347075 182 134551 1.29e+07 2099
2列车,H2 3 2 363981 182 97713 1.29e+07 1379
2列车,H2 3 3 363981 182 97713 1.29e+07 1378
2列车,H2 3 4 363981 182 97713 1.29e+07 1379
2列车,H1 3 1 2572353 197 207273 7.61e+07 4023
2列车,H1 3 2 50765313 197 237542 1.13e+09 8152
2列车,H1 3 3 53812153 197 230360 1.21e+09 8313
2列车,H1 3 4 53887381 197 227043 1.21e+09 8283

结果表明,本地绑定器和媒体的容量影响有限。最重要的参数是列车数量、假设和全局绑定器的容量。需要注意的是,表6.3中的结果由于内存不足而受到限制。为了优化DDD库,正在进行一些额外的测试,以评估缓存和垃圾回收器的影响。

  • 使用DDD实现进行模型调试 :由于所有状态都通过DDD存储在内存中,可以通过编写同态并将其应用于DDD来检查属性。在实现过程中发现的属性或错误包括:
    • 覆盖整个模型所需的最小资源 :可达状态计算表明并确认全局绑定器的最小容量为3。如果容量小于3,模型将无法覆盖,所有转换都不会激活。
    • 不正确的规范 :对可达状态的检查显示了模型中的结构错误,如死锁情况、缺少确认消息和不正确的预条件。

综上所述,通过对BART系统的建模和验证,展示了使用DDD进行状态空间计算的方法和优势。通过合理的状态编码、同态定义和算法设计,可以有效地计算可达状态,并验证系统的关键属性。同时,实验结果为模型的优化和调试提供了有价值的信息。

行为建模与验证:以BART系统为例的深入剖析

5. 总结与展望

通过以上对BART系统的详细分析,我们全面了解了如何运用数据决策图(DDD)进行系统的行为建模与验证。下面对整个过程进行总结,并对未来的研究方向进行展望。

5.1 成果总结
  • DDD实现 :成功构建了用于处理DDD的类层次结构,通过DDD、Hom和InductiveHom三个类,实现了对DDD数学概念的有效转换。三个管理单元(DDD管理单元、HOM管理单元和计算单元)的设计,保证了内存共享、同态唯一性以及计算效率,为后续的状态空间计算奠定了基础。
  • BART系统建模 :从铁路系统模型出发,明确了系统的基本假设和物理特性。UML模型清晰地展示了系统的架构,包括各个类及其之间的关系。组件及其交互的规范详细描述了系统的运行机制,确保了系统的正常运行。同时,定义了系统必须验证的关键属性和附加属性,为系统的正确性提供了保障。
  • LfP图应用 :通过LfP架构图和行为契约,解决了UML模型中的一些问题,如通信系统和外部数据的表示。LfP允许类和媒体的静态和动态实例化,提供了更灵活的建模方式。
  • 状态空间计算 :基于DDD结构的状态编码,解决了状态表示的规范性和动态性问题。通过定义各种同态,实现了消息传输、预条件评估和转换触发等功能。示例展示了不同策略下的同态实现,体现了方法的灵活性。公平性算法的设计避免了不必要的状态计算,提高了计算效率。
  • 评估与调试 :状态空间计算的实验结果表明,列车数量、假设和全局绑定器容量是影响计算结果的重要因素。通过对可达状态的检查,发现并解决了模型中的一些问题,如资源不足和规范错误。
5.2 未来展望
  • 模型优化 :虽然通过添加假设简化了模型,但这些假设在一定程度上限制了模型的真实性。未来可以进一步研究如何在不牺牲计算效率的前提下,减少假设的使用,提高模型的准确性。
  • 算法改进 :目前的状态空间计算算法在处理复杂系统时可能会遇到性能瓶颈。可以探索更高效的算法,如并行计算或启发式搜索,以提高计算速度和扩展性。
  • 公平性增强 :当前的公平性算法通过区分实时和非实时转换来处理公平性问题,但在某些情况下可能不够完善。可以研究更精细的公平性策略,确保系统在各种情况下都能公平地处理列车。
  • 应用拓展 :本研究的方法可以应用于其他类似的嵌入式分布式系统,如航空交通管理、工业自动化等。未来可以将该方法推广到更多领域,验证其通用性和有效性。

以下是整个过程的mermaid流程图,展示了从系统建模到状态空间计算和评估的主要步骤:

graph LR
    A[系统建模] --> B[UML模型设计]
    B --> C[LfP图表示]
    C --> D[状态编码]
    D --> E[同态定义]
    E --> F[状态空间计算]
    F --> G[公平性处理]
    G --> H[评估与调试]
    H --> I[模型优化]
    I --> J[未来应用拓展]

通过对BART系统的研究,我们不仅掌握了一种有效的行为建模与验证方法,还为解决复杂系统的设计和分析问题提供了新的思路。未来的研究将继续深入探索,不断完善和拓展该方法的应用范围。

6. 相关技术对比

在系统建模和验证领域,除了本文使用的DDD方法,还有其他一些常见的技术。下面对这些技术进行简要对比,以便更好地理解DDD方法的优势和适用场景。

技术名称 优点 缺点 适用场景
DDD(数据决策图) 支持动态状态表示,通过哈希表和缓存提高计算效率,可实现状态共享;能有效处理复杂系统的状态空间计算 实现相对复杂,需要定义多个类和同态;对动态性的处理需要遵循一定规则 适用于嵌入式分布式系统,尤其是状态具有动态特性的系统
有限状态机(FSM) 简单直观,易于理解和实现;可以清晰地表示系统的状态转换 对于复杂系统,状态数量可能会急剧增加,导致模型难以管理;不适合处理动态状态 适用于状态较少、行为相对简单的系统
模型检查(Model Checking) 可以自动验证系统的属性,提供反例帮助调试;能够处理大规模系统 状态空间爆炸问题严重,对于复杂系统可能无法在合理时间内完成验证 适用于需要严格验证系统属性的场景,如安全关键系统
仿真技术 可以模拟系统的运行过程,直观地观察系统的行为;能够考虑系统的物理特性 结果的准确性依赖于模型的精度和参数设置;无法保证系统的正确性 适用于对系统性能和行为进行初步评估的场景

通过对比可以看出,DDD方法在处理复杂系统的动态状态和状态空间计算方面具有独特的优势。但在实际应用中,需要根据系统的特点和需求,选择合适的技术或结合多种技术进行系统的建模和验证。

7. 实际应用建议

如果要将本文介绍的方法应用到实际项目中,以下是一些建议:
- 需求分析 :在开始建模之前,充分了解系统的需求和特点,确定系统的关键属性和约束条件。这将有助于选择合适的建模方法和确定状态编码的方式。
- 状态编码设计 :根据系统的动态特性,设计合理的状态编码方案。确保状态的规范性和可比较性,避免动态性带来的歧义问题。可以参考本文中提出的排序和前缀原则。
- 同态定义 :根据系统的行为和转换规则,定义相应的同态。同态的设计要考虑到消息传输、预条件评估和转换触发等功能。在实现过程中,可以参考本文中的示例和算法。
- 实验与优化 :在计算状态空间时,进行不同参数的实验,观察结果的变化。根据实验结果,调整模型的假设和参数,优化计算效率。同时,通过对可达状态的检查,及时发现和解决模型中的问题。
- 团队协作 :建模和验证工作通常需要多个团队成员的协作。确保团队成员对方法和模型有共同的理解,加强沟通和协作,提高工作效率。

以下是一个简单的步骤列表,总结了实际应用的主要过程:
1. 进行系统需求分析
2. 设计状态编码方案
3. 定义同态
4. 进行状态空间计算实验
5. 根据实验结果优化模型
6. 检查可达状态,调试模型
7. 持续改进和完善模型

通过遵循这些建议和步骤,可以更有效地将DDD方法应用到实际项目中,提高系统的可靠性和正确性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值