Theory First_Order_Superposition

theory First_Order_Superposition
  imports
    Saturation_Framework.Lifting_to_Non_Ground_Calculi
    Ground_Superposition
    First_Order_Select
    First_Order_Ordering
    First_Order_Type_System
begin

hide_type Inference_System.inference
hide_const
  Inference_System.Infer
  Inference_System.prems_of
  Inference_System.concl_of
  Inference_System.main_prem_of

(* Hide as much of Restricted_Predicates.wfp_on as possible *)
hide_fact
  Restricted_Predicates.wfp_on_imp_minimal
  Restricted_Predicates.wfp_on_imp_inductive_on
  Restricted_Predicates.inductive_on_imp_wfp_on
  Restricted_Predicates.wfp_on_iff_inductive_on
  Restricted_Predicates.wfp_on_iff_minimal
  Restricted_Predicates.wfp_on_imp_has_min_elt
  Restricted_Predicates.wfp_on_induct
  Restricted_Predicates.wfp_on_UNIV
  Restricted_Predicates.wfp_less
  Restricted_Predicates.wfp_on_measure_on
  Restricted_Predicates.wfp_on_mono
  Restricted_Predicates.wfp_on_subset
  Restricted_Predicates.wfp_on_restrict_to
  Restricted_Predicates.wfp_on_imp_irreflp_on
  Restricted_Predicates.accessible_on_imp_wfp_on
  Restricted_Predicates.wfp_on_tranclp_imp_wfp_on
  Restricted_Predicates.wfp_on_imp_accessible_on
  Restricted_Predicates.wfp_on_accessible_on_iff
  Restricted_Predicates.wfp_on_restrict_to_tranclp
  Restricted_Predicates.wfp_on_restrict_to_tranclp'
  Restricted_Predicates.wfp_on_restrict_to_tranclp_wfp_on_conv

section ‹First-Order Layer›

locale first_order_superposition_calculus =
  first_order_select select +
  first_order_ordering lesst
  for 
    select :: "('f, ('v :: infinite)) select" and
    lesst :: "('f, 'v) term  ('f, 'v) term  bool" (infix "t" 50) +
  fixes
    tiebreakers :: "'f gatom clause   ('f, 'v) atom clause  ('f, 'v) atom clause  bool" and
    typeof_fun :: "('f, 'ty) fun_types"
  assumes
    wellfounded_tiebreakers: 
      "clauseG. wfP (tiebreakers clauseG)  
               transp (tiebreakers clauseG)  
               asymp (tiebreakers clauseG)" and
    function_symbols: "τ. f. typeof_fun f = ([], τ)" and
    ground_critical_pair_theorem: "(R :: 'f gterm rel). ground_critical_pair_theorem R" and
    variables: "|UNIV :: 'ty set| ≤o |UNIV :: 'v set|"
begin

abbreviation typed_tiebreakers :: 
      "'f gatom clause  ('f, 'v, 'ty) typed_clause  ('f, 'v, 'ty) typed_clause  bool" where 
    "typed_tiebreakers clauseG clause1 clause2  tiebreakers clauseG (fst clause1) (fst clause2)"

lemma wellfounded_typed_tiebreakers: 
      "wfP (typed_tiebreakers clauseG)  
       transp (typed_tiebreakers clauseG) 
      asymp (typed_tiebreakers clauseG)"
proof(intro conjI)

  show "wfp (typed_tiebreakers clauseG)"
    using wellfounded_tiebreakers
    by (meson wfP_if_convertible_to_wfP)

  show "transp (typed_tiebreakers clauseG)"
    using wellfounded_tiebreakers
    by (smt (verit, ccfv_threshold) transpD transpI)

  show "asymp (typed_tiebreakers clauseG)"
    using wellfounded_tiebreakers
    by (meson asympD asympI)
qed

definition is_merged_var_type_env where
  "is_merged_var_type_env 𝒱 X 𝒱X ρX Y 𝒱Y ρY 
    (x  X. welltyped typeof_fun 𝒱 (ρX x) (𝒱X x)) 
    (y  Y. welltyped typeof_fun 𝒱 (ρY y) (𝒱Y y))"

