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".›
  
(* we don't really need this lemma, sledgehammer would find a proof anyway. But it would be massively ugly. *)
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
(* I tried Inf instead of Min first. Only has downsides. *)

text‹Showing termination is slightly technical\dots›
termination interpolate
  apply(relation "measure (λ(F,H). card (atoms F - atoms H))") 
              (* "measure (λ(F,H). card (atoms F))" also works, but doesn't make things more beautiful *)
   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)))"
(* and the wikipedia example: *)
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)
        (* you need to tell sledgehammer about formula.set if you want it to find a proof here… *)
      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 { (* sledgehammer… *)
        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