Suppose I write a Fixpoint algorithm in Coq that sums up all the "halves" of a number:
Fixpoint sum_of_halves (a : nat) : nat :=
match a with
| 0 => 0
| 2 * k => a + (sum_of_halves k)
| S (2 * k) => a + (sum_of_halves k)
end.
Trying to evaluate the algorithm would get: Error: Invalid notation for pattern.
How can I get Coq to recognize that a is either an even or an odd number, and match it with either 2 * k or S (2 * k)?
Coq can only match on constructors. nat has two constructors, O and S, so you cannot match on 2 * k. You will have to use a non-match construct or a non-nat type or a different algorithm.
You need to prove that there are only three cases for a given natural number a. Either a is 0, either a is the double of another number k and k < a, or a is the double k + 1 and k < a, that the three cases are exclusive (this is important, otherwise making pattern matching possible would lead to an inconistency).
Fortunately, all this can be done. It is a bit advanced Coq programming, but it is somehow already done in ZArith. Here is a solution.
First note that the other number is already provided by one of the functions in the Coq library, div2.
Require Import Arith Nat.
Definition cases_div2 (a : nat) :
{k : nat | a = 2 * k /\ k < a}+{k : nat | a = S (2 * k) /\ k < a}+{a=0}.
destruct a as [ | a'].
right; reflexivity.
case_eq (odd (S a')); intros odd_a.
left; right; exists (div2 (S a')); rewrite (div2_odd (S a')) at 1.
split.
rewrite odd_a; simpl b2n; ring.
apply lt_div2; auto with arith.
left; left; exists (div2 (S a')); rewrite (div2_odd (S a')) at 1.
split.
rewrite odd_a; simpl b2n; ring.
apply lt_div2; auto with arith.
Defined.
Now, you can pattern match on your number a using cases_div2, but it is still not enough to define your function, because recursion using Fixpoint relies on recursive calls happening on the predecessor, and here k cannot be written as a predecessor pattern that will work for any input a. You need a stronger kind of recursion. I usually rely on Function or Fix for this kind of strong recursion. Here is an example with Fix
Definition sum_of_halves : nat -> nat :=
Fix Arith.Wf_nat.lt_wf (fun _ => nat)
(fun a (sum_of_halves' : forall y, y < a -> nat) =>
match cases_div2 a with
| inright h => 0
| inleft (inl (exist _ k (conj keq klt))) =>
a + sum_of_halves' k klt
| inleft (inr (exist _ k (conj keq klt))) =>
a + sum_of_halves' k klt
end).
Then to reason about sum_of_halves you will need to reason by well founded induction and use Fix_eq.
This is one possibility.
Related
I'm trying to formalize each integer as an equivalence class of pairs of natural numbers, where the first component is the positive part, and the second component is the negative part.
Definition integer : Type := prod nat nat.
I want to define a normalization function where positives and negatives cancel as much as possible.
Fixpoint normalize (i : integer) : integer :=
let (a, b) := i in
match a with
| 0 => (0, b)
| S a' => match b with
| 0 => (S a', 0)
| S b' => normalize (a', b')
end
end.
However Coq says:
Error:
Recursive definition of normalize is ill-formed.
In environment
normalize : integer -> integer
i : integer
a : nat
b : nat
a' : nat
b' : nat
Recursive call to normalize has principal argument
equal to "(a', b')" instead of a subterm of "i".
I think this might have to do with well-founded recursion?
Now Program Fixpoint has become so good that you can define normalize like this:
Require Import Program.
Definition integer :Type := (nat*nat).
Program Fixpoint normalize (i:integer) {measure (max (fst i) (snd i))} :=
match i with
| (S i1, S i2) => normalize (i1, i2)
| (_, _) => i
end.
It is able to handle all the proof obligations by itself!
To use it and reason about it, you will probably want to define some rewrite lemmas.
Lemma normalize_0_l i: normalize (0, i) = (0, i).
Proof. reflexivity. Qed.
Lemma normalize_0_r i: normalize (i, 0) = (i, 0).
Proof. destruct i; reflexivity. Qed.
Lemma normalize_inj i j: normalize (S i, S j) = normalize (i, j).
unfold normalize at 1; rewrite fix_sub_eq; simpl; fold (normalize (i, j)).
- reflexivity.
- now intros [[|x] [|y]] f g H.
Qed.
I got the unfold... rewrite ... simpl... fold technique from here!
In addition to #larsr's answer: the Equations plugin offers some nice features like auto generation of simplification lemmas analogous to normalize_0_l, etc. E.g. for the example below we have normalize_equation_1, normalize_equation_2 etc.
Moreover, just as the Function plugin does, Equations provides functional induction schemes that make proofs about properties of functions quite elegant.
From Equations Require Import Equations.
Definition integer : Type := prod nat nat.
Equations normalize (i : integer) : integer by wf (fst i) :=
normalize (0, b) := (0, b);
normalize (S a', 0) := (S a', 0);
normalize (S a', S b') := normalize (a', b')
.
(* see Coq's response for the list of auto generated lemmas *)
Let's prove some properties of normalize using functional induction. Equations provide some tactics that make using it easier. I will use funelim in this case.
From Coq Require Import Arith.
Lemma normalize_sub_lt a b :
a < b -> normalize (a, b) = (0, b - a).
Proof.
funelim (normalize (a, b)); simpl in *.
- now rewrite Nat.sub_0_r.
- now intros []%Nat.nlt_0_r.
- intros a_lt_b%Nat.succ_lt_mono; auto.
Qed.
The second part of normalize's spec can be proved in the same manner.
Lemma normalize_sub_gte a b :
b <= a -> normalize (a, b) = (a - b, 0).
Recursive calls must be made on a "subterm" of the original argument. A subterm for a term in an inductive type is essentially a term of the same type that was used to create the original term. For example, a subterm of a natural number like S a' is a'.
Unfortunately for your definition (as written), a pair i: prod nat nat doesn't have any subterms in this sense. This is because prod isn't a recursive type. Its constructor pair: A -> B -> prod A B doesn't take anything of type prod A B as an argument.
To fix this, I'd suggest defining your function on two separate natural numbers first.
Fixpoint normalize_helper (a b : nat) : integer :=
match a with
| 0 => (0, b)
| S a' => match b with
| 0 => (S a', 0)
| S b' => normalize a' b'
end
end.
Then normalize can easily be defined in terms of normalize_helper.
While it is useful to learn how to write this type of recursive function, in this particular case I think it would be better to avoid the recursion and use standard definitions:
Require Import Coq.Arith.Arith.
Definition integer : Type := (nat * nat).
Definition normalize (i : integer) : integer :=
if snd i <=? fst i then (fst i - snd i, 0)
else (0, snd i - fst i).
I've began learning Coq, and am trying to prove something that seems fairly simple: if a list contains x, then the number of instances of x in that list will be > 0.
I've defined the contains and count functions as follows:
Fixpoint contains (n: nat) (l: list nat) : Prop :=
match l with
| nil => False
| h :: t => if beq_nat h n then True else contains n t
end.
Fixpoint count (n acc: nat) (l: list nat) : nat :=
match l with
| nil => acc
| h :: t => if beq_nat h n then count n (acc + 1) t else count n acc t
end.
I'm trying to prove:
Lemma contains_count_ge1 : forall (n: nat) (l: list nat), contains n l -> (count n 0 l > 0).
I understand the proof will involve unfolding the definitions of count and contains, but then I'd like to say "the list cannot be nil, as contains is true, so there must be an element x in l such that beq_nat h x is true", and I've played around a bit but can't figure out how to use tactics to do this. Any guidance would be greatly appreciated.
ejgallego already gave a great solution to your problem in his answer. I would still like to single out an important point that he left out: in Coq, you must always argue from first principles, and be very pedantic and precise about your proofs.
You argued that the proof should proceed as follows:
The list cannot be nil, as contains is true, so there must be an element x in l such that beq_nat h x is true.
Even though this makes intuitive sense for humans, it is not precise enough for Coq to understand. The problem, as ejgallego's answer shows, is that your informal reasoning conceals a use of induction. Indeed, it is useful to try to expand out your argument in more details even before translating it into tactics. We could proceed like this, for instance:
Let us prove that, for every n : nat and ns : list nat, contains n ns implies count n 0 ns > 0. We proceed by induction on the list ns. If ns = nil, the definition of contains implies that False holds; a contradiction. We are thus left with the case ns = n' :: ns', where we can use the following induction hypothesis: contains n ns' -> count n 0 ns' > 0. There are two sub-cases to consider: whether beq_nat n n' is true or not.
If beq_nat n n' is true, by the definition of count, we see that we just have to show that count n (0 + 1) ns' > 0. Note there isn't a direct way to proceed here. This is because you wrote count tail-recursively, using an accumulator. While this is perfectly reasonable in functional programming, it can making proving properties about count more difficult. In this case, we would need the following auxiliary lemma, also proved by induction: forall n acc ns, count n acc ns = acc + count n 0 ns. I'll let you figure out how to prove this one. But assuming that we have already established it, the goal would reduce to showing that 1 + count n 0 ns' > 0. This is true by simple arithmetic. (There is an even simpler way that does not require an auxiliary lemma, but it would require slightly generalizing the statement you're proving.)
If beq_nat n n' is false, by the definitions of contains and count, we would need to show that contains n ns' implies count n 0 ns' > 0. This is exactly what the induction hypothesis gives us, and we are done.
There are two lessons to be learned here. The first one is that doing formal proofs often requires translating your intuition in formal terms that the system can understand. We know intuitively what it means to have some element occur inside of a list. But if we were to explain what that means more formally, we would resort to some kind of recursive traversal of the list, which would probably turn out to be the very definition of count that you wrote in Coq. And in order to reason about recursion, we need induction. The second lesson is that the way you define things in Coq has important consequences for the proofs you write. ejgallego's solution did not require any auxiliary lemmas beyond those in the standard library, precisely because his definition of count was not tail-recursive.
Well, you pose many questions about basic Coq beyond what is IMO possible to address here. For this particular problem, I would proceed this way (in reality I would use the already provided lemmas in MathComp):
From Coq Require Import PeanoNat Bool List.
Fixpoint contains (n: nat) (l: list nat) : bool :=
match l with
| nil => false
| h :: t => if Nat.eqb h n then true else contains n t
end.
Fixpoint count (n : nat) (l: list nat) : nat :=
match l with
| nil => 0
| h :: t => if Nat.eqb h n then S (count n t) else count n t
end.
Lemma contains_count_ge1 n l : contains n l = true -> count n l > 0.
Proof.
induction l as [|x l IHl]; simpl; [now congruence|].
now destruct (Nat.eqb_spec x n); auto with arith.
Qed.
My "standard" solution:
Lemma test n (l : list nat) : n \in l -> 0 < count_mem n l.
Proof. by rewrite lt0n => /count_memPn/eqP. Qed.
and different definitions of count and contains that may prove useful:
Fixpoint contains (n: nat) (l: list nat) : bool :=
match l with
| nil => false
| h :: t => Nat.eqb h n || contains n t
end.
Fixpoint count (n : nat) (l: list nat) : nat :=
match l with
| nil => 0
| h :: t => Nat.b2n (Nat.eqb h n) + (count n t)
end.
In Coq, I'm having problems with applying the rewrite tactic in the following situation:
Section Test.
Hypothesis s t : nat -> nat.
Hypothesis s_ext_eq_t : forall (x : nat), s x = t x.
Definition dummy_s : nat -> nat :=
fun n => match n with
| O => 42
| S np => s np
end.
Definition dummy_t : nat -> nat :=
fun n => match n with
| O => 42
| S np => t np
end.
Goal forall (n : nat), dummy_s n = dummy_t n.
Proof.
intro n. unfold dummy_s. unfold dummy_t.
At that stage, the local context and current goal look as follows:
1 subgoals, subgoal 1 (ID 6)
s : nat -> nat
t : nat -> nat
s_ext_eq_t : forall x : nat, s x = t x
n : nat
============================
match n with
| 0 => 42
| S np => s np
end = match n with
| 0 => 42
| S np => t np
end
Now it should be possible to apply the rewrite tactic to replace the occurence of s np in the goal by t np, thereby making it possible to solve the goal using reflexivity. However,
rewrite s_ext_eq_t.
gives
Toplevel input, characters 0-18:
Error: Found no subterm matching "s ?190" in the current goal.
What am I doing wrong? One can get into a situation where rewrite is applicable via
destruct n.
(* n = 0 *)
reflexivity.
(* n > 0 *)
rewrite s_ext_eq_t.
reflexivity.
Qed.
but in the actual situation I am facing, several such destructs would be necessary, and I wonder whether rewrite or a variant of it is able to do this automatically.
Addendum The above situation naturally occurs when proving that a function defined via well-founded recursion has the desired fixed point property:
Suppose A: Type and that R: A -> A -> Prop is a well-founded relation, i.e. we have Rwf: well_founded R. Then, given a type family P: A -> Type we may construct a section
Fix : forall (x : A), P a
through recursion over R, with the recursion step given as a function
F : forall x:A, (forall y:A, R y x -> P y) -> P x
See https://coq.inria.fr/library/Coq.Init.Wf.html However, to show that Fix indeed has the fixed point property
forall (x : A), Fix x = F (fun (y:A) _ => Fix y)`
we need to provide a witness
F_ext : forall (x:A) (f g:forall y:A, R y x -> P y),
(forall (y:A) (p:R y x), f y p = g y p) -> F f = F g.
i.e. we have to show that F does not use anything else from the given f: forall y:A, R y x -> P y but its values. Of course, in any concrete situation, this should be trivial to verify, but when one tries to prove it, one runs into a situation a minimal example of which I have presented above: One is facing a huge equality of two copies of the code for the recursion step, one time with f and another time with g. Your assumption tells that f and g are extensionally equal, so one should be able to rewrite them. However, in the code for the recursion step, there might be a large number of pattern matchings and new variables that doesn't make sense in the local context, hence it would be (unnecessarily?) quite tedious to destruct dozens of times before being allowed to apply rewrite.
As mentioned in a comment above, it is not possible to perform the rewrite directly on the branch of the match statement, because np is not in scope in the top-level environment. As far as Coq's theory is concerned, a proof of your statement will have to destruct n at some point.
Although I am not aware of any tactics for automating this kind of problem, it is not too hard to come up with some custom ltac code for solving your problem without too much pain:
Ltac solve_eq :=
try reflexivity;
match goal with
| |- match ?x with _ => _ end
= match ?x with _ => _ end =>
destruct x; auto
end.
Goal forall (n : nat), dummy_s n = dummy_t n.
Proof.
intro n. unfold dummy_s. unfold dummy_t.
solve_eq.
Qed.
If your extensional equality results are hypotheses that appear in your context, then solve_eq should be able to solve many goals of this shape; if not, you might have to add extra lemmas to your hint database.
I am new to Coq and need some help with some of trivial examples to get me started. In particular I am interested in defining some operations of vectors (fixed size lists) using dependent types. I started with Vector package and trying to implement some additional functions. For example I am having difficulty implementing trivial 'take' and 'drop' functions, which take or drop first 'p' elements from the list.
Require Import Vector.
Fixpoint take {A} {n} (p:nat) (a: t A n) : p<=n -> t A p :=
match a return ( p<=n -> t A p) with
| cons A v (S m) => cons (hd v) (take m (tl v)) m
| nil => fun pf => a
end.
The error (in case of nil) is:
The term "a" has type "t A n" while it is expected to have type "t A p".
Could somebody help me with some starting points? Thanks!
I don't understand your approach. You're always returning a non-empty vector when the argument is a non-empty vector, but take must return nil when p=0 regardless of the vector.
Here's one approach to building take. Rather than using the hypothesis p <= n, I express the length of the argument n as a sum of the number p of elements to take and the number of trailing elements m, which is possible iff p <= n. This allows for an easier recursive definition, because (S p') + m is structurally equal to S (p' + m). Note that the discrimination is on the number of elements to take: return nil if taking 0, return cons head new_tail otherwise.
This version of the take function has the desired computational behavior, so all that's left is to define one with the desired proof content. I use the Program feature to do this conveniently: fill in the computational content (trivial, I just need to say that I want to use m = n - p), then complete the proof obligations (which are simple arithmetic).
Require Import Arith.
Require Import Vector.
Fixpoint take_plus {A} {m} (p:nat) : t A (p+m) -> t A p :=
match p return t A (p+m) -> t A p with
| 0 => fun a => nil _
| S p' => fun a => cons A (hd a) _ (take_plus p' (tl a))
end.
Program Definition take A n p (a : t A n) (H : p <= n) : t A p :=
take_plus (m := n - p) p a.
Solve Obligations using auto with arith.
For your newdrop : forall A n p, t A n -> p <= n -> t A (n-p), the following approach works. You need to help Coq by telling it what p and n become in the recursive call.
Program Fixpoint newdrop {A} {n} p : t A n -> p <= n -> t A (n-p) :=
match p return t A n -> p <= n -> t A (n-p) with
| 0 => fun a H => a
| S p' => fun a H => newdrop p' (tl a) (_ : p' <= n - 1)
end.
Next Obligation.
omega.
Qed.
Next Obligation.
omega.
Qed.
Next Obligation.
omega.
Qed.
Next Obligation.
omega.
Qed.
I don't know why Solve Obligations using omega. doesn't work but solving each obligation individually works.
I would like to use an hypothesis in a function to rule out some of the cases in a match statement. I wonder how this is done in Coq.
A very simple example is a function that uses match on a nat. I would like to use an hypothesis that says that n <> 0 so that I won't have to provide a match pattern for 0, like this:
Fixpoint minus_1 (n:nat) (H:n<>0): nat :=
match n with
| S n' => n'
end.
The above example gives Error: Non exhaustive pattern-matching: no clause found for pattern 0.
How do I make use of H to not have to provide a pattern for 0?
You can rely on the Program library to fill some gaps for you, for example:
Require Import Arith Program.
Program Fixpoint minus_1 (n: nat) (h: n <> 0) : nat :=
match n with
| S p => p
| _ => _
end.
or you can build the term "by hand" using tactics (in v8.4):
Fixpoint minus_1 (n: nat) (h: n <> 0) {struct n} : nat.
destruct n as [ | p ].
- case h; reflexivity.
- exact p.
Defined.
Here is a version that should work on older version of Coq:
Definition minus_1 (n: nat) (h: n <> 0) : nat.
revert h.
elim n.
intros heq; case heq; reflexivity.
intros p _ _; exact p.
Defined.
In all cases, you can use Print minus_1. to see the resulting term.
You can use a return annotation on the match:
Lemma notNotEqual : forall x:nat, (x <> x) -> False.
auto.
Qed.
Definition predecessor (n:nat) : n<>0 -> nat :=
match n return (n <> 0 -> nat) with
| 0 =>
fun H : 0 <> 0 =>
match notNotEqual 0 H with end
| S m => fun _ => m
end.
This is covered in Adam Chlipala's book, "Certified Programming with Dependent Types", starting in the chapter on Inductive Types. It is also covered in Chapter 17 of the Coq manual, "Extended pattern-matching", by Cristina Cornes and Hugo Herbelin.
You could also mix the function style with the tactics style using refine:
Definition predecessor_alt (n:nat) : n<>0 -> nat.
refine
(match n return (n <> 0 -> nat) with
| 0 => _
| S m => fun _ => m
end).
intros; assert False as nope.
auto.
inversion nope.
Defined.