Two Coq Problems SOS: one is about IndProp, another has something to do with recursion, I guess - recursion

(* 4. Let oddn and evenn be the predicates that test whether a given number
is odd or even. Show that the sum of an odd number with an even number is odd. *)
Inductive oddn : nat -> Prop :=
| odd1 : oddn 1
| odd2 : forall n, oddn n -> oddn (S (S n)).
Inductive evenn : nat -> Prop :=
| even1 : evenn 0
| even2 : forall n, evenn n -> evenn (S (S n)).
Theorem odd_add : forall n m, oddn n -> evenn m -> oddn (n + m).
Proof. intros. destruct m.
+ Search add. rewrite <- plus_n_O. apply H.
+ destruct H.
++ simpl. apply odd2.
I don't know how can I prove this theorem, since I can not link oddn with evenn.
(* 6. We call a natural number good if the sum of all
its digits is divisible by 5. For example 122 is good
but 93 is not. Define a function count such that
(count n) returns the number of good numbers smaller than
or equal to n. Here we assume that 0 <= n < 10000.
Hint: You may find the "let ... in" struct useful. You may
directly use the div and modulo functions defined in the
standard library of Coq. *)
Definition isGood(n:nat) : bool :=
Fixpoint count (n : nat) : nat :=
match n with
| 0 => 1
| S n' => if isGood n then 1 + count n'
else count n'
end.
Compute count 15.
Example count_test1 : count 15 = 3.
Proof. reflexivity. Qed.
Example count_test2 : count 2005 = 401.
Proof. reflexivity. Qed.
For the second problem, I got stuck because the recursion I defined won't be accepted by Coq(non-decreasing?).
I just got stuck with these two problems, can anyone work them out?

If you want to define independently oddnand even, you may prove a lemma which relates these two predicates, like:
Remark R : forall n, (evenn n <-> oddn (S n)) /\
(oddn n <-> evenn (S n)).
(* proof by induction on n *)
Then, it's easy to apply this remark for solving your first exercise.
Please note that you may define even and odd in several other ways:
as mutually inductive predicates
with existential quantifiers
define even, then oddin function of even
...
I don't understand the problem with the second exercise.
A few days ago, we discussed about a function sum_digits you can use (with modulo) to define isGood.
Your function count looks OK, but quite inefficient (with Peano natural numbers).

Related

Coq: Prove equality of two factorial functions using induction

I want to prove that two factorial functions are equivalent in Coq using induction.
The base case n = 0 is easy, however, the induction case is more complicated. I see, that if I could rewrite (visit_fac_v2 n' (n * a)) to n * (visit_fac_v2 n' a), I would be done. However, translating this idea into Coq causes me troubles.
How would one go about proving this in Coq?
Fixpoint fac_v1 (n : nat) : nat :=
match n with
| 0 => 1
| S n' => n * (fac_v1 n')
end.
Fixpoint visit_fac_v2 (n a : nat) : nat :=
match n with
| 0 => a
| S n' => visit_fac_v2 n' (n * a)
end.
Definition fac_v2 (n : nat) : nat :=
visit_fac_v2 n 1.
Proposition equivalence_of_fac_v1_and_fac_v2 :
forall n : nat,
fac_v1 n = fac_v2 n.
Proof.
Abort.
A typical thing to do when proving that a direct-style function and its accumulator-based equivalent are equal is to state a stronger invariant which ought to be true for any value the accumulator may hold.
You can then specialise it to the value the function is called with thus obtaining the statement you are interested in as a corollary of the more general one.
The general statement here is as follows:
Theorem general_equivalence_of_fac_v1_and_fac_v2 :
forall n a : nat,
a * fac_v1 n = visit_fac_v2 n a.
And its proof is fairly straightforward (you do have to be careful and ensure that induction comes before intro a because you want the induction hypothesis to be valid for any a):
Proof.
intros n; induction n; intro a.
- simpl ; ring.
- simpl ; rewrite <- IHn ; ring.
Qed.
Your proposition is a direct consequence of this more general theorem.
In the inductive case, you can apply the induction hypothesis and simplify the goal to:
visit_fac_v2 n 1 + n * visit_fac_v2 n 1 = visit_fac_v2 n (S n)
To prove this, you can use the following lemma:
Lemma visit_fac_v2_extract:
forall n a : nat,
visit_fac_v2 n a = a * visit_fac_v2 n 1.

Showing terminating recursion for cumsum in Coq

