Using Omega to prove a lemma in Coq
Question
I am trying to make a proof in Coq using Omega. I spent a lot of time on it, but nothing came to me. I have to say I am new in Coq, so I am not at ease with this kind of language, and I do not have much experience. But I am working on it.
Here's the code I have to prove:
Require Import Arith. Fixpoint div2 (n : nat) := match n with | S (S p) => S (div2 p) | _ => 0 end. Fixpoint mod2 (n : nat) := match n with | S (S p) => mod2 p | x => x end.
To make this proof, I thought it would help to prove by induction this lemma first:
forall n : nat, 2 * div2 n + mod2 n = n
Then this one, using omega and div2_eq:
forall n : nat, div2 n <= n
But I did not manage to go further.
Does anyone know what to do?
Answer
You can easily derive induction principles from the functions div2 and mod2 like so:
Require Import FunInd. Functional Scheme div2_ind := Induction for div2 Sort Prop. Functional Scheme mod2_ind := Induction for mod2 Sort Prop.
div2_ind and mod2_ind have more or less types:
To apply these theorems you can conveniently write functional induction (div2 n) or functional induction (mod2 n) where you might usually write induction n.
But a stronger induction principle is associated with these functions:
forall P1 : nat -> Prop, P1 0 -> P1 1 -> (forall n1 : nat, P1 n1 -> P1 (S (S n1))) -> forall n1 : nat, P1 n1forall P1 : nat -> Prop, P1 0 -> P1 1 -> (forall n1 : nat, P1 n1 -> P1 (S (S n1))) -> forall n1 : nat, P1 n1P1: nat -> Prop
H1: P1 0
H2: P1 1
H3: forall n1 : nat, P1 n1 -> P1 (S (S n1))forall n1 : nat, P1 n1P1: nat -> Prop
H1: P1 0
H2: P1 1
H3: forall n1 : nat, P1 n1 -> P1 (S (S n1))
H4: forall m : nat, m < 0 -> P1 mP1 0P1: nat -> Prop
H1: P1 0
H2: P1 1
H3: forall n1 : nat, P1 n1 -> P1 (S (S n1))
H4: forall m : nat, m < 1 -> P1 mP1 1P1: nat -> Prop
H1: P1 0
H2: P1 1
H3: forall n1 : nat, P1 n1 -> P1 (S (S n1))
n1: nat
H4: forall m : nat, m < S (S n1) -> P1 mP1 (S (S n1))P1: nat -> Prop
H1: P1 0
H2: P1 1
H3: forall n1 : nat, P1 n1 -> P1 (S (S n1))
H4: forall m : nat, m < 0 -> P1 mP1 0P1: nat -> Prop
H1: P1 0
H2: P1 1
H3: forall n1 : nat, P1 n1 -> P1 (S (S n1))
H4: forall m : nat, m < 1 -> P1 mP1 1P1: nat -> Prop
H1: P1 0
H2: P1 1
H3: forall n1 : nat, P1 n1 -> P1 (S (S n1))
n1: nat
H4: forall m : nat, m < S (S n1) -> P1 mP1 (S (S n1))Qed.
In fact, the domain of any function is a clue to a useful induction principle. For example, the induction principle associated to the domain of the functions plus : nat -> nat -> nat and mult : nat -> nat -> nat is just structural induction. Which makes me wonder why Functional Scheme doesn't just generate these more general principles instead.
In any case, the proofs of your theorems then become:
Require Import Lia.forall n : nat, 2 * div2 n + mod2 n = nforall n : nat, 2 * div2 n + mod2 n = n2 * div2 0 + mod2 0 = 02 * div2 1 + mod2 1 = 1n1: nat
H1: 2 * div2 n1 + mod2 n1 = n12 * div2 (S (S n1)) + mod2 (S (S n1)) = S (S n1)2 * div2 0 + mod2 0 = 0lia.0 = 02 * div2 1 + mod2 1 = 1lia.1 = 1n1: nat
H1: 2 * div2 n1 + mod2 n1 = n12 * div2 (S (S n1)) + mod2 (S (S n1)) = S (S n1)lia. Qed.n1: nat
H1: div2 n1 + (div2 n1 + 0) + mod2 n1 = n1S (div2 n1 + S (div2 n1 + 0) + mod2 n1) = S (S n1)forall n : nat, div2 n <= nforall n : nat, div2 n <= ndiv2 0 <= 0div2 1 <= 1n1: nat
H1: div2 n1 <= n1div2 (S (S n1)) <= S (S n1)div2 0 <= 0lia.0 <= 0div2 1 <= 1lia.0 <= 1n1: nat
H1: div2 n1 <= n1div2 (S (S n1)) <= S (S n1)lia. Qed.n1: nat
H1: div2 n1 <= n1S (div2 n1) <= S (S n1)
You should familiarize yourself with functional induction, but more importantly, you should really familiarize yourself with well-founded induction.