Theory MLSS_Calculus

(*<*)
theory MLSS_Calculus
  imports "HOL-Library.Sublist" MLSS_Semantics MLSS_Typing_Defs
begin
(*>*)

section ‹The Calculus›
text ‹
  We define a tableau calculus for MLSS build up from linear and branching expansion rules.
›

subsection ‹Closedness›

fun member_seq :: "'a pset_term ⇒ 'a pset_atom list ⇒ 'a pset_term ⇒ bool" where
  "member_seq s [] t ⟷ s = t"
| "member_seq s ((s' ∈s u) # cs) t ⟷ s = s' ∧ member_seq u cs t"
| "member_seq _ _ _ ⟷ False"

fun member_cycle :: "'a pset_atom list ⇒ bool" where
  "member_cycle ((s ∈s t) # cs) = member_seq s ((s ∈s t) # cs) s"
| "member_cycle _ = False"

inductive bclosed :: "'a branch ⇒ bool" where
  contr: "⟦ φ ∈ set b; Neg φ ∈ set b ⟧ ⟹ bclosed b"
| memEmpty: "AT (t ∈s (∅ n)) ∈ set b ⟹ bclosed b"
| neqSelf: "AF (t =s t) ∈ set b ⟹ bclosed b"
| memberCycle: "⟦ member_cycle cs; set cs ⊆ Atoms (set b) ⟧ ⟹ bclosed b"

abbreviation "bopen b ≡ ¬ bclosed b"

subsection ‹Linear Expansion Rules›

fun tlvl_terms :: "'a pset_atom ⇒ 'a pset_term set" where
  "tlvl_terms (t1 ∈s t2) = {t1, t2}"
| "tlvl_terms (t1 =s t2) = {t1, t2}"

lemma tlvl_intros[intro, simp]:
  "t1 ∈ tlvl_terms (t1 ∈s t2)"
  "t2 ∈ tlvl_terms (t2 ∈s t1)"
  "t1 ∈ tlvl_terms (t1 =s t2)"
  "t2 ∈ tlvl_terms (t2 =s t1)"
  by auto
  
fun subst_tlvl :: "'a pset_term ⇒ 'a pset_term ⇒ 'a pset_atom ⇒ 'a pset_atom" where
  "subst_tlvl t1 t2 (s1 ∈s s2) =
    (if s1 = t1 then t2 else s1) ∈s (if s2 = t1 then t2 else s2)"
| "subst_tlvl t1 t2 (s1 =s s2) =
    (if s1 = t1 then t2 else s1) =s (if s2 = t1 then t2 else s2)"

inductive lexpands_fm :: "'a branch ⇒ 'a branch ⇒ bool" where
  "And p q ∈ set b ⟹ lexpands_fm [p, q] b"
| "Neg (Or p q) ∈ set b ⟹ lexpands_fm [Neg p, Neg q] b"
| "⟦ Or p q ∈ set b; Neg p ∈ set b ⟧ ⟹ lexpands_fm [q] b"
| "⟦ Or p q ∈ set b; Neg q ∈ set b ⟧ ⟹ lexpands_fm [p] b"
| "⟦ Neg (And p q) ∈ set b; p ∈ set b ⟧ ⟹ lexpands_fm [Neg q] b"
| "⟦ Neg (And p q) ∈ set b; q ∈ set b ⟧ ⟹ lexpands_fm [Neg p] b"
| "Neg (Neg p) ∈ set b ⟹ lexpands_fm [p] b"

inductive lexpands_un :: "'a branch ⇒ 'a branch ⇒ bool" where
  "AF (s ∈s t1 ⊔s t2) ∈ set b ⟹ lexpands_un [AF (s ∈s t1), AF (s ∈s t2)] b"
| "⟦ AT (s ∈s t1) ∈ set b; t1 ⊔s t2 ∈ subterms (last b) ⟧
    ⟹ lexpands_un [AT (s ∈s t1 ⊔s t2)] b"
| "⟦ AT (s ∈s t2) ∈ set b; t1 ⊔s t2 ∈ subterms (last b) ⟧
    ⟹ lexpands_un [AT (s ∈s t1 ⊔s t2)] b"
| "⟦ AT (s ∈s t1 ⊔s t2) ∈ set b; AF (s ∈s t1) ∈ set b ⟧
    ⟹ lexpands_un [AT (s ∈s t2)] b"
