I'm not sure how to apply the let expression in coq. This is from the selection sort example in PF.
Once the select function is defined, this lemma is proved.
Lemma select_perm: forall x l,
let (y,r) := select x l in
Permutation (x::l) (y::r).
These are some use cases to see how it works.
Compute select_perm 3 [10;32;4;6;5].
= select_perm 3 [10; 32; 4; 6; 5]
: let (y, r) := select 3 [10; 32; 4; 6; 5] in
Permutation [3; 10; 32; 4; 6; 5] (y :: r)
Compute select 3 [10; 32; 4; 6; 5].
= (3, [10; 32; 4; 6; 5])
: nat * list nat
How can I further evaluate this to expose the actual Permutation - something along the lines of Compute ((select_perm 3 [10;32;4;6;5]) (select 3 [10; 32; 4; 6; 5]))?
I'm not sure how to use this lemma in applying the below theorem.
Lemma selsort_perm:
forall n,
forall l, length l = n -> Permutation l (selsort l n).
Proof.
intros.
generalize dependent n.
induction l; intros.
- subst.
simpl.
constructor.
- subst. simpl.
destruct (select a l) eqn:?.
With the corresponding goals, I want to apply select_perm somehow (apply (select_perm a l)).
a : nat
l : list nat
IHl : forall n : nat, length l = n -> Permutation l (selsort l n)
n : nat
l0 : list nat
Heqp : select a l = (n, l0)
============================
Permutation (a :: l) (n :: selsort l0 (length l))
Or, correspondingly, prove via transitivity assert (Permutation (a :: l) (n :: l0)) and somehow bring the following Heqp into a let expression in with the new goal .
Is there an easy way to treat let expressions like function application in coq?
Edit:
I have found an adhoc alternative solution by modifying select_perm to select_perm'
Lemma select_perm': forall x l,
Permutation (x::l) ((fst (select x l)) :: (snd (select x l))).
And inducting over the length of the list rather than the list itself (can provide that code if necessary), but would rather just use Appel's original definition...
Yes, this is a tricky matter. Here is the structure I propose. To make a workable, self-example, I just assume the existence of functions select and selsort and of the relation Permutation.
I actually introduce in my goal the instance of the theorem that I wish to use (as you suggested), and then I can rewrite with Heqp. The last two lines are where things actually happen.
Require Import List.
Section playground.
Variable select : nat -> list nat -> nat * list nat.
Variable Permutation : list nat -> list nat -> Prop.
Lemma select_perm: forall x l,
let (y,r) := select x l in
Permutation (x::l) (y::r).
Proof.
Admitted.
Variable selsort : list nat -> nat -> list nat.
Lemma goal_at_hand (a : nat) (l : list nat)
(IHl : forall n : nat, length l = n -> Permutation l (selsort l n))
(n : nat) (l0 : list nat) (Heqp : select a l = (n, l0)):
Permutation (a :: l) (n :: selsort l0 (length l)).
Proof.
generalize (select_perm a l).
rewrite Heqp.
What makes this tricky is that Coq uses the let ... := ... in ... syntax, but this is actually a pattern-matching expression: you need the expression to be explicitly an application of the pair constructor for the let expression to transform itself in a simpler form.
The goal you obtain has the following shape, I suppose you need a lemma stating that Permutation is transitive to proceed.
Permutation (a :: l) (n :: l0) ->
Permutation (a :: l) (n :: selsort l0 (length l))
Related
I have less than relation between two index values and want to esteblish a relation between indexes. Have hypothesis - (nth i2 l d < nth i1 l d). There are two possibilities that (i2 < i1) or (i2> i1). I want to consider both cases. Plz guide me in writing this relation.
Use Nat.lt_gt_cases, which proves n < m \/ n > m given n <> m. In context, that would look like this
Require Import PeanoNat.
Goal forall (d : nat) (l : list nat) (n m : nat), nth n l d < nth m l d -> True.
intros d l n m prf.
assert (ineq : n <> m). (* hypothesis for lt_gt_cases *)
{ intros ->.
now apply Nat.lt_irrefl in prf.
}
destruct (proj1 (Nat.lt_gt_cases n m) ineq) as [ord | ord].
(* two goals left, one with n < m and the other with m > n *)
I have a Contradictory statements in hypothesis. Want to convert it into true=false. Thanks for guidence in advance. Here is code
n < current_value 0 (n :: l)
current_value 0 (n :: l)<= n.
The question could be a lot more complete. What is the type of n? I'll assume that it is nat.
Starting like this:
Lemma manual:
forall current_value n l P,
n < current_value 0 (n :: l) ->
current_value 0 (n :: l) <= n ->
P.
Proof.
intros.
We arrive at a state that looks like this (omitting things we don't need):
H : n < current_value 0 (n :: l)
H0 : current_value 0 (n :: l) ≤ n
-----
P
The strategy will be to prove that H and H0 together lead to a contradiction from which we can prove any statement P.
We know that n < m (if m stands for the expression current_value 0 (n :: l)) and also m <= n. What can we prove from this? You can search for relevant lemmas using the Search command with a pattern that summarizes what you know:
Search (?n < ?m -> ?m <= ?p -> _).
This query means "given that I know that n < m and also m <= p for the same m, what can I deduce?". The named variables in the query need the ? prefix, they can stand for any expressions. They are not related to any variables you might have in the current environment.
One of the search hits is this (in PeanoNat, which you will have to import):
Nat.lt_le_trans:
forall n m p : nat, n < m -> m <= p -> n < p
So given this lemma we should be able to prove n < n and see if we can make progress from there.
{
apply Nat.lt_le_trans with (m := current_value 0 (n :: l)).
auto.
auto.
}
Now we have:
H1 : n < n
-----
P
So now we have a more "obvious" contradiction in an assumption. Do we have a lemma for proving that this is indeed false?
Search (~ ?n < ?n).
This gives:
Nat.lt_irrefl: forall x : nat, ~ x < x
So then:
apply Nat.lt_irrefl in H1.
We arrive at:
H1 : False
-----
P
This is a tautology that we can prove with tauto:
tauto.
Qed.
Doing such simple arithmetic manually can get very tedious, so there is a lot of automation for doing it. Here's a simpler method using the lia tactic:
Require Import Lia.
Lemma automatic:
forall current_value n l P,
n < current_value 0 (n :: l) ->
current_value 0 (n :: l) <= n ->
P.
Proof.
intros.
lia.
Qed.
Internally this will do some sort of similar reasoning, proving a contradiction in the assumptions.
In hypothesis, I have a natural number that cannot be zero.When we add this number
to an another function,whose output is also natural number. I have to prove that result of addition of these two values equal to zero is false. I should not dig about f,because addition of anything in non zero term ,become equal to zero is false statement.
`H : (m =? 0) = false
(f+ m =? 0) = false`
Short answer:
Require Import Lia.
rewrite !Nat.eqb_neq; lia.
Long answer:
I feel sorry that this question arises. Historically, most of the reasoning in Coq about equality is done with the eq concept, with the notation m = n, not with the boolean equality, on which you rely here. It is also important to know that Coq has a specific notation for "disequality" or "non-equality" : m <> n stands for ~ (m = n).
So if you add typed the following statement instead, there would be an easy solution:
Require Import Arith Lia.
Lemma example1 f m : m <> 0 -> f + m <> 0.
Proof. lia. Qed.
Unfortunately, this does not work for the way you express your statement:
Lemma example2 f m : (m =? 0) = false -> (f + m =? 0) = false.
Proof.
Fail lia.
If you call Search with the following pattern, you see that the boolean comparison expression is logically equivalent to basic equality, but only if you use specific theorems to express this:
Search (_ =? _).
Nat.eqb_refl: forall x : nat, (x =? x) = true
beq_nat_refl: forall n : nat, true = (n =? n)
Nat.eqb_sym: forall x y : nat, (x =? y) = (y =? x)
Nat.eqb_spec: forall x y : nat, Bool.reflect (x = y) (x =? y)
beq_nat_eq: forall n m : nat, true = (n =? m) -> n = m
beq_nat_true: forall n m : nat, (n =? m) = true -> n = m
Nat.eqb_eq: forall n m : nat, (n =? m) = true <-> n = m
beq_nat_false: forall n m : nat, (n =? m) = false -> n <> m
Nat.eqb_neq: forall x y : nat, (x =? y) = false <-> x <> y
Nat.pow2_bits_eqb: forall n m : nat, Nat.testbit (2 ^ n) m = (n =? m)
Nat.bit0_eqb: forall a : nat, Nat.testbit a 0 = (a mod 2 =? 1)
Nat.eqb_compare:
forall x y : nat, (x =? y) = match x ?= y with
| Eq => true
| _ => false
end
Nat.setbit_eqb:
forall a n m : nat,
Nat.testbit (Nat.setbit a n) m = ((n =? m) || Nat.testbit a m)%bool
Nat.clearbit_eqb:
forall a n m : nat,
Nat.testbit (Nat.clearbit a n) m = (Nat.testbit a m && negb (n =? m))%bool
Nat.testbit_eqb: forall a n : nat, Nat.testbit a n = ((a / 2 ^ n) mod 2 =? 1)
But there is no theorem that expresses the interaction of addition with equality to 0. You can also see this using a more precise pattern.
Search (_ =? _) 0 (_ + _).
This returns nothing.
On the other hand, if you type
Search (_ = _) 0 (_ + _).
You see many theorems, one of which is relevant to your problem.
Nat.eq_add_0: forall n m : nat, n + m = 0 <-> n = 0 /\ m = 0
And this one is enough to solve the problem, if it is expressed with _ = _ instead of _ =? _. So to solve your specific problem, we need first to transform comparisons using _ =? _ into equality statements,and then do logical reasoning using the available theorems. In the first search result, we have the theorem Nat.eqb_neq that is adapted to your situation. Continuing on the proof of example2 above, we can write:
Rewrite !Nat.eqb_neq.
The goal becomes:
f, m : nat
============================
m <> 0 -> f + m <> 0
Now, we could do logical reasoning using the theorem Nat.eq_add_0.
rewrite Nat.eq_add_0.
We can finish the proof by small step like this.
intros mn0 [fis0 mis0]; case mn0; assumption.
we can also ask an automatic tool to finish the proof for us:
tauto.
But going a little backward in time, we can also observe the statement after rewriting with Nat.eqb_neq. This is a statement in linear arithmetic (it contains comparisons, natural numbers, and no product between variables). This statement is in the scope of a tactic for this theory, the one used most often now is lia.
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.
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.