

theory Mgu = Main + Terms + Fresh + Equ + Substs:

(* unification problems *)

syntax
 "_equ_prob"   :: "trm \<Rightarrow> trm \<Rightarrow> (trm\<times>trm)"        ("_ \<approx>? _" [81,81] 81)
 "_fresh_prob" :: "string \<Rightarrow> trm \<Rightarrow> (string\<times>trm)"  ("_ \<sharp>? _" [81,81] 81)

translations 
  "t1 \<approx>? t2" \<rightharpoonup> "(t1,t2)"
  " a \<sharp>? t"  \<rightharpoonup> "(a,t)"

(* all solutions for a unification problem *)

types 
  problem_type = "((trm\<times>trm)list) \<times> ((string\<times>trm)list)"
  unifier_type = "fresh_envs \<times> substs"

consts 
  U :: "problem_type \<Rightarrow> (unifier_type set)"
defs all_solutions_def : 
  "U P  \<equiv> {(nabla,s). 
             (\<forall> (t1,t2)\<in>set (fst P). nabla \<turnstile> subst s t1 \<approx> subst s t2) \<and> 
             (\<forall>   (a,t)\<in>set (snd P). nabla \<turnstile> a \<sharp> subst s t) }"

(* set of variables in unification problems *)

consts
  vars_fprobs :: "((string\<times>trm) list) \<Rightarrow> (string set)"
  vars_eprobs :: "((trm\<times>trm)list) \<Rightarrow> (string set)"
  vars_probs  :: "problem_type \<Rightarrow> nat"
primrec
  "vars_fprobs [] = {}"
  "vars_fprobs (x#xs) = (vars_trm (snd x))\<union>(vars_fprobs xs)"
primrec
  "vars_eprobs [] = {}"
  "vars_eprobs (x#xs) = (vars_trm (snd x))\<union>(vars_trm (fst x))\<union>(vars_eprobs xs)"
defs
  vars_probs_def: "vars_probs P \<equiv> card((vars_fprobs (snd P))\<union>(vars_eprobs (fst P)))"


(* most general unifier *)

consts 
  mgu :: "problem_type \<Rightarrow> unifier_type \<Rightarrow> bool"
defs mgu_def:
  "mgu P unif \<equiv> 
   \<forall> (nabla,s1)\<in> U P. (\<exists> s2. (nabla\<Turnstile>(subst s2) (fst unif)) \<and> 
                              (nabla\<Turnstile>subst (s2 \<bullet>(snd unif)) \<approx> subst s1))"

(* idempotency of a unifier *)

consts 
  idem :: "unifier_type \<Rightarrow> bool"
defs 
  idem_def: "idem unif \<equiv> (fst unif)\<Turnstile> subst ((snd unif)\<bullet>(snd unif)) \<approx> subst (snd unif)"

(* application of a substitution to a problem *)

consts 
  apply_subst :: "substs \<Rightarrow> problem_type \<Rightarrow> problem_type"
defs apply_subst_def: 
  "apply_subst s P \<equiv> (map (\<lambda>(t1,t2). (subst s t1 \<approx>? subst s t2)) (fst P),
                      map (\<lambda>(a,t).   (a \<sharp>? (subst s t)) ) (snd P))" 

(* equality reductions *)

consts 
  s_red :: "(problem_type \<times> substs \<times> problem_type) set"
syntax 
  "_s_red" :: "problem_type \<Rightarrow> substs \<Rightarrow> problem_type \<Rightarrow> bool"  ("_ \<turnstile> _ \<leadsto> _ " [80,80,80] 80)
