Section FullFOL.
Context {Sigma : Signature}.
Definition form_shift n := var_term (S n).
Notation "↑" := form_shift.
(* **** Subformula *)
Inductive sf : form -> form -> Prop :=
| SImplL phi psi : sf phi (phi --> psi)
| SImplR phi psi : sf psi (phi --> psi)
(* | SEq s t s' t' : sf (Pr s' t') (Eq s t) *)
| SDisjL phi psi : sf phi (phi ∨ psi)
| SDisjR phi psi : sf psi (phi ∨ psi)
| SConjL phi psi : sf phi (phi ∧ psi)
| SConjR phi psi : sf psi (phi ∧ psi)
| SAll phi t : sf (phi [t .: ids]) (∀ phi)
| SEx phi t : sf (phi [t .: ids]) (∃ phi).
(* ** Formula size *)
Fixpoint size (phi : form ) :=
match phi with
| Pred _ _ => 0
| Fal => 0
| Impl phi psi
| Conj phi psi
| Disj phi psi => S (size phi + size psi)
| All phi
| Ex phi => S (size phi)
end.
(* **** Forall and Vector.t technology **)
Inductive Forall (A : Type) (P : A -> Type) : forall n, vector A n -> Type :=
| Forall_nil : Forall P (@Vector.nil A)
| Forall_cons : forall n (x : A) (l : vector A n), P x -> Forall P l -> Forall P (@Vector.cons A x n l).
Inductive vec_in (A : Type) (a : A) : forall n, vector A n -> Type :=
| vec_inB n (v : vector A n) : vec_in a (cons a v)
| vec_inS a' n (v :vector A n) : vec_in a v -> vec_in a (cons a' v).
Hint Constructors vec_in : core.
(* **** Free variables *)
Inductive unused_term (n : nat) : term -> Prop :=
| uft_var m : n <> m -> unused_term n (var_term m)
| uft_Func F v : (forall t, vec_in t v -> unused_term n t) -> unused_term n (Func F v).
Inductive unused (n : nat) : form -> Prop :=
| uf_Fal : unused n Fal
| uf_Pred P v : (forall t, vec_in t v -> unused_term n t) -> unused n (Pred P v)
| uf_I phi psi : unused n phi -> unused n psi -> unused n (Impl phi psi)
| uf_A phi psi : unused n phi -> unused n psi -> unused n (Conj phi psi)
| uf_O phi psi : unused n phi -> unused n psi -> unused n (Disj phi psi)
| uf_All phi : unused (S n) phi -> unused n (All phi)
| uf_Ex phi : unused (S n) phi -> unused n (Ex phi).
Definition unused_L n A := forall phi, phi el A -> unused n phi.
Definition closed phi := forall n, unused n phi.
Proof with eauto using unused.
induction phi.
- exists 0...
- destruct (@vec_unused _ t) as [k H]. 1: eauto using find_unused_term. exists k. eauto using unused.
- destruct IHphi1, IHphi2. exists (x + x0). intros m Hm. constructor; [ apply u | apply u0 ]; lia.
- destruct IHphi1, IHphi2. exists (x + x0). intros m Hm. constructor; [ apply u | apply u0 ]; lia.
- destruct IHphi1, IHphi2. exists (x + x0). intros m Hm. constructor; [ apply u | apply u0 ]; lia.
- destruct IHphi. exists x. intros m Hm. constructor. apply u. lia.
- destruct IHphi. exists x. intros m Hm. constructor. apply u. lia.
Qed.
Definition capture n phi := nat_rect _ phi (fun _ => All) n.
Definition close phi := capture (proj1_sig (find_unused phi)) phi.
Fixpoint big_imp A phi :=
match A with
| List.nil => phi
| a :: A' => a --> (big_imp A' phi)
end.
(* **** Substituting unused variables *)
Definition shift_P P n :=
match n with
| O => False
| S n' => P n'
end.

Lemma subst_unused_term xi sigma P t :
(forall x, dec (P x)) -> (forall m, ~ P m -> xi m = sigma m) -> (forall m, P m -> unused_term m t) ->
subst_term xi t = subst_term sigma t.