| "⟦ AT (s ∈s t1 ⊔s t2) ∈ set b; AF (s ∈s t2) ∈ set b ⟧
    ⟹ lexpands_un [AT (s ∈s t1)] b"
| "⟦ AF (s ∈s t1) ∈ set b; AF (s ∈s t2) ∈ set b; t1 ⊔s t2 ∈ subterms (last b) ⟧
    ⟹ lexpands_un [AF (s ∈s t1 ⊔s t2)] b"

inductive lexpands_int :: "'a branch ⇒ 'a branch ⇒ bool" where
  "AT (s ∈s t1 ⊓s t2) ∈ set b ⟹ lexpands_int [AT (s ∈s t1), AT (s ∈s t2)] b"
| "⟦ AF (s ∈s t1) ∈ set b; t1 ⊓s t2 ∈ subterms (last b) ⟧
    ⟹ lexpands_int [AF (s ∈s t1 ⊓s t2)] b"
| "⟦ AF (s ∈s t2) ∈ set b; t1 ⊓s t2 ∈ subterms (last b) ⟧
    ⟹ lexpands_int [AF (s ∈s t1 ⊓s t2)] b"
| "⟦ AF (s ∈s t1 ⊓s t2) ∈ set b; AT (s ∈s t1) ∈ set b ⟧
    ⟹ lexpands_int [AF (s ∈s t2)] b"
| "⟦ AF (s ∈s t1 ⊓s t2) ∈ set b; AT (s ∈s t2) ∈ set b ⟧
    ⟹ lexpands_int [AF (s ∈s t1)] b"
| "⟦ AT (s ∈s t1) ∈ set b; AT (s ∈s t2) ∈ set b; t1 ⊓s t2 ∈ subterms (last b) ⟧
    ⟹ lexpands_int [AT (s ∈s t1 ⊓s t2)] b"

inductive lexpands_diff :: "'a branch ⇒ 'a branch ⇒ bool" where
  "AT (s ∈s t1 -s t2) ∈ set b ⟹ lexpands_diff [AT (s ∈s t1), AF (s ∈s t2)] b"
| "⟦ AF (s ∈s t1) ∈ set b; t1 -s t2 ∈ subterms (last b) ⟧
    ⟹ lexpands_diff [AF (s ∈s t1 -s t2)] b"
| "⟦ AT (s ∈s t2) ∈ set b; t1 -s t2 ∈ subterms (last b) ⟧
    ⟹ lexpands_diff [AF (s ∈s t1 -s t2)] b"
| "⟦ AF (s ∈s t1 -s t2) ∈ set b; AT (s ∈s t1) ∈ set b ⟧
    ⟹ lexpands_diff [AT (s ∈s t2)] b"
| "⟦ AF (s ∈s t1 -s t2) ∈ set b; AF (s ∈s t2) ∈ set b ⟧
    ⟹ lexpands_diff [AF (s ∈s t1)] b"
| "⟦ AT (s ∈s t1) ∈ set b; AF (s ∈s t2) ∈ set b; t1 -s t2 ∈ subterms (last b) ⟧
    ⟹ lexpands_diff [AT (s ∈s t1 -s t2)] b"

inductive lexpands_single :: "'a branch ⇒ 'a branch ⇒ bool" where
  "Single t1 ∈ subterms (last b) ⟹ lexpands_single [AT (t1 ∈s Single t1)] b"
| "AT (s ∈s Single t1) ∈ set b ⟹ lexpands_single [AT (s =s t1)] b"
| "AF (s ∈s Single t1) ∈ set b ⟹ lexpands_single [AF (s =s t1)] b"

inductive lexpands_eq :: "'a branch ⇒ 'a branch ⇒ bool" where
  "⟦ AT (t1 =s t2) ∈ set b; AT l ∈ set b; t1 ∈ tlvl_terms l ⟧
    ⟹ lexpands_eq [AT (subst_tlvl t1 t2 l)] b"
| "⟦ AT (t1 =s t2) ∈ set b; AF l ∈ set b; t1 ∈ tlvl_terms l ⟧
    ⟹ lexpands_eq [AF (subst_tlvl t1 t2 l)] b"
