Theory EPathHintikka
section ‹Escape path formulas are Hintikka›
theory EPathHintikka imports Hintikka ProverLemmas begin
text ‹In this theory, we show that the formulas in the sequents on a saturated escape path in a
  proof tree form a Hintikka set.
  This is a crucial part of our completeness proof.›
subsection ‹Definitions›
text ‹In this section we define a few concepts that make the following proofs easier to read.›
text ‹‹pseq› is the sequent in a node.›
definition pseq :: ‹state × rule ⇒ sequent› where
  ‹pseq z = snd (fst z)›
text ‹‹ptms› is the list of terms in a node.›
definition ptms :: ‹state × rule ⇒ tm list› where
  ‹ptms z = fst (fst z)›
subsection ‹Facts about streams›
text ‹Escape paths are infinite, so if you drop the first ‹n› nodes, you are still on the path.›
lemma epath_sdrop: ‹epath steps ⟹ epath (sdrop n steps)›
  by (induct n) (auto elim: epath.cases)
text ‹Dropping the first ‹n› elements of a stream can only reduce the set of elements in the stream.›
lemma sset_sdrop: ‹sset (sdrop n s) ⊆ sset s›
proof (induct n arbitrary: s)
  case (Suc n)
  then show ?case
    by (metis in_mono sdrop_simps(2) stl_sset subsetI)
qed simp
subsection  ‹Transformation of states on an escape path›
text ‹We need to prove some lemmas about how the states of an escape path are connected.›
text ‹Since escape paths are well-formed, the eff relation holds between the nodes on the path.›
lemma epath_eff:
  assumes ‹epath steps› ‹eff (snd (shd steps)) (fst (shd steps)) ss›
  shows ‹fst (shd (stl steps)) |∈| ss›
  using assms by (metis (mono_tags, lifting) epath.simps eff_def)
text ‹The list of terms in a state contains the terms of the current sequent and the terms from the
  previous state.›
