Search code examples
logiccoqmodulocoq-tactic

How in Coq to use mod arithmetic (specifically Zplus_mod theorem) for natural numbers?


I want to apply the library theorem:

Theorem Zplus_mod: forall a b n, (a + b) mod n = (a mod n + b mod n) mod n.

where a b n are expected to have the type Z.

I have a subexpression (a + b) mod 3 in my goal, with a b : nat.

rewrite Zplus_mod gives an error Found no subterm matching

rewrite Zplus_mod with (a := a) gives an error "a" has type "nat" while it is expected to have type "Z".

Since natural numbers are also integers, how to use Zplus_mod theorem for nat arguments?


Solution

  • You can't apply this theorem, because the notation mod refers to a function on natural numbers Nat.modulo in a context where you are using natural numbers, while the notation mod refers to Z.modulo when you are referring to integers of type Z.

    Using the Search command ou can search specifically for theorems about Nat.modulo and (_ + _)%nat and you will see that some existing theorems are actually close to your needs (Nat.add_mod_idemp_l and Nat.add_mod_idemp_r).

    You can also look for a theorem that links Z.modulo and Nat.modulo. This gives mod_Zmod. But this forces you to work in the type of integers:

    Require Import Arith ZArith.
    
    Search Z.modulo Nat.modulo.
    
     (* The answer is :  
        mod_Zmod: forall n m, m <> 0 -> Z.of_nat (n mod m) = 
           (Z.of_nat n mod Z.of_nat m)%Z  *)
    

    One way out is to find a theorem that tells you that the function Z.of_nat is injective. I found it by typing the following command.

    Search Z.of_nat "inj".
    

    In the long list that was produced, the relevant theorem is Nat2Z.inj, you then need to show how Z.of_nat interacts with all of the operators involved. Most of these theorems require n to be non-zero, so I add this as a condition. Here is the example.

    Lemma example (a b n : nat) : 
       n <> 0 -> (a + b) mod n = (a mod n + b mod n) mod n.
    Proof.
    intro nn0.
    apply Nat2Z.inj.
    rewrite !mod_Zmod; auto.
    rewrite !Nat2Z.inj_add.
    rewrite !mod_Zmod; auto.
    rewrite Zplus_mod.
    easy.
    Qed.
    

    This answers your question, but frankly, I believe you would be better off using the lemmas Nat.add_mod_idemp_l and Nat.add_mod_idemp_r.