Theory Sema_Craig
subsection‹Craig Interpolation using Semantics›
theory Sema_Craig
imports Substitution_Sema
begin
text‹Semantic proof of Craig interpolation following Harrison~\<^cite>‹"harrison2009handbook"›.›
lemma subst_true_false:
assumes "𝒜 ⊨ F"
shows "𝒜 ⊨ ((F[⊤ / n]) ❙∨ (F[⊥ / n]))"
using assms by(cases "𝒜 n"; simp add: substitution_lemma fun_upd_idem)
theorem interpolation:
assumes "⊨ Γ ❙→ Δ"
obtains ρ where
"⊨ Γ ❙→ ρ" "⊨ ρ ❙→ Δ"
"atoms ρ ⊆ atoms Γ"
"atoms ρ ⊆ atoms Δ"
proof(goal_cases)
let ?as = "atoms Γ - atoms Δ"
have fas: "finite ?as" by simp
from fas assms have "∃ρ. ((⊨ Γ ❙→ ρ) ∧ (⊨ ρ ❙→ Δ) ∧ (atoms ρ ⊆ atoms Γ) ∧ (atoms ρ ⊆ atoms Δ))"
proof(induction ?as arbitrary: Γ rule: finite_induct)
case empty
from ‹{} = atoms Γ - atoms Δ› have "atoms Γ ⊆ atoms Δ" by blast
with ‹⊨ Γ ❙→ Δ› show ?case by(intro exI[where x=Γ]) simp
next
case (insert a A)
hence e: "a ∈ atoms Γ" "a ∉ atoms Δ" by auto
define Γ' where "Γ' = (Γ[⊤ / a]) ❙∨ (Γ[⊥ / a])"
have su: "atoms Γ' ⊆ atoms Γ" unfolding Γ'_def by(cases "a ∈ atoms Γ"; simp add: subst_atoms)
from ‹⊨ Γ ❙→ Δ› e have "⊨ Γ' ❙→ Δ" by (auto simp add: substitution_lemma Γ'_def)
from ‹a ▹ A = atoms Γ - atoms Δ› ‹a ∉ A› e have "A = atoms Γ' - atoms Δ" by(simp add: subst_atoms Γ'_def) blast
from insert.hyps(3)[OF this ‹⊨ Γ' ❙→ Δ›] obtain ρ where ρ: "⊨ Γ' ❙→ ρ" "⊨ ρ ❙→ Δ" "atoms ρ ⊆ atoms Γ'" "atoms ρ ⊆ atoms Δ" by clarify
have "⊨ Γ ❙→ ρ" using ρ(1) subst_true_false unfolding Γ'_def by fastforce
with ρ su show ?case by(intro exI[where x=ρ]) simp
qed
moreover case 1
ultimately show thesis by blast
qed
text‹The above proof is constructive, and it is actually very easy to write a procedure down.›
function interpolate where
"interpolate F H = (
let K = atoms F - atoms H in
if K = {}
then F
else (
let k = Min K
in interpolate ((F[⊤ / k]) ❙∨ (F[⊥ / k])) H
)
)" by pat_completeness simp
text‹Showing termination is slightly technical\dots›
termination interpolate
apply(relation "measure (λ(F,H). card (atoms F - atoms H))")
subgoal by simp
apply (simp add: subst_atoms_simp)
apply(intro conjI impI)
apply(intro psubset_card_mono)
subgoal by simp
apply(subgoal_tac "Min (atoms F - atoms H) ∉ atoms H")
subgoal by blast
apply (meson atoms_finite Diff_eq_empty_iff Diff_iff Min_in finite_Diff)+
done
text‹Surprisingly, @{const interpolate} is even executable,
despite all the set operations involving @{const atoms}›
lemma "interpolate (And (Atom (0::nat)) (Atom 1)) (Or (Atom 1) (Atom 2)) =
(⊤ ❙∧ Atom 1) ❙∨ (⊥ ❙∧ Atom 1)" by simp
value[code] "simplify_consts (interpolate (And (Atom (0::nat)) (Atom 1)) (Or (Atom 1) (Atom 2)))"
lemma "let P = Atom (0 :: nat); Q = Atom 1; R = Atom 2; T = Atom 3;
φ = (❙¬(P ❙∧ Q)) ❙→ (❙¬R ❙∧ Q);
ψ = (T ❙→ P) ❙∨ (T ❙→ (❙¬R));
I = interpolate φ ψ in
(size I) = 23 ∧ simplify_consts I = Atom 2 ❙→ Atom 0"
by code_simp
theorem nonexistential_interpolation:
assumes "⊨ F ❙→ H"
shows
"⊨ F ❙→ interpolate F H" (is "?t1") "⊨ interpolate F H ❙→ H" (is "?t2")
"atoms (interpolate F H) ⊆ atoms F ∩ atoms H" (is "?s")
proof -
let ?as = "atoms F - atoms H"
have fas: "finite ?as" by simp
hence "?t1 ∧ ?t2 ∧ ?s" using assms
proof(induction "card ?as" arbitrary: F H)
case (Suc n)
let ?inf = "Min (atoms F - atoms H)"
define G where "G = (F[⊤ / ?inf]) ❙∨ (F[⊥ / ?inf])"
have e: "Min (atoms F - atoms H) ∈ atoms F - atoms H" by (metis Min_in Suc.hyps(2) Suc.prems(1) card.empty nat.simps(3))
with Suc(2) have "n = card (atoms G - atoms H)" unfolding G_def subst_atoms_simp
proof -
assume a1: "Suc n = card (atoms F - atoms H)"
assume "Min (atoms F - atoms H) ∈ atoms F - atoms H"
hence a2: "Min (atoms F - atoms H) ∈ atoms F ∧ Min (atoms F - atoms H) ∉ atoms H" by simp
have "n = card (atoms F - atoms H) - 1"
using a1 by presburger
hence "n = card (atoms (F[⊤ / Min (atoms F - atoms H)]) ∪ atoms (F[⊥ / Min (atoms F - atoms H)]) - atoms H)"
using a2 by (metis (full_types) formula.set(2) Diff_insert Diff_insert2 Suc.prems(1) Un_absorb Un_empty_right card_Diff_singleton e subst_atoms top_atoms_simp)
thus "n = card (atoms ((F[⊤ / Min (atoms F - atoms H)]) ❙∨ (F[⊥ / Min (atoms F - atoms H)])) - atoms H)" by simp
qed
moreover have "finite (atoms G - atoms H)" "⊨ G ❙→ H" using Suc(3-) e
by(auto simp: G_def substitution_lemma)
ultimately have IH: "⊨ G ❙→ interpolate G H" "⊨ interpolate G H ❙→ H"
"atoms (interpolate G H) ⊆ atoms G ∩ atoms H" using Suc by blast+
moreover have "⊨ F ❙→ G" unfolding G_def
using subst_true_false by fastforce
moreover {
assume a1: "atoms (interpolate ((F[⊤/Min (atoms F - atoms H)]) ❙∨ (F[⊥/Min (atoms F - atoms H)])) H) ⊆ atoms (F[⊤/Min (atoms F - atoms H)]) ∪ atoms (F[⊥/Min (atoms F - atoms H)]) ∧ atoms (interpolate ((F[⊤/Min (atoms F - atoms H)]) ❙∨ (F[⊥/Min (atoms F - atoms H)])) H) ⊆ atoms H"
have f2: "atoms ((⊥::'a formula) ❙→ ⊥) = atoms ⊥"
by simp
then have f3: "atoms F - {Min (atoms F - atoms H)} = atoms (F[⊤/Min (atoms F - atoms H)])"
by (metis (no_types) DiffD1 Top_def Un_empty_right e formula.simps(91) subst_atoms)
have "atoms (F[⊥/Min (atoms F - atoms H)]) = atoms (F[⊤/Min (atoms F - atoms H)])"
using f2 by (metis (no_types) DiffD1 Top_def e subst_atoms)
then have "¬ atoms F ⊆ atoms H ⟶ atoms (interpolate ((F[⊤/Min (atoms F - atoms H)]) ❙∨ (F[⊥/Min (atoms F - atoms H)])) H) ⊆ atoms F"
using f3 a1 by blast
} ultimately show ?case
by (intro conjI; subst interpolate.simps; simp del: interpolate.simps add: Let_def G_def; blast?)
qed auto
thus "?t1" "?t2" "?s" by simp_all
qed
text‹So no, the proof is by no means easier this way.
Admittedly, part of the fuzz is due to @{const Min},
but replacing atoms with something that returns lists doesn't make it better.›
end