Prove a constant is even - coq

Given the inductive definition of evenness, how is it best proved that, say, 1024 is an even number?
Repeating apply even_S down to zero is certainly not the right approach.

As HTNW pointed out, you can use Ltac automation to produce such a proof. This has the disadvantage of producing a large proof term even_S (even_S ... even_O), thus slowing down proofs. In this case, it is better to reformulate the goal using a boolean decision procedure:
Fixpoint evenb (n : nat) : bool :=
match n with
| 0 => true
| 1 => false
| S (S m) => evenb m
end.
Lemma evenb_correct : forall n, evenb n = true <-> even n.
(* Fun exercise! *)
Coq can prove that evenb 1024 = true simply by evaluating the left-hand side:
Goal (even 1024). apply evenb_correct. reflexivity. Qed.

Repeating apply even_S is not the way. repeat apply even_S is. If even_S is a constructor, there's also repeat constructor.
Inductive even : nat -> Prop :=
| even_O : even O
| even_S : forall n, even n -> even (S (S n)).
Goal (even 1024). repeat apply even_S. exact even_O. Qed.
Goal (even 1024). repeat constructor. Qed. (* also finds even_O, would leave as goal otherwise *)

Related

proof of adding 1 to some number changes the parity in Coq

I defined even as:
Inductive even : nat -> Prop :=
| ev0: even O
| evSS: forall n, even n -> even (S (S n)).
But now I want to prove:
Lemma add1_diff (x: nat) : even (S x) = ~even x.
Can I prove:
even (S O) = (~ even O)
Thanks in advance.
You usually can't prove the equality of two Props. An equality in Prop means that the proof terms for a logical statement are equal. This is sometimes the case, but rarely. Here are a few examples:
Require Import PeanoNat.
Import Nat.
Inductive even : nat -> Prop :=
| ev0: even O
| evSS: forall n, even n -> even (S (S n)).
Example ex1 (n : nat) : (n >= 1) = (1 <= n).
Proof.
(* The proofs are equal because >= is defined in terms of <= *)
reflexivity.
Qed.
Example ex2: even (2+2) = even 4.
Proof.
(* The proofs are equal because 2+2 can be reduced to 4 *)
reflexivity.
Qed.
Example ex3 (n : nat) : even (2+n) = even (n+2).
Proof.
(* The proofs are equal because 2+n is equal to n+2 *)
rewrite add_comm.
reflexivity.
Qed.
Example ex4 (n : nat): even (S (S n)) = even n.
Proof.
(* The proofs cannot be equal, because the left side proof always
requires one evSS constructor more than the right hand side. *)
Abort.
For this reason one uses the equivalence of two Props, which is <->, rather than the equality. The equivalence of the last statement is provable:
Example ex4 (n : nat): even (S (S n)) <-> even n.
Proof.
split; intros H.
- inversion H.
assumption.
- constructor.
assumption.
Qed.
So to answer your question: the equality of the two statements is most likely not provable, but the equivalence is. In case you need help with that, please ask.
No, you cannot prove your goal: natively there is basically no way to prove equality of propositions. What you can do instead is to use propositional equivalence, rather than equality, that is prove
even (S 0) <-> ~ (even 0)
or more generally
Lemma add1_diff (x : nat) : even (S x) <-> ~ (even x)

Some help dealing with inject/unject and vector types

