Problem #2 Solution
Infinite valleys ->
LPO
Given f : nat -> bool
, we can define the binary sequence which determines whether or not a true
has occured at or below x
in f
as follows:
Fixpoint true_below(f : nat -> bool)(x : nat) : bool :=
match x with
|0 => f 0
|S y => f x || true_below f y
end.
We can then turn that into a decreasing function nat -> nat
as follows:
Definition to_nat(f : nat -> bool) : nat -> nat := fun x => if f x then 0 else 1.
Lemma to_nat_decr : forall f, decr (to_nat (true_below f)).
If we are assuming that any decreasing function has an infinite valley somewhere, we can look at the value an infinite valley (at, say, x0
) takes for to_nat (true_below f))
. If it is 0
, then we know that f
has a true
somewhere, using the following lemma:
Lemma true_below_correct1 : forall f x, true_below f x = true -> exists y, f y = true.
If it is 1
, then we can conclude that f
is everywhere false
as follows: if f x = true
for some x
, then true_below f y = true
for any y
greater than x
:
Lemma true_below_correct2 : forall f x y, true_below f x = true -> x <= y -> true_below f y = true.
We can then prove that true_below f (max x0 x)
has to be both false
and true
, a contradiction.
LPO ->
Infinite valleys
The strategy here for finding an infinite valley is much the same as our strategy for finding an n
-valley in problem 1: Inducting on f 0
, start at 0
, look if the value of f
ever drops. If it doesn’t, we’re done. If it does, then use the inductive hypothesis. Of course, the key problem for us is that you can’t generally tell if a function’s value ever drops. However, we can if we have the LPO.
Given f : nat -> nat
, we can produce a boolean-valued function that signifies whether or not f
strictly decreases at a given point:
Definition Slt(f : nat -> nat) : nat -> bool :=
fun x => match lt_dec (f (S x)) (f x) with
|left _ => true
|right _ => false
end.
(lt_dec
is Coq’s standard proof of the decidability of <
)
Using LPO, we can then check if Slt f
has a true
or not. If it does, then the value of f
does drop; if not, then f
is constant. This is expressed in the following two lemmas:
Lemma Slt_correct1 : forall f, decr f -> (forall x, Slt f x = false) -> forall x, f x = f 0.
Lemma Slt_correct2 : forall f, decr f -> forall y, Slt f y = true -> f (S y) < f 0.