PetriKit

入门指南

请注意,本教程假设您正在类 Unix 系统上使用 Swift 4。

安装 PetriKit

您可以使用 Swift Package Manager 来使用 PetriKit。 为您的应用程序创建一个空目录,打开其中的终端并创建一个新的 Swift 命令行工具。

mkdir /some/path/to/your/app
cd /some/path/to/your/app
swift package init --type executable

您需要将 PetriKit 作为依赖项添加到您的应用程序。 打开生成的文件 Package.swift 并按如下方式编辑其内容:

// swift-tools-version:4.2

import PackageDescription

let package = Package(
  name: "MyApp",
  dependencies: [
    .package(url: "https://github.com/kyouko-taiga/PetriKit.git", from: "2.0.0")
  ],
  targets: [
    .target(
      name: "MyApp",
      dependencies: ["PetriKit"]),
  ])

这将允许您在您的源代码中导入 PetriKit。 在 Sources/MyApp/main.swift 的开头添加以下语句:

import PetriKit

现在您可以使用 PetriKit 了。

创建 Place/Transition Net(库所/变迁网)

PetriKit 中的 Petri 网通过两种协议描述:Transition(变迁)和 PetriNet(Petri 网)。 这些协议仅描述了一种类型表示变迁(或 Petri 网)的最低要求。 它们可以被视为 Petri 网结构的抽象描述。 因此,它们不能直接使用,而应该针对特定类型的 Petri 网进行实现。

PetriKit 为 Place/Transition nets(库所/变迁网,或 P/T 网)提供了这样的实现。 它们是最简单的 Petri 网变体之一。 您可以按如下方式创建一个 P/T 网:

enum Place {
  case p0, p1
}

let t0 = PTTransition<Place>(
  named         : "t0",
  preconditions : [PTArc(place: .p0)],
  postconditions: [PTArc(place: .p1)])
let t1 = PTTransition<Place>(
  named         : "t1",
  preconditions : [PTArc(place: .p1)],
  postconditions: [PTArc(place: .p0)])

let pn = PTNet(transitions: [t0, t1])

上面的代码创建了一个由两个库所和两个变迁组成的 P/T 网 pn

模拟 Place/Transition Nets(库所/变迁网)

您可以按如下方式模拟变迁的激发:

let m = t0.fire(from: [.p0: 1, .p1: 1])

上面的代码将变迁 t0 从标志 [.p0: 1, .p1: 1](即每个库所一个 token)激发后获得的标志赋值给 m。 请注意,TransitionProtocol 协议的 fire(from:) 方法返回一个 optional。 这是因为如果给定标志下变迁不可激发,该方法应返回 nil

您还可以从给定的初始标志模拟 P/T 网的执行:

let m = pn.simulate(steps: 4, from: [.p0: 1, .p1: 0])

上面的代码模拟 4 步执行,每一步随机选择一个可激发的变迁,或者如果模拟达到死锁则提前停止。

可视化 Place/Transition Nets(库所/变迁网)

类型 PTNet 带有一个特殊方法 saveAsDot,它将给定的 P/T 网输出为 Graphviz 文件。 请注意,这需要您同时导入 Foundation 库。

import Foundation

// ...

try pn.saveAsDot(to: URL(fileURLWithPath: "pn.dot"), withMarking: [.p0: 1, .p1: 2])

上面的代码会将带有标志 [.p0: 1, .p1: 2] 的 P/T 网 pn 输出到名为 pn.dot 的文件中。