I'm reading through CPDT while doing the readings and exercises from Pierce's course here: https://www.cis.upenn.edu/~bcpierce/courses/670Fall12/
This question relates to HW10 here: https://www.cis.upenn.edu/~bcpierce/courses/670Fall12/HW10.v
Here's the code up to my question
Require Import Arith Bool List.
Require Import CpdtTactics MoreSpecif.
Set Implicit Arguments.
(* Length-Indexed Lists *)
Section ilist.
Variable A : Set.
Inductive ilist : nat -> Set :=
| Nil : ilist O
| Cons : forall n, A -> ilist n -> ilist (S n).
Definition ilength n (l : ilist n) := n.
Fixpoint app n1 (ls1 : ilist n1)
n2 (ls2 : ilist n2)
: ilist (n1 + n2) :=
match ls1
(*in (ilist n1) return (ilist (n1 + n2))*)
with
| Nil => ls2
| Cons _ x ls1' => Cons x (app ls1' ls2)
end.
(* Coq automatically adds annotations to the
definition of app. *)
Print app.
Fixpoint inject (ls : list A) : ilist (length ls) :=
match ls with
| nil => Nil
| h :: t => Cons h (inject t)
end.
Print inject.
Fixpoint unject n (ls : ilist n) : list A :=
match ls with
| Nil => nil
| Cons _ h t => h :: unject t
end.
Theorem inject_inverse : forall ls,
unject (inject ls) = ls.
induction ls; crush.
Qed.
(* Exercise (20 min) : Prove the opposite, that inject (unject ls) = ls.
You cannot state this theorem directly, since ls : ilist n
and inject (unject ls) : ilist (length (unject ls)).
One approach is to define an alternative version of equality ilist_eq
on ilists and prove that the equality holds under this definition.
If you do this, prove that ilist_eq is an equivalence relation (and try
to automate the proof).
Another more involved approach is to prove that n = length (unject ls)
and then to define a function that, given (ls : ilist n) and a
proof that m = n, produces an ilist m. In this approach you may
find proof irrelevance convenient.
*)
Because I really want to better understand dependent types and how to use proofs in programs, I decided to try to do the latter. Here is what I have so far.
Definition ilists_sizechange (n1 n2:nat) (l1:ilist n1) (P:n1=n2): ilist n2.
subst.
assumption.
Defined.
Lemma ilists_size_equal: forall n (ls:ilist n), n = length (unject ls).
Proof.
intros.
induction ls.
reflexivity.
simpl.
auto.
Qed.
Theorem unject_inject_thehardway: forall n (ls:ilist n),
inject (unject ls) = ilists_sizechange ls (ilists_size_equal ls).
Proof.
intros.
induction ls.
simpl.
?????????????????
Qed.
When I get to "?????????????????" that's where I'm stuck. I have a target like Nil = ilists_sizechange Nil (ilists_size_equal Nil) and I'm not really sure what I can do here.
I tried writing ilists_sizechange as a more direct function, but failed to do so. Not sure how to massage the type checking.
I guess I'm curious first if this approach is fruitful, or if I'm making some fundamental mistake. I'm also curious what the most concise way of expressing inject (unject ls) = ilists_sizechange ls (ilists_size_equal ls). is...here there are two custom functions (the sizechange and the proof of equality), and one imagines it should be possible with just one.
Coq is great but the syntax around dependently types stuff can be tricky. I appreciate any help!
Edit: I realize that an inductive type or something expressing equality of two lists and then building up and showing the sizes are equal is probably easier (eg the first suggestion they have), but I want to understand this case because I can imagine running into these sorts of issues in the future and I want to know how to work around them.
Edit2: I was able to make it past the Nil case using the following
dep_destruct (ilists_size_equal Nil).
compute.
reflexivity.
But then get stuck on the Cons case...I will try to prove some theorems and see if I can't get there, but I think I'm still missing something conceptual here.
Although functions may depend on proof objects, one approach (I'm going to show below) is to define the functions so that they don't use the proof objects except to construct other proof objects and to eliminate absurd cases, ensuring that opaque proofs never block computation. Another approach is to fully embrace dependently typed programming and the unification of "proofs as programs", but that's a much bigger paradigm shift to explain, so I'm not going to do that.
Starting with ilists_sizechange, we now care about the shape of the term constructed by tactics, so not all tactics are allowed. Not wanting to use the equality proof rules out the tactic subst. Instead we can recurse (induction) on the list l1 and pattern-match (destruct) on the natural number n2; there are four cases:
two absurd ones, which can be eliminated by using the equality (discriminate)
the 0 = 0 case, where you can just construct the empty list
the S m1 = S m2 case, where you can construct Cons, use the induction hypothesis (i.e., recursive call), and then you are asked for a proof of m1 = m2, which is where you can fall back to regular reasoning without caring what the proof term looks like.
Definition ilists_sizechange (n1 n2:nat) (l1:ilist n1) (P:n1=n2): ilist n2.
Proof.
revert n2 P. (* Generalize the induction hypothesis. *)
induction l1; destruct n2; discriminate + constructor; auto.
Defined.
While the rest of the proof below would technically work with that definition, it is still not ideal because any computation would unfold ilist_sizechange into an ugly function. While we've been careful to give that function the "right" computational behavior, tactic-based programming tends to be sloppy about some finer details of the syntax of those functions, which makes later proofs where they appear hard to read.
To have it look nicer in proofs, one way is to define a Fixpoint with the refine tactic. You write down the body of the function in Gallina, and put underscores for the proof terms, which become obligations that you have to prove separately. refine is not the only way to perform this technique, there's also the Program Fixpoint command and the Equations plugin. I would recommend looking into Equations. I stick with refine out of familiarity.
As you can see, intuitively all this function does is deconstruct the list l1, indexed by n1, and reconstruct it with index n2.
Fixpoint ilists_sizechange (n1 n2 :nat) (l1:ilist n1) {struct l1} : n1 = n2 -> ilist n2.
Proof.
refine (
match l1, n2 with
| Nil, 0 => fun _ => Nil
| Cons x xs, S n2' => fun EQ => Cons x (ilists_sizechange _ _ xs _)
| _, _ => fun _ => _
end
); try discriminate.
auto.
Defined.
The proof of ilists_size_equal needs no modification.
Lemma ilists_size_equal: forall n (ls:ilist n), n = length (unject ls).
Proof.
intros.
induction ls.
reflexivity.
simpl.
auto.
Qed.
For the final proof, there is one more step: first generalize the equality proof.
The idea is that ilists_sizechange doesn't actually look at it, but when it makes a recursive call it will need to construct some other proof, and this generalization allows you to use the induction hypothesis independently of that particular proof.
Theorem unject_inject_ : forall n (ls:ilist n) (EQ : n = length (unject ls)),
inject (unject ls) = ilists_sizechange ls EQ.
Proof.
intros n ls; induction ls; cbn.
- reflexivity.
- intros EQ. f_equal. apply IHls. (* Here we have ilists_sizechange applied to some big proof object, which we can ignore because the induction hypothesis generalizes over all such proof objects *)
Qed.
Then you want to specialize that theorem to use a concrete proof, ensuring that such a proof exists so the theorem is not vacuous.
Theorem unject_inject : forall n (ls:ilist n),
inject (unject ls) = ilists_sizechange ls (ilists_size_equal _).
Proof.
intros; apply unject_inject_.
Qed.
Here is one solution:
(* Length-Indexed Lists *)
Require Import Coq.Lists.List.
Import ListNotations.
Section ilist.
Variable A : Set.
Inductive ilist : nat -> Set :=
| Nil : ilist O
| Cons : forall {n}, A -> ilist n -> ilist (S n).
Fixpoint inject (ls : list A) : ilist (length ls) :=
match ls with
| nil => Nil
| h :: t => Cons h (inject t)
end.
Fixpoint unject {n} (ls : ilist n) : list A :=
match ls with
| Nil => nil
| Cons h t => h :: unject t
end.
Definition cast {A B : Set} (e : A = B) : A -> B :=
match e with eq_refl => fun x => x end.
Fixpoint length_unject n (l : ilist n) : length (unject l) = n :=
match l with
| Nil => eq_refl
| Cons _ l => f_equal S (length_unject _ l)
end.
Theorem unject_inverse n (ls : ilist n) :
cast (f_equal ilist (length_unject _ ls)) (inject (unject ls)) = ls.
Proof.
induction ls as [|n x l IH]; simpl; trivial.
revert IH.
generalize (inject (unject l)).
generalize (length_unject _ l).
generalize (length (unject l)).
intros m e.
destruct e.
simpl.
intros; congruence.
Qed.
End ilist.
The trick is to make your goal sufficiently general, and then to destruct the equality. The generalization is required to ensure that your goal is well-typed after destructing; failing to generalize will often lead to dependent-type errors.
Here, I've defined the length lemma by hand to be able to use the reduction machinery. But you could also have used proof irrelevance to get the proof to reduce to eq_refl after the fact.

How to make coq simplify expressions inside an implication hypothesis

Im trying to prove the following lemma:
Inductive even : nat → Prop :=
| ev_0 : even 0
| ev_SS (n : nat) (H : even n) : even (S (S n)).
Lemma even_Sn_not_even_n : forall n,
even (S n) <-> not (even n).
Proof.
intros n. split.
+ intros H. unfold not. intros H1. induction H1 as [|n' E' IHn].
- inversion H.
- inversion_clear H. apply IHn in H0. apply H0.
+ unfold not. intros H. induction n as [|n' E' IHn].
-
Qed.
Here is what I got at the end:
1 subgoal (ID 173)
H : even 0 -> False
============================
even 1
I want coq to evaluate "even 0" to true and "even 1" to false. I tried simpl, apply ev_0 in H. but they give an error. What to do?
Answer to the title
simpl in H.
Real answer
The above code will not work.
The definition of even from the Logical Foundations book is:
Inductive even : nat → Prop :=
| ev_0 : even 0
| ev_SS (n : nat) (H : even n) : even (S (S n)).
even 0 is a Prop, not a bool. Looks like you're mixing up the types True and False and the booleans true and false. They're totally different things, and not interchangeable under Coq's logic. In short, even 0 does not simplify to true or True or anything. It is just even 0. If you want to show even 0 is logically true, you should construct a value of that type.
I don't remember which tactics are available at that point in LF, but here are some possibilities:
(* Since you know `ev_0` is a value of type `even 0`,
construct `False` from H and destruct it.
This is an example of forward proof. *)
set (contra := H ev_0). destruct contra.
(* ... or, in one step: *)
destruct (H ev_0).
(* We all know `even 1` is logically false,
so change the goal to `False` and work from there.
This is an example of backward proof. *)
exfalso. apply H. apply ev_0.

How to apply theorems for definitions with restrictions in coq

I found a number of examples of definitions with restrictions in coq. Here is for example a variation of the pred function:
Lemma Lemma_NotZeroIsNotEqualToZero : ~ 0 <> 0.
Proof.
omega.
Qed.
Definition pred (s : { n : nat | n <> 0 }) : nat :=
match s with
| exist 0 pf => match (Lemma_NotZeroIsNotEqualToZero pf) with end
| exist (S n') _ => n'
end.
But I don't actually understand how to use this definition. Suppose I want to use pred for some natural number and I proved that this number is not zero. Like, for instance, suppose I proved the following lemma:
Lemma Lemma_TenIsNotEqualToZero : 10 <> 0.
Proof.
omega.
Qed.
Now, I want to compute what in essence is "pred 10" using Lemma_TenIsNotEqualToZero:
Eval compute in (pred ??).
How to do it?
pred is a function taking a sig type (try to Print sig.). Simply put, it's an inductive type with one constructor stating that "there exists an x of type A such that P x is true".
If you want to create a term of type {n : nat | n <> 0}, you will have to build it using constructors, like any other inductive type. In your case:
Eval compute in (pred (exist 10 Lemma_TenIsNotEqualToZero)).
It is the exact same syntax you used to pattern match on the s argument of pred.
Hope it helps,
V
PS: using omega for both your proofs is really overkill...
Lemma Lemma_NotZeroIsNotEqualToZero : ~ 0 <> 0.
Proof.
intro h.
apply h; reflexivity.
Qed.
Lemma Lemma_TenIsNotEqualToZero : 10 <> 0.
Proof.
intro h.
discriminate h.
Qed.
Edit: exists takes 3 arguments in practice (use Print to get a clear idea what are they used for). Depending on the status of implicit types, you should write
exists _ 10 Lemma_TenIsNotEqualToZero
with the additional _.

Using remember in induction over proposition gives 'ill-typed' error in Coq

Here are the inductive & computational definitions of evenness of natural numbers.
Inductive ev : nat -> Prop :=
| ev_0 : ev O
| ev_SS : forall n:nat, ev n -> ev (S (S n)).
Definition even (n:nat) : Prop :=
evenb n = true.
And the proof that one implies the other.
Theorem ev__even : forall n,
ev n -> even n.
intros n E.
induction E as [ | n' E' ].
reflexivity. apply IHE'. Qed.
I didn't think much of this proof at first, but on a closer look I find something troubling. The problem is that after the reflexivity step, I expect to see the context
1 subgoal
n' : nat
E : ev (S (S n'))
E' : ev n'
IHE' : ev n' -> even n'
====================================================================== (1/1)
even (S (S n'))
But what I actually get instead is
1 subgoal
n' : nat
E' : ev n'
IHE' : even n'
====================================================================== (1/1)
even (S (S n'))
Although the theorem is still provable as is, it is disturbing to see hypotheses mysteriously disappear. I'd like to know how to get the context I initially expected. From web searches I understand that this is a general problem with induction over constructed terms in Coq. One proposed solution on SO suggests using the remember tactic on hypotheses to be kept. But when I try that in this proof,
Theorem ev__even : forall n,
ev n -> even n.
intros n E.
remember E.
induction E as [ | n' E' ].
I get the following error message at the induction step.
Error: Abstracting over the term "n" leads to a term
"fun n : nat => forall e : ev n, e = E -> even n" which is ill-typed.
Which I do not really understand. I think the problem is that E has a free variable, but in that case I would be stuck, since there is no way to introduce E without also introducing n. (generalize dependent n would generalize E with it)
Is there any way to obtain the initially expected context?
To be useful, the induction tactic tries to generalize over all variables that depend on the thing you are doing induction on, and things that depend on the indices of its type. In your case, this implies generalizing over n, the newly generated proof e : ev n, and the equality e = E. However, it does not generalize over E itself, because the induction principles that are automatically generated for propositions ignore the proof argument. Unfortunately, this means that that generalization will be ill-typed, and your intuition is correct: because E was not generalized with n, its type will mention a different number, which will make the equality e = E ill-typed.
I don't understand what the induction tactic is doing here.
Whenever I don't understand what a tactic is doing, I try to just write the proof term myself.
If you invoke the induction principle by hand, you can keep the original hypothesis:
Theorem ev__even : forall n, ev n -> even n.
intros n E.
refine (ev_ind even _ _ n E).
- reflexivity.
- intros n' E' IH.
apply IH.
Qed.
This is what the context looks like in the second case of the induction:
n : nat
E : ev n
n' : nat
E' : ev n'
IH : even n'
============================
even (S (S n'))
Assuming
Fixpoint evenb (n:nat) : bool :=
match n with
| O => true
| S O => false
| S (S n') => evenb n'
end.