[Agda] strange termination check
Sergei Meshveliani
mechvel at botik.ru
Sat Oct 12 11:42:15 CEST 2013
On Sat, 2013-10-12 at 14:33 +0900, Andreas Abel wrote:
> Unfortunately, the termination-depth-trick works only for natural
> numbers and sizes, not for lists and other data structures with a
> constructor that has more than one argument.
>
The consequence is that one does not know how to provide termination
without complications brought with inductive types.
For example, I tried to replace in the below example the step
(b ∷ b' ∷ bs) --> b' ∷ bs
with one-level step, by denoting b'' = b' :: bs ...
And failed.
Is this difficult (if correct) to implement in Agda, say,
"termination by a proper subterm" ?
> See my previous message
>
> https://lists.chalmers.se/pipermail/agda/2013/005855.html
>
> for an implementation of powerToPos that works.
The story is as follows.
My current aim is
(1) to have the binary exponentiation method powerToPos both for Bin
(Bin⁺) and for Nat,
(2) to provide a proof
powerEq : ... powerToPos x (suc n) == x ∙ (powerToPos x n)
for n : Bin⁺, Nat
(for Bin⁺, suc is converted to (addCarryToBitList 1b)).
I think that it is better to do all this first for Bin⁺, and then to
prove this for Nat by applying the conversions Nat <-> Bin⁺.
And the law (2) does not hold for your version of binPower
(probably, this can be tackled somehow).
So, I try another version: powerToPos, with the condition argument
(Positive bs) expressing "last bit is 1".
There I have a strange problem with the recursion step
(b ∷ b' ∷ bs) --> b' ∷ bs,
and ask:
"has it sense for Agda to generalize the termination condition
respectively?"
(also is it difficult to implement?).
Meanwhile, I modify the implementation for HasLast1 to
data Positive : Bin⁺ → Set -- "has last 1"
where
single : Positive (1b ∷ [])
cons : {b : Bit} → {bs : Bin⁺} → Positive bs → Positive (b ∷ bs)
And this helps with termination for powerToPos.
I do not know precisely, why, but probably because Agda sees the step of
(cons positive-bs) --> positive-bs
in another argument.
(In HasLast1, this argument was evaluated to b == 1b by normalization,
and this was not a constructor for a recursion step).
But this success is by occasion. In other examples the absence of an
automatic generalized recursion step will bite programmers.
Now, the proof for (2) for Bin⁺ is close to end. I hope to finish it,
and then hope that Nat <-> Bin⁺ will help.
Thanks,
------
Sergei
> On 2013-10-11 08:45, Sergei Meshveliani wrote:
> > On Thu, 2013-10-10 at 21:57 +0400, Sergei Meshveliani wr (b ∷ b' ∷ bs)ote:
> >> Please, why the below powerToPos is not checked as terminating ?
> >>
> >>
> >> {-# OPTIONS --termination-depth=3 #-}
> >> module Report where
> >> open import Level using () renaming (zero to 0ℓ)
> >> open import Function using (case_of_)
> >> open import Relation.Binary
> >> using (module Setoid; module
> >> IsEquivalence;_Preserves_⟶_)
> >> open import Relation.Binary.PropositionalEquality using (_≡_)
> >> open import Algebra using (Semigroup; module Semigroup)
> >> open import Data.Empty using (⊥)
> >> open import Data.List using ([]; _∷_)
> >> open import Data.Fin using (Fin) renaming (zero to 0b; suc to
> >> sucB)
> >> open import Data.Digit using (Bit)
> >> open import Data.Bin using (Bin⁺)
> >>
> >> 1b : Bit
> >> 1b = sucB 0b
> >>
> >> postulate H : Semigroup 0ℓ 0ℓ
> >>
> >> open Semigroup H using (setoid; _≈_; _∙_)
> >> renaming (Carrier to C; isEquivalence to
> >> ≈equiv)
> >> open IsEquivalence ≈equiv using ()
> >> renaming (refl to ≈refl; sym to ≈sym; trans to
> >> ≈trans)
> >>
> >> HasLast1 : Bin⁺ → Set -- "is the bit list of a non-zero
> >> binary"
> >> HasLast1 [] = ⊥
> >> HasLast1 (b ∷ []) = b ≡ 1b
> >> HasLast1 (_ ∷ b ∷ bs) = HasLast1 (b ∷ bs)
> >>
> >> powerToPos : C → (bs : Bin⁺) → HasLast1 bs → C
> >>
> >> [..]
> >
> >> The recursion (b ∷ b' ∷ bs) --> (b' ∷ bs)
> >>
> >> by the second argument is well-founded. Why does not the checker see
> >> the
> >> termination proof?
> >
> >
> > Sorry, the implementation needs to be
> >
> > powerToPos _ [] ()
> > powerToPos x (0b ∷ []) ()
> > powerToPos x (sucB 0b ∷ []) _ = x
> > powerToPos x (sucB (sucB ()) ∷ [])
> >
> > powerToPos x (b ∷ b' ∷ bs) last1-b:b':bs =
> > case b of \ { 0b → p ∙ p
> > ; (sucB 0b) → x ∙ (p ∙
> > p)
> > ; (sucB (sucB ()))
> > }
> > where
> > hl1 : HasLast1 (b' ∷ bs)
> > hl1 = last1-b:b':bs
> >
> > p = powerToPos x (b' ∷ bs) hl1
> >
> > -----------------------------------------------------------------------
> >
> > And again, I do not understand why is not it checked as terminating.
> >
> > Thanks,
> >
> > ------
> > Sergei
> >
> >
> > _______________________________________________
> > Agda mailing list
> > Agda at lists.chalmers.se
> > https://lists.chalmers.se/mailman/listinfo/agda
>
More information about the Agda
mailing list