How to use coercion with sig in coq - coq

I have a code like
Definition even := {n : nat | exists k, n = k + k}.
Definition even_to_nat (e : even) : nat.
Admitted.
Coercion even_to_nat : even >-> nat.
Example Ex : forall n : even, exists k, k + k = n.
Admitted.
Example Ex2 : forall k, exists n : even, k + k = n.
Admitted.
How should I remove Admitted in this case?
Also, why does
Example Ex' : forall n : even, exists k, n = k + k
not work even with coercion? Is there a nice way to remove such errors?

This is a definition for the even_to_nat function written in Gallina:
Definition even := {n : nat | exists k, n = k + k}.
Definition even_to_nat (e : even) : nat :=
match e with
| exist _ n _ => n
end.
Coercion even_to_nat : even >-> nat.
It pattern matches on e to retrieve the wrapped natural number n.
This is an equivalent implementation using tactics:
Definition even_to_nat_tac (e : even) : nat.
destruct e.
auto.
Defined.
The destruct tactic essentially pattern matches on e. Then, auto automatically uses the natural number inside to finish the definition.
Here is a Gallina implementation of your first example:
Example Ex : forall n : even, exists k, k + k = n :=
fun n => match n with
| exist _ n (ex_intro _ k eq) => ex_intro (fun k => k + k = n) k (eq_sym eq)
end.
Essentially, it pattern matches on n, retrieves the k and the proof that n = k + k, then uses eq_sym to flip the equality.
Here is an implementation for Ex2:
Example Ex2 : forall k, exists n : even, k + k = n :=
fun k =>
let n := k + k in
let exists_k := ex_intro (fun k => n = k + k) k eq_refl in
let even_nat := exist (fun n => exists k, n = k + k) n exists_k in
ex_intro (fun n => k + k = even_to_nat n) even_nat eq_refl.
exists_k is the proof contained inside an even number stating exists k, n + n = k. even_nat is an even number fulfilling the condition exists n, k + k = n, where n is obviously k + k. Finally, I inhabit the desired type. It seems that I can't use coercions here, so I explicitly use even_to_nat.
Alternatively, the coercion works if I add a type annotation:
Example Ex2 : forall k, exists n : even, k + k = n :=
fun k =>
let n := k + k in
let exists_k := ex_intro (fun k => n = k + k) k eq_refl in
let even_nat := exist (fun n => exists k, n = k + k) n exists_k in
ex_intro (fun (n : even) => k + k = n) even_nat eq_refl.
For your Ex' example, see the warning in this example from the coercion documentation. Given the coercion Coercion bool_in_nat : bool >-> nat.:
Note that Check (true = O) would fail. This is "normal" behavior of coercions. To validate true=O, the coercion is searched from nat to bool. There is none.
You can only coerce on the right side of the equality type, not the left.

Related

How to prove a odd number is the successor of double of nat in coq?

I have the odd number definition as below:
Definition Odd n := exists k, n = 2*k+1.
And I have an oddb define that whether 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 if a number is the successor of a double of nat; then it is a odd number.
Theorem question_1c:
forall n, Odd n -> (oddb n = true).
Proof.
unfold Odd. intros. inversion H.
rewrite H0. simpl. induction x.
- simpl. reflexivity.
- Admitted.
I stuck on the second goal.. it showed that I need to prove Sx.. and the hypothesis I have from now seems like not helpful...
1 subgoal
n : nat
H : exists k : nat, n = 2 * k + 1
x : nat
H0 : n = 2 * S x + 1
IHx : n = 2 * x + 1 -> oddb (x + (x + 0) + 1) = true
______________________________________(1/1)
oddb (S x + (S x + 0) + 1) = true
Can anyone help me?? tHnak you
Standard induction let you jump from n to n+1. Here with your odd function
you need to jump from n to n+2. So what is needed is a stronger induction. One way to do this is to prove:
Theorem question_1c:
forall n m, m <= n -> Odd m -> (oddb m = true).
by standard induction on n (but for all m smaller)

Rewrite match with single branch that doesn't depend on matched value

