Prop and bool in Coq - boolean

How can I use a comparison of to rational numbers in an if-statement?
if 1 = 2 then 1 else 2
1 = 2 is of course Prop and not bool.

I don't understand how dfan's answer is related to the question...
Of course, 1 = 2 is a Prop, it is the statement that 1 is equal to 2. Hopefully you don't have a proof of this statement...
What you want is a function that, given two natural numbers, 1 and 2, returns true if they are equal, and false if they aren't.
The library Coq.Arith.EqNat gives you such a function, named beq_nat.
In fact, you might want something even better, a function that returns a proof of equality or a proof of difference:
(* In Coq.Arith.Peano_dec *)
Theorem eq_nat_dec : forall n m, {n = m} + {n <> m}.
(* ^ a proof that n = m
^ or a proof that n <> m *)
if is overloaded to work with such things, so you can even write:
if eq_nat_dec 2 3 then ... else ...

Qeq_bool indeed takes two rationals and produces a bool.
Require Export QArith_base.
Eval compute in Qeq_bool (3#2) (3#2). = true: bool
Eval compute in Qeq_bool (3#2) (5#2). = false: bool
Eval compute in (if Qeq_bool (3#2) (5#2) then 7 else 9). = 9: nat

Related

Inductive types carrying proofs

There is this one exercise in "Software Foundations" that I've been trying to solve correctly for some time now but I've actually hit a wall in terms of trying to write down the function being asked for. Here is the relevant part of the exercise
Consider a different, more efficient representation of natural numbers
using a binary rather than unary system. That is, instead of saying
that each natural number is either zero or the successor of a natural
number, we can say that each binary number is either
zero,
twice a binary number, or
one more than twice a binary number.
(a) First, write an inductive definition of the type bin corresponding
to this description of binary numbers.
The naive definition doesn't quite work because you end up being able to construct terms that add 1 to a number that already had 1 added to it or multiplying zero with 2 for no good reason. In order to avoid those I figured I would encode some kind of state transition into the constructors to avoid those but this is kinda tricky so this was the best I could come up with
Inductive tag : Type := z | nz | m. (* zero | nonzero | multiply by 2 *)
Inductive bin_nat : tag -> Type :=
(* zero *)
| Zero : bin_nat z
(* nonzero *)
| One : bin_nat nz
(* multiply by 2 -> nonzero *)
| PlusOne : bin_nat m -> bin_nat nz
(* nonzero | multiply by 2 -> multiply by 2 *)
| Multiply : forall {t : tag}, (t = m \/ t = nz) -> bin_nat t -> bin_nat m.
With the above representation I avoid the issues of terms that don't make sense but now I have to carry around proofs whenever I multiply by 2. I actually have no idea how to use these things in recursive functions though.
I know how to construct the proofs and the terms and they look like this
(* nonzero *)
Definition binr (t : tag) := or_intror (t = m) (eq_refl nz).
(* multiply by 2 *)
Definition binl (t : tag) := or_introl (t = nz) (eq_refl tag m).
(* some terms *)
Check Zero.
Check One.
Check (Multiply (binr _) One).
Check (Multiply (binl _) (Multiply (binr _) One)).
Check PlusOne (Multiply (binl _) (Multiply (binr _) One)).
I can also write down a "proof" of the theorem that I want to correspond to a function but I don't know how to actually convert it to a function. Here's the proof for the conversion function
Definition binary_to_nat : forall t : tag, bin_nat t -> nat.
Proof.
intros.
einduction H as [ | | b | t proof b ].
{ exact 0. } (* Zero *)
{ exact 1. } (* One *)
{ exact (S (IHb b)). } (* PlusOne *)
{ (* Multiply *)
edestruct t.
cut False.
intros F.
case F.
case proof.
intros F.
inversion F.
intros F.
inversion F.
exact (2 * (IHb b)).
exact (2 * (IHb b)).
}
Defined.
I know this term is the function I want because I can verify that I get the right answers when I compute with it
Section Examples.
Example a : binary_to_nat z Zero = 0.
Proof.
lazy.
trivial.
Qed.
Example b : binary_to_nat nz One = 1.
Proof.
lazy.
trivial.
Qed.
Example c : binary_to_nat m ((Multiply (binl _) (Multiply (binr _) One))) = 4.
Proof.
lazy.
trivial.
Qed.
End Examples.
So finally the question, is there an easy way to convert the above proof term to an actual function in a simple way or do I have to try to reverse engineer the proof term?
I like your idea of representing a valid binary number using states and an indexed inductive type. However, as the question indicates, it's possible to get away with just three constructors on the inductive type: zero, multiply by 2, and multiply by 2 and add one. That means that the only transition we need to avoid is multiplying zero by 2.
Inductive tag : Type := z | nz. (* zero | nonzero *)
Inductive bin_nat : tag -> Type :=
(* zero *)
| Zero : bin_nat z
(* multiply by 2 *)
| TimesTwo : bin_nat nz -> bin_nat nz
(* multiply by 2 and add one *)
| TimesTwoPlusOne : forall {t : tag}, bin_nat t -> bin_nat nz.
Then, for example,
Let One := TimesTwoPlusOne Zero. (* 1 *)
Let Two := TimesTwo One. (* 10 *)
Let Three := TimesTwoPlusOne One. (* 11 *)
Let Four := TimesTwo Two. (* 100 *)
So TimesTwo adds a zero to the end of the binary representation and TimesTwoPlusOne adds a one.
If you want to try this yourself, don't look any further.
(I would have put this in spoiler tags, but apparently code blocks in spoiler tags are glitchy)
Incrementing a binary number.
Fixpoint bin_incr {t: tag} (n: bin_nat t): bin_nat nz :=
match n with
| Zero => One
| TimesTwo n' => TimesTwoPlusOne n'
| #TimesTwoPlusOne _ n' => TimesTwo (bin_incr n')
end.
A helper definition for converting nat to binary.
Definition nat_tag (n: nat): tag :=
match n with
| 0 => z
| S _ => nz
end.
Converting nat to binary.
Fixpoint nat_to_bin (n: nat): bin_nat (nat_tag n) :=
match n with
| 0 => Zero
| S n' => bin_incr (nat_to_bin n')
end.
Converting binary to nat. Note that this uses the notations for multiplication and addition of natural numbers. If this doesn't work, you may not have the right scopes open.
Fixpoint bin_to_nat {t: tag} (n: bin_nat t): nat :=
match n with
| Zero => 0
| TimesTwo n' => 2 * (bin_to_nat n')
| #TimesTwoPlusOne _ n' => 1 + 2 * (bin_to_nat n')
end.
We get actual functions from these definitions (note that 20 is 10100 in binary).
Compute nat_to_bin 20.
= TimesTwo
(TimesTwo (TimesTwoPlusOne (TimesTwo (TimesTwoPlusOne Zero))))
: bin_nat (nat_tag 20)
Compute bin_to_nat (nat_to_bin 20).
= 20
: nat
One further technical note. I used this code on two versions of Coq (8.6 and 8.9+alpha) and one version demanded that I put the tag in explicitly when matching on TimesTwoPlusOne, while the other allowed it to stay implicit. The above code should work in either case.

Coq: How to prove if statements involving strings?

I have a string a and on comparison with string b, if equals has an string c, else has string x. I know in the hypothesis that fun x <= fun c. How do I prove this below statement? fun is some function which takes in string and returns nat.
fun (if a == b then c else x) <= S (fun c)
The logic seems obvious but I am unable to split the if statements in coq. Any help would be appreciated.
Thanks!
Let me complement Yves answer pointing out to a general "view" pattern that works well in many situations were case analysis is needed. I will use the built-in support in math-comp but the technique is not specific to it.
Let's assume your initial goal:
From mathcomp Require Import all_ssreflect.
Variables (T : eqType) (a b : T).
Lemma u : (if a == b then 0 else 1) = 2.
Proof.
now, you could use case_eq + simpl to arrive to next step; however, you can also match using more specialized "view" lemmas. For example, you could use ifP:
ifP : forall (A : Type) (b : bool) (vT vF : A),
if_spec b vT vF (b = false) b (if b then vT else vF)
where if_spec is:
Inductive if_spec (A : Type) (b : bool) (vT vF : A) (not_b : Prop) : bool -> A -> Set :=
IfSpecTrue : b -> if_spec b vT vF not_b true vT
| IfSpecFalse : not_b -> if_spec b vT vF not_b false vF
That looks a bit confusing, the important bit is the parameters to the type family bool -> A -> Set. The first exercise is "prove the ifP lemma!".
Indeed, if we use ifP in our proof, we get:
case: ifP.
Goal 1: (a == b) = true -> 0 = 2
Goal 2: (a == b) = false -> 1 = 2
Note that we didn't have to specify anything! Indeed, lemmas of the form { A
} + { B } are just special cases of this view pattern. This trick works in many other situations, for example, you can also use eqP, which has a spec relating the boolean equality with the propositional one. If you do:
case: eqP.
you'll get:
Goal 1: a = b -> 0 = 2
Goal 2: a <> b -> 1 = 2
which is very convenient. In fact, eqP is basically a generic version of the type_dec principle.
If you can write an if-then-else statement, it means that the test expression a == b is in a type with two constructors (like bool) or (sumbool). I will first assume the type is bool. In that case, the best approach during a proof is to enter the following command.
case_eq (a == b); intros hyp_ab.
This will generate two goals. In the first one, you will have an hypothesis
hyp_ab : a == b = true
that asserts that the test succeeds and the goal conclusion has the following shape (the if-then-else is replaced by the then branch):
fun c <= S (fun c)
In the second goal, you will have an hypothesis
hyp_ab : a == b = false
and the goal conclusion has the following shape (the if-then-else is replaced by the else branch).
fun x <= S (fun c)
You should be able to carry on from there.
On the other hand, the String library from Coq has a function string_dec with return type {a = b}+{a <> b}. If your notation a == b is a pretty notation for string_dec a b, it is better to use the following tactic:
destruct (a == b) as [hyp_ab | hyp_ab].
The behavior will be quite close to what I described above, only easier to use.
Intuitively, when you reason on an if-then-else statement, you use a command like case_eq, destruct, or case that leads you to studying separately the two executions paths, remember in an hypothesis why you took each of these executions paths.

What is difference between `destruct` and `case_eq` tactics in Coq?

I understood destruct as it breaks an inductive definition into its constructors. I recently saw case_eq and I couldn't understand what it does differently?
1 subgoals
n : nat
k : nat
m : M.t nat
H : match M.find (elt:=nat) n m with
| Some _ => true
| None => false
end = true
______________________________________(1/1)
cc n (M.add k k m) = true
In the above context, if I do destruct M.find n m it breaks H into true and false whereas case_eq (M.find n m) leaves H intact and adds separate proposition M.find (elt:=nat) n m = Some v, which I can rewrite to get same effect as destruct.
Can someone please explain me the difference between the two tactics and when which one should be used?
The first basic tactic in the family of destruct and case_eq is called case. This tactic modifies only the conclusion. When you type case A and A has a type T which is inductive, the system replaces A in the goal's conclusion by instances of all the constructors of type T, adding universal quantifications for the arguments of these constructors, if needed. This creates as many goals as there are constructors in type T. The formula A disappears from the goal and if there is any information about A in an hypothesis, the link between this information and all the new constructors that replace it in the conclusion gets lost. In spite of this, case is an important primitive tactic.
Loosing the link between information in the hypotheses and instances of A in the conclusion is a big problem in practice, so developers came up with two solutions: case_eq and destruct.
Personnally, when writing the Coq'Art book, I proposed that we write a simple tactic on top of case that keeps a link between A and the various constructor instances in the form of an equality. This is the tactic now called case_eq. It does the same thing as case but adds an extra implication in the goal, where the premise of the implication is an equality of the form A = ... and where ... is an instance of each constructor.
At about the same time, the tactic destruct was proposed. Instead of limiting the effect of replacement in the goal's conclusion, destruct replaces all instances of A appearing in the hypotheses with instances of constructors of type T. In a sense, this is cleaner because it avoids relying on the extra concept of equality, but it is still incomplete because the expression A may be a compound expression f B, and if B appears in the hypothesis but not f B the link between A and B will still be lost.
Illustration
Definition my_pred (n : nat) := match n with 0 => 0 | S p => p end.
Lemma example n : n <= 1 -> my_pred n <= 0.
Proof.
case_eq (my_pred n).
Gives the two goals
------------------
n <= 1 -> my_pred n = 0 -> 0 <= 0
and
------------------
forall p, my_pred n = S p -> n <= 1 -> S p <= 0
the extra equality is very useful here.
In this question I suggested that the developer use case_eq (a == b) when (a == b) has type bool because this type is inductive and not very informative (constructors have no argument). But when (a == b) has type {a = b}+{a <> b} (which is the case for the string_dec function) the constructors have arguments that are proofs of interesting properties and the extra universal quantification for the arguments of the constructors are enough to give the relevant information, in this case a = b in a first goal and a <> b in a second goal.

Stuck in the construction of a very simple function

I am learning Coq. I am stuck on a quite silly problem (which has no motivation, it is really silly). I want to build a function from ]2,+oo] to the set of integers mapping x to x-3. That should be simple... In any language I know, it is simple. But not in Coq. First, I write (I explain with a lot of details so that someone can explain what I don't understand in the behaviour of Coq)
Definition f : forall n : nat, n > 2 -> nat.
I get a subgoal
============================
forall n : nat, n > 2 -> nat
which means that Coq wants a map from a proof of n>2 to the set of integers. Fine. So I want to tell it that n = 3 + p for some integer p, and then return the integer p. I write :
intros n H.
And I get the context/subgoal
n : nat
H : n > 2
============================
nat
Then i suppose that I have proved n = 3 + p for some integer p by
cut(exists p, 3 + p = n).
I get the context/subgoal
n : nat
H : n > 2
============================
(exists p : nat, 3 + p = n) -> nat
subgoal 2 (ID 6) is:
exists p : nat, 3 + p = n
I move the hypothesis in the context by
intro K.
I obtain:
n : nat
H : n > 2
K : exists p : nat, 3 + p = n
============================
nat
subgoal 2 (ID 6) is:
exists p : nat, 3 + p = n
I will prove the existence of p later. Now I want to finish the proof by exact p. So i need first to do a
destruct K as (p,K).
and I obtain the error message
Error: Case analysis on sort Set is not allowed for inductive
definition ex.
And I am stuck.
You are absolutely right! Writing this function should be easy in any reasonable programming language, and, fortunately, Coq is no exception.
In your case, it is much easier to define your function by simply ignoring the proof argument you are supplying:
Definition f (n : nat) : nat := n - 3.
You may then wonder "but wait a second, the natural numbers aren't closed under subtraction, so how can this make sense?". Well, in Coq, subtraction on the natural numbers isn't really subtraction: it is actually truncated. If you try to subtract, say, 3 from 2, you get 0 as an answer:
Goal 2 - 3 = 0. reflexivity. Qed.
What this means in practice is that you are always allowed to "subtract" two natural numbers and get a natural number back, but in order for this subtraction make sense, the first argument needs to be greater than the second. We then get lemmas such as the following (available in the standard library):
le_plus_minus_r : forall n m, n <= m -> n + (m - n) = m
In most cases, working with a function that is partially correct, such as this definition of subtraction, is good enough. If you want, however, you can restrict the domain of f to make its properties more pleasant. I've taken the liberty of doing the following script with the ssreflect library, which makes writing this kind of function easier:
Require Import Ssreflect.ssreflect Ssreflect.ssrfun Ssreflect.ssrbool.
Require Import Ssreflect.ssrnat Ssreflect.eqtype.
Definition f (n : {n | 2 < n}) : nat :=
val n - 3.
Definition finv (m : nat) : {n | 2 < n} :=
Sub (3 + m) erefl.
Lemma fK : cancel f finv.
Proof.
move=> [n Pn] /=; apply/val_inj=> /=.
by rewrite /f /= addnC subnK.
Qed.
Lemma finvK : cancel finv f.
Proof.
by move=> n; rewrite /finv /f /= addnC addnK.
Qed.
Now, f takes as an argument a natural number n that is greater than 2 (the {x : T | P x} form is syntax sugar for the sig type from the standard library, which is used for forming types that work like subsets). By restricting the argument type, we can write an inverse function finv that takes an arbitrary nat and returns another number that is greater than 2. Then, we can prove lemmas fK and finvK, which assert that fK and finvK are inverses of each other.
On the definition of f, we use val, which is ssreflect's idiom for extracting the element out of a member of a type such as {n | 2 < n}. The Sub function on finv does the opposite, packaging a natural number n with a proof that 2 < n and returning an element of {n | 2 < n}. Here, we rely crucially on the fact that the < is expressed in ssreflect as a boolean computation, so that Coq can use its computation rules to check that erefl, a proof of true = true, is also a valid proof of 2 < 3 + m.
To conclude, the mysterious error message you got in the end has to do with Coq's rules governing computational types, with live in Type, and propositional types, which live in Prop. Coq's rules forbid you from using proofs of propositions to build elements that have computational content (such as natural numbers), except in very particular cases. If you wanted, you could still finish your definition by using {p | 3 + p = n} instead of exists p, 3 + p = n -- both mean the same thing, except the former lives in Type while the latter lives in Prop.

Coordinates in Coq

I apologize if this is obviously posted somewhere, but I have been trying Google search and SO search and found nothing on this yet.
Part A.
Is there a standard library for defining coordinates/vectors and points in R^2 and R^3 in Coq? I pretty much want to do standard stuff, like adding vectors, cross products, scaling, etc.
If not, how is this for a start:
Require Import Coq.Reals.Reals.
Inductive Coordinate2 : Type := Point2: R -> R -> Coordinate2.
Definition R2plus (u:Coordinate2) (v:Coordinate2) : Coordinate2 :=
match u, v with
| (Point2 ux uy),(Point2 vx vy)=>(Point2 ((ux+vx)%R) ((uy+vy)%R))
end.
(* etc. *)
Notation "x + y" := (R2plus x y).
Also, why when I run:
Eval compute in ((2%R) < (3%R))%R.
Do I get
= (2 < 3)%R
: Prop
rather than
True
or something?
Part B.
Is this even a good idea? I want to build an algorithm which computes some things using real numbers, and prove the algorithm correct in Coq. Is Coq.Reals.Reals the right thing to be using, or is it really too abstract?
Instead of defining Coordinate2 you could also use (R * R)%type, list R, or t R 2, where t A n, defined in Vector, is a list of size n.
You might want to give your notations a scope and a delimiting key to avoid clashes with other notations.
Notation "x + y" := (R2plus x y) : r2_scope.
Delimit Scope r2_scope with R2.
Eval compute in ((Point2 0 1) + (Point2 2 3))%R2.
Prop, Set, and Type are sorts, which means something of type Prop might be defined inductively.
For example, for the nats, le is defined as
Inductive le : nat -> nat -> Prop :=
| le_n : forall n, le n n
| le_S : forall n m : nat, le n m -> le n (S m).
2 <= 2 is true because it's inhabited by le_n 2
2 <= 3 is true because it's inhabited by le_S 2 2 (le_n 2)
2 <= 4 is true because it's inhabited by le_S 2 3 (le_S 2 2 (le_n 2))
3 <= 2 is false because it's not inhabited
For 2 <= 3 to reduce to True, le would have to be defined like, for example,
Fixpoint le (n m : nat) : Prop :=
match n with
| 0 => True
| S n =>
match m with
| 0 => False
| S m => le n m
end
end.
Coq's definition of Rplus and Rlt are actually axioms. To check the definition of something use the Print command.
To answer part B, I guess it depends on how well you understand mathematical analysis and the various ways of defining the reals. If you're more familiar with numerical methods, you might want to use the rationals instead.