I want to prove that computing the cumulative sum between a and b terminates.
I use an Acc lt x term to show that the recursion decreases, like this
Require Import Omega.
Lemma L1 : forall a b, a<b -> (b-(1+a)) < (b-a).
intros; omega. Qed.
Lemma term_lemma: forall a b, Acc lt (b-a) -> Acc lt (b-(1+a)).
intros; inversion H; clear H; constructor; intros; apply H0; omega.
Defined.
Fixpoint cumsum a b (H: Acc lt (b-a)) {struct H} : nat.
refine (
match lt_dec a b with
| left a_lt_b => a + cumsum (1+a) b _
| right a_ge_b => if beq_nat a b then a else 0
end
).
apply (term_lemma _ _ H).
Qed.
It clears all subgoals but it won't typecheck at the Qed statement. Coq complains:
Recursive definition of cumsum is ill-formed
Recursive call to cumsum has principal argument equal to
"term_lemma a b H" instead of a subterm of "H".
I guess I should somehow use L1 to show that the argument in the H term in the recursive call is actually smaller, but how do I do that?
Because you invert H before building something similar-ish back again by using constructor ; apply H0, you get a term_lemma with a pattern matching that's equivalent to what you'd want but confuses Coq's termination checker (You can inspect a term by using Print NAME.).
You don't need to do all of this inversion business if you remember that you already know that a < b thanks to your case analysis on lt_dec a b. By letting your lemma take an extra argument, you can now use the strict subterm of the Accessibility predicate to get your witness:
Require Import Omega.
Lemma term_lemma: forall a b, a < b -> Acc lt (b-a) -> Acc lt (b-(1+a)).
intros a b altb [H]; apply H; omega.
Defined.
Fixpoint cumsum a b (H: Acc lt (b-a)) {struct H} : nat.
refine (
match lt_dec a b with
| left a_lt_b => a + cumsum (1+a) b _
| right a_ge_b => if beq_nat a b then a else 0
end
).
apply (term_lemma _ _ a_lt_b H).
Defined.

explain a simple operation in coq

