Require Import List Arith Lia Max Wellfounded Setoid Eqdep_dec.
From Undecidability.Shared.Libs.DLW.Utils
Require Import utils_tac utils_list finite.
From Undecidability.Shared.Libs.DLW.Vec
Require Import pos.
From Undecidability.Shared.Libs.DLW.Wf
Require Import wf_finite wf_chains.
From Undecidability.TRAKHTENBROT
Require Import notations fol_ops.
Set Implicit Arguments.
Inductive bt : Set := bt_leaf | bt_node : bt -> bt -> bt.
Local Notation "∅" := bt_leaf. Local Infix "⪧" := bt_node.
Section bt_rect'.
Variables (P : bt -> Type)
(HP0 : P ∅)
(HP1 : forall x t, P t -> P (x⪧t)).
Theorem bt_rect' t : P t.
Proof. induction t; auto. Qed.
End bt_rect'.
Fact bt_eq_dec (s t : bt) : { s = t } + { s <> t }.
Proof. decide equality. Qed.
Fact bt_eq_pirr (s t : bt) (H1 H2 : s = t) : H1 = H2.
Proof. apply UIP_dec, bt_eq_dec. Qed.
Fixpoint bt_depth t :=
match t with
| ∅ => 0
| r⪧s => max (S ⌞r⌟) ⌞s⌟
end
where "⌞ t ⌟" := (bt_depth t).
Inductive bt_equiv : bt -> bt -> Prop :=
| in_bte_refl : forall s, s ≈ s
| in_bte_sym : forall s t, s ≈ t
-> t ≈ s
| in_bte_tran : forall r s t, r ≈ s
-> s ≈ t
-> r ≈ t
| in_bte_cntr : forall s t, s⪧s⪧t ≈ s⪧t
| in_bte_comm : forall s t u, s⪧t⪧u ≈ t⪧s⪧u
| in_bte_cngr : forall s s' t t', s ≈ s'
-> t ≈ t'
-> s⪧t ≈ s'⪧t'
where "s ≈ t" := (bt_equiv s t).
Hint Constructors bt_equiv : core.
Local Notation "s ≉ t" := (~ s ≈ t).
Notation bte_refl := in_bte_refl.
Notation bte_trans := in_bte_tran.
Fact bte_sym x y : x ≈ y <-> y ≈ x.
Proof. split; auto. Qed.
Add Parametric Relation: (bt) (bt_equiv)
reflexivity proved by bte_refl
symmetry proved by in_bte_sym
transitivity proved by bte_trans
as bte_rst.
Add Parametric Morphism: (bt_node) with signature
(bt_equiv) ==> (bt_equiv) ==> (bt_equiv) as bt_node_congr.
Proof. intros; auto. Qed.
Fact bte_leaf_eq s t : s ≈ t -> (s = ∅ <-> t = ∅).
Proof. induction 1; try tauto; split; discriminate. Qed.
Fact bte_discr s t : s⪧t ≉ ∅.
Proof.
intros H; apply bte_leaf_eq in H.
generalize (proj2 H eq_refl); discriminate.
Qed.
Fact bte_inv_0 s : s ≈ ∅ <-> s = ∅.
Proof.
split.
+ intros H; destruct s; auto.
apply bte_discr in H; tauto.
+ intros ->; auto.
Qed.
Definition bt_mem s t := s⪧t ≈ t.
Local Infix "∈" := bt_mem.
Local Notation "s ∉ t" := (~ s ∈ t).
Section establishing_membership_inversion.
Reserved Notation "x ⋷ y" (at level 70, no associativity).
Inductive bt_restr_mem : bt -> bt -> Prop :=
| in_btrm_0 : forall s t, s ⋷ s⪧t
| in_btrm_1 : forall s t u, s ⋷ u -> s ⋷ t⪧u
where "s ⋷ t" := (bt_restr_mem s t).
Hint Constructors bt_restr_mem : core.
Fact btrm_inv u s t : u ⋷ s⪧t <-> u = s \/ u ⋷ t.
Proof.
split.
+ inversion 1; auto.
+ intros [ <- | ]; constructor; auto.
Qed.
Notation "s ≾ t" := (forall u, u ⋷ s -> exists v, v ⋷ t /\ u ≈ v).
Fact bt_rincl_refl s : s ≾ s.
Proof. intros u; exists u; auto. Qed.
Fact bt_rincl_trans r s t : r ≾ s -> s ≾ t -> r ≾ t.
Proof.
intros H1 H2 u Hu.
destruct H1 with (1 := Hu) as (v & Hv & H3).
destruct H2 with (1 := Hv) as (w & ? & ?).
exists w; split; auto.
apply bte_trans with v; auto.
Qed.
Hint Resolve bt_rincl_refl bt_rincl_trans : core.
Lemma bte_rincl s t : s ≈ t -> s ≾ t.
Proof.
intros H.
assert (s ≾ t /\ t ≾ s) as K; [ | apply K ].
induction H as [ s | s t H IH | r s t H1 [] H2 []
| s t | s t u | s s' t t' H1 [H2 H3] H4 [H5 H6] ];
auto; try tauto.
+ split; apply bt_rincl_trans with s; auto.
+ split; intros u; rewrite btrm_inv; intros [ <- | ]; exists u; auto.
+ split; intros v; rewrite btrm_inv; intros [ <- | ]; exists v; auto;
revert H; rewrite btrm_inv; intros [ <- | ]; auto.
+ split.
* intros u; rewrite btrm_inv.
intros [ <- | ].
- exists s'; auto.
- destruct (H5 _ H) as (v & ? & ?); exists v; auto.
* intros u; rewrite btrm_inv.
intros [ <- | ].
- exists s; auto.
- destruct (H6 _ H) as (v & ? & ?); exists v; auto.
Qed.
Fact btrm_btm s t : s ⋷ t -> s ∈ t.
Proof.
induction 1 as [ | s t u ]; try (constructor; auto; fail).
constructor; apply bte_trans with (t⪧s⪧u); auto.
Qed.
Hint Resolve btrm_btm : core.
Fact btm_congr_l s t u : s ≈ t -> s ∈ u -> t ∈ u.
Proof. intros ? H; apply bte_trans with (2 := H); auto. Qed.
Fact btm_congr_r s t u : s ≈ t -> u ∈ s -> u ∈ t.
Proof.
intros H1 H2.
apply bte_trans with (2 := H1),
bte_trans with (2 := H2); auto.
Qed.
Fact btm_inv_0 s : s ∈ ∅ <-> False.
Proof. split; try tauto; apply bte_discr. Qed.
Fact btm_inv u s t : u ∈ s⪧t <-> u ≈ s \/ u ∈ t.
Proof.
split.
+ intros H.
destruct (@bte_rincl _ _ H u) as (v & H1 & ?); auto.
revert H1; rewrite btrm_inv; intros [ <- | ]; auto.
right; apply bte_trans with (v⪧t); auto.
apply btrm_btm; auto.
+ intros [ H | H ].
* apply btm_congr_l with s; auto.
* apply bte_trans with (1 := in_bte_comm _ _ _); auto.
Qed.
End establishing_membership_inversion.
Add Parametric Morphism: (bt_mem) with signature
(bt_equiv) ==> (bt_equiv) ==> (iff) as bte_congr.
Proof.
intros x y H1 a b H2; split; intros H.
+ apply btm_congr_l with (1 := H1),
btm_congr_r with (1 := H2); auto.
+ rewrite bte_sym in H1.
rewrite bte_sym in H2.
apply btm_congr_l with (1 := H1),
btm_congr_r with (1 := H2); auto.
Qed.
Tactic Notation "btm" "simpl" :=
repeat match goal with
| |- context[_ ∈ _ ⪧ _] => rewrite btm_inv; auto; try tauto
| |- context[_ ∈ ∅] => rewrite btm_inv_0; auto; try tauto
end.
Theorem btm_finite_t t : { l | forall s, s ∈ t <-> exists s', s ≈ s' /\ In s' l }.
Proof.
induction t as [ | s (ls & Hs) t (lt & Ht) ].
+ exists nil; intros s; btm simpl; simpl; firstorder.
+ exists (s::lt); intros u; btm simpl; simpl.
rewrite Ht; split.
* intros [ H | (s' & H1 & H2) ].
- exists s; auto.
- exists s'; auto.
* intros (s' & H1 & [ H2 | H2 ]); subst; auto.
right; exists s'; auto.
Qed.
Section bte_depth.
Opaque max.
Fact bte_depth_eq s t : s ≈ t -> ⌞s⌟ = ⌞t⌟.
Proof.
induction 1; simpl; auto.
+ transitivity ⌞s⌟; auto.
+ rewrite max_assoc, max_idempotent; auto.
+ rewrite max_assoc, (max_comm (S _)), max_assoc; auto.
Qed.
Fact btm_depth s t : s ∈ t -> ⌞s⌟ < ⌞t⌟.
Proof.
intros H; apply bte_depth_eq in H.
rewrite <- H; simpl.
apply lt_le_trans with (1 := lt_n_Sn _).
apply le_max_l.
Qed.
Theorem btm_wf : well_founded (fun s t => s ∈ t).
Proof.
apply wf_incl with (1 := btm_depth),
wf_inverse_image, lt_wf.
Qed.
End bte_depth.
Definition btree_wf_rect := well_founded_induction_type btm_wf.
Section establishing_decidability.
Reserved Notation "x ≺ y" (at level 70, no associativity).
Inductive bt_lt : bt -> bt -> Prop :=
| in_btlt_0 : forall s t, ∅ ≺ s⪧t
| in_btlt_1 : forall s s' t t', s ≺ s' -> s⪧t ≺ s'⪧t'
| in_btlt_2 : forall s t t', t ≺ t' -> s⪧t ≺ s⪧t'
where "s ≺ t" := (bt_lt s t).
Hint Constructors bt_lt : core.
Fact bt_lt_irrefl s : ~ s ≺ s.
Proof.
intros H.
assert (forall t, s ≺ t -> s <> t) as D;
[ | apply D in H; destruct H; auto ].
clear H; induction 1 as [ s t | s s' t t' H IH | s t t' H IH ];
try discriminate; contradict IH; inversion IH; auto.
Qed.
Fact bt_lt_trans r s t : r ≺ s -> s ≺ t -> r ≺ t.
Proof.
intros H1; revert H1 t.
induction 1; inversion 1; auto.
Qed.
Fact bt_lt_eq_lt_dec s t : { s ≺ t } + { s = t } + { t ≺ s }.
Proof.
revert t; induction s as [ | s1 H1 s2 H2 ] using bt_rect; intros [ | t1 t2 ]; auto.
destruct (H1 t1) as [ [] | ]; auto;
destruct (H2 t2) as [ [] | ]; subst; auto.
Qed.
Fixpoint bt_insert s t : bt :=
match t with
| ∅ => s⪧∅
| t⪧u => match bt_lt_eq_lt_dec s t with
| inleft (left _) => s⪧t⪧u
| inleft (right _) => t⪧u
| inright _ => t⪧(s→u)
end
end
where "s → t" := (bt_insert s t).
Fact bt_lt_eq_lt_dec_refl s : exists H, bt_lt_eq_lt_dec s s = inleft (right H).
Proof.
destruct (bt_lt_eq_lt_dec s s) as [ [ C | H ] | C ].
1,3: exfalso; revert C; apply bt_lt_irrefl.
exists H; auto.
Qed.
Ltac bt_lt_eq H :=
match goal with
|- context [bt_lt_eq_lt_dec ?x ?x]
=> destruct (bt_lt_eq_lt_dec_refl x) as (H & ->)
end.
Fact bt_insert_leaf s : s→∅ = s⪧∅.
Proof. reflexivity. Qed.
Fact bt_insert_eq s t : s→s⪧t = s⪧t.
Proof. simpl; bt_lt_eq H; auto. Qed.
Fact bt_insert_lt s t u : s ≺ t -> s→t⪧u = s⪧t⪧u.
Proof.
intros H; simpl.
destruct (bt_lt_eq_lt_dec s t) as [[|]|]; auto.
+ contradict H; subst; apply bt_lt_irrefl.
+ destruct (@bt_lt_irrefl s); apply bt_lt_trans with t; auto.
Qed.
Fact bt_insert_gt s t u : t ≺ s -> s→t⪧u = t⪧(s→u).
Proof.
intros H; simpl.
destruct (bt_lt_eq_lt_dec s t) as [[|]|]; auto.
+ destruct (@bt_lt_irrefl s); apply bt_lt_trans with t; auto.
+ contradict H; subst; apply bt_lt_irrefl.
Qed.
Fact bt_insert_equiv s t : s→t ≈ s⪧t.
Proof.
induction t as [ | t u Hu ] using bt_rect'; simpl; auto.
destruct (bt_lt_eq_lt_dec s t) as [[]|]; subst; auto.
apply bte_trans with (t⪧s⪧u); auto.
Qed.
Fixpoint bt_norm t :=
match t with
| ∅ => ∅
| s⪧t => s† → t†
end
where "t †" := (bt_norm t).
Hint Resolve bt_insert_equiv : core.
Fact bt_norm_eq t : t† ≈ t.
Proof.
induction t as [ | s ? t ? ]; simpl; auto.
apply bte_trans with (s†⪧t†); auto.
Qed.
Opaque bt_insert.
Tactic Notation "rew" "bt" "insert" :=
repeat match goal with
| |- context[_→∅] => rewrite bt_insert_leaf
| |- context[?x→?x⪧_] => rewrite bt_insert_eq
| H : ?x ≺ ?y |- context[?x→?y⪧_] => rewrite bt_insert_lt with (1 := H)
| H : ?x ≺ ?y |- context[?y→?x⪧_] => rewrite bt_insert_gt with (1 := H)
end.
Tactic Notation "bt" "insert" "case" hyp(x) hyp(y) :=
destruct (bt_lt_eq_lt_dec x y) as [ [|] | ]; subst; rew bt insert; auto.
Tactic Notation "bt" "lt" "trans" constr(t) := apply bt_lt_trans with t; auto.
Tactic Notation "bt" "lt" "cycle" :=
match goal with
| H1 : ?x ≺ ?x |- _ => destruct (@bt_lt_irrefl x); auto
| H1 : ?x ≺ ?y,
H2 : ?y ≺ ?x |- _ => destruct (@bt_lt_irrefl x); bt lt trans y
| H1 : ?x ≺ ?y,
H2 : ?y ≺ ?z,
H3 : ?z ≺ ?x |- _ => destruct (@bt_lt_irrefl x); bt lt trans y; bt lt trans z
end.
Fact bt_insert_cntr s t : s→s→t = s→t.
Proof.
induction t as [ | t1 t2 IH2 ] using bt_rect'; rew bt insert; auto.
bt insert case s t1; f_equal; auto.
Qed.
Fact bt_insert_comm s t u : s→t→u = t→s→u.
Proof.
induction u as [ | u1 u2 IH ] using bt_rect'.
+ rew bt insert; bt insert case s t.
+ bt insert case t u1;
bt insert case s u1;
bt insert case s t;
try bt lt cycle;
f_equal; auto.
Qed.
Hint Resolve bt_insert_cntr bt_insert_comm bt_norm_eq : core.
Theorem bte_norm_iff s t : s ≈ t <-> s† = t†.
Proof.
split.
+ induction 1; simpl; auto.
* transitivity s†; auto.
* f_equal; auto.
+ intros H.
apply bte_trans with s †; auto.
rewrite H; auto.
Qed.
Theorem bt_norm_idem s : s†† = s†.
Proof. apply bte_norm_iff; auto. Qed.
Theorem bte_dec s t : { s ≈ t } + { s ≉ t }.
Proof.
destruct (bt_eq_dec s† t†) as [ H | H ];
rewrite <- bte_norm_iff in H; auto.
Qed.
End establishing_decidability.
Corollary btm_dec s t : { s ∈ t } + { s ∉ t }.
Proof. apply bte_dec. Qed.
Section more_decidability.
Section btm_ex_dec.
Variable (P : bt -> Prop) (HP : forall s t, s ≈ t -> P s -> P t).
Theorem btm_ex_dec t : (forall x, x ∈ t -> { P x } + { ~ P x })
-> { s | s ∈ t /\ P s } + { forall s, s ∈ t -> ~ P s }.
Proof.
induction t as [ | s t IHt ] using bt_rect'; intros Ht.
+ right; intros ?; btm simpl.
+ destruct (Ht s) as [ H | H ]; btm simpl; auto.
* left; exists s; btm simpl; auto.
* destruct IHt as [ (x & H1 & H2) | H1 ].
- intros x Hx; apply Ht; btm simpl.
- left; exists x; btm simpl.
- right; intros x; btm simpl.
intros [ | ]; auto.
contradict H; revert H; apply HP; auto.
Qed.
End btm_ex_dec.
Corollary btm_fa_dec (P : _ -> Prop) t :
(forall s t, s ≈ t -> P s -> P t)
-> (forall x, x ∈ t -> { P x } + { ~ P x })
-> { s | s ∈ t /\ ~ P s } + { forall s, s ∈ t -> P s }.
Proof.
intros H1 H2.
destruct btm_ex_dec with (P := fun x => ~ P x) (t := t)
as [ H | H ]; auto.
+ intros u v G1 G2; contradict G2; revert G2; apply H1; auto.
+ intros x Hx; specialize (H2 _ Hx); tauto.
+ right; intros s Hs; specialize (H _ Hs).
destruct (H2 _ Hs); tauto.
Qed.
Definition btm_select (P : _ -> Prop) t :
(forall s t, s ≈ t -> P s -> P t)
-> (forall x, x ∈ t -> { P x } + { ~ P x })
-> { s | forall x, x ∈ s <-> x ∈ t /\ P x }.
Proof.
intros HP0.
induction t as [ | s t Ht ] using bt_rect'; intros HP.
+ exists ∅; intros s; btm simpl.
+ destruct Ht as (t' & H').
* intros x Hx; apply HP; btm simpl.
* destruct (HP s) as [ H | H ]; btm simpl; auto.
- exists (s⪧t'); intros x; btm simpl.
rewrite H'.
split; try tauto.
intros [ H1 | (H1 & H2) ]; auto.
split; auto.
revert H; apply HP0; auto.
- exists t'; intros x; rewrite H'; btm simpl.
split; try tauto.
intros ([H1|H1] & H2); split; auto.
contradict H; revert H2; apply HP0; auto.
Qed.
Definition btm_partition x s : x ∈ s -> { t | s ≈ x⪧t /\ x ∉ t }.
Proof.
induction s as [ | y s IHs ] using bt_rect'.
+ intros H; exfalso; revert H; btm simpl.
+ intros H; rewrite btm_inv in H.
destruct (bte_dec x y) as [ H1 | H1 ];
destruct (btm_dec x s) as [ H2 | H2 ]; try (exfalso; tauto).
* destruct (IHs H2) as (t & H3 & H4).
exists t; split; auto.
rewrite <- H1, H3; auto.
* exists s; auto.
* destruct (IHs H2) as (t & H3 & H4).
exists (y⪧t); split; auto.
- apply bte_trans with (y⪧x⪧t); auto.
- contradict H4; revert H4; btm simpl.
Qed.
End more_decidability.
Definition bt_incl x y := forall u, u ∈ x -> u ∈ y.
Local Infix "⊆" := bt_incl.
Add Parametric Morphism: (bt_incl) with signature
(bt_equiv) ==> (bt_equiv) ==> (iff) as bti_congr.
Proof.
intros x y H1 a b H2; split; intros H z.
+ rewrite <- H2, <- H1; apply H.
+ rewrite H1, H2; apply H.
Qed.
Fact bti_refl x : x ⊆ x.
Proof. red; auto. Qed.
Hint Resolve bti_refl : core.
Fact bti_trans x y z : x ⊆ y -> y ⊆ z -> x ⊆ z.
Proof. intros H1 H2 k Hx; apply H2, H1; auto. Qed.
Fact bti_comp s t : t ⊆ s⪧t.
Proof. intro; rewrite btm_inv; auto. Qed.
Fact bti_0 x : ∅ ⊆ x.
Proof. intro; btm simpl. Qed.
Fact bti_inv_0 x : x ⊆ ∅ <-> x = ∅.
Proof.
split; intros H; subst; auto.
destruct x as [ | s t ]; auto.
specialize (H s); revert H; btm simpl.
intros []; auto.
Qed.
Fact bti_mono_r x s t : s ⊆ t -> x⪧s ⊆ x⪧t.
Proof. intros ? ?; btm simpl; intros []; auto. Qed.
Fact bte_bti s t : s ≈ t -> s ⊆ t.
Proof. intros ? ?; apply btm_congr_r; auto. Qed.
Fact btm_bti x s : x ∈ s -> x⪧s ⊆ s.
Proof. intro; apply bte_bti; auto. Qed.
Fact bti_congr_l x y t : x ≈ y -> x ⊆ t-> y ⊆ t.
Proof.
intros H1 H2 z Hz.
apply H2; revert Hz; apply btm_congr_r; auto.
Qed.
Fact bti_congr_r x s t : s ≈ t -> x ⊆ s -> x ⊆ t.
Proof.
intros H1 H2 z Hz.
generalize (H2 _ Hz); apply btm_congr_r; auto.
Qed.
Hint Resolve bti_0 bti_refl bti_comp bti_mono_r : core.
Lemma bti_dec s t : { s ⊆ t } + { ~ s ⊆ t }.
Proof.
destruct btm_fa_dec with (P := fun x => x ∈ t) (t := s)
as [ (x & H1 & H2) | H1 ]; auto.
+ intros ? ?; apply btm_congr_l.
+ intros ? ?; apply btm_dec.
Qed.
Lemma bti_equiv s t : s ⊆ t -> t ⊆ s -> s ≈ t.
Proof.
revert t; induction s as [ | x s Hs ] using bt_rect'.
+ intros t _ Ht.
destruct t as [ | y t ]; auto.
generalize (Ht y); btm simpl.
intros []; auto.
+ induction t as [ | y _ t Ht ].
* intros H _; generalize (H x).
btm simpl; intros []; auto.
* intros H1 H2.
destruct (btm_dec x s) as [ H3 | H3 ].
- apply bte_trans with s; auto.
apply Hs.
++ apply bti_trans with (2 := H1); auto.
++ apply bti_trans with (1 := H2), btm_bti; auto.
- assert (x ∈ y⪧t) as H4 by (apply H1; auto; btm simpl).
destruct btm_partition with (1 := H4)
as (u & H5 & H6).
assert (s ≈ u) as H7.
{ apply Hs.
+ intros z Hz.
assert (z ∈ x⪧u) as H7.
{ apply btm_congr_r with (1 := H5), H1, btm_inv; auto. }
apply btm_inv in H7; destruct H7 as [ H7 | ]; auto.
contradict H3; revert Hz; apply btm_congr_l; auto.
+ intros z Hz.
assert (z ∈ x⪧s) as H7.
{ apply H2, btm_congr_r with (1 := in_bte_sym H5), btm_inv; auto. }
apply btm_inv in H7; destruct H7 as [ H7 | ]; auto.
contradict H6; revert Hz; apply btm_congr_l; auto. }
apply bte_trans with (x⪧u); auto.
Qed.
Fact bte_incl_equiv s t : s ≈ t <-> s ⊆ t /\ t ⊆ s.
Proof.
split.
+ intro; split; apply bte_bti; auto.
+ intros []; apply bti_equiv; auto.
Qed.
Fact bte_ext s t : s ≈ t <-> forall x, x ∈ s <-> x ∈ t.
Proof. rewrite bte_incl_equiv; firstorder. Qed.
Fact bti_inv x s t : x ⊆ s⪧t <-> x ⊆ t \/ exists y, y ⊆ t /\ x ≈ s⪧y.
Proof.
split.
+ intros H.
destruct (btm_dec s x) as [ H1 | H1 ].
* destruct btm_partition with (1 := H1)
as (y & H2 & H3).
right; exists y; split; auto.
intros z Hz.
assert (z ∈ s⪧t) as C.
{ apply H.
apply btm_congr_r with (1 := in_bte_sym H2), btm_inv; auto. }
apply btm_inv in C; destruct C as [C|]; auto.
contradict H3; revert Hz; apply btm_congr_l; auto.
* left.
intros y Hy.
specialize (H _ Hy).
apply btm_inv in H.
destruct H as [ H | ]; auto.
contradict H1.
revert Hy; apply btm_congr_l; auto.
+ intros [ H | (y & H1 & H2) ].
* apply bti_trans with (1 := H); auto.
* intros z Hz.
apply bti_congr_r with (1 := H2) in Hz; auto.
revert Hz; btm simpl; intros []; auto.
Qed.
Fixpoint bt_cup s t :=
match s with
| ∅ => t
| x⪧s => x⪧(s ∪ t)
end
where "s ∪ t" := (bt_cup s t).
Theorem bt_cup_spec x s t : x ∈ s ∪ t <-> x ∈ s \/ x ∈ t.
Proof.
revert x; induction s as [ | y s Hs ] using bt_rect';
intros x; simpl; btm simpl.
rewrite Hs; tauto.
Qed.
Fact bt_cup_left s t : s ⊆ s ∪ t.
Proof. intro; rewrite bt_cup_spec; auto. Qed.
Fact bt_cup_right s t : t ⊆ s ∪ t.
Proof. intro; rewrite bt_cup_spec; auto. Qed.
Hint Resolve bt_cup_left bt_cup_right : core.
Add Parametric Morphism: (bt_cup) with signature
(bt_equiv) ==> (bt_equiv) ==> (bt_equiv) as bt_cup_congr.
Proof.
intros s s' H t t'; revert H.
do 3 rewrite bte_ext; intros H1 H2 x.
do 2 rewrite bt_cup_spec.
rewrite H1, H2; tauto.
Qed.
Fact bt_cup_incl s t x : s ∪ t ⊆ x <-> s ⊆ x /\ t ⊆ x.
Proof.
split.
+ intros H; split; apply bti_trans with (2 := H); auto.
+ intros [] z; rewrite bt_cup_spec; intros []; auto.
Qed.
Fact bt_cup_mono s s' t t' : s ⊆ s' -> t ⊆ t' -> s ∪ t ⊆ s' ∪ t'.
Proof.
intros H1 H2 x; do 2 rewrite bt_cup_spec.
intros [ H | H ]; [ left | right ]; revert H; auto.
Qed.
Hint Resolve bt_cup_mono : core.
Definition bt_transitive t := forall u v, u ∈ v -> v ∈ t -> u ∈ t.
Fact bt_transitive_incl u t : bt_transitive t -> u ∈ t -> u ⊆ t.
Proof.
intros H H1 x H2.
revert H2 H1; apply H.
Qed.
Fixpoint bt_tc t :=
match t with
| ∅ => ∅
| s⪧t => s⪧(↓s ∪ ↓t)
end
where "↓ t" := (bt_tc t).
Fact bt_tc_incr t : t ⊆ ↓t.
Proof.
intro; induction t; simpl; auto; btm simpl.
rewrite bt_cup_spec; tauto.
Qed.
Hint Resolve bt_tc_incr : core.
Theorem bt_tc_trans t : bt_transitive ↓t.
Proof.
induction t as [ | s Hs t Ht ]; simpl; intros u v H1; btm simpl; intros H2.
rewrite bt_cup_spec in H2.
rewrite bt_cup_spec.
destruct H2 as [ H2 | [ H2 | H2 ] ].
+ rewrite H2 in H1; right; left; auto; apply bt_tc_incr; auto.
+ right; left; revert H2; apply Hs; auto.
+ right; right; revert H2; apply Ht; auto.
Qed.
Hint Resolve bt_tc_trans : core.
Fact bt_tc_incl_transitive s t : bt_transitive t -> s ⊆ t -> ↓s ⊆ t.
Proof.
intros H.
induction s as [ | u Hu v Hv ]; simpl; auto.
intros H1 x; btm simpl; rewrite bt_cup_spec.
intros [ H2 | [ H2 | H2 ] ].
+ rewrite H2; apply H1; btm simpl.
+ revert H2; apply Hu.
intros a Ha; apply H with (1 := Ha), H1; btm simpl.
+ revert H2; apply Hv; intros ? ?; apply H1; btm simpl.
Qed.
Fact bt_tc_mono s t : s ⊆ t -> ↓s ⊆ ↓t.
Proof.
intros H.
apply bt_tc_incl_transitive; auto.
apply bti_trans with (1 := H); auto.
Qed.
Fact bt_tc_idem t : (↓↓t) ⊆ ↓t.
Proof. apply bt_tc_incl_transitive; auto. Qed.
Hint Resolve bt_tc_mono bt_tc_idem : core.
Fact bt_tc_cup s t : ↓(s ∪ t) ⊆ ↓s ∪ ↓t.
Proof.
apply bt_tc_incl_transitive; auto.
intros x y; do 2 rewrite bt_cup_spec.
intros H [ H1 | H1 ]; [ left | right ];
revert H H1; apply bt_tc_trans.
Qed.
Fact bt_tc_congr_l u v t : u ≈ v -> u ∈ ↓t -> v ∈ ↓t.
Proof.
revert u v; induction t using bt_rect'; simpl;
intros ? ? ?; apply btm_congr_l; auto.
Qed.
Fact bt_tc_congr_r u s t : s ≈ t -> u ∈ ↓s <-> u ∈ ↓t.
Proof.
intros H; revert u.
rewrite bte_incl_equiv in H; destruct H.
apply bte_ext, bti_equiv; auto.
Qed.
Add Parametric Morphism: (bt_tc) with signature
(bt_equiv) ==> (bt_equiv) as bt_tc_congr.
Proof. intros; apply bte_ext; intro; apply bt_tc_congr_r; auto. Qed.
Section bt_pow.
Fixpoint bt_mcomp x t :=
match t with
| ∅ => ∅
| s⪧t => (x⪧s) ⪧ (bt_mcomp x t)
end.
Fact bt_mcomp_spec x t u : u ∈ bt_mcomp x t <-> exists k, k ∈ t /\ u ≈ x⪧k.
Proof.
revert u; induction t as [ | s t Ht ] using bt_rect'; intros u; simpl.
+ rewrite btm_inv_0; split; try tauto.
intros (k & Hk & _); revert Hk; rewrite btm_inv_0; auto.
+ rewrite btm_inv; split.
* intros [ H | H ].
- exists s; split; auto; btm simpl.
- rewrite Ht in H.
destruct H as (k & ? & ?).
exists k; split; auto.
btm simpl.
* intros (k & H1 & H2); revert H1 H2.
rewrite btm_inv, Ht.
intros [H2|H2] H1; auto.
- left; apply bte_trans with (1 := H1); auto.
- right; exists k; auto.
Qed.
Fixpoint bt_pow t :=
match t with
| ∅ => ∅⪧∅
| x⪧t => bt_pow t ∪ bt_mcomp x (bt_pow t)
end.
Fact bt_pow_spec t x : x ∈ bt_pow t <-> x ⊆ t.
Proof.
revert x; induction t as [ | s t Ht ] using bt_rect'; intros x; simpl.
+ rewrite btm_inv, btm_inv_0, bti_inv_0, bte_inv_0; tauto.
+ rewrite bti_inv, bt_cup_spec, bt_mcomp_spec, Ht.
split; intros [ | (y & H) ]; auto; right; exists y;
revert H; rewrite Ht; auto.
Qed.
Fact bt_pow_transitive t : bt_transitive t -> bt_transitive (bt_pow t).
Proof.
intros H x y H1.
do 2 rewrite bt_pow_spec.
intros H2 z Hz.
apply H2 in H1.
revert Hz H1; apply H.
Qed.
Fact bt_pow_trans_incl t : bt_transitive t -> t ⊆ bt_pow t.
Proof.
intros Ht.
intros x Hx.
apply bt_pow_spec; intros y Hy.
revert Hx; apply Ht; auto.
Qed.
Fact bt_pow_iter_trans t n : bt_transitive t -> bt_transitive (iter bt_pow t n)
/\ t ⊆ iter bt_pow t n.
Proof.
revert t; induction n as [ | n IHn ]; simpl; intros t Ht; auto; split.
+ apply IHn, bt_pow_transitive; auto.
+ destruct (IHn _ (bt_pow_transitive Ht)) as [ _ H ].
apply bti_trans with (2 := H), bt_pow_trans_incl; auto.
Qed.
Fact bt_pow_iter_mono t t' n : t ⊆ t' -> iter bt_pow t n ⊆ iter bt_pow t' n.
Proof.
revert t t'; induction n as [ | n IHn ]; simpl; auto; intros t t' H.
apply IHn; intro; do 2 rewrite bt_pow_spec.
intro; apply bti_trans with t; auto.
Qed.
Fact bt_pow_iter_le t n m : n <= m -> bt_transitive t -> iter bt_pow t n ⊆ iter bt_pow t m.
Proof.
intros H; revert H t.
induction 1 as [ | m Hm IHm ]; auto; intros t Ht.
apply bti_trans with (1 := IHm _ Ht); simpl.
apply bt_pow_iter_mono, bt_pow_trans_incl; auto.
Qed.
End bt_pow.
Add Parametric Morphism: (bt_pow) with signature
(bt_equiv) ==> (bt_equiv) as bt_pow_congr.
Proof. intros ? ? H; apply bte_ext; intro; do 2 rewrite bt_pow_spec; rewrite H; tauto. Qed.
Definition bt_opair s t := (s⪧∅)⪧(s⪧t⪧∅)⪧∅.
Local Notation "⟬ s , t ⟭" := (bt_opair s t).
Section ordered_pairs.
Fact bt_sg_inv x y : x⪧∅ ≈ y⪧∅ <-> x ≈ y.
Proof.
split; auto.
rewrite bte_ext.
intros H; specialize (H x).
do 2 rewrite btm_inv, btm_inv_0 in H.
apply proj1 in H; destruct H; try tauto; auto.
Qed.
Fact bt_sg_db_inv a x y : a⪧∅ ≈ x⪧y⪧∅ <-> a ≈ x /\ a ≈ y.
Proof.
split.
+ intros H.
rewrite bte_ext in H.
generalize (proj2 (H x)) (proj2 (H y)).
btm simpl; intros [|[]] [|[]]; auto.
+ intros [].
apply bte_trans with (a⪧a⪧∅); auto.
Qed.
Fact bt_db_inv a b x y : a⪧b⪧∅ ≈ x⪧y⪧∅ <-> a ≈ x /\ b ≈ x /\ x ≈ y
\/ a ≈ x /\ b ≈ y
\/ a ≈ y /\ b ≈ x.
Proof.
split.
+ intros H.
rewrite bte_ext in H.
generalize (proj1 (H a)) (proj1 (H b)) (proj2 (H x)) (proj2 (H y)).
btm simpl; intros [|[|[]]] [|[|[]]] [|[|[]]] [|[|[]]]; auto.
+ intros [ (H1&H2&H3) | [ (H1&H2) | (H1&H2) ] ]; auto.
* do 2 (apply in_bte_cngr; auto).
apply bte_trans with x; auto.
* apply bte_trans with (1 := in_bte_comm _ _ _).
do 2 (apply in_bte_cngr; auto).
Qed.
Fact bt_opair_spec x s t : x ∈ ⟬s,t⟭ <-> x ≈ s⪧∅ \/ x ≈ s⪧t⪧∅.
Proof. unfold bt_opair; btm simpl. Qed.
Fact bt_opair_equiv s t s' t' : ⟬s,t⟭ ≈⟬s',t'⟭ <-> s≈s' /\ t≈t'.
Proof.
split.
2: intros []; unfold bt_opair; auto.
intros H; rewrite bte_ext in H.
assert (forall x, (x ≈ s⪧∅ \/ x ≈ s⪧t⪧∅) <-> (x ≈ s'⪧∅ \/ x ≈ s'⪧t'⪧∅)) as H'.
{ intros x; generalize (H x); do 2 rewrite bt_opair_spec; tauto. }
clear H; revert H'; intros H.
generalize (proj1 (H _) (or_introl (in_bte_refl _)))
(proj1 (H _) (or_intror (in_bte_refl _)))
(proj2 (H _) (or_introl (in_bte_refl _)))
(proj2 (H _) (or_intror (in_bte_refl _))).
repeat rewrite bt_db_inv.
do 2 rewrite (bte_sym (_⪧_⪧_)).
repeat rewrite bt_sg_inv.
repeat rewrite bt_sg_db_inv.
intros.
repeat match goal with
| H : _ /\ _ |- _ => destruct H
| H : _ \/ _ |- _ => destruct H
end; split; auto;
try (apply bte_trans with s); auto;
try (apply bte_trans with s'); auto.
Qed.
End ordered_pairs.
Add Parametric Morphism: (bt_opair) with signature
(bt_equiv) ==> (bt_equiv) ==> (bt_equiv) as bt_pair_congr.
Proof. intros; apply bt_opair_equiv; auto. Qed.
Fact btm_opair_pow x y t : x ∈ t -> y ∈ t -> ⟬x,y⟭ ∈ bt_pow (bt_pow t).
Proof.
rewrite bt_pow_spec.
intros Hx Hy p.
rewrite bt_opair_spec.
intros [H|H]; apply bte_sym in H;
apply btm_congr_l with (1 := H); apply bt_pow_spec.
+ intros z; btm simpl; intros [ Hz | [] ].
revert Hx; apply btm_congr_l; auto.
+ intros z; btm simpl; intros [ Hz | [ Hz | [] ] ];
[ revert Hx | revert Hy ]; apply btm_congr_l; auto.
Qed.
Section FOL_encoding.
Fact bt_enc_equiv s t : s ≈ t <-> forall x, x ∈ s <-> x ∈ t.
Proof. apply bte_ext. Qed.
Fact bt_enc_empty s : s ≈ ∅ <-> forall x, ~ x ∈ s.
Proof. rewrite bte_ext; apply forall_equiv; intro; btm simpl. Qed.
Fact bt_enc_sg s t : s ≈ t⪧∅ <-> forall x, x ∈ s <-> x ≈ t.
Proof. rewrite bte_ext; apply forall_equiv; intro; btm simpl. Qed.
Fact bt_enc_db u s t : u ≈ s⪧t⪧∅ <-> forall x, x ∈ u <-> x ≈ s \/ x ≈ t.
Proof. rewrite bte_ext; apply forall_equiv; intros; btm simpl. Qed.
Fact bt_enc_opair p s t : p ≈ ⟬s,t⟭ <-> (forall x, x ∈ p <-> x ≈ s⪧∅ \/ x ≈ s⪧t⪧∅).
Proof.
rewrite bte_ext; apply forall_equiv; intro.
rewrite bt_opair_spec; tauto.
Qed.
Fact bt_enc_otriple p r s t : p ≈ ⟬r,⟬s,t⟭⟭ <-> exists a, p ≈ ⟬r,a⟭ /\ a ≈ ⟬s,t⟭ .
Proof.
split.
+ exists ⟬s,t⟭; auto.
+ intros (a & H1 & H2).
apply bte_trans with (1 := H1).
apply bt_opair_equiv; auto.
Qed.
Fact bt_enc_rel3 a b c t : ⟬a,⟬b,c⟭⟭ ∈ t <-> exists p, p ≈ ⟬a,⟬b,c⟭⟭ /\ p ∈ t.
Proof.
split.
+ exists ⟬a,⟬b,c⟭⟭ ; auto.
+ intros (p & H1 & H2).
revert H2; apply btm_congr_l; auto.
Qed.
Fixpoint tuple (l : list bt) :=
match l with
| nil => ∅
| x::l => ⟬x,tuple l⟭
end.
Fact bt_enc_tuple_0 p : p ≈ tuple nil <-> p ≈ ∅.
Proof. simpl; tauto. Qed.
Fact bt_enc_tuple p x l : p ≈ tuple (x::l) <-> exists a, p ≈ ⟬x,a⟭ /\ a ≈ tuple l.
Proof.
simpl; split.
+ exists (tuple l); auto; split; auto.
+ intros (a & H1 & H2).
apply bte_trans with (1 := H1).
apply bt_opair_equiv; auto.
Qed.
End FOL_encoding.
Section nat2bt.
Fixpoint nat2bt n : bt :=
match n with
| 0 => ∅
| S n => (nat2bt n)⪧(nat2bt n)
end.
Fact nat2bt_transitive n : bt_transitive (nat2bt n).
Proof.
induction n as [ | n IHn ]; simpl.
+ intros ? ?; btm simpl.
+ intros a b; btm simpl.
intros H1 [ H2 | H3 ]; right.
* rewrite <- H2; auto.
* revert H1 H3; apply IHn.
Qed.
Hint Resolve nat2bt_transitive : core.
Fact nat2bt_mono n m : n <= m -> nat2bt n ⊆ nat2bt m.
Proof.
induction 1 as [ | m Hm IHm ]; auto.
apply bti_trans with (1 := IHm).
apply bt_transitive_incl; auto.
simpl; btm simpl.
Qed.
Let nat2bt_inv_full m x : x ∈ nat2bt m -> { n | n < m /\ x ≈ nat2bt n }.
Proof.
revert x; induction m as [ | m IHm ]; intros x; simpl; btm simpl.
+ intro E; exfalso; revert E; btm simpl.
+ intros H; rewrite btm_inv in H.
destruct (bte_dec x (nat2bt m)) as [ H1 | H1 ].
* exists m; split; auto.
* destruct (IHm x) as (n & H2 & H3); try tauto.
exists n; split; auto; lia.
Qed.
Definition bt2nat n x Hx := proj1_sig (@nat2bt_inv_full n x Hx).
Fact bt2nat_lt n x Hx : @bt2nat n x Hx < n.
Proof. apply (proj2_sig (@nat2bt_inv_full n x Hx)). Qed.
Fact bt2nat_fix n x Hx : nat2bt (@bt2nat n x Hx) ≈ x.
Proof. apply bte_sym, (proj2_sig (@nat2bt_inv_full n x Hx)). Qed.
Fact nat2bt_inj n m : nat2bt n ≈ nat2bt m -> n = m.
Proof.
revert m; induction n as [ | n IHn ]; intros [ | m ]; simpl; auto.
+ intros H; symmetry in H; apply bte_discr in H; tauto.
+ intros H; apply bte_discr in H; tauto.
+ intros H; rewrite bte_ext in H.
f_equal; apply IHn; clear IHn.
generalize (proj1 (H (nat2bt n)))
(proj2 (H (nat2bt m))); btm simpl.
intros [H0 | H0] [H1 | H1]; auto.
apply btm_depth in H0.
apply btm_depth in H1.
lia.
Qed.
Hint Resolve nat2bt_mono : core.
Fact nat2bt_order_iso n m : nat2bt n ⊆ nat2bt m <-> n <= m.
Proof.
split; eauto.
intros H.
destruct (le_lt_dec m n); try lia.
cut (n = m); try lia.
apply nat2bt_inj, bti_equiv; eauto.
Qed.
Fact nat2bt_strict n m : nat2bt n ∈ nat2bt m <-> n < m.
Proof.
split.
+ intros H.
destruct (le_lt_dec m n) as [ H1 | ]; auto.
generalize (nat2bt_mono H1 H); intros H2.
apply btm_depth in H2; lia.
+ intros H; apply (nat2bt_mono H).
simpl; btm simpl.
Qed.
End nat2bt.
Section pos2bt.
Definition pos2bt n (p : pos n) := nat2bt (pos2nat p).
Fact pos2bt_in n p : @pos2bt n p ∈ nat2bt n.
Proof. apply nat2bt_strict, pos2nat_prop. Qed.
Let bt2pos_full n x : x ∈ nat2bt n -> { p | x ≈ @pos2bt n p }.
Proof.
intros Hx.
assert (bt2nat _ Hx < n).
{ apply nat2bt_strict; rewrite bt2nat_fix; auto. }
exists (nat2pos H); unfold pos2bt; rewrite pos2nat_nat2pos.
rewrite bt2nat_fix; auto.
Qed.
Definition bt2pos n x Hx := proj1_sig (@bt2pos_full n x Hx).
Fact bt2pos_fix n x Hx : pos2bt (@bt2pos n x Hx) ≈ x.
Proof. apply bte_sym, (proj2_sig (@bt2pos_full n x Hx)). Qed.
Fact pos2bt_inj n p q : @pos2bt n p ≈ pos2bt q -> p = q.
Proof. intro H; apply pos2nat_inj, nat2bt_inj, H. Qed.
End pos2bt.