lemma effect_tms:
  assumes ‹(B, z') |∈| effect r (A, z)›
  shows ‹B = remdups (A @ subterms z @ subterms z')›
  using assms by (smt (verit, best) effect.simps fempty_iff fimageE prod.simps(1))
text ‹The two previous lemmas can be combined into a single lemma.›
lemma epath_effect:
  assumes ‹epath steps› ‹shd steps = ((A, z), r)›
  shows ‹∃B z' r'. (B, z') |∈| effect r (A, z) ∧ shd (stl steps) = ((B, z'), r') ∧
          (B = remdups (A @ subterms z @ subterms z'))›
  using assms epath_eff effect_tms
  by (metis (mono_tags, lifting) eff_def fst_conv prod.collapse snd_conv)
text ‹The list of terms in the next state on an escape path contains the terms in the current state
  plus the terms from the next state.›
lemma epath_stl_ptms:
  assumes ‹epath steps›
  shows ‹ptms (shd (stl steps)) = remdups (ptms (shd steps) @
    subterms (pseq (shd steps)) @ subterms (pseq (shd (stl steps))))›
  using assms epath_effect
  by (metis (mono_tags) eff_def effect_tms epath_eff pseq_def ptms_def surjective_pairing)
text ‹The list of terms never decreases on an escape path.›
lemma epath_sdrop_ptms:
  assumes ‹epath steps›
  shows ‹set (ptms (shd steps)) ⊆ set (ptms (shd (sdrop n steps)))›
  using assms
proof (induct n)
  case (Suc n)
  then have ‹epath (sdrop n steps)›
    using epath_sdrop by blast
  then show ?case
    using Suc epath_stl_ptms by fastforce
qed simp
subsection ‹Preservation of formulas on escape paths›
text ‹If a property will eventually hold on a path, there is some index from which it begins to
  hold, and before which it does not hold.›
lemma ev_prefix_sdrop:
  assumes ‹ev (holds P) xs›
  shows ‹∃n. list_all (not P) (stake n xs) ∧ holds P (sdrop n xs)›
  using assms
proof (induct xs)
  case (base xs)
  then show ?case
    by (metis list.pred_inject(1) sdrop.simps(1) stake.simps(1))
next
  case (step xs)
  then show ?case
    by (metis holds.elims(1) list.pred_inject(2) list_all_simps(2) sdrop.simps(1-2) stake.simps(1-2))
qed
text ‹More specifically, the path will consists of a prefix and a suffix for which the property
  does not hold and does hold, respectively.›
lemma ev_prefix:
  assumes ‹ev (holds P) xs›
  shows ‹∃pre suf. list_all (not P) pre ∧ holds P suf ∧ xs = pre @- suf›
  using assms ev_prefix_sdrop by (metis stake_sdrop)
text ‹All rules are always enabled, so they are also always enabled at specific steps.›
lemma always_enabledAtStep: ‹enabledAtStep r xs›
  by (simp add: RuleSystem_Defs.enabled_def eff_def)
text ‹If a formula is in the sequent in the first state of an escape path and none of the rule
  applications in some prefix of the path affect that formula, the formula will still be in the
  sequent after that prefix.›
lemma epath_preserves_unaffected:
  assumes ‹p ∈ set (pseq (shd steps))› and ‹epath steps› and ‹steps = pre @- suf› and
    ‹list_all (not (λstep. affects (snd step) p)) pre›
  shows ‹p ∈ set (pseq (shd suf))›
  using assms
proof (induct pre arbitrary: steps)
  case Nil
  then show ?case
    by simp
next
  case (Cons q pre)
  from this(3) show ?case
  proof cases
    case (epath sl)
    from this(2-4) show ?thesis
      using Cons(1-2, 4-5) effect_preserves_unaffected unfolding eff_def pseq_def list_all_def
      by (metis (no_types, lifting) list.sel(1) list.set_intros(1-2) prod.exhaust_sel
          shift.simps(2) shift_simps(1) stream.sel(2))
  qed
qed
subsection ‹Formulas on an escape path form a Hintikka set›
text ‹This definition captures the set of formulas on an entire path›
definition ‹tree_fms steps ≡ ⋃ss ∈ sset steps. set (pseq ss)›
text ‹The sequent at the head of a path is in the set of formulas on that path›
lemma pseq_in_tree_fms: ‹⟦x ∈ sset steps; p ∈ set (pseq x)⟧ ⟹ p ∈ tree_fms steps›
  using pseq_def tree_fms_def by blast
text ‹If a formula is in the set of formulas on a path, there is some index on the path where that
  formula can be found in the sequent.›
lemma tree_fms_in_pseq: ‹p ∈ tree_fms steps ⟹ ∃n. p ∈ set (pseq (steps !! n))›
  unfolding pseq_def tree_fms_def using sset_range[of steps] by simp
text ‹If a path is saturated, so is any suffix of that path (since saturation is defined in terms of
  the always operator).›
lemma Saturated_sdrop: ‹Saturated steps ⟹ Saturated (sdrop n steps)›
  by (simp add: RuleSystem_Defs.Saturated_def alw_iff_sdrop saturated_def)
text ‹This is an abbreviation that determines whether a given rule is applied in a given state.›
abbreviation ‹is_rule r step ≡ snd step = r›
text ‹If a path is saturated, it is always possible to find a state in which a given rule is applied.›
lemma Saturated_ev_rule:
  assumes ‹Saturated steps›
  shows ‹ev (holds (is_rule r)) (sdrop n steps)›
proof -
  have ‹Saturated (sdrop n steps)›
    using ‹Saturated steps› Saturated_sdrop by fast
  moreover have ‹r ∈ Prover.R›
    by (metis rules_repeat snth_sset)
  ultimately have ‹saturated r (sdrop n steps)›
    unfolding Saturated_def by fast
  then show ?thesis
    unfolding saturated_def using always_enabledAtStep holds.elims(3) by blast
qed
text ‹On an escape path, the sequent is never an axiom (since that would end the branch, and escape
  paths are infinitely long).›
lemma epath_never_branchDone:
  assumes ‹epath steps›
  shows ‹alw (holds (not (branchDone o pseq))) steps›
proof (rule ccontr)
  assume ‹¬ ?thesis›
  then have ‹ev (holds (branchDone o pseq)) steps›
    by (simp add: alw_iff_sdrop ev_iff_sdrop)
  then obtain n where n: ‹holds (branchDone o pseq) (sdrop n steps)›
    using sdrop_wait by blast
  let ?suf = ‹sdrop n steps›
  have ‹∀r A. effect r (A, pseq (shd ?suf)) = {||}›
    unfolding effect_def using n by simp
  moreover have ‹epath ?suf›
    using ‹epath steps› epath_sdrop by blast
  then have ‹∀r A. ∃z' r'. z' |∈| effect r (A, pseq (shd ?suf)) ∧ shd (stl ?suf) = (z', r')›
    using epath_effect by (metis calculation prod.exhaust_sel pseq_def)
  ultimately show False
    by blast
qed
text ‹Finally we arrive at the main result of this theory:
  The set of formulas on a saturated escape path form a Hintikka set.
  The proof basically says that, given a formula, we can find some index into the path where a rule
  is applied to decompose that formula into the parts needed for the Hintikka set.
  The lemmas above are used to guarantee that the formula does not disappear (and that the branch
  does not end) before the rule is applied, and that the correct formulas are generated by the
  effect function when the rule is finally applied.
  For Beta rules, only one of the constituent formulas need to be on the path, since the path runs
  along only one of the two branches.
  For Gamma and Delta rules, the construction of the list of terms in each state guarantees that
  the formulas are instantiated with terms in the Hintikka set.›
lemma escape_path_Hintikka:
  assumes ‹epath steps› and ‹Saturated steps›
  shows ‹Hintikka (tree_fms steps)›
    (is ‹Hintikka ?H›)
proof
  fix n ts
  assume pre: ‹Pre n ts ∈ ?H›
  then obtain m where m: ‹Pre n ts ∈ set (pseq (shd (sdrop m steps)))›
    using tree_fms_in_pseq by auto
  show ‹Neg (Pre n ts) ∉ ?H›
  proof
    assume ‹Neg (Pre n ts) ∈ ?H›
    then obtain k where k: ‹Neg (Pre n ts) ∈ set (pseq (shd (sdrop k steps)))›
      using tree_fms_in_pseq by auto
    let ?pre = ‹stake (m + k) steps›
    let ?suf = ‹sdrop (m + k) steps›
    have
      1: ‹¬ affects r (Pre n ts)› and
      2: ‹¬ affects r (Neg (Pre n ts))› for r
      unfolding affects_def by (cases r, simp_all)+
    have ‹list_all (not (λstep. affects (snd step) (Pre n ts))) ?pre›
      unfolding list_all_def using 1 by (induct ?pre) simp_all
    then have p: ‹Pre n ts ∈ set (pseq (shd ?suf))›
      using ‹epath steps› epath_preserves_unaffected m epath_sdrop
      by (metis (no_types, lifting) list.pred_mono_strong list_all_append
          sdrop_add stake_add stake_sdrop)
    have ‹list_all (not (λstep. affects (snd step) (Neg (Pre n ts)))) ?pre›
      unfolding list_all_def using 2 by (induct ?pre) simp_all
    then have np: ‹Neg (Pre n ts) ∈ set (pseq (shd ?suf))›
      using ‹epath steps› epath_preserves_unaffected k epath_sdrop
      by (smt (verit, best) add.commute list.pred_mono_strong list_all_append sdrop_add
          stake_add stake_sdrop)
    have ‹holds (branchDone o pseq) ?suf›
      using p np branchDone_contradiction by auto
    moreover have ‹¬ holds (branchDone o pseq) ?suf›
      using ‹epath steps› epath_never_branchDone by (simp add: alw_iff_sdrop)
    ultimately show False
      by blast
  qed
next
  fix p q
  assume ‹Dis p q ∈ ?H› (is ‹?f ∈ ?H›)
  then obtain n where n: ‹?f ∈ set (pseq (shd (sdrop n steps)))›
    using tree_fms_in_pseq by auto
  let ?steps = ‹sdrop n steps›
  let ?r = AlphaDis
  have ‹ev (holds (is_rule ?r)) ?steps›
    using ‹Saturated steps› Saturated_ev_rule by blast
  then obtain pre suf where
    pre: ‹list_all (not (is_rule ?r)) pre› and
    suf: ‹holds (is_rule ?r) suf› and
    ori: ‹?steps = pre @- suf›
    using ev_prefix by blast
  have ‹affects r ?f ⟷ r = ?r› for r
    unfolding affects_def by (cases r) simp_all
  then have ‹list_all (not (λstep. affects (snd step) ?f)) pre›
    using pre by simp
  moreover have ‹epath (pre @- suf)›
    using ‹epath steps› epath_sdrop ori by metis
  ultimately have ‹?f ∈ set (pseq (shd suf))›
    using epath_preserves_unaffected n ori by metis
  moreover have ‹epath suf›
    using ‹epath (pre @- suf)› epath_sdrop by (metis alwD alw_iff_sdrop alw_shift)
  then obtain B z' r' where
    z': ‹(B, z') |∈| effect ?r (ptms (shd suf), pseq (shd suf))› ‹shd (stl suf) = ((B, z'), r')›
    using suf epath_effect unfolding pseq_def ptms_def
    by (metis (mono_tags, lifting) holds.elims(2) prod.collapse)
  ultimately have ‹p ∈ set z'› ‹q ∈ set z'›
    using parts_in_effect unfolding parts_def by fastforce+
  then show ‹p ∈ ?H ∧ q ∈ ?H›
    using z'(2) ori pseq_in_tree_fms
    by (metis (no_types, opaque_lifting) Un_iff fst_conv pseq_def shd_sset snd_conv sset_sdrop
        sset_shift stl_sset subset_eq)
next
  fix p q
  assume ‹Imp p q ∈ tree_fms steps› (is ‹?f ∈ ?H›)
  then obtain n where n: ‹?f ∈ set (pseq (shd (sdrop n steps)))›
    using tree_fms_in_pseq by auto
  let ?steps = ‹sdrop n steps›
  let ?r = AlphaImp
  have ‹ev (holds (is_rule ?r)) ?steps›
    using ‹Saturated steps› Saturated_ev_rule by blast
  then obtain pre suf where
    pre: ‹list_all (not (is_rule ?r)) pre› and
    suf: ‹holds (is_rule ?r) suf› and
    ori: ‹?steps = pre @- suf›
    using ev_prefix by blast
  have ‹affects r ?f ⟷ r = ?r› for r
    unfolding affects_def by (cases r) simp_all
  then have ‹list_all (not (λstep. affects (snd step) ?f)) pre›
    using pre by simp
  moreover have ‹epath (pre @- suf)›
    using ‹epath steps› epath_sdrop ori by metis
  ultimately have ‹?f ∈ set (pseq (shd suf))›
    using epath_preserves_unaffected n ori by metis
  moreover have ‹epath suf›
    using ‹epath (pre @- suf)› epath_sdrop by (metis alwD alw_iff_sdrop alw_shift)
  then obtain B z' r' where
    z': ‹(B, z') |∈| effect ?r (ptms (shd suf), pseq (shd suf))› ‹shd (stl suf) = ((B, z'), r')›
    using suf epath_effect unfolding pseq_def ptms_def
    by (metis (mono_tags, lifting) holds.elims(2) prod.collapse)
  ultimately have ‹Neg p ∈ set z'› ‹q ∈ set z'›
    using parts_in_effect unfolding parts_def by fastforce+
  then show ‹Neg p ∈ ?H ∧ q ∈ ?H›
    using z'(2) ori pseq_in_tree_fms
    by (metis (no_types, opaque_lifting) Un_iff fst_conv pseq_def shd_sset snd_conv sset_sdrop
        sset_shift stl_sset subset_eq)
next
  fix p q
  assume ‹Neg (Con p q) ∈ ?H› (is ‹?f ∈ ?H›)
  then obtain n where n: ‹?f ∈ set (pseq (shd (sdrop n steps)))›
    using tree_fms_in_pseq by auto
  let ?steps = ‹sdrop n steps›
  let ?r = AlphaCon
  have ‹ev (holds (is_rule ?r)) ?steps›
    using ‹Saturated steps› Saturated_ev_rule by blast
  then obtain pre suf where
    pre: ‹list_all (not (is_rule ?r)) pre› and
    suf: ‹holds (is_rule ?r) suf› and
    ori: ‹?steps = pre @- suf›
    using ev_prefix by blast
  have ‹affects r ?f ⟷ r = ?r› for r
    unfolding affects_def by (cases r) simp_all
  then have ‹list_all (not (λstep. affects (snd step) ?f)) pre›
    using pre by simp
  moreover have ‹epath (pre @- suf)›
    using ‹epath steps› epath_sdrop ori by metis
  ultimately have ‹?f ∈ set (pseq (shd suf))›
    using epath_preserves_unaffected n ori by metis
  moreover have ‹epath suf›
    using ‹epath (pre @- suf)› epath_sdrop by (metis alwD alw_iff_sdrop alw_shift)
  then obtain B z' r' where
    z': ‹(B, z') |∈| effect ?r (ptms (shd suf), pseq (shd suf))› ‹shd (stl suf) = ((B, z'), r')›
    using suf epath_effect unfolding pseq_def ptms_def
    by (metis (mono_tags, lifting) holds.elims(2) prod.collapse)
  ultimately have ‹Neg p ∈ set z'› ‹Neg q ∈ set z'›
    using parts_in_effect unfolding parts_def by fastforce+
  then show ‹Neg p ∈ ?H ∧ Neg q ∈ ?H›
    using z'(2) ori pseq_in_tree_fms
    by (metis (no_types, opaque_lifting) Un_iff fst_conv pseq_def shd_sset snd_conv sset_sdrop
        sset_shift stl_sset subset_eq)
next
  fix p q
  assume ‹Con p q ∈ ?H› (is ‹?f ∈ ?H›)
  then obtain n where n: ‹?f ∈ set (pseq (shd (sdrop n steps)))›
    using tree_fms_in_pseq by auto
  let ?steps = ‹sdrop n steps›
  let ?r = BetaCon
  have ‹ev (holds (is_rule ?r)) ?steps›
    using ‹Saturated steps› Saturated_ev_rule by blast
  then obtain pre suf where
    pre: ‹list_all (not (is_rule ?r)) pre› and
    suf: ‹holds (is_rule ?r) suf› and
    ori: ‹?steps = pre @- suf›
    using ev_prefix by blast
  have ‹affects r ?f ⟷ r = ?r› for r
    unfolding affects_def by (cases r) simp_all
  then have ‹list_all (not (λstep. affects (snd step) ?f)) pre›
    using pre by simp
  moreover have ‹epath (pre @- suf)›
    using ‹epath steps› epath_sdrop ori by metis
  ultimately have ‹?f ∈ set (pseq (shd suf))›
    using epath_preserves_unaffected n ori by metis
  moreover have ‹epath suf›
    using ‹epath (pre @- suf)› epath_sdrop by (metis alwD alw_iff_sdrop alw_shift)
  then obtain B z' r' where
    z': ‹(B, z') |∈| effect ?r (ptms (shd suf), pseq (shd suf))› ‹shd (stl suf) = ((B, z'), r')›
    using suf epath_effect unfolding pseq_def ptms_def
    by (metis (mono_tags, lifting) holds.elims(2) prod.collapse)
  ultimately consider ‹p ∈ set z'› | ‹q ∈ set z'›
    using parts_in_effect unfolding parts_def by fastforce
  then show ‹p ∈ ?H ∨ q ∈ ?H›
    using z'(2) ori pseq_in_tree_fms
    by (metis (no_types, opaque_lifting) Un_iff fst_conv pseq_def shd_sset snd_conv sset_sdrop
        sset_shift stl_sset subset_eq)
next
  fix p q
  assume ‹Neg (Imp p q) ∈ ?H› (is ‹?f ∈ ?H›)
  then obtain n where n: ‹?f ∈ set (pseq (shd (sdrop n steps)))›
    using tree_fms_in_pseq by auto
  let ?steps = ‹sdrop n steps›
  let ?r = BetaImp
  have ‹ev (holds (is_rule ?r)) ?steps›
    using ‹Saturated steps› Saturated_ev_rule by blast
  then obtain pre suf where
    pre: ‹list_all (not (is_rule ?r)) pre› and
    suf: ‹holds (is_rule ?r) suf› and
    ori: ‹?steps = pre @- suf›
    using ev_prefix by blast
  have ‹affects r ?f ⟷ r = ?r› for r
    unfolding affects_def by (cases r) simp_all
  then have ‹list_all (not (λstep. affects (snd step) ?f)) pre›
    using pre by simp
  moreover have ‹epath (pre @- suf)›
    using ‹epath steps› epath_sdrop ori by metis
  ultimately have ‹?f ∈ set (pseq (shd suf))›
    using epath_preserves_unaffected n ori by metis
  moreover have ‹epath suf›
    using ‹epath (pre @- suf)› epath_sdrop by (metis alwD alw_iff_sdrop alw_shift)
  then obtain B z' r' where
    z': ‹(B, z') |∈| effect ?r (ptms (shd suf), pseq (shd suf))› ‹shd (stl suf) = ((B, z'), r')›
    using suf epath_effect unfolding pseq_def ptms_def
    by (metis (mono_tags, lifting) holds.elims(2) prod.collapse)
  ultimately consider ‹p ∈ set z'› | ‹Neg q ∈ set z'›
    using parts_in_effect unfolding parts_def by fastforce
  then show ‹p ∈ ?H ∨ Neg q ∈ ?H›
    using z'(2) ori pseq_in_tree_fms
    by (metis (no_types, opaque_lifting) Un_iff fst_conv pseq_def shd_sset snd_conv sset_sdrop
        sset_shift stl_sset subset_eq)
next
  fix p q
  assume ‹Neg (Dis p q) ∈ ?H› (is ‹?f ∈ ?H›)
  then obtain n where n: ‹?f ∈ set (pseq (shd (sdrop n steps)))›
    using tree_fms_in_pseq by auto
  let ?steps = ‹sdrop n steps›
  let ?r = BetaDis
  have ‹ev (holds (is_rule ?r)) ?steps›
    using ‹Saturated steps› Saturated_ev_rule by blast
  then obtain pre suf where
    pre: ‹list_all (not (is_rule ?r)) pre› and
    suf: ‹holds (is_rule ?r) suf› and
    ori: ‹?steps = pre @- suf›
    using ev_prefix by blast
  have ‹affects r ?f ⟷ r = ?r› for r
    unfolding affects_def by (cases r) simp_all
  then have ‹list_all (not (λstep. affects (snd step) ?f)) pre›
    using pre by simp
  moreover have ‹epath (pre @- suf)›
    using ‹epath steps› epath_sdrop ori by metis
  ultimately have ‹?f ∈ set (pseq (shd suf))›
    using epath_preserves_unaffected n ori by metis
  moreover have ‹epath suf›
    using ‹epath (pre @- suf)› epath_sdrop by (metis alwD alw_iff_sdrop alw_shift)
  then obtain B z' r' where
    z': ‹(B, z') |∈| effect ?r (ptms (shd suf), pseq (shd suf))› ‹shd (stl suf) = ((B, z'), r')›
    using suf epath_effect unfolding pseq_def ptms_def
    by (metis (mono_tags, lifting) holds.elims(2) prod.collapse)
  ultimately consider ‹Neg p ∈ set z'› | ‹Neg q ∈ set z'›
    using parts_in_effect unfolding parts_def by fastforce
  then show ‹Neg p ∈ ?H ∨ Neg q ∈ ?H›
    using z'(2) ori pseq_in_tree_fms
    by (metis (no_types, opaque_lifting) Un_iff fst_conv pseq_def shd_sset snd_conv sset_sdrop
        sset_shift stl_sset subset_eq)
next
  fix p
  assume ‹Exi p ∈ ?H› (is ‹?f ∈ ?H›)
  then obtain n where n: ‹?f ∈ set (pseq (shd (sdrop n steps)))›
    using tree_fms_in_pseq by auto
  let ?r = GammaExi
  show ‹∀t ∈ terms ?H. sub 0 t p ∈ ?H›
  proof
    fix t
    assume t: ‹t ∈ terms ?H›
    show ‹sub 0 t p ∈ ?H›
    proof -
      have ‹∃m. t ∈ set (subterms (pseq (shd (sdrop m steps))))›
      proof (cases ‹(⋃f ∈ ?H. set (subtermFm f)) = {}›)
        case True
        moreover have ‹∀p ∈ set (pseq (shd steps)). p ∈ ?H›
          unfolding tree_fms_def by (metis pseq_in_tree_fms shd_sset tree_fms_def)
        ultimately have ‹∀p ∈ set (pseq (shd steps)). subtermFm p = []›
          by simp
        then have ‹concat (map subtermFm (pseq (shd steps))) = []›
          by (induct ‹pseq (shd steps)›) simp_all
        then have ‹subterms (pseq (shd steps)) = [Fun 0 []]›
          unfolding subterms_def by (metis list.simps(4) remdups_eq_nil_iff)
        then show ?thesis
          using True t unfolding terms_def
          by (metis empty_iff insert_iff list.set_intros(1) sdrop.simps(1))
      next
        case False
        then obtain pt where pt: ‹t ∈ set (subtermFm pt)› ‹pt ∈ ?H›
          using t unfolding terms_def by (metis (no_types, lifting) UN_E)
        then obtain m where m: ‹pt ∈ set (pseq (shd (sdrop m steps)))›
          using tree_fms_in_pseq by auto
        then show ?thesis
          using pt(1) set_subterms by fastforce
      qed
      then obtain m where ‹t ∈ set (subterms (pseq (shd (sdrop m steps))))›
        by blast
      then have ‹t ∈ set (ptms (shd (stl (sdrop m steps))))›
        using epath_stl_ptms epath_sdrop ‹epath steps›
        by (metis (no_types, opaque_lifting) Un_iff set_append set_remdups)
      moreover have ‹epath (stl (sdrop m steps))›
        using epath_sdrop ‹epath steps› by (meson epath.cases)
      ultimately have ‹∀k ≥ m. t ∈ set (ptms (shd (stl (sdrop k steps))))›
        using epath_sdrop_ptms by (metis (no_types, lifting) le_Suc_ex sdrop_add sdrop_stl subsetD)
      then have above: ‹∀k > m. t ∈ set (ptms (shd (sdrop k steps)))›
        by (metis Nat.lessE less_irrefl_nat less_trans_Suc linorder_not_less sdrop_simps(2))
      let ?pre = ‹stake (n + m + 1) steps›
      let ?suf = ‹sdrop (n + m + 1) steps›
      have *: ‹¬ affects r ?f› for r
        unfolding affects_def by (cases r, simp_all)+
      have ‹ev (holds (is_rule ?r)) ?suf›
        using ‹Saturated steps› Saturated_ev_rule by blast
      then obtain pre suf k where
        pre: ‹list_all (not (is_rule ?r)) pre› and
        suf: ‹holds (is_rule ?r) suf› and
        ori: ‹pre = stake k ?suf› ‹suf = sdrop k ?suf›
        using ev_prefix_sdrop by blast
      have k: ‹∃k > m. suf = sdrop k steps›
        using ori by (meson le_add2 less_add_one order_le_less_trans sdrop_add trans_less_add1)
      have ‹list_all (not (λstep. affects (snd step) ?f)) ?pre›
        unfolding list_all_def using * by (induct ?pre) simp_all
      then have ‹?f ∈ set (pseq (shd ?suf))›
        using ‹epath steps› epath_preserves_unaffected n epath_sdrop
        by (metis (no_types, lifting) list.pred_mono_strong list_all_append
            sdrop_add stake_add stake_sdrop)
      then have ‹?f ∈ set (pseq (shd suf))›
        using ‹epath steps› epath_preserves_unaffected n epath_sdrop * ori
        by (metis (no_types, lifting) list.pred_mono_strong pre stake_sdrop)
      moreover have ‹epath suf›
        using ‹epath steps› epath_sdrop ori by blast
      then obtain B z' r' where
        z': ‹(B, z') |∈| effect ?r (ptms (shd suf), pseq (shd suf))›
        ‹shd (stl suf) = ((B, z'), r')›
        using suf epath_effect unfolding pseq_def ptms_def
        by (metis (mono_tags, lifting) holds.elims(2) prod.collapse)
      moreover have ‹t ∈ set (ptms (shd suf))›
        using above k by (meson le_add2 less_add_one order_le_less_trans)
      ultimately have ‹sub 0 t p ∈ set z'›
        using parts_in_effect[where A=‹ptms (shd suf)›] unfolding parts_def by fastforce
      then show ?thesis
        using k pseq_in_tree_fms z'(2)
        by (metis Pair_inject in_mono prod.collapse pseq_def shd_sset sset_sdrop stl_sset)
    qed
  qed
next
  fix p
  assume ‹Neg (Uni p) ∈ ?H› (is ‹?f ∈ ?H›)
  then obtain n where n: ‹?f ∈ set (pseq (shd (sdrop n steps)))›
    using tree_fms_in_pseq by auto
  let ?r = GammaUni
  show ‹∀t ∈ terms ?H. Neg (sub 0 t p) ∈ ?H›
  proof
    fix t
    assume t: ‹t ∈ terms ?H›
    show ‹Neg (sub 0 t p) ∈ ?H›
    proof -
      have ‹∃m. t ∈ set (subterms (pseq (shd (sdrop m steps))))›
      proof (cases ‹(⋃f ∈ ?H. set (subtermFm f)) = {}›)
        case True
        moreover have ‹∀p ∈ set (pseq (shd steps)). p ∈ ?H›
          unfolding tree_fms_def by (metis pseq_in_tree_fms shd_sset tree_fms_def)
        ultimately have ‹∀p ∈ set (pseq (shd steps)). subtermFm p = []›
          by simp
        then have ‹concat (map subtermFm (pseq (shd steps))) = []›
          by (induct ‹pseq (shd steps)›) simp_all
        then have ‹subterms (pseq (shd steps)) = [Fun 0 []]›
          unfolding subterms_def by (metis list.simps(4) remdups_eq_nil_iff)
        then show ?thesis
          using True t unfolding terms_def
          by (metis empty_iff insert_iff list.set_intros(1) sdrop.simps(1))
      next
        case False
        then obtain pt where pt: ‹t ∈ set (subtermFm pt)› ‹pt ∈ ?H›
          using t unfolding terms_def by (metis (no_types, lifting) UN_E)
        then obtain m where m: ‹pt ∈ set (pseq (shd (sdrop m steps)))›
          using tree_fms_in_pseq by auto
        then show ?thesis
          using pt(1) set_subterms by fastforce
      qed
      then obtain m where ‹t ∈ set (subterms (pseq (shd (sdrop m steps))))›
        by blast
      then have ‹t ∈ set (ptms (shd (stl (sdrop m steps))))›
        using epath_stl_ptms epath_sdrop ‹epath steps›
        by (metis (no_types, lifting) Un_iff set_append set_remdups)
      moreover have ‹epath (stl (sdrop m steps))›
        using epath_sdrop ‹epath steps› by (meson epath.cases)
      ultimately have ‹∀k ≥ m. t ∈ set (ptms (shd (stl (sdrop k steps))))›
        using epath_sdrop_ptms by (metis (no_types, lifting) le_Suc_ex sdrop_add sdrop_stl subsetD)
      then have above: ‹∀k > m. t ∈ set (ptms (shd (sdrop k steps)))›
        by (metis Nat.lessE less_irrefl_nat less_trans_Suc linorder_not_less sdrop_simps(2))
      let ?pre = ‹stake (n + m + 1) steps›
      let ?suf = ‹sdrop (n + m + 1) steps›
      have *: ‹¬ affects r ?f› for r
        unfolding affects_def by (cases r, simp_all)+
      have ‹ev (holds (is_rule ?r)) ?suf›
        using ‹Saturated steps› Saturated_ev_rule by blast
      then obtain pre suf k where
        pre: ‹list_all (not (is_rule ?r)) pre› and
        suf: ‹holds (is_rule ?r) suf› and
        ori: ‹pre = stake k ?suf› ‹suf = sdrop k ?suf›
        using ev_prefix_sdrop by blast
      have k: ‹∃k > m. suf = sdrop k steps›
        using ori by (meson le_add2 less_add_one order_le_less_trans sdrop_add trans_less_add1)
      have ‹list_all (not (λstep. affects (snd step) ?f)) ?pre›
        unfolding list_all_def using * by (induct ?pre) simp_all
      then have ‹?f ∈ set (pseq (shd ?suf))›
        using ‹epath steps› epath_preserves_unaffected n epath_sdrop
        by (metis (no_types, lifting) list.pred_mono_strong list_all_append
            sdrop_add stake_add stake_sdrop)
      then have ‹?f ∈ set (pseq (shd suf))›
        using ‹epath steps› epath_preserves_unaffected n epath_sdrop * ori
        by (metis (no_types, lifting) list.pred_mono_strong pre stake_sdrop)
      moreover have ‹epath suf›
        using ‹epath steps› epath_sdrop ori by blast
      then obtain B z' r' where
        z': ‹(B, z') |∈| effect ?r (ptms (shd suf), pseq (shd suf))›
        ‹shd (stl suf) = ((B, z'), r')›
        using suf epath_effect unfolding pseq_def ptms_def
        by (metis (mono_tags, lifting) holds.elims(2) prod.collapse)
      moreover have ‹t ∈ set (ptms (shd suf))›
        using above k by (meson le_add2 less_add_one order_le_less_trans)
      ultimately have ‹Neg (sub 0 t p) ∈ set z'›
        using parts_in_effect[where A=‹ptms (shd suf)›] unfolding parts_def by fastforce
      then show ?thesis
        using k pseq_in_tree_fms z'(2)
        by (metis Pair_inject in_mono prod.collapse pseq_def shd_sset sset_sdrop stl_sset)
    qed
  qed
next
  fix p
  assume ‹Uni p ∈ tree_fms steps› (is ‹?f ∈ ?H›)
  then obtain n where n: ‹?f ∈ set (pseq (shd (sdrop n steps)))›
    using tree_fms_in_pseq by auto
  let ?steps = ‹sdrop n steps›
  let ?r = DeltaUni
  have ‹ev (holds (is_rule ?r)) ?steps›
    using ‹Saturated steps› Saturated_ev_rule by blast
  then obtain pre suf where
    pre: ‹list_all (not (is_rule ?r)) pre› and
    suf: ‹holds (is_rule ?r) suf› and
    ori: ‹?steps = pre @- suf›
    using ev_prefix by blast
  have ‹affects r ?f ⟷ r = ?r› for r
    unfolding affects_def by (cases r) simp_all
  then have ‹list_all (not (λstep. affects (snd step) ?f)) pre›
    using pre by simp
  moreover have ‹epath (pre @- suf)›
    using ‹epath steps› epath_sdrop ori by metis
  ultimately have ‹?f ∈ set (pseq (shd suf))›
    using epath_preserves_unaffected n ori by metis
  moreover have ‹epath suf›
    using ‹epath (pre @- suf)› epath_sdrop by (metis alwD alw_iff_sdrop alw_shift)
  then obtain B z' r' where
    z': ‹(B, z') |∈| effect ?r (ptms (shd suf), pseq (shd suf))› ‹shd (stl suf) = ((B, z'), r')›
    using suf epath_effect unfolding pseq_def ptms_def
    by (metis (mono_tags, lifting) holds.elims(2) prod.collapse)
  ultimately obtain C where
    C: ‹set (ptms (shd suf)) ⊆ set C› ‹sub 0 (Fun (generateNew C) []) p ∈ set z'›
    using parts_in_effect[where B=B and z'=‹z'› and z=‹pseq (shd suf)› and r=‹?r› and p=‹Uni p›]
    unfolding parts_def by auto
  then have *: ‹sub 0 (Fun (generateNew C) []) p ∈ ?H›
    using z'(2) ori pseq_in_tree_fms
    by (metis (no_types, lifting) Pair_inject Un_iff in_mono prod.collapse pseq_def shd_sset
        sset_sdrop sset_shift stl_sset)
  let ?t = ‹Fun (generateNew C) []›
  show ‹∃t ∈ terms ?H. sub 0 t p ∈ ?H›
  proof (cases ‹?t ∈ set (subtermFm (sub 0 ?t p))›)
    case True
    then have ‹?t ∈ terms ?H›
      unfolding terms_def using * by (metis UN_I empty_iff)
    then show ?thesis
      using * by blast
  next
    case False
    then have ‹sub 0 t p = sub 0 ?t p› for t
      using sub_const_transfer by metis
    moreover have ‹terms ?H ≠ {}›
      unfolding terms_def by simp
    then have ‹∃t. t ∈ terms ?H›
      by blast
    ultimately show ?thesis
      using * by metis
  qed
next
  fix p
  assume ‹Neg (Exi p) ∈ tree_fms steps› (is ‹?f ∈ ?H›)
  then obtain n where n: ‹?f ∈ set (pseq (shd (sdrop n steps)))›
    using tree_fms_in_pseq by auto
  let ?steps = ‹sdrop n steps›
  let ?r = DeltaExi
  have ‹ev (holds (is_rule ?r)) ?steps›
    using ‹Saturated steps› Saturated_ev_rule by blast
  then obtain pre suf where
    pre: ‹list_all (not (is_rule ?r)) pre› and
    suf: ‹holds (is_rule ?r) suf› and
    ori: ‹?steps = pre @- suf›
    using ev_prefix by blast
  have ‹affects r ?f ⟷ r = ?r› for r
    unfolding affects_def by (cases r) simp_all
  then have ‹list_all (not (λstep. affects (snd step) ?f)) pre›
    using pre by simp
  moreover have ‹epath (pre @- suf)›
    using ‹epath steps› epath_sdrop ori by metis
  ultimately have ‹?f ∈ set (pseq (shd suf))›
    using epath_preserves_unaffected n ori by metis
  moreover have ‹epath suf›
    using ‹epath (pre @- suf)› epath_sdrop by (metis alwD alw_iff_sdrop alw_shift)
  then obtain B z' r' where
    z': ‹(B, z') |∈| effect ?r (ptms (shd suf), pseq (shd suf))› ‹shd (stl suf) = ((B, z'), r')›
    using suf epath_effect unfolding pseq_def ptms_def
    by (metis (mono_tags, lifting) holds.elims(2) prod.collapse)
  ultimately obtain C where
    C: ‹set (ptms (shd suf)) ⊆ set C› ‹Neg (sub 0 (Fun (generateNew C) []) p) ∈ set z'›
    using parts_in_effect[where B=B and z'=z' and z=‹pseq (shd suf)› and r=‹?r› and p=‹Neg (Exi p)›]
    unfolding parts_def by auto
  then have *: ‹Neg (sub 0 (Fun (generateNew C) []) p) ∈ ?H›
    using z'(2) ori pseq_in_tree_fms
    by (metis (no_types, lifting) Pair_inject Un_iff in_mono prod.collapse pseq_def shd_sset
        sset_sdrop sset_shift stl_sset)
  let ?t = ‹Fun (generateNew C) []›
  show ‹∃t ∈ terms ?H. Neg (sub 0 t p) ∈ ?H›
  proof (cases ‹?t ∈ set (subtermFm (Neg (sub 0 ?t p)))›)
    case True
    then have ‹?t ∈ terms ?H›
      unfolding terms_def using * by (metis UN_I empty_iff)
    then show ?thesis
      using * by blast
  next
    case False
    then have ‹Neg (sub 0 t p) = Neg (sub 0 ?t p)› for t
      using sub_const_transfer by (metis subtermFm.simps(7))
    moreover have ‹terms ?H ≠ {}›
      unfolding terms_def by simp
    then have ‹∃t. t ∈ terms ?H›
      by blast
    ultimately show ?thesis
      using * by metis
  qed
next
  fix p
  assume ‹Neg (Neg p) ∈ tree_fms steps› (is ‹?f ∈ ?H›)
  then obtain n where n: ‹?f ∈ set (pseq (shd (sdrop n steps)))›
    using tree_fms_in_pseq by auto
  let ?steps = ‹sdrop n steps›
  let ?r = NegNeg
  have ‹ev (holds (is_rule ?r)) ?steps›
    using ‹Saturated steps› Saturated_ev_rule by blast
  then obtain pre suf where
    pre: ‹list_all (not (is_rule ?r)) pre› and
    suf: ‹holds (is_rule ?r) suf› and
    ori: ‹?steps = pre @- suf›
    using ev_prefix by blast
  have ‹affects r ?f ⟷ r = ?r› for r
    unfolding affects_def by (cases r) simp_all
  then have ‹list_all (not (λstep. affects (snd step) ?f)) pre›
    using pre by simp
  moreover have ‹epath (pre @- suf)›
    using ‹epath steps› epath_sdrop ori by metis
  ultimately have ‹?f ∈ set (pseq (shd suf))›
    using epath_preserves_unaffected n ori by metis
  moreover have ‹epath suf›
    using ‹epath (pre @- suf)› epath_sdrop by (metis alwD alw_iff_sdrop alw_shift)
  then obtain B z' r' where
    z': ‹(B, z') |∈| effect ?r (ptms (shd suf), pseq (shd suf))› ‹shd (stl suf) = ((B, z'), r')›
    using suf epath_effect unfolding pseq_def ptms_def
    by (metis (mono_tags, lifting) holds.elims(2) prod.collapse)
  ultimately have ‹p ∈ set z'›
    using parts_in_effect unfolding parts_def by fastforce
  then show ‹p ∈ ?H›
    using z'(2) ori pseq_in_tree_fms
    by (metis (no_types, lifting) Pair_inject Un_iff in_mono prod.collapse pseq_def shd_sset
        sset_sdrop sset_shift stl_sset)
qed
end