How to consider both out puts in list - coq

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 *)

Related

Proving a_j ≤ b_j → sum (a_j) ≤ sum (b_j)

I have that for all j in {1, 2, .. N} such that j ≠ i it holds that a_j ≤ b_j. I want to prove in Coq that
How can I do that and what modules are the best for these kinds of manipulations?
The mathematical components library has a theory of "big" operations with lots of lemmas. Here is how one might prove your result:
From mathcomp Require Import all_ssreflect.
Lemma test N (f g : nat -> nat) (i : 'I_N) :
(forall j, j != i -> f i <= g i) ->
\sum_(j < N | j != i) f i <= \sum_(j < N | j != i) g i.
Proof. move=> f_leq_g; exact: leq_sum. Qed.
Edit
If you want to reason about operations over the real numbers, you will also need to install the mathematical components analysis library. Here is how one might adapt this proof to work over the real numbers:
(* Bring real numbers into scope, as well as
the theory of algebraic and numeric structures *)
Require Import Coq.Reals.Reals.
From mathcomp Require Import all_ssreflect ssralg ssrnum Rstruct reals.
(* Change summation and other notations to work over rings
rather than the naturals *)
Local Open Scope ring_scope.
Lemma test N (f g : nat -> R) (i : 'I_N) :
(forall j, j != i -> f i <= g i) ->
\sum_(j < N | j != i) f i <= \sum_(j < N | j != i) g i.
Proof. move=> f_leq_g; exact: Num.Theory.ler_sum. Qed.
You can do this without the mathematical components library using lia and induction.
Require Import Arith.
Require Import Lia.
Fixpoint sum (f: nat -> nat) (N: nat) :=
match N with
| 0 => 0
| S m => f 0 + sum (fun x => f (S x)) m
end.
Fixpoint sum_except (f: nat -> nat) (i : nat) (N: nat) {struct N} :=
match N with
| 0 => 0
| S m =>
match i with
| 0 => 0 + sum (fun x => f (S x)) m
| S j => f 0 + sum_except (fun x => f (S x)) j m
end
end.
Lemma SumLess : forall N a b,
(forall j, a j <= b j) ->
sum a N <= sum b N.
Proof.
induction N.
- simpl; lia.
- intros; simpl.
admit. (* I'll leave this as an exercise. Use lia. *)
Qed.
Lemma SumExceptLess :
forall N i a b,
(forall j, not (j = i) ->
a j <= b j) ->
sum_except a i N <= sum_except b i N.
Proof.
induction N.
- simpl. lia.
- destruct i.
simpl.
+ intros.
apply SumLess; auto.
+ intros; simpl.
admit. (* Again, I'll leave this for you to discover. Use lia. Follow the same pattern as you did in SumLess. *)
Qed.

How to simplify a statement of lemma

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.

Well-founded induction for a counting predicate

Here is the definition for the Count predicate. It uses 2 indices to denote starting and ending elements, "check" predicate to count/skip the "current" element and the last argument "sum" to keep track the number of elements that satisfy check predicate between these boundary indices.
Require Import ZArith.
Open Scope Z_scope.
Inductive Count : Z -> Z -> (Z -> Prop) -> Z -> Prop :=
| Q_Nil:
forall (m n : Z),
forall (check : Z -> Prop),
(n <= m) ->
(Count m n check 0)
| Q_Hit:
forall (m n sum : Z),
forall (check : Z -> Prop),
let x := (n - 1) in
(m < n) ->
(check x) ->
(Count m x check sum) ->
(Count m n check (1 + sum))
| Q_Miss:
forall (m n sum : Z),
forall (check : Z -> Prop),
let x := (n - 1) in
(m < n) ->
~(check x) ->
(Count m x check sum) ->
(Count m n check sum).
It is required to prove that the number of counted elements "sum" is non-negative.
Goal
forall (m n sum : Z),
forall (check : Z -> Prop),
(Count m n check sum) -> (0 <= sum).
Proof.
Obviously, the induction could be applied here. However, schemes like natlike_rec3 are not applicable because of the Q_Hit|Q_Miss difference in sum element (i.e. +1 in Q_Hit).
Here is my proof attempt till the step where an induction should be applied.
Proof.
Require Import Psatz.
intros m n sum check.
assert (X: n <= m \/ n > m) by lia.
destruct X as [le|gt].
+ intro.
inversion H; subst; intuition.
+ pose (p := (n - m)).
assert (PZ: p > 0). { subst p. auto with zarith. }
replace n with (m + p) in * by (subst p; auto with zarith).
1 subgoal
m, n, sum : Z
check : Z -> Prop
p := n - m : Z
gt : m + p > m
PZ : p > 0
______________________________________(1/1)
Count m (m + p) check sum -> 0 <= sum
I think that maybe well_founded_induction_type_2 could be used further with relation on sum and p: sum <= p.
You can use induction on the Count hypothesis (in a way, that's the main point of Inductive types).
Proof.
intros.
induction H.
all: omega.
(* or, as a single sequence: intros; induction H; omega. *)
(* lia also works instead of omega, and should probably be preferred nowadays (Require Import Lia.) *)
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.