(*  Title:      HOL/Auth/n_mesi_lemma_on_inv__2.thy
    Author:     Yongjian Li and Kaiqiang Duan, State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
    Copyright    2016 State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
*)

header{*The n_mesi Protocol Case Study*}

theory n_mesi_lemma_on_inv__2 imports n_mesi_base
begin
section{*All lemmas on causal relation between inv__2 and some rule r*}
lemma n_t1Vsinv__2:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_t1  i)" and
a2: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__2  p__Inv0 p__Inv2)"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain i where a1:"i\<le>N\<and>r=n_t1  i" apply fastforce done
from a2 obtain p__Inv0 p__Inv2 where a2:"p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__2  p__Inv0 p__Inv2" apply fastforce done
have "(i=p__Inv2)\<or>(i=p__Inv0)\<or>(i~=p__Inv0\<and>i~=p__Inv2)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv2)"
  have "?P3 s"
  apply (cut_tac a1 a2 b1, simp, rule_tac x="(neg (andForm (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)) (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E))))" in exI, auto) done
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i=p__Inv0)"
  have "?P1 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv0\<and>i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
ultimately show "invHoldForRule s f r (invariants N)" by satx
qed

lemma n_t2Vsinv__2:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_t2 N i)" and
a2: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__2  p__Inv0 p__Inv2)"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain i where a1:"i\<le>N\<and>r=n_t2 N i" apply fastforce done
from a2 obtain p__Inv0 p__Inv2 where a2:"p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__2  p__Inv0 p__Inv2" apply fastforce done
have "(i=p__Inv2)\<or>(i=p__Inv0)\<or>(i~=p__Inv0\<and>i~=p__Inv2)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv2)"
  have "((formEval (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)) s))\<or>((formEval (andForm (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))\<or>((formEval (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))\<or>((formEval (andForm (andForm (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))" by auto
  moreover {
    assume c1: "((formEval (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  ultimately have "invHoldForRule s f r (invariants N)" by satx
}
moreover {
  assume b1: "(i=p__Inv0)"
  have "((formEval (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)) s))\<or>((formEval (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) s))\<or>((formEval (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) s))\<or>((formEval (andForm (andForm (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) s))" by auto
  moreover {
    assume c1: "((formEval (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  ultimately have "invHoldForRule s f r (invariants N)" by satx
}
moreover {
  assume b1: "(i~=p__Inv0\<and>i~=p__Inv2)"
  have "((formEval (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E))) s))\<or>((formEval (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E))) s))\<or>((formEval (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E))) s))\<or>((formEval (andForm (andForm (andForm (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E))) s))\<or>((formEval (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))\<or>((formEval (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))\<or>((formEval (andForm (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))\<or>((formEval (andForm (andForm (andForm (andForm (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))\<or>((formEval (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))\<or>((formEval (andForm (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))\<or>((formEval (andForm (andForm (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))\<or>((formEval (andForm (andForm (andForm (andForm (andForm (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))\<or>((formEval (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))\<or>((formEval (andForm (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))\<or>((formEval (andForm (andForm (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))\<or>((formEval (andForm (andForm (andForm (andForm (andForm (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))" by auto
  moreover {
    assume c1: "((formEval (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (andForm (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (andForm (andForm (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (andForm (andForm (andForm (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (andForm (andForm (andForm (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I)) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (andForm (andForm (andForm (andForm (andForm (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const I))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv2)) (Const E)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const I)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const M)))) (neg (eqn (IVar (Para (Ident ''state'') p__Inv0)) (Const E)))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2 b1 c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  ultimately have "invHoldForRule s f r (invariants N)" by satx
}
ultimately show "invHoldForRule s f r (invariants N)" by satx
qed

lemma n_t3Vsinv__2:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_t3 N i)" and
a2: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__2  p__Inv0 p__Inv2)"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain i where a1:"i\<le>N\<and>r=n_t3 N i" apply fastforce done
from a2 obtain p__Inv0 p__Inv2 where a2:"p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__2  p__Inv0 p__Inv2" apply fastforce done
have "(i=p__Inv2)\<or>(i=p__Inv0)\<or>(i~=p__Inv0\<and>i~=p__Inv2)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv2)"
  have "?P1 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i=p__Inv0)"
  have "?P1 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv0\<and>i~=p__Inv2)"
  have "?P1 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
ultimately show "invHoldForRule s f r (invariants N)" by satx
qed

lemma n_t4Vsinv__2:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_t4 N i)" and
a2: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__2  p__Inv0 p__Inv2)"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain i where a1:"i\<le>N\<and>r=n_t4 N i" apply fastforce done
from a2 obtain p__Inv0 p__Inv2 where a2:"p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__2  p__Inv0 p__Inv2" apply fastforce done
have "(i=p__Inv2)\<or>(i=p__Inv0)\<or>(i~=p__Inv0\<and>i~=p__Inv2)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv2)"
  have "?P1 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i=p__Inv0)"
  have "?P1 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv0\<and>i~=p__Inv2)"
  have "?P1 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
ultimately show "invHoldForRule s f r (invariants N)" by satx
qed
end


(*  Title:      HOL/Auth/n_germanSymIndex_lemma_inv__38_on_rules.thy
    Author:     Yongjian Li and Kaiqiang Duan, State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
    Copyright    2016 State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
*)

header{*The n_germanSymIndex Protocol Case Study*}

theory n_germanSymIndex_lemma_inv__38_on_rules imports n_germanSymIndex_lemma_on_inv__38
begin
section{*All lemmas on causal relation between inv__38*}
lemma lemma_inv__38_on_rules:
  assumes b1: "r \<in> rules N" and b2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__38  p__Inv2)"
  shows "invHoldForRule s f r (invariants N)"
  proof -
  have c1: "(\<exists> i d. i\<le>N\<and>d\<le>N\<and>r=n_Store  i d)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendReqS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendReqE__part__0  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendReqE__part__1  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReqS N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReqE N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInv__part__0  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInv__part__1  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInvAck  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvInvAck  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendGntS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendGntE N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvGntS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvGntE  i)"
  apply (cut_tac b1, auto) done
    moreover {
      assume d1: "(\<exists> i d. i\<le>N\<and>d\<le>N\<and>r=n_Store  i d)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_StoreVsinv__38) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendReqS  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendReqSVsinv__38) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendReqE__part__0  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendReqE__part__0Vsinv__38) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendReqE__part__1  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendReqE__part__1Vsinv__38) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvReqS N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvReqSVsinv__38) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvReqE N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvReqEVsinv__38) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendInv__part__0  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendInv__part__0Vsinv__38) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendInv__part__1  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendInv__part__1Vsinv__38) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendInvAck  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendInvAckVsinv__38) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvInvAck  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvInvAckVsinv__38) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendGntS  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendGntSVsinv__38) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendGntE N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendGntEVsinv__38) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvGntS  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvGntSVsinv__38) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvGntE  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvGntEVsinv__38) done
    }

  ultimately show "invHoldForRule s f r (invariants N)"
  by satx
qed

end


           (*-------------------------------------------*
            |        CSP-Prover on Isabelle2005         |
            |               February 2006               |
            |                  April 2006  (modified)   |
            |                  April 2007  (modified)   |
            |                 August 2007  (modified)   |
            |                                           |
            |        Yoshinao Isobe (AIST JAPAN)        |
            *-------------------------------------------*)

theory FNF_F_nf
imports FNF_F_nf_int FNF_F_sf
begin

(*  The following simplification rules are deleted in this theory file *)
(*  because they unexpectly rewrite UnionT and InterT.                 *)
(*                  disj_not1: (~ P | Q) = (P --> Q)                   *)

declare disj_not1 [simp del]

(*  The following simplification rules are deleted in this theory file *)
(*       P (if Q then x else y) = ((Q --> P x) & (~ Q --> P y))        *)

declare split_if  [split del]

(*****************************************************************

         1. full normalizing
         2.
         3.

 *****************************************************************)

(*==================================================================*
 |                          fsfF --> fnfF                           |
 *==================================================================*)

inductive_set
  fnfF_fsfF_rel :: "(nat * ('p,'a) proc * ('p,'a) proc) set"

where
fnfF_fsfF_rel_zero:
  "(0, P, NDIV) : fnfF_fsfF_rel"
|
fnfF_fsfF_rel_etc:
  "P ~: fsfF_proc
   ==> (Suc n, P, P |. Suc n) : fnfF_fsfF_rel"
|
fnfF_fsfF_rel_int:
  "[| ALL c. if (c: sumset C)
             then (Suc n, SPf c, NPf c) : fnfF_fsfF_rel
             else NPf c = DIV ;
      sumset C ~= {} ; ALL c: sumset C. SPf c : fsfF_proc |]
   ==>
   (Suc n, (!! :C .. SPf), !! c:C ..[Suc n] NPf c)
   : fnfF_fsfF_rel"
|
fnfF_fsfF_rel_step:
  "[| ALL a. if a:A
             then (n, SPf a, NPf a) : fnfF_fsfF_rel
             else NPf a = DIV ;
      ALL a:A. SPf a : fsfF_proc ;
      Q = SKIP | Q = DIV | Q = STOP |]
   ==>
   (Suc n, (? :A -> SPf) [+] Q,
      ((? :A -> NPf) [+] (if (Q = SKIP) then SKIP else DIV))
      |~| (!set Y:(if Q = STOP then {A} else {}) .. (? a:Y -> DIV)))
    : fnfF_fsfF_rel"

(*** function ***)

