Theory WCFG

Up to index of Isabelle/HOL/Jinja/Slicing

theory WCFG
imports Com BasicDefs
header {* \isaheader{CFG} *}

theory WCFG imports Com "../Basic/BasicDefs" begin

subsection{* CFG nodes *}

datatype w_node = Node nat ("'('_ _ '_')")
| Entry ("'('_Entry'_')")
| Exit ("'('_Exit'_')")

fun label_incr :: "w_node => nat => w_node" ("_ ⊕ _" 60)
where "(_ l _) ⊕ i = (_ l + i _)"
| "(_Entry_) ⊕ i = (_Entry_)"
| "(_Exit_) ⊕ i = (_Exit_)"


lemma Exit_label_incr [dest]: "(_Exit_) = n ⊕ i ==> n = (_Exit_)"
by(cases n,auto)

lemma label_incr_Exit [dest]: "n ⊕ i = (_Exit_) ==> n = (_Exit_)"
by(cases n,auto)

lemma Entry_label_incr [dest]: "(_Entry_) = n ⊕ i ==> n = (_Entry_)"
by(cases n,auto)

lemma label_incr_Entry [dest]: "n ⊕ i = (_Entry_) ==> n = (_Entry_)"
by(cases n,auto)

lemma label_incr_inj:
"n ⊕ c = n' ⊕ c ==> n = n'"
by(cases n)(cases n',auto)+

lemma label_incr_simp:"n ⊕ i = m ⊕ (i + j) ==> n = m ⊕ j"
by(cases n,auto,cases m,auto)

lemma label_incr_simp_rev:"m ⊕ (j + i) = n ⊕ i ==> m ⊕ j = n"
by(cases n,auto,cases m,auto)

lemma label_incr_start_Node_smaller:
"(_ l _) = n ⊕ i ==> n = (_(l - i)_)"
by(cases n,auto)

lemma label_incr_ge:"(_ l _) = n ⊕ i ==> l ≥ i"
by(cases n) auto

lemma label_incr_0 [dest]:
"[|(_0_) = n ⊕ i; i > 0|] ==> False"
by(cases n) auto

lemma label_incr_0_rev [dest]:
"[|n ⊕ i = (_0_); i > 0|] ==> False"
by(cases n) auto

subsection{* CFG edges *}

type_synonym w_edge = "(w_node × state edge_kind × w_node)"

inductive While_CFG :: "cmd => w_node => state edge_kind => w_node => bool"
("_ \<turnstile> _ -_-> _")
where

WCFG_Entry_Exit:
"prog \<turnstile> (_Entry_) -(λs. False)\<surd>-> (_Exit_)"

| WCFG_Entry:
"prog \<turnstile> (_Entry_) -(λs. True)\<surd>-> (_0_)"

| WCFG_Skip:
"Skip \<turnstile> (_0_) -\<Up>id-> (_Exit_)"

| WCFG_LAss:
"V:=e \<turnstile> (_0_) -\<Up>(λs. s(V:=(interpret e s)))-> (_1_)"

| WCFG_LAssSkip:
"V:=e \<turnstile> (_1_) -\<Up>id-> (_Exit_)"

| WCFG_SeqFirst:
"[|c1 \<turnstile> n -et-> n'; n' ≠ (_Exit_)|] ==> c1;;c2 \<turnstile> n -et-> n'"

| WCFG_SeqConnect:
"[|c1 \<turnstile> n -et-> (_Exit_); n ≠ (_Entry_)|] ==> c1;;c2 \<turnstile> n -et-> (_0_) ⊕ #:c1"

| WCFG_SeqSecond:
"[|c2 \<turnstile> n -et-> n'; n ≠ (_Entry_)|] ==> c1;;c2 \<turnstile> n ⊕ #:c1 -et-> n' ⊕ #:c1"

| WCFG_CondTrue:
"if (b) c1 else c2 \<turnstile> (_0_) -(λs. interpret b s = Some true)\<surd>-> (_0_) ⊕ 1"

| WCFG_CondFalse:
"if (b) c1 else c2 \<turnstile> (_0_) -(λs. interpret b s = Some false)\<surd>-> (_0_) ⊕ (#:c1 + 1)"

| WCFG_CondThen:
"[|c1 \<turnstile> n -et-> n'; n ≠ (_Entry_)|] ==> if (b) c1 else c2 \<turnstile> n ⊕ 1 -et-> n' ⊕ 1"

| WCFG_CondElse:
"[|c2 \<turnstile> n -et-> n'; n ≠ (_Entry_)|]
==> if (b) c1 else c2 \<turnstile> n ⊕ (#:c1 + 1) -et-> n' ⊕ (#:c1 + 1)"


| WCFG_WhileTrue:
"while (b) c' \<turnstile> (_0_) -(λs. interpret b s = Some true)\<surd>-> (_0_) ⊕ 2"

| WCFG_WhileFalse:
"while (b) c' \<turnstile> (_0_) -(λs. interpret b s = Some false)\<surd>-> (_1_)"

| WCFG_WhileFalseSkip:
"while (b) c' \<turnstile> (_1_) -\<Up>id-> (_Exit_)"

| WCFG_WhileBody:
"[|c' \<turnstile> n -et-> n'; n ≠ (_Entry_); n' ≠ (_Exit_)|]
==> while (b) c' \<turnstile> n ⊕ 2 -et-> n' ⊕ 2"


| WCFG_WhileBodyExit:
"[|c' \<turnstile> n -et-> (_Exit_); n ≠ (_Entry_)|] ==> while (b) c' \<turnstile> n ⊕ 2 -et-> (_0_)"

lemmas WCFG_intros = While_CFG.intros[split_format (complete)]
lemmas WCFG_elims = While_CFG.cases[split_format (complete)]
lemmas WCFG_induct = While_CFG.induct[split_format (complete)]


subsection {* Some lemmas about the CFG *}

lemma WCFG_Exit_no_sourcenode [dest]:
"prog \<turnstile> (_Exit_) -et-> n' ==> False"
by(induct prog n"(_Exit_)" et n' rule:WCFG_induct,auto)


lemma WCFG_Entry_no_targetnode [dest]:
"prog \<turnstile> n -et-> (_Entry_) ==> False"
by(induct prog n et n'"(_Entry_)" rule:WCFG_induct,auto)


lemma WCFG_sourcelabel_less_num_nodes:
"prog \<turnstile> (_ l _) -et-> n' ==> l < #:prog"
proof(induct prog "(_ l _)" et n' arbitrary:l rule:WCFG_induct)
case (WCFG_SeqFirst c1 et n' c2)
from `l < #:c1` show ?case by simp
next
case (WCFG_SeqConnect c1 et c2)
from `l < #:c1` show ?case by simp
next
case (WCFG_SeqSecond c2 n et n' c1)
note IH = `!!l. n = (_ l _) ==> l < #:c2`
from `n ⊕ #:c1 = (_ l _)` obtain l' where "n = (_ l' _)" by(cases n) auto
from IH[OF this] have "l' < #:c2" .
with `n ⊕ #:c1 = (_ l _)` `n = (_ l' _)` show ?case by simp
next
case (WCFG_CondThen c1 n et n' b c2)
note IH = `!!l. n = (_ l _) ==> l < #:c1`
from `n ⊕ 1 = (_ l _)` obtain l' where "n = (_ l' _)" by(cases n) auto
from IH[OF this] have "l' < #:c1" .
with `n ⊕ 1 = (_ l _)` `n = (_ l' _)` show ?case by simp
next
case (WCFG_CondElse c2 n et n' b c1)
note IH = `!!l. n = (_ l _) ==> l < #:c2`
from `n ⊕ (#:c1 + 1) = (_ l _)` obtain l' where "n = (_ l' _)" by(cases n) auto
from IH[OF this] have "l' < #:c2" .
with `n ⊕ (#:c1 + 1) = (_ l _)` `n = (_ l' _)` show ?case by simp
next
case (WCFG_WhileBody c' n et n' b)
note IH = `!!l. n = (_ l _) ==> l < #:c'`
from `n ⊕ 2 = (_ l _)` obtain l' where "n = (_ l' _)" by(cases n) auto
from IH[OF this] have "l' < #:c'" .
with `n ⊕ 2 = (_ l _)` `n = (_ l' _)` show ?case by simp
next
case (WCFG_WhileBodyExit c' n et b)
note IH = `!!l. n = (_ l _) ==> l < #:c'`
from `n ⊕ 2 = (_ l _)` obtain l' where "n = (_ l' _)" by(cases n) auto
from IH[OF this] have "l' < #:c'" .
with `n ⊕ 2 = (_ l _)` `n = (_ l' _)` show ?case by simp
qed (auto simp:num_inner_nodes_gr_0)


lemma WCFG_targetlabel_less_num_nodes:
"prog \<turnstile> n -et-> (_ l _) ==> l < #:prog"
proof(induct prog n et "(_ l _)" arbitrary:l rule:WCFG_induct)
case (WCFG_SeqFirst c1 n et c2)
from `l < #:c1` show ?case by simp
next
case (WCFG_SeqSecond c2 n et n' c1)
note IH = `!!l. n' = (_ l _) ==> l < #:c2`
from `n' ⊕ #:c1 = (_ l _)` obtain l' where "n' = (_ l' _)" by(cases n') auto
from IH[OF this] have "l' < #:c2" .
with `n' ⊕ #:c1 = (_ l _)` `n' = (_ l' _)` show ?case by simp
next
case (WCFG_CondThen c1 n et n' b c2)
note IH = `!!l. n' = (_ l _) ==> l < #:c1`
from `n' ⊕ 1 = (_ l _)` obtain l' where "n' = (_ l' _)" by(cases n') auto
from IH[OF this] have "l' < #:c1" .
with `n' ⊕ 1 = (_ l _)` `n' = (_ l' _)` show ?case by simp
next
case (WCFG_CondElse c2 n et n' b c1)
note IH = `!!l. n' = (_ l _) ==> l < #:c2`
from `n' ⊕ (#:c1 + 1) = (_ l _)` obtain l' where "n' = (_ l' _)" by(cases n') auto
from IH[OF this] have "l' < #:c2" .
with `n' ⊕ (#:c1 + 1) = (_ l _)` `n' = (_ l' _)` show ?case by simp
next
case (WCFG_WhileBody c' n et n' b)
note IH = `!!l. n' = (_ l _) ==> l < #:c'`
from `n' ⊕ 2 = (_ l _)` obtain l' where "n' = (_ l' _)" by(cases n') auto
from IH[OF this] have "l' < #:c'" .
with `n' ⊕ 2 = (_ l _)` `n' = (_ l' _)` show ?case by simp
qed (auto simp:num_inner_nodes_gr_0)


lemma WCFG_EntryD:
"prog \<turnstile> (_Entry_) -et-> n'
==> (n' = (_Exit_) ∧ et = (λs. False)\<surd>) ∨ (n' = (_0_) ∧ et = (λs. True)\<surd>)"

by(induct prog n"(_Entry_)" et n' rule:WCFG_induct,auto)


(*<*)declare One_nat_def [simp del] add_2_eq_Suc' [simp del](*>*)

lemma WCFG_edge_det:
"[|prog \<turnstile> n -et-> n'; prog \<turnstile> n -et'-> n'|] ==> et = et'"
proof(induct rule:WCFG_induct)
case WCFG_Entry_Exit thus ?case by(fastforce dest:WCFG_EntryD)
next
case WCFG_Entry thus ?case by(fastforce dest:WCFG_EntryD)
next
case WCFG_Skip thus ?case by(fastforce elim:WCFG_elims)
next
case WCFG_LAss thus ?case by(fastforce elim:WCFG_elims)
next
case WCFG_LAssSkip thus ?case by(fastforce elim:WCFG_elims)
next
case (WCFG_SeqFirst c1 n et n' c2)
note IH = `c1 \<turnstile> n -et'-> n' ==> et = et'`
from `c1 \<turnstile> n -et-> n'` `n' ≠ (_Exit_)` obtain l where "n' = (_ l _)"
by (cases n') auto
with `c1 \<turnstile> n -et-> n'` have "l < #:c1"
by(fastforce intro:WCFG_targetlabel_less_num_nodes)
with `c1;;c2 \<turnstile> n -et'-> n'` `n' = (_ l _)` have "c1 \<turnstile> n -et'-> n'"
by(fastforce elim:WCFG_elims intro:WCFG_intros dest:label_incr_ge)
from IH[OF this] show ?case .
next
case (WCFG_SeqConnect c1 n et c2)
note IH = `c1 \<turnstile> n -et'-> (_Exit_) ==> et = et'`
from `c1 \<turnstile> n -et-> (_Exit_)` `n ≠ (_Entry_)` obtain l where "n = (_ l _)"
by (cases n) auto
with `c1 \<turnstile> n -et-> (_Exit_)` have "l < #:c1"
by(fastforce intro:WCFG_sourcelabel_less_num_nodes)
with `c1;;c2 \<turnstile> n -et'-> (_ 0 _) ⊕ #:c1` `n = (_ l _)` have "c1 \<turnstile> n -et'-> (_Exit_)"
by(fastforce elim:WCFG_elims dest:WCFG_targetlabel_less_num_nodes label_incr_ge)
from IH[OF this] show ?case .
next
case (WCFG_SeqSecond c2 n et n' c1)
note IH = `c2 \<turnstile> n -et'-> n' ==> et = et'`
from `c2 \<turnstile> n -et-> n'` `n ≠ (_Entry_)` obtain l where "n = (_ l _)"
by (cases n) auto
with `c2 \<turnstile> n -et-> n'` have "l < #:c2"
by(fastforce intro:WCFG_sourcelabel_less_num_nodes)
with `c1;;c2 \<turnstile> n ⊕ #:c1 -et'-> n' ⊕ #:c1` `n = (_ l _)` have "c2 \<turnstile> n -et'-> n'"
by -(erule WCFG_elims,(fastforce dest:WCFG_sourcelabel_less_num_nodes label_incr_ge
dest!:label_incr_inj)+)
from IH[OF this] show ?case .
next
case WCFG_CondTrue thus ?case by(fastforce elim:WCFG_elims)
next
case WCFG_CondFalse thus ?case by(fastforce elim:WCFG_elims)
next
case (WCFG_CondThen c1 n et n' b c2)
note IH = `c1 \<turnstile> n -et'-> n' ==> et = et'`
from `c1 \<turnstile> n -et-> n'` `n ≠ (_Entry_)` obtain l where "n = (_ l _)"
by (cases n) auto
with `c1 \<turnstile> n -et-> n'` have "l < #:c1"
by(fastforce intro:WCFG_sourcelabel_less_num_nodes)
with `if (b) c1 else c2 \<turnstile> n ⊕ 1 -et'-> n' ⊕ 1` `n = (_ l _)`
have "c1 \<turnstile> n -et'-> n'"
by -(erule WCFG_elims,(fastforce dest:label_incr_ge label_incr_inj)+)
from IH[OF this] show ?case .
next
case (WCFG_CondElse c2 n et n' b c1)
note IH = `c2 \<turnstile> n -et'-> n' ==> et = et'`
from `c2 \<turnstile> n -et-> n'` `n ≠ (_Entry_)` obtain l where "n = (_ l _)"
by (cases n) auto
with `c2 \<turnstile> n -et-> n'` have "l < #:c2"
by(fastforce intro:WCFG_sourcelabel_less_num_nodes)
with `if (b) c1 else c2 \<turnstile> n ⊕ (#:c1 + 1) -et'-> n' ⊕ (#:c1 + 1)` `n = (_ l _)`
have "c2 \<turnstile> n -et'-> n'"
by -(erule WCFG_elims,(fastforce dest:WCFG_sourcelabel_less_num_nodes
label_incr_inj label_incr_ge label_incr_simp_rev)+)
from IH[OF this] show ?case .
next
case WCFG_WhileTrue thus ?case by(fastforce elim:WCFG_elims)
next
case WCFG_WhileFalse thus ?case by(fastforce elim:WCFG_elims)
next
case WCFG_WhileFalseSkip thus ?case by(fastforce elim:WCFG_elims)
next
case (WCFG_WhileBody c' n et n' b)
note IH = `c' \<turnstile> n -et'-> n' ==> et = et'`
from `c' \<turnstile> n -et-> n'` `n ≠ (_Entry_)` obtain l where "n = (_ l _)"
by (cases n) auto
moreover
with `c' \<turnstile> n -et-> n'` have "l < #:c'"
by(fastforce intro:WCFG_sourcelabel_less_num_nodes)
moreover
from `c' \<turnstile> n -et-> n'` `n' ≠ (_Exit_)` obtain l' where "n' = (_ l' _)"
by (cases n') auto
moreover
with `c' \<turnstile> n -et-> n'` have "l' < #:c'"
by(fastforce intro:WCFG_targetlabel_less_num_nodes)
ultimately have "c' \<turnstile> n -et'-> n'" using `while (b) c' \<turnstile> n ⊕ 2 -et'-> n' ⊕ 2`
by(fastforce elim:WCFG_elims dest:label_incr_start_Node_smaller)
from IH[OF this] show ?case .
next
case (WCFG_WhileBodyExit c' n et b)
note IH = `c' \<turnstile> n -et'-> (_Exit_) ==> et = et'`
from `c' \<turnstile> n -et-> (_Exit_)` `n ≠ (_Entry_)` obtain l where "n = (_ l _)"
by (cases n) auto
with `c' \<turnstile> n -et-> (_Exit_)` have "l < #:c'"
by(fastforce intro:WCFG_sourcelabel_less_num_nodes)
with `while (b) c' \<turnstile> n ⊕ 2 -et'-> (_0_)` `n = (_ l _)`
have "c' \<turnstile> n -et'-> (_Exit_)"
by -(erule WCFG_elims,auto dest:label_incr_start_Node_smaller)
from IH[OF this] show ?case .
qed

(*<*)declare One_nat_def [simp] add_2_eq_Suc' [simp](*>*)

lemma less_num_nodes_edge_Exit:
obtains l et where "l < #:prog" and "prog \<turnstile> (_ l _) -et-> (_Exit_)"
proof -
have "∃l et. l < #:prog ∧ prog \<turnstile> (_ l _) -et-> (_Exit_)"
proof(induct prog)
case Skip
have "0 < #:Skip" by simp
moreover have "Skip \<turnstile> (_0_) -\<Up>id-> (_Exit_)" by(rule WCFG_Skip)
ultimately show ?case by blast
next
case (LAss V e)
have "1 < #:(V:=e)" by simp
moreover have "V:=e \<turnstile> (_1_) -\<Up>id-> (_Exit_)" by(rule WCFG_LAssSkip)
ultimately show ?case by blast
next
case (Seq prog1 prog2)
from `∃l et. l < #:prog2 ∧ prog2 \<turnstile> (_ l _) -et-> (_Exit_)`
obtain l et where "l < #:prog2" and "prog2 \<turnstile> (_ l _) -et-> (_Exit_)"
by blast
from `prog2 \<turnstile> (_ l _) -et-> (_Exit_)`
have "prog1;;prog2 \<turnstile> (_ l _) ⊕ #:prog1 -et-> (_Exit_) ⊕ #:prog1"
by(fastforce intro:WCFG_SeqSecond)
with `l < #:prog2` show ?case by(rule_tac x="l + #:prog1" in exI,auto)
next
case (Cond b prog1 prog2)
from `∃l et. l < #:prog1 ∧ prog1 \<turnstile> (_ l _) -et-> (_Exit_)`
obtain l et where "l < #:prog1" and "prog1 \<turnstile> (_ l _) -et-> (_Exit_)"
by blast
from `prog1 \<turnstile> (_ l _) -et-> (_Exit_)`
have "if (b) prog1 else prog2 \<turnstile> (_ l _) ⊕ 1 -et-> (_Exit_) ⊕ 1"
by(fastforce intro:WCFG_CondThen)
with `l < #:prog1` show ?case by(rule_tac x="l + 1" in exI,auto)
next
case (While b prog')
have "1 < #:(while (b) prog')" by simp
moreover have "while (b) prog' \<turnstile> (_1_) -\<Up>id-> (_Exit_)"
by(rule WCFG_WhileFalseSkip)
ultimately show ?case by blast
qed
with that show ?thesis by blast
qed


lemma less_num_nodes_edge:
"l < #:prog ==> ∃n et. prog \<turnstile> n -et-> (_ l _) ∨ prog \<turnstile> (_ l _) -et-> n"
proof(induct prog arbitrary:l)
case Skip
from `l < #:Skip` have "l = 0" by simp
hence "Skip \<turnstile> (_ l _) -\<Up>id-> (_Exit_)" by(fastforce intro:WCFG_Skip)
thus ?case by blast
next
case (LAss V e)
from `l < #:V:=e` have "l = 0 ∨ l = 1" by auto
thus ?case
proof
assume "l = 0"
hence "V:=e \<turnstile> (_Entry_) -(λs. True)\<surd>-> (_ l _)" by(fastforce intro:WCFG_Entry)
thus ?thesis by blast
next
assume "l = 1"
hence "V:=e \<turnstile> (_ l _) -\<Up>id-> (_Exit_)" by(fastforce intro:WCFG_LAssSkip)
thus ?thesis by blast
qed
next
case (Seq prog1 prog2)
note IH1 = `!!l. l < #:prog1 ==>
∃n et. prog1 \<turnstile> n -et-> (_ l _) ∨ prog1 \<turnstile> (_ l _) -et-> n`

note IH2 = `!!l. l < #:prog2 ==>
∃n et. prog2 \<turnstile> n -et-> (_ l _) ∨ prog2 \<turnstile> (_ l _) -et-> n`

show ?case
proof(cases "l < #:prog1")
case True
from IH1[OF this] obtain n et
where "prog1 \<turnstile> n -et-> (_ l _) ∨ prog1 \<turnstile> (_ l _) -et-> n" by blast
thus ?thesis
proof
assume "prog1 \<turnstile> n -et-> (_ l _)"
hence "prog1;; prog2 \<turnstile> n -et-> (_ l _)" by(fastforce intro:WCFG_SeqFirst)
thus ?thesis by blast
next
assume edge:"prog1 \<turnstile> (_ l _) -et-> n"
show ?thesis
proof(cases "n = (_Exit_)")
case True
with edge have "prog1;; prog2 \<turnstile> (_ l _) -et-> (_0_) ⊕ #:prog1"
by(fastforce intro:WCFG_SeqConnect)
thus ?thesis by blast
next
case False
with edge have "prog1;; prog2 \<turnstile> (_ l _) -et-> n"
by(fastforce intro:WCFG_SeqFirst)
thus ?thesis by blast
qed
qed
next
case False
hence "#:prog1 ≤ l" by simp
then obtain l' where "l = l' + #:prog1" and "l' = l - #:prog1" by simp
from `l = l' + #:prog1` `l < #:prog1;; prog2` have "l' < #:prog2" by simp
from IH2[OF this] obtain n et
where "prog2 \<turnstile> n -et-> (_ l' _) ∨ prog2 \<turnstile> (_ l' _) -et-> n" by blast
thus ?thesis
proof
assume "prog2 \<turnstile> n -et-> (_ l' _)"
show ?thesis
proof(cases "n = (_Entry_)")
case True
with `prog2 \<turnstile> n -et-> (_ l' _)` have "l' = 0" by(auto dest:WCFG_EntryD)
obtain l'' et'' where "l'' < #:prog1"
and "prog1 \<turnstile> (_ l'' _) -et''-> (_Exit_)"
by(erule less_num_nodes_edge_Exit)
hence "prog1;;prog2 \<turnstile> (_ l'' _) -et''-> (_0_) ⊕ #:prog1"
by(fastforce intro:WCFG_SeqConnect)
with `l' = 0` `l = l' + #:prog1` show ?thesis by simp blast
next
case False
with `prog2 \<turnstile> n -et-> (_ l' _)`
have "prog1;;prog2 \<turnstile> n ⊕ #:prog1 -et-> (_ l' _) ⊕ #:prog1"
by(fastforce intro:WCFG_SeqSecond)
with `l = l' + #:prog1` show ?thesis by simp blast
qed
next
assume "prog2 \<turnstile> (_ l' _) -et-> n"
hence "prog1;;prog2 \<turnstile> (_ l' _) ⊕ #:prog1 -et-> n ⊕ #:prog1"
by(fastforce intro:WCFG_SeqSecond)
with `l = l' + #:prog1` show ?thesis by simp blast
qed
qed
next
case (Cond b prog1 prog2)
note IH1 = `!!l. l < #:prog1 ==>
∃n et. prog1 \<turnstile> n -et-> (_ l _) ∨ prog1 \<turnstile> (_ l _) -et-> n`

note IH2 = `!!l. l < #:prog2 ==>
∃n et. prog2 \<turnstile> n -et-> (_ l _) ∨ prog2 \<turnstile> (_ l _) -et-> n`

show ?case
proof(cases "l = 0")
case True
have "if (b) prog1 else prog2 \<turnstile> (_Entry_) -(λs. True)\<surd>-> (_0_)"
by(rule WCFG_Entry)
with True show ?thesis by simp blast
next
case False
hence "0 < l" by simp
then obtain l' where "l = l' + 1" and "l' = l - 1" by simp
thus ?thesis
proof(cases "l' < #:prog1")
case True
from IH1[OF this] obtain n et
where "prog1 \<turnstile> n -et-> (_ l' _) ∨ prog1 \<turnstile> (_ l' _) -et-> n" by blast
thus ?thesis
proof
assume edge:"prog1 \<turnstile> n -et-> (_ l' _)"
show ?thesis
proof(cases "n = (_Entry_)")
case True
with edge have "l' = 0" by(auto dest:WCFG_EntryD)
have "if (b) prog1 else prog2 \<turnstile> (_0_) -(λs. interpret b s = Some true)\<surd>->
(_0_) ⊕ 1"

by(rule WCFG_CondTrue)
with `l' = 0` `l = l' + 1` show ?thesis by simp blast
next
case False
with edge have "if (b) prog1 else prog2 \<turnstile> n ⊕ 1 -et-> (_ l' _) ⊕ 1"
by(fastforce intro:WCFG_CondThen)
with `l = l' + 1` show ?thesis by simp blast
qed
next
assume "prog1 \<turnstile> (_ l' _) -et-> n"
hence "if (b) prog1 else prog2 \<turnstile> (_ l' _) ⊕ 1 -et-> n ⊕ 1"
by(fastforce intro:WCFG_CondThen)
with `l = l' + 1` show ?thesis by simp blast
qed
next
case False
hence "#:prog1 ≤ l'" by simp
then obtain l'' where "l' = l'' + #:prog1" and "l'' = l' - #:prog1"
by simp
from `l' = l'' + #:prog1` `l = l' + 1` `l < #:(if (b) prog1 else prog2)`
have "l'' < #:prog2" by simp
from IH2[OF this] obtain n et
where "prog2 \<turnstile> n -et-> (_ l'' _) ∨ prog2 \<turnstile> (_ l'' _) -et-> n" by blast
thus ?thesis
proof
assume "prog2 \<turnstile> n -et-> (_ l'' _)"
show ?thesis
proof(cases "n = (_Entry_)")
case True
with `prog2 \<turnstile> n -et-> (_ l'' _)` have "l'' = 0" by(auto dest:WCFG_EntryD)
have "if (b) prog1 else prog2 \<turnstile> (_0_) -(λs. interpret b s = Some false)\<surd>->
(_0_) ⊕ (#:prog1 + 1)"

by(rule WCFG_CondFalse)
with `l'' = 0` `l' = l'' + #:prog1` `l = l' + 1` show ?thesis by simp blast
next
case False
with `prog2 \<turnstile> n -et-> (_ l'' _)`
have "if (b) prog1 else prog2 \<turnstile> n ⊕ (#:prog1 + 1) -et->
(_ l'' _) ⊕ (#:prog1 + 1)"

by(fastforce intro:WCFG_CondElse)
with `l = l' + 1` `l' = l'' + #:prog1` show ?thesis by simp blast
qed
next
assume "prog2 \<turnstile> (_ l'' _) -et-> n"
hence "if (b) prog1 else prog2 \<turnstile> (_ l'' _) ⊕ (#:prog1 + 1) -et->
n ⊕ (#:prog1 + 1)"

by(fastforce intro:WCFG_CondElse)
with `l = l' + 1` `l' = l'' + #:prog1` show ?thesis by simp blast
qed
qed
qed
next
case (While b prog')
note IH = `!!l. l < #:prog'
==> ∃n et. prog' \<turnstile> n -et-> (_ l _) ∨ prog' \<turnstile> (_ l _) -et-> n`

show ?case
proof(cases "l < 1")
case True
have "while (b) prog' \<turnstile> (_Entry_) -(λs. True)\<surd>-> (_0_)" by(rule WCFG_Entry)
with True show ?thesis by simp blast
next
case False
hence "1 ≤ l" by simp
thus ?thesis
proof(cases "l < 2")
case True
with `1 ≤ l` have "l = 1" by simp
have "while (b) prog' \<turnstile> (_0_) -(λs. interpret b s = Some false)\<surd>-> (_1_)"
by(rule WCFG_WhileFalse)
with `l = 1` show ?thesis by simp blast
next
case False
with `1 ≤ l` have "2 ≤ l" by simp
then obtain l' where "l = l' + 2" and "l' = l - 2"
by(simp del:add_2_eq_Suc')
from `l = l' + 2` `l < #:while (b) prog'` have "l' < #:prog'" by simp
from IH[OF this] obtain n et
where "prog' \<turnstile> n -et-> (_ l' _) ∨ prog' \<turnstile> (_ l' _) -et-> n" by blast
thus ?thesis
proof
assume "prog' \<turnstile> n -et-> (_ l' _)"
show ?thesis
proof(cases "n = (_Entry_)")
case True
with `prog' \<turnstile> n -et-> (_ l' _)` have "l' = 0" by(auto dest:WCFG_EntryD)
have "while (b) prog' \<turnstile> (_0_) -(λs. interpret b s = Some true)\<surd>->
(_0_) ⊕ 2"

by(rule WCFG_WhileTrue)
with `l' = 0` `l = l' + 2` show ?thesis by simp blast
next
case False
with `prog' \<turnstile> n -et-> (_ l' _)`
have "while (b) prog' \<turnstile> n ⊕ 2 -et-> (_ l' _) ⊕ 2"
by(fastforce intro:WCFG_WhileBody)
with `l = l' + 2` show ?thesis by simp blast
qed
next
assume "prog' \<turnstile> (_ l' _) -et-> n"
show ?thesis
proof(cases "n = (_Exit_)")
case True
with `prog' \<turnstile> (_ l' _) -et-> n`
have "while (b) prog' \<turnstile> (_ l' _) ⊕ 2 -et-> (_0_)"
by(fastforce intro:WCFG_WhileBodyExit)
with `l = l' + 2` show ?thesis by simp blast
next
case False
with `prog' \<turnstile> (_ l' _) -et-> n`
have "while (b) prog' \<turnstile> (_ l' _) ⊕ 2 -et-> n ⊕ 2"
by(fastforce intro:WCFG_WhileBody)
with `l = l' + 2` show ?thesis by simp blast
qed
qed
qed
qed
qed


(*<*)declare One_nat_def [simp del](*>*)

lemma WCFG_deterministic:
"[|prog \<turnstile> n1 -et1-> n1'; prog \<turnstile> n2 -et2-> n2'; n1 = n2; n1' ≠ n2'|]
==> ∃Q Q'. et1 = (Q)\<surd> ∧ et2 = (Q')\<surd> ∧ (∀s. (Q s --> ¬ Q' s) ∧ (Q' s --> ¬ Q s))"

proof(induct arbitrary:n2 n2' rule:WCFG_induct)
case (WCFG_Entry_Exit prog)
from `prog \<turnstile> n2 -et2-> n2'` `(_Entry_) = n2` `(_Exit_) ≠ n2'`
have "et2 = (λs. True)\<surd>" by(fastforce dest:WCFG_EntryD)
thus ?case by simp
next
case (WCFG_Entry prog)
from `prog \<turnstile> n2 -et2-> n2'` `(_Entry_) = n2` `(_0_) ≠ n2'`
have "et2 = (λs. False)\<surd>" by(fastforce dest:WCFG_EntryD)
thus ?case by simp
next
case WCFG_Skip
from `Skip \<turnstile> n2 -et2-> n2'` `(_0_) = n2` `(_Exit_) ≠ n2'`
have False by(fastforce elim:WCFG.While_CFG.cases)
thus ?case by simp
next
case (WCFG_LAss V e)
from `V:=e \<turnstile> n2 -et2-> n2'` `(_0_) = n2` `(_1_) ≠ n2'`
have False by -(erule WCFG.While_CFG.cases,auto)
thus ?case by simp
next
case (WCFG_LAssSkip V e)
from `V:=e \<turnstile> n2 -et2-> n2'` `(_1_) = n2` `(_Exit_) ≠ n2'`
have False by -(erule WCFG.While_CFG.cases,auto)
thus ?case by simp
next
case (WCFG_SeqFirst c1 n et n' c2)
note IH = `!!n2 n2'. [|c1 \<turnstile> n2 -et2-> n2'; n = n2; n' ≠ n2'|]
==> ∃Q Q'. et = (Q)\<surd> ∧ et2 = (Q')\<surd> ∧ (∀s. (Q s --> ¬ Q' s) ∧ (Q' s --> ¬ Q s))`

from `c1;;c2 \<turnstile> n2 -et2-> n2'` `c1 \<turnstile> n -et-> n'` `n = n2` `n' ≠ n2'`
have "c1 \<turnstile> n2 -et2-> n2' ∨ (c1 \<turnstile> n2 -et2-> (_Exit_) ∧ n2' = (_0_) ⊕ #:c1)"
apply - apply(erule WCFG.While_CFG.cases)
apply(auto intro:WCFG.While_CFG.intros)
by(case_tac n,auto dest:WCFG_sourcelabel_less_num_nodes)+
thus ?case
proof
assume "c1 \<turnstile> n2 -et2-> n2'"
from IH[OF this `n = n2` `n' ≠ n2'`] show ?case .
next
assume "c1 \<turnstile> n2 -et2-> (_Exit_) ∧ n2' = (_0_) ⊕ #:c1"
hence edge:"c1 \<turnstile> n2 -et2-> (_Exit_)" and n2':"n2' = (_0_) ⊕ #:c1" by simp_all
from IH[OF edge `n = n2` `n' ≠ (_Exit_)`] show ?case .
qed
next
case (WCFG_SeqConnect c1 n et c2)
note IH = `!!n2 n2'. [|c1 \<turnstile> n2 -et2-> n2'; n = n2; (_Exit_) ≠ n2'|]
==> ∃Q Q'. et = (Q)\<surd> ∧ et2 = (Q')\<surd> ∧ (∀s. (Q s --> ¬ Q' s) ∧ (Q' s --> ¬ Q s))`

from `c1;;c2 \<turnstile> n2 -et2-> n2'` `c1 \<turnstile> n -et-> (_Exit_)` `n = n2` `n ≠ (_Entry_)`
`(_0_) ⊕ #:c1 ≠ n2'` have "c1 \<turnstile> n2 -et2-> n2' ∧ (_Exit_) ≠ n2'"
apply - apply(erule WCFG.While_CFG.cases)
apply(auto intro:WCFG.While_CFG.intros)
by(case_tac n,auto dest:WCFG_sourcelabel_less_num_nodes)+
from IH[OF this[THEN conjunct1] `n = n2` this[THEN conjunct2]]
show ?case .
next
case (WCFG_SeqSecond c2 n et n' c1)
note IH = `!!n2 n2'. [|c2 \<turnstile> n2 -et2-> n2'; n = n2; n' ≠ n2'|]
==> ∃Q Q'. et = (Q)\<surd> ∧ et2 = (Q')\<surd> ∧ (∀s. (Q s --> ¬ Q' s) ∧ (Q' s --> ¬ Q s))`

from `c1;;c2 \<turnstile> n2 -et2-> n2'` `c2 \<turnstile> n -et-> n'` `n ⊕ #:c1 = n2`
`n' ⊕ #:c1 ≠ n2'` `n ≠ (_Entry_)`
obtain nx where "c2 \<turnstile> n -et2-> nx ∧ nx ⊕ #:c1 = n2'"
apply - apply(erule WCFG.While_CFG.cases)
apply(auto intro:WCFG.While_CFG.intros)
apply(cases n,auto dest:WCFG_sourcelabel_less_num_nodes)
apply(cases n,auto dest:WCFG_sourcelabel_less_num_nodes)
by(fastforce dest:label_incr_inj)
with `n' ⊕ #:c1 ≠ n2'` have edge:"c2 \<turnstile> n -et2-> nx" and neq:"n' ≠ nx"
by auto
from IH[OF edge _ neq] show ?case by simp
next
case (WCFG_CondTrue b c1 c2)
from `if (b) c1 else c2 \<turnstile> n2 -et2-> n2'` `(_0_) = n2` `(_0_) ⊕ 1 ≠ n2'`
show ?case by -(erule WCFG.While_CFG.cases,auto)
next
case (WCFG_CondFalse b c1 c2)
from `if (b) c1 else c2 \<turnstile> n2 -et2-> n2'` `(_0_) = n2` `(_0_) ⊕ #:c1 + 1 ≠ n2'`
show ?case by -(erule WCFG.While_CFG.cases,auto)
next
case (WCFG_CondThen c1 n et n' b c2)
note IH = `!!n2 n2'. [|c1 \<turnstile> n2 -et2-> n2'; n = n2; n' ≠ n2'|]
==> ∃Q Q'. et = (Q)\<surd> ∧ et2 = (Q')\<surd> ∧ (∀s. (Q s --> ¬ Q' s) ∧ (Q' s --> ¬ Q s))`

from `if (b) c1 else c2 \<turnstile> n2 -et2-> n2'` `c1 \<turnstile> n -et-> n'` `n ≠ (_Entry_)`
`n ⊕ 1 = n2` `n' ⊕ 1 ≠ n2'`
obtain nx where "c1 \<turnstile> n -et2-> nx ∧ n' ≠ nx"
apply - apply(erule WCFG.While_CFG.cases)
apply(auto intro:WCFG.While_CFG.intros)
apply(drule label_incr_inj) apply auto
apply(drule label_incr_simp_rev[OF sym])
by(case_tac na,auto dest:WCFG_sourcelabel_less_num_nodes)
from IH[OF this[THEN conjunct1] _ this[THEN conjunct2]] show ?case by simp
next
case (WCFG_CondElse c2 n et n' b c1)
note IH = `!!n2 n2'. [|c2 \<turnstile> n2 -et2-> n2'; n = n2; n' ≠ n2'|]
==> ∃Q Q'. et = (Q)\<surd> ∧ et2 = (Q')\<surd> ∧ (∀s. (Q s --> ¬ Q' s) ∧ (Q' s --> ¬ Q s))`

from `if (b) c1 else c2 \<turnstile> n2 -et2-> n2'` `c2 \<turnstile> n -et-> n'` `n ≠ (_Entry_)`
`n ⊕ #:c1 + 1 = n2` `n' ⊕ #:c1 + 1 ≠ n2'`
obtain nx where "c2 \<turnstile> n -et2-> nx ∧ n' ≠ nx"
apply - apply(erule WCFG.While_CFG.cases)
apply(auto intro:WCFG.While_CFG.intros)
apply(drule label_incr_simp_rev)
apply(case_tac na,auto,cases n,auto dest:WCFG_sourcelabel_less_num_nodes)
by(fastforce dest:label_incr_inj)
from IH[OF this[THEN conjunct1] _ this[THEN conjunct2]] show ?case by simp
next
case (WCFG_WhileTrue b c')
from `while (b) c' \<turnstile> n2 -et2-> n2'` `(_0_) = n2` `(_0_) ⊕ 2 ≠ n2'`
show ?case by -(erule WCFG.While_CFG.cases,auto)
next
case (WCFG_WhileFalse b c')
from `while (b) c' \<turnstile> n2 -et2-> n2'` `(_0_) = n2` `(_1_) ≠ n2'`
show ?case by -(erule WCFG.While_CFG.cases,auto)
next
case (WCFG_WhileFalseSkip b c')
from `while (b) c' \<turnstile> n2 -et2-> n2'` `(_1_) = n2` `(_Exit_) ≠ n2'`
show ?case by -(erule WCFG.While_CFG.cases,auto dest:label_incr_ge)
next
case (WCFG_WhileBody c' n et n' b)
note IH = `!!n2 n2'. [|c' \<turnstile> n2 -et2-> n2'; n = n2; n' ≠ n2'|]
==> ∃Q Q'. et = (Q)\<surd> ∧ et2 = (Q')\<surd> ∧ (∀s. (Q s --> ¬ Q' s) ∧ (Q' s --> ¬ Q s))`

from `while (b) c' \<turnstile> n2 -et2-> n2'` `c' \<turnstile> n -et-> n'` `n ≠ (_Entry_)`
`n' ≠ (_Exit_)` `n ⊕ 2 = n2` `n' ⊕ 2 ≠ n2'`
obtain nx where "c' \<turnstile> n -et2-> nx ∧ n' ≠ nx"
apply - apply(erule WCFG.While_CFG.cases)
apply(auto intro:WCFG.While_CFG.intros)
apply(fastforce dest:label_incr_ge[OF sym])
apply(fastforce dest:label_incr_inj)
by(fastforce dest:label_incr_inj)
from IH[OF this[THEN conjunct1] _ this[THEN conjunct2]] show ?case by simp
next
case (WCFG_WhileBodyExit c' n et b)
note IH = `!!n2 n2'. [|c' \<turnstile> n2 -et2-> n2'; n = n2; (_Exit_) ≠ n2'|]
==> ∃Q Q'. et = (Q)\<surd> ∧ et2 = (Q')\<surd> ∧ (∀s. (Q s --> ¬ Q' s) ∧ (Q' s --> ¬ Q s))`

from `while (b) c' \<turnstile> n2 -et2-> n2'` `c' \<turnstile> n -et-> (_Exit_)` `n ≠ (_Entry_)`
`n ⊕ 2 = n2` `(_0_) ≠ n2'`
obtain nx where "c' \<turnstile> n -et2-> nx ∧ (_Exit_) ≠ nx"
apply - apply(erule WCFG.While_CFG.cases)
apply(auto intro:WCFG.While_CFG.intros)
apply(fastforce dest:label_incr_ge[OF sym])
by(fastforce dest:label_incr_inj)
from IH[OF this[THEN conjunct1] _ this[THEN conjunct2]] show ?case by simp
qed

(*<*)declare One_nat_def [simp](*>*)

end