Skip to Content.
Sympa Menu

coq-club - Re: [Coq-Club] Termination for three argument addition function on natural numbers

coq-club AT inria.fr

Subject: The Coq mailing list

List archive

Re: [Coq-Club] Termination for three argument addition function on natural numbers


Chronological Thread 
  • From: mukesh tiwari <mukeshtiwari.iiitm AT gmail.com>
  • To: coq-club AT inria.fr
  • Subject: Re: [Coq-Club] Termination for three argument addition function on natural numbers
  • Date: Wed, 22 Sep 2021 16:02:45 +1000
  • Authentication-results: mail2-smtp-roc.national.inria.fr; spf=None smtp.pra=mukeshtiwari.iiitm AT gmail.com; spf=Pass smtp.mailfrom=mukeshtiwari.iiitm AT gmail.com; spf=None smtp.helo=postmaster AT mail-ed1-f54.google.com
  • Ironport-hdrordr: A9a23:vO/W5Kw07dIXBni1s8oOKrPwKb1zdoMgy1knxilNoHxuH/Bw9vre+MjzsCWftN9/Yh4dcLy7WZVoIkmskKKdg7NhXotKNTOO0ACVwZlZgbcKqAeBJ8SRzIBgPN9bAspD4FqbNykcsS59ijPIdeod/A==
  • Ironport-phdr: A9a23:BlExzx0N1yEdH8rEsmDOTwQyDhhOgF0UFjAc5pdvsb9SaKPrp82kYBaHo6Q0xwKWFazgqNt8w9LMtK7hXWFSqb2gi1slNKJ2ahkelM8NlBYhCsPWQWfyLfrtcjBoVJ8aDAwt8H60K1VaF9jjbFPOvHKy8SQSGhLiPgZpO+j5AIHfg9qr2+yo/5DffgpEiTq/bLhvMBi4sALdu9UMj4B/MKgx0BzJonVJe+RS22xlIE+Ykgj/6Mmt4pNt6jxctP09+cFOV6X6ZLk4QqdDDDs6KWA15dbkugfFQACS+3YTSGQWkh5PAwjY8BH3W4r6vyXmuuZh3iSRIMv7Rq02Vzu/9admUBDniCkFODA5/m/ZidF+grxHrx+6vRNz35TZbZuJOPZifK7Qe84RS2pbXsZWUixMGoa8b5YMD+UfJuZYr5T2p0cPrRqwHwasHuLvwSJPi3/zwK060PouERrG3Aw8HtIPvm7brM/0NKsIUOC1zajIzSnGb/5N1jf97ZLHchElof2WQb1wds/RxFApGgjYgVqetZbrMCmJ1uQRrWeb9exgWPqxhmAotg1/rSSiytowhoTLh48YyVLJ+yplzYg1K9C1R1N3bMOrHZdOuC+UOYR4T8AtTm12pio3yaMLtYOmcSULzpks2h3Ra+SffoSW/h7uUPydLDR4iX5/Zr6zmxW//VKgx+DzUMS/zUxEoTBfktbWs3AAzxzT5daDSvt65kqh3CyA1wHX6u1dP087iLfXJ4cvwrMwmZcfq0vDHijxmEX5iK+ZaF8o9fSv6+Tiernmp5mcOJFoigzmLKgihsiyDf47PwUORWSX5/iw2b758UD5T7hGlvg2nbPYsJDeK8QbvKm5AwpN34Ym9ha/DCmp0M8YnXkbLVJEdgiIj5LoO13UIfD4DPa/g0ipkDpwyPDGO6fuApTJLnTZjLjherN951ZGyAUv1dBf+45UCrYZLf3vXU/xrcXUAQM9Mwyp2OnqE85914MbWWKXGKCVKqLSsVmS5uIuOeaAfoEVuCyuY8QisvXplDoynUIXVaivx5oeLn6iTdp8JEDMZGfvj8wBWXsLoQMkTaS+jUCBXCVTe3etVrg9oDA6CZ6jJYjGT4GpxreG2XHoTdVtemlaBwXUQj/TfIKeVqJUAMpzCspokzhBWLT4DoF8iVehswj1z7chJe3RqHVwXXfL29185umVnhY3p2Qc5yu13GSETmUylWQNFWZe4Q==

Hi Wilayat,

Indeed, it should be p instead of 0. Good catch!

Best,
Mukesh

On Wed, Sep 22, 2021 at 3:51 PM Wilayat Khan <wilayatk AT gmail.com> wrote:
Hello All

Just to clear myself, should not the recursive call in the last case include the third argument p? Such as
| S n', S m' => S (S (three_add n' m' p))

Best, 

Wilayat

On Wed, Sep 22, 2021 at 4:59 AM mukesh tiwari <mukeshtiwari.iiitm AT gmail.com> wrote:
Thanks Dominique for the excellent answer!

"Btw, I wondered if there is a reason for you not to implement the tail recursive version, ie three_add (S n) (S m) p = three_add n m (S (S p)) ?" Nothing in particular. The original poster hasn't mentioned the reason for three argument sum, but now that you mentioned it it might be the case that the OP was looking for a constant-space sum function.

