IMPのoperational semantics その3
これは一人Computer Scienceアドベントカレンダー 7日目の記事です。
前回はcommandとcommandの評価を定義した。
6. Coherent lemmas
SKIP
subsection {* Coherent lemmas *}
lemma coh_B_Skip:
assumes "<SKIP,st> ⇓ st'"
shows "st = st'"
using cbig.cases [OF assms] by auto
始めの補題はSKIPについてで、 <SKIP,st> ⇓ st'
ならば st = st'
というものである。
直観的には明らかであろうし、証明も場合分けをするだけで済む。
Ass
lemma coh_B_Ass:
assumes "<x ::= a , st> ⇓ st'"
shows "st' = st [x ↦ aeval st a]"
using cbig.cases [OF assms] by auto
次は変数への代入。これも簡単なので省略。
Seq
lemma coh_B_Seq:
assumes "<c1 ;; c2 , st> ⇓ st'"
obtains st'' where "<c1 , st> ⇓ st''" and "<c2 , st''> ⇓ st'"
<c1 ;; c2,st> ⇓ st'
ならば、 c1
を実行すると評価が停止し、さらにその後 c2
を実行すると st'
の状態になって評価が停止するということが言えるはずである。
上では後々の便利さのために obtains ... where ...
で補題を宣言しているが、証明は存在量化を使った命題を示すという感じでやる。
proof-
have "<c1 ;; c2 , st> ⇓ st' ⟹ ∃st''. (<c1 , st> ⇓ st'') ∧ (<c2 , st''> ⇓ st')"
by (erule cbig.cases, auto)
then obtain st'' where "<c1 , st> ⇓ st''" and "<c2 , st''> ⇓ st'"
by (simp add: assms, auto)
then show ?thesis
using that by blast
qed
証明の内容自体は場合分けくらいしかしてないのでよいと思う。
If
<IF b THEN c1 ELSE c2 , st> ⇓ st'
のときにst'がどうなるかは b
が何になるかによって変わるのでここでは2つ補題をおく。
lemma coh_B_IfTrue:
assumes "<IF b THEN c1 ELSE c2 , st> ⇓ st'"
and "beval st b = True"
shows "<c1 , st> ⇓ st'"
proof-
have "<IF b THEN c1 ELSE c2 , st> ⇓ st' ⟹ <c1,st> ⇓ st'"
apply (cases rule: cbig.cases, auto)
using assms(2) apply auto
done
then show ?thesis by (simp add: assms(1))
qed
lemma coh_B_IfFalse:
assumes "<IF b THEN c1 ELSE c2 , st> ⇓ st'"
and "beval st b = False"
shows "<c2 , st> ⇓ st'"
proof-
have "<IF b THEN c1 ELSE c2 , st> ⇓ st' ⟹ <c2,st> ⇓ st'"
apply (cases rule: cbig.cases, auto)
using assms(2) apply auto
done
then show ?thesis by (simp add: assms(1))
qed
見たままではあるが、bがtrueになるときはc1が実行され、bがfalseになるときはc2が実行される。
ところでbはboolではなくbexpだったので、場合分けは beval st b
によって行うことに注意。
While
さて最後にWHILEである。 WHILEもIFと同じく与えられた条件が成り立つかによって場合分けを行う。
lemma coh_B_WhileFalse:
assumes "beval st b = False"
and "<WHILE b DO c , st> ⇓ st'"
shows "st = st'"
proof-
have "<WHILE b DO c , st> ⇓ st' ⟹ st = st'"
apply (erule cbig.cases, auto)
apply (simp add: assms(1))
done
then show ?thesis by (simp add: assms(2))
qed
lemma coh_B_WhileStep:
assumes "beval st b = True"
and "<WHILE b DO c , st> ⇓ st''"
obtains "st'" where "<c,st> ⇓ st'" and "<WHILE b DO c , st'> ⇓ st''"
proof-
have "<WHILE b DO c , st> ⇓ st'' ⟹ ∃st'. (<c,st> ⇓ st') ∧ (<WHILE b DO c , st'> ⇓ st'')"
by (erule cbig.cases, auto simp add: assms(1))
then obtain "st'" where "<c,st> ⇓ st'" and "<WHILE b DO c , st'> ⇓ st''"
by (simp add: assms, auto)
then show ?thesis
using that by blast
qed
これも場合分けやるだけ。
7. Proof of Determinism
いよいよ目標だったcbigのDeterminismを示そう。
subsection {* Determinism *}
lemma cbig_deterministic: "⟦ <c,st> ⇓ st'; <c,st> ⇓ st'' ⟧ ⟹ st' = st''"
proof-
have "<c,st> ⇓ st' ⟹ (∀st''. (<c,st> ⇓ st'') ⟶ st' = st'')"
apply (induction rule: cbig.induct)
apply (simp add: coh_B_Skip)
apply (rule, rule) using coh_B_Ass apply auto[1]
apply (rule, rule, erule coh_B_Seq, simp)
using coh_B_IfTrue apply blast
using coh_B_IfFalse apply blast
apply (simp add: coh_B_WhileFalse)
by (metis coh_B_WhileStep)
then show "⟦ <c,st> ⇓ st'; <c,st> ⇓ st'' ⟧ ⟹ st' = st''"
by simp
qed
といっても証明自体は上で示した補題を使うだけなので簡単。 ちなみにこの証明は、inductionの行以外は全てsledgehammerで導出しているのでマウスでボタンをぽちぽちやっているだけで証明が終わる。
さて、上のcoherent lemmaでは場合分けしか行わなかったが、実際にこの補題は必要なのだろうか?と疑問に思うかもしれない。 やってみると分かるのだが、この証明を上のような補題なしで直接行うのはかなり困難である。caseによる場合分けが必要であることがわかっても、今示そうとしている命題はかなり複雑なので解の探索が上の補題に比べてずっと難しくなる。
補題をおくということは仮定を減らすことでもあり、本当に必要な仮定だけにしないと現実的な時間で探索が終わらないということはよくあるので、このように適切な補題をおくのは(証明が再利用できるだけでなく)大切なことである。
8. Small-step & Big-step
次に目標となる定理は次である。
theorem "<c,st> ⟶* <SKIP,st'> ⟷ <c,st> ⇓ st'"
これはsmall-stepとbig-stepの関係を表す定理である。
(ここで、 <c,st> ⟶* <SKIP,st'>
はcsmallを何回かしたやつ、みたいな意味で、まだ定義していないが下で定める。)
以下でこの定理を示していく。
まとめ
というところで今回はおしまい。
次回はこの、small-stepとbig-stepを関係づける定理を示してこのIMP編も終わりになります。