First proof over Reals in Coq - coq

I'm new to Coq. I've been working through Pierce's Logical Foundations. I'm stepping out-of-scope of the text into Real numbers and finding myself clueless. I thought I'd prove something easy so I wrote out some formulas for interest calculations. Now I'd like to prove my conversions are correctly written in my Theorem.
I have no idea how to proceed and am in need of hints and guides!!!
From Coq Require Import Reals.Reals.
Definition simple_compound (A r n m : R) : R :=
A * (Rpower (1 + r / m) (m * n)).
Definition continuous_compound (A r n: R) : R :=
A * (exp (r * n)).
Definition simple_to_continuous_interest (Rm n m: R) : R :=
m * ln (1 + Rm).
Definition continuous_to_simple_interest (Rc n m: R) : R :=
m * (exp (Rc / m) - 1).
(** Prove that given Rm n m, then Rc is m * ln (1 + Rm). *)
Theorem continuous_to_simple_works : forall (A Rc n m : R),
continuous_compound A Rc n = simple_compound A (continuous_to_simple_interest Rc n m) n m.
Proof.
intros A Rc n m.
unfold continuous_compound. unfold simple_compound. unfold continuous_to_simple_interest.
simpl. (** ... and I'm stuck. I would know how to do this algebraically but am clueless in Coq. *)

First, I suggest to unfold Rpower.
Second, a useful lemma is f_equal; it states that, to prove f a = f b, it suffices to prove a = b. (There is also a tactic with the exact same name, which will behave similarly.)
Third, you need to perform some algebraic simplifications. To do so, you can use replace foo with bar; as the name implies, it replaces all the occurrences of foo in the goal with bar and it requires you to prove bar = foo. This latter equality can then be discharged with the field tactic, which checks that two expressions are equal by using the rewriting rules of addition, multiplication, division.
Fourth, you should end up with a goal containing a subterm ln (exp baz). Obviously, you want to replace it with baz. You can use the command Search (ln (exp _)) to find the name of the corresponding lemma. It happens to be named ln_exp, so rewrite ln_exp will do the trick.

Related

Can any one help me how to prove this therom in coq

~ (exists x:D, ~ R x)->(forall y:D, R y)
I have worked on it for quite a long time, but it seems that I cannot use the left part of the implication well.
This is the first part of my code:
Parameter D: Set.
Parameter x: D.
Parameter y: D.
Parameter R: D->Prop.
Lemma b: ~(exists x:D, ~ (R x))->(forall y:D, (R y)).
Can anyone help me figure out how to write the rest of of the code?
Your question is a bit vague, as you don't specify what D and R are, and where you are stuck in your proof. Try providing a minimal working example, with an explicit fail tactic for where you're stuck in the proof.
In classical logic (the one you're use to in maths), as you have the excluded middle rule, you can always do a case analysis on whether something is true or false. In vanilla Coq, built for intuitionistic logic, it's not the case. Your result is actually not provable if the predicate R is not decidable (if it's not either true or false on every input : forall (x:D), R x \/ ~R x), if the type D is not empty.
Try adding the decidability of R as an hypothesis and reprove it. It should follow more or less this structure (the key being the case analysis on whether (R y) is true or false) :
Parameter D: Set.
Parameter R: D -> Prop.
Lemma yourGoal :
(forall x, R x \/ ~ R x) -> (* Decidability of R *)
~ ( exists x, ~ (R x) )->
forall y, (R y).
Proof.
intros Hdec Hex y. (* naming the hypothesis for convenience *)
specialize (Hdec y).
destruct Hdec as [H_Ry_is_true | H_Ry_is_false]. (* case analysis, creates two goals *)
+ (* (R y) is true, which is our goal. *)
assumption.
+ (* (R y) is false, which contradicts Hex *)
exfalso. (* transform your goal into False *)
apply Hex.
(* should be easy from here, using the [exists] tactic *)
Qed.
Ps: this exact result (and its link with excluded middle) is mentioned in Software foundations, which is a great resource to learn Coq and logic : https://softwarefoundations.cis.upenn.edu/lf-current/Logic.html#not_exists_dist

Defining recursive function over product type

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

Coq: Nested(?) subtype defining nonzero rational numbers and their reciprocals

I tried to define the reciprocal of a nonzero rational number, imitating the answers in my another question. I tried to delay the proof, but it seems that I misunderstood.
The following is my code:
1) Integers: define z (= a - b) as a pair (a, b) which is in a setoid with the equiv rel (a, b) ~ (c, d) <-> a + d = b + c
Definition Z_eq (z w: integer): Prop :=
match z with
| (z1, z2) =>
match w with
| (w1, w2) => z1 + w2 = z2 + w1
end
end.
Add Parametric Relation:
integer Z_eq
reflexivity proved by Z_refl
symmetry proved by Z_symm
transitivity proved by Z_tran
as Z. (** proved; omitting the proof *)
(** addition, subtraction, negation, multiplication are well-defined as a morphism *)
Add Morphism Z_plus with signature Z_eq ==> Z_eq ==> Z_eq as Z_plus_morph.
(** etc. *)
2) Positive integers: {n : nat | 0 <? n }
(** as in answers of the previous question *)
Local Coercion is_true : bool >-> Sortclass.
Definition Z_pos: Set := {n : nat | 0 <? n }.
Definition Z_pos__N (p: Z_pos): nat := proj1_sig p.
Coercion Z_pos__N : Z_pos >-> nat.
Definition Z_pos__Z (p: Z_pos): integer := (proj1_sig p, 0).
Coercion Z_pos__Z : Z_pos >-> integer.
Definition Z_pos_plus : Z_pos -> Z_pos -> Z_pos.
intros [x xpos%Nat.ltb_lt] [y ypos%Nat.ltb_lt].
refine (exist _ (x + y) _).
now apply Nat.ltb_lt, Nat.add_pos_pos.
Defined.
Definition Z_pos_mult : Z_pos -> Z_pos -> Z_pos.
intros [x xpos%Nat.ltb_lt] [y ypos%Nat.ltb_lt].
refine (exist _ (x * y) _).
now apply Nat.ltb_lt, Nat.mul_pos_pos.
Defined.
Lemma Z_pos_mult_compat: forall p q: Z_pos, Z_pos__N (Z_pos_mult p q) = Z_pos__N p * Z_pos__N q.
Proof. now intros [x xpos] [y ypos]. Qed.
Definition ZP1: Z_pos.
refine (exist _ 1 _). easy.
Defined.
3) Nonzero integers: {z : integer | z <Z> Z0}
(** nonzero integer *)
Definition Z_nonzero: Set := {z : integer | z <Z> Z0}.
(* abs value of a nonzero integer as an obj of type Z_pos *)
Definition Z_nonzero_abs__Z_pos (z: Z_nonzero): Z_pos.
destruct z as [[z1 z2] z3].
exists ((z1 - z2) + (z2 - z1))%nat.
Admitted. (** proof ommited *)
(* multiplication b/w two nonzero integers *)
Definition Z_nonzero_mult (z w: Z_nonzero): Z_nonzero.
exists (proj1_sig z *Z proj1_sig w).
Admitted.
(* sign of n - m *)
Definition N_sgn_diff__Z (n m: nat): integer :=
if n >? m then Z1 else if n =? m then Z0 else -Z Z1.
(* sign of n - m *)
Definition Z_nonzero_sgn__Z (z: Z_nonzero): Z_nonzero.
destruct z as [[z1 z2] z3].
exists (N_sgn_diff__Z z1 z2).
Admitted.
4) Rational numbers: ( a // b ) (a: integer, b: Z_pos)
Inductive rational: Type :=
| prerat : integer -> Z_pos -> rational.
Notation "( x '//' y )" := (prerat x y).
(* equality *)
Definition Q_eq (p q: rational): Prop :=
match p with
| (p1 // p2) =>
match q with
| (q1 // q2) => (Z_mult p1 (Z_pos__Z q2)) =Z= (Z_mult (Z_pos__Z p2) q1)
end
end.
(* numerator of a rational *)
Definition Q_numerator (q: rational) :=
match q with
| (iq // rq) => iq
end.
(* nonzero rationals *)
Definition Q_nonzero: Set := {q : rational | Q_numerator q <Z> Z0}.
(* numerator and denominator *)
Definition Q_nonzero_numerator (q: Q_nonzero): Z_nonzero.
destruct q as [[q1 q2] q3].
exists q1.
simpl in q3. apply q3.
Qed.
Definition Q_nonzero_denominator (q: Q_nonzero): Z_pos.
destruct q as [[q1 q2] q3].
exact q2.
Qed.
Definition Q_recip (q: Q_nonzero): Q_nonzero.
exists ( proj1_sig (Z_nonzero_mult (Z_nonzero_sgn__Z (Q_nonzero_numerator q)) (Z_pos__Z_nonzero (Q_nonzero_denominator q))) // Z_nonzero_abs__Z_pos (Q_nonzero_numerator q) ).
Admitted. (* proved. *)
(* inherited equality *)
Definition Q_nonzero_eq (p q: Q_nonzero): Prop := (proj1_sig p) =Q= (proj1_sig q).
Add Morphism Q_recip with signature Q_nonzero_eq ==> Q_nonzero_eq as Q_recip_morph.
Proof. (* well-definedness of Q_recip *)
destruct x, y.
unfold Q_nonzero_eq. simpl. intros.
unfold Q_recip. (* <----- unfolded result was very long and complex; not simplified after simpl. *)
Abort.
I think this definitions are somewhat complex, but it was my best try...
Now, how can I prove the consistency of the morphism Q_recip?
(View full code)
I think you forgot to add the definition of Q_nonzero in your development, so I cannot run your code. However, I believe that the issue is that you have used Qed instead of Defined in some of your definitions. This question discusses the issue in more detail. (In any case, as Emilio points out, it is usually better to avoid definitions in proof mode, as they tend to be harder to reason about, as you've probably noticed.)
A note on style: your development mimics common definitions of number systems from first principles in set theory, where we often use equivalence classes to define the integers, the rational numbers, etc. Though elegant, this approach is often inconvenient to use in Coq. The main issue is that, because of the lack of proper quotient types, you are forced to use setoids everywhere, which prevents you from using Coq's much more convenient equality operator =. It is simpler to write these definitions as plain datatypes. For instance, you can define the integers as
Inductive int :=
| Posz : nat -> int
| Negz : nat -> int.
where Posz represents the canonical injection from natural numbers into integers, and Negz maps the natural number n to the integer - n - 1. This is the approach followed in the mathematical components library. Of course, the standard library also has its own definition of the integers (here), so you do not need to replicate it. Defining the rationals is more complicated, but it can still be done: in mathematical components, they are defined as pairs of coprime integers (num, den) such that den > 0 and num.

Pattern Matching with Even and Odd Cases

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.

How can I rewrite "+ 1" (plus one) to "S" (succ) in Coq?

I have the following Lemma with an incomplete proof:
Lemma s_is_plus_one : forall n:nat, S n = n + 1.
Proof.
intros.
reflexivity.
Qed.
This proof fails with
Unable to unify "n + 1" with "S n".
It seems like eq_S would be the way to prove this, but I can't apply it (it doesn't recognize n + 1 as S n: Error: Unable to find an instance for the variable y.). I've also tried ring, but it can't find a relation. When I use rewrite, it just reduces to the same final goal.
How can I finish this proof?
This is related to the way (+) is defined. You can access (+)'s underlying definition by turning notations off (in CoqIDE that's in View > Display notations), seeing that the notation (+) corresponds to the function Nat.add and then calling Print Nat.add which gives you:
Nat.add =
fix add (n m : nat) {struct n} : nat :=
match n with
| O => m
| S p => S (add p m)
end
You can see that (+) is defined by matching on its first argument which in n + 1 is the variable n. Because n does not start with either O or S (it's not "constructor-headed"), the match cannot reduce. Which means you won't be able to prove the equality just by saying that the two things compute to the same normal form (which is what reflexivity claims).
Instead you need to explain to coq why it is the case that for any n the equality will hold true. A classic move in the case of a recursive function like Nat.add is to proceed with a proof by induction. And it does indeed do the job here:
Lemma s_is_plus_one : forall n:nat, S n = n + 1.
Proof.
intros. induction n.
- reflexivity.
- simpl. rewrite <- IHn. reflexivity.
Qed.
Another thing you can do is notice that 1 on the other hand is constructor-headed which means that the match would fire if only you had 1 + n rather than n + 1. Well, we're in luck because in the standard library someone already has proven that Nat.add is commutative so we can just use that:
Lemma s_is_plus_one : forall n:nat, S n = n + 1.
Proof.
intros.
rewrite (Nat.add_comm n 1).
reflexivity.
Qed.
A last alternative: using SearchAbout (?n + 1), we can find all the theorems talking about the pattern ?n + 1 for some variable ?n (the question mark is important here). The first result is the really relevant lemma:
Nat.add_1_r: forall n : nat, n + 1 = S n