translations "P1 \<turnstile>sigma\<leadsto> P2" \<rightleftharpoons> "(P1,sigma,P2)\<in>s_red"
inductive s_red
intros
  unit_sred[intro!,dest!]:    "((Unit\<approx>?Unit)#xs,ys) \<turnstile>[]\<leadsto> (xs,ys)"
  paar_sred[intro!,dest!]:    "((Paar t1 t2\<approx>?Paar s1 s2)#xs,ys) \<turnstile>[]\<leadsto> ((t1\<approx>?s1)#(t2\<approx>?s2)#xs,ys)"
  func_sred[intro!,dest!]:    "((Func F t1\<approx>?Func F t2)#xs,ys) \<turnstile>[]\<leadsto> ((t1\<approx>?t2)#xs,ys)"
  abst_aa_sred[intro!,dest!]: "((Abst a t1\<approx>?Abst a t2)#xs,ys) \<turnstile>[]\<leadsto> ((t1\<approx>?t2)#xs,ys)"
  abst_ab_sred[intro!]: "a\<noteq>b\<Longrightarrow> 
                       ((Abst a t1\<approx>?Abst b t2)#xs,ys) \<turnstile>[]\<leadsto> ((t1\<approx>?swap [(a,b)] t2)#xs,(a\<sharp>?t2)#ys)"
  atom_sred[intro!,dest!]:    "((Atom a\<approx>?Atom a)#xs,ys) \<turnstile>[]\<leadsto> (xs,ys)"  
  susp_sred[intro!,dest!]:    "((Susp pi1 X\<approx>?Susp pi2 X)#xs,ys) 
                                \<turnstile>[]\<leadsto> (xs,(map (\<lambda>a. a\<sharp>? Susp [] X) (ds_list pi1 pi2))@ys)"
  var_1_sred[intro!]:   "\<not>(occurs X t)\<Longrightarrow>((Susp pi X\<approx>?t)#xs,ys)
                               \<turnstile>[(X,swap (rev pi) t)]\<leadsto> apply_subst [(X,swap (rev pi) t)] (xs,ys)"
  var_2_sred[intro!]:   "\<not>(occurs X t)\<Longrightarrow>((t\<approx>?Susp pi X)#xs,ys) 
                               \<turnstile>[(X,swap (rev pi) t)]\<leadsto> apply_subst [(X,swap (rev pi) t)] (xs,ys)"

(* freshness reductions *)

consts 
  c_red :: "(problem_type \<times> fresh_envs \<times> problem_type) set"
syntax 
  "_c_red" :: "problem_type \<Rightarrow> fresh_envs \<Rightarrow> problem_type \<Rightarrow> bool" ("_ \<turnstile> _ \<rightarrow> _ " [80,80,80] 80)
translations "P1 \<turnstile>nabla\<rightarrow> P2" \<rightleftharpoons> "(P1,nabla,P2)\<in>c_red"
inductive c_red
intros
  unit_cred[intro!]:    "([],(a \<sharp>? Unit)#xs) \<turnstile>{}\<rightarrow> ([],xs)"
  paar_cred[intro!]:    "([],(a \<sharp>? Paar t1 t2)#xs) \<turnstile>{}\<rightarrow> ([],(a\<sharp>?t1)#(a\<sharp>?t2)#xs)"
  func_cred[intro!]:    "([],(a \<sharp>? Func F t)#xs) \<turnstile>{}\<rightarrow> ([],(a\<sharp>?t)#xs)"
  abst_aa_cred[intro!]: "([],(a \<sharp>? Abst a t)#xs) \<turnstile>{}\<rightarrow> ([],xs)"
  abst_ab_cred[intro!]: "a\<noteq>b\<Longrightarrow>([],(a \<sharp>? Abst b t)#xs) \<turnstile>{}\<rightarrow> ([],(a\<sharp>?t)#xs)"
  atom_cred[intro!]:    "a\<noteq>b\<Longrightarrow>([],(a \<sharp>? Atom b)#xs) \<turnstile>{}\<rightarrow> ([],xs)"  
  susp_cred[intro!]:    "([],(a \<sharp>? Susp pi X)#xs) \<turnstile>{((swapas (rev pi) a),X)}\<rightarrow> ([],xs)" 

(* unification reduction sequence *)

consts 
  red_plus :: "(problem_type \<times> unifier_type \<times> problem_type) set"
syntax 
  red_plus :: "problem_type \<Rightarrow> unifier_type \<Rightarrow> problem_type \<Rightarrow> bool" ("_ \<Turnstile> _ \<Rightarrow> _ " [80,80,80] 80)

translations "P1 \<Turnstile>(nabla,s)\<Rightarrow> P2" \<rightleftharpoons> "(P1,(nabla,s),P2)\<in>red_plus"
inductive red_plus
intros
  sred_single[intro!]: "\<lbrakk>P1\<turnstile>s1\<leadsto>P2\<rbrakk>\<Longrightarrow>P1\<Turnstile>({},s1)\<Rightarrow>P2"
  cred_single[intro!]: "\<lbrakk>P1\<turnstile>nabla1\<rightarrow>P2\<rbrakk>\<Longrightarrow>P1\<Turnstile>(nabla1,[])\<Rightarrow>P2"
  sred_step[intro!]:   "\<lbrakk>P1\<turnstile>s1\<leadsto>P2;P2\<Turnstile>(nabla2,s2)\<Rightarrow>P3\<rbrakk>\<Longrightarrow>P1\<Turnstile>(nabla2,(s2\<bullet>s1))\<Rightarrow>P3"
  cred_step[intro!]:   "\<lbrakk>P1\<turnstile>nabla1\<rightarrow>P2;P2\<Turnstile>(nabla2,[])\<Rightarrow>P3\<rbrakk>\<Longrightarrow>P1\<Turnstile>(nabla2\<union>nabla1,[])\<Rightarrow>P3"

lemma mgu_idem: 
  "\<lbrakk>(nabla1,s1)\<in>U P; 
   \<forall>(nabla2,s2)\<in> U P. nabla2\<Turnstile>(subst s2) nabla1 \<and>  nabla2\<Turnstile>subst(s2 \<bullet> s1)\<approx>subst s2 \<rbrakk>\<Longrightarrow>
   mgu P (nabla1,s1)\<and>idem (nabla1,s1)"
apply(rule conjI)
apply(simp only: mgu_def)
apply(rule ballI)
apply(simp)
apply(drule_tac x="x" in bspec)
apply(assumption)
apply(force)
apply(drule_tac x="(nabla1,s1)" in bspec)
apply(assumption)
apply(simp add: idem_def)
done

lemma problem_subst_comm: "((nabla,s2)\<in>U (apply_subst s1 P)) = ((nabla,(s2\<bullet>s1))\<in>U P)"
apply(simp add: all_solutions_def apply_subst_def)
apply(auto)
apply(drule_tac x="(a,b)" in bspec, assumption, simp add: subst_comp_expand)+
done

lemma P1_to_P2_sred: 
  "\<lbrakk>(nabla1,s1)\<in>U P1; P1 \<turnstile>s2\<leadsto> P2 \<rbrakk>\<Longrightarrow>((nabla1,s1)\<in>U P2) \<and> (nabla1\<Turnstile>subst (s1\<bullet>s2)\<approx>subst s1)"
apply(ind_cases "P1 \<turnstile>s2\<leadsto> P2")
apply(simp_all)
--Unit
apply(force intro!: equ_refl simp add: all_solutions_def ext_subst_def subst_equ_def subst_susp)
--Paar
apply(simp add: all_solutions_def ext_subst_def subst_equ_def subst_susp)
apply(force intro!: equ_refl dest!: equ_paar_elim)
--Func
apply(simp add: all_solutions_def ext_subst_def subst_equ_def subst_susp)
apply(force intro!: equ_refl dest!: equ_func_elim)
--Abst.aa
apply(simp add: all_solutions_def ext_subst_def subst_equ_def subst_susp)
apply(force intro!: equ_refl dest!: equ_abst_aa_elim)
--Abst.ab
apply(simp add: all_solutions_def ext_subst_def subst_equ_def subst_susp)
apply(force intro!: equ_refl dest!: equ_abst_ab_elim simp add: subst_swap_comm)
--Atom
apply(simp add: all_solutions_def ext_subst_def subst_equ_def subst_susp)
apply(force intro!: equ_refl)
--Susp
apply(rule conjI)
apply(auto)
apply(simp add: all_solutions_def)
apply(erule conjE)+
apply(simp add: ds_list_equ_ds)
apply(simp only: subst_susp)
apply(drule equ_pi1_pi2_dec[THEN mp])
apply(auto)
apply(drule_tac x="aa" in bspec)
apply(assumption)
apply(simp add: subst_susp)
apply(simp add: subst_equ_def subst_susp)
apply(rule ballI)
apply(rule equ_refl)
--Var.one
apply(drule_tac "t2.1"="swap (rev pi) t" in subst_not_occurs[THEN mp])
apply(simp only: problem_subst_comm)
apply(simp add: all_solutions_def ext_subst_def subst_equ_def)
apply(rule conjI)
apply(rule ballI)
apply(erule conjE)+
apply(drule unif_1)
apply(clarify)
apply(drule_tac x="(a,b)" in bspec)
apply(assumption)
apply(simp)
apply(simp add: unif_2a)
apply(erule conjE)+
apply(drule unif_1)
apply(rule ballI)
apply(clarify)
apply(drule_tac x="(a,b)" in bspec)
apply(assumption)
apply(simp)
apply(simp add: unif_2b)
apply(rule unif_1)
apply(simp add: all_solutions_def)
--Var.two
apply(drule_tac "t2.1"="swap (rev pi) t" in subst_not_occurs[THEN mp])
apply(simp only: problem_subst_comm)
apply(simp add: all_solutions_def ext_subst_def subst_equ_def)
apply(auto)
apply(drule_tac x="(a,b)" in bspec)
apply(assumption)
apply(simp)
apply(drule equ_sym)
apply(drule unif_1)
apply(simp add: unif_2a)
apply(drule_tac x="(a,b)" in bspec)
apply(assumption)
apply(simp)
apply(drule equ_sym)
apply(drule unif_1)
apply(simp add: unif_2b)
apply(rule unif_1)
apply(rule equ_sym)
apply(simp add: all_solutions_def)
done

lemma P1_from_P2_sred: "\<lbrakk>(nabla1,s1)\<in>U P2; P1\<turnstile>s2\<leadsto>P2\<rbrakk>\<Longrightarrow>(nabla1,s1\<bullet>s2)\<in>U P1"
apply(ind_cases "P1 \<turnstile>s2\<leadsto> P2")
--Susp.Paar.Func.Abst.aa
apply(simp add: all_solutions_def, force)
apply(simp add: all_solutions_def, force)
apply(simp add: all_solutions_def, force)
apply(simp add: all_solutions_def, force)
--Abst.ab
apply(simp only: all_solutions_def)
apply(force simp add: subst_swap_comm)
--Atom
apply(simp only: all_solutions_def, force)
--Susp
apply(simp)
apply(auto)
apply(simp add: all_solutions_def)
apply(simp add: ds_list_equ_ds)
apply(subgoal_tac "nabla1\<turnstile>(swap pi1 (subst s1 (Susp [] X)))\<approx>(swap pi2 (subst s1 (Susp [] X)))")
apply(simp add: subst_susp subst_swap_comm)
apply(simp add: subst_susp subst_swap_comm)
apply(rule equ_pi1_pi2_add[THEN mp])
apply(drule conjunct2)
apply(auto)
apply(drule_tac x="(a,Susp [] X)" in bspec)
apply(auto)
apply(simp add: subst_susp)
--Var.one
apply(simp only: problem_subst_comm)
apply(simp only: all_solutions_def)
apply(simp)
apply(simp only: subst_comp_expand)
apply(subgoal_tac "subst [(X, swap (rev pi) t)] t = t")--A
apply(simp add: subst_susp)
apply(simp only: subst_swap_comm)
apply(simp only: equ_pi_to_right[THEN sym])
apply(simp only: equ_involutive_right)
apply(rule equ_refl)
--A
apply(rule subst_not_occurs[THEN mp])
apply(assumption)
--Var.two
apply(simp only: problem_subst_comm)
apply(simp only: all_solutions_def)
apply(simp)
apply(simp only: subst_comp_expand)
apply(subgoal_tac "subst [(X, swap (rev pi) t)] t = t")--B
apply(simp add: subst_susp)
apply(simp only: subst_swap_comm)
apply(simp only: equ_pi_to_left[THEN sym])
apply(simp only: equ_involutive_left)
apply(rule equ_refl)
--B
apply(rule subst_not_occurs[THEN mp])
apply(assumption)
done

lemma P1_to_P2_cred: 
  "\<lbrakk>(nabla1,s1)\<in>U P1; P1 \<turnstile>nabla2\<rightarrow> P2 \<rbrakk>\<Longrightarrow>((nabla1,s1)\<in>U P2) \<and> (nabla1\<Turnstile>(subst s1) nabla2)"
apply(ind_cases " P1\<turnstile>nabla2\<rightarrow>P2")
apply(simp_all)
apply(auto simp add: ext_subst_def all_solutions_def)
apply(rule fresh_swap_left[THEN mp])
apply(simp add: subst_swap_comm[THEN sym] subst_susp)
done

lemma P1_from_P2_cred: 
  "\<lbrakk>(nabla1,s1)\<in>U P2; P1 \<turnstile>nabla2\<rightarrow> P2; nabla3\<Turnstile>(subst s1) nabla2\<rbrakk>\<Longrightarrow>(nabla1\<union>nabla3,s1)\<in>U P1"
apply(ind_cases "P1 \<turnstile>nabla2\<rightarrow> P2")
apply(simp_all)
apply(auto simp add: ext_subst_def all_solutions_def fresh_weak)
apply(simp add: subst_susp)
apply(rule fresh_swap_right[THEN mp])
apply(drule_tac "nabla2.1"="nabla1" in fresh_weak[THEN mp])
apply(subgoal_tac "nabla3 \<union> nabla1=nabla1 \<union> nabla3")--A
apply(simp)
apply(rule Un_commute)
done

lemma P1_to_P2_red_plus: "\<lbrakk>P1 \<Turnstile>(nabla,s)\<Rightarrow>P2\<rbrakk>\<Longrightarrow> (nabla1,s1)\<in>U P1 \<longrightarrow>
  ((nabla1,s1)\<in>U P2)\<and>(nabla1\<Turnstile>subst (s1\<bullet>s)\<approx>subst s1)\<and>(nabla1\<Turnstile>(subst s1) nabla)"
apply(erule red_plus.induct)
-- sred
apply(rule impI)
apply(drule_tac "P2.0"="P2" and "s2.0"="s1a" in P1_to_P2_sred)
apply(force)
apply(rule conjI, force)+
apply(force simp add: ext_subst_def)
-- cred
apply(rule impI)
apply(drule_tac "P2.0"="P2" and "nabla2.0"="nabla1a" in P1_to_P2_cred)
apply(assumption)
apply(force intro!: equ_refl simp add: subst_equ_def)
-- sred
apply(rule impI)
apply(drule_tac "P2.0"="P2" and "s2.0"="s1a" in P1_to_P2_sred)
apply(assumption)
apply(erule conjE)+
apply(rule conjI)
apply(force)
apply(rule conjI)
apply(drule mp)
apply(assumption)
apply(erule conjE)+
apply(rule_tac "s2.0"="((s1\<bullet>s2)\<bullet>s1a)" in subst_trans)
apply(simp only: subst_assoc subst_equ_def)
apply(rule ballI)
apply(rule equ_refl)
apply(rule_tac "s2.0"="(s1\<bullet>s1a)" in subst_trans)
apply(rule subst_cancel_right)
apply(assumption)
apply(assumption)
apply(force)
-- cred
apply(rule impI)
apply(drule_tac "P2.0"="P2" and "nabla2.0"="nabla1a" in P1_to_P2_cred)
apply(auto simp add: ext_subst_def)
done

lemma P1_from_P2_red_plus: "\<lbrakk>P1 \<Turnstile>(nabla,s)\<Rightarrow>P2\<rbrakk>\<Longrightarrow>(nabla1,s1)\<in>U P2\<longrightarrow>
        nabla3\<Turnstile>(subst s1)(nabla)\<longrightarrow>(nabla1\<union>nabla3,(s1\<bullet>s))\<in>U P1"
apply(erule red_plus.induct)
-- sred
apply(rule impI)+
apply(drule_tac "P1.0"="P1" and "s2.0"="s1a" in P1_from_P2_sred)
apply(assumption)
apply(force simp only: all_solutions_def equ_weak fresh_weak)
-- cred
apply(rule impI)+
apply(drule_tac "P1.0"="P1" and "nabla3.0"="nabla3" and "nabla2.0"="nabla1a" in P1_from_P2_cred)
apply(assumption)+
apply(simp add: all_solutions_def)
-- sred
apply(rule impI)+
apply(simp)
apply(drule_tac "P1.0"="P1" and "P2.0"="P2" and "s2.0"="s1a" in P1_from_P2_sred)
apply(assumption)
apply(simp add: all_solutions_def subst_assoc)
-- cred
apply(rule impI)+
apply(subgoal_tac "nabla3 \<Turnstile> (subst s1) nabla2")--A
apply(simp)
apply(drule_tac "P1.0"="P1" and "P2.0"="P2" and
                "nabla2.0"="nabla1a" and "nabla3.0"="nabla3" in P1_from_P2_cred)
apply(assumption)
apply(simp)
apply(simp add: ext_subst_def)
apply(subgoal_tac "nabla1 \<union> nabla3 \<union> nabla3=nabla1 \<union> nabla3")--A
apply(simp)
--A
apply(force)
--B
apply(simp add: ext_subst_def)
done

lemma mgu: "\<lbrakk>P \<Turnstile>(nabla,s)\<Rightarrow>([],[])\<rbrakk>\<Longrightarrow> mgu P (nabla,s) \<and> idem (nabla,s)"
apply(frule_tac "nabla3.2"="nabla" and "nabla2"="nabla" and 
                "s1.2"="[]" and "nabla1.2"="{}"
                in P1_from_P2_red_plus[THEN mp,THEN mp])
apply(force simp add: all_solutions_def)
apply(force simp add: ext_subst_def)
apply(rule mgu_idem)
apply(simp add: all_solutions_def)
apply(rule ballI)
apply(clarify)
apply(drule_tac  "nabla1.0"="a" and "s1.0"="b"in P1_to_P2_red_plus)
apply(simp)
done  

end









