Compute if in a decideable prop in coq - coq

I want to write a function that calculate count of true values of p 0 .. p t in a nat->prop function.
Section count_sc.
Variable p:nat->Prop.
Hypothesis p_dec:forall x:nat , {p x} + { ~ p x }.
Fixpoint count (x : nat) :=
match x with
| 0 => if p_dec(0) then 1 else 0
| S y => if p_dec(x) then 1+count y else count y
end.
End count_sc.
Definition fret (x:nat) := False.
Check count.
Axiom fret_dec : forall x : nat , { fret x } + { ~ fret x }.
Theorem hello_decide : forall x : nat , count fret fret_dec x = 0.
Proof.
intros.
induction x.
unfold count.
replace (fret_dec 0) with false.
Qed.
Before the replace tactic i should proof some goal like this:
(if fret_dec 0 then 1 else 0) = 0
Coq dose not automaticly compute the value of the if statement. and if i try to replace the fret_dec with it's value, i will get this error:
Error: Terms do not have convertible types.
How i can write count function that i can unfold and use it in theorems?

You have declared fret_dec as an axiom. But that means it does not have a definition, or implementation in other words. Thus, Coq cannot compute with it.
You can still prove your theorem like so, using the destruct tactic:
Theorem hello_decide : forall x : nat , count fret fret_dec x = 0.
Proof.
induction x as [| x IH].
- unfold count. destruct (fret_dec 0) as [contra | _].
+ contradiction.
+ reflexivity.
- simpl. rewrite IH. destruct (fret_dec (S x)) as [contra | _].
+ contradiction.
+ reflexivity.
Qed.
But, in this case it is really easy to provide such a decision procedure instead of postulating it. And this simplifies the proof a lot:
Definition fret_dec' (x : nat) : { fret x } + { ~ fret x }.
Proof. right. intros contra. contradiction. Defined.
Theorem hello_decide' : forall x : nat , count fret fret_dec' x = 0.
Proof.
induction x as [|x IH]; simpl.
- reflexivity.
- exact IH.
Qed.

Related

Proving S (n + m) = n + (S m), how to rewrite n+1 = S(n)?

