[Agda] Nat for termination counter
Sergei Meshveliani
mechvel at botik.ru
Mon Dec 18 21:40:30 CET 2017
Dear all,
I have a certain doubt about using the counter of Nat for termination
proofs.
Consider the function for listing binary numbers:
----------------------------------------
pred : Bin → Bin
pred = fromBits ∘ minusCarry 1b ∘ toBits
downFrom : Bin → List Bin
downFrom 0# = [ 0# ]
downFrom (bs 1#) = (bs 1#) ∷ (downFrom (pred (bs 1#)))
----------------------------------------
Bin is intended to be used in order to avoid certain expensive
operations with Nat.
downFrom is fast, but it has termination problem.
It needs a terminating version which is also fast. I try:
---------------------------------------------------------------------
downFrom x = aux x (toℕ x) refl
where
aux : (x : Bin) → (cnt : ℕ) → toℕ x ≡ cnt → List Bin
aux 0# _ _ = [ 0# ]
aux (bs 1#) 0 bs1N≡0 = ⊥-elim (toℕ-bs1≢0 bs bs1N≡0)
aux (bs 1#) (suc cnt) bs1N≡cnt' = bs1 ∷ (aux (pred bs1) cnt eq)
where
bs1 = bs 1#
eq : toℕ (pred bs1) ≡ cnt
eq = begin toℕ (pred bs1) ≡⟨ toℕ-pred-homo bs1 ⟩
predN (toℕ bs1) ≡⟨ cong predN bs1N≡cnt' ⟩
predN (suc cnt) ≡⟨ refl ⟩
cnt
∎
---------------------------------------------------------------------
It applies a certain theorem of toℕ-pred-homo.
It also uses the toℕ conversion for the counter cnt, and the counter
serves termination proof.
I do not know how to avoid potentially large data for the counter
(never looked into sized types).
But I have an impression that here the usage of toℕ does not explode
the evaluation cost. Because
* the (suc cnt) data always appears fast from toℕ bs1 (?),
and the next counter is cnt,
* the cnt value is evaluated lazily, it never becomes large in memory
(?).
What people think of this?
As an experiment, I try
-------------------------
test : Bin → List String
test x =
"x = " ∷ showB x ∷
"\nxL = " ∷ showB xL ∷
[]
where
xs = downFrom x; xL = last 0# xs
-------------------------
- build x ∷ (pred x) ∷ pred (pred x) ∷ ... ∷ 0# ∷ []
and print the last elment (x is input from file).
Running this shows a linear cost order:
the time for (x *2) is 2 * (time for x).
How people think, is this a reliable approach?
Thanks,
------
Sergei
More information about the Agda
mailing list