Require Import List Arith Nat Lia Max Wellfounded Coq.Setoids.Setoid.
From Undecidability.Shared.Libs.DLW.Utils
Require Import utils_tac utils_list finite.
From Undecidability.Shared.Libs.DLW.Vec
Require Import pos vec.
From Undecidability.TRAKHTENBROT
Require Import notations fol_ops fo_sig fo_terms fo_logic.
Import fol_notations.
Set Default Proof Using "Type".
Set Implicit Arguments.
Local Notation ø := vec_nil.
Local Infix "∊" := In (at level 70, no associativity).
Local Infix "⊑" := incl (at level 70, no associativity).
Section membership.
Variable (X : Type) (mem : X -> X -> Prop).
Infix "∈" := mem.
Notation "x ∉ y" := (~ x ∈ y).
Definition mb_incl x y := forall a, a ∈ x -> a ∈ y.
Definition mb_equiv x y := forall a, a ∈ x <-> a ∈ y.
Infix "⊆" := mb_incl.
Infix "≈" := mb_equiv.
Notation "x ≉ y" := (~ x ≈ y).
Definition mb_transitive t := forall x y, x ∈ y -> y ∈ t -> x ∈ t.
Fact mb_incl_refl x : x ⊆ x.
Proof. red; auto. Qed.
Fact mb_incl_trans x y z : x ⊆ y -> y ⊆ z -> x ⊆ z.
Proof. unfold mb_incl; auto. Qed.
Fact mb_equiv_eq x y : x ≈ y <-> x ⊆ y /\ y ⊆ x.
Proof. firstorder. Qed.
Fact mb_equiv_refl_True x : x ≈ x <-> True. Proof. unfold mb_equiv; tauto. Qed.
Fact mb_equiv_refl x : x ≈ x. Proof. unfold mb_equiv; tauto. Qed.
Fact mb_equiv_sym x y : x ≈ y -> y ≈ x.
Proof. do 2 rewrite mb_equiv_eq; tauto. Qed.
Fact mb_equiv_trans x y z : x ≈ y -> y ≈ z -> x ≈ z.
Proof. repeat rewrite mb_equiv_eq; unfold mb_incl; intros [] []; split; auto. Qed.
Add Parametric Relation: (X) (mb_equiv)
reflexivity proved by mb_equiv_refl
symmetry proved by mb_equiv_sym
transitivity proved by mb_equiv_trans
as mb_equiv_equivalence.
Hint Resolve mb_equiv_refl mb_equiv_sym : core.
Definition mb_member_ext := forall x y z, x ≈ y -> x ∈ z -> y ∈ z.
Variable (mb_axiom_ext : mb_member_ext).
Fact mb_equiv_mem x y : x ≈ y -> forall z, x ∈ z <-> y ∈ z.
Proof using mb_axiom_ext. split; apply mb_axiom_ext; auto. Qed.
Add Parametric Morphism: (mem) with signature
(mb_equiv) ==> (mb_equiv) ==> (iff) as mb_mem_congruence.
Proof using mb_axiom_ext.
intros x y H1 a b H2; red in H1, H2; split;
rewrite <- H2; apply mb_axiom_ext; auto.
Qed.
Add Parametric Morphism: (fun x y => x ⊆ y) with signature
(mb_equiv) ==> (mb_equiv) ==> (iff) as mb_incl_congruence.
Proof using mb_axiom_ext.
intros x y H1 a b H2; split; intros H z.
+ rewrite <- H1, <- H2; auto.
+ rewrite H1, H2; auto.
Qed.
Reserved Notation "p ≋ ⦃ a , b ⦄" (at level 70, format "p ≋ ⦃ a , b ⦄").
Reserved Notation "p ≋ ⦅ a , b ⦆" (at level 70, format "p ≋ ⦅ a , b ⦆").
Reserved Notation "t ≋ ⦉ v ⦊" (at level 70, format "t ≋ ⦉ v ⦊").
Definition mb_is_pair p x y := forall a, a ∈ p <-> a ≈ x \/ a ≈ y.
Notation "p ≋ ⦃ a , b ⦄" := (mb_is_pair p a b).
Fact mb_is_pair_comm p x y : p ≋ ⦃x,y⦄ -> p ≋ ⦃y,x⦄.
Proof. unfold mb_is_pair; fol equiv fa; intro; tauto. Qed.
Add Parametric Morphism: (mb_is_pair) with signature
(mb_equiv) ==> (mb_equiv) ==> (mb_equiv) ==> (iff) as mb_is_pair_congruence.
Proof using mb_axiom_ext.
intros p q H1 x x' H2 y y' H3.
fol equiv fa; intro.
rewrite H1, H2, H3; tauto.
Qed.
Fact mb_is_pair_fun p q x y : p ≋ ⦃x,y⦄ -> q ≋ ⦃x,y⦄ -> p ≈ q.
Proof. intros H1 H2; red in H1, H2; intro; rewrite H1, H2; tauto. Qed.
Fact mb_is_pair_inj p x y x' y' :
p ≋ ⦃x,y⦄
-> p ≋ ⦃x',y'⦄
-> x ≈ x' /\ y ≈ y'
\/ x ≈ y' /\ y ≈ x'.
Proof.
unfold mb_is_pair; intros H1 H2.
generalize (proj1 (H2 x)) (proj1 (H2 y)); rewrite H1, H1, mb_equiv_refl_True, mb_equiv_refl_True.
generalize (proj1 (H1 x')) (proj1 (H1 y')); rewrite H2, H2, mb_equiv_refl_True, mb_equiv_refl_True.
intros [] [] [] []; auto.
Qed.
Fact mb_is_pair_inj' p x y : p ≋ ⦃x,x⦄ -> p ≋ ⦃y,y⦄ -> x ≈ y.
Proof. intros H1 H2; generalize (mb_is_pair_inj H1 H2); tauto. Qed.
Definition mb_is_opair p x y := exists a b, a ≋ ⦃x,x⦄ /\ b ≋ ⦃x,y⦄ /\ p ≋ ⦃a,b⦄.
Notation "p ≋ ⦅ a , b ⦆" := (mb_is_opair p a b).
Add Parametric Morphism: (mb_is_opair) with signature
(mb_equiv) ==> (mb_equiv) ==> (mb_equiv) ==> (iff) as mb_is_opair_congruence.
Proof using mb_axiom_ext.
intros p q H1 x x' H2 y y' H3.
do 2 (fol equiv ex; intro).
rewrite H1, H2, H3; tauto.
Qed.
Fact mb_is_opair_fun p q x y : p ≋ ⦅x,y⦆ -> q ≋ ⦅x,y⦆ -> p ≈ q.
Proof using mb_axiom_ext.
intros (a & b & H1 & H2 & H3) (u & v & G1 & G2 & G3).
generalize (mb_is_pair_fun H1 G1) (mb_is_pair_fun H2 G2); intros E1 E2.
rewrite E1, E2 in H3.
revert H3 G3; apply mb_is_pair_fun.
Qed.
Fact mb_is_opair_inj p x y x' y' : p ≋ ⦅x,y⦆ -> p ≋ ⦅x',y'⦆ -> x ≈ x' /\ y ≈ y'.
Proof using mb_axiom_ext.
intros (a & b & H1 & H2 & H3) (u & v & G1 & G2 & G3).
generalize (mb_is_pair_inj H3 G3); intros [ (E1 & E2) | (E1 & E2) ].
+ rewrite E1 in H1; rewrite E2 in H2.
generalize (mb_is_pair_inj' H1 G1); intros E; split; auto.
rewrite E in H2.
generalize (mb_is_pair_inj H2 G2); intros [ | (E3 & E4) ]; try tauto.
rewrite E4; auto.
+ rewrite E1 in H1; rewrite E2 in H2.
generalize (mb_is_pair_inj H2 G1) (mb_is_pair_inj H1 G2).
intros [ (E3 & E4) | (E3 & E4) ] [ (E5 & E6) | (E5 & E6) ];
rewrite E4, <- E5; auto.
Qed.
Fixpoint mb_is_tuple t n (v : vec X n) :=
match v with
| vec_nil => forall z, z ∉ t
| x##v => exists t', t ≋ ⦅x,t'⦆ /\ t' ≋ ⦉v⦊
end
where "t ≋ ⦉ v ⦊" := (mb_is_tuple t v).
Fact mb_is_tuple_congr p q n (v : vec X n) : p ≈ q -> p ≋ ⦉v⦊ -> q ≋ ⦉v⦊ .
Proof using mb_axiom_ext.
revert p q; induction v as [ | n x v IHv ]; intros p q.
+ simpl; intros E H x; rewrite <- E; auto.
+ intros E (t & H1 & H2); exists t; split; auto.
rewrite <- E; auto.
Qed.
Fact mb_is_tuple_fun p q n (v : vec _ n) : p ≋ ⦉v⦊ -> q ≋ ⦉v⦊ -> p ≈ q.
Proof using mb_axiom_ext.
revert p q; induction v as [ | n x v IHv ]; intros p q.
+ simpl; intros H1 H2.
apply mb_equiv_eq; split.
* intros z Hz; apply H1 in Hz; tauto.
* intros z Hz; apply H2 in Hz; tauto.
+ intros (p' & H1 & H2) (q' & H3 & H4).
generalize (IHv _ _ H2 H4); intros E.
rewrite E in H1.
revert H1 H3; apply mb_is_opair_fun.
Qed.
Fact mb_is_tuple_inj t n (v w : vec _ n) p :
t ≋ ⦉v⦊ -> t ≋ ⦉w⦊ -> vec_pos v p ≈ vec_pos w p.
Proof using mb_axiom_ext.
intros H1 H2; revert t w H1 H2 p; induction v as [ | n x v IHv ]; intros t w.
+ intros _ _ p; invert pos p.
+ vec split w with y.
intros (p & H1 & H2) (q & H3 & H4).
destruct (mb_is_opair_inj H1 H3) as (E1 & E2).
apply mb_is_tuple_congr with (1 := E2) in H2.
specialize (IHv _ _ H2 H4).
intros j; invert pos j; auto.
Qed.
Definition mb_has_pairs (l : X) :=
forall x y, x ∈ l -> y ∈ l -> exists p, p ≋ ⦃x,y⦄ .
Definition mb_has_tuples (l : X) n :=
forall v : vec _ n, (forall p, vec_pos v p ∈ l) -> exists t, t ≋ ⦉v⦊.
Definition mb_is_tuple_in r n (v : vec _ n) :=
exists t, t ≋ ⦉v⦊ /\ t ∈ r.
Notation "t ∋ ⦉ v ⦊" := (mb_is_tuple_in t v) (at level 70, format "t ∋ ⦉ v ⦊").
Fact mb_is_tuple_in_congr x y n (v : vec _ n) : y ≈ x -> x ∋ ⦉v⦊ -> y ∋ ⦉v⦊ .
Proof using mb_axiom_ext.
intros E (t & H1 & H2); exists t; split; auto.
rewrite E; auto.
Qed.
Definition mb_is_tot n (l s : X) :=
forall v, (forall p : pos n, vec_pos v p ∈ l)
-> exists x p t, x ∈ l /\ p ∈ s /\ p ≋ ⦅x,t⦆ /\ t ≋ ⦉v⦊.
Definition mb_is_fun (l s : X) :=
forall p q x x' y, x ∈ l -> x' ∈ l
-> p ∈ s -> q ∈ s
-> p ≋ ⦅x,y⦆
-> q ≋ ⦅x',y⦆
-> x ≈ x'.
Variable (Rdec : forall x y, { x ∈ y } + { x ∉ y })
(Xfin : finite_t X).
Local Definition lX : list X := proj1_sig Xfin.
Local Definition HX : forall x, In x lX := proj2_sig Xfin.
Hint Resolve HX : core.
Fact mb_incl_choose x y : { z | z ∈ x /\ z ∉ y } + { x ⊆ y }.
Proof using Xfin Rdec.
set (P z := z ∈ x /\ z ∉ y).
set (Q z := z ∈ x -> z ∈ y).
destruct list_dec with (P := P) (Q := Q) (l := lX)
as [ (z & _ & H2 & H3) | H ]; unfold P, Q in *; clear P Q.
+ intros z; destruct (Rdec z x); destruct (Rdec z y); tauto.
+ left; exists z; auto.
+ right; intros z; apply H; auto.
Qed.
Fact mb_incl_dec x y : { x ⊆ y } + { ~ x ⊆ y }.
Proof using Xfin Rdec.
destruct (mb_incl_choose x y) as [ (?&?&?) |]; auto.
Qed.
Fact mb_equiv_dec x y : { x ≈ y } + { x ≉ y }.
Proof using Xfin Rdec.
destruct (mb_incl_dec x y); [ destruct (mb_incl_dec y x) | ].
1: left; apply mb_equiv_eq; auto.
all: right; rewrite mb_equiv_eq; tauto.
Qed.
Hint Resolve mb_equiv_dec : core.
Fact mb_is_pair_dec p x y : { p ≋ ⦃x,y⦄ } + { ~ p ≋ ⦃x,y⦄ }.
Proof using Xfin Rdec.
unfold mb_is_pair.
apply (fol_quant_sem_dec fol_fa); auto; intros u.
apply fol_equiv_dec; auto.
apply (fol_bin_sem_dec fol_disj); auto.
Qed.
Hint Resolve mb_is_pair_dec : core.
Fact mb_is_opair_dec p x y : { p ≋ ⦅x,y⦆ } + { ~ p ≋ ⦅x,y⦆ }.
Proof using Xfin Rdec.
unfold mb_is_opair.
do 2 (apply (fol_quant_sem_dec fol_ex); auto; intro).
repeat (apply (fol_bin_sem_dec fol_conj); auto).
Qed.
Hint Resolve mb_is_opair_dec : core.
Fact mb_is_tuple_dec t n (v : vec _ n) : { t ≋ ⦉v⦊ } + { ~ t ≋ ⦉v⦊ }.
Proof using Xfin Rdec.
revert t; induction v as [ | x n v IHv ]; intros t.
+ apply (fol_quant_sem_dec fol_fa); auto; intro.
apply (fol_bin_sem_dec fol_imp); auto.
+ simpl; apply (fol_quant_sem_dec fol_ex); auto; intro.
apply (fol_bin_sem_dec fol_conj); auto.
Qed.
Hint Resolve mb_is_tuple_dec : core.
Fact mb_is_tuple_in_dec r n (v : vec _ n) : { r ∋ ⦉v⦊ } + { ~ r ∋ ⦉v⦊ }.
Proof using Xfin Rdec.
apply (fol_quant_sem_dec fol_ex); auto; intro.
apply (fol_bin_sem_dec fol_conj); auto.
Qed.
End membership.
Section FOL_encoding.
Notation Σ2 := (Σrel 2).
Variable (Y : Type) (M2 : fo_model Σ2 Y).
Let mem a b := fom_rels M2 tt (a##b##ø).
Infix "∈ₘ" := mem (at level 59, no associativity).
Definition Σ2_mem x y := @fol_atom Σ2 tt (£x##£y##ø).
Infix "∈" := Σ2_mem.
Definition Σ2_non_empty l := ∃ 0 ∈ (1+l).
Definition Σ2_incl x y := ∀ 0 ∈ (S x) ⤑ 0 ∈ (S y).
Definition Σ2_equiv x y := ∀ 0 ∈ (S x) ↔ 0 ∈ (S y).
Infix "⊆" := Σ2_incl.
Infix "≈" := Σ2_equiv.
Definition Σ2_transitive t := ∀∀ 1 ∈ 0 ⤑ 0 ∈ (2+t) ⤑ 1 ∈ (2+t).
Definition Σ2_extensional := ∀∀∀ 2 ≈ 1 ⤑ 2 ∈ 0 ⤑ 1 ∈ 0.
Definition Σ2_is_pair p x y := ∀ 0 ∈ (S p) ↔ 0 ≈ S x ⟇ 0 ≈ S y.
Definition Σ2_is_opair p x y :=
∃∃ Σ2_is_pair 1 (2+x) (2+x)
⟑ Σ2_is_pair 0 (2+x) (2+y)
⟑ Σ2_is_pair (2+p) 1 0.
Fact Σ2_is_opair_vars p x y : fol_vars (Σ2_is_opair p x y) ⊑ p::x::y::nil.
Proof. cbv; tauto. Qed.
Fixpoint Σ2_is_tuple t n : vec nat n -> fol_form Σ2 :=
match n with
| 0 => fun _ => ∀ 0 ∈ (S t) ⤑ ⊥
| S n => fun v => ∃ Σ2_is_opair (S t) (S (vec_head v)) 0
⟑ Σ2_is_tuple 0 (vec_map S (vec_tail v))
end.
Fact Σ2_is_tuple_vars t n v : fol_vars (@Σ2_is_tuple t n v) ⊑ t::vec_list v.
Proof.
revert t v; induction n as [ | n IHn ]; intros t v.
+ vec nil v; cbv; tauto.
+ vec split v with x; simpl Σ2_is_tuple.
intros i; rewrite fol_vars_quant, in_flat_map.
intros (j & H1 & H2).
rewrite fol_vars_bin, in_app_iff in H1.
destruct H1 as [ H1 | H1 ].
* apply Σ2_is_opair_vars in H1.
destruct H1 as [ | [ | [ | [] ] ] ]; subst j; simpl in *; tauto.
* apply IHn in H1.
destruct H1 as [ <- | H1 ].
- simpl in *; tauto.
- rewrite vec_list_vec_map, in_map_iff in H1.
destruct H1 as (y & <- & H1); simpl in *.
destruct H2 as [ -> | [] ]; tauto.
Qed.
Definition Σ2_is_tuple_in r n v := ∃ @Σ2_is_tuple 0 n (vec_map S v) ⟑ 0 ∈ (S r).
Fact Σ2_is_tuple_in_vars r n v : fol_vars (@Σ2_is_tuple_in r n v) ⊑ r::vec_list v.
Proof.
unfold Σ2_is_tuple_in.
intros x; rewrite fol_vars_quant, in_flat_map.
intros (y & H1 & H2).
rewrite fol_vars_bin, in_app_iff in H1.
destruct H1 as [ H1 | H1 ].
+ apply Σ2_is_tuple_vars in H1.
simpl in H1; rewrite vec_list_vec_map, in_map_iff in H1.
destruct H1 as [ <- | (z & <- & H1) ]; simpl in *; try tauto.
destruct H2 as [ <- | [] ]; auto.
+ simpl in H1.
destruct H1 as [ <- | [ <- | [] ] ]; simpl in *; tauto.
Qed.
Definition Σ2_has_tuples l n :=
fol_mquant fol_fa n ( (fol_vec_fa (vec_set_pos (fun p : pos n => pos2nat p ∈ (l+n))))
⤑ ∃ Σ2_is_tuple 0 (vec_set_pos (fun p : pos n => S (pos2nat p)))).
Definition Σ2_is_tot n l s :=
fol_mquant fol_fa n ( (fol_vec_fa (vec_set_pos (fun p : pos n => pos2nat p ∈ (l+n))))
⤑ ∃∃∃ 2 ∈ ((3+l)+n) ⟑ 1 ∈ ((3+s)+n) ⟑ Σ2_is_opair 1 2 0 ⟑ @Σ2_is_tuple 0 n (vec_set_pos (fun p : pos n => 3+pos2nat p)) ).
Definition Σ2_is_fun l s :=
∀∀∀∀∀ 2 ∈ (5+l) ⤑ 1 ∈ (5+l) ⤑
4 ∈ (5+s) ⤑ 3 ∈ (5+s) ⤑
Σ2_is_opair 4 2 0 ⤑
Σ2_is_opair 3 1 0 ⤑
2 ≈ 1.
Definition Σ2_list_in l lv := fol_lconj (map (fun x => x ∈ l) lv).
Notation "⟪ A ⟫" := (fun ψ => fol_sem M2 ψ A).
Section semantics.
Fact Σ2_transitive_spec t ψ : ⟪Σ2_transitive t⟫ ψ = mb_transitive mem (ψ t).
Proof. reflexivity. Qed.
Fact Σ2_non_empty_spec l ψ : ⟪Σ2_non_empty l⟫ ψ = exists x, x ∈ₘ ψ l.
Proof. reflexivity. Qed.
Fact Σ2_incl_spec x y ψ : ⟪Σ2_incl x y⟫ ψ = mb_incl mem (ψ x) (ψ y).
Proof. reflexivity. Qed.
Fact Σ2_equiv_spec x y ψ : ⟪Σ2_equiv x y⟫ ψ = mb_equiv mem (ψ x) (ψ y).
Proof. reflexivity. Qed.
Fact Σ2_extensional_spec ψ : ⟪Σ2_extensional⟫ ψ = mb_member_ext mem.
Proof. reflexivity. Qed.
Fact Σ2_is_pair_spec p x y ψ : ⟪Σ2_is_pair p x y⟫ ψ = mb_is_pair mem (ψ p) (ψ x) (ψ y).
Proof. reflexivity. Qed.
Fact Σ2_is_opair_spec p x y ψ : ⟪Σ2_is_opair p x y⟫ ψ = mb_is_opair mem (ψ p) (ψ x) (ψ y).
Proof. reflexivity. Qed.
Fact Σ2_is_tuple_spec t n v ψ : ⟪@Σ2_is_tuple t n v⟫ ψ <-> mb_is_tuple mem (ψ t) (vec_map ψ v).
Proof.
induction n as [ | n IHn ] in t, v, ψ |- *.
+ vec nil v; reflexivity.
+ vec split v with x.
simpl Σ2_is_tuple.
simpl mb_is_tuple.
rewrite fol_sem_quant_fix.
fol equiv ex; intros y.
rewrite fol_sem_bin_fix.
fol equiv conj.
* reflexivity.
* rewrite IHn, vec_map_map; reflexivity.
Qed.
Fact Σ2_is_tuple_in_spec r n v ψ : ⟪@Σ2_is_tuple_in r n v⟫ ψ <-> mb_is_tuple_in mem (ψ r) (vec_map ψ v).
Proof.
simpl; fol equiv ex; intro; fol equiv conj.
+ rewrite Σ2_is_tuple_spec, vec_map_map; simpl; reflexivity.
+ reflexivity.
Qed.
Fact Σ2_has_tuples_spec l n ψ : ⟪Σ2_has_tuples l n⟫ ψ <-> mb_has_tuples mem (ψ l) n.
Proof.
unfold Σ2_has_tuples.
rewrite fol_sem_mforall.
fol equiv fa; intros v.
rewrite fol_sem_bin_fix.
fol equiv imp.
+ rewrite fol_sem_vec_fa.
fol equiv; intros p.
rew vec; simpl.
now rewrite env_vlift_fix0, env_vlift_fix1.
+ rewrite fol_sem_quant_fix.
fol equiv ex; intros x.
rewrite Σ2_is_tuple_spec; simpl.
fol equiv rel.
apply vec_pos_ext; intros p.
rew vec; simpl.
rewrite env_vlift_fix0; auto.
Qed.
Fact Σ2_is_fun_spec l s ψ : ⟪Σ2_is_fun l s⟫ ψ = mb_is_fun mem (ψ l) (ψ s).
Proof. reflexivity. Qed.
Fact Σ2_is_tot_spec n l s ψ : ⟪Σ2_is_tot n l s⟫ ψ <-> mb_is_tot mem n (ψ l) (ψ s).
Proof.
unfold Σ2_is_tot, mb_is_tot.
rewrite fol_sem_mforall.
fol equiv; intros v.
rewrite fol_sem_bin_fix.
fol equiv imp.
+ rewrite fol_sem_vec_fa.
fol equiv; intros p.
rew vec; simpl.
rewrite env_vlift_fix0, env_vlift_fix1; tauto.
+ rewrite fol_sem_quant_fix; fol equiv ex; intros x.
rewrite fol_sem_quant_fix; fol equiv ex; intros p.
rewrite fol_sem_quant_fix; fol equiv ex; intros t.
do 3 (rewrite fol_sem_bin_fix).
repeat fol equiv conj.
* simpl; rewrite env_vlift_fix1; tauto.
* simpl; rewrite env_vlift_fix1; tauto.
* rewrite Σ2_is_opair_spec; simpl; tauto.
* rewrite Σ2_is_tuple_spec; simpl.
fol equiv.
apply vec_pos_ext; intros q; rew vec.
simpl; rewrite env_vlift_fix0; auto.
Qed.
Fact Σ2_list_in_spec l lv ψ : ⟪Σ2_list_in l lv⟫ ψ <-> forall x, x ∊ lv -> ψ x ∈ₘ ψ l.
Proof.
unfold Σ2_list_in; rewrite fol_sem_lconj.
split.
+ intros H x Hx.
apply (H (_ ∈ _)), in_map_iff.
exists x; auto.
+ intros H f; rewrite in_map_iff.
intros (x & <- & ?); apply H; auto.
Qed.
End semantics.
End FOL_encoding.