Theory NU
theory NU
imports NU_Termination
begin
section ‹Unification›
text ‹
Proves that all problems that are stuck and fail, have no unifier.
›
definition stuck :: "problem_type set" where
stuck_def: "stuck ≡ { P1. ¬(∃P2 nabla s. P1 ⊨(nabla,s)⇒P2)}"
inductive fail :: "problem_type ⇒ bool" where
fail_occur_abst [intro!]: "⟦occurs X t⟧⟹ fail ((Susp pi X ≈? Abst a t) # xs, ys)" |
fail_occur_func [intro!]: "⟦occurs X t⟧⟹ fail (Susp pi X ≈?Func F t#xs,ys)" |
fail_occur_paar [intro!]: "⟦occurs X t1∨occurs X t2⟧⟹ fail (Susp pi X≈?Paar t1 t2#xs,ys)" |
fail_fresh_atom [intro!]: "fail ([],a♯? Atom a#ys)"|
fail_diff_atoms [intro!]: "a≠b⟹ fail (Atom a≈? Atom b#xs,ys)" |
fail_abst_unit [intro!]: " fail (Abst a t≈?Unit#xs,ys)" |
fail_abst_atom [intro!]: "fail (Abst a t≈?Atom b#xs,ys)" |
fail_abst_paar [intro!]: "fail (Abst a t≈?Paar t1 t2#xs,ys)" |
fail_func_abst [intro!]: "fail (Func F t1≈?Abst a t#xs,ys)" |
fail_atom_unit [intro!]: "fail (Atom b≈?Unit#xs,ys)" |
fail_paar_unit [intro!]: "fail (Paar t1 t2≈?Unit#xs,ys)" |
fail_func_unit [intro!]: "fail (Func F t1≈?Unit#xs,ys)" |
fail_atom_paar [intro!]: "fail (Atom a≈?Paar t1 t2#xs,ys)" |
fail_func_atom [intro!]: "fail (Func F t1≈?Atom a#xs,ys)" |
fail_func_paar [intro!]: "fail (Func F t≈?Paar t1 t2#xs,ys)" |
fail_diff_func [intro!]: "⟦F1≠F2⟧⟹ fail (Func F1 t1≈?Func F2 t2#xs,ys)" |
fail_sym [intro!]: "fail (s ≈? t # xs, ys) ⟹ fail (t ≈? s # xs, ys)"
definition
normal_form :: "problem_type ⇒ problem_type set" where
"normal_form P1 ≡ if P1 ∈ stuck then {P1} else {P2. ∃nabla s. P1⊨(nabla,s)⇒P2 ∧ P2∈stuck}"
lemma U_equ_symm:
shows "U (s≈?t#xs, ys) = U (t≈?s#xs, ys)"
by(auto simp add: all_solutions_def equ_symm)
lemma fail_then_empty:
assumes "fail P1"
shows "U P1 = {}"
using assms
proof(induct rule: fail.induct)
case (fail_occur_abst X t pi a xs ys)
let ?P = "(Susp pi X ≈? Abst a t # xs, ys)"
{ assume "U ((Susp pi X, Abst a t) # xs, ys) ≠ {}"
then obtain s nabla where eq1: "nabla ⊢ subst s (Susp pi X) ≈ Abst a (subst s t)"
by (auto simp add: all_solutions_def)
moreover
have "occurs X t" by fact
then obtain t' pi' where
eq2: "nabla ⊢ subst s (Susp pi X) ≈ swap pi' t'" "t'∈sub_trms (subst s t)"
using occurs_sub_trm_equ by blast
moreover
have eq3: "¬ nabla ⊢ (Abst a (subst s t)) ≈ swap pi' t'"
using eq2 psub_trm_not_equ by auto
then have "False" using eq1 eq2 eq3
by (metis equ_symm equ_trans)
}
then show "U ?P = {}" by auto
next
case (fail_occur_func X t pi F xs ys)
let ?P = "(Susp pi X ≈? Func F t # xs, ys)"
{ assume "U ((Susp pi X, Func F t) # xs, ys) ≠ {}"
then obtain s nabla where eq1: "nabla ⊢ subst s (Susp pi X) ≈ Func F (subst s t)"
by (auto simp add: all_solutions_def)
moreover
have "occurs X t" by fact
then obtain t' pi' where
eq2: "nabla ⊢ subst s (Susp pi X) ≈ swap pi' t'" "t'∈sub_trms (subst s t)"
using occurs_sub_trm_equ by blast
moreover
have eq3: "¬ nabla ⊢ (Func F (subst s t)) ≈ swap pi' t'"
using eq2 psub_trm_not_equ by auto
then have "False" using eq1 eq2 eq3
by (metis equ_symm equ_trans)
}
then show "U ?P = {}" by auto
next
case (fail_occur_paar X t1 t2 pi xs ys)
let ?P = "(Susp pi X ≈? Paar t1 t2 # xs, ys)"
have "occurs X t1 ∨ occurs X t2" by fact
then show "U ?P = {}"
proof
{assume "occurs X t1"
{assume "U ((Susp pi X, Paar t1 t2) # xs, ys) ≠ {}"
then obtain s nabla where eq1: "nabla ⊢ subst s (Susp pi X) ≈ Paar (subst s t1) (subst s t2)"
by (auto simp add: all_solutions_def)
moreover
have "occurs X t1" by fact
then obtain t' pi' where
eq2: "nabla ⊢ subst s (Susp pi X) ≈ swap pi' t'" "t'∈sub_trms (subst s t1)"
using occurs_sub_trm_equ by blast
moreover
have eq3: "¬ nabla ⊢ (Paar (subst s t1) (subst s t2)) ≈ swap pi' t'"
using eq2 psub_trm_not_equ by auto
then have "False" using eq1 eq2 eq3
by (metis equ_symm equ_trans)}
then show "U ?P = {}" by auto}
{assume "occurs X t2"
{assume "U ((Susp pi X, Paar t1 t2) # xs, ys) ≠ {}"
then obtain s nabla where eq1: "nabla ⊢ subst s (Susp pi X) ≈ Paar (subst s t1) (subst s t2)"
by (auto simp add: all_solutions_def)
moreover
have "occurs X t2" by fact
then obtain t' pi' where
eq2: "nabla ⊢ subst s (Susp pi X) ≈ swap pi' t'" "t'∈sub_trms (subst s t2)"
using occurs_sub_trm_equ by blast
moreover
have eq3: "¬ nabla ⊢ (Paar (subst s t1) (subst s t2)) ≈ swap pi' t'"
using eq2 psub_trm_not_equ by auto
then have "False" using eq1 eq2 eq3
by (metis equ_symm equ_trans)
}
then show "U ?P = {}" by auto}
qed
next
case (fail_fresh_atom a ys)
let ?P = "([], a ♯? Atom a # ys)"
have "∄ nabla s. nabla ⊢ a ♯ subst s (Atom a)"
using subst_atom Fresh_elims(3) by auto
thus "U ?P = {}"
using all_solutions_def by simp
next
case (fail_diff_atoms a b xs ys)
let ?P = "(Atom a ≈? Atom b # xs, ys)"
from ‹a ≠ b› have "∄ nabla s. nabla ⊢ subst s (Atom a) ≈ subst s (Atom b)"
using Equ_elims(1) by auto
thus "U ?P = {}"
using all_solutions_def by simp
next
case (fail_abst_unit a t xs ys)
let ?P = "(Abst a t ≈? Unit # xs, ys)"
have "∄ nabla s. nabla ⊢ subst s (Abst a t) ≈ subst s Unit"
by (auto elim: equ.cases)
thus "U ?P = {}"
using all_solutions_def by simp
next
case (fail_abst_atom a t b xs ys)
let ?P = "(Abst a t ≈? Atom b # xs, ys)"
have "∄ nabla s. nabla ⊢ subst s (Abst a t) ≈ subst s (Atom b)"
by (auto elim: equ.cases)
thus "U ?P = {}"
using all_solutions_def by simp
next
case (fail_abst_paar a t t1 t2 xs ys)
let ?P = "(Abst a t ≈? Paar t1 t2 # xs, ys)"
have "∄ nabla s. nabla ⊢ subst s (Abst a t) ≈ subst s (Paar t1 t2)"
by (auto elim: equ.cases)
thus "U ?P = {}"
using all_solutions_def by simp
next
case (fail_func_abst F t1 a t xs ys)
let ?P = "(Func F t1 ≈? Abst a t # xs, ys)"
have "∄ nabla s. nabla ⊢ subst s (Func F t1) ≈ subst s (Abst a t)"
by (auto elim: equ.cases)
thus "U ?P = {}"
using all_solutions_def by simp
next
case (fail_atom_unit b xs ys)
let ?P = "(Atom b ≈? Unit # xs, ys)"
have "∄ nabla s. nabla ⊢ subst s (Atom b) ≈ subst s (Unit)"
by (auto elim: equ.cases)
thus "U ?P = {}"
using all_solutions_def by simp
next
case (fail_paar_unit t1 t2 xs ys)
let ?P = "(Paar t1 t2 ≈? Unit # xs, ys)"
have "∄ nabla s. nabla ⊢ subst s (Paar t1 t2) ≈ subst s (Unit)"
by (auto elim: equ.cases)
thus "U ?P = {}"
using all_solutions_def by simp
next
case (fail_func_unit F t1 xs ys)
let ?P = "(Func F t1≈? Unit # xs, ys)"
have "∄ nabla s. nabla ⊢ subst s (Func F t1) ≈ subst s (Unit)"
by (auto elim: equ.cases)
thus "U ?P = {}"
using all_solutions_def by simp
next
case (fail_atom_paar b t1 t2 xs ys)
let ?P = "(Atom b ≈? Paar t1 t2 # xs, ys)"
have "∄ nabla s. nabla ⊢ subst s (Atom b) ≈ subst s (Paar t1 t2)"
by (auto elim: equ.cases)
thus "U ?P = {}"
using all_solutions_def by simp
next
case (fail_func_atom F t1 b xs ys)
let ?P = "(Func F t1 ≈? Atom b # xs, ys)"
have "∄ nabla s. nabla ⊢ subst s (Func F t1) ≈ subst s (Atom b)"
by (auto elim: equ.cases)
thus "U ?P = {}"
using all_solutions_def by simp
next
case (fail_func_paar F t t1 t2 xs ys)
let ?P = "(Func F t ≈? Paar t1 t2 # xs, ys)"
have "∄ nabla s. nabla ⊢ subst s (Func F t) ≈ subst s (Paar t1 t2)"
by (auto elim: equ.cases)
thus "U ?P = {}"
using all_solutions_def by simp
next
case (fail_diff_func F1 F2 t1 t2 xs ys)
let ?P = "(Func F1 t1 ≈? Func F2 t2 # xs, ys)"
from ‹F1 ≠ F2› have "∄ nabla s. nabla ⊢ subst s (Func F1 t1) ≈ subst s (Func F2 t2)"
by (auto elim: equ.cases)
thus "U ?P = {}"
using all_solutions_def by simp
next
case (fail_sym s t xs ys)
let ?P = "(t ≈? s # xs, ys)"
have "fail ((s, t) # xs, ys)"
"U ((s, t) # xs, ys) = {}" by fact+
thus "U ?P = {}"
using all_solutions_def U_equ_symm by simp
qed
lemma not_reduce_then_fail:
assumes "¬ (∃nabla s P'. ((t1 ≈? t2) # xs, ys) ⊨ (nabla,s) ⇒ P')"
shows "fail ((t1 ≈? t2) # xs, ys)"
using assms
proof(cases t1)
case (Abst a t1')
have t1_def: "t1 = Abst a t1'" by fact
then show "fail ((t1, t2) # xs, ys)"
proof(cases t2)
case (Abst b t2')
with t1_def
have "((t1 ≈? t2)#xs,ys) ⊢[]↝ ((t1'≈?t2')#xs,ys) ∨
((t1≈? t2)#xs,ys) ⊢[]↝ ((t1'≈?swap [(a,b)] t2')#xs,(a♯?t2')#ys)"
using abst_aa_sred abst_ab_sred by (cases "a=b") auto
hence "∃ P2. ((t1 ≈? t2)#xs,ys) ⊨({},[])⇒P2"
using sred_single by blast
thus "fail ((t1, t2) # xs, ys)"
using assms by simp
next
case (Susp pi X)
have t2_def: "t2 = Susp pi X" by fact
with t1_def
show "fail ((t1, t2) # xs, ys)"
proof(cases "occurs X t1'")
case True
with t1_def t2_def
show "fail ((t1, t2) # xs, ys)"
using fail_sym[OF fail_occur_abst[OF True]] by simp
next
case False
with t1_def
have not_occurs: "¬ occurs X t1" by simp
hence "((t1≈? Susp pi X)#xs,ys)
⊢[(X,swap (rev pi) t1)]↝ apply_subst [(X,swap (rev pi) t1)] (xs,ys)"
using t1_def var_2_sred[OF not_occurs] by simp
hence "∃ P2 s. ((t1 ≈? t2)#xs,ys) ⊨({},s)⇒P2"
using t1_def t2_def sred_single by blast
thus "fail ((t1, t2) # xs, ys)"
using assms by simp
qed
qed (auto)
next
case (Susp pi X)
have t1_def: "t1 = Susp pi X" by fact
then show "fail ((t1, t2) # xs, ys)"
proof(cases "occurs X t2")
case True
then show "fail ((t1, t2) # xs, ys)"
proof(cases t2)
case (Abst a t2')
have t2_def: "t2 = Abst a t2'" by fact
with True
have "occurs X t2'" unfolding occurs.simps(4) t2_def by argo
thus "fail ((t1, t2) # xs, ys)"
using t1_def t2_def fail_occur_abst by simp
next
case (Susp pi' Y)
have t2_def: "t2 = Susp pi' Y" by fact
have "X = Y"
using True unfolding t2_def occurs.simps(3)
by argo
hence "((Susp pi X≈?Susp pi' Y)#xs,ys)
⊢[]↝ (xs,(map (λa. a♯? Susp [] X) (ds_list pi pi'))@ys)"
using susp_sred by simp
hence "∃ P2. ((t1 ≈? t2)#xs,ys) ⊨({},[])⇒P2"
using sred_single t1_def t2_def by blast
thus"fail ((t1, t2) # xs, ys)"
using assms by simp
next
case (Paar t21 t22)
have t2_def: "t2 = Paar t21 t22" by fact
with True
have "occurs X t21 ∨ occurs X t22" unfolding occurs.simps(5) t2_def by argo
thus "fail ((t1, t2) # xs, ys)"
using t1_def t2_def fail_occur_paar by simp
next
case (Func f t2')
have t2_def: "t2 = Func f t2'" by fact
with True
have "occurs X t2'" unfolding occurs.simps(6) t2_def by argo
thus "fail ((t1, t2) # xs, ys)"
using t1_def t2_def fail_occur_func by simp
qed (auto simp add: True)
next
case False
hence "((Susp pi X, t2) # xs, ys) ⊢
[(X, swap (rev pi) t2)] ↝ apply_subst [(X, swap (rev pi) t2)] (xs, ys)"
using var_1_sred[OF False] by simp
hence "∃ P2 s. ((t1 ≈? t2)#xs,ys) ⊨({},s)⇒P2"
using t1_def sred_single by blast
thus "fail ((t1, t2) # xs, ys)"
using assms by simp
qed
next
case Unit
have t1_def: "t1 = Unit" by fact
then show "fail ((t1, t2) # xs, ys)"
proof(cases t2)
case (Susp pi X)
have t2_def: "t2 = Susp pi X" by fact
with t1_def have not_occurs: "¬ occurs X t1" by simp
hence "((t1≈? Susp pi X)#xs,ys)
⊢[(X,swap (rev pi) t1)]↝ apply_subst [(X,swap (rev pi) t1)] (xs,ys)"
using t1_def var_2_sred[OF not_occurs] by simp
hence "∃ P2 s. ((t1 ≈? t2)#xs,ys) ⊨({},s)⇒P2"
using t1_def t2_def sred_single by blast
thus "fail ((t1, t2) # xs, ys)"
using assms by simp
next
case Unit
with t1_def
have "((t1 ≈? t2)#xs,ys) ⊢[]↝ (xs,ys)"
using unit_sred by auto
hence "∃ P2. ((t1 ≈? t2)#xs,ys) ⊨({},[])⇒P2"
using sred_single by blast
thus "fail ((t1, t2) # xs, ys)"
using assms by simp
qed (auto)
next
case (Atom a)
have t1_def: "t1 = Atom a" by fact
then show "fail ((t1, t2) # xs, ys)"
proof(cases t2)
case (Susp pi X)
have t2_def: "t2 = Susp pi X" by fact
with t1_def have not_occurs: "¬ occurs X t1" by simp
hence "((t1≈? Susp pi X)#xs,ys)
⊢[(X,swap (rev pi) t1)]↝ apply_subst [(X,swap (rev pi) t1)] (xs,ys)"
using t1_def var_2_sred[OF not_occurs] by simp
hence "∃ P2 s. ((t1 ≈? t2)#xs,ys) ⊨({},s)⇒P2"
using t1_def t2_def sred_single by blast
thus "fail ((t1, t2) # xs, ys)"
using assms by simp
next
case (Atom b)
have t2_def: "t2 = Atom b" by fact
then show "fail ((t1, t2) # xs, ys)"
proof(cases "a=b")
case True
hence "((t1 ≈? t2)#xs,ys) ⊢[]↝ (xs,ys)"
using t2_def t1_def atom_sred by simp
hence "∃ P2. ((t1 ≈? t2)#xs,ys) ⊨({},[])⇒P2"
using sred_single by blast
thus "fail ((t1, t2) # xs, ys)"
using assms by simp
qed (simp add: t1_def t2_def fail_diff_atoms)
qed(auto)
next
case (Paar t11 t12)
have t1_def: "t1 = Paar t11 t12" by fact
then show "fail ((t1, t2) # xs, ys)"
proof(cases t2)
next
case (Susp pi X)
have t2_def: "t2 = Susp pi X" by fact
then show "fail ((t1, t2) # xs, ys)"
proof(cases "occurs X t11 ∨ occurs X t12")
case True
then show "fail ((t1, t2) # xs, ys)"
using t1_def t2_def fail_sym[OF fail_occur_paar[OF True]] by simp
next
case False
hence "¬ occurs X t1"
using t1_def by simp
hence "((t1≈?Susp pi X)#xs,ys)
⊢[(X,swap (rev pi) t1)]↝ apply_subst [(X,swap (rev pi) t1)] (xs,ys)"
by auto
hence "∃ P2 s. ((t1 ≈? t2)#xs,ys) ⊨({},s)⇒P2"
using t1_def t2_def sred_single by blast
thus "fail ((t1, t2) # xs, ys)"
using assms by simp
qed
next
case (Paar t21 t22)
have t2_def: "t2 = Paar t21 t22" by fact
with t1_def have
"((t1 ≈? t2)#xs,ys) ⊢[]↝ ((t11≈?t21)#(t12≈?t22)#xs,ys)"
using paar_sred by simp
hence "∃ P2. ((t1 ≈? t2)#xs,ys) ⊨({},[])⇒P2"
using sred_single by blast
thus "fail ((t1, t2) # xs, ys)"
using assms by simp
qed(auto)
next
case (Func f t1')
have t1_def: "t1 = Func f t1'" by fact
then show "fail ((t1, t2) # xs, ys)"
proof(cases t2)
case (Susp pi X)
have t2_def: "t2 = Susp pi X" by fact
with t1_def
show "fail ((t1, t2) # xs, ys)"
proof(cases "occurs X t1'")
case True
with t1_def t2_def
show "fail ((t1, t2) # xs, ys)"
using fail_sym[OF fail_occur_func[OF True]] by simp
next
case False
with t1_def
have not_occurs: "¬ occurs X t1" by simp
hence "((t1≈? Susp pi X)#xs,ys)
⊢[(X,swap (rev pi) t1)]↝ apply_subst [(X,swap (rev pi) t1)] (xs,ys)"
using t1_def var_2_sred[OF not_occurs] by simp
hence "∃ P2 s. ((t1 ≈? t2)#xs,ys) ⊨({},s)⇒P2"
using t1_def t2_def sred_single by blast
thus "fail ((t1, t2) # xs, ys)"
using assms by simp
qed
next
case (Func g t2')
have t2_def: "t2 = Func g t2'" by fact
then show "fail ((t1, t2) # xs, ys)"
proof(cases "f=g")
case True
hence "((t1 ≈? t2)#xs,ys) ⊢[]↝ ((t1'≈?t2')#xs,ys)"
using t1_def t2_def func_sred by simp
hence "∃ P2. ((t1 ≈? t2)#xs,ys) ⊨({},[])⇒P2"
using sred_single by blast
thus "fail ((t1, t2) # xs, ys)"
using assms by simp
next
case False
then show "fail ((t1, t2) # xs, ys)"
using t1_def t2_def fail_diff_func[OF False] by simp
qed
qed(auto)
qed
lemma fresh_reduces_if_not_atom:
assumes "t ≠ Atom a"
shows "∃P2 nabla s. ([], (a ♯? t) # xs) ⊨ (nabla,s) ⇒ P2"
using assms cred_single
proof(cases t)
case (Abst b t')
then show "∃P2 nabla s. ([], (a ♯? t) # xs) ⊨ (nabla, s) ⇒ P2"
proof(cases "a=b")
case True
hence "([], (a ♯? t) # xs) ⊢{}→ ([],xs)"
unfolding Abst using abst_aa_cred by simp
then show "∃P2 nabla s. ([], (a ♯? t) # xs) ⊨ (nabla, s) ⇒ P2"
using cred_single by blast
next
case False
hence "([], (a ♯? t) # xs) ⊢{}→ ([], (a♯? t') # xs)"
unfolding Abst using abst_ab_cred by simp
then show "∃P2 nabla s. ([], (a ♯? t) # xs) ⊨ (nabla, s) ⇒ P2"
using cred_single by blast
qed
next
case (Atom b)
with assms
have "a ≠ b" by simp
hence "([], (a ♯? t) # xs) ⊢ {}→ ([],xs)"
unfolding Atom using atom_cred by simp
then show "∃P2 nabla s. ([], (a ♯? t) # xs) ⊨ (nabla, s) ⇒ P2"
using cred_single by blast
qed (simp add: cred_single, blast+)
lemma empty_stuck:
shows "([],[]) ∈ stuck"
proof-
have "¬ (∃P2 nabla s. ([],[]) ⊨ (nabla,s) ⇒ P2)"
by (auto elim: red_plus.cases s_red.cases c_red.cases)
thus "([],[]) ∈ stuck"
unfolding stuck_def by auto
qed
lemma fail_is_stuck:
assumes "fail P"
shows "P ∈ stuck"
using assms
proof(induct rule: fail.induct)
case (fail_occur_abst X t pi a xs ys)
have t_occurs: "occurs X t" by fact
moreover have "¬ (∃P2 nabla s. ((Susp pi X ≈? Abst a t) # xs, ys) ⊨ (nabla,s) ⇒ P2)"
proof
assume "∃P2 nabla s. ((Susp pi X ≈? Abst a t) # xs, ys) ⊨ (nabla,s) ⇒ P2"
then obtain P2 nabla s where
red: "((Susp pi X ≈? Abst a t) # xs, ys) ⊨ (nabla,s) ⇒ P2"
by auto
thus False
proof (cases rule: red_plus.cases)
case sred_single
have "((Susp pi X, Abst a t) # xs, ys) ⊢ s ↝ P2" by fact
hence "¬ occurs X t"
by (auto elim: s_red.cases)
with t_occurs show False by simp
next
case cred_single
have "((Susp pi X, Abst a t) # xs, ys) ⊢ nabla → P2" by fact
moreover have "fst ((Susp pi X, Abst a t) # xs, ys) ≠ []"
by simp
ultimately show False
using c_red_eqs_empty by blast
next
case (sred_step s1 P3 s2)
have "((Susp pi X, Abst a t) # xs, ys) ⊢ s1 ↝ P3" by fact
hence "¬ occurs X t"
by (auto elim: s_red.cases)
with t_occurs show False by simp
next
case (cred_step nabla1 P3 nabla2)
have "((Susp pi X, Abst a t) # xs, ys) ⊢ nabla1 → P3" by fact
moreover have "fst ((Susp pi X, Abst a t) # xs, ys) ≠ []"
by simp
ultimately show False
using c_red_eqs_empty by blast
qed
qed
then show "((Susp pi X, Abst a t) # xs, ys) ∈ stuck"
unfolding stuck_def by simp
next
case (fail_occur_func X t pi F xs ys)
have t_occurs: "occurs X t" by fact
moreover have "¬ (∃P2 nabla s. ((Susp pi X ≈? Func F t) # xs, ys) ⊨ (nabla,s) ⇒ P2)"
proof
assume "∃P2 nabla s. ((Susp pi X ≈? Func F t) # xs, ys) ⊨ (nabla,s) ⇒ P2"
then obtain P2 nabla s where
red: "((Susp pi X ≈? Func F t) # xs, ys) ⊨ (nabla,s) ⇒ P2"
by auto
thus False
proof (cases rule: red_plus.cases)
case sred_single
have "((Susp pi X, Func F t) # xs, ys) ⊢ s ↝ P2" by fact
hence "¬ occurs X t"
by (auto elim: s_red.cases)
with t_occurs show False by simp
next
case cred_single
have "((Susp pi X, Func F t) # xs, ys) ⊢ nabla → P2" by fact
moreover have "fst ((Susp pi X, Func F t) # xs, ys) ≠ []"
by simp
ultimately show False
using c_red_eqs_empty by blast
next
case (sred_step s1 P3 s2)
have "((Susp pi X, Func F t) # xs, ys) ⊢ s1 ↝ P3" by fact
hence "¬ occurs X t"
by (auto elim: s_red.cases)
with t_occurs show False by simp
next
case (cred_step nabla1 P3 nabla2)
have "((Susp pi X, Func F t) # xs, ys) ⊢ nabla1 → P3" by fact
moreover have "fst ((Susp pi X, Func F t) # xs, ys) ≠ []"
by simp
ultimately show False
using c_red_eqs_empty by blast
qed
qed
then show "((Susp pi X, Func F t) # xs, ys) ∈ stuck"
unfolding stuck_def by simp
next
case (fail_occur_paar X t1 t2 pi xs ys)
have "occurs X t1 ∨ occurs X t2" by fact
hence t_occurs: "occurs X (Paar t1 t2)"
using occurs.simps(5) by auto
moreover have "¬ (∃P2 nabla s. ((Susp pi X ≈? Paar t1 t2) # xs, ys) ⊨ (nabla,s) ⇒ P2)"
proof
assume "∃P2 nabla s. ((Susp pi X ≈? Paar t1 t2) # xs, ys) ⊨ (nabla,s) ⇒ P2"
then obtain P2 nabla s where
red: "((Susp pi X ≈? Paar t1 t2) # xs, ys) ⊨ (nabla,s) ⇒ P2"
by auto
thus False
proof (cases rule: red_plus.cases)
case sred_single
have "((Susp pi X, Paar t1 t2) # xs, ys) ⊢ s ↝ P2" by fact
hence "¬ occurs X (Paar t1 t2)"
by (auto elim: s_red.cases)
with t_occurs show False by simp
next
case cred_single
have "((Susp pi X, Paar t1 t2) # xs, ys) ⊢ nabla → P2" by fact
moreover have "fst ((Susp pi X, Paar t1 t2) # xs, ys) ≠ []"
by simp
ultimately show False
using c_red_eqs_empty by blast
next
case (sred_step s1 P3 s2)
have "((Susp pi X, Paar t1 t2) # xs, ys) ⊢ s1 ↝ P3" by fact
hence "¬ occurs X (Paar t1 t2)"
by (auto elim: s_red.cases)
with t_occurs show False by simp
next
case (cred_step nabla1 P3 nabla2)
have "((Susp pi X, Paar t1 t2) # xs, ys) ⊢ nabla1 → P3" by fact
moreover have "fst ((Susp pi X, Paar t1 t2) # xs, ys) ≠ []"
by simp
ultimately show False
using c_red_eqs_empty by blast
qed
qed
then show "((Susp pi X, Paar t1 t2) # xs, ys) ∈ stuck"
unfolding stuck_def by simp
next
case (fail_fresh_atom a ys)
have "¬ (∃P2 nabla s. ([], (a, Atom a) # ys) ⊨ (nabla,s) ⇒ P2)"
by (auto elim: red_plus.cases s_red.cases c_red.cases)
then show "([], (a, Atom a) # ys) ∈ stuck"
unfolding stuck_def by simp
next
case (fail_diff_atoms a b xs ys)
hence "¬ (∃P2 nabla s. ((Atom a, Atom b) # xs, ys) ⊨ (nabla,s) ⇒ P2)"
by (auto elim: red_plus.cases s_red.cases c_red.cases)
then show "((Atom a, Atom b) # xs, ys) ∈ stuck"
unfolding stuck_def by simp
next
case (fail_abst_unit a t xs ys)
hence "¬ (∃P2 nabla s. ((Abst a t, Unit) # xs, ys) ⊨ (nabla,s) ⇒ P2)"
by (auto elim: red_plus.cases s_red.cases c_red.cases)
then show "((Abst a t, Unit) # xs, ys) ∈ stuck"
unfolding stuck_def by simp
next
case (fail_abst_atom a t b xs ys)
hence "¬ (∃P2 nabla s. ((Abst a t, Atom b) # xs, ys) ⊨ (nabla,s) ⇒ P2)"
by (auto elim: red_plus.cases s_red.cases c_red.cases)
then show "((Abst a t, Atom b) # xs, ys) ∈ stuck"
unfolding stuck_def by simp
next
case (fail_abst_paar a t t1 t2 xs ys)
hence "¬ (∃P2 nabla s. ((Abst a t, Paar t1 t2) # xs, ys) ⊨ (nabla,s) ⇒ P2)"
by (auto elim: red_plus.cases s_red.cases c_red.cases)
then show "((Abst a t, Paar t1 t2) # xs, ys) ∈ stuck"
unfolding stuck_def by simp
next
case (fail_func_abst F t1 a t xs ys)
hence "¬ (∃P2 nabla s. ((Func F t1, Abst a t) # xs, ys) ⊨ (nabla,s) ⇒ P2)"
by (auto elim: red_plus.cases s_red.cases c_red.cases)
then show "((Func F t1, Abst a t) # xs, ys) ∈ stuck"
unfolding stuck_def by simp
next
case (fail_atom_unit b xs ys)
hence "¬ (∃P2 nabla s. ((Atom b, Unit) # xs, ys) ⊨ (nabla,s) ⇒ P2)"
by (auto elim: red_plus.cases s_red.cases c_red.cases)
then show "((Atom b, Unit) # xs, ys) ∈ stuck"
unfolding stuck_def by simp
next
case (fail_paar_unit t1 t2 xs ys)
hence "¬ (∃P2 nabla s. ((Paar t1 t2, Unit) # xs, ys) ⊨ (nabla,s) ⇒ P2)"
by (auto elim: red_plus.cases s_red.cases c_red.cases)
then show "((Paar t1 t2, Unit) # xs, ys) ∈ stuck"
unfolding stuck_def by simp
next
case (fail_func_unit F t1 xs ys)
hence "¬ (∃P2 nabla s. ((Func F t1, Unit) # xs, ys) ⊨ (nabla,s) ⇒ P2)"
by (auto elim: red_plus.cases s_red.cases c_red.cases)
then show "((Func F t1, Unit) # xs, ys) ∈ stuck"
unfolding stuck_def by simp
next
case (fail_atom_paar a t1 t2 xs ys)
hence "¬ (∃P2 nabla s. ((Atom a, Paar t1 t2) # xs, ys) ⊨ (nabla,s) ⇒ P2)"
by (auto elim: red_plus.cases s_red.cases c_red.cases)
then show "((Atom a, Paar t1 t2) # xs, ys) ∈ stuck"
unfolding stuck_def by simp
next
case (fail_func_atom F t1 a xs ys)
hence "¬ (∃P2 nabla s. ((Func F t1, Atom a) # xs, ys) ⊨ (nabla,s) ⇒ P2)"
by (auto elim: red_plus.cases s_red.cases c_red.cases)
then show "((Func F t1, Atom a) # xs, ys) ∈ stuck"
unfolding stuck_def by simp
next
case (fail_func_paar F t t1 t2 xs ys)
hence "¬ (∃P2 nabla s. ((Func F t, Paar t1 t2) # xs, ys) ⊨ (nabla,s) ⇒ P2)"
by (auto elim: red_plus.cases s_red.cases c_red.cases)
then show "((Func F t, Paar t1 t2) # xs, ys) ∈ stuck"
unfolding stuck_def by simp
next
case (fail_diff_func F1 F2 t1 t2 xs ys)
hence "¬ (∃P2 nabla s. ((Func F1 t1, Func F2 t2) # xs, ys) ⊨ (nabla,s) ⇒ P2)"
by (auto elim: red_plus.cases s_red.cases c_red.cases)
then show "((Func F1 t1, Func F2 t2) # xs, ys) ∈ stuck"
unfolding stuck_def by simp
next
case (fail_sym s t xs ys)
hence not_reduce: "∄ P2 nabla s1. ((s, t) # xs, ys) ⊨ (nabla, s1) ⇒ P2"
unfolding stuck_def by simp
have"∄ P2 nabla s1. ((t, s) # xs, ys) ⊨ (nabla, s1) ⇒ P2"
proof
assume "∃P2 nabla s1. ((t, s) # xs, ys) ⊨ (nabla, s1) ⇒ P2"
then obtain P2 nabla s1 where
reduces: "((t, s) # xs, ys) ⊨ (nabla, s1) ⇒ P2"
by auto
hence "∃ P3 nabla1 s2. ((s, t) # xs, ys) ⊨ (nabla1, s2) ⇒ P3"
using red_plus_symm[of ‹((t, s) # xs, ys)› t s xs ys nabla s1 P2] by auto
with not_reduce show False by simp
qed
then show "((t, s) # xs, ys) ∈ stuck" unfolding stuck_def by simp
qed
lemma stuck_equiv:
shows "stuck = {([],[])} ∪ {P1. fail P1}"
proof (rule set_eqI, rule iffI)
fix P
{assume P_is_stuck: "P ∈ stuck"
then obtain eqs freshs where
P_def: "P = (eqs, freshs)" by (cases P)
show "P ∈ {([], [])} ∪ {P1. fail P1}"
proof(cases eqs)
case Nil
then show "P ∈ {([], [])} ∪ {P1. fail P1}"
proof(cases freshs)
case Nil
with ‹eqs = []›
show "P ∈ {([], [])} ∪ {P1. fail P1}" using P_def by simp
next
case (Cons c freshs')
then obtain a t where c_def: "c = a ♯? t" by force
have "t = Atom a"
using fresh_reduces_if_not_atom P_is_stuck
unfolding stuck_def P_def Nil Cons c_def by blast
hence "fail P"
unfolding P_def Nil Cons c_def using fail_fresh_atom by simp
thus "P ∈ {([], [])} ∪ {P1. fail P1}" by auto
qed
next
case(Cons e eqs')
then obtain s t where e_def: "e = s ≈? t" by force
have "fail P"
using P_is_stuck unfolding P_def Cons e_def
stuck_def using not_reduce_then_fail by simp
thus "P ∈ {([], [])} ∪ {P1. fail P1}" by auto
qed }
{assume "P ∈ {([], [])} ∪ {P1. fail P1}"
then show "P ∈ stuck"
using empty_stuck fail_is_stuck by blast
}
qed
lemma u_empty_sred:
assumes "P1⊢s↝P2" and "U P2 ={}"
shows "U P1 = {}"
using assms P1_from_P2_sred all_solutions_def P1_to_P2_sred by blast
lemma u_empty_cred:
assumes "P1⊢nabla→P2" and "U P2 ={}"
shows "U P1={}"
using assms P1_from_P2_cred all_solutions_def P1_to_P2_cred by blast
lemma u_empty_red_plus:
assumes "P1⊨(nabla,s)⇒P2" and "U P2 ={}"
shows "U P1={}"
using assms P1_from_P2_red_plus all_solutions_def P1_to_P2_red_plus1 by fast
lemma empty_then_fail:
assumes "U P1={}"
shows" (∀P ∈ normal_form P1. fail P)"
proof
fix P
assume P_is_nf: "P ∈ normal_form P1"
hence P_is_stuck: "P ∈ stuck"
using normal_form_def by (cases "P1 ∈ stuck") auto
hence P_is_empty_or_fails: "P = ([],[]) ∨ fail P"
using stuck_equiv by auto
have "P ≠ ([],[])"
proof
assume P_empty: "P = ([],[])"
hence solution: "({},[]) ∈ U P"
using all_solutions_def by simp
hence P_neq: "P ≠ P1"
using assms by auto
show False
proof(cases "P1∈ stuck")
case True
then have "normal_form P1 = {P1}"
unfolding normal_form_def by simp
with P_is_nf have "P = P1" by simp
with P_neq show False by simp
next
case False
with P_is_nf
obtain nabla s where P1_goes_to_P: "P1 ⊨ (nabla, s) ⇒ P"
unfolding normal_form_def by auto
hence "({} ∪ nabla, [] ∙ s) ∈ U P1"
using P1_from_P2_red_plus[OF P1_goes_to_P solution ext_subst_id] by simp
with assms show False by simp
qed
qed
thus "fail P"
using P_is_empty_or_fails by simp
qed
lemma not_empty_then_not_fail:
assumes "U P1≠{}"
shows "¬(∃P∈ normal_form P1. fail P)"
proof(simp, rule ballI)
fix P
assume P_is_nf: "P ∈ normal_form P1"
show "¬ fail P"
proof
assume P_fails: "fail P"
show False
proof(cases "P1∈ stuck")
case True
have "normal_form P1 = {P1}"
unfolding normal_form_def using True by simp
hence "P = P1" using P_is_nf by simp
with P_fails have "U P1 = {}"
using fail_then_empty by simp
thus False using assms by simp
next
case False
with P_is_nf
obtain nabla s where P1_goes_to_P: "P1 ⊨ (nabla, s) ⇒ P"
unfolding normal_form_def by auto
moreover have "U P = {}"
using P_fails fail_then_empty by simp
ultimately have "U P1 = {}"
using u_empty_red_plus by simp
then show False
using assms by simp
qed
qed
qed
end