Library HoTT.BoundedSearch
Bounded Search
Require Import Basics.Overture Basics.Decidable Basics.Trunc Basics.Tactics.
Require Import Types.Sigma Types.Prod.
Require Import Truncations.Core.
Require Import Spaces.Nat.Core.
Section bounded_search.
Context (P : nat → Type) (P_dec : ∀ n, Decidable (P n)).
We open type_scope again after nat_scope in order to use the product type notation.
Local Open Scope nat_scope.
Local Open Scope type_scope.
Local Definition minimal (n : nat) : Type := ∀ m : nat, P m → n ≤ m.
Local Open Scope type_scope.
Local Definition minimal (n : nat) : Type := ∀ m : nat, P m → n ≤ m.
If we assume Funext, then minimal n is a proposition. But to avoid needing Funext, we propositionally truncate it.
Local Definition min_n_Type : Type := { n : nat & merely (P n) × merely (minimal n) }.
Local Instance ishpropmin_n : IsHProp min_n_Type.
Proof.
apply ishprop_sigma_disjoint.
intros n n' [p m] [p' m'].
strip_truncations.
apply leq_antisym.
- exact (m n' p').
- exact (m' n p).
Defined.
Local Definition smaller (n : nat) := { l : nat & P l × minimal l × (l ≤ n) }.
Local Definition smaller_S (n : nat) (k : smaller n) : smaller (S n).
Proof.
destruct k as [l [[p m] z]].
∃ l.
repeat split.
1,2: assumption.
exact _.
Defined.
Local Definition bounded_search (n : nat) : smaller n + ∀ l : nat, (l ≤ n) → not (P l).
Proof.
induction n as [|n IHn].
- destruct (dec (P 0)) as [h|n].
+ left.
exact (0; (h, fun _ _ ⇒ _, _)).
+ right.
intros l lleq0.
by rewrite (leq_antisym lleq0 _ : l = 0).
- destruct IHn as [s|n0].
+ left; by apply smaller_S.
+ destruct (dec (P n.+1)) as [h|nP].
× left.
refine (n.+1; (h, _, _)).
intros m pm.
apply leq_iff_not_gt.
unfold gt, lt; intro leq_Sm_Sn.
apply leq_pred' in leq_Sm_Sn.
destruct (n0 m leq_Sm_Sn pm).
× right.
by apply leq_ind_l.
Defined.
Local Definition n_to_min_n (n : nat) (Pn : P n) : min_n_Type.
Proof.
destruct (bounded_search n) as [[l [[Pl ml] _]] | none].
- exact (l; (tr Pl, tr ml)).
- destruct (none n (leq_refl n) Pn).
Defined.
Local Definition prop_n_to_min_n (P_inhab : hexists P) : min_n_Type.
Proof.
strip_truncations.
exact (n_to_min_n (P_inhab.1) (P_inhab.2)).
Defined.
Definition minimal_n (P_inhab : hexists P) : { n : nat & P n }.
Proof.
destruct (prop_n_to_min_n P_inhab) as [n [p _]].
exact (n; fst merely_inhabited_iff_inhabited_stable p).
Defined.
Local Instance ishpropmin_n : IsHProp min_n_Type.
Proof.
apply ishprop_sigma_disjoint.
intros n n' [p m] [p' m'].
strip_truncations.
apply leq_antisym.
- exact (m n' p').
- exact (m' n p).
Defined.
Local Definition smaller (n : nat) := { l : nat & P l × minimal l × (l ≤ n) }.
Local Definition smaller_S (n : nat) (k : smaller n) : smaller (S n).
Proof.
destruct k as [l [[p m] z]].
∃ l.
repeat split.
1,2: assumption.
exact _.
Defined.
Local Definition bounded_search (n : nat) : smaller n + ∀ l : nat, (l ≤ n) → not (P l).
Proof.
induction n as [|n IHn].
- destruct (dec (P 0)) as [h|n].
+ left.
exact (0; (h, fun _ _ ⇒ _, _)).
+ right.
intros l lleq0.
by rewrite (leq_antisym lleq0 _ : l = 0).
- destruct IHn as [s|n0].
+ left; by apply smaller_S.
+ destruct (dec (P n.+1)) as [h|nP].
× left.
refine (n.+1; (h, _, _)).
intros m pm.
apply leq_iff_not_gt.
unfold gt, lt; intro leq_Sm_Sn.
apply leq_pred' in leq_Sm_Sn.
destruct (n0 m leq_Sm_Sn pm).
× right.
by apply leq_ind_l.
Defined.
Local Definition n_to_min_n (n : nat) (Pn : P n) : min_n_Type.
Proof.
destruct (bounded_search n) as [[l [[Pl ml] _]] | none].
- exact (l; (tr Pl, tr ml)).
- destruct (none n (leq_refl n) Pn).
Defined.
Local Definition prop_n_to_min_n (P_inhab : hexists P) : min_n_Type.
Proof.
strip_truncations.
exact (n_to_min_n (P_inhab.1) (P_inhab.2)).
Defined.
Definition minimal_n (P_inhab : hexists P) : { n : nat & P n }.
Proof.
destruct (prop_n_to_min_n P_inhab) as [n [p _]].
exact (n; fst merely_inhabited_iff_inhabited_stable p).
Defined.
As a consequence of bounded_search we deduce that bounded existence is decidable. See also decidable_exists_bounded_nat in Spaces/Lists/Theory.v for a similar result with different dependencies.
Definition decidable_search (n : nat) : Decidable { l : nat & (l ≤ n) × P l }.
Proof.
destruct (bounded_search n) as [s | no_l].
- destruct s as [l [[Pl min] l_leq_n]].
exact (inl (l; (l_leq_n, Pl))).
- right.
intros [l [l_leq_n Pl]].
exact (no_l l l_leq_n Pl).
Defined.
End bounded_search.
Section bounded_search_alt_type.
Context (X : Type)
(e : nat <~> X)
(P : X → Type)
(P_dec : ∀ x, Decidable (P x))
(P_inhab : hexists P).
Proof.
destruct (bounded_search n) as [s | no_l].
- destruct s as [l [[Pl min] l_leq_n]].
exact (inl (l; (l_leq_n, Pl))).
- right.
intros [l [l_leq_n Pl]].
exact (no_l l l_leq_n Pl).
Defined.
End bounded_search.
Section bounded_search_alt_type.
Context (X : Type)
(e : nat <~> X)
(P : X → Type)
(P_dec : ∀ x, Decidable (P x))
(P_inhab : hexists P).
Bounded search works for types equivalent to the naturals even without full univalence.
Definition minimal_n_alt_type : {x : X & P x}.
Proof.
pose (P' n := P (e n)).
pose (P'_dec n := P_dec (e n) : Decidable (P' n)).
assert (P'_inhab : hexists P').
{
strip_truncations. apply tr.
destruct P_inhab as [x p].
∃ (e ^-1 x).
unfold P'.
rewrite (eisretr e). exact p.
}
destruct (minimal_n P' P'_dec P'_inhab) as [n p'].
exact ((e n); p').
Defined.
End bounded_search_alt_type.
Proof.
pose (P' n := P (e n)).
pose (P'_dec n := P_dec (e n) : Decidable (P' n)).
assert (P'_inhab : hexists P').
{
strip_truncations. apply tr.
destruct P_inhab as [x p].
∃ (e ^-1 x).
unfold P'.
rewrite (eisretr e). exact p.
}
destruct (minimal_n P' P'_dec P'_inhab) as [n p'].
exact ((e n); p').
Defined.
End bounded_search_alt_type.