Require Import List Arith Lia Eqdep_dec Bool.
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 decidable fol_ops membership hfs.
Set Default Proof Using "Type".
Set Implicit Arguments.
Section bt_model_n.
Variable (X : Type) (Xfin : finite_t X) (Xdiscr : discrete X) (x0 : X) (nt : nat).
Notation "∅" := hfs_empty.
Infix "∈" := hfs_mem.
Notation "x ⊆ y" := (forall u, u ∈ x -> u ∈ y).
Notation "⟬ x , y ⟭" := (hfs_opair x y).
Section the_model.
Local Definition X_surj_hfs : { d : hfs &
{ f : hfs -> X &
{ g : X -> hfs |
hfs_transitive d
/\ ∅ ∈ d
/\ (forall p, g p ∈ d)
/\ (forall x, x ∈ d -> exists p, x = g p)
/\ (forall p, f (g p) = p)
}}}.
Proof using x0 Xfin Xdiscr.
destruct (finite_t_discrete_bij_t_pos Xfin)
as ([ | n ] & Hn); auto.
1: { exfalso; destruct Hn as (f & g & H1 & H2).
generalize (f x0); intro p; invert pos p. }
destruct Hn as (f & g & H1 & H2).
destruct (hfs_pos_n_transitive n)
as (l & g' & f' & G1 & G0 & G2 & G3 & G4).
exists l, (fun x => g (g' x)), (fun x => f' (f x)); msplit 4; auto.
+ intros x Hx.
destruct (G3 x Hx) as (p & Hp).
exists (g p); rewrite H2; auto.
+ intros p; rewrite G4; auto.
Qed.
Local Definition d := projT1 X_surj_hfs.
Local Definition s := projT1 (projT2 X_surj_hfs).
Local Definition i := proj1_sig (projT2 (projT2 (X_surj_hfs))).
Let Hd : hfs_transitive d. Proof. apply (proj2_sig (projT2 (projT2 (X_surj_hfs)))). Qed.
Let Hempty : ∅ ∈ d. Proof. apply (proj2_sig (projT2 (projT2 (X_surj_hfs)))). Qed.
Local Fact Hs : forall x, s (i x) = x.
Proof. apply (proj2_sig (projT2 (projT2 (X_surj_hfs)))). Qed.
Local Fact Hi : forall x, i x ∈ d.
Proof. apply (proj2_sig (projT2 (projT2 (X_surj_hfs)))). Qed.
Local Fact Hi' : forall s, s ∈ d -> exists x, s = i x.
Proof. apply (proj2_sig (projT2 (projT2 (X_surj_hfs)))). Qed.
Local Definition p := iter hfs_pow d (1+(2*nt)).
Local Fact Hp1 : hfs_transitive p.
Proof. apply hfs_iter_pow_trans; auto. Qed.
Local Fact Hp2 : d ∈ p.
Proof.
apply hfs_iter_pow_le with (n := 1); simpl; auto; try lia.
apply hfs_pow_spec; auto.
Qed.
Local Fact Hp5 n v : (forall p, vec_pos v p ∈ d) -> @hfs_tuple n v ∈ iter hfs_pow d (2*n).
Proof. apply hfs_tuple_pow; auto. Qed.
Local Fact Hp6 n v : n <= nt -> (forall p, vec_pos v p ∈ d) -> @hfs_tuple n v ∈ p.
Proof.
intros L H; apply Hp5 in H.
revert H; apply hfs_iter_pow_le; try lia; auto.
Qed.
End the_model.
Variable (R : vec X nt -> Prop).
Hypothesis HR : forall v, { R v } + { ~ R v }.
Hint Resolve finite_t_prod hfs_mem_fin_t : core.
Hint Resolve Hp1 Hp2 Hp5 Hp6 Hs Hi Hi' : core.
Section the_relation.
Let encode_R : { r | r ∈ p
/\ (forall v, @hfs_tuple nt v ∈ r -> forall q, vec_pos v q ∈ d)
/\ forall v, R v <-> hfs_tuple (vec_map i v) ∈ r }.
Proof.
set (P v := R (vec_map s v) /\ forall q, vec_pos v q ∈ d).
set (f := @hfs_tuple nt).
destruct hfs_comprehension with (P := P) (f := f) as (r & Hr).
+ apply fin_t_dec.
* intros; apply HR.
* apply fin_t_vec with (P := fun t => t ∈ d).
apply hfs_mem_fin_t.
+ exists r; msplit 2.
* unfold p; rewrite plus_comm, iter_plus with (b := 1).
apply hfs_pow_spec; intros x; rewrite Hr.
intros (v & H1 & <-).
apply Hp5, H1.
* unfold f; intros v.
rewrite Hr.
intros (w & H1 & H2).
apply hfs_tuple_spec in H2; subst w.
apply H1.
* intros v.
rewrite Hr.
split.
- exists (vec_map i v); split; auto.
split; auto.
++ rewrite vec_map_map.
revert H; apply fol_equiv_ext.
f_equal; apply vec_pos_ext; intro; rew vec.
++ intro; rew vec.
- intros (w & (H1 & _) & H2).
apply hfs_tuple_spec in H2.
revert H1; subst w; apply fol_equiv_ext.
f_equal; apply vec_pos_ext; intro; rew vec.
Qed.
Local Definition r := proj1_sig encode_R.
Local Fact Hr1 : r ∈ p.
Proof. apply (proj2_sig encode_R). Qed.
Local Fact Hr2 v : @hfs_tuple nt v ∈ r -> forall q, vec_pos v q ∈ d.
Proof. apply (proj2_sig encode_R). Qed.
Local Fact Hr3 v : R v <-> hfs_tuple (vec_map i v) ∈ r.
Proof. apply (proj2_sig encode_R). Qed.
End the_relation.
Hint Resolve Hr1 Hr2 Hr3 : core.
Local Definition p_bool x := if hfs_mem_dec x p then true else false.
Local Fact p_bool_spec x : x ∈ p <-> p_bool x = true.
Proof.
unfold p_bool.
destruct (hfs_mem_dec x p); split; try tauto; discriminate.
Qed.
Local Fact p_bool_spec1 x : x ∈ p -> p_bool x = true.
Proof. apply p_bool_spec. Qed.
Local Fact p_bool_spec2 x : p_bool x = true -> x ∈ p.
Proof. apply p_bool_spec. Qed.
Local Definition Y := sig (fun x => p_bool x = true).
Notation π1 := (@proj1_sig _ (fun x => p_bool x = true)).
Hint Resolve p_bool_spec p_bool_spec1 p_bool_spec2 : core.
Local Fact eqY : forall x y : Y, π1 x = π1 y -> x = y.
Proof.
intros (x & Hx) (y & Hy); simpl.
intros; subst; f_equal; apply UIP_dec, bool_dec.
Qed.
Local Fact HY : finite_t Y.
Proof.
apply fin_t_finite_t.
+ intros; apply UIP_dec, bool_dec.
+ generalize (hfs_mem_fin_t p); apply fin_t_equiv.
intros x; auto.
Qed.
Local Fact discrY : discrete Y.
Proof.
intros (x & Hx) (y & Hy).
destruct (hfs_eq_dec x y) as [ -> | D ].
+ left; f_equal; apply UIP_dec, bool_dec.
+ right; contradict D; inversion D; auto.
Qed.
Local Definition mem (x y : Y) := π1 x ∈ π1 y.
Local Fact mem_dec : forall x y, { mem x y } + { ~ mem x y }.
Proof.
intros (a & ?) (b & ?); unfold mem; simpl; apply hfs_mem_dec.
Qed.
Local Definition yd : Y := exist _ _ (p_bool_spec1 Hp2).
Local Definition yr : Y := exist _ _ (p_bool_spec1 Hr1).
Local Fact fa_mem_Y (P : _ -> Prop) :
(forall a, a ∈ p -> P a)
<-> (forall a, P (π1 a)).
Proof.
split.
+ intros H (a & Ha); simpl; auto.
+ intros H a Ha.
apply (H (exist _ _ (p_bool_spec1 Ha))).
Qed.
Local Fact ex_mem_Y (P : _ -> Prop) :
(exists a, a ∈ p /\ P a)
<-> (exists a, P (π1 a)).
Proof.
split.
+ intros (a & H & Ha).
exists (exist _ a (p_bool_spec1 H)); auto.
+ intros ((a & Ha) & H); simpl in *; eauto.
Qed.
Local Fact mem_fa_Y (P : _ -> Prop) k : k ∈ p -> (forall a, P a -> a ∈ p)
-> (forall a, a ∈ k <-> P a)
<-> (forall a, π1 a ∈ k <-> P (π1 a)).
Proof.
intros H1 H2.
rewrite <- fa_mem_Y with (P := fun a => a ∈ k <-> P a).
split.
+ intros H ? _; auto.
+ intros H a; split.
* intros Ha; apply H; auto.
apply (Hp1 Ha); auto.
* intros Ha; apply H; auto.
Qed.
Local Fact mem_equiv_Y u v :
u ∈ p
-> v ∈ p
-> (forall y : Y, π1 y ∈ u <-> π1 y ∈ v)
<-> (forall x : hfs, x ∈ u <-> x ∈ v).
Proof.
intros Hu Hv.
symmetry; apply mem_fa_Y; auto.
intros s Hs; apply (Hp1 Hs); auto.
Qed.
Local Fact is_equiv : forall x y, mb_equiv mem x y <-> π1 x = π1 y.
Proof.
intros (x & Hx) (y & Hy); simpl.
unfold mb_equiv, mem; simpl; split.
2: { intros []; tauto. }
rewrite mem_equiv_Y; auto; apply hfs_mem_ext.
Qed.
Local Fact mem_ext_Y x y : x ∈ p -> y ∈ p -> (forall a, π1 a ∈ x <-> π1 a ∈ y) <-> x = y.
Proof.
intros H1 H2; split.
+ intros H; apply hfs_mem_ext.
rewrite mem_fa_Y; auto.
intros z Hz; apply (Hp1 Hz); auto.
+ intros ->; tauto.
Qed.
Hint Resolve mem_ext_Y : core.
Local Fact is_pair : forall x y k, mb_is_pair mem k x y
<-> π1 k = hfs_pair (π1 x) (π1 y).
Proof.
intros (x & Hx) (y & Hy) (k & Hk); simpl.
unfold mb_is_pair; simpl.
unfold mb_equiv, mem; simpl.
rewrite hfs_pair_spec'.
rewrite mem_fa_Y; auto.
2: intros ? [ -> | -> ]; auto.
fol equiv; intros (a & Ha); simpl.
fol equiv; try tauto.
fol equiv; auto.
Qed.
Local Fact is_opair : forall x y k, mb_is_opair mem k x y
<-> π1 k = ⟬π1 x,π1 y⟭.
Proof.
intros (x & Hx) (y & Hy) (k & Hk); simpl.
unfold mb_is_opair; simpl.
split.
+ intros ((a & Ha) & (b & Hb) & H); revert H.
repeat rewrite is_pair; simpl.
intros (-> & -> & ->); auto.
+ intros ->.
generalize Hx Hy Hk; revert Hx Hy Hk.
do 3 rewrite <- p_bool_spec at 1.
intros Hx' Hy' Hk' Hx Hy Hk.
apply hfs_trans_opair_inv in Hk'; auto.
do 2 rewrite p_bool_spec in Hk'.
destruct Hk' as (H1 & H2).
exists (exist _ (hfs_pair x x) H1).
exists (exist _ (hfs_pair x y) H2).
repeat rewrite is_pair; simpl; auto.
Qed.
Local Fact is_tuple n : forall v t, @mb_is_tuple _ mem t n v
<-> π1 t = hfs_tuple (vec_map π1 v).
Proof.
induction n as [ | n IHn ]; intros v (t & Ht).
+ vec nil v; clear v; simpl; split.
* intros H; apply hfs_mem_ext.
intros z; split.
- intros Hz.
assert (Hz' : p_bool z = true).
{ apply p_bool_spec.
apply Hp1 with (1 := Hz), p_bool_spec; auto. }
destruct (H (exist _ z Hz')); auto.
- rewrite hfs_empty_spec; tauto.
* intros -> (z & ?); unfold mem; simpl.
rewrite hfs_empty_spec; tauto.
+ vec split v with x; simpl; split.
* intros (t' & H1 & H2).
rewrite IHn in H2; try lia.
rewrite <- H2.
apply is_opair with (k := exist _ t Ht); auto.
* intros ->.
assert (H1 : p_bool (hfs_tuple (vec_map π1 v)) = true).
{ apply p_bool_spec.
apply p_bool_spec in Ht.
apply hfs_trans_opair_inv, proj2, hfs_trans_pair_inv in Ht; auto; tauto. }
exists (exist _ (hfs_tuple (vec_map π1 v)) H1); split.
- rewrite is_opair; simpl; auto.
- rewrite IHn; simpl; auto.
Qed.
Local Fact has_tuples : mb_has_tuples mem yd nt.
Proof.
intros v Hv.
set (t := hfs_tuple (vec_map (proj1_sig (P:=fun x : hfs => p_bool x = true)) v)).
assert (H1 : p_bool t = true).
{ apply p_bool_spec, Hp6; auto; intro; rew vec; apply Hv. }
exists (exist _ t H1).
apply is_tuple; simpl; reflexivity.
Qed.
Local Definition i' x : Y := exist _ _ (p_bool_spec1 (Hp1 (Hi x) Hp2)).
Local Fact Hi'' x : mem (i' x) yd.
Proof. unfold i', yd, mem; simpl; auto. Qed.
Hint Resolve Hi'' : core.
Local Definition s' (y : Y) : X := s (π1 y).
Theorem reln_hfs : { Y : Type &
{ _ : finite_t Y &
{ mem : Y -> Y -> Prop &
{ _ : forall u v, { mem u v } + { ~ mem u v } &
{ yd : Y &
{ yr : Y &
{ i : X -> Y &
{ s : Y -> X &
(forall x, mem (i x) yd)
/\ (forall y, mem y yd -> exists x, y = i x)
/\ (forall v, R v <-> mb_is_tuple_in mem yr (vec_map i v))
}}}}}}}}.
Proof using x0 Xfin Xdiscr HR.
exists Y, HY, mem, mem_dec, yd, yr, i', s'.
msplit 2; auto.
+ intros y Hy; unfold i'.
destruct (Hi' Hy) as (x & Hx).
exists x; apply eqY; simpl; auto.
+ intros v; rewrite Hr3; split.
* intros Hv.
red.
assert (H1 : p_bool (hfs_tuple (vec_map i v)) = true).
{ apply p_bool_spec, Hp1 with (1 := Hv); auto. }
exists (exist _ (hfs_tuple (vec_map i v)) H1); split.
- apply is_tuple; simpl; rewrite vec_map_map; auto.
- unfold yr; red; simpl; auto.
* intros ((t & Ht) & H1 & H2).
rewrite is_tuple in H1.
simpl in H1, H2.
rewrite vec_map_map in H1; subst t; auto.
Qed.
End bt_model_n.