I want to show the following:
match H in (_ = y) return y with
| eq_refl => exist (fun n' : nat => n' < n) x0 l
end = exist (fun n' : nat => n' < n) x0 l
I have in my context:
H : ltn n = ltn n
n : nat
x0 : nat
l : x0 < n
Where
Definition ltn (n : nat) : Type := {n' | n' < n}.
I'm unable to destruct on H, because the resulting term would be ill-typed, but it seems clear the equality holds because the only possible branch from match does not depend on what's being matched.
The problem (as you said) is that Coq cannot destruct H, once it's a variable without "matchings" and the definition equality (that you are using) is based on normalization and string verification, you will not able to operate this. Anyway, without axioms, you can not destruct an equality instance, given that you are implying that all equalities are equals (definitional equals). The implication of considering all equalities as "equals" assumes that your core is extensionally typed. For the sake of compatibility with others type theories (like homotopy type theory), Coq doesn't allow you to mention UIP without as axiom. UIP axiom and K axiom are very related. You can just export the axioms from Coq standard library.
Theorem exact_eq : forall (n' n x0 : nat) (l : x0 < n) (H : {n' | n' < n} = {n' | n' < n}),
match H in (_ = y) return y with
| eq_refl => exist (fun n' : nat => n' < n) x0 l
end = exist (fun n' : nat => n' < n) x0 l.
intros.
(*UIP_refl : forall (H : x = x), H = erefl x*)
by set(#UIP_refl _ _ H); subst.
Qed.

even (n + m) -> even n /\ even m \/ odd n /\ odd m

How can I prove this lemma:
Lemma even_plus_split n m :
even (n + m) -> even n /\ even m \/ odd n /\ odd m.
These are the only libraries and definition that can be used:
Require Import Arith.
Require Import Coq.omega.Omega.
Definition even (n: nat) := exists k, n = 2 * k.
Definition odd (n: nat) := exists k, n = 2 * k + 1.
I am new to Coq and confused about it. Can you give me a solution? Thanks in advance!
the code so far:
Lemma even_plus_split n m :
even (n + m) -> even n /\ even m \/ odd n /\ odd m.
Proof.
intros.
unfold even.
unfold even in H.
destruct H as [k H].
unfold odd.
exists (1/2*k).
result so far:
1 subgoal
n, m, k : nat
H : n + m = 2 * k
______________________________________(1/1)
(exists k0 : nat, n = 2 * k0) /\ (exists k0 : nat, m = 2 * k0) \/
(exists k0 : nat, n = 2 * k0 + 1) /\ (exists k0 : nat, m = 2 * k0 + 1)
I just want to make k0 equals to 1/2*k, and therefore I suppose it would make sense, but I can't do that.
I just want to make k0 equals to 1/2*k, and therefore I suppose it would make sense, but I can't do that.
There is a function called Nat.div2, which divides a natural number by 2. Running Search Nat.div2.
Nat.le_div2: forall n : nat, Nat.div2 (S n) <= n
Nat.lt_div2: forall n : nat, 0 < n -> Nat.div2 n < n
Nat.div2_decr: forall a n : nat, a <= S n -> Nat.div2 a <= n
Nat.div2_wd: Morphisms.Proper (Morphisms.respectful eq eq) Nat.div2
Nat.div2_spec: forall a : nat, Nat.div2 a = Nat.shiftr a 1
Nnat.N2Nat.inj_div2: forall a : N, N.to_nat (N.div2 a) = Nat.div2 (N.to_nat a)
Nnat.Nat2N.inj_div2: forall n : nat, N.of_nat (Nat.div2 n) = N.div2 (N.of_nat n)
Nat.div2_double: forall n : nat, Nat.div2 (2 * n) = n
Nat.div2_div: forall a : nat, Nat.div2 a = a / 2
Nat.div2_succ_double: forall n : nat, Nat.div2 (S (2 * n)) = n
Nat.div2_odd: forall a : nat, a = 2 * Nat.div2 a + Nat.b2n (Nat.odd a)
Nat.div2_bitwise:
forall (op : bool -> bool -> bool) (n a b : nat),
Nat.div2 (Nat.bitwise op (S n) a b) = Nat.bitwise op n (Nat.div2 a) (Nat.div2 b)
Of these, the most promising seems to be Nat.div2_odd: forall a : nat, a = 2 * Nat.div2 a + Nat.b2n (Nat.odd a). If you pose proof this lemma, you can destruct (Nat.odd a) and use simpl to get that either a = 2 * Nat.div2 a or a = 2 * Nat.div2 a + 1, for whichever a you choose.
This may not give you a solution directly (I am not convinced that setting k0 to k / 2 is the right decision), but if it does not, you should make sure that you can figure out how to prove this fact on paper before you try it in Coq. Coq is very good at making sure that you don't make any jumps of logic that you're not allowed to make; it's extremely bad at helping you figure out how to prove a fact that you don't yet know how to prove.
Everybody who tries to answer seems to be dancing around the fact that you actually chose a wrong direction for this proof. Here is a example:
if n = 601 and m = 399, then n + m = 2 * 500,
n = 2 * 300 + 1, and m = 2 * 199 + 1.
Between 500, 300, and 199, the 1/2 ratio does not appear anywhere.
Still the statement (even n /\ even m) / (odd n /\ odd m) is definitely true.
So for now, you have more a math problem than a Coq problem.
You have to make a proof for universally quantified numbers n and m, but somehow this proof should also work for specific choices of these numbers. So in a sense you can make the mental exercise of testing your proof on examples.

Getting a stronger induction principle in Coq

Assume the following:
Inductive bin : Set := Z | O.
Fixpoint fib (n : nat) : list bin :=
match n with
| 0 => [Z]
| S k => match k with
| 0 => [O]
| S k' => fib k' ++ fib k
end
end.
I would like to show:
Theorem fib_first : forall n,
Nat.Even n -> n > 3 -> exists w, fib n = Z :: w.
However, by performing induction on n, I get a really useless inductive
hypothesis fixing n, stating that IH : Nat.Even n -> n > 3 -> exists w : list bin, fib n = Z :: w.
What I would ideally have is the following: IH : forall n : nat, Nat.Even n -> n > 3 -> exists w : list bin, fib n = Z :: w. Naturally I cannot assume the original proposition, but it feels like I need to prove something stronger perhaps?
My idea for the inductive reasoning would be made possible by expanding F n = F n-2 . F n-1, we know F n-2 is even iff F n is even, and since neither of F n-2 or F n-1 is empty, we can show the substring is shorter, therefore sufficient for the inductive hypothesis - how does one express this in Coq?
The trick is to unfold the definition of Nat.Even and do induction on n / 2 instead of n:
Theorem fib_first : forall n,
Nat.Even n -> exists w, fib n = Z :: w.
Proof.
intros n [m ->].
induction m as [|m IH].
- now exists nil.
- rewrite <- mult_n_Sm, plus_comm.
generalize (2 * m) IH. clear m IH. simpl.
intros n [w ->].
simpl. eauto.
Qed.
Note that your n > 3 hypothesis is not actually needed.

Convert ~exists to forall in hypothesis

I'm stuck in situation where I have hypothesis ~ (exists k, k <= n+1 /\ f k = f (n+2)) and wish to convert it into equivalent (I hope so) hypothesis forall k, k <= n+1 -> f k <> f (n+2).
Here is little example:
Require Import Coq.Logic.Classical_Pred_Type.
Require Import Omega.
Section x.
Variable n : nat.
Variable f : nat -> nat.
Hypothesis Hf : forall i, f i <= n+1.
Variable i : nat.
Hypothesis Hi : i <= n+1.
Hypothesis Hfi: f i = n+1.
Hypothesis H_nex : ~ (exists k, k <= n+1 /\ f k = f (n+2)).
Goal (f (n+2) <= n).
I tried to use not_ex_all_not from Coq.Logic.Classical_Pred_Type.
Check not_ex_all_not.
not_ex_all_not
: forall (U : Type) (P : U -> Prop),
~ (exists n : U, P n) -> forall n : U, ~ P n
apply not_ex_all_not in H_nex.
Error: Unable to find an instance for the variable n.
I don't understand what this error means, so as a random guess I tried this:
apply not_ex_all_not with (n := n) in H_nex.
It succeeds but H_nex is complete nonsense now:
H_nex : ~ (n <= n+1 /\ f n = f (n + 2))
On the other hand it is easy to solve my goal if H_nex is expressed as forall:
Hypothesis H_nex : forall k, k <= n+1 -> f k <> f (n+2).
specialize (H_nex i).
specialize (Hf (n+2)).
omega.
I found similar question but failed to apply it to my case.
If you want to use the not_ex_all_not lemma, what you want to proof needs to look like the lemma. E.g. you can proof the following first:
Lemma lma {n:nat} {f:nat->nat} : ~ (exists k, k <= n /\ f k = f (n+1)) ->
forall k, ~(k <= n /\ f k = f (n+1)).
intro H.
apply not_ex_all_not.
trivial.
Qed.
and then proof the rest:
Theorem thm (n:nat) (f:nat->nat) : ~ (exists k, k <= n /\ f k = f (n+1)) ->
forall k, k <= n -> f k <> f (n+1).
intro P.
specialize (lma P). intro Q.
intro k.
specialize (Q k).
tauto.
Qed.
I'm not quite sure what your problem is.
Here is how to show trivially that your implication holds.
Section S.
Variable n : nat.
Variable f : nat -> nat.
Hypothesis H : ~ (exists k, k <= n /\ f k = f (n+1)).
Goal forall k, k <= n -> f k <> f (n+1).
Proof.
intros k H1 H2.
apply H.
exists k.
split; assumption.
Qed.
End S.
Also your goal is provable by apply Hf., so I'm not sure but you seem to have some confusion...