inductive eq_resolution :: "('f, 'v, 'ty) typed_clause  ('f, 'v, 'ty) typed_clause  bool" where
  eq_resolutionI: 
   "premise = add_mset literal premise' 
    literal = term !≈ term' 
    term_subst.is_imgu μ {{ term, term' }} 
    welltyped_imgu' typeof_fun 𝒱 term term' μ 
    select premise = {#}  is_maximall (literal ⋅l μ) (premise  μ)  
      is_maximall (literal ⋅l μ) ((select premise)  μ) 
    conclusion = premise'  μ 
    eq_resolution (premise, 𝒱) (conclusion, 𝒱)"

inductive eq_factoring :: "('f, 'v, 'ty) typed_clause  ('f, 'v, 'ty) typed_clause  bool" where
  eq_factoringI: "
    premise = add_mset literal1 (add_mset literal2 premise') 
    literal1 = term1  term1' 
    literal2 = term2  term2' 
    select premise = {#}  
    is_maximall (literal1 ⋅l μ) (premise  μ) 
    ¬ (term1 ⋅t μ t term1' ⋅t μ) 
    term_subst.is_imgu μ {{ term1, term2 }} 
    welltyped_imgu' typeof_fun 𝒱 term1 term2 μ 
    conclusion = add_mset (term1  term2') (add_mset (term1' !≈ term2') premise')  μ 
    eq_factoring (premise, 𝒱) (conclusion, 𝒱)"

inductive superposition ::
  "('f, 'v, 'ty) typed_clause  ('f, 'v, 'ty) typed_clause  ('f, 'v, 'ty) typed_clause  bool"
where
  superpositionI:
   "term_subst.is_renaming ρ1 
    term_subst.is_renaming ρ2 
    clause.vars (premise1  ρ1)   clause.vars (premise2  ρ2) = {} 
    premise1 = add_mset literal1 premise1' 
    premise2 = add_mset literal2 premise2' 
    𝒫  {Pos, Neg} 
    literal1 = 𝒫 (Upair context1term1 term1') 
    literal2 = term2  term2' 
    ¬ is_Var term1 
    term_subst.is_imgu μ {{term1 ⋅t ρ1, term2 ⋅t ρ2}} 
    welltyped_imgu' typeof_fun 𝒱3 (term1 ⋅t ρ1) (term2 ⋅t ρ2) μ 
    x  clause.vars (premise1  ρ1). 𝒱1 (the_inv ρ1 (Var x)) = 𝒱3 x 
    x  clause.vars (premise2  ρ2). 𝒱2 (the_inv ρ2 (Var x)) = 𝒱3 x 
    welltypedσ_on (clause.vars premise1) typeof_fun 𝒱1 ρ1 
    welltypedσ_on (clause.vars premise2) typeof_fun 𝒱2 ρ2 
    (τ τ'. has_type typeof_fun 𝒱2 term2 τ  has_type typeof_fun 𝒱2 term2' τ'  τ = τ') 
    ¬ (premise1  ρ1  μ c premise2  ρ2  μ) 
    (𝒫 = Pos 
       select premise1 = {#} 
       is_strictly_maximall (literal1 ⋅l ρ1 ⋅l μ) (premise1  ρ1  μ)) 
    (𝒫 = Neg 
       (select premise1 = {#}  is_maximall (literal1 ⋅l ρ1 ⋅l μ) (premise1  ρ1  μ) 
           is_maximall (literal1 ⋅l ρ1 ⋅l μ) ((select premise1)  ρ1  μ))) 
    select premise2 = {#} 
    is_strictly_maximall (literal2 ⋅l ρ2 ⋅l μ) (premise2  ρ2  μ) 
    ¬ (context1term1 ⋅t ρ1 ⋅t μ t term1' ⋅t ρ1 ⋅t μ) 
    ¬ (term2 ⋅t ρ2 ⋅t μ t term2' ⋅t ρ2 ⋅t μ) 
    conclusion = add_mset (𝒫 (Upair (context1 ⋅tc ρ1)term2' ⋅t ρ2 (term1' ⋅t ρ1))) 
          (premise1'  ρ1 + premise2'  ρ2)  μ 
    all_types 𝒱1  all_types 𝒱2 
    superposition (premise2, 𝒱2) (premise1, 𝒱1) (conclusion, 𝒱3)"

abbreviation eq_factoring_inferences where
  "eq_factoring_inferences  
    { Infer [premise] conclusion | premise conclusion. eq_factoring premise conclusion }"

abbreviation eq_resolution_inferences where
  "eq_resolution_inferences  
    { Infer [premise] conclusion | premise conclusion. eq_resolution premise conclusion }"

abbreviation superposition_inferences where
  "superposition_inferences  { Infer [premise2, premise1] conclusion 
    |  premise2 premise1 conclusion. superposition premise2 premise1 conclusion}"

definition inferences :: "('f, 'v, 'ty) typed_clause inference set" where
  "inferences  superposition_inferences  eq_resolution_inferences  eq_factoring_inferences"

abbreviation bottomF :: "('f, 'v, 'ty) typed_clause set" ("F") where
  "bottomF  {({#}, 𝒱) | 𝒱. all_types 𝒱 }"

subsubsection ‹Alternative Specification of the Superposition Rule›

inductive pos_superposition ::
  "('f, 'v, 'ty) typed_clause  ('f, 'v, 'ty) typed_clause  ('f, 'v, 'ty) typed_clause  bool"
where
  pos_superpositionI: "
    term_subst.is_renaming ρ1 
    term_subst.is_renaming ρ2 
    clause.vars (P1  ρ1)  clause.vars (P2  ρ2) = {} 
    P1 = add_mset L1 P1' 
    P2 = add_mset L2 P2' 
    L1 = s1u1  s1' 
    L2 = t2  t2' 
    ¬ is_Var u1 
    term_subst.is_imgu μ {{u1 ⋅t ρ1, t2 ⋅t ρ2}} 
    welltyped_imgu' typeof_fun 𝒱3 (u1 ⋅t ρ1) (t2 ⋅t ρ2) μ 
    x  clause.vars (P1  ρ1). 𝒱1 (the_inv ρ1 (Var x)) = 𝒱3 x 
    x  clause.vars (P2  ρ2). 𝒱2 (the_inv ρ2 (Var x)) = 𝒱3 x 
    welltypedσ_on (clause.vars P1) typeof_fun 𝒱1 ρ1 
    welltypedσ_on (clause.vars P2) typeof_fun 𝒱2 ρ2 
    (τ τ'. has_type typeof_fun 𝒱2 t2 τ  has_type typeof_fun 𝒱2 t2' τ'  τ = τ') 
    ¬ (P1  ρ1  μ c P2  ρ2  μ) 
    select P1 = {#} 
    is_strictly_maximall  (L1 ⋅l ρ1 ⋅l μ) (P1  ρ1  μ) 
    select P2 = {#} 
    is_strictly_maximall  (L2 ⋅l ρ2 ⋅l μ) (P2  ρ2  μ) 
    ¬ (s1u1 ⋅t ρ1 ⋅t μ t s1' ⋅t ρ1 ⋅t μ) 
    ¬ (t2 ⋅t ρ2 ⋅t μ t t2' ⋅t ρ2 ⋅t μ) 
    C = add_mset ((s1 ⋅tc ρ1)t2' ⋅t ρ2  (s1' ⋅t ρ1)) (P1'  ρ1 + P2'  ρ2)  μ 
    all_types 𝒱1  all_types 𝒱2 
    pos_superposition (P2, 𝒱2) (P1, 𝒱1) (C, 𝒱3)"

lemma superposition_if_pos_superposition:
  assumes "pos_superposition P2 P1 C"
  shows "superposition P2 P1 C"
  using assms
proof (cases rule: pos_superposition.cases)
  case (pos_superpositionI ρ1 ρ2 P1 P2 L1 P1' L2 P2' s1 u1 s1' t2 t2' μ 𝒱3 𝒱1 𝒱2 C)
  then show ?thesis
    using superpositionI[of ρ1 ρ2 P1 P2]
    by blast
qed

inductive neg_superposition ::
  "('f, 'v, 'ty) typed_clause  ('f, 'v, 'ty) typed_clause  ('f, 'v, 'ty) typed_clause  bool"
where
  neg_superpositionI: "
    term_subst.is_renaming ρ1 
    term_subst.is_renaming ρ2 
    clause.vars (P1  ρ1)  clause.vars (P2  ρ2) = {} 
    P1 = add_mset L1 P1' 
    P2 = add_mset L2 P2' 
    L1 = s1u1 !≈ s1' 
    L2 = t2  t2' 
    ¬ is_Var u1 
    term_subst.is_imgu μ {{u1 ⋅t ρ1, t2 ⋅t ρ2}} 
    welltyped_imgu' typeof_fun 𝒱3 (u1 ⋅t ρ1) (t2 ⋅t ρ2) μ 
    x  clause.vars (P1  ρ1). 𝒱1 (the_inv ρ1 (Var x)) = 𝒱3 x 
    x  clause.vars (P2  ρ2). 𝒱2 (the_inv ρ2 (Var x)) = 𝒱3 x 
    welltypedσ_on (clause.vars P1) typeof_fun 𝒱1 ρ1 
    welltypedσ_on (clause.vars P2) typeof_fun 𝒱2 ρ2 
    (τ τ'. has_type typeof_fun 𝒱2 t2 τ  has_type typeof_fun 𝒱2 t2' τ'  τ = τ') 
    ¬ (P1  ρ1  μ c P2  ρ2  μ) 
    select P1 = {#}  
      is_maximall (L1 ⋅l ρ1 ⋅l μ) (P1  ρ1  μ)  is_maximall (L1 ⋅l ρ1 ⋅l μ) ((select P1)  ρ1  μ) 
    select P2 = {#} 
    is_strictly_maximall  (L2 ⋅l ρ2 ⋅l μ) (P2  ρ2  μ) 
    ¬ (s1u1 ⋅t ρ1 ⋅t μ t s1' ⋅t ρ1 ⋅t μ) 
    ¬ (t2 ⋅t ρ2 ⋅t μ t t2' ⋅t ρ2 ⋅t μ) 
    C = add_mset (Neg (Upair (s1 ⋅tc ρ1)t2' ⋅t ρ2  (s1' ⋅t ρ1))) (P1'  ρ1 + P2'  ρ2)  μ 
    all_types 𝒱1  all_types 𝒱2 
    neg_superposition (P2, 𝒱2) (P1, 𝒱1) (C, 𝒱3)"

lemma superposition_if_neg_superposition:
  assumes "neg_superposition  P2 P1 C"
  shows "superposition P2 P1 C"
  using assms
proof (cases P2 P1 C rule: neg_superposition.cases)
  case (neg_superpositionI ρ1 ρ2 P1 L1 P1' P2 L2 P2' s1 u1 s1' t2 t2' μ 𝒱3 𝒱1 𝒱2 C)
  then show ?thesis
    using superpositionI[of ρ1 ρ2 P1 L1 P1' P2 L2 P2']
    by blast
qed

lemma superposition_iff_pos_or_neg:
  "superposition P2 P1 C  pos_superposition P2 P1 C  neg_superposition P2  P1 C"
proof (rule iffI)
  assume "superposition P2 P1 C"
  thus "pos_superposition  P2 P1 C  neg_superposition P2 P1 C"
  proof (cases P2 P1 C rule: superposition.cases)
    case (superpositionI ρ1 ρ2 premise1 premise2 literal1 premise1' literal2 premise2' 𝒫 context1 
          term1 term1' term2 term2' μ)
    then show ?thesis
      using
        pos_superpositionI[of ρ1 ρ2 premise1 premise2 literal1 premise1' literal2 premise2' context1 
                              term1 term1' term2 term2' μ]
        neg_superpositionI[of ρ1 ρ2 premise1 premise2 literal1 premise1' literal2 premise2' context1 
                              term1 term1' term2 term2' μ] 
      by blast
  qed
next
  assume "pos_superposition P2 P1 C  neg_superposition P2 P1 C"
  thus "superposition P2 P1 C"
    using superposition_if_neg_superposition superposition_if_pos_superposition by metis
qed

lemma eq_resolution_preserves_typing:
  assumes
    step: "eq_resolution (D, 𝒱) (C, 𝒱)" and
    wt_D: "welltypedc typeof_fun 𝒱 D"
  shows "welltypedc typeof_fun 𝒱 C"
  using step
proof (cases "(D, 𝒱)" "(C, 𝒱)" rule: eq_resolution.cases)
  case (eq_resolutionI literal premise' "term" term' μ)
  obtain τ where τ:
    "welltyped typeof_fun 𝒱 term τ"
    "welltyped typeof_fun 𝒱 term' τ"
    using wt_D
    unfolding 
      eq_resolutionI 
      welltypedc_add_mset 
      welltypedl_def 
      welltypeda_def
    by clause_simp

  then have "welltypedc typeof_fun 𝒱 (D   μ)"
    using wt_D welltypedσ_welltypedc eq_resolutionI(4)
    by blast
    
  then show ?thesis
    unfolding eq_resolutionI subst_clause_add_mset welltypedc_add_mset
    by clause_simp
qed

lemma has_type_welltyped:
  assumes "has_type typeof_fun 𝒱 term τ" "welltyped typeof_fun 𝒱 term τ'"
  shows "welltyped typeof_fun 𝒱 term τ"
  using assms
  by (smt (verit, best) welltyped.simps has_type.simps has_type_right_unique right_uniqueD)

lemma welltyped_has_type: 
  assumes "welltyped typeof_fun 𝒱 term τ"
  shows "has_type typeof_fun 𝒱 term τ"
  using assms welltyped.cases has_type.simps by fastforce

lemma eq_factoring_preserves_typing:
  assumes
    step: "eq_factoring (D, 𝒱) (C, 𝒱)" and
    wt_D: "welltypedc typeof_fun 𝒱 D"
  shows "welltypedc typeof_fun 𝒱 C"
  using step
proof (cases "(D, 𝒱)" "(C, 𝒱)" rule: eq_factoring.cases)
  case (eq_factoringI literal1 literal2 premise' term1 term1' term2 term2' μ)
  
  have wt_Dμ: "welltypedc typeof_fun 𝒱 (D  μ)"
    using wt_D welltypedσ_welltypedc eq_factoringI
    by blast

  show ?thesis
  proof-
    have "τ τ'.
       L∈#premise'  μ.
           τ. tset_uprod (atm_of L). First_Order_Type_System.welltyped typeof_fun 𝒱 t τ;
        First_Order_Type_System.welltyped typeof_fun 𝒱 (term1 ⋅t μ) τ;
        First_Order_Type_System.welltyped typeof_fun 𝒱 (term1' ⋅t μ) τ;
        First_Order_Type_System.welltyped typeof_fun 𝒱 (term2 ⋅t μ) τ';
        First_Order_Type_System.welltyped typeof_fun 𝒱 (term2' ⋅t μ) τ'
        τ. First_Order_Type_System.welltyped typeof_fun 𝒱 (term1 ⋅t μ) τ 
               First_Order_Type_System.welltyped typeof_fun 𝒱 (term2' ⋅t μ) τ"
       by (metis welltyped_right_unique eq_factoringI(8) right_uniqueD welltypedσ_welltyped)

     moreover have "τ τ'.
       L∈#premise'  μ.
           τ. tset_uprod (atm_of L). First_Order_Type_System.welltyped typeof_fun 𝒱 t τ;
        First_Order_Type_System.welltyped typeof_fun 𝒱 (term1 ⋅t μ) τ;
        First_Order_Type_System.welltyped typeof_fun 𝒱 (term1' ⋅t μ) τ;
        First_Order_Type_System.welltyped typeof_fun 𝒱 (term2 ⋅t μ) τ';
        First_Order_Type_System.welltyped typeof_fun 𝒱 (term2' ⋅t μ) τ'
        τ. First_Order_Type_System.welltyped typeof_fun 𝒱 (term1' ⋅t μ) τ 
               First_Order_Type_System.welltyped typeof_fun 𝒱 (term2' ⋅t μ) τ"
       by (metis welltyped_right_unique eq_factoringI(8) right_uniqueD welltypedσ_welltyped)

     ultimately show ?thesis
       using wt_Dμ
       unfolding welltypedc_def welltypedl_def welltypeda_def eq_factoringI subst_clause_add_mset 
         subst_literal subst_atom
       by auto
   qed
qed

lemma superposition_preserves_typing:
  assumes
    step: "superposition (D, 𝒱2) (C, 𝒱1) (E, 𝒱3)" and
    wt_C: "welltypedc typeof_fun 𝒱1 C" and
    wt_D: "welltypedc typeof_fun 𝒱2 D"
  shows "welltypedc typeof_fun 𝒱3 E"
  using step
proof (cases "(D, 𝒱2)" "(C, 𝒱1)" "(E, 𝒱3)" rule: superposition.cases)
  case (superpositionI ρ1 ρ2 literal1 premise1' literal2 premise2' 𝒫 context1 term1 term1' term2 
         term2' μ)

  have welltyped_μ: "welltypedσ typeof_fun 𝒱3 μ"
    using superpositionI(11)
    by blast

  have "welltypedc typeof_fun 𝒱3 (C  ρ1)"
    using wt_C welltypedc_renaming_weaker[OF superpositionI(1, 12)] 
    by blast

  then have wt_Cμ: "welltypedc typeof_fun 𝒱3 (C  ρ1  μ)"
    using welltypedσ_welltypedc[OF welltyped_μ]
    by blast

  have "welltypedc typeof_fun 𝒱3 (D  ρ2)"
    using wt_D welltypedc_renaming_weaker[OF superpositionI(2, 13)]
    by blast    

  then have wt_Dμ: "welltypedc typeof_fun 𝒱3 (D  ρ2  μ)"
    using welltypedσ_welltypedc[OF welltyped_μ]
    by blast

  note imgu = term_subst.subst_imgu_eq_subst_imgu[OF superpositionI(10)]

  show ?thesis
    using literal_cases[OF superpositionI(6)] wt_Cμ wt_Dμ
    by cases (clause_simp simp: superpositionI imgu)
qed

end

end