Require Import List Arith Bool Lia Eqdep_dec.

From Undecidability.Shared.Libs.DLW.Utils
  Require Import utils_tac utils_list utils_nat finite.

From Undecidability.Shared.Libs.DLW.Vec
  Require Import pos vec.

From Undecidability.TRAKHTENBROT
  Require Import notations utils fol_ops fo_sig fo_terms fo_logic fo_sat.

Import fol_notations.

Set Default Proof Using "Type".

Set Implicit Arguments.


Local Notation ø := vec_nil.

Section no_syms.

  Variable Σ : fo_signature.

  Definition Σ_empty_syms : fo_signature.
  Proof using Σ.
    exists Empty_set (rels Σ).
    + exact (fun _ => 1).
    + exact (ar_rels Σ).
  Defined.

  Notation Σ' := Σ_empty_syms.

  Implicit Types (t : fo_term (ar_syms Σ)) (A : fol_form Σ).

  Local Definition fo_term_no_sym t : incl (fo_term_syms t) nil -> nat.
  Proof.
    refine (match t with
      | in_var i => fun _ => i
      | in_fot s _ => fun H => False_rect nat _
    end).
    apply (H s (or_introl eq_refl)).
  Defined.

  Local Fact fo_term_no_sym_pirr t H1 H2 : fo_term_no_sym t H1 = fo_term_no_sym t H2.
  Proof.
    revert t H1 H2; intros [ i | s v ] H1 H2; simpl; auto.
    destruct (H1 s).
  Qed.

  Fixpoint Σ_no_sym (A : fol_form Σ) : incl (fol_syms A) nil -> fol_form Σ'.
  Proof.
    refine (match A with
      | => fun _ =>
      | fol_atom r v => fun H => @fol_atom Σ' r (vec_set_pos (fun p => in_var (fo_term_no_sym (vec_pos v p) _)))
      | fol_bin b A B => fun H => fol_bin b (Σ_no_sym A _) (Σ_no_sym B _)
      | fol_quant q A => fun H => fol_quant q (Σ_no_sym A _)
    end).
    + intros s Hs; apply H, in_flat_map; exists (vec_pos v p); split; auto; apply in_vec_list, in_vec_pos.
    + intros ? ?; apply H, in_app_iff; simpl; auto.
    + intros ? ?; apply H, in_app_iff; simpl; auto.
    + apply H.
  Defined.

  Variable (A : fol_form Σ) (HA : incl (fol_syms A) nil).

  Section semantics.

    Variable (X : Type).

    Local Fact fo_term_no_sym_sem t Ht M φ : @fo_term_sem _ X M φ t = φ (@fo_term_no_sym t Ht).
    Proof.
      revert t Ht; intros [ i | s v ] H; simpl; auto; destruct H.
    Qed.

    Section soundness.

      Hypothesis (M : fo_model Σ X).

      Let M' : fo_model Σ' X.
      Proof.
        split.
        + intros [].
        + apply (fom_rels M).
      Defined.

      Local Fact Σ_no_sym_sound φ : fol_sem M φ A <-> fol_sem M' φ (Σ_no_sym A HA).
      Proof.
        revert HA φ.
        induction A as [ | r v | b B HB C HC | q B HB ]; intros H φ.
        + simpl; tauto.
        + simpl fol_sem; apply fol_equiv_ext; f_equal.
          apply vec_pos_ext; intros p; rew vec; rew fot.
          apply fo_term_no_sym_sem.
        + apply fol_bin_sem_ext; auto.
        + apply fol_quant_sem_ext; auto.
      Qed.

      Hypothesis (Xf : finite_t X)
                 (Md : fo_model_dec M)
                 (phi : nat -> X)
                 (H : fol_sem M phi A).

      Local Fact Σ_no_sym_soundness : fo_form_fin_dec_SAT_in (Σ_no_sym A HA) X.
      Proof using Xf Md H.
        exists M', Xf, Md, phi.
        revert H; apply Σ_no_sym_sound.
      Qed.

    End soundness.

    Section completeness.

      Hypothesis (M' : fo_model Σ' X) (phi : nat -> X).

      Let M : fo_model Σ X.
      Proof.
       split.
        + intros _ _; exact (phi 0).
        + apply (fom_rels M').
      Defined.

      Local Fact Σ_no_sym_complete φ : fol_sem M φ A <-> fol_sem M' φ (Σ_no_sym A HA).
      Proof.
        revert HA φ.
        induction A as [ | r v | b B HB C HC | q B HB ]; intros H φ.
        + simpl; tauto.
        + simpl fol_sem; apply fol_equiv_ext; f_equal.
          apply vec_pos_ext; intros p; rew vec; rew fot.
          apply fo_term_no_sym_sem.
        + apply fol_bin_sem_ext; auto.
        + apply fol_quant_sem_ext; auto.
      Qed.

      Hypothesis (Xf : finite_t X)
                 (M'd : fo_model_dec M')
                 (H : fol_sem M' phi (Σ_no_sym A HA)).

      Local Fact Σ_no_sym_completeness : fo_form_fin_dec_SAT_in A X.
      Proof using Xf HA H M'd.
        exists M, Xf, M'd, phi.
        revert H; apply Σ_no_sym_complete.
      Qed.

    End completeness.

  End semantics.

  Theorem Σ_no_sym_correct : { B : fol_form Σ' | fo_form_fin_dec_SAT A <-> fo_form_fin_dec_SAT B }.
  Proof using HA.
    exists (Σ_no_sym A HA).
    split.
    + intros (X & M & H1 & H2 & phi & H3); exists X; apply Σ_no_sym_soundness with M phi; auto.
    + intros (X & M & H1 & H2 & phi & H3); exists X; apply Σ_no_sym_completeness with M phi; auto.
  Qed.

End no_syms.