Theory NU_Completeness
theory NU_Completeness
imports NU_Soundness
begin
section‹Completeness›
text‹Defines a reflexive-transitive relation from Freshness and Nominal Equational decomposition
and an inductive schema for proving completeness.›
text‹The reflexive-transitive closures of sred and cred.›
inductive sred_rtc :: "problem_type ⇒ substs ⇒ problem_type ⇒ bool" ("_ ⊢ _ ↝⇧* _" [80,80,80] 80)
where
sred_refl[intro!]: "P1 ⊢ [] ↝⇧* P1" |
sred_rtc_step[intro!]: "⟦P1 ⊢ s1 ↝ P2; P2 ⊢ s2 ↝⇧* P3⟧ ⟹ P1 ⊢ (s2 ∙ s1) ↝⇧* P3"
inductive cred_rtc :: "problem_type ⇒ fresh_envs ⇒ problem_type ⇒ bool" ("_ ⊢ _ →⇧* _ " [80,80,80] 80)
where
cred_refl[intro!] : "P1 ⊢ {} →⇧* P1" |
cred_rtc_step[intro!] : "⟦P1 ⊢ nabla1 → P2; P2 ⊢ nabla2 →⇧* P3⟧ ⟹ P1 ⊢ (nabla2 ∪ nabla1) →⇧* P3"
text‹Either the measure reduces or the problem stays the same under equation reductions.›
lemma rank_r_sred_rtc:
assumes "P1 ⊢ s ↝⇧* P2"
shows "(P2, P1) ∈ rank_r ∨ P1 = P2"
using assms
proof (induct rule: sred_rtc.induct)
case (sred_refl P1)
then show "(P1, P1) ∈ rank_r ∨ P1 = P1" by simp
next
case (sred_rtc_step P1 s1 P' s2 P2)
then have "(P', P1) ∈ rank_r"
using rank_r_sred by blast
moreover have "(P2, P') ∈ rank_r ∨ P' = P2"
using sred_rtc_step by simp
ultimately show "(P2, P1) ∈ rank_r ∨ P1 = P2"
using sred_rtc_step rank_r_trans by blast
qed
text‹If the problem does not change under the reflexive-transitive closure of sred,
the substitution must be empty.›
lemma sred_rtc_no_cycle:
assumes "P ⊢ s ↝⇧* P"
shows "s = []"
proof(rule ccontr)
assume "s ≠ []"
hence "(P,P) ∈ rank_r"
proof(cases rule: sred_rtc.cases[OF assms])
case (1 P1)
then show ?thesis
using ‹s ≠ []› by auto
next
case (2 P1 s1 P2 s2 P3)
hence "(P2,P1) ∈ rank_r"
using rank_r_sred by simp
moreover have "P1 = P3"
using 2(1,3) by simp
moreover have "(P3, P2) ∈ rank_r ∨ P2=P3"
using 2(5) rank_r_sred_rtc by simp
ultimately have "(P3,P3) ∈ rank_r"
using rank_r_trans by blast
then show "(P, P) ∈ rank_r"
using 2(3) by simp
qed
thus "False" using wf_rank_r by simp
qed
text‹If P1 reduces to a diferent P2 under steps of sred, then it reduces via ‹red_plus›.›
lemma sred_rtc_to_redplus:
assumes "P1 ≠ P2" "P1 ⊢ s ↝⇧* P2"
shows "P1 ⊨ ({}, s) ⇒ P2"
using assms
proof(induct rule: sred_rtc.induct[OF assms(2)])
case (1 P1)
then show ?case by simp
next
case (2 P1 s1 P' s2 P2)
then show "P1 ⊨ ({}, s2 ∙ s1) ⇒ P2"
proof(cases "P' = P2")
case True
with 2(1,2) have
i: "P1 ⊢ s1 ↝ P2" "P2 ⊢ s2 ↝⇧* P2" by simp+
hence "s2 = []"
using sred_rtc_no_cycle by simp
with i have "P1 ⊢ (s2∙s1) ↝ P2" by simp
then show "P1 ⊨ ({}, s2 ∙ s1) ⇒ P2 "
using sred_single by simp
next
case False
with 2(2,3) have "P' ⊨ ({}, s2) ⇒ P2"
by simp
with 2(1) show "P1 ⊨ ({}, s2 ∙ s1) ⇒ P2"
using sred_step by simp
qed
qed
text‹The following two lemmas guarantee that we don't apply any non-trivial step of equational
reductions after applying a freshness reduction.›
lemma no_nontrivial_sred_after_cred_aux:
assumes "P1 ⊢ nabla → P2" and "P2 ⊢ s ↝⇧* P3"
shows "P2 = P3"
using assms
proof(induct rule: sred_rtc.induct[OF assms(2)])
case (1 P2)
then show ?case by simp
next
case (2 P2 s' P' s2 P3)
hence "fst P2 = []"
using c_red_eqs_empty by auto
moreover have "fst P2 ≠ []"
using 2(1) sred_eqs_not_empty by simp
ultimately have False by auto
then show ?case by simp
qed
lemma no_nontrivial_sred_after_cred:
assumes "P1 ⊢ nabla1 → P2"
and "P2 ⊢ s ↝⇧* P'" and "P' ⊢ nabla2 →⇧* P3"
shows "P1 ⊢ (nabla2 ∪ nabla1) →⇧* P3"
using assms
proof-
from assms(1,2) have "P2 = P'"
using no_nontrivial_sred_after_cred_aux by simp
hence "P2 ⊢ nabla2 →⇧* P3"
using assms(3) by simp
with assms(1) show "P1 ⊢ (nabla2 ∪ nabla1) →⇧* P3"
using cred_rtc_step by simp
qed
text‹If there is a reduction from P1 to P2 via ‹red_plus›, we can split into equational reductions
first and freshness reductions after.›
lemma red_plus_decompose:
assumes "P1 ⊨ (nabla, s) ⇒ P2"
shows "∃ P3. P1 ⊢ s ↝⇧* P3 ∧ P3 ⊢ nabla →⇧* P2"
using assms
proof (induction P1≡"P1" nablas≡"(nabla, s)" P2≡"P2" arbitrary: nabla s P1 P2 rule: red_plus.induct)
case (sred_single P1 s1 P2)
hence "P1 ⊢ s1 ↝⇧* P2"
using sred_rtc_step[OF sred_single sred_refl] by simp
moreover have "P2 ⊢ {} →⇧* P2"
using cred_refl by simp
ultimately show "∃P3. P1 ⊢ s1 ↝⇧* P3 ∧ P3 ⊢ {} →⇧* P2" by blast
next
case (cred_single P1 nabla1 P2)
hence "P1 ⊢ nabla1 →⇧* P2"
using cred_rtc_step[OF cred_single cred_refl] by simp
moreover have "P1 ⊢ [] ↝⇧* P1"
using sred_refl by simp
ultimately show "∃P3. P1 ⊢ [] ↝⇧* P3 ∧ P3 ⊢ nabla1 →⇧* P2" by blast
next
case (sred_step P1 s1 P' nabla2 s2 P2)
have "P1 ⊢ s1 ↝ P'" by fact
moreover obtain P3 where
IH: "P' ⊢ s2 ↝⇧* P3" "P3 ⊢ nabla2 →⇧* P2"
using sred_step(3) by auto
ultimately have "P1 ⊢ s2 ∙ s1 ↝⇧* P3"
using sred_rtc_step by simp
with IH(2) show "∃P3. P1 ⊢ s2 ∙ s1 ↝⇧* P3 ∧ P3 ⊢ nabla2 →⇧* P2"
by blast
next
case (cred_step P1 nabla1 P' nabla2 P2)
have i: "P1 ⊢ nabla1 → P'" by fact
moreover obtain P3 where
IH: "P' ⊢ [] ↝⇧* P3" "P3 ⊢ nabla2 →⇧* P2"
using cred_step(3) by auto
ultimately have "P1 ⊢ (nabla2 ∪ nabla1) →⇧* P2"
using no_nontrivial_sred_after_cred by simp
moreover have "P1 ⊢ [] ↝⇧* P1"
using sred_refl by simp
ultimately show "∃P3. P1 ⊢ [] ↝⇧* P3 ∧ P3 ⊢ (nabla2 ∪ nabla1) →⇧* P2"
by blast
qed
text‹A form of transitivity of ‹red_plus›.›
lemma red_plus_transitivity:
assumes "P1 ⊨ (nabla1, s1) ⇒ P2"
and "P2 ⊨ (nabla2, s2) ⇒ P3"
shows "∃ nabla3 s3. P1 ⊨ (nabla3, s3) ⇒ P3"
using assms
proof (induction rule: red_plus.induct[OF assms(1)])
case (2 P1 nabla1 P2)
then obtain P' where
i: "P2 ⊢ s2 ↝⇧* P'"
using red_plus_decompose by blast
with 2(1) have "P2 = P'"
using no_nontrivial_sred_after_cred_aux by simp
hence "s2 = []"
using i(1) sred_rtc_no_cycle by simp
hence "P2 ⊨ (nabla2, []) ⇒ P3"
using 2(3) by simp
with 2(1) show "∃nabla3 s3. P1 ⊨ (nabla3, s3) ⇒ P3"
using cred_step by auto
next
case (4 P1 nabla P' nabla' P2)
then obtain nabla3 s3 where
P_prime_to_P3: "P' ⊨ (nabla3, s3) ⇒ P3" by auto
then obtain P'' where "P' ⊢ s3 ↝⇧* P''" "P'' ⊢ nabla3 →⇧* P3"
using red_plus_decompose by blast
with 4(1) have "P' = P''"
using no_nontrivial_sred_after_cred_aux by simp
moreover have "s3 =[]"
using ‹P' ⊢ s3 ↝⇧* P''› sred_rtc_no_cycle calculation by simp
hence "P' ⊨ (nabla3, []) ⇒ P3"
using P_prime_to_P3 by simp
with 4(1) show "∃nabla3 s3. P1 ⊨ (nabla3, s3) ⇒ P3"
using cred_step by auto
qed (auto)
text‹Every problem has a normal form.›
lemma normal_form_exists:
shows "P ∈ stuck ∨ (∃ P2 nabla s. P ⊨(nabla,s)⇒P2 ∧ P2∈stuck )"
proof(induction P rule: wf_induct_rule[OF wf_rank_r])
case (1 P)
then show "P ∈ stuck ∨ (∃P2 nabla s. P ⊨ (nabla, s) ⇒ P2 ∧ P2 ∈ stuck)"
proof (cases "P ∈ stuck")
case True
then show "P ∈ stuck ∨ (∃P2 nabla s. P ⊨ (nabla, s) ⇒ P2 ∧ P2 ∈ stuck)" by simp
next
case False
then obtain P' nabla s where P_to_P_prime:
"P ⊨(nabla,s)⇒P'"
unfolding stuck_def by auto
hence "(P', P) ∈ rank_r"
using rank_r_red_plus by simp
hence aux: "P' ∈ stuck ∨ (∃P2 nabla s. P' ⊨ (nabla, s) ⇒ P2 ∧ P2 ∈ stuck)"
using 1 by simp
then show "P ∈ stuck ∨ (∃P2 nabla s. P ⊨ (nabla, s) ⇒ P2 ∧ P2 ∈ stuck)"
proof(cases "P' ∈ stuck")
case True
then show ?thesis
using P_to_P_prime by blast
next
case False
then obtain P2 nabla' s' where
P_prime_to_P2: "P' ⊨ (nabla', s') ⇒ P2" "P2 ∈ stuck"
using aux by auto
then obtain nabla1 s1 where "P ⊨ (nabla1, s1) ⇒ P2" "P2∈ stuck"
using P_to_P_prime red_plus_transitivity by blast
then show ?thesis by blast
qed
qed
qed
text‹The procedure is complete, i.e., if a non-empty problem has a solution, then ‹red_plus› finds
the most general solution.›
theorem completeness:
assumes "P1 ≠ ([],[])" "U P1 ≠ {}"
shows "∃ nabla' s'. P1 ⊨ (nabla', s') ⇒ ([],[]) ∧ mgu P1 (nabla', s')"
proof-
have P1_not_stuck: "P1 ∉ stuck"
proof
assume "P1∈ stuck"
hence "P1 = ([],[])∨ fail P1"
unfolding stuck_equiv by simp
hence "P1 =([],[])"
using assms(2) fail_then_empty by blast
thus False using assms(1) by simp
qed
then obtain P2 nabla' s' where
normal_form: "P1 ⊨ (nabla', s') ⇒ P2" "P2 ∈ stuck"
using normal_form_exists by blast
hence "P2 ∈ normal_form P1"
using P1_not_stuck unfolding normal_form_def by auto
hence "P2=([],[])"
using not_empty_then_not_fail[OF assms(2)] normal_form(2) stuck_equiv by auto
with normal_form(1) have "P1 ⊨ (nabla', s') ⇒ ([],[])" by simp
moreover have "mgu P1 (nabla',s')"
using mgu calculation by simp
ultimately show "∃nabla' s'. P1 ⊨ (nabla', s') ⇒ ([], []) ∧ mgu P1 (nabla', s')"
by auto
qed
end