How to do induction on BinNums.Z in Coq/ - coq

I'm trying to do a simple function that like this
Fixpoint find_0 (n : BinNums.Z) :=
match n with
Z0 => n
| Zpos p => find_0 p
| Zneg q => find_0 q
end.
But p is positive and not Z so this is ill typed.
If I try
Fixpoint find_0 (n : BinNums.Z) :=
match n with
Z0 => n
| Zpos p => find_0 (n - 1)
| Zneg q => find_0 (n + 1)
end.
then Coq can't verify that this is strong normalizing, the error
Recursive definition of find_0 is ill-formed.
In environment
find_0 : BinNums.Z -> BinNums.Z
n : BinNums.Z
p : positive
Recursive call to find_0 has principal argument equal to
"n - 1" instead of a subterm of "n".
Recursive definition is:
"fun n : BinNums.Z =>
match n with
| 0 => n
| Z.pos _ => find_0 (n - 1)
| BinInt.Z.neg _ => find_0 (n + 1)%Z
end".
What to do in this situation?
Regards

Since the definition of Bignums.Z:
Inductive Z : Set :=
Z0 : Z
| Zpos : positive -> Z
| Zneg : positive -> Z.
is not recursive, you cannot write recursive functions over it. Instead you write a simple non recursive Definition to handle the constructors of Bignums.Z and there you call recursive functions you define on positives. It is also good style to define the functions you need on positives separataely on positives.