definition
  fnfF_fsfF     :: "nat => ('p,'a) proc => ('p,'a) proc"
  where
  fnfF_fsfF_def:
    "fnfF_fsfF n SP == THE NP. (n, SP, NP) : fnfF_fsfF_rel"

definition
  fnfF          :: "nat => ('p,'a) proc => ('p,'a) proc"
  where
  fnfF_def :
    "fnfF == (%n P. fnfF_fsfF n (fsfF P))"

definition
  XfnfF         :: "('p,'a) proc => ('p,'a) proc"
  where
  XfnfF_def :
    "XfnfF == (%P. !nat n .. (fnfF n P))"

(****************************************************************
 |                      uniquness                               |
 ****************************************************************)

lemma fnfF_fsfF_rel_unique_in_lm:
   "(n, SP, NP1) : fnfF_fsfF_rel
    ==> (ALL NP2. ((n, SP, NP2) : fnfF_fsfF_rel
                   --> NP1 = NP2))"
apply (rule fnfF_fsfF_rel.induct[of n SP NP1])
apply (simp)

(* zero *)
apply (intro allI impI)
apply (rotate_tac -1)
apply (erule fnfF_fsfF_rel.cases)
apply (simp_all)

(* etc *)
apply (intro allI impI)
apply (rotate_tac -1)
apply (erule fnfF_fsfF_rel.cases)
apply (simp_all)
apply (simp add: fsfF_proc_int)
apply (simp add: fsfF_proc_ext)

(* int *)
apply (intro allI impI)
apply (rotate_tac -1)
apply (erule fnfF_fsfF_rel.cases, simp_all)

 apply (rotate_tac -3)
 apply (drule sym)
 apply (simp add: fsfF_proc_int)

 apply (subgoal_tac "NPf = NPfa", simp)
 apply (simp add: fun_eq_iff)
 apply (intro allI)
 apply (drule_tac x="x" in spec)+
 apply (case_tac "x : sumset Ca")
 apply (simp)
 apply (simp)

(* step *)
apply (intro allI impI)
apply (rotate_tac -1)
apply (erule fnfF_fsfF_rel.cases, simp_all)

 apply (rotate_tac -3)
 apply (drule sym)
 apply (simp add: fsfF_proc_ext)

 apply (rule conjI)
 apply (subgoal_tac "NPf = NPfa", simp)
 apply (simp add: fun_eq_iff)
 apply (intro allI)
 apply (drule_tac x="x" in spec)+
 apply (case_tac "x : Aa")
 apply (simp)
 apply (simp)

 apply (simp split: split_if)
done

(*-----------------------*
 |        unique         |
 *-----------------------*)

lemma fnfF_fsfF_rel_unique:
   "[| (n, SP, NP1) : fnfF_fsfF_rel;
       (n, SP, NP2) : fnfF_fsfF_rel |]
    ==> NP1 = NP2"
by (simp add: fnfF_fsfF_rel_unique_in_lm)

lemma fnfF_fsfF_rel_EX1:
   "(EX NP. (n, SP, NP) : fnfF_fsfF_rel)
 = (EX! NP. (n, SP, NP) : fnfF_fsfF_rel)"
apply (rule iffI)

 apply (erule exE)
 apply (rule_tac a="NP" in ex1I)
 apply (simp)
 apply (simp add: fnfF_fsfF_rel_unique)

 apply (elim ex1_implies_exE)
 apply (simp)
done

(*------------------------------------------------------------*
 |                      fnfF_fsfF_rel (iff)                   |
 *------------------------------------------------------------*)

(* zero *)

lemma fnfF_fsfF_rel_zero_iff:
  "(0, SP, NP) : fnfF_fsfF_rel = (NP = NDIV)"
apply (rule)
apply (erule fnfF_fsfF_rel.cases, simp_all)
apply (simp add: fnfF_fsfF_rel_zero)
done

(* etc *)

lemma fnfF_fsfF_rel_etc_iff:
  "P ~: fsfF_proc
   ==> (Suc n, P, NP) : fnfF_fsfF_rel
       = (NP = P |. Suc n)"
apply (rule)
apply (erule fnfF_fsfF_rel.cases, simp_all)
 apply (simp add: fsfF_proc_int)
 apply (simp add: fsfF_proc_ext)
apply (simp add: fnfF_fsfF_rel_etc)
done

(* int *)

lemma fnfF_fsfF_rel_int_iff:
  "[| ALL c. if (c: sumset C)
             then (Suc n, SPf c, NPf c) : fnfF_fsfF_rel
             else NPf c = DIV ;
      sumset C ~= {} ; ALL c: sumset C. SPf c : fsfF_proc |]
   ==>
   (Suc n, (!! :C .. SPf), NP) : fnfF_fsfF_rel
   = (NP = !! c:C ..[Suc n] NPf c)"
apply (rule)
apply (erule fnfF_fsfF_rel.cases, simp_all)

 apply (rotate_tac -3)
 apply (drule sym)
 apply (simp add: fsfF_proc_int)

 apply (subgoal_tac "NPfa = NPf", simp)
 apply (simp add: fun_eq_iff)
 apply (rule allI)
 apply (drule_tac x="x" in spec)+
 apply (case_tac "x : sumset Ca")
 apply (simp add: fnfF_fsfF_rel_unique)

 apply (simp)
apply (simp add: fnfF_fsfF_rel_int)
done

(* step *)

lemma fnfF_fsfF_rel_step_iff:
  "[| ALL a. if a:A
             then (n, SPf a, NPf a) : fnfF_fsfF_rel
             else NPf a = DIV ;
      ALL a:A. SPf a : fsfF_proc ;
      Q = SKIP | Q = DIV | Q = STOP |]
   ==>
   (Suc n, (? :A -> SPf) [+] Q, NP) : fnfF_fsfF_rel
   = (NP = ((? :A -> NPf) [+] (if (Q = SKIP) then SKIP else DIV))
      |~| (!set Y:(if Q = STOP then {A} else {}) .. (? a:Y -> DIV)))"
apply (rule)
apply (erule fnfF_fsfF_rel.cases, simp_all)

 apply (rotate_tac -3)
 apply (drule sym)
 apply (simp add: fsfF_proc_ext)

 apply (rule conjI)
 apply (subgoal_tac "NPfa = NPf", simp)
 apply (simp add: fun_eq_iff)
 apply (intro allI conjI)
 apply (elim conjE)
 apply (drule_tac x="x" in spec)+
 apply (case_tac "x : Aa")
 apply (simp add: fnfF_fsfF_rel_unique)
 apply (simp)
 apply (simp split: split_if)

apply (simp add: fnfF_fsfF_rel_step)
done

(****************************************************************
 |                      existency                               |
 ****************************************************************)

(*** exists ***)

lemma fnfF_fsfF_rel_exists_zero:
   "(EX NP. (0, SP, NP) : fnfF_fsfF_rel)"
apply (rule_tac x="NDIV" in exI)
apply (simp add: fnfF_fsfF_rel.intros)
done

lemma fnfF_fsfF_rel_exists_notin:
   "P ~: fsfF_proc
    ==> (EX NP. (n, P, NP) : fnfF_fsfF_rel)"
apply (insert nat_zero_or_Suc)
apply (drule_tac x="n" in spec)
apply (elim disjE exE)
apply (simp add: fnfF_fsfF_rel_exists_zero)
apply (rule_tac x="P |. n" in exI)
apply (simp add: fnfF_fsfF_rel.intros)
done

(*** in fsfF_proc ***)

lemma fnfF_fsfF_rel_exists_in:
   "SP : fsfF_proc
    ==> ALL n. (EX NP. (n, SP, NP) :  fnfF_fsfF_rel)"
apply (rule fsfF_proc.induct[of SP])
apply (simp)

(* int *)
apply (rule allI)
apply (insert nat_zero_or_Suc)
apply (drule_tac x="n" in spec)
apply (elim disjE exE)
apply (simp add: fnfF_fsfF_rel_exists_zero)

apply (erule dist_BALL_conjE)
apply (simp add: exchange_ALL_BALL)
apply (simp add: choice_BALL_EX)
apply (drule_tac x="n" in spec)
apply (elim exE)
apply (rule_tac x="!! c:C ..[Suc m] (if (c : sumset C) then f c else DIV)" in exI)
apply (rule fnfF_fsfF_rel.intros)
apply (simp split: split_if)
apply (simp_all)

(* ext *)
apply (rule allI)
apply (drule_tac x="n" in spec)
apply (rotate_tac -1)
apply (erule disjE)
apply (simp add: fnfF_fsfF_rel_exists_zero)

apply (elim exE)
apply (erule dist_BALL_conjE)

