Theory SE_Graph_Pre

theory SE_Graph_Pre
imports IA_Instance
theory SE_Graph_Pre
  imports
    "LTS.IA_Instance"
begin

(*
  p = position,
  pv = program variable
  lv = logical variable
   n = node identifier
*)

datatype ('p,'pv,'lv) abstract_state =
  As (pos : 'p)
     (stack : "'pv ⇀ 'lv")
     (kb : "'lv IA.formula")

type_synonym ('n,'v) as_config = "'n × ('v × IA.ty ⇒ IA.val)"

inductive as_as_step where
  "as_as_step as1 as2 σ τ μ"
  if
  "IA.assignment v" "IA.assignment v'" "IA.assignment σ" "IA.assignment τ"
  "IA.satisfies v (kb as1)" "IA.satisfies v' (kb as2)"
  "∀ n lv. stack as1 n = Some lv ⟶ σ (n,IA.IntT) = v (lv,IA.IntT)"
  "∀ n lv. stack as2 n = Some lv ⟶ τ (n,IA.IntT) = v' (lv,IA.IntT)"
  "∀ lv ty. v (μ lv,ty) = v' (lv,ty)"

locale graph' =
  fixes as_of_node :: "'n ⇒ ('pos,'pv,'lv::linorder) abstract_state"
        and renaming_of_edge :: "('n × 'n) ⇒ ('lv ⇒ 'lv)"
        and edges ::  "('n × 'n) set"
begin

definition nodes where "nodes = fst ` edges ∪ snd ` edges"

inductive_set as_step :: "(('n,'pv) as_config × ('n,'pv) as_config) set" where
   "{n1,n2} ⊆ nodes ⟹
   (n1, n2) ∈ edges ⟹
   IA.assignment v ⟹
   IA.assignment v' ⟹
   IA.assignment σ ⟹
   IA.assignment τ ⟹
   IA.satisfies v (kb (as_of_node n1)) ⟹
   IA.satisfies v' (kb (as_of_node n2)) ⟹
   (∀ n lv. stack (as_of_node n1) n = Some lv ⟶ σ (n,IA.IntT) = v (lv,IA.IntT) ) ⟹
   (∀ n lv. stack (as_of_node n2) n = Some lv ⟶ τ (n,IA.IntT) = v' (lv,IA.IntT) ) ⟹
   renaming_of_edge (n1, n2) = μ ⟹
   ∀ lv ty. v (μ lv,ty) = v' (lv,ty) ⟹
   ((n1,σ), (n2,τ)) ∈ as_step"

lemma as_as_as_step:
  assumes "(n1, n2) ∈ edges" "renaming_of_edge (n1, n2) = μ"
    and a: "as_as_step (as_of_node n1) (as_of_node n2) σ τ μ"
  shows "((n1,σ), (n2,τ)) ∈ as_step"
  using a assms
proof (induction "as_of_node n1" "as_of_node n2" σ τ μ rule: as_as_step.induct)
  case (1 v v' σ τ μ)
  have "{n1, n2} ⊆ nodes"
    unfolding nodes_def using assms by auto
  then show ?case
    using 1 assms by (intro as_step.intros[where v=v and v'=v']) (auto)
qed

lemma as_as_as_step':
  assumes "((n1,σ), (n2,τ)) ∈ as_step" "renaming_of_edge (n1, n2) = μ"
  shows "as_as_step (as_of_node n1) (as_of_node n2) σ τ μ"
  using assms
proof (induction n1 σ n2 τ rule: as_step.induct)
  case (1 n1 n2 v v' σ τ μ)
  then show ?case
    by (intro as_as_step.intros[where v=v and v'=v']) (auto)
qed

lemma as_step_nodes: "((n1,σ), (n2,τ)) ∈ as_step ⟹ {n1,n2} ⊆ nodes"
  by (induct rule: as_step.induct, auto)

lemma as_step_edge: "((n1,σ), (n2,τ)) ∈ as_step ⟹ (n1,n2) ∈ edges"
  by (induct rule: as_step.induct, auto)

end


end