open import Data.Nat using (ℕ;suc;zero)
open import Data.Rational
open import Data.Product
open import Relation.Nullary
open import Data.Bool using (Bool;false;true)
halve : ℕ → ℚ
halve zero = 1ℚ
halve (suc p) = ½ * halve p
∃-halve : ∀ {a b} → 0ℚ < a → a < b → ∃[ p ] (halve p * b < a)
∃-halve {a} {b} 0<a a<b = h 1 where
h : ℕ → ∃[ p ] (halve p * b < a)
h p with halve p * b <? a
h p | .true because ofʸ b'<a = p , b'<a
h p | .false because ofⁿ ¬b'<a = h (suc p)
The termination checker fails in that last case and it is no wonder as the recursion obviously is neither well funded nor structural. Nevertheless, I am quite sure this should be valid, but have no idea how to prove the termination of ∃-halve
. Any advice for how this might be done?
When you’re stuck on a lemma like this, a good general principle is to forget Agda and its technicalities for a minute. How would you prove it in ordinary human-readable mathematical prose, in as elementary way as possible?
Your “iterated halving” function is computing b/(2^p). So you’re trying to show: for any positive rationals a, b, there is some natural p such that b/(2^p) < a. This inequality is equivalent to 2^p > b/a. You can break this down into two steps: find some natural n ≥ b/a, and then find some p such that 2^p > n.
As mentioned in comments, a natural way to do find such numbers would be to implement the ceiling function and the log_2 function. But as you say, those would be rather a lot of work, and you don’t need them here; you just need existence of such numbers. So you can do the above proof in three steps, each of which is elementary enough for a self-contained Agda proof, requiring only very basic algebraic facts as background:
Lemma 1: for any rational q, there’s some natural n > q. (Proof: use the definition of the ordering on rationals, and a little bit of algebra.)
Lemma 2: for any natural n, there’s some natural p such that 2^p > n. (Proof: take e.g. p := (n+1); prove by induction on n that 2^(n+1) > n.)
Lemma 3: these together imply the theorem about halving that you wanted. (Proof: a bit of algebra with rationals, showing that the b/(2^p) < a is equivalent to 2^p > b/a, and showing that your iterated-halving function gives b/2^p.)