Built with Alectryon, running Coq+SerAPI v8.20.0+0.20.0. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus. On Mac, use instead of Ctrl.
[Loading ML file ssrmatching_plugin.cmxs (using legacy method) ... done]
[Loading ML file ssreflect_plugin.cmxs (using legacy method) ... done]
[Loading ML file ring_plugin.cmxs (using legacy method) ... done]
Serlib plugin: coq-elpi.elpi is not available: serlib support is missing. Incremental checking for commands in this plugin will be impacted.
[Loading ML file coq-elpi.elpi ... done]
Notation "_ + _" was already used in scope nat_scope. [notation-overridden,parsing,default]
Notation "_ - _" was already used in scope nat_scope. [notation-overridden,parsing,default]
Notation "_ <= _" was already used in scope nat_scope. [notation-overridden,parsing,default]
Notation "_ < _" was already used in scope nat_scope. [notation-overridden,parsing,default]
Notation "_ >= _" was already used in scope nat_scope. [notation-overridden,parsing,default]
Notation "_ > _" was already used in scope nat_scope. [notation-overridden,parsing,default]
Notation "_ <= _ <= _" was already used in scope nat_scope. [notation-overridden,parsing,default]
Notation "_ < _ <= _" was already used in scope nat_scope. [notation-overridden,parsing,default]
Notation "_ <= _ < _" was already used in scope nat_scope. [notation-overridden,parsing,default]
Notation "_ < _ < _" was already used in scope nat_scope. [notation-overridden,parsing,default]
Notation "_ * _" was already used in scope nat_scope. [notation-overridden,parsing,default]
[Loading ML file zify_plugin.cmxs (using legacy method) ... done]
[Loading ML file micromega_core_plugin.cmxs (using legacy method) ... done]
[Loading ML file micromega_plugin.cmxs (using legacy method) ... done]
[Loading ML file btauto_plugin.cmxs (using legacy method) ... done]
Require Import prosa.util.tactics. (** This file introduces a function called [search_arg] that allows finding the argument within a given range for which a function is minimal w.r.t. to a given order while satisfying a given predicate, along with lemmas establishing the basic properties of [search_arg]. Note that while this is quite similar to [arg min ...] / [arg max ...] in [ssreflect] ([fintype]), this function is subtly different in that it possibly returns None and that it does not require the last element in the given range to satisfy the predicate. In contrast, [ssreflect]'s notion of extremum in [fintype] uses the upper bound of the search space as the default value, which is rather unnatural when searching through a schedule. *) (** First, we show that, given an interval <<[t1, t2)>> and a predicate [P], either no element in the interval satisfy [P] or there is an element that satisfies [P]. *)

forall (P : pred nat) (t1 t2 : nat), (forall t : nat, t1 <= t < t2 -> ~~ P t) \/ (exists t : nat, t1 <= t < t2 /\ P t /\ (forall t' : nat, t1 <= t' -> P t' -> t <= t'))

forall (P : pred nat) (t1 t2 : nat), (forall t : nat, t1 <= t < t2 -> ~~ P t) \/ (exists t : nat, t1 <= t < t2 /\ P t /\ (forall t' : nat, t1 <= t' -> P t' -> t <= t'))
P: pred nat
t1, t2: nat

(forall t : nat, t1 <= t < t2 -> ~~ P t) \/ (exists t : nat, t1 <= t < t2 /\ P t /\ (forall t' : nat, t1 <= t' -> P t' -> t <= t'))
P: pred nat
t1, t2: nat
ALL: {in index_iota t1 t2, forall x : Datatypes_nat__canonical__eqtype_Equality, ~~ P x}

(forall t : nat, t1 <= t < t2 -> ~~ P t) \/ (exists t : nat, t1 <= t < t2 /\ P t /\ (forall t' : nat, t1 <= t' -> P t' -> t <= t'))
P: pred nat
t1, t2: nat
x: Datatypes_nat__canonical__eqtype_Equality
IN: t1 <= x < t2
Px: P x
(forall t : nat, t1 <= t < t2 -> ~~ P t) \/ (exists t : nat, t1 <= t < t2 /\ P t /\ (forall t' : nat, t1 <= t' -> P t' -> t <= t'))
P: pred nat
t1, t2: nat
ALL: {in index_iota t1 t2, forall x : Datatypes_nat__canonical__eqtype_Equality, ~~ P x}

(forall t : nat, t1 <= t < t2 -> ~~ P t) \/ (exists t : nat, t1 <= t < t2 /\ P t /\ (forall t' : nat, t1 <= t' -> P t' -> t <= t'))
by left => t IN; apply: ALL; rewrite mem_index_iota.
P: pred nat
t1, t2: nat
x: Datatypes_nat__canonical__eqtype_Equality
IN: t1 <= x < t2
Px: P x

(forall t : nat, t1 <= t < t2 -> ~~ P t) \/ (exists t : nat, t1 <= t < t2 /\ P t /\ (forall t' : nat, t1 <= t' -> P t' -> t <= t'))
P: pred nat
t1, t2: nat
x: Datatypes_nat__canonical__eqtype_Equality
IN: t1 <= x < t2
Px: P x

(forall t : nat, t1 <= t < t2 -> ~~ P t) \/ (exists t : nat, t1 <= t < t2 /\ P t /\ (forall t' : nat, t1 <= t' -> P t' -> t <= t'))
P: pred nat
t1, t2: nat
x: Datatypes_nat__canonical__eqtype_Equality
IN: t1 <= x < t2
Px: P x

exists t : nat, t1 <= t < t2 /\ P t /\ (forall t' : nat, t1 <= t' -> P t' -> t <= t')
P: pred nat
t1, t2: nat
x: Datatypes_nat__canonical__eqtype_Equality
IN: t1 <= x < t2
Px: P x
EX: exists n : nat, (t1 <= n < t2) && P n

exists t : nat, t1 <= t < t2 /\ P t /\ (forall t' : nat, t1 <= t' -> P t' -> t <= t')
P: pred nat
t1, t2: nat
x: Datatypes_nat__canonical__eqtype_Equality
IN: t1 <= x < t2
Px: P x
EX: exists n : nat, (t1 <= n < t2) && P n
x': nat
IN': t1 <= x' < t2
Px': P x'
MIN: forall n : nat, (t1 <= n < t2) && P n -> x' <= n

exists t : nat, t1 <= t < t2 /\ P t /\ (forall t' : nat, t1 <= t' -> P t' -> t <= t')
P: pred nat
t1, t2: nat
x: Datatypes_nat__canonical__eqtype_Equality
IN: t1 <= x < t2
Px: P x
EX: exists n : nat, (t1 <= n < t2) && P n
x': nat
IN': t1 <= x' < t2
Px': P x'
MIN: forall n : nat, (t1 <= n < t2) && P n -> x' <= n
t': nat
LT: t1 <= t'
Pt': P t'

x' <= t'
P: pred nat
t1, t2: nat
x: Datatypes_nat__canonical__eqtype_Equality
IN: t1 <= x < t2
Px: P x
EX: exists n : nat, (t1 <= n < t2) && P n
x': nat
IN': t1 <= x' < t2
Px': P x'
MIN: forall n : nat, (t1 <= n < t2) && P n -> x' <= n
t': nat
LT: t1 <= t'
Pt': P t'
NEQ2: t' < t2

x' <= t'
by apply: MIN; repeat(apply/andP; split => //). } Qed. (** Next, we proceed to the function [search_arg]. *) Section ArgSearch. (* Given a function [f] that maps the naturals to elements of type [T]... *) Context {T : Type}. Variable f: nat -> T. (* ... a predicate [P] on [T] ... *) Variable P: pred T. (* ... and an order [R] on [T] ... *) Variable R: rel T. (* ... we define the procedure [search_arg] to iterate a given search space [a, b), while checking each element whether [f] satisfies [P] at that point and returning the extremum as defined by [R]. *) Fixpoint search_arg (a b : nat) : option nat := if a < b then match b with | 0 => None | S b' => match search_arg a b' with | None => if P (f b') then Some b' else None | Some x => if P (f b') && R (f b') (f x) then Some b' else Some x end end else None. (** In the following, we establish basic properties of [search_arg]. *) (* To begin, we observe that the search yields [None] iff predicate [P] does not hold for any of the points in the search interval. *)
T: Type
f: nat -> T
P: pred T
R: rel T

forall a b : nat, search_arg a b = None <-> (forall x : nat, a <= x < b -> ~~ P (f x))
T: Type
f: nat -> T
P: pred T
R: rel T

forall a b : nat, search_arg a b = None <-> (forall x : nat, a <= x < b -> ~~ P (f x))
T: Type
f: nat -> T
P: pred T
R: rel T
a, b: nat

search_arg a b = None -> forall x : nat, a <= x < b -> ~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b: nat
(forall x : nat, a <= x < b -> ~~ P (f x)) -> search_arg a b = None
T: Type
f: nat -> T
P: pred T
R: rel T
a, b: nat

search_arg a b = None -> forall x : nat, a <= x < b -> ~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
HYP: search_arg a b' = None -> forall x : nat, a <= x < b' -> ~~ P (f x)

search_arg a b'.+1 = None -> forall x : nat, a <= x < b'.+1 -> ~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
HYP: search_arg a b' = None -> forall x : nat, a <= x < b' -> ~~ P (f x)

(if a < b'.+1 then match search_arg a b' with | Some x => if P (f b') && R (f b') (f x) then Some b' else Some x | None => if P (f b') then Some b' else None end else None) = None -> forall x : nat, a <= x < b'.+1 -> ~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
HYP: search_arg a b' = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
a_lt_b: a < b'.+1

match search_arg a b' with | Some x => if P (f b') && R (f b') (f x) then Some b' else Some x | None => if P (f b') then Some b' else None end = None -> forall x : nat, a <= x < b'.+1 -> ~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
HYP: search_arg a b' = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
not_a_lt_b': ~~ (a < b'.+1)
TRIV: None = None
forall x : nat, a <= x < b'.+1 -> ~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
HYP: search_arg a b' = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
a_lt_b: a < b'.+1

match search_arg a b' with | Some x => if P (f b') && R (f b') (f x) then Some b' else Some x | None => if P (f b') then Some b' else None end = None -> forall x : nat, a <= x < b'.+1 -> ~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
a_lt_b: a < b'.+1

(search_arg a b' = None -> forall x : nat, a <= x < b' -> ~~ P (f x)) -> match search_arg a b' with | Some x => if P (f b') && R (f b') (f x) then Some b' else Some x | None => if P (f b') then Some b' else None end = None -> forall x : nat, a <= x < b'.+1 -> ~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
a_lt_b: a < b'.+1
y: nat

(Some y = None -> forall x : nat, a <= x < b' -> ~~ P (f x)) -> (if P (f b') && R (f b') (f y) then Some b' else Some y) = None -> forall x : nat, a <= x < b'.+1 -> ~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
a_lt_b: a < b'.+1
HYP: None = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
NIL: (if P (f b') then Some b' else None) = None
x: nat
a <= x < b'.+1 -> ~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
a_lt_b: a < b'.+1
y: nat

(Some y = None -> forall x : nat, a <= x < b' -> ~~ P (f x)) -> (if P (f b') && R (f b') (f y) then Some b' else Some y) = None -> forall x : nat, a <= x < b'.+1 -> ~~ P (f x)
case: (P (f b') && R (f b') (f y)) => //.
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
a_lt_b: a < b'.+1
HYP: None = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
NIL: (if P (f b') then Some b' else None) = None
x: nat

a <= x < b'.+1 -> ~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
a_lt_b: a < b'.+1
HYP: None = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
NIL: (if P (f b') then Some b' else None) = None
x: nat
a_le_x: a <= x
x_lt_b': x < b'.+1

~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
a_lt_b: a < b'.+1
HYP: None = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
NIL: (if P (f b') then Some b' else None) = None
x: nat
a_le_x: a <= x

x < b'.+1 -> ~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
a_lt_b: a < b'.+1
HYP: None = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
NIL: (if P (f b') then Some b' else None) = None
x: nat
a_le_x: a <= x
EQ: x = b'

~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
a_lt_b: a < b'.+1
HYP: None = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
NIL: (if P (f b') then Some b' else None) = None
x: nat
a_le_x: a <= x
LT: x < b'
~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
a_lt_b: a < b'.+1
HYP: None = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
NIL: (if P (f b') then Some b' else None) = None
x: nat
a_le_x: a <= x
EQ: x = b'

~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
a_lt_b: a < b'.+1
HYP: None = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
NIL: (if P (f b') then Some b' else None) = None
x: nat
a_le_x: a <= x
EQ: x = b'

~~ P (f b')
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
a_lt_b: a < b'.+1
HYP: None = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
x: nat
a_le_x: a <= x
EQ: x = b'

(if P (f b') then Some b' else None) = None -> ~~ P (f b')
case: (P (f b')) => //.
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
a_lt_b: a < b'.+1
HYP: None = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
NIL: (if P (f b') then Some b' else None) = None
x: nat
a_le_x: a <= x
LT: x < b'

~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
a_lt_b: a < b'.+1
HYP: forall x : nat, a <= x < b' -> ~~ P (f x)
NIL: (if P (f b') then Some b' else None) = None
x: nat
a_le_x: a <= x
LT: x < b'

~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
a_lt_b: a < b'.+1
HYP: forall x : nat, a <= x < b' -> ~~ P (f x)
NIL: (if P (f b') then Some b' else None) = None
x: nat
a_le_x: a <= x
LT: x < b'

a <= x < b'
by apply /andP; split.
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
HYP: search_arg a b' = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
not_a_lt_b': ~~ (a < b'.+1)
TRIV: None = None

forall x : nat, a <= x < b'.+1 -> ~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
HYP: search_arg a b' = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
not_a_lt_b': ~~ (a < b'.+1)
TRIV: None = None
x: nat
a_le_x: a <= x
b_lt_b': x < b'.+1

~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
HYP: search_arg a b' = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
not_a_lt_b': ~~ (a < b'.+1)
TRIV: None = None
x: nat
a_le_x: a <= x
b_lt_b': x < b'.+1

False
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
HYP: search_arg a b' = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
TRIV: None = None
x: nat
a_le_x: a <= x
b_lt_b': x < b'.+1

~~ (a < b'.+1) -> False
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
HYP: search_arg a b' = None -> forall x : nat, a <= x < b' -> ~~ P (f x)
TRIV: None = None
x: nat
a_le_x: a <= x
b_lt_b': x < b'.+1
b'_lt_a: ~ a <= b'

False
by move: (leq_ltn_trans a_le_x b_lt_b').
T: Type
f: nat -> T
P: pred T
R: rel T
a, b: nat

(forall x : nat, a <= x < b -> ~~ P (f x)) -> search_arg a b = None
T: Type
f: nat -> T
P: pred T
R: rel T
a, b: nat

(forall x : nat, a <= x < b -> ~~ P (f x)) -> search_arg a b = None
T: Type
f: nat -> T
P: pred T
R: rel T
a, b: nat

(forall x : nat, a <= x < b -> ~~ P (f x)) -> (fix search_arg (a b : nat) {struct b} : option nat := if a < b then match b with | 0 => None | b'.+1 => match search_arg a b' with | Some x => if P (f b') && R (f b') (f x) then Some b' else Some x | None => if P (f b') then Some b' else None end end else None) a b = None
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat

((forall x : nat, a <= x < b' -> ~~ P (f x)) -> (fix search_arg (a b : nat) {struct b} : option nat := if a < b then match b with | 0 => None | b'.+1 => match search_arg a b' with | Some x => if P (f b') && R (f b') (f x) then Some b' else Some x | None => if P (f b') then Some b' else None end end else None) a b' = None) -> (forall x : nat, a <= x < b'.+1 -> ~~ P (f x)) -> (if a < b'.+1 then match (fix search_arg (a b : nat) {struct b} : option nat := if a < b then match b with | 0 => None | b'.+1 => match search_arg a b' with | Some x => if P (f b') && R (f b') (f x) then Some b' else Some x | None => if P (f b') then Some b' else None end end else None) a b' with | Some x => if P (f b') && R (f b') (f x) then Some b' else Some x | None => if P (f b') then Some b' else None end else None) = None
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
IND: (forall x : nat, a <= x < b' -> ~~ P (f x)) -> search_arg a b' = None
NOT_SAT: forall x : nat, a <= x < b'.+1 -> ~~ P (f x)

(if a < b'.+1 then match search_arg a b' with | Some x => if P (f b') && R (f b') (f x) then Some b' else Some x | None => if P (f b') then Some b' else None end else None) = None
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
IND: (forall x : nat, a <= x < b' -> ~~ P (f x)) -> search_arg a b' = None
NOT_SAT: forall x : nat, a <= x < b'.+1 -> ~~ P (f x)

search_arg a b' = None
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
IND: (forall x : nat, a <= x < b' -> ~~ P (f x)) -> search_arg a b' = None
NOT_SAT: forall x : nat, a <= x < b'.+1 -> ~~ P (f x)
(if a < b'.+1 then if P (f b') then Some b' else None else None) = None
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
IND: (forall x : nat, a <= x < b' -> ~~ P (f x)) -> search_arg a b' = None
NOT_SAT: forall x : nat, a <= x < b'.+1 -> ~~ P (f x)

search_arg a b' = None
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
IND: (forall x : nat, a <= x < b' -> ~~ P (f x)) -> search_arg a b' = None
NOT_SAT: forall x : nat, a <= x < b'.+1 -> ~~ P (f x)
x: nat
a_le_x: a <= x
x_lt_n: x < b'

~~ P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
IND: (forall x : nat, a <= x < b' -> ~~ P (f x)) -> search_arg a b' = None
NOT_SAT: forall x : nat, a <= x < b'.+1 -> ~~ P (f x)
x: nat
a_le_x: a <= x
x_lt_n: x < b'

a <= x < b'.+1
by apply /andP; split.
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
IND: (forall x : nat, a <= x < b' -> ~~ P (f x)) -> search_arg a b' = None
NOT_SAT: forall x : nat, a <= x < b'.+1 -> ~~ P (f x)

(if a < b'.+1 then if P (f b') then Some b' else None else None) = None
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
IND: (forall x : nat, a <= x < b' -> ~~ P (f x)) -> search_arg a b' = None
NOT_SAT: forall x : nat, a <= x < b'.+1 -> ~~ P (f x)
a_lt_b: a < b'.+1

(if P (f b') then Some b' else None) = None
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
IND: (forall x : nat, a <= x < b' -> ~~ P (f x)) -> search_arg a b' = None
NOT_SAT: forall x : nat, a <= x < b'.+1 -> ~~ P (f x)
a_lt_b: a < b'.+1

P (f b') = false
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
IND: (forall x : nat, a <= x < b' -> ~~ P (f x)) -> search_arg a b' = None
NOT_SAT: forall x : nat, a <= x < b'.+1 -> ~~ P (f x)
a_lt_b: a < b'.+1

~~ P (f b')
T: Type
f: nat -> T
P: pred T
R: rel T
a, b': nat
IND: (forall x : nat, a <= x < b' -> ~~ P (f x)) -> search_arg a b' = None
NOT_SAT: forall x : nat, a <= x < b'.+1 -> ~~ P (f x)
a_lt_b: a < b'.+1

a <= b' < b'.+1
by apply /andP; split. } Qed. (* Conversely, if we know that [f] satisfies [P] for at least one point in the search space, then [search_arg] yields some point. *)
T: Type
f: nat -> T
P: pred T
R: rel T

forall a b : nat, (exists x : nat, a <= x < b /\ P (f x)) -> exists y : nat, search_arg a b = Some y
T: Type
f: nat -> T
P: pred T
R: rel T

forall a b : nat, (exists x : nat, a <= x < b /\ P (f x)) -> exists y : nat, search_arg a b = Some y
T: Type
f: nat -> T
P: pred T
R: rel T
a, b: nat
H_exists: exists x : nat, a <= x < b /\ P (f x)

exists y : nat, search_arg a b = Some y
T: Type
f: nat -> T
P: pred T
R: rel T
a, b: nat
H_exists: exists x : nat, a <= x < b /\ P (f x)
SEARCH: search_arg a b = None

exists y : nat, None = Some y
T: Type
f: nat -> T
P: pred T
R: rel T
a, b: nat
H_exists: exists x : nat, a <= x < b /\ P (f x)

search_arg a b = None -> exists y : nat, None = Some y
T: Type
f: nat -> T
P: pred T
R: rel T
a, b: nat
H_exists: exists x : nat, a <= x < b /\ P (f x)
NOT_exists: forall x : nat, a <= x < b -> ~~ P (f x)

exists y : nat, None = Some y
T: Type
f: nat -> T
P: pred T
R: rel T
a, b: nat
H_exists: exists x : nat, a <= x < b /\ P (f x)
NOT_exists: forall x : nat, a <= x < b -> ~~ P (f x)

False
T: Type
f: nat -> T
P: pred T
R: rel T
a, b: nat
NOT_exists: forall x : nat, a <= x < b -> ~~ P (f x)
x: nat
RANGE: a <= x < b
Pfx: P (f x)

False
by move: (NOT_exists x RANGE) => /negP not_Pfx. Qed. (* Since [search_arg] considers only points at which [f] satisfies [P], if it returns a point, then that point satisfies [P]. *)
T: Type
f: nat -> T
P: pred T
R: rel T

forall a b x : nat, search_arg a b = Some x -> P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T

forall a b x : nat, search_arg a b = Some x -> P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, b, x: nat

search_arg a b = Some x -> P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n: nat
IND: search_arg a n = Some x -> P (f x)

search_arg a n.+1 = Some x -> P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n: nat
IND: search_arg a n = Some x -> P (f x)

(if a < n.+1 then match search_arg a n with | Some x => if P (f n) && R (f n) (f x) then Some n else Some x | None => if P (f n) then Some n else None end else None) = Some x -> P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n: nat
IND: search_arg a n = Some x -> P (f x)
a_lt_Sn: (a < n.+1) = true

match search_arg a n with | Some x => if P (f n) && R (f n) (f x) then Some n else Some x | None => if P (f n) then Some n else None end = Some x -> P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n: nat
IND: search_arg a n = Some x -> P (f x)

(a < n.+1) = true -> match search_arg a n with | Some x => if P (f n) && R (f n) (f x) then Some n else Some x | None => if P (f n) then Some n else None end = Some x -> P (f x)
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n: nat
IND: search_arg a n = Some x -> P (f x)
a_lt_Sn: (a <= n) = true

match search_arg a n with | Some x => if P (f n) && R (f n) (f x) then Some n else Some x | None => if P (f n) then Some n else None end = Some x -> P (f x)
destruct (search_arg a n) as [q|] eqn:REC; destruct (P (f n)) eqn:Pfn => //=; [elim: (R (f n) (f q)) => // |]; by move=> x_is; injection x_is => <-. Qed. (* Since [search_arg] considers only points within a given range, if it returns a point, then that point lies within the given range. *)
T: Type
f: nat -> T
P: pred T
R: rel T

forall a b x : nat, search_arg a b = Some x -> a <= x < b
T: Type
f: nat -> T
P: pred T
R: rel T

forall a b x : nat, search_arg a b = Some x -> a <= x < b
T: Type
f: nat -> T
P: pred T
R: rel T
a, b, x: nat

search_arg a b = Some x -> a <= x < b
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n: nat
IND: search_arg a n = Some x -> a <= x < n

search_arg a n.+1 = Some x -> a <= x < n.+1
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n: nat
IND: search_arg a n = Some x -> a <= x < n

(if a < n.+1 then match search_arg a n with | Some x => if P (f n) && R (f n) (f x) then Some n else Some x | None => if P (f n) then Some n else None end else None) = Some x -> a <= x < n.+1
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n: nat
IND: search_arg a n = Some x -> a <= x < n
a_lt_Sn: (a < n.+1) = true

match search_arg a n with | Some x => if P (f n) && R (f n) (f x) then Some n else Some x | None => if P (f n) then Some n else None end = Some x -> a <= x < n.+1
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n: nat
IND: search_arg a n = Some x -> a <= x < n

(a < n.+1) = true -> match search_arg a n with | Some x => if P (f n) && R (f n) (f x) then Some n else Some x | None => if P (f n) then Some n else None end = Some x -> a <= x < n.+1
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n: nat
IND: search_arg a n = Some x -> a <= x < n
a_lt_Sn: (a <= n) = true

match search_arg a n with | Some x => if P (f n) && R (f n) (f x) then Some n else Some x | None => if P (f n) then Some n else None end = Some x -> a <= x < n.+1
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n, q: nat
REC: search_arg a n = Some q
IND: Some q = Some x -> a <= x < n
a_lt_Sn: (a <= n) = true

(if R (f n) (f q) then Some n else Some q) = Some x -> a <= x < n.+1
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n, q: nat
REC: search_arg a n = Some q
IND: Some q = Some x -> a <= x < n
a_lt_Sn: (a <= n) = true
Some q = Some x -> a <= x < n.+1
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n: nat
REC: search_arg a n = None
IND: None = Some x -> a <= x < n
a_lt_Sn: (a <= n) = true
Some n = Some x -> a <= x < n.+1
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n, q: nat
REC: search_arg a n = Some q
IND: Some q = Some x -> a <= x < n
a_lt_Sn: (a <= n) = true

(if R (f n) (f q) then Some n else Some q) = Some x -> a <= x < n.+1
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n, q: nat
REC: search_arg a n = Some q
IND: Some q = Some x -> a <= x < n
a_lt_Sn: (a <= n) = true
x_is: Some q = Some x

a <= x < n.+1
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n, q: nat
REC: search_arg a n = Some q
IND: Some q = Some x -> a <= x < n
a_lt_Sn: (a <= n) = true
x_is: Some q = Some x
a_le_x: a <= x
x_lt_n: x < n

a <= x < n.+1
by apply /andP; split.
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n, q: nat
REC: search_arg a n = Some q
IND: Some q = Some x -> a <= x < n
a_lt_Sn: (a <= n) = true

Some q = Some x -> a <= x < n.+1
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n, q: nat
REC: search_arg a n = Some q
IND: Some q = Some x -> a <= x < n
a_lt_Sn: (a <= n) = true
x_is: Some q = Some x

a <= x < n.+1
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n, q: nat
REC: search_arg a n = Some q
IND: Some q = Some x -> a <= x < n
a_lt_Sn: (a <= n) = true
x_is: Some q = Some x
a_le_x: a <= x
x_lt_n: x < n

a <= x < n.+1
by apply /andP; split.
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n: nat
REC: search_arg a n = None
IND: None = Some x -> a <= x < n
a_lt_Sn: (a <= n) = true

Some n = Some x -> a <= x < n.+1
T: Type
f: nat -> T
P: pred T
R: rel T
a, x, n: nat
REC: search_arg a n = None
IND: None = Some x -> a <= x < n
a_lt_Sn: (a <= n) = true
x_is: Some n = Some x

a <= x < n.+1
by injection x_is => <-; apply /andP; split. Qed. (* Let us assume that [R] is a reflexive and transitive total order... *) Hypothesis R_reflexive: reflexive R. Hypothesis R_transitive: transitive R. Hypothesis R_total: total R. (* ...then [search_arg] yields an extremum w.r.t. to [a, b), that is, if [search_arg] yields a point x, then [R (f x) (f y)] holds for any [y] in the search range [a, b) that satisfies [P]. *)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R

forall a b x : nat, search_arg a b = Some x -> forall y : nat, a <= y < b -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R

forall a b x : nat, search_arg a b = Some x -> forall y : nat, a <= y < b -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, b, x: nat
SEARCH: search_arg a b = Some x

forall y : nat, a <= y < b -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat

search_arg a n.+1 = Some x -> forall y : nat, a <= y < n.+1 -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat

(if a < n.+1 then match search_arg a n with | Some x => if P (f n) && R (f n) (f x) then Some n else Some x | None => if P (f n) then Some n else None end else None) = Some x -> forall y : nat, a <= y < n.+1 -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a < n.+1) = true

match search_arg a n with | Some x => if P (f n) && R (f n) (f x) then Some n else Some x | None => if P (f n) then Some n else None end = Some x -> forall y : nat, a <= y < n.+1 -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat

(a < n.+1) = true -> match search_arg a n with | Some x => if P (f n) && R (f n) (f x) then Some n else Some x | None => if P (f n) then Some n else None end = Some x -> forall y : nat, a <= y < n.+1 -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true

match search_arg a n with | Some x => if P (f n) && R (f n) (f x) then Some n else Some x | None => if P (f n) then Some n else None end = Some x -> forall y : nat, a <= y < n.+1 -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, Some q = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true

(if R (f n) (f q) then Some n else Some q) = Some x -> forall y : nat, a <= y < n.+1 -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, Some q = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = false
Some q = Some x -> forall y : nat, a <= y < n.+1 -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
REC: search_arg a n = None
IND: forall x : nat, None = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
Some n = Some x -> forall y : nat, a <= y < n.+1 -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, Some q = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true

(if R (f n) (f q) then Some n else Some q) = Some x -> forall y : nat, a <= y < n.+1 -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true

(if R (f n) (f q) then Some n else Some q) = Some x -> forall y : nat, a <= y < n.+1 -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
REL: R (f n) (f q) = true
some_x_is: Some n = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
EQ: y = n

R (f n) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
REL: R (f n) (f q) = true
some_x_is: Some n = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n
R (f n) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
REL: R (f n) (f q) = false
some_x_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
EQ: y = n
R (f q) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
REL: R (f n) (f q) = false
some_x_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n
R (f q) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
REL: R (f n) (f q) = true
some_x_is: Some n = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
EQ: y = n

R (f n) (f y)
by rewrite EQ; apply (R_reflexive (f n)).
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
REL: R (f n) (f q) = true
some_x_is: Some n = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n

R (f n) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
REL: R (f n) (f q) = true
some_x_is: Some n = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n

R (f q) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
REL: R (f n) (f q) = true
some_x_is: Some n = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n
HOLDS: a <= y < n -> P (f y) -> R (f q) (f y)

R (f q) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
REL: R (f n) (f q) = true
some_x_is: Some n = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n
HOLDS: a <= y < n -> P (f y) -> R (f q) (f y)

a <= y < n
by apply /andP; split.
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
REL: R (f n) (f q) = false
some_x_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
EQ: y = n

R (f q) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
REL: R (f n) (f q) = false
some_x_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
EQ: y = n

R (f q) (f n)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
REL: R (f n) (f q) = false
some_x_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
EQ: y = n
R_nq: R (f n) (f q)

R (f q) (f n)
by move: REL => /negP.
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
REL: R (f n) (f q) = false
some_x_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n

R (f q) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
REL: R (f n) (f q) = false
some_x_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n
HOLDS: a <= y < n -> P (f y) -> R (f q) (f y)

R (f q) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, search_arg a n = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
REL: R (f n) (f q) = false
some_x_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n
HOLDS: a <= y < n -> P (f y) -> R (f q) (f y)

a <= y < n
by apply /andP; split.
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, Some q = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = false

Some q = Some x -> forall y : nat, a <= y < n.+1 -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, Some q = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = false
some_q_is: Some q = Some x
y: nat
a_le_y: a <= y
y_lt_Sn: y < n.+1
Pfy: P (f y)

R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, Some q = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = false
some_q_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)

y < n.+1 -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, Some q = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = false
some_q_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)

y <= n -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, Some q = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = false
some_q_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
EQ: y = n

R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, Some q = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = false
some_q_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n
R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, Some q = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = false
some_q_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
EQ: y = n

R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, Some q = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = false
some_q_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
EQ: y = n

False
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, Some q = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
some_q_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
EQ: y = n
Pfn: ~ P (f n)

False
by subst.
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, Some q = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = false
some_q_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n

R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n, q: nat
REC: search_arg a n = Some q
IND: forall x : nat, Some q = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = false
some_q_is: Some q = Some x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n

a <= y < n
by apply /andP; split.
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
REC: search_arg a n = None
IND: forall x : nat, None = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true

Some n = Some x -> forall y : nat, a <= y < n.+1 -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
REC: search_arg a n = None
IND: forall x : nat, None = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
some_n_is: Some n = Some x

forall y : nat, a <= y < n.+1 -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
REC: search_arg a n = None
IND: forall x : nat, None = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
some_n_is: Some n = Some x
n_is: n = x

forall y : nat, a <= y < n.+1 -> P (f y) -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
REC: search_arg a n = None
IND: forall x : nat, None = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
some_n_is: Some n = Some x
n_is: n = x
y: nat
a_le_y: a <= y
y_lt_Sn: y < n.+1
Pfy: P (f y)

R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
REC: search_arg a n = None
IND: forall x : nat, None = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
some_n_is: Some n = Some x
n_is: n = x
y: nat
a_le_y: a <= y
Pfy: P (f y)

y < n.+1 -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
REC: search_arg a n = None
IND: forall x : nat, None = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
some_n_is: Some n = Some x
n_is: n = x
y: nat
a_le_y: a <= y
Pfy: P (f y)

y <= n -> R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
REC: search_arg a n = None
IND: forall x : nat, None = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
some_n_is: Some n = Some x
n_is: n = x
y: nat
a_le_y: a <= y
Pfy: P (f y)
EQ: y = n

R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
REC: search_arg a n = None
IND: forall x : nat, None = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
some_n_is: Some n = Some x
n_is: n = x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n
R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
REC: search_arg a n = None
IND: forall x : nat, None = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
some_n_is: Some n = Some x
n_is: n = x
y: nat
a_le_y: a <= y
Pfy: P (f y)
EQ: y = n

R (f x) (f y)
by rewrite -n_is EQ; apply (R_reflexive (f n)).
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
REC: search_arg a n = None
IND: forall x : nat, None = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
some_n_is: Some n = Some x
n_is: n = x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n

R (f x) (f y)
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
REC: search_arg a n = None
IND: forall x : nat, None = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
some_n_is: Some n = Some x
n_is: n = x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n

False
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
IND: forall x : nat, None = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
some_n_is: Some n = Some x
n_is: n = x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n

search_arg a n = None -> False
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
IND: forall x : nat, None = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
some_n_is: Some n = Some x
n_is: n = x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n
NONE: forall x : nat, a <= x < n -> ~~ P (f x)

False
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
IND: forall x : nat, None = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
some_n_is: Some n = Some x
n_is: n = x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n
NONE: forall x : nat, a <= x < n -> ~~ P (f x)
not_Pfy: a <= y < n -> ~~ P (f y)

False
T: Type
f: nat -> T
P: pred T
R: rel T
R_reflexive: reflexive (T:=T) R
R_transitive: transitive (T:=T) R
R_total: total (T:=T) R
a, n: nat
IND: forall x : nat, None = Some x -> forall y : nat, a <= y < n -> P (f y) -> R (f x) (f y)
x: nat
a_lt_Sn: (a <= n) = true
Pfn: P (f n) = true
some_n_is: Some n = Some x
n_is: n = x
y: nat
a_le_y: a <= y
Pfy: P (f y)
y_lt_n: y < n
NONE: forall x : nat, a <= x < n -> ~~ P (f x)
not_Pfy: ~~ P (f y)

False
by move: not_Pfy => /negP. Qed. End ArgSearch. Section ExMinn. (* We show that the fact that the minimal satisfying argument [ex_minn ex] of a predicate [pred] satisfies another predicate [P] implies the existence of a minimal element that satisfies both [pred] and [P]. *)

forall (P : nat -> Prop) (pred : nat -> bool) (ex0 : exists n : nat, pred n), P (ex_minn (P:=pred) ex0) -> exists n : nat, P n /\ pred n /\ (forall n' : nat, pred n' -> n <= n')

forall (P : nat -> Prop) (pred : nat -> bool) (ex0 : exists n : nat, pred n), P (ex_minn (P:=pred) ex0) -> exists n : nat, P n /\ pred n /\ (forall n' : nat, pred n' -> n <= n')
P: nat -> Prop
pred: nat -> bool
ex: exists n : nat, pred n

P (ex_minn (P:=pred) ex) -> exists n : nat, P n /\ pred n /\ (forall n' : nat, pred n' -> n <= n')
P: nat -> Prop
pred: nat -> bool
ex: exists n : nat, pred n
H: P (ex_minn (P:=pred) ex)

pred (ex_minn (P:=pred) ex)
P: nat -> Prop
pred: nat -> bool
ex: exists n : nat, pred n
H: P (ex_minn (P:=pred) ex)
forall n' : nat, pred n' -> ex_minn (P:=pred) ex <= n'
all: have MIN := ex_minnP ex; move: MIN => [n Pn MIN]; auto. Qed. (* As a corollary, we show that if there is a constant [c] such that [P c], then the minimal satisfying argument [ex_minn ex] of a predicate [P] is less than or equal to [c]. *)

forall (P : nat -> bool) (exP : exists n : nat, P n) (c : nat), P c -> ex_minn (P:=P) exP <= c

forall (P : nat -> bool) (exP : exists n : nat, P n) (c : nat), P c -> ex_minn (P:=P) exP <= c
P: nat -> bool
exP: exists n : nat, P n
c: nat
EX: P c

ex_minn (P:=P) exP <= c
P: nat -> bool
exP: exists n : nat, P n
c: nat
EX: P c
GT: c < ex_minn (P:=P) exP

False
P: nat -> bool
exP: exists n : nat, P n
c: nat
EX: P c
n: nat
LT: c < n
Pn: P n
MIN: forall n' : nat, P n' -> n <= n'

False
P: nat -> bool
exP: exists n : nat, P n
c: nat
EX: P c
n: nat
LT: c < n
Pn: P n
MIN: n <= c

False
by move: MIN; rewrite leqNgt; move => /negP MIN; apply: MIN. Qed. End ExMinn.