Every recursive function in Coq must clearly have a decreasing aspect. For many inductive types, this decreasing aspect is provided naturally by the recursive structure of this inductive type. If you look at the definition of positive, you see this:
Inductive positive : Set :=
xI : positive -> positive | xO : positive -> positive | xH : positive.
When an object p of type positive fits the pattern xO q, q is visibly smaller than p, if only as a piece of data (and here because the agreed meaning of xO is multiplication by 2, q is also numerically smaller than p).
When looking at the data type for Z, you see that there is no recursion and thus no visible decreasing pattern, where the smaller object would also be of type Z, so you cannot write a recursive function using the Fixpoint approach.
However, there exists an extension of Coq, called Equations, that will make it possible to write the function you want. The trick is that you still need to explain that something is decreasing during the recursive call. This calls for an extra object, a relation that is known to have no infinite path. Such a relation is called well-founded. Here the relation we will use is called Zwf.
From Equations Require Import Equations.
Require Import ZArith Zwf Lia.
#[export]Instance Zwf_wf (base : Z) : WellFounded (Zwf base).
Proof.
constructor; apply Zwf_well_founded.
Qed.
Equations find0 (x : Z) : Z by wf (Z.abs x) (Zwf 0) :=
find0 Z0 := Z0; find0 (Zpos p) := find0 (Zpos p - 1);
find0 (Zneg p) := find0 (Zneg p + 1).
Next Obligation.
set (x := Z.pos p); change (Zwf 0 (Z.abs (x - 1)) (Z.abs x)).
unfold Zwf. lia.
Qed.
Next Obligation.
set (x := Z.neg p); change (Zwf 0 (Z.abs (x + 1)) (Z.abs x)).
unfold Zwf. lia.
Qed.
There is a little more work than for a direct recursive function using Fixpoint, because we need to explain that we are using a well founded relation, make sure the Equations extension will find the information (this is the purpose of the Instance part of the script. Then, we also need to show that each recursive call satisfies the decrease property. Here, what decreases is the numeric value of the absolute value of the integer.
The Equations tool will gives you a collection of theorems to help reason on the find0 function. In particular, theorems find0_equation1, find0_equation2, and find0_equation3 really express that we defined a function that follows the algorithm you intended.

Related

How do I describe a multiplication of vectorized matrices?

I want to calculate a product of huge (specific) matrices. From a point complexity of view, the product should be taken the form of an elementwise expression.
I tried to "vectorize" the matrices with mxvec / vec_mx and calculate the product via one dimensional streams. But indices access was blocked by the term of enum ('I_p * 'I_q).
I want to know a nth value of enum ('I_p * 'I_q) because I want to decscribe a multiplication of matrices in the form of a primitive expression in an underlying field.
How do I do this? In particular, how do I prove this statement?
From mathcomp Require Import all_ssreflect.
Lemma nth_enum_prod p q (a : 'I_q) :
val a = index (ord0, a) (enum (prod_finType (ordinal_finType p.+1) (ordinal_finType q))).
I'm surprised you need to vectorize the matrices if your definition is point-wise, usually you should be able to define your result as \matrix_(i, j) op, for example the standard definition of matrix multiplication is:
\matrix_(i, k) \sum_j (A i j * B j k).
By the way, a quick "dirty" proof of your lemma is:
Lemma nth_enum_prod p q (a : 'I_q) : val a = index (#ord0 p, a) (enum predT).
Proof.
have /(_ _ 'I_q) pair_snd_inj: injective [eta pair ord0] by move => n T i j [].
have Hfst : (ord0, a) \in [seq (ord0, x2) | x2 <- enum 'I_q].
by move=> n; rewrite mem_map /= ?mem_enum.
rewrite enumT !unlock /= /prod_enum enum_ordS /= index_cat {}Hfst.
by rewrite index_map /= ?index_enum_ord.
Qed.
but indeed if you find yourself using this it means you are into a different kind of problem. I just posted it as an illustration on how to manipulate this kind of expressions.
edit: based on your comment, a more principled way to manipulate the above is to define a lemma about index and products; I've left the full proof as an exercise, but the outline is:
Lemma index_allpairs (T U : eqType) (x : T) (y : U) r s :
(* TODO: Some conditions are missing here *)
index (x,y) [seq (x,y) | x <- r , y <- s] =
size s * (index x r) + index y s.
Proof.
Admitted.
Lemma index_ord_allpairs p q (x : 'I_p) (y : 'I_q) :
index (x,y) [seq (x,y) | x <- enum 'I_p , y <- enum 'I_q] = q * x + y.
Proof. by rewrite index_allpairs ?mem_enum ?size_enum_ord ?index_enum_ord. Qed.
Lemma nth_enum_prod p q (a : 'I_q) : val a = index (#ord0 p, a) (enum predT).
Proof. by rewrite enumT unlock index_ord_allpairs muln0. Qed.

How to prove mathematical induction formulae in LEAN theorem prover?

Can anyone help me understand how to write the proof of a simple result that can be easily obtained by induction, for example the formula for the sum of the first n natural numbers: 1+2+...+n = n(n+1)/2, using the LEAN theorem prover?
Here is my proof. You'll need mathlib for it to work.
import algebra.big_operators tactic.ring
open finset
example (n : ℕ) : 2 * (range (n + 1)).sum id = n * (n + 1) :=
begin
induction n with n ih,
{ refl },
{ rw [sum_range_succ, mul_add, ih, id.def, nat.succ_eq_add_one],
ring }
end
range (n + 1) is the set of natural numbers less than n + 1, i.e. 0 to n.
I used the finset.sum function. If s is a finset and f is a function, then
s.sum f is $\sum_{x \in s} f(x)$.
The induction tactic does induction. There are then two cases. The case n = 0 can be done with refl since this is nothing more than a computation.
The inductive step can be done with rw. Using a VSCode you can click after each comma in my proof to see what each rw does. This gets it into a form that the ring tactic will solve.

Church numerals

There are 4 exercises in Poly module related to Church numerals:
Definition cnat := forall X : Type, (X -> X) -> X -> X.
As far as I understand cnat is a function that takes a function f(x), it's argument x and returns it's value for this argument: f(x).
Then there are 4 examples for 0, 1, 2 and 3 represented in Church notation.
But how to solve this? I understand that we must apply the function one more time. The value returned by cnat will be the argument. But how to code it? Use a recursion?
Definition succ (n : cnat) : cnat
(* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
Update
I tried this:
Definition succ (n : cnat) : cnat :=
match n with
| zero => one
| X f x => X f f(x) <- ?
Remember that a Church numeral is a function of two arguments (or three if you also count the type). The arguments are a function f and a start value x0. The Church numeral applies f to x0 some number of times. Four f x0 would correspond to f (f (f (f x0))) and Zero f x0 would ignore f and just be x0.
For the successor of n, remember that n will apply any function f for you n times, so if your task is to create a function applies some f on some x0 n+1 times, just leave the bulk of the work to the church numeral n, by giving it your f and x0, and then finish off with one more application of f to the result returned by n.
You won't be needing any match because functions are not inductive data types that can be case analysed upon...
You can write the Definition for succ in the following way:
Definition succ (n : cnat) : cnat :=
fun (X : Type) (f : X -> X) (x : X) => f (n X f x).
As far as I understand cnat is a function that takes a function f(x), it's argument x and returns it's value for this argument: f(x).
Note that cnat itself isn't a function. Instead, cnat is the type of all such functions. Also note that elements of cnat take X as an argument as well. It'll help to keep the definition of cnat in mind.
Definition succ (n: cnat): cnat.
Proof.
unfold cnat in *. (* This changes `cnat` with its definition everywhere *)
intros X f x.
After this, our goal is just X, and we have n : forall X : Type, (X -> X) -> X -> X, X, f and x as premises.
If we applied n to X, f and x (as n X f x), we would get an element of X, but this isn't quite what we want, since the end result would just be n again. Instead, we need to apply f an extra time somewhere. Can you see where? There are two possibilities.

How to formalize the termination of a term reduction relation in Coq?

I have a term rewriting system (A, →) where A is a set and → a infix binary relation on A. Given x and y of A, x → y means that x reduces to y.
To implement some properties I simply use the definitions from Coq.Relations.Relation_Definitions and Coq.Relations.Relation_Operators.
Now I want to formalize the following property :
→ is terminating, that is : there is no infinite descending chain a0 → a1 → ...
How can I achieve that in Coq ?
Showing that a rewriting relation terminates is the same thing as showing that it is well-founded. This can be encoded with an inductive predicate in Coq:
Inductive Acc {A} (R : A -> A -> Prop) (x: A) : Prop :=
Acc_intro : (forall y:A, R x y -> Acc R y) -> Acc R x.
Definition well_founded {A} (R : A -> A -> Prop) :=
forall a:A, Acc R a.
(This definition is essentially the same one of the Acc and well_founded predicates in the standard library, but I've changed the order of the relation to match the conventions used in rewriting systems.)
Given a type A and a relation R on A, Acc R x means that every sequence of R reductions starting from x : A is terminating; thus, well_founded R means that every sequence starting at any point is terminating. (Acc stands for "accessible".)
It might not be very clear why this definition works; first, how can we even show that Acc R x holds for any x at all? Notice that if x is an element does not reduce (that is, such that R x y never holds for any y), then the premise of Acc_intro trivially holds, and we are able to conclude Acc R x. For instance, this would allow us to show Acc gt 0. If R is indeed well-founded, then we can work backwards from such base cases and conclude that other elements of A are accessible. A formal proof of well-foundedness is more complicated than that, because it has to work generically for every x, but this at least shows how we could show that each element is accessible separately.
OK, so maybe we can show that Acc R x holds. How do we use it, then?
With the induction and recursion principles that Coq generates for Acc; for instance:
Acc_ind : forall A (R : A -> A -> Prop) (P : A -> Prop),
(forall x : A, (forall y : A, R x y -> P y) -> P x) ->
forall x : A, Acc R x -> P x
When R is well-founded, this is simply the principle of well-founded induction. We can paraphrase it as follows. Suppose that we can show that P x holds for any x : A while making use of an induction hypothesis that says that P y holds whenever R x y. (Depending on the meaning of R, this could mean that x steps to y, or that y is strictly smaller than x, etc.) Then, P x holds for any x such that Acc R x. Well-founded recursion works similarly, and intuitively expresses that a recursive definition is valid if every recursive call is performed on "smaller" elements.
Adam Chlipala's CPDT has a chapter on general recursion that has a more comprehensive coverage of this material.

How to build a function implicitly in Coq?

I am trying to prove that every group has an inverse function.
I have defined a group as follows:
Record Group:Type := {
G:Set;
mult:G->G->G;
e:G;
assoc:forall x y z:G, mult x (mult y z)=mult (mult x y) z;
neut:forall x:G, mult e x=x /\ mult x e=x;
inverse:forall x:G,exists y:G, mult x y = e
}.
I am aware that it is better to just replace the inverse axiom by inverse:forall x:G, {y: mult x y = e}., or even inverse:G->G. is_inverse:forall x:G, mult x (inverse x)=e., but I prefer my definition, mainly because I want the definition to be identical to the one given in a classroom.
So I have included a suitable version of the axiom of choice:
Axiom indefinite_description : forall (A : Type) (P: A->Prop), ex P -> sig P.
Axiom functional_choice : forall A B (R:A->B->Prop), (forall x, exists y, R x y) -> (exists f, forall x, R x (f x)).
Now I can prove my claim:
Lemma inv_func_exists(H:Group):exists inv_func:G H->G H, (forall x:G H, mult H x (inv_func(x))=e H).
generalize (inverse H).
apply functional_choice.
Qed.
Now that I have proved the existence, I would like to define an actual function. Here I feel that things start to go messy. The following definition creates an actual function, but seems to ugly and complicated:
Definition inv_func(H:Group):G H->G H.
pose (inv_func_exists H).
pose indefinite_description.
generalize e0 s.
trivial.
Qed.
Lastly, I would like to prove that inv_func is actually an inverse function:
Lemma inv_func_is_inverse:forall (H:Group), forall x:(G H), mult H x (inv_func H x)=e H.
I can see that Coq knows how inv_func was defined (e.g. Print inv_func), but I have no idea how to formally prove the lemma.
To conclude, I would appreciate suggestions as to how to prove the last lemma, and of better ways to define inv_func (but under my definition of group, without including the existence of such a function in the group definition. I believe the question could be relevant in many other situations when one can prove some correspondence for each element and needs to build this correspondence as a function).
There are quite a few questions inside your question. I'll try to address all of them:
First, there is no reason to prefer exists x, P + description over {x | P}, indeed, it seems weird you do so. {x | P} is perfectly valid as "there exists a x that can be computed" and I would rather use that definition with your groups.
Secondly, when creating definitions using tactics, you should end the proof with the command Defined. Using Qed will declare the definition "Opaque", which means it cannot be expanded, then preventing you proof.
The way to extract the witness from your definition is by using a projection. In this case, proj1_sig.
Using all the above we arrive at:
Definition inv_func' (H:Group) (x : G H) : G H.
Proof.
destruct (inverse H x) as [y _].
exact y.
Defined.
Definition inv_func (H:Group) (x : G H) : G H := proj1_sig (inverse H x).
Lemma inv_func_is_inverse (H:Group) (x: G H) : mult H x (inv_func H x) = e H.
Proof. now unfold inv_func; destruct (inverse H x). Qed.