Best,
Mukesh




On Tue, Sep 21, 2021 at 5:37 PM Dominique Larchey-Wendling <dominique.larchey-wendling AT loria.fr> wrote:
Dear Mukesh,

As Robbert already explained, exactly one of the fixpoint arguments must decrease
structurally (always the same on every sub-call). I see that you worked out
the induction on a measure tactic. If you do not want to use + for your measure,
you could alternatively proceed by lexicographic induction on the first two
arguments, ie Acc lex2 (n,m) instead of Acc lt (n+m); see below.

Notice that the well-foundedness of lex2 is proved by nested induction so
this somewhat closed to what Robbert proposed but you do not get exactly
the same extraction if the function itself is nested.

Btw, I wondered if there is a reason for you not to implement the tail recursive
version, ie three_add (S n) (S m) p = three_add n m (S (S p)) ?

Combined, this would give the code below, with fully spec'ed add_three to
get the properties you want from your definition.

Best,

Dominique

Require Import Arith Lia Extraction.

Inductive lex2 : nat*nat -> nat*nat -> Prop :=
  | in_lex2_0 x y n m : x < y -> lex2 (x,n) (y,m)
  | in_lex2_1 x n m : n < m -> lex2 (x,n) (x,m).

Fact lex2_wf : well_founded lex2.
Proof.
  intros (x,y); revert y.
  induction x as [ x IHx ] using (well_founded_induction lt_wf).
  induction y as [ y IHy ] using (well_founded_induction lt_wf).
  constructor.
  intros (n,m); inversion 1; subst; auto.
Qed.

Section def.

  Let Fixpoint add_three (n m p : nat) {H : Acc lex2 (n,m)} : { r | r = n + m + p }.
  Proof.
    refine (
      match n as n' return n = n' -> _ with
        | 0 => fun Hn => match m as m' return m = m' -> _ with
          | 0    => fun Hm => exist _ p _
          | S m' => fun Hm => let (r,Hr) := add_three 0 m' (S p) _ in exist _ r _
        end eq_refl
        | S n' => fun Hn => match m as m' return m = m' -> _ with
          | 0    => fun Hm => let (r,Hr) := add_three n' 0 (S p) _ in exist _ r _
          | S m' => fun Hm => let (r,Hr) := add_three n' m' (S (S p)) _ in exist _ r _
        end eq_refl
      end eq_refl); try lia.
    all: subst; apply Acc_inv with (1 := H); 
           try (constructor 1; auto; fail); 
           constructor 2; auto.
  Qed.

  Definition three_add n m p := proj1_sig (@add_three n m p (lex2_wf (n,m))).

  Fact three_add_spec n m p : three_add n m p = n + m + p.
  Proof. apply (proj2_sig (@add_three _ _ _ _)). Qed.

End def.

Extraction three_add.



De: "mukesh tiwari" <mukeshtiwari.iiitm AT gmail.com>
À: "coq-club" <coq-club AT inria.fr>
Envoyé: Mardi 21 Septembre 2021 08:09:36
Objet: [Coq-Club] Termination for three argument addition function on natural numbers
Why does the Coq termination checker complain that it cannot guess the decreasing argument for the three_add function? How can I convince Coq that it terminates, without using the well founded argument (see add_three). (I tried few variants of add_three but it did not work)

Fail Fixpoint three_add (n m p : nat) : nat :=
match n, m with
| 0, 0 => p
| S n', 0 => S (three_add n' 0 p)
| 0, S m' => S (three_add 0 m' p)
| S n', S m' => S (S (three_add n' m' 0))
end.

The command has indeed failed with message: Cannot guess decreasing argument of fix.

More context: someone, in the Zulip Coq channel, has asked about an addition function on natural numbers, albeit with three arguments, so I wrote three_add but the termination checker did not like it. Therefore, I ended up writing one, which I recently learnt from Dominique, but it seems overkill for a simple function like three_add. Moreover, it relies on the Coq's addition function (+ in Acc lt (n + m)), so I would not call it a (perfect) solution, so my question is: is it possible to define three_add without any additional machinery?

Definition add_three (n m p : nat) : nat.
 refine((fix add_three n m p (H: Acc lt (n + m)) {struct H} :=
 match n as n' return n = n' -> _ with
 | 0 =>
 match m as m' return m = m' -> _ with
 | 0 => fun Hm Hn => p
 | S m' => fun Hm Hn => S (add_three 0 m' p _)
 end eq_refl
 | S n' =>
 match m as m' return m = m' -> _ with
 | 0 => fun Hm Hn => S (add_three n' 0 p _)
 | S m' => fun Hm Hn => S (S (add_three n' m' p _))
 end eq_refl
 end eq_refl) n m p _).
 subst. apply Acc_inv with (1 := H).
 abstract lia.
 subst. apply Acc_inv with (1 := H).
 abstract lia.
 subst. apply Acc_inv with (1 := H).
 abstract lia.
 apply lt_wf.
Defined.


Best,
Mukesh




Archive powered by MHonArc 2.6.19+.

Top of Page