株式会社ジェーエフピー

Event-B

EVent-B

電気ポットの「企画要求仕様」(リスト1)を題材にします。以下の5項目の要求が書かれています。

リスト1 企画要求仕様

PR01: 電気ポットの容量は2リットルとし、10度Cから沸騰するまでの時間は、15分以内とする。
PR02: 電源コンセントをつなぐと、直ちに作動し、ヒータで加熱を始め、沸騰に達したら、90度Cに保温する。
PR03: 再沸騰ボタンが押されたら、再沸騰を始める。
PR04: 水が加えられ、温度が低下したら、再沸騰を始める。
PR05: 保温中であれば、お湯を注ぐことができる。

分析者は、5条項ポットの「企画要求仕様」を読んで、直接、Event-Bのモデルを書きました。まず、初期モデルのコンテキスト(リスト2)を書きました。「コンテキスト」とは、簡単に言うと、Event-Bのモデルで使用する定数を定義するところです。リスト2では「no_power_supply」「heat_until_boil」「keep_temperature」という3個の定数を定義しています。これらは、それぞれ、「電源が供給されていない」「沸騰するまで加熱する」「保温する」という、ポットの状態を表します。

リスト2 初期モデルのコンテキスト

CONTEXT
context_0 CONSTANTS
no_power_supply // 電源が供給されていない heat_until_boil // 沸騰するまで加熱する keep_temperature // 保温する set_of_modes // ポットのモードの集合 AXIOMS axm1 : no_power_supply = 0 axm2 : heat_until_boil = 1 axm3 : keep_temperature = 2 axm4 : set_of_modes = {no_power_supply, heat_until_boil, keep_temperature}
END

続いて、初期モデルのマシン(リスト3)を書きました。「マシン」とは、モデルの「動き」を定義するところです。具体的には、変数とイベントを定義します。

リスト3 初期モデルのマシン

MACHINE
machine_0 SEES
context_0 VARIABLES mode // ポットのモード INVARIANTS inv1 : mode ∈ set_of_modes EVENTS INITIALISATION ≙ // 初期状態を定義する。 STATUS ordinary BEGIN act1 : mode ≔ no_power_supply // 初期状態では電源が供給されていない。 END user_connects_power_plug ≙ // ユーザーが電源コンセントをつないだ。[PR02] STATUS ordinary WHEN grd1 : mode = no_power_supply // 電源が供給されていないとき。 THEN act1 : mode ≔ heat_until_boil // 沸騰するまで加熱する。[PR02] END
water_becomes_boil ≙ // 沸騰した。[PR02] STATUS ordinary WHEN grd1 : mode = heat_until_boil // ヒーターが加熱しているとき。 THEN act1 : mode ≔ keep_temperature // 90°Cに保温せよ。[PR02] END
user_pushes_boil_button ≙ // ユーザーが再沸騰ボタンを押した。[PR03] STATUS ordinary WHEN grd1 : mode = keep_temperature // 保温しているとき。もとの要求にはないが、このように推測できる。 THEN act1 : mode ≔ heat_until_boil // 再沸騰せよ。[PR03] END
user_pours_cold_water_into_pot ≙ // ユーザーがポットに水を注いだ。[PR04] STATUS ordinary WHEN grd1 : mode = keep_temperature // 保温しているとき。もとの要求にはないが、このように推測できる。 THEN act1 : mode ≔ heat_until_boil // 再沸騰せよ。[PR04] END user_requires_discharging_hot_water ≙ // ユーザーがポットにお湯を注ぐことを要求した。[PR05] STATUS ordinary WHEN grd1 : mode = keep_temperature // 保温中であれば [PR05] THEN skip END END

さらに、第1次精義化モデルのコンテキスト(リスト4)を書きました。精義化とは、refinementの(当社での)訳語です。

リスト4 第1次精義化モデルのコンテキスト

CONTEXT context_1 EXTENDS context_0 CONSTANTS capacity_of_pot // ポットの容量 [ml] start_volume // 水量の初期値 [ml] start_temperature // 水温の初期値 [°C] AXIOMS axm1 : capacity_of_pot = 2000 // ポットの容量は2000 mlである。[PR01] axm2 : 0 < start_volume // 初期の数量は0ではない。 axm3 : start_volume ≤ capacity_of_pot // 初期の水量はポットの容量以下である。 axm4 : 0 ≤ start_temperature // 初期の水温は0°C以上である。 axm5 : start_temperature < 100 // 初期の水温は沸騰していない。 END

最後に、第1次精義化モデルのマシン(リスト5)を書きました。

リスト5 第1次精義化モデルのマシン

MACHINE machine_1 REFINES machine_0 SEES context_1 VARIABLES mode volume // 水量 [ml] temperature // 水温 [°C] INVARIANTS inv1 : 0 ≤ volume // 水量は0以上である。 inv2 : volume ≤ capacity_of_pot // 水量はポットの容量以下である。 inv3 : 0 ≤ temperature // 水温は0°C以上である。 inv4 : temperature ≤ 100 // 水温は0°C以下である。 EVENTS INITIALISATION ≙ STATUS ordinary BEGIN act1 : volume ≙ start_volume // 水量の初期状態を設定する。 act2 : temperature ≙ start_temperature // 水温の初期状態を設定する。 END
user_connects_power_plug ≙ STATUS ordinary REFINES user_connects_power_plug WHEN grd1 : mode = no_power_supply THEN act1 : mode ≙ heat_until_boil END
water_becomes_boil ≙ STATUS ordinary REFINES water_becomes_boil WHEN grd1 : temperature = 100 // 水温が100°Cになった。(ただし、もとの要求からは読み取れない) grd2 : mode = heat_until_boil THEN act1 : mode ≙ keep_temperature END
user_pours_cold_water_into_pot ≙ STATUS ordinary REFINES user_pours_cold_water_into_pot WHEN grd1 : mode = keep_temperature grd2 : volume < capacity_of_pot grd3 : 0 < temperature THEN act1 : volume :≙ volume < volume' ∧ volume' ≤ capacity_of_pot act2 : temperature :≙ 0 ≤ temperature' ∧ temperature' < temperature act3 : mode ≙ heat_until_boil END
user_pushes_boil_button ≙ STATUS ordinary REFINES user_pushes_boil_button WHEN grd1 : mode = keep_temperature THEN act1 : mode ≙ heat_until_boil END
user_requires_discharging_hot_water ≙ STATUS ordinary REFINES user_requires_discharging_hot_water WHEN grd1 : mode = keep_temperature grd2 : 0 < volume THEN act1 : volume :≙ 0 ≤ volume' ∧ volume' < volume END
water_becomes_hotter ≙ STATUS ordinary WHEN grd1 : mode = heat_until_boil grd2 : temperature < 100 THEN act1 : temperature :≙ temperature < temperature' ∧ temperature' ≤ 100 END
water_becomes_cooler ≙ STATUS ordinary WHEN grd1 : mode = keep_temperature grd2 : 90 < temperature THEN act1 : temperature :≙ 90 ≤ temperature' ∧ temperature' < temperature END END

以上のEvent-Bのモデルは、5pot-eventb.zip [ZIP] を Rodin でインポートすると、モデルの正しさを証明することができます。