I have the following code,
Here O is the charater O not zero 0
Module Playground1.
Inductive nat : Type :=
| O : nat
| S : nat → nat.
Definition pred (n : nat) : nat :=
match n with
| O ⇒ O
| S n' ⇒ n'
end.
End Playground1.
Definition minustwo (n : nat) : nat :=
match n with
| O ⇒ O
| S O ⇒ O
| S (S n') ⇒ n'
end.
Check (S (S (S (S O)))).
Eval compute in (minustwo 4).
I just want to know how it evaluates to 2? I mean how it is actually checking with a numeral and subtracting? I am not subtracting anything here, still it is working? I want to know what is the basic idea here? When I call minustwo 4 how coq know it is a numeral and how it is returning the result? How the matching is working here?
It is quite easy with Coq to follow step by step what is going on. But before we can do that, we need to know what your program looks like to Coq without all the syntactic sugar. To do that, type the following in your program:
Set Printing All.
If you now print minustwo, you will see that
Print minustwo
> match n return nat with
> | O => O
> | S n0 => match n0 return nat with
> | O => O
> | S n' => n'
> end
> end
your pattern match is actually broken up into two pattern matches.
Not let us see step by step how Coq evaluates minustwo 4. To do so, create the following theorem:
Goal (minustwo 4 = 2).
We don't care that much about the theorem itself, we care more about the fact that it contains the term minustwo 4. We can now simplify the expression step by step (you should run this in an ide to actually see what is going on).
First, we unfold the definition of minustwo, using a tactic called cbv delta.
cbv delta. (* unfold the definition of minustwo *)
We can now call the function, using the tactic cbv beta.
cbv beta. (* do the function call *)
We can now do the pattern match with
cbv iota; cbv beta. (* pattern match *)
And because Coq broke up the match into two, we get to do it again
cbv iota; cbv beta. (* pattern match *)
And that is why minustwo 4 is 2
reflexivity.
Qed.

Isabelle: Predecessor function

I am not sure, but I think sometimes my proofs would be easier if I had a predecessor function, e.g., in case a variable is known not to be zero.
I don't know a good example, but perhaps here: { fix n have "(n::nat) > 0 ⟹ (∑i<n. f i) = Predecessor n" sorry }
Possibly because it is not a good idea, there is no predecessor function in the library.
Is there a way to simulate a predecessor function or similar?
I have thought of this example:
theorem dummy:
shows "1=1" (* dummy *)
proof-
(* Predecessor function *)
def pred == "λnum::nat. (∑i∈{ i . Suc i = num}. i)"
{fix n :: nat
from pred_def have "n>0 ⟹ Suc (pred n) = n"
apply(induct n)
by simp_all
}
show ?thesis sorry
qed
Your definition is unnecessarily complicated. Why do you not just write
def pred ≡ "λn::nat. n - 1"
Then you can have
have [simp]: "⋀n. n > 0 ⟹ Suc (pred n) = n" by (simp add: pred_def)
In the case of 0, the pred function then simply returns 0 and Suc (pred 0) = 0 obviously doesn't hold. You could also define pred ≡ "λn. THE n'. Suc n' = n". That would return the unique natural number whose successor is n if such a number exists (i.e. if n > 0) and undefined (i.e. some natural number you know nothing about) otherwise. However, I would argue that in this case, it is much easier and sensible to just do pred ≡ λn::nat. n - 1.
I would suspect that in most cases, you can simply forgo the pred function and write n - 1; however, I do know that it is sometimes good to have the - 1 “protected” by a definition. In these cases, I usually def a variable n' as n - 1 and prove Suc n' = n – basically the same thing. In my opinion, seeing as proving this takes only one line, it does not really merit a definition of its own, such as this pred function, but one could make a reasonable case for it, I guess.
Another thing: I've noticed you use lemma "1 = 1" as some kind of dummy environment to do Isar proofs in. I would like to point out the existence of notepad, which exists precisely for that use case and that can be used as follows:
notepad
begin
have "some fact" by something
end

General recursion and induction in Coq

Let's suppose that I have
type T
wellfounded relation R: T->T->Prop
function F1: T->T that makes argument "smaller"
condition C: T->Prop that describes "start values" of R
function F2: T->T that makes argument "bigger"
How can I make Fixpoint that looks similar to this:
Fixpoint Example (n:T):X :=
match {C n} + {~C n} with
left _ => ... |
right _ => Example (F1 n)
end.
And how I can make possible the following usage of tactic 'induction' (or similar):
Theorem ...
Proof.
...
induction n F.
(* And now I have two goals:
the first with assumption C n and goal P n,
the second with assumption P n and goal P (F2 n) *)
...
Qed.
I tried to do that with type nz: {n:nat | n<>O} (looking in the chapter 7.1 of Certified Programming with Dependent Types book) but got only this far:
Require Import Omega.
Definition nz: Set := {n:nat | n<>O}.
Theorem nz_t1 (n:nat): S n<>O. Proof. auto. Qed.
Definition nz_eq (n m:nz) := eq (projT1 n) (projT1 m).
Definition nz_one: nz := exist _ 1 (nz_t1 O).
Definition nz_lt (n m:nz) := lt (projT1 n) (projT1 m).
Definition nz_pred (n:nz): nz := exist _ (S (pred (pred (projT1 n)))) (nz_t1 _).
Theorem nz_Acc: forall (n:nz), Acc nz_lt n.
Proof.
intro. destruct n as [n pn], n as [|n]. omega.
induction n; split; intros; destruct y as [y py]; unfold nz_lt in *; simpl in *.
omega.
assert (y<S n\/y=S n). omega. destruct H0.
assert (S n<>O); auto.
assert (nz_lt (exist _ y py) (exist _ (S n) H1)). unfold nz_lt; simpl; assumption.
fold nz_lt in *. apply Acc_inv with (exist (fun n0:nat=>n0<>O) (S n) H1). apply IHn.
unfold nz_lt; simpl; assumption.
rewrite <- H0 in IHn. apply IHn.
Defined.
Theorem nz_lt_wf: well_founded nz_lt. Proof. exact nz_Acc. Qed.
Lemma pred_wf: forall (n m:nz), nz_lt nz_one n -> m = nz_pred n -> nz_lt m n.
Proof.
intros. unfold nz_lt, nz_pred in *. destruct n as [n pn], m as [m pm]. simpl in *.
destruct n, m; try omega. simpl in *. inversion H0. omega.
Defined.
I couldn't understand what happens further because it was too complicated for me.
P.S. As I see it - there isn't any good enough tutorial about general recursion and induction in Coq for beginners. At least I could find. :(
I'll try to write a more complete answer later, but Coq has a command called Function that makes it easier to write functions whose arguments decrease according to some well-ordering. Look for the command on the reference manual (http://coq.inria.fr/distrib/current/refman/Reference-Manual004.html#hevea_command48), specifically the "wf" variant.

Resources