| "⟦ AT (t1 =s t2) ∈ set b; AT l ∈ set b; t2 ∈ tlvl_terms l ⟧
    ⟹ lexpands_eq [AT (subst_tlvl t2 t1 l)] b"
| "⟦ AT (t1 =s t2) ∈ set b; AF l ∈ set b; t2 ∈ tlvl_terms l ⟧
    ⟹ lexpands_eq [AF (subst_tlvl t2 t1 l)] b"
| "⟦ AT (s ∈s t) ∈ set b; AF (s' ∈s t) ∈ set b ⟧
    ⟹ lexpands_eq [AF (s =s s')] b"

fun polarise :: "bool ⇒ 'a fm ⇒ 'a fm" where
  "polarise True φ = φ"
| "polarise False φ = Neg φ"

lemma lexpands_eq_induct'[consumes 1, case_names subst neq]:
  assumes "lexpands_eq b' b"
  assumes "⋀t1 t2 t1' t2' p l b. 
      ⟦ AT (t1 =s t2) ∈ set b; polarise p (Atom l) ∈ set b;
       (t1', t2') ∈ {(t1, t2), (t2, t1)}; t1' ∈ tlvl_terms l ⟧
      ⟹ P [polarise p (Atom (subst_tlvl t1' t2' l))] b"
  assumes "⋀s t s' b. ⟦ AT (s ∈s t) ∈ set b; AF (s' ∈s t) ∈ set b ⟧ ⟹ P [AF (s =s s')] b"
  shows "P b' b"
  using assms(1)
  apply(induction rule: lexpands_eq.induct)
  by (metis assms(2-) insertI1 insertI2 polarise.simps)+

inductive lexpands :: "'a branch ⇒ 'a branch ⇒ bool" where
  "lexpands_fm b' b ⟹ lexpands b' b"
| "lexpands_un b' b ⟹ lexpands b' b"
| "lexpands_int b' b ⟹ lexpands b' b"
| "lexpands_diff b' b ⟹ lexpands b' b"
| "lexpands_single b' b ⟹ lexpands b' b"
| "lexpands_eq b' b ⟹ lexpands b' b"

lemma lexpands_induct[consumes 1]:
  assumes "lexpands b' b"
  shows "
    (⋀p q b. And p q ∈ set b ⟹ P [p, q] b) ⟹
    (⋀p q b. Neg (Or p q) ∈ set b ⟹ P [Neg p, Neg q] b) ⟹
    (⋀p q b. Or p q ∈ set b ⟹ Neg p ∈ set b ⟹ P [q] b) ⟹
    (⋀p q b. Or p q ∈ set b ⟹ Neg q ∈ set b ⟹ P [p] b) ⟹
    (⋀p q b. Neg (And p q) ∈ set b ⟹ p ∈ set b ⟹ P [Neg q] b) ⟹
    (⋀p q b. Neg (And p q) ∈ set b ⟹ q ∈ set b ⟹ P [Neg p] b) ⟹
    (⋀p b. Neg (Neg p) ∈ set b ⟹ P [p] b) ⟹
    (⋀s t1 t2 b. AF (s ∈s t1 ⊔s t2) ∈ set b ⟹ P [AF (s ∈s t1), AF (s ∈s t2)] b) ⟹
    (⋀s t1 b t2. AT (s ∈s t1) ∈ set b ⟹ t1 ⊔s t2 ∈ subterms (last b) ⟹ P [AT (s ∈s t1 ⊔s t2)] b) ⟹
    (⋀s t2 b t1. AT (s ∈s t2) ∈ set b ⟹ t1 ⊔s t2 ∈ subterms (last b) ⟹ P [AT (s ∈s t1 ⊔s t2)] b) ⟹
    (⋀s t1 t2 b. AT (s ∈s t1 ⊔s t2) ∈ set b ⟹ AF (s ∈s t1) ∈ set b ⟹ P [AT (s ∈s t2)] b) ⟹
    (⋀s t1 t2 b. AT (s ∈s t1 ⊔s t2) ∈ set b ⟹ AF (s ∈s t2) ∈ set b ⟹ P [AT (s ∈s t1)] b) ⟹
    (⋀s t1 b t2. AF (s ∈s t1) ∈ set b ⟹ AF (s ∈s t2) ∈ set b ⟹ t1 ⊔s t2 ∈ subterms (last b) ⟹ P [AF (s ∈s t1 ⊔s t2)] b) ⟹
    (⋀s t1 t2 b. AT (s ∈s t1 ⊓s t2) ∈ set b ⟹ P [AT (s ∈s t1), AT (s ∈s t2)] b) ⟹
    (⋀s t1 b t2. AF (s ∈s t1) ∈ set b ⟹ t1 ⊓s t2 ∈ subterms (last b) ⟹ P [AF (s ∈s t1 ⊓s t2)] b) ⟹
    (⋀s t2 b t1. AF (s ∈s t2) ∈ set b ⟹ t1 ⊓s t2 ∈ subterms (last b) ⟹ P [AF (s ∈s t1 ⊓s t2)] b) ⟹
    (⋀s t1 t2 b. AF (s ∈s t1 ⊓s t2) ∈ set b ⟹ AT (s ∈s t1) ∈ set b ⟹ P [AF (s ∈s t2)] b) ⟹
    (⋀s t1 t2 b. AF (s ∈s t1 ⊓s t2) ∈ set b ⟹ AT (s ∈s t2) ∈ set b ⟹ P [AF (s ∈s t1)] b) ⟹
    (⋀s t1 b t2. AT (s ∈s t1) ∈ set b ⟹ AT (s ∈s t2) ∈ set b ⟹ t1 ⊓s t2 ∈ subterms (last b) ⟹ P [AT (s ∈s t1 ⊓s t2)] b) ⟹
    (⋀s t1 t2 b. AT (s ∈s t1 -s t2) ∈ set b ⟹ P [AT (s ∈s t1),  AF (s ∈s t2)] b) ⟹
    (⋀s t1 b t2. AF (s ∈s t1) ∈ set b ⟹ t1 -s t2 ∈ subterms (last b) ⟹ P [AF (s ∈s t1 -s t2)] b) ⟹
    (⋀s t2 b t1. AT (s ∈s t2) ∈ set b ⟹ t1 -s t2 ∈ subterms (last b) ⟹ P [AF (s ∈s t1 -s t2)] b) ⟹
    (⋀s t1 t2 b. AF (s ∈s t1 -s t2) ∈ set b ⟹ AT (s ∈s t1) ∈ set b ⟹ P [AT (s ∈s t2)] b) ⟹
    (⋀s t1 t2 b. AF (s ∈s t1 -s t2) ∈ set b ⟹ AF (s ∈s t2) ∈ set b ⟹ P [AF (s ∈s t1)] b) ⟹
    (⋀s t1 b t2. AT (s ∈s t1) ∈ set b ⟹ AF (s ∈s t2) ∈ set b ⟹ t1 -s t2 ∈ subterms (last b) ⟹ P [AT (s ∈s t1 -s t2)] b) ⟹
    (⋀t1 b. Single t1 ∈ subterms (last b) ⟹ P [AT (t1 ∈s Single t1)] b) ⟹
    (⋀s t1 b. AT (s ∈s Single t1) ∈ set b ⟹ P [AT (s =s t1)] b) ⟹
    (⋀s t1 b. AF (s ∈s Single t1) ∈ set b ⟹ P [AF (s =s t1)] b) ⟹
    (⋀t1 t2 b l. AT (t1 =s t2) ∈ set b ⟹ AT l ∈ set b ⟹ t1 ∈ tlvl_terms l ⟹ P [AT (subst_tlvl t1 t2 l)] b) ⟹
    (⋀t1 t2 b l. AT (t1 =s t2) ∈ set b ⟹ AF l ∈ set b ⟹ t1 ∈ tlvl_terms l ⟹ P [AF (subst_tlvl t1 t2 l)] b) ⟹
    (⋀t1 t2 b l. AT (t1 =s t2) ∈ set b ⟹ AT l ∈ set b ⟹ t2 ∈ tlvl_terms l ⟹ P [AT (subst_tlvl t2 t1 l)] b) ⟹
    (⋀t1 t2 b l. AT (t1 =s t2) ∈ set b ⟹ AF l ∈ set b ⟹ t2 ∈ tlvl_terms l ⟹ P [AF (subst_tlvl t2 t1 l)] b) ⟹  
    (⋀s t b s'. AT (s ∈s t) ∈ set b ⟹ AF (s' ∈s t) ∈ set b ⟹ P [AF (s =s s')] b) ⟹ P b' b"
  using assms
  apply(induction rule: lexpands.induct)
  subgoal apply(induction rule: lexpands_fm.induct) by metis+
  subgoal apply(induction rule: lexpands_un.induct) by metis+
  subgoal apply(induction rule: lexpands_int.induct) by metis+
  subgoal apply(induction rule: lexpands_diff.induct) by metis+
  subgoal apply(induction rule: lexpands_single.induct) by metis+
  subgoal apply(induction rule: lexpands_eq.induct) by metis+
  done


subsection ‹Branching Expansion Rules›

inductive bexpands_nowit :: "'a branch set ⇒ 'a branch ⇒ bool" where
  "⟦ Or p q ∈ set b;
     p ∉ set b; Neg p ∉ set b ⟧
    ⟹ bexpands_nowit {[p], [Neg p]} b"
| "⟦ Neg (And p q) ∈ set b;
     Neg p ∉ set b; p ∉ set b ⟧
    ⟹ bexpands_nowit {[Neg p], [p]} b"
| "⟦ AT (s ∈s t1 ⊔s t2) ∈ set b; t1 ⊔s t2 ∈ subterms (last b);
     AT (s ∈s t1) ∉ set b; AF (s ∈s t1) ∉ set b ⟧
    ⟹ bexpands_nowit {[AT (s ∈s t1)], [AF (s ∈s t1)]} b"
| "⟦ AT (s ∈s t1) ∈ set b; t1 ⊓s t2 ∈ subterms (last b);
     AT (s ∈s t2) ∉ set b; AF (s ∈s t2) ∉ set b ⟧
    ⟹ bexpands_nowit {[AT (s ∈s t2)], [AF (s ∈s t2)]} b"
| "⟦ AT (s ∈s t1) ∈ set b; t1 -s t2 ∈ subterms (last b);
     AT (s ∈s t2) ∉ set b; AF (s ∈s t2) ∉ set b ⟧
    ⟹ bexpands_nowit {[AT (s ∈s t2)], [AF (s ∈s t2)]} b"

inductive bexpands_wit ::
  "'a pset_term ⇒ 'a pset_term ⇒ 'a ⇒ 'a branch set ⇒ 'a branch ⇒ bool" for t1 t2 x where
  "⟦ AF (t1 =s t2) ∈ set b; t1 ∈ subterms (last b); t2 ∈ subterms (last b);
     ∄x. AT (x ∈s t1) ∈ set b ∧ AF (x ∈s t2) ∈ set b;
     ∄x. AT (x ∈s t2) ∈ set b ∧ AF (x ∈s t1) ∈ set b;
     x ∉ vars b; ¬ urelem (last b) t1; ¬ urelem (last b) t2 ⟧
    ⟹ bexpands_wit t1 t2 x {[AT (Var x ∈s t1), AF (Var x ∈s t2)],
                              [AT (Var x ∈s t2), AF (Var x ∈s t1)]} b"

inductive_cases bexpands_wit_cases[consumes 1]: "bexpands_wit t1 t2 x bs' b"

lemma bexpands_witD:
  assumes "bexpands_wit t1 t2 x bs' b"
  shows "bs' = {[AT (Var x ∈s t1), AF (Var x ∈s t2)],
               [AT (Var x ∈s t2), AF (Var x ∈s t1)]}"
        "AF (t1 =s t2) ∈ set b" "t1 ∈ subterms (last b)" "t2 ∈ subterms (last b)"
        "∄x. AT (x ∈s t1) ∈ set b ∧ AF (x ∈s t2) ∈ set b"
        "∄x. AT (x ∈s t2) ∈ set b ∧ AF (x ∈s t1) ∈ set b"
        "¬ urelem (last b) t1" "¬ urelem (last b) t2"
        "x ∉ vars b"
  using bexpands_wit.cases[OF assms] by metis+

inductive bexpands :: "'a branch set ⇒ 'a branch ⇒ bool" where
  "bexpands_nowit bs' b ⟹ bexpands bs' b"
| "bexpands_wit t1 t2 x bs' b ⟹ bexpands bs' b"

lemma bexpands_disjnt:
  assumes "bexpands bs' b" "b' ∈ bs'"
  shows "set b ∩ set b' = {}"
  using assms
proof(induction bs' b rule: bexpands.induct)
  case (1 bs b)
  then show ?case
    by (induction rule: bexpands_nowit.induct) (auto intro: list.set_intros(1))
next
  case (2 t1 t2 x bs b)
  then show ?case
  proof(induction rule: bexpands_wit.induct)
    case (1 b)
    from ‹x ∉ vars b›
    have "AT (Var x ∈s t1) ∉ set b" "AF (Var x ∈s t1) ∉ set b"
      unfolding vars_branch_def by auto
    with 1 show ?case
      by (auto intro: list.set_intros(1) simp: disjnt_iff vars_fm_vars_branchI)
  qed
qed

lemma bexpands_branch_not_Nil:
  assumes "bexpands bs' b" "b' ∈ bs'"
  shows "b' ≠ []"
  using assms
proof(induction bs' b rule: bexpands.induct)
  case (1 bs' b)
  then show ?case
    by (induction rule: bexpands_nowit.induct) auto
next
  case (2 t1 t2 x bs' b)
  then show ?case
    by (induction rule: bexpands_wit.induct) auto
qed

lemma bexpands_nonempty: "bexpands bs' b ⟹ bs' ≠ {}"
proof(induction rule: bexpands.induct)
  case (1 bs' b)
  then show ?case by (induction rule: bexpands_nowit.induct) auto
next
  case (2 t1 t2 x bs' b)
  then show ?case by (induction rule: bexpands_wit.induct) auto
qed

lemma bexpands_strict_mono:
  assumes "bexpands bs' b" "b' ∈ bs'"
  shows "set b ⊂ set (b' @ b)"
  using bexpands_disjnt[OF assms] bexpands_branch_not_Nil[OF assms]
  by (simp add: less_le) (metis Un_Int_eq(1) set_empty2)

inductive_cases bexpands_cases[consumes 1, case_names no_param param]: "bexpands bs b"


subsection ‹Expansion Closure›

inductive expandss :: "'a branch ⇒ 'a branch ⇒ bool" where
  "expandss b b"
| "lexpands b3 b2 ⟹ set b2 ⊂ set (b3 @ b2) ⟹ expandss b2 b1 ⟹ expandss (b3 @ b2) b1"
| "bexpands bs b2 ⟹ b3 ∈ bs ⟹ expandss b2 b1 ⟹ expandss (b3 @ b2) b1"

lemma expandss_trans: "expandss b3 b2 ⟹ expandss b2 b1 ⟹ expandss b3 b1"
  by (induction rule: expandss.induct) (auto simp: expandss.intros)

lemma expandss_suffix:
  "expandss b1 b2 ⟹ suffix b2 b1"
  apply(induction rule: expandss.induct)
    apply(auto simp: suffix_appendI)
  done

lemmas expandss_mono = set_mono_suffix[OF expandss_suffix]

lemma expandss_last_eq[simp]:
  "expandss b' b ⟹ b ≠ [] ⟹ last b' = last b"
  by (metis expandss_suffix last_appendR suffix_def)

lemma expandss_not_Nil:
  "expandss b' b ⟹ b ≠ [] ⟹ b' ≠ []"
  using expandss_suffix suffix_bot.extremum_uniqueI by blast


subsection ‹Well-Formed Branch›

definition "wf_branch b ≡ ∃φ. expandss b [φ]"

lemma wf_branch_singleton[simp]: "wf_branch [φ]"
  unfolding wf_branch_def using expandss.intros(1) by blast

lemma wf_branch_not_Nil[simp, intro?]: "wf_branch b ⟹ b ≠ []"
  unfolding wf_branch_def
  using expandss_suffix suffix_bot.extremum_uniqueI by blast

lemma wf_branch_expandss: "wf_branch b ⟹ expandss b' b ⟹ wf_branch b'"
  using expandss_trans wf_branch_def by blast

lemma wf_branch_lexpands:
  "wf_branch b ⟹ lexpands b' b ⟹ set b ⊂ set (b' @ b) ⟹ wf_branch (b' @ b)"
  by (metis expandss.simps wf_branch_expandss)

(*<*)
end
(*>*)