apply (simp add: exchange_ALL_BALL)
apply (simp add: choice_BALL_EX)
apply (drule_tac x="m" in spec)
apply (elim exE)
apply (rule_tac x=
"((? a:A -> (if (a : A) then f a else DIV)) [+] (if (Q = SKIP) then SKIP else DIV))
      |~| (!set Y:(if Q = STOP then {A} else {}) .. (? a:Y -> DIV))" in exI)
apply (rule fnfF_fsfF_rel.intros)
apply (simp split: split_if)
apply (simp_all)
done

(*-----------------------*
 |        exists         |
 *-----------------------*)

lemma fnfF_fsfF_rel_exists:
   "EX NP. (n, SP, NP) :  fnfF_fsfF_rel"
apply (case_tac "SP ~: fsfF_proc")
apply (simp add: fnfF_fsfF_rel_exists_notin)
apply (simp add: fnfF_fsfF_rel_exists_in)
done

(*-----------------------*
 |    uniquely exists    |
 *-----------------------*)

lemma fnfF_fsfF_rel_unique_exists:
   "EX! NP. (n, SP, NP) :  fnfF_fsfF_rel"
apply (simp add: fnfF_fsfF_rel_EX1[THEN sym])
apply (simp add: fnfF_fsfF_rel_exists)
done

(*------------------------------------------------------------*
 |                        in fsfF_proc                        |
 *------------------------------------------------------------*)

lemma fnfF_fsfF_rel_zero_in:
  "(0, SP, NP) : fnfF_fsfF_rel ==> NP : fnfF_proc"
apply (simp add: fnfF_fsfF_rel_zero_iff)
done

lemma fnfF_fsfF_rel_in_lm:
  "SP : fsfF_proc ==>
   ALL n NP. (n, SP, NP) : fnfF_fsfF_rel --> NP : fnfF_proc"
apply (rule fsfF_proc.induct[of SP])
apply (simp)

(* int *)
apply (intro allI)
apply (insert nat_zero_or_Suc)
apply (drule_tac x="n" in spec)
apply (elim disjE exE)
apply (simp add: fnfF_fsfF_rel_zero_in)

apply (intro impI)
apply (simp)
apply (rotate_tac -1)
apply (erule fnfF_fsfF_rel.cases, simp_all)

 apply (rotate_tac -3)
 apply (drule sym)
 apply (simp add: fsfF_proc.intros)

apply (rule fnfF_Rep_int_choice_in)
apply (rule ballI)
apply (drule_tac x="c" in spec, simp)

(* ext *)
apply (intro allI)
apply (drule_tac x="n" in spec)
apply (rotate_tac -1)
apply (erule disjE)
apply (simp add: fnfF_fsfF_rel_zero_in)

apply (intro impI)
apply (erule fnfF_fsfF_rel.cases, simp_all)

 apply (rotate_tac -3)
 apply (drule sym)
 apply (simp add: fsfF_proc.intros)

apply (rule fnfF_proc.intros)

 apply (simp split: split_if)
 apply (intro allI impI)
 apply (drule_tac x="a" in spec, simp)

 apply (simp add: fnfF_set_condition_def)
 apply (intro allI impI)
 apply (simp split: split_if)
 apply (elim conjE bexE)
 apply (case_tac "Qa = STOP")
 apply (simp)
 apply (simp)

 apply (force)
 apply (force)
done

(*------------------------------------*
 |                 in                 |
 *------------------------------------*)

lemma fnfF_fsfF_rel_in:
  "[| SP : fsfF_proc ; (n, SP, NP) : fnfF_fsfF_rel |]
   ==> NP : fnfF_proc"
apply (insert fnfF_fsfF_rel_in_lm[of SP])
apply (blast)
done

(*------------------------------------------------------------*
 |             syntactical transformation to fsfF             |
 *------------------------------------------------------------*)

(*** relation ***)

lemma cspF_fnfF_fsfF_rel_eqF_zero:
   "(0, P, NP) : fnfF_fsfF_rel
     ==> P |. 0 =F NP"
apply (simp add: fnfF_fsfF_rel_zero_iff)
apply (rule cspF_rw_left)
apply (rule cspF_Depth_rest_Zero)
apply (rule cspF_NDIV_eqF)
done

lemma cspF_fnfF_fsfF_rel_eqF_notin:
   "[| P ~: fsfF_proc ; (n, P, NP) : fnfF_fsfF_rel |]
    ==> P |. n =F NP"
apply (insert nat_zero_or_Suc)
apply (drule_tac x="n" in spec)
apply (elim disjE exE)
apply (simp add: cspF_fnfF_fsfF_rel_eqF_zero)
apply (simp add: fnfF_fsfF_rel_etc_iff)
done

lemma cspF_fnfF_fsfF_rel_eqF_in:
    "SP : fsfF_proc ==>
     ALL n NP. (n, SP, NP) : fnfF_fsfF_rel
                --> SP |. n =F NP"
apply (rule fsfF_proc.induct[of SP])
apply (simp)

(* int *)
apply (intro allI)
apply (insert nat_zero_or_Suc)
apply (drule_tac x="n" in spec)
apply (elim disjE exE)
apply (simp add: cspF_fnfF_fsfF_rel_eqF_zero)

apply (intro impI)
apply (simp)
apply (rotate_tac -1)
apply (erule fnfF_fsfF_rel.cases, simp_all)
apply (elim conjE)

apply (rule cspF_rw_right)
apply (rule cspF_fnfF_Rep_int_choice_eqF[THEN cspF_sym])

apply (rule cspF_rw_left)
apply (rule cspF_Dist)
apply (rule cspF_rw_right)
apply (rule cspF_Dist)
apply (rule cspF_decompo)
apply (simp)
apply (drule_tac x="c" in bspec, simp)
apply (drule_tac x="c" in spec)
apply (simp)
apply (drule_tac x="Suc na" in spec)
apply (drule_tac x="NPf c" in spec)
apply (simp)

apply (rule cspF_rw_left)
apply (rule cspF_Depth_rest_n[THEN cspF_sym])
apply (rule cspF_decompo)
apply (simp)
apply (simp)

(* ext *)
apply (intro allI)
apply (drule_tac x="n" in spec)
apply (rotate_tac -1)
apply (erule disjE)
apply (simp add: cspF_fnfF_fsfF_rel_eqF_zero)

apply (intro impI)
apply (erule fnfF_fsfF_rel.cases, simp_all)

apply (rule cspF_rw_left)
apply (rule cspF_Ext_dist)
apply (rule cspF_rw_left)
apply (rule cspF_decompo)
apply (rule cspF_step)
apply (subgoal_tac "Qa |. Suc na =F Qa")
 apply (simp)
 apply (case_tac "Q = STOP")
 apply (simp add: cspF_STOP_Depth_rest)
 apply (simp add: cspF_SKIP_or_DIV_Depth_rest)

 apply (case_tac "Qa = STOP")
 apply (simp)

 (* STOP *)
 apply (rule cspF_rw_left)
 apply (rule cspF_unit)
 apply (rule cspF_rw_left)
 apply (rule cspF_input_DIV)
 apply (rule cspF_decompo)
 apply (rule cspF_decompo)
 apply (rule cspF_decompo)
 apply (simp)
 apply (drule_tac x="a" in bspec, simp)
 apply (drule_tac x="na" in spec)
 apply (drule_tac x="NPf a" in spec)
 apply (simp)
 apply (simp)
 apply (rule cspF_rw_right)
 apply (rule cspF_Rep_int_choice_singleton)
 apply (rule cspF_reflex)

 (* SKIP | DIV *)
 apply (simp)
 apply (rule cspF_rw_right)
 apply (rule cspF_decompo)
 apply (rule cspF_reflex)
 apply (rule cspF_Rep_int_choice_DIV)
 apply (rule cspF_rw_right)
 apply (rule cspF_unit)
 apply (rule cspF_decompo)
 apply (rule cspF_decompo)
 apply (simp)
 apply (drule_tac x="a" in bspec, simp)
 apply (drule_tac x="na" in spec)
 apply (drule_tac x="NPf a" in spec)
 apply (simp)
 apply (force)
done

(*------------------------------------*
 |                 eqF                |
 *------------------------------------*)

lemma cspF_fnfF_fsfF_rel_eqF:
   "(n, SP, NP) : fnfF_fsfF_rel ==> SP |. n =F NP"
apply (case_tac "SP ~: fsfF_proc")
apply (simp add: cspF_fnfF_fsfF_rel_eqF_notin)
apply (simp add: cspF_fnfF_fsfF_rel_eqF_in)
done

(*************************************************************
                  relation --> function
 *************************************************************)

lemma fnfF_fsfF_in_rel:
    "(n, SP, fnfF_fsfF n SP) : fnfF_fsfF_rel"
apply (simp add: fnfF_fsfF_def)
apply (rule theI'
  [of "(%NP. (n, SP, NP) : fnfF_fsfF_rel)"])
apply (simp add: fnfF_fsfF_rel_unique_exists)
done

lemma fnfF_fsfF_from_rel:
    "((n, SP, NP) : fnfF_fsfF_rel)
   = (fnfF_fsfF n SP = NP)"
apply (rule iffI)
apply (simp add: fnfF_fsfF_def)
apply (simp add: fnfF_fsfF_rel_unique_exists the1_equality)

apply (drule sym)
apply (simp add: fnfF_fsfF_in_rel)
done

lemma fnfF_fsfF_to_rel:
    "(fnfF_fsfF n SP = NP)
   = ((n, SP, NP) : fnfF_fsfF_rel)"
by (simp add: fnfF_fsfF_from_rel)

(*************************************************************
                          function
 *************************************************************)

lemma fnfF_fsfF_zero:
  "fnfF_fsfF 0 SP = NDIV"
apply (simp add: fnfF_fsfF_to_rel)
apply (simp add: fnfF_fsfF_rel_zero_iff)
done

lemma fnfF_fsfF_etc:
  "P ~: fsfF_proc
   ==> fnfF_fsfF (Suc n) P = P |. (Suc n)"
apply (simp add: fnfF_fsfF_to_rel)
apply (simp add: fnfF_fsfF_rel_etc_iff)
done

lemma fnfF_fsfF_int:
  "[| sumset C ~= {} ; ALL c: sumset C. SPf c : fsfF_proc |]
   ==>
   fnfF_fsfF (Suc n) (!! :C .. SPf) =
    !! c:C ..[Suc n] (if c: sumset C then (fnfF_fsfF (Suc n) (SPf c)) else DIV)"
apply (simp add: fnfF_fsfF_to_rel)
apply (rule fnfF_fsfF_rel_int)
apply (simp_all)
apply (simp split: split_if)
apply (simp add: fnfF_fsfF_in_rel)
done

lemma fnfF_fsfF_step:
  "[| ALL a:A. SPf a : fsfF_proc ; Q = SKIP | Q = DIV | Q = STOP |]
   ==>
   fnfF_fsfF (Suc n) ((? :A -> SPf) [+] Q) =
      ((? a:A -> (if a:A then (fnfF_fsfF n (SPf a)) else DIV))
        [+] (if (Q = SKIP) then SKIP else DIV))
      |~| (!set Y:(if Q = STOP then {A} else {}) .. (? a:Y -> DIV))"
apply (simp add: fnfF_fsfF_to_rel)
apply (rule fnfF_fsfF_rel_step)
apply (simp_all)
apply (simp split: split_if)
apply (simp add: fnfF_fsfF_in_rel)
done

lemmas fnfF_fsfF =
       fnfF_fsfF_etc
       fnfF_fsfF_int
       fnfF_fsfF_step

(*------------------------------------------------------------*
 |                        in fsfF_proc                        |
 *------------------------------------------------------------*)

lemma fnfF_fsfF_in:
  "SP : fsfF_proc
   ==> fnfF_fsfF n SP : fnfF_proc"
apply (rule fnfF_fsfF_rel_in[of SP n])
apply (simp_all add: fnfF_fsfF_in_rel)
done

(*------------------------------------------------------------*
 |             syntactical transformation to fsfF             |
 *------------------------------------------------------------*)

lemma cspF_fnfF_fsfF_eqF:
   "SP |. n =F fnfF_fsfF n SP"
apply (rule cspF_fnfF_fsfF_rel_eqF)
apply (simp add: fnfF_fsfF_in_rel)
done

(*===============================================================*
   theorem --- fnfF P is a (restricted) full normal form ---
 *===============================================================*)

theorem fnfF_in: "fnfF n P : fnfF_proc"
apply (simp add: fnfF_def)
apply (simp add: fnfF_fsfF_in fsfF_in)
done

(*===============================================================*
        theorem --- fnfF P is equal to P based on F ---
 *===============================================================*)

theorem cspF_fnfF_eqF:
  "FPmode = CPOmode | FPmode = MIXmode ==> P |. n =F fnfF n P"
apply (simp add: fnfF_def)
apply (rule cspF_rw_right)
apply (rule cspF_fnfF_fsfF_eqF[THEN cspF_sym])
apply (rule cspF_rw_left)
apply (rule cspF_decompo)
apply (simp)
apply (rule cspF_fsfF_eqF)
apply (simp)
apply (rule cspF_reflex)
done

(*------------------------*
 |     auxiliary laws     |
 *------------------------*)

lemma cspF_fnfF_eqF_Depth_rest:
  "FPmode = CPOmode | FPmode = MIXmode
   ==> (fnfF n P) |. n =F fnfF n P"
apply (rule cspF_rw_left)
apply (rule cspF_decompo)
apply (simp)
apply (rule cspF_fnfF_eqF[THEN cspF_sym])
apply (simp)
apply (rule cspF_rw_left)
apply (rule cspF_Depth_rest_min)
apply (simp)
apply (rule cspF_fnfF_eqF)
apply (simp)
done

(*===============================================================*
          theorem --- XfnfF P is a full normal form ---
 *===============================================================*)

theorem XfnfF_in:
  "FPmode = CPOmode | FPmode = MIXmode ==> XfnfF P : XfnfF_proc"
apply (simp add: XfnfF_def)
apply (simp add: XfnfF_proc_def)
apply (rule_tac x="(%n. fnfF n P)" in exI)
apply (simp)
apply (simp add: fnfF_in)
apply (rule allI)
apply (rule cspF_rw_right)
apply (rule cspF_decompo)
apply (simp)
apply (rule cspF_decompo)
apply (simp)
apply (rule cspF_fnfF_eqF[THEN cspF_sym])
apply (simp)

apply (rule cspF_rw_left)
apply (rule cspF_fnfF_eqF[THEN cspF_sym])
apply (simp)
apply (rule cspF_decompo)
apply (simp)
apply (rule cspF_nat_Depth_rest)
done

(*===============================================================*
          theorem --- XfnfF P is equal to P based on F ---
 *===============================================================*)

theorem cspF_XfnfF_eqF:
   "FPmode = CPOmode | FPmode = MIXmode ==> P =F XfnfF P"
apply (simp add: XfnfF_def)
apply (rule cspF_rw_right)
apply (rule cspF_decompo)
apply (simp)
apply (rule cspF_fnfF_eqF[THEN cspF_sym])
apply (simp)
apply (rule cspF_nat_Depth_rest)
done

(****************** to add them again ******************)

declare split_if    [split]
declare disj_not1   [simp]

end


theory JVMCFG_wf imports JVMInterpretation "../Basic/CFGExit_wf" begin

text {*
\isaheader{Instantiation of the @{text "CFG_wf"} locale}
*}

subsection {* Variables and Values *}

datatype jinja_var = HeapVar "addr" | Stk "nat" "nat" | Loc "nat" "nat"
datatype jinja_val = Object "obj option" | Primitive "val"

fun state_val :: "state \<Rightarrow> jinja_var \<Rightarrow> jinja_val"
where
  "state_val (h, stk, loc) (HeapVar a) = Object (h a)"
| "state_val (h, stk, loc) (Stk cd idx) = Primitive (stk (cd, idx))"
| "state_val (h, stk, loc) (Loc cd idx) = Primitive (loc (cd, idx))"

subsection {* The @{text Def} and @{text Use} sets *}

inductive_set Def :: "wf_jvmprog \<Rightarrow> j_node \<Rightarrow> jinja_var set"
  for P :: "wf_jvmprog"
  and n :: "j_node"
where
  Def_Load:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Load idx;
  cd = length cs;
  i = stkLength P C M pc\<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Def P n"

| Def_Store:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Store idx;
  cd = length cs \<rbrakk>
  \<Longrightarrow> Loc cd idx \<in> Def P n"

| Def_Push:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Push v;
  cd = length cs;
  i = stkLength P C M pc \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Def P n"

| Def_New_Normal_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = New Cl;
  cd = length cs;
  i = stkLength P C M pc \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Def P n"

| Def_New_Normal_Heap:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = New Cl \<rbrakk>
  \<Longrightarrow> HeapVar a \<in> Def P n"

| Def_Exc_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',True)\<rfloor> _);
  cs' \<noteq> [];
  cd = length cs' - 1;
  (C',M',pc') = hd cs';
  i = stkLength P C' M' pc' - 1\<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Def P n"

| Def_Getfield_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Getfield Fd Cl;
  cd = length cs;
  i = stkLength P C M pc - 1 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Def P n"

| Def_Putfield_Heap:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Putfield Fd Cl \<rbrakk>
  \<Longrightarrow> HeapVar a \<in> Def P n"

| Def_Invoke_Loc:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Invoke M' n';
  cs' \<noteq> [];
  hd cs' = (C',M',0);
  i < locLength P C' M' 0;
  cd = Suc (length cs) \<rbrakk>
  \<Longrightarrow> Loc cd i \<in> Def P n"

| Def_Return_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#(D,M',pc')#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Return;
  cd = length cs;
  i = stkLength P D M' (Suc pc') - 1 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Def P n"

| Def_IAdd_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = IAdd;
  cd = length cs;
  i = stkLength P C M pc - 2 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Def P n"

| Def_CmpEq_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = CmpEq;
  cd = length cs;
  i = stkLength P C M pc - 2 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Def P n"

inductive_set Use :: "wf_jvmprog \<Rightarrow> j_node \<Rightarrow> jinja_var set"
  for P :: "wf_jvmprog"
  and n :: "j_node"
where
  Use_Load:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Load idx;
  cd = length cs \<rbrakk>
  \<Longrightarrow> (Loc cd idx) \<in> Use P n"

| Use_Store:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Store idx;
  cd = length cs;
  Suc i = (stkLength P C M pc) \<rbrakk>
  \<Longrightarrow> (Stk cd i) \<in> Use P n"

| Use_New:
  "\<lbrakk> n = (_ (C, M, pc)#cs,x _);
  x = None \<or> x = \<lfloor>(cs',False)\<rfloor>;
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = New Cl \<rbrakk>
  \<Longrightarrow> HeapVar a \<in> Use P n"

| Use_Getfield_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,x _);
  x = None \<or> x = \<lfloor>(cs',False)\<rfloor>;
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Getfield Fd Cl;
  cd = length cs;
  Suc i = stkLength P C M pc \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_Getfield_Heap:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Getfield Fd Cl \<rbrakk>
  \<Longrightarrow> HeapVar a \<in> Use P n"

| Use_Putfield_Stk_Pred:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Putfield Fd Cl;
  cd = length cs;
  i = stkLength P C M pc - 2 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_Putfield_Stk_Update:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Putfield Fd Cl;
  cd = length cs;
  i = stkLength P C M pc - 2 \<or> i = stkLength P C M pc - 1 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_Putfield_Heap:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Putfield Fd Cl \<rbrakk>
  \<Longrightarrow> HeapVar a \<in> Use P n"

| Use_Checkcast_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,x _);
  x = None \<or> x = \<lfloor>(cs',False)\<rfloor>;
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Checkcast Cl;
  cd = length cs;
  i = stkLength P C M pc - Suc 0 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_Checkcast_Heap:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Checkcast Cl \<rbrakk>
  \<Longrightarrow> HeapVar a \<in> Use P n"

| Use_Invoke_Stk_Pred:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Invoke M' n';
  cd = length cs;
  i = stkLength P C M pc - Suc n' \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_Invoke_Heap_Pred:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Invoke M' n' \<rbrakk>
  \<Longrightarrow> HeapVar a \<in> Use P n"

| Use_Invoke_Stk_Update:
  "\<lbrakk> n = (_ (C, M, pc)#cs,\<lfloor>(cs',False)\<rfloor> _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Invoke M' n';
  cd = length cs;
  i < stkLength P C M pc;
  i \<ge> stkLength P C M pc - Suc n' \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_Return_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#(D,M',pc')#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Return;
  cd = Suc (length cs);
  i = stkLength P C M pc - 1 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_IAdd_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = IAdd;
  cd = length cs;
  i = stkLength P C M pc - 1 \<or> i = stkLength P C M pc - 2 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_IfFalse_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = (IfFalse b);
  cd = length cs;
  i = stkLength P C M pc - 1 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_CmpEq_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,None _);
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = CmpEq;
  cd = length cs;
  i = stkLength P C M pc - 1 \<or> i = stkLength P C M pc - 2 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_Throw_Stk:
  "\<lbrakk> n = (_ (C, M, pc)#cs,x _);
  x = None \<or> x = \<lfloor>(cs',True)\<rfloor>;
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Throw;
  cd = length cs;
  i = stkLength P C M pc - 1 \<rbrakk>
  \<Longrightarrow> Stk cd i \<in> Use P n"

| Use_Throw_Heap:
  "\<lbrakk> n = (_ (C, M, pc)#cs,x _);
  x = None \<or> x = \<lfloor>(cs',True)\<rfloor>;
  instrs_of (P\<^bsub>wf\<^esub>) C M ! pc = Throw \<rbrakk>
  \<Longrightarrow> HeapVar a \<in> Use P n"

declare correct_state_def [simp del]

lemma edge_transfer_uses_only_Use:
  "\<lbrakk>valid_edge (P,C0,Main) a; \<forall>V \<in> Use P (sourcenode a). state_val s V = state_val s' V\<rbrakk>
  \<Longrightarrow> \<forall>V \<in> Def P (sourcenode a). state_val (BasicDefs.transfer (kind a) s) V =
                                  state_val (BasicDefs.transfer (kind a) s') V"
proof
  fix V
  assume ve: "valid_edge (P, C0, Main) a"
    and use_eq: "\<forall>V\<in>Use P (sourcenode a). state_val s V = state_val s' V"
    and v_in_def: "V \<in> Def P (sourcenode a)"
  obtain h stk loc where [simp]: "s = (h,stk,loc)" by (cases s, fastforce)
  obtain h' stk' loc' where [simp]: "s' = (h',stk',loc')" by (cases s', fastforce)
  note P_wf = wf_jvmprog_is_wf [of P]
  from ve
  have ex_edge: "(P,C0,Main) \<turnstile> (sourcenode a)-kind a\<rightarrow>(targetnode a)"
    and vn: "valid_node (P,C0,Main) (sourcenode a)"
    by simp_all
  show "state_val (transfer (kind a) s) V = state_val (transfer (kind a) s') V"
  proof (cases "sourcenode a")
    case (Node cs x) [simp]
    from vn ex_edge have "cs \<noteq> []"
      by (cases x, auto elim: JVM_CFG.cases)
    then obtain C M pc cs' where [simp]: "cs = (C, M, pc)#cs'" by (cases cs, fastforce+)
    with vn obtain ST LT where wt: "((P\<^bsub>\<Phi>\<^esub>) C M ! pc) = \<lfloor>(ST,LT)\<rfloor>"
      by (cases cs', (cases x, auto)+)
    show ?thesis
    proof (cases "instrs_of (P\<^bsub>wf\<^esub>) C M ! pc")
      case (Load n) [simp]
      from ex_edge have [simp]: "x = None"
        by (auto elim!: JVM_CFG.cases)
      hence "Loc (length cs') n \<in> Use P (sourcenode a)"
        by (auto intro!: Use_Load)
      with use_eq have "state_val s (Loc (length cs') n) = state_val s' (Loc (length cs') n)"
        by (simp del: state_val.simps)
      with v_in_def ex_edge show ?thesis
        by (auto elim!: Def.cases
                  elim: JVM_CFG.cases
                  simp: split_beta)
    next
      case (Store n) [simp]
      from ex_edge have [simp]:"x = None"
        by (auto elim!: JVM_CFG.cases)
      have "ST \<noteq> []"
      proof -
        from vn
        obtain Ts T mxs mxl "is" xt
          where C_sees_M: "P\<^bsub>wf\<^esub> \<turnstile> C sees M: Ts\<rightarrow>T = (mxs, mxl, is, xt) in C"
          by (cases cs', auto)
        with vn
        have "pc < length is"
          by (cases cs', auto dest: sees_method_fun)
        from P_wf C_sees_M
        have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
          by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
        with Store C_sees_M wt `pc < length is`
        show ?thesis
          by (fastforce simp: wt_method_def)
      qed
      then obtain ST1 STr where [simp]: "ST = ST1#STr"
        by (cases ST, fastforce+)
      from wt
        have "Stk (length cs') (length ST - 1) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use_src")
          by -(rule Use_Store, fastforce+)
      with use_eq have "state_val s ?stk_top = state_val s' ?stk_top"
        by (simp del: state_val.simps)
      with v_in_def ex_edge wt show ?thesis
        by (auto elim!: Def.cases
                  elim: JVM_CFG.cases
                  simp: split_beta)
    next
      case (Push val) [simp]
      from ex_edge have "x = None"
        by (auto elim!: JVM_CFG.cases)
      with v_in_def ex_edge show ?thesis
        by (auto elim!: Def.cases
                  elim: JVM_CFG.cases)
    next
      case (New Cl) [simp]
      show ?thesis
      proof (cases x)
        case None
        with v_in_def have False
          by (auto elim: Def.cases)
        thus ?thesis by simp
      next
        case (Some x')
        then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
          by (cases x', fastforce)
        have "\<not> xf \<longrightarrow> (\<forall>addr. HeapVar addr \<in> Use P (sourcenode a))"
          by (fastforce intro: Use_New)
        with use_eq
        have "\<not> xf \<longrightarrow> (\<forall>addr. state_val s (HeapVar addr) = state_val s' (HeapVar addr))"
          by (simp del: state_val.simps)
        hence "\<not> xf \<longrightarrow> h = h'"
          by (auto intro: ext)
        with v_in_def ex_edge show ?thesis
          by (auto elim!: Def.cases
                    elim: JVM_CFG.cases)
      qed
    next
      case (Getfield Fd Cl) [simp]
      show ?thesis
      proof (cases x)
        case None
        with v_in_def have False
          by (auto elim: Def.cases)
        thus ?thesis by simp
      next
        case (Some x')
        then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
          by (cases x', fastforce)
        have "ST \<noteq> []"
        proof -
          from vn obtain T Ts mxs mxl "is" xt
            where sees_M: "(P\<^bsub>wf\<^esub>) \<turnstile> C sees M:Ts\<rightarrow>T = (mxs,mxl,is,xt) in C"
            by (cases cs', auto)
          with vn
          have "pc < length is"
            by (cases cs', auto dest: sees_method_fun)
          from P_wf sees_M have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
            by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
          with Getfield sees_M wt `pc < length is` show ?thesis
            by (fastforce simp: wt_method_def)
        qed
        then obtain ST1 STr where [simp]: "ST = ST1#STr" by (cases ST, fastforce)
        from wt
        have "\<not> xf \<longrightarrow> (Stk (length cs') (length ST - 1) \<in> Use P (sourcenode a))"
          (is "?xf \<longrightarrow> ?stk_top \<in> ?Use_src")
          by (auto intro!: Use_Getfield_Stk)
        with use_eq
        have stk_top_eq: "\<not> xf \<longrightarrow> state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        have "\<not> xf \<longrightarrow> (\<forall>addr. HeapVar addr \<in> Use P (sourcenode a))"
          by (auto intro!: Use_Getfield_Heap)
        with use_eq
        have "\<not> xf \<longrightarrow> (\<forall>addr. state_val s (HeapVar addr) = state_val s' (HeapVar addr))"
          by (simp del: state_val.simps)
        hence "\<not> xf \<longrightarrow> h = h'"
          by (auto intro: ext)
        with ex_edge v_in_def stk_top_eq wt
        show ?thesis
          by (auto elim!: Def.cases
                    elim: JVM_CFG.cases
                    simp: split_beta)
      qed
    next
      case (Putfield Fd Cl) [simp]
      show ?thesis
      proof (cases x)
        case None
        with v_in_def have False
          by (auto elim: Def.cases)
        thus ?thesis by simp
      next
        case (Some x')
        then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
          by (cases x', fastforce)
        have "length ST > 1"
        proof -
          from vn obtain T Ts mxs mxl "is" xt
            where sees_M: "(P\<^bsub>wf\<^esub>) \<turnstile> C sees M:Ts\<rightarrow>T = (mxs,mxl,is,xt) in C"
            by (cases cs', auto)
          with vn
          have "pc < length is"
            by (cases cs', auto dest: sees_method_fun)
          from P_wf sees_M have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
            by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
          with Putfield sees_M `pc < length is` wt show ?thesis
            by (fastforce simp: wt_method_def)
        qed
        then obtain ST1 STr' where "ST = ST1#STr' \<and> length STr' > 0"
          by (cases ST, fastforce+)
        then obtain ST2 STr where [simp]: "ST = ST1#ST2#STr"
          by (cases STr', fastforce+)
        from wt
        have "\<not> xf \<longrightarrow> (Stk (length cs') (length ST - 1) \<in> Use P (sourcenode a))"
          (is "?xf \<longrightarrow> ?stk_top \<in> ?Use_src")
          by (fastforce intro: Use_Putfield_Stk_Update)
        with use_eq have stk_top:"(\<not> xf) \<longrightarrow> state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        from wt
        have "\<not> xf \<longrightarrow> (Stk (length cs') (length ST - 2) \<in> Use P (sourcenode a))"
          (is "?xf \<longrightarrow> ?stk_nxt \<in> ?Use_src")
          by (fastforce intro: Use_Putfield_Stk_Update)
        with use_eq
        have stk_nxt:"(\<not> xf) \<longrightarrow> state_val s ?stk_nxt = state_val s' ?stk_nxt"
          by (simp del: state_val.simps)
        have "\<not> xf \<longrightarrow> (\<forall>addr. HeapVar addr \<in> Use P (sourcenode a))"
          by (fastforce intro: Use_Putfield_Heap)
        with use_eq
        have "\<not> xf \<longrightarrow> (\<forall>addr. state_val s (HeapVar addr) = state_val s' (HeapVar addr))"
          by (simp del: state_val.simps)
        hence "\<not> xf \<longrightarrow> h = h'"
          by (auto intro: ext)
        with ex_edge v_in_def stk_top stk_nxt wt show ?thesis
          by (auto elim!: Def.cases
                   elim: JVM_CFG.cases
                   simp: split_beta)
      qed
    next
      case (Checkcast Cl) [simp]
      show ?thesis
      proof (cases x)
        case None
        with v_in_def have False
          by (auto elim: Def.cases)
        thus ?thesis by simp
      next
        case (Some x')
        with ex_edge obtain cs''
          where "x = \<lfloor>(cs'',True)\<rfloor>"
          by (auto elim!: JVM_CFG.cases)
        with v_in_def ex_edge show ?thesis
          by (auto elim!: Def.cases
                    elim: JVM_CFG.cases)
      qed
    next
      case (Invoke M' n') [simp]
      show ?thesis
      proof (cases x)
        case None
        with v_in_def have False
          by (auto elim: Def.cases)
        thus ?thesis by simp
      next
        case (Some x')
        then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
          by (cases x', fastforce)
        show ?thesis
        proof (cases xf)
          case True
          with v_in_def ex_edge show ?thesis
            by (auto elim!: Def.cases
                      elim: JVM_CFG.cases)
        next
          case False [simp]
          have "length ST > n'"
          proof -
            from vn obtain T Ts mxs mxl "is" xt
              where sees_M: "(P\<^bsub>wf\<^esub>) \<turnstile> C sees M:Ts\<rightarrow>T = (mxs,mxl,is,xt) in C"
              by (cases cs', auto)
            with vn
            have "pc < length is"
              by (cases cs', auto dest: sees_method_fun)
            from P_wf sees_M have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
              by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
            with Invoke sees_M `pc < length is` wt show ?thesis
              by (fastforce simp: wt_method_def)
          qed
          moreover obtain STn where "STn = take n' ST" by fastforce
          moreover obtain STs where "STs = ST ! n'" by fastforce
          moreover obtain STr where "STr = drop (Suc n') ST" by fastforce
          ultimately have [simp]:" ST = STn@STs#STr \<and> length STn = n'"
            by (auto simp: id_take_nth_drop)
          from wt
          have "\<forall>i. i \<le> n' \<longrightarrow> Stk (length cs') (length ST - Suc i) \<in> Use P (sourcenode a)"
            by (fastforce intro: Use_Invoke_Stk_Update)
          with use_eq
          have
            "\<forall>i. i \<le> n' \<longrightarrow> state_val s (Stk (length cs') (length ST - Suc i)) =
                           state_val s' (Stk (length cs') (length ST - Suc i))"
            by (simp del: state_val.simps)
          hence stk_eq:
            "\<forall>i. i \<le> n' \<longrightarrow> state_val s (Stk (length cs') (i + length STr)) =
                           state_val s' (Stk (length cs') (i + length STr))"
            by (clarsimp, erule_tac x="n' - i" in allE, auto simp: add.commute)
          from ex_edge obtain C'
            where trg: "targetnode a = (_ (C',M',0)#(C, M, pc)#cs',None _)"
            by (fastforce elim: JVM_CFG.cases)
          with ex_edge stk_eq v_in_def wt
          show ?thesis
            by (auto elim!: Def.cases) (erule JVM_CFG.cases, auto simp: split_beta add.commute)
        qed
      qed
    next
      case Return [simp]
      show ?thesis
      proof (cases x)
        case None [simp]
        show ?thesis
        proof (cases cs')
          case Nil
          with v_in_def show ?thesis
            by (auto elim!: Def.cases)
        next
          case (Cons aa list)
          then obtain C' M' pc' cs'' where [simp]: "cs' = (C',M',pc')#cs''"
            by (cases aa, fastforce)
          from wt
          have "Stk (length cs') (length ST - 1) \<in> Use P (sourcenode a)"
            by (fastforce intro: Use_Return_Stk)
          with use_eq
          have "state_val s (Stk (length cs') (length ST - 1)) =
                state_val s' (Stk (length cs') (length ST - 1))"
            by (simp del: state_val.simps)
          with v_in_def ex_edge wt show ?thesis
            by (auto elim!: Def.cases
                      elim: JVM_CFG.cases
                      simp: split_beta)
        qed
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case Pop
      with v_in_def ex_edge show ?thesis
        by (auto elim!: Def.cases elim: JVM_CFG.cases)
    next
      case IAdd [simp]
      show ?thesis
      proof (cases x)
        case None [simp]
        from wt
        have "Stk (length cs') (length ST - 1) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (auto intro!: Use_IAdd_Stk)
        with use_eq
        have stk_top:"state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        from wt
        have "Stk (length cs') (length ST - 2) \<in> Use P (sourcenode a)"
          (is "?stk_snd \<in> ?Use")
          by (auto intro!: Use_IAdd_Stk)
        with use_eq
        have stk_snd:"state_val s ?stk_snd = state_val s' ?stk_snd"
          by (simp del: state_val.simps)
        with v_in_def ex_edge stk_top wt show ?thesis
          by (auto elim!: Def.cases
                    elim: JVM_CFG.cases
                    simp: split_beta)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case (IfFalse b) [simp]
      show ?thesis
      proof (cases x)
        case None [simp]
        from wt
        have "Stk (length cs') (length ST - 1) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (auto intro!: Use_IfFalse_Stk)
        with use_eq
        have stk_top:"state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        with v_in_def ex_edge wt show ?thesis
          by (auto elim!: Def.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case CmpEq [simp]
      show ?thesis
      proof (cases x)
        case None [simp]
        have "Stk (length cs') (stkLength P C M pc - 1) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (auto intro!: Use_CmpEq_Stk)
        with use_eq
        have stk_top:"state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        have "Stk (length cs') (stkLength P C M pc - 2) \<in> Use P (sourcenode a)"
          (is "?stk_snd \<in> ?Use")
          by (auto intro!: Use_CmpEq_Stk)
        with use_eq
        have stk_snd:"state_val s ?stk_snd = state_val s' ?stk_snd"
          by (simp del: state_val.simps)
        with v_in_def ex_edge stk_top wt show ?thesis
          by (auto elim!: Def.cases
                    elim: JVM_CFG.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case (Goto i)
      with ex_edge v_in_def show ?thesis
        by (auto elim!: Def.cases
                  elim: JVM_CFG.cases)
    next
      case Throw [simp]
      show ?thesis
      proof (cases x)
        case None [simp]
        have "Stk (length cs') (stkLength P C M pc - 1) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (auto intro!: Use_Throw_Stk)
        with use_eq
        have stk_top:"state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        with v_in_def show ?thesis
          by (auto elim!: Def.cases)
      next
        case (Some x')
        then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
          by (cases x', fastforce)
        hence "xf \<longrightarrow> Stk (length cs') (stkLength P C M pc - 1) \<in> Use P (sourcenode a)"
          (is "xf \<longrightarrow> ?stk_top \<in> ?Use")
          by (fastforce intro: Use_Throw_Stk)
        with use_eq
        have stk_top:"xf \<longrightarrow> state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        with v_in_def ex_edge show ?thesis
          by (auto elim!: Def.cases
                    elim: JVM_CFG.cases)
      qed
    qed
  next
    case Entry
    with vn v_in_def show ?thesis
      by -(erule Def.cases, auto)
  qed
qed

lemma CFG_edge_Uses_pred_equal:
  "\<lbrakk> valid_edge (P,C0,Main) a;
  pred (kind a) s;
  \<forall>V \<in> Use P (sourcenode a). state_val s V = state_val s' V\<rbrakk>
  \<Longrightarrow> pred (kind a) s'"
proof -
  assume ve: "valid_edge (P,C0,Main) a"
    and pred: "pred (kind a) s"
    and use_eq: "\<forall>V\<in>Use P (sourcenode a). state_val s V = state_val s' V"
  obtain h stk loc where [simp]: "s = (h,stk,loc)" by (cases s, blast)
  obtain h' stk' loc' where [simp]: "s' = (h',stk',loc')" by (cases s', blast)
  from ve
  have vn: "valid_node (P,C0,Main) (sourcenode a)"
    and ex_edge: "(P,C0,Main) \<turnstile> (sourcenode a)-kind a\<rightarrow>(targetnode a)"
    by simp_all
  note P_wf = wf_jvmprog_is_wf [of P]
  show "pred (kind a) s'"
  proof (cases "sourcenode a")
    case (Node cs x) [simp]
    from ve have "cs \<noteq> []"
      by (cases x, auto elim: JVM_CFG.cases)
    then obtain C M pc cs' where [simp]: "cs = (C, M, pc)#cs'" by (cases cs, fastforce+)
    from vn obtain ST LT where wt: "((P\<^bsub>\<Phi>\<^esub>) C M ! pc) = \<lfloor>(ST,LT)\<rfloor>"
      by (cases cs', (cases x, auto)+)
    show ?thesis
    proof (cases "instrs_of (P\<^bsub>wf\<^esub>) C M ! pc")
      case (Load nat)
      with ex_edge show ?thesis
        by (auto elim: JVM_CFG.cases)
    next
      case (Store nat)
      with ex_edge show ?thesis
        by (auto elim: JVM_CFG.cases)
    next
      case (Push val)
      with ex_edge show ?thesis
        by (auto elim: JVM_CFG.cases)
    next
      case (New Cl) [simp]
      show ?thesis
      proof (cases x)
        case None
        hence "\<forall>addr. HeapVar addr \<in> Use P (sourcenode a)"
          by (auto intro!: Use_New)
        with use_eq have "\<forall>addr. state_val s (HeapVar addr) = state_val s' (HeapVar addr)"
          by (simp del: state_val.simps)
        hence "h = h'"
          by (auto intro: ext)
        with ex_edge pred show ?thesis
          by (auto elim!: JVM_CFG.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case (Getfield Fd Cl) [simp]
      have "ST \<noteq> []"
      proof -
        from vn obtain T Ts mxs mxl "is" xt
          where sees_M: "(P\<^bsub>wf\<^esub>) \<turnstile> C sees M:Ts\<rightarrow>T = (mxs,mxl,is,xt) in C"
          by (cases cs', (cases x, auto)+)
        with vn
        have "pc < length is"
          by (cases cs', (cases x, auto dest: sees_method_fun)+)
        from P_wf sees_M have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
          by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
        with Getfield wt sees_M `pc < length is` show ?thesis
          by (fastforce simp: wt_method_def)
      qed
      then obtain ST1 STr where [simp]: "ST = ST1#STr" by (cases ST, fastforce+)
      show ?thesis
      proof (cases x)
        case None [simp]
        from wt
        have "Stk (length cs') (length ST - 1) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (fastforce intro: Use_Getfield_Stk)
        with use_eq have "state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        with ex_edge pred wt show ?thesis
          by (auto elim: JVM_CFG.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case (Putfield Fd Cl) [simp]
      have "length ST > 1"
      proof -
        from vn obtain T Ts mxs mxl "is" xt
          where sees_M: "(P\<^bsub>wf\<^esub>) \<turnstile> C sees M:Ts\<rightarrow>T = (mxs,mxl,is,xt) in C"
          by (cases cs', (cases x, auto)+)
        with vn
        have "pc < length is"
          by (cases cs', (cases x, auto dest: sees_method_fun)+)
        from P_wf sees_M have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
          by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
        with Putfield wt sees_M `pc < length is` show ?thesis
          by (fastforce simp: wt_method_def)
      qed
      then obtain ST1 STr' where "ST = ST1#STr' \<and> STr' \<noteq> []" by (cases ST, fastforce+)
      then obtain ST2 STr where [simp]: "ST = ST1#ST2#STr" by (cases STr', fastforce+)
      show ?thesis
      proof (cases x)
        case None [simp]
        with wt
        have "Stk (length cs') (length ST - 2) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (fastforce intro: Use_Putfield_Stk_Pred)
        with use_eq have "state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        with ex_edge pred wt show ?thesis
          by (auto elim: JVM_CFG.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case (Checkcast Cl) [simp]
      have "ST \<noteq> []"
      proof -
        from vn obtain T Ts mxs mxl "is" xt
          where sees_M: "(P\<^bsub>wf\<^esub>) \<turnstile> C sees M:Ts\<rightarrow>T = (mxs,mxl,is,xt) in C"
          by (cases cs', (cases x, auto)+)
        with vn
        have "pc < length is"
          by (cases cs', (cases x, auto dest: sees_method_fun)+)
        from P_wf sees_M have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
          by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
        with Checkcast wt sees_M `pc < length is` show ?thesis
          by (fastforce simp: wt_method_def)
      qed
      then obtain ST1 STr where [simp]: "ST = ST1#STr" by (cases ST, fastforce+)
      show ?thesis
      proof (cases x)
        case None [simp]
        from wt
        have "Stk (length cs') (stkLength P C M pc - Suc 0) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (fastforce intro: Use_Checkcast_Stk)
        with use_eq
        have stk_top: "state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        have "\<forall>addr. HeapVar addr \<in> Use P (sourcenode a)"
          by (fastforce intro: Use_Checkcast_Heap)
        with use_eq
        have "\<forall>addr. state_val s (HeapVar addr) = state_val s' (HeapVar addr)"
          by (simp del: state_val.simps)
        hence "h = h'"
          by (auto intro: ext)
        with ex_edge stk_top pred wt show ?thesis
          by (auto elim: JVM_CFG.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case (Invoke M' n') [simp]
      have "length ST > n'"
      proof -
        from vn obtain T Ts mxs mxl "is" xt
          where sees_M: "(P\<^bsub>wf\<^esub>) \<turnstile> C sees M:Ts\<rightarrow>T = (mxs,mxl,is,xt) in C"
          by (cases cs', (cases x, auto)+)
        with vn
        have "pc < length is"
          by (cases cs', (cases x, auto dest: sees_method_fun)+)
        from P_wf sees_M have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
          by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
        with Invoke wt sees_M `pc < length is` show ?thesis
          by (fastforce simp: wt_method_def)
      qed
      moreover obtain STn where "STn = take n' ST" by fastforce
      moreover obtain STs where "STs = ST ! n'" by fastforce
      moreover obtain STr where "STr = drop (Suc n') ST" by fastforce
      ultimately have [simp]:" ST = STn@STs#STr \<and> length STn = n'"
        by (auto simp: id_take_nth_drop)
      show ?thesis
      proof (cases x)
        case None [simp]
        with wt
        have "Stk (length cs') (stkLength P C M pc - Suc n') \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (fastforce intro: Use_Invoke_Stk_Pred)
        with use_eq
        have stk_top: "state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        have "\<forall>addr. HeapVar addr \<in> Use P (sourcenode a)"
          by (fastforce intro: Use_Invoke_Heap_Pred)
        with use_eq
        have "\<forall>addr. state_val s (HeapVar addr) = state_val s' (HeapVar addr)"
          by (simp del: state_val.simps)
        hence "h = h'"
          by (auto intro: ext)
        with ex_edge stk_top pred wt show ?thesis
          by (auto elim: JVM_CFG.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case Return
      with ex_edge show ?thesis
        by (auto elim: JVM_CFG.cases)
    next
      case Pop
      with ex_edge show ?thesis
        by (auto elim: JVM_CFG.cases)
    next
      case IAdd
      with ex_edge show ?thesis
        by (auto elim: JVM_CFG.cases)
    next
      case (IfFalse b) [simp]
      show ?thesis
      proof (cases x)
        case None [simp]
        have "Stk (length cs') (stkLength P C M pc - 1) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (fastforce intro: Use_IfFalse_Stk)
        with use_eq
        have "state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        with ex_edge pred wt show ?thesis
          by (auto elim: JVM_CFG.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    next
      case CmpEq
      with ex_edge show ?thesis
        by (auto elim: JVM_CFG.cases)
    next
      case (Goto i)
      with ex_edge show ?thesis
        by (auto elim: JVM_CFG.cases)
    next
      case Throw [simp]
      have "ST \<noteq> []"
      proof -
        from vn obtain T Ts mxs mxl "is" xt
          where sees_M: "(P\<^bsub>wf\<^esub>) \<turnstile> C sees M:Ts\<rightarrow>T = (mxs,mxl,is,xt) in C"
          by (cases cs', (cases x, auto)+)
        with vn
        have "pc < length is"
          by (cases cs', (cases x, auto dest: sees_method_fun)+)
        from P_wf sees_M have "wt_method (P\<^bsub>wf\<^esub>) C Ts T mxs mxl is xt (P\<^bsub>\<Phi>\<^esub> C M)"
          by (auto dest: sees_wf_mdecl simp: wf_jvm_prog_phi_def wf_mdecl_def)
        with Throw wt sees_M `pc < length is` show ?thesis
          by (fastforce simp: wt_method_def)
      qed
      then obtain ST1 STr where [simp]: "ST = ST1#STr" by (cases ST, fastforce+)
      show ?thesis
      proof (cases x)
        case None [simp]
        from wt
        have "Stk (length cs') (stkLength P C M pc - 1) \<in> Use P (sourcenode a)"
          (is "?stk_top \<in> ?Use")
          by (fastforce intro: Use_Throw_Stk)
        with use_eq
        have stk_top: "state_val s ?stk_top = state_val s' ?stk_top"
          by (simp del: state_val.simps)
        have "\<forall>addr. HeapVar addr \<in> Use P (sourcenode a)"
          by (fastforce intro: Use_Throw_Heap)
        with use_eq
        have "\<forall>addr. state_val s (HeapVar addr) = state_val s' (HeapVar addr)"
          by (simp del: state_val.simps)
        hence "h = h'"
          by (auto intro: ext)
        with ex_edge pred stk_top wt show ?thesis
          by (auto elim!: JVM_CFG.cases)
      next
        case (Some x')
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      qed
    qed
  next
    case Entry
    with ex_edge pred show ?thesis
      by (auto elim: JVM_CFG.cases)
  qed
qed

lemma edge_no_Def_equal:
  "\<lbrakk> valid_edge (P, C0, Main) a;
     V \<notin> Def P (sourcenode a) \<rbrakk>
  \<Longrightarrow> state_val (transfer (kind a) s) V = state_val s V"
proof -
  assume ve:"valid_edge (P, C0, Main) a"
    and v_not_def: "V \<notin> Def P (sourcenode a)"
  obtain h stk loc where [simp]: "(s::state) = (h, stk, loc)" by (cases s, blast)
  from ve have vn: "valid_node (P, C0, Main) (sourcenode a)"
    and ex_edge: "(P, C0, Main) \<turnstile> (sourcenode a)-kind a\<rightarrow>(targetnode a)"
    by simp_all
  show "state_val (transfer (kind a) s) V = state_val s V"
  proof (cases "sourcenode a")
    case (Node cs x) [simp]
    with ve have "cs \<noteq> []"
      by (cases x, auto elim: JVM_CFG.cases)
    then obtain C M pc cs' where [simp]: "cs = (C, M, pc)#cs'" by (cases cs, fastforce+)
    with vn obtain ST LT where wt: "((P\<^bsub>\<Phi>\<^esub>) C M ! pc) = \<lfloor>(ST,LT)\<rfloor>"
      by (cases cs', (cases x, auto)+)
    show ?thesis
    proof (cases "instrs_of (P\<^bsub>wf\<^esub>) C M ! pc")
      case (Load nat) [simp]
      from ex_edge have "x = None"
        by (auto elim: JVM_CFG.cases)
      with v_not_def have "V \<noteq> Stk (length cs') (stkLength P C M pc)"
        by (auto intro!: Def_Load)
      with ex_edge show ?thesis
        by (auto elim!: JVM_CFG.cases, cases V, auto)
    next
      case (Store nat) [simp]
      with ex_edge have "x = None"
        by (auto elim: JVM_CFG.cases)
      with v_not_def have "V \<noteq> Loc (length cs') nat"
        by (auto intro!: Def_Store)
      with ex_edge show ?thesis
        by (auto elim!: JVM_CFG.cases, cases V, auto)
    next
      case (Push val) [simp]
      with ex_edge have "x = None"
        by (auto elim: JVM_CFG.cases)
      with v_not_def have "V \<noteq> Stk (length cs') (stkLength P C M pc)"
        by (auto intro!: Def_Push)
      with ex_edge show ?thesis
        by (auto elim!: JVM_CFG.cases, cases V, auto)
    next
      case (New Cl) [simp]
      show ?thesis
      proof (cases x)
        case None
        with ex_edge show ?thesis
          by (auto elim: JVM_CFG.cases)
      next
        case (Some x')
        then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
          by (cases x', fastforce)
        with ex_edge v_not_def show ?thesis
          apply (auto elim!: JVM_CFG.cases)
            apply (cases V, auto intro!: Def_New_Normal_Stk Def_New_Normal_Heap)
           by (cases V, auto intro!: Def_Exc_Stk)+
     qed
   next
     case (Getfield F Cl) [simp]
     show ?thesis
     proof (cases x)
       case None
       with ex_edge show ?thesis
         by (auto elim: JVM_CFG.cases)
     next
       case (Some x')
       then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
         by (cases x', fastforce)
       with ex_edge v_not_def show ?thesis
         apply (auto elim!: JVM_CFG.cases simp: split_beta)
           apply (cases V, auto intro!: Def_Getfield_Stk)
          by (cases V, auto intro!: Def_Exc_Stk)+
     qed
   next
     case (Putfield Fd Cl) [simp]
     show ?thesis
     proof (cases x)
       case None
       with ex_edge show ?thesis
         by (auto elim: JVM_CFG.cases)
     next
       case (Some x')
       then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
         by (cases x', fastforce)
       with ex_edge v_not_def show ?thesis
         apply (auto elim!: JVM_CFG.cases simp: split_beta)
           apply (cases V, auto intro!: Def_Putfield_Heap)
          by (cases V, auto intro!: Def_Exc_Stk)+
     qed
   next
     case (Checkcast Cl) [simp]
     show ?thesis
     proof (cases x)
       case None
       with ex_edge show ?thesis
         by (auto elim: JVM_CFG.cases)
     next
       case (Some x')
       then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
         by (cases x', fastforce)
       with ex_edge v_not_def show ?thesis
         apply (auto elim!: JVM_CFG.cases)
          by (cases V, auto intro!: Def_Exc_Stk)+
     qed
   next
     case (Invoke M' n') [simp]
     show ?thesis
     proof (cases x)
       case None
       with ex_edge show ?thesis
         by (auto elim: JVM_CFG.cases)
     next
       case (Some x')
       then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
         by (cases x', fastforce)
       from ex_edge v_not_def show ?thesis
         apply (auto elim!: JVM_CFG.cases)
           apply (cases V, auto intro!: Def_Invoke_Loc)
          by (cases V, auto intro!: Def_Exc_Stk)+
     qed
   next
     case Return
     with ex_edge v_not_def show ?thesis
       apply (auto elim!: JVM_CFG.cases)
       by (cases V, auto intro!: Def_Return_Stk)
   next
     case Pop
     with ex_edge show ?thesis
       by (auto elim: JVM_CFG.cases)
   next
     case IAdd
     with ex_edge v_not_def show ?thesis
       apply (auto elim!: JVM_CFG.cases)
       by (cases V, auto intro!: Def_IAdd_Stk)
   next
     case (IfFalse b)
     with ex_edge show ?thesis
       by (auto elim: JVM_CFG.cases)
   next
     case CmpEq
     with ex_edge v_not_def show ?thesis
       apply (auto elim!: JVM_CFG.cases)
       by (cases V, auto intro!: Def_CmpEq_Stk)
   next
     case (Goto i)
     with ex_edge show ?thesis
       by (auto elim: JVM_CFG.cases)
   next
     case Throw [simp]
     show ?thesis
     proof (cases x)
       case None
       with ex_edge show ?thesis
         by (auto elim: JVM_CFG.cases)
     next
       case (Some x')
       then obtain cs'' xf where [simp]: "x = \<lfloor>(cs'',xf)\<rfloor>"
         by (cases x', fastforce)
       from ex_edge v_not_def show ?thesis
         apply (auto elim!: JVM_CFG.cases)
          by (cases V, auto intro!: Def_Exc_Stk)+
      qed
    qed
  next
    case Entry
    with ex_edge show ?thesis
      by (auto elim: JVM_CFG.cases)
  qed
qed

interpretation JVM_CFG_wf: CFG_wf
  "sourcenode" "targetnode" "kind" "valid_edge prog" "(_Entry_)"
  "Def (fst prog)" "Use (fst prog)" "state_val"
  for prog
proof (unfold_locales)
  show "Def (fst prog) (_Entry_) = {} \<and> Use (fst prog) (_Entry_) = {}"
    by (auto elim: Def.cases Use.cases)
next
  fix a V s
  assume ve:"valid_edge prog a"
    and v_not_def: "V \<notin> Def (fst prog) (sourcenode a)"
  thus "state_val (transfer (kind a) s) V = state_val s V"
    by -(cases prog,
    rule edge_no_Def_equal [of "fst prog" "fst (snd prog)" "snd (snd prog)"], auto)
next
  fix a s s'
  assume ve: "valid_edge prog a"
    and use_eq: "\<forall>V\<in>Use (fst prog) (sourcenode a). state_val s V = state_val s' V"
  thus "\<forall>V\<in>Def (fst prog) (sourcenode a).
    state_val (transfer (kind a) s) V = state_val (transfer (kind a) s') V"
    by -(cases prog,
      rule edge_transfer_uses_only_Use [of "fst prog" "fst(snd prog)" "snd(snd prog)"], auto)
next
  fix a s s'
  assume ve: "valid_edge prog a"
    and pred: "pred (kind a) s"
    and use_eq: "\<forall>V\<in>Use (fst prog) (sourcenode a). state_val s V = state_val s' V"
  thus "pred (kind a) s'"
    by -(cases prog,
      rule CFG_edge_Uses_pred_equal [of "fst prog" "fst(snd prog)" "snd(snd prog)"], auto)
next
  fix a a'
  assume ve_a: "valid_edge prog a"
    and ve_a': "valid_edge prog a'"
    and src_eq: "sourcenode a = sourcenode a'"
    and trg_neq: "targetnode a \<noteq> targetnode a'"
  hence "prog \<turnstile> (sourcenode a)-kind a\<rightarrow>(targetnode a)"
    and "prog \<turnstile> (sourcenode a')-kind a'\<rightarrow>(targetnode a')"
    by simp_all
  with src_eq trg_neq
  show "\<exists>Q Q'. kind a = (Q)\<^sub>\<surd> \<and> kind a' = (Q')\<^sub>\<surd> \<and> (\<forall>s. (Q s \<longrightarrow> \<not> Q' s) \<and> (Q' s \<longrightarrow> \<not> Q s))"
    apply (cases prog, auto)
    apply (erule JVM_CFG.cases, erule_tac [!] JVM_CFG.cases)
    (* This takes veeery long! *)
    by simp_all
qed

interpretation JVM_CFGExit_wf: CFGExit_wf
  "sourcenode" "targetnode" "kind" "valid_edge prog" "(_Entry_)"
  "Def (fst prog)" "Use (fst prog)" "state_val" "(_Exit_)"
proof
  show "Def (fst prog) (_Exit_) = {} \<and> Use (fst prog) (_Exit_) = {}"
    by(fastforce elim:Def.cases Use.cases)
qed

end