Theorem add_0_r : forall n:nat, n + 0 = n.
Proof.
intros n. induction n as [| n' IHn'].
- (* n = 0 *) reflexivity.
- (* n = S n' *) simpl. rewrite -> IHn'. reflexivity. Qed.
Theorem plus_n_Sm : forall n m : nat,
S (n + m) = n + (S m).
Proof.
intros n m. induction m as [| m' IHn']. rewrite -> add_0_r. rewrite <- sum.
The last tactic rewirte <- sum does not work. This is the goal:
n: ℕ
-------------
S(n) = n + 1
I don't know how to rewrite n+1 as S(n). I think that n+1 is just a notation for S(n), right?
If you look at the definition of + as follows, you can see that it is defined by induction on its first argument:
Locate "+". (* to obtain the name Nat.add *)
Print Nat.add.
(*
Nat.add =
fix add (n m : nat) {struct n} : nat :=
match n with
| 0 => m
| S p => S (add p m)
end
: nat -> nat -> nat
*)
As a result 1 + n is indeed convertible to S n (you can see that using Eval cbn in 1 + ?[n].) but not n + 1 (if you unfold Nat.add. you will obtain a pattern match stuck on the variable n).
For your proof, that specific definition of + means that you might reconsider your approach and try to do your proof by induction on n rather than m (paying attention to have the right induction hypothesis).
If you are using the nat type from the standard library, then n+1 is not a notation for S n, but a notation for the function Nat.add. In that case n+1 is not apparently equal to S n. You need to prove it by an induction on n.
By the way, if you are using Nat.nat, you need to use induction on n rather than m. Because Nat.add is defined by a match on the first argument. In this case, your first subgoal of the induction can be proved simply by reflexivity. (Coq is able to simplify S (0 + m) and 0 + S m, but not S (n + 0) and n + 1).
Was able to prove with the following:
Theorem plus_n_Sm : forall n m : nat,
S (n + m) = n + (S m).
Proof.
intros n m. induction n as [| n' IHn'].
- simpl. reflexivity.
- simpl. rewrite -> IHn'. reflexivity.
Qed.

Is it possible to prove oddb 0 = true?? coq

I have define an odd like this:
Inductive odd : nat -> Prop :=
| odd_1 : odd 1
| odd_S : forall n:nat, odd n -> odd (n + 1).
And below is testing if a number is odd or not.
Fixpoint oddb (n : nat) { struct n } : bool :=
match n with
| 0 => false
| 1 => true
| S (S n) => oddb n
end.
I am trying to prove this:
Theorem odd_is_odd:
forall n, (oddb n = true) -> odd n.
Proof.
intros n. induction n.
- simpl. intro H. exfalso. inversion H.
- intro H. rewrite s_is_plus_one. constructor. apply IHn. destruct n.
*
But i got stuck here... it needs me prove oddb 0 = true which is false = true.. is it possible???
1 subgoal
IHn : oddb 0 = true -> odd 0
H : oddb 1 = true
______________________________________(1/1)
oddb 0 = true
Below is the lemma I used
Lemma s_is_plus_one : forall n:nat, S n = n + 1.
Proof.
intros. induction n.
- reflexivity.
- simpl. rewrite <- IHn. reflexivity.
Qed.
Your definition of odd seems wrong. Is it not n+2. Anyway our problem
is related to
How to prove a odd number is the successor of double of nat in coq?

Proof irrelevance for boolean equality

I'm trying to prove group axioms for Z_3 type:
Require Import Coq.Arith.PeanoNat.
Record Z_3 : Type := Z3
{
n :> nat;
proof : (Nat.ltb n 3) = true
}.
Proposition lt_0_3 : (0 <? 3) = true.
Proof.
simpl. reflexivity.
Qed.
Definition z3_0 : Z_3 := (Z3 0 lt_0_3).
Proposition lt_1_3 : (1 <? 3) = true.
Proof.
reflexivity.
Qed.
Definition z3_1 : Z_3 := (Z3 1 lt_1_3).
Proposition lt_2_3 : (2 <? 3) = true.
Proof.
reflexivity.
Qed.
Definition z3_2 : Z_3 := (Z3 2 lt_2_3).
Proposition three_ne_0 : 3 <> 0.
Proof.
discriminate.
Qed.
Lemma mod_upper_bound_bool : forall (a b : nat), (not (eq b O)) -> (Nat.ltb (a mod b) b) = true.
Proof.
intros a b H. apply (Nat.mod_upper_bound a b) in H. case Nat.ltb_spec0.
- reflexivity.
- intros Hcontr. contradiction.
Qed.
Definition Z3_op (x y: Z_3) : Z_3 :=
let a := (x + y) mod 3 in
Z3 a (mod_upper_bound_bool _ 3 three_ne_0).
Lemma Z3_eq n m p q : n = m -> Z3 n p = Z3 m q.
Proof.
intros H. revert p q. rewrite H. clear H. intros. apply f_equal.
We are almost done:
1 subgoal (ID 41)
n, m : nat
p, q : (m <? 3) = true
============================
p = q
What theorem should I use to prove that p = q?
Update 1
Theorem bool_dec :
(forall x y: bool, {x = y} + {x <> y}).
Proof.
intros x y. destruct x.
- destruct y.
+ left. reflexivity.
+ right. intro. discriminate H.
- destruct y.
+ right. intro. discriminate H.
+ left. reflexivity.
Qed.
Lemma Z3_eq n m p q : n = m -> Z3 n p = Z3 m q.
Proof.
intros H. revert p q. rewrite H. clear H. intros. apply f_equal. apply UIP_dec. apply bool_dec.
Qed.
You are probably interested in knowing that every two proofs of a decidable equality are equal. This is explained and proved here: https://coq.inria.fr/library/Coq.Logic.Eqdep_dec.html
You are interested in particular in the lemma UIP_dec: https://coq.inria.fr/library/Coq.Logic.Eqdep_dec.html#UIP_dec
Theorem UIP_dec :
forall (A:Type),
(forall x y:A, {x = y} + {x <> y}) ->
forall (x y:A) (p1 p2:x = y), p1 = p2.
You will have then to prove that equalities of booleans are decidable (i.e. that you can write a function which says whether two given booleans are equal or not) which you should also be able to find in the standard library but which should be easily provable by hand as well.
This is a different question but since you asked: bool_dec exists and even has that name!
The easy way to find it is to use the command
Search sumbool bool.
It will turn up several lemmata, including pretty early:
Bool.bool_dec: forall b1 b2 : bool, {b1 = b2} + {b1 <> b2}
Why did I search sumbool? sumbool is the type which is written above:
{ A } + { B } := sumbool A B
You can find it using the very nice Locate command:
Locate "{".
will turn up
"{ A } + { B }" := sumbool A B : type_scope (default interpretation)
(and other notations involving "{").

Z_3: left id proof

I am close to ending the proof for Z_3 left id. Here is what I have so far
Require Import Coq.Arith.PeanoNat.
Require Import Coq.Bool.Bool.
Require Import Coq.Logic.Eqdep_dec.
Record Z_3 : Type := Z3
{
n :> nat;
proof : (Nat.ltb n 3) = true
}.
Proposition lt_0_3 : (0 <? 3) = true.
Proof.
simpl. reflexivity.
Qed.
Definition z3_0 : Z_3 := (Z3 0 lt_0_3).
Proposition lt_1_3 : (1 <? 3) = true.
Proof.
reflexivity.
Qed.
Definition z3_1 : Z_3 := (Z3 1 lt_1_3).
Proposition lt_2_3 : (2 <? 3) = true.
Proof.
reflexivity.
Qed.
Definition z3_2 : Z_3 := (Z3 2 lt_2_3).
Proposition three_ne_0 : 3 <> 0.
Proof.
discriminate.
Qed.
Lemma mod_upper_bound_bool : forall (a b : nat), b <> O -> (a mod b <? b) = true.
Proof.
intros a b H. apply (Nat.mod_upper_bound a b) in H. case Nat.ltb_spec0.
- reflexivity.
- intros Hcontr. contradiction.
Qed.
Definition Z3_op (x y: Z_3) : Z_3 :=
let a := (x + y) mod 3 in
Z3 a (mod_upper_bound_bool _ 3 three_ne_0).
Lemma Z3_eq n m p q : n = m -> Z3 n p = Z3 m q.
Proof.
intros H. revert p q. rewrite H. clear H. intros. apply f_equal. apply UIP_dec. apply bool_dec.
Qed.
Proposition Z3_left_id' : forall x: Z_3, (Z3_op z3_0 x) = x.
Proof.
intro. unfold Z3_op. destruct x as [n proof]. apply Z3_eq.
Result:
1 subgoal (ID 46)
n : nat
proof : (n <? 3) = true
============================
(z3_0 + {| n := n; proof := proof |}) mod 3 = n
I found the following theorems that could be useful:
Nat.ltb_spec0
: forall x y : nat, reflect (x < y) (x <? y)
Nat.mod_small: forall a b : nat, a < b -> a mod b = a
Is it possible to get rid of profs in the goal, convert proof from bool to Prop, and then use Nat.mod_small?
Update
Proposition Z3_left_id' : forall x: Z_3, (Z3_op z3_0 x) = x.
Proof.
intro. unfold Z3_op. destruct x as [vx proof]. apply Z3_eq. unfold n, z3_0. rewrite plus_O_n. apply Nat.mod_small.
1 subgoal (ID 67)
vx : nat
proof : (vx <? 3) = true
============================
vx < 3
You need the coercion to execute. Unfortunately,
by naming the bound variable of your proof n and the projection from Z_3 to nat n, you painted yourself in a corner.
Here are four solutions:
1/ this one I mention just for the record: you can talk about the constant n that was defined in this file by using the file name as a module qualifier.
unfold user4035_oct_16.n.
user4035_oct_16 is the name of the current file, this is ugly.
2/ you could call a computation function that computes everything, however computation of modulo leaves unsightly terms in the goal, so you could decide to not compute that particular part.
cbn -[Nat.modulo].
I like this one, but it requires that you spend sometime learning how to use cbn.
3/ You can avoid the name clash by renaming variables in the goal.
rename n into m.
unfold n, Z3_0.
Not very nice either.
4/ Just go back in your script and replace destruct x as [n proof] with destruct x as [vx proof], then you can type:
unfold n, z3_0.
you will be able to use the lemmas you suggest.
Proof:
Proposition Z3_left_id : forall x: Z_3, (Z3_op z3_0 x) = x.
Proof.
intro. unfold Z3_op. destruct x as [vx proof]. apply Z3_eq. unfold n, z3_0. rewrite plus_O_n. apply Nat.mod_small. apply Nat.ltb_lt in proof. assumption.
Qed.

Check less or equal natural number in coq

I have function (beq_nat_refl) which determines the equality of two natural numbers and gives a boolean. But now I want to prove a lemma stating that a natural number x is less or equal to x.
May I use the above function (beq_nat_refl)?
Theorem beq_nat_refl :
forall n : nat,
true = beq_nat n n.
Theorem leq_nat :
forall x:nat,
x <= x.
That would work if you would define x <= y as x < y || x == y; however this is not the definition, so usually the proof of x <= x tends to be induction [on the computational case] or by applying the base constructor if using a witness.
Here is a straightforward path to proving leq_nat from similar definitions:
Fixpoint leb (n m : nat) : bool :=
match n, m with
| 0 , _ => true
| _ , 0 => false
| S n, S m => leb n m
end.
Lemma leb_nat_refl : forall (n : nat), leb n n = true.
Proof.
induction n; simpl.
+ reflexivity.
+ assumption.
Qed.
Lemma leb_nat_reflect : forall (n : nat), leb n n = true <-> n <= n.
Proof.
induction n; simpl; split; intros.
+ constructor.
+ reflexivity.
+ constructor.
+ apply IHn. constructor.
Qed.
Theorem leq_nat : forall (n : nat), n <= n.
Proof.
intros.
apply leb_nat_reflect.
apply leb_nat_refl.
Qed.