Timings for BoundedSearch.v
(** * Bounded Search *)
(** The main result of this file is [minimal_n], which say that if [P : nat -> Type] is a family such that each [P n] is decidable and [{n & P n}] is merely inhabited, then [{n & P n}] is inhabited. Since [P n] is decidable, it is sufficient to prove [{n & merely (P n)}], and to do this, we prove the stronger claim that there is a *minimal* [n] satisfying [merely (P n)]. This stronger claim is a proposition, which is what makes the argument work. Along the way, we also prove that [{ l : nat & (l <= n) * P l }] is decidable for each [n]. *)
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.
Context (P : nat -> Type) (P_dec : forall 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 := forall 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.
apply ishprop_sigma_disjoint.
intros n n' [p m] [p' m'].
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).
destruct k as [l [[p m] z]].
Local Definition bounded_search (n : nat) : smaller n + forall l : nat, (l <= n) -> not (P l).
destruct (dec (P 0)) as [h|n].
exact (0; (h, fun _ _ => _, _)).
by rewrite (leq_antisym lleq0 _ : l = 0).
left; by apply smaller_S.
destruct (dec (P n.+1)) as [h|nP].
refine (n.+1; (h, _, _)).
unfold gt, lt; intro leq_Sm_Sn.
apply leq_pred' in leq_Sm_Sn.
destruct (n0 m leq_Sm_Sn pm).
Local Definition n_to_min_n (n : nat) (Pn : P n) : min_n_Type.
destruct (bounded_search n) as [[l [[Pl ml] _]] | none].
exact (l; (tr Pl, tr ml)).
destruct (none n (leq_refl n) Pn).
Local Definition prop_n_to_min_n (P_inhab : hexists P) : min_n_Type.
exact (n_to_min_n (P_inhab.1) (P_inhab.2)).
Definition minimal_n (P_inhab : hexists P) : { n : nat & P n }.
destruct (prop_n_to_min_n P_inhab) as [n [p _]].
exact (n; fst merely_inhabited_iff_inhabited_stable p).
(** 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 }.
destruct (bounded_search n) as [s | no_l].
destruct s as [l [[Pl min] l_leq_n]].
exact (inl (l; (l_leq_n, Pl))).
exact (no_l l l_leq_n Pl).
Section bounded_search_alt_type.
Context (X : Type)
(e : nat <~> X)
(P : X -> Type)
(P_dec : forall 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}.
pose (P'_dec n := P_dec (e n) : Decidable (P' n)).
assert (P'_inhab : hexists P').
destruct P_inhab as [x p].
destruct (minimal_n P' P'_dec P'_inhab) as [n p'].
End bounded_search_alt_type.