Suppose I want to define a type of Monomials in Coq. These would be finite maps from some ordered set of variables to nat where, say, x²y³ is represented by the map that sends x to 2, y to 3 and where everything else gets the default value, zero.
The basic definitions don't seem so hard:
Require Import
Coq.FSets.FMapFacts
Coq.FSets.FMapList
Coq.Structures.OrderedType.
Module Monomial (K : OrderedType).
Module M := FMapList.Make(K).
Module P := WProperties_fun K M.
Module F := P.F.
Definition Var : Type := M.key.
Definition Monomial : Type := M.t nat.
Definition mon_one : Monomial := M.empty _.
Definition add_at (a : option nat) (b : option nat) : option nat :=
match a, b with
| Some aa, Some bb => Some (aa + bb)
| Some aa, None => Some aa
| None, Some bb => Some bb
| None, None => None
end.
Definition mon_times (M : Monomial) (M' : Monomial) : Monomial :=
M.map2 add_at M M'.
End Monomial.
At this point, I'd like to prove something like:
Lemma mon_times_comm : forall M M', mon_times M M' = mon_times M' M.
I can see how to prove that the two maps are Equal using the lemma Equal_mapsto_iff, but I'd really like to say that my type really represents monomials and that multiplication is genuinely commutative (and the maps are eq).
I'm pretty new to Coq: is this a reasonable thing to try to prove?
Also, I realise that this might depend on the finite map implementation: if FMapList was the wrong choice and another implementation makes this easier, please point me at that!
I can see how to prove that the two maps are Equal using the lemma Equal_mapsto_iff, but I'd really like to say that my type really represents monomials and that multiplication is genuinely commutative (and the maps are eq).
I'm pretty new to Coq: is this a reasonable thing to try to prove?
Also, I realise that this might depend on the finite map implementation: if FMapList was the wrong choice and another implementation makes this easier, please point me at that!
Indeed, you are on the right track. The set type you are using doesn't have the property that two sets with the same elements are definitionally equal in Coq. As such sets are implemented as binary trees you may have Node(A, Node(B,C)) <> Node(Node(A,B),C).
In particular, having a good "set type" is an extremely challenging task in Coq due to several issues, see the anwser How to define set in coq without defining set as a list of elements for a bit more of discussion.
Doing proper algebra does indeed require a lot of complex infrastructure, #ErikMD's pointer is the right one, you should have a look at math-comp and related papers to get an understanding on the state of the art. Of course, keep experimenting!
Regarding the formalization of monomials and multivariate polynomials in Coq, you could consider using the multinomials library. It is available on OPAM:
$ opam install coq-mathcomp-multinomials
and it naturally proves a similar result to your mon_times_comm lemma:
From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq.
From mathcomp Require Import choice finfun tuple fintype ssralg bigop.
From SsrMultinomials Require Import freeg mpoly.
Lemma test1 (n : nat) (m1 m2 : 'X_{1..n}) : (m1 + m2 = m2 + m1)%MM.
Proof.
move=> *.
by rewrite addmC.
Qed.
Lemma test2 (n : nat) (R : comRingType) (p q : {mpoly R[n]}) :
(p * q = q * p)%R.
Proof.
move=> *.
by rewrite mpoly_mulC.
Qed.
Note that the multinomials library is built upon the MathComp library that is strongly related to the SSReflect extension of the Coq proof language.
Finally, note that this library is very convenient to develop Coq proofs involving multinomial polynomials, but doesn't directly allow computing with these Coq datatypes (Eval vm_compute in ...). If you are also interested in that aspect, you may also want to take a look at the CoqEAL library (and in particular its multipoly.v theory that relies on FMaps).
Related
It feels like the following Coq statement should be true constructively:
Require Import Decidable.
Lemma dec_search_nat_counterexample (P : nat -> Prop) (decH : forall i, decidable (P i))
: (~ (forall i, P i)) -> exists i, ~ P i.
If there were an upper bound, I'd expect to be able to show something of the form "suppose that not every i < N satisfies P i. Then there is an i < N where ~ P i". Indeed, you could actually write a function to find a minimal example by searching from zero.
Of course, there's not an upper bound for the original claim, but I feel like there should be an inductive argument to get there from the bounded version above. But I'm not clever enough to figure out how! Am I missing a clever trick? Or is there a fundamental reason that this cann't work, despite the well-orderedness of the natural numbers?
Reworked answer after Meven Lennon-Bertrand's comment
This statement is equivalent to Markov's principle with P and ~P exchanged. Since P is decidable we have P <-> (~ ~ P), so that one can do this replacement.
This paper (http://pauillac.inria.fr/~herbelin/articles/lics-Her10-markov.pdf) suggest that Markov's principle is not provable in Coq, since the author (one of the authors of Coq) suggests a new logic in this paper which allows to prove Markov's principle.
Old answer:
This is morally the "Limited Principle of Omniscience" - LPO (see https://en.wikipedia.org/wiki/Limited_principle_of_omniscience). It requires classical axioms to prove it in Coq - or you assert itself as an axiom.
See e.g.:
Require Import Coquelicot.Markov.
Check LPO.
Print Assumptions LPO.
Afair there is no standard library version of it.
I'm using Coq and Coquelicot Library, and I'd like to know a better way to handle limit easily.
When I want to prove \lim_{x \to 1} (x^2-1)/(x-1) = 2, I code as follows.
Require Import Reals Lra.
From mathcomp Require Import all_ssreflect.
From Coquelicot Require Import Coquelicot.
Lemma lim_1_2 : is_lim (fun x:R => (x^2 - 1)/(x - 1)) 1 2.
Proof.
apply (is_lim_ext_loc (fun x:R => x + 1)).
- rewrite /Rbar_locally' /locally' /within /locally.
exists (mkposreal 1 Rlt_0_1).
move => y Hyball Hyneq1.
field; lra.
- apply is_lim_plus'; [apply is_lim_id | apply is_lim_const].
Qed.
In this example, I explicitly write the goal term (fun x:R => x + 1). Is there any way to transform (fun x:R => (x^2 - 1)/(x - 1)) to (fun x:R => x + 1) like rewrite tactic? In other words, I'm looking for a similar tactic as under for eq_big_nat.
Coquelicot is optimized for ease of use and uses total functions rather than dependent restrictions wherever possible - e.g. you can write down an integral without having a prove that it exists, but as far as I know this does not extend to division by zero. To make your above equation work, one would need a definition of division, which somehow can handle the 0/0 you get for x=1. One can define a division for functions (polynomials) which can handle this in a reasonable way - and this is what you are using implicitly by stating that this makes sense, but one cannot define division for individual real numbers which can handle 0/0 in the way you would like. But the division operator you use above is a division on individual numbers and not on polynomials. In informal mathematics one is sometimes a bit sloppy about such things.
Besides the 0/0 issue, you also would have to use the axiom of functional extensionality, which states that two functions are equal in case they are equal for each point.
Here is a snippet of Coq which shows what one can be done and where the issues are :
Require Import Reals.
Require Import Lra.
Require Import FunctionalExtensionality.
Open Scope R.
Definition dom := {x : R | x<>1}.
Definition dom2R (x : dom) : R := proj1_sig x.
Coercion dom2R : dom >-> R.
Example Example:
(fun x : dom => (x^2 - 1)/(x - 1))
= (fun x : dom => x + 1).
Proof.
apply functional_extensionality.
intros [x xH].
cbv.
field.
lra.
Qed.
All in all it is not that bad with the implicit coercion from dom to Real, although the function is in reality more complicated than it looks since each x is an implicit coercion projecting from dom to R.
Also one could have an axiom of functional extensionality, which works if the domain of one function is a subset of the domain of the other function. I am not sure if this would be consistent, though and it would also require a non standard definition of equality because with the usual equality only things of the same type can be equal. This would allow you to equate the polynomial fraction with the polynomial on the full R.
I hope this explains why things are as they are. Coquelicot relies on the division operator from the standard library, for which you can't prove anything in case the denominator is zero. This is sometimes inconvenient, but to my knowledge (which is not very extensive - I am physicist not mathematician) up to now nobody came up with a definition of division which allows you to easily do what you want.
I'm interested in trying my hand at constructing set theory using Coq. I would like to define a type sets without specifying what its members are, and a function mapping two sets to a Prop
Definition elem (s1 s1 : sets) : Prop.
I would then make the axioms of set theory hypotheses, and express theorems as (for example)
Theorem : ZFC -> (forall s : sets, ~ elem s s).
However, the syntax above doesn't work. Is this idea something that can be done in Coq? Is there a better way to accomplish this goal in Coq? I am very new to Coq, so I apologize if there is an obvious way of doing this that I don't know.
You need to give names to theorems. And for postulating things, use Parameter and Axiom (which technically mean the same thing but you can use to informally distinguish between concepts and facts).
Parameter set : Type.
Parameter elem : set -> set -> Prop.
Axiom set_extensionality : forall x y, (forall z, elem z x <-> elem z y) -> x = y.
(* etc. *)
In comparison, Definition and Theorem are used for defining and proving things. Having postulated the ZFC axioms, you can prove that a set is not an element of itself. The Theorem command takes a theorem name first (used to refer to it in the future):
Theorem no_self_elem : forall x, ~ elem x x.
Proof.
(* tactics here. *)
Qed.
I have used functional induction in this proof that I have been trying. As far as I understand, it essentially allows one to perform induction on all parameters of a recursive function "at the same time".
The tactics page states that:
The tactic functional induction performs case analysis and induction following the definition of a function. It makes use of a principle generated by Function
I assume that principle is something technical whose definition I do not know. What does it mean?
In the future, how do I find out what this tactic is doing? (Is there some way to access the LTac?)
Is there a more canonical way of solving the theorem which I pose below?
Require Import FunInd.
Require Import Coq.Lists.List.
Require Import Coq.FSets.FMapInterface.
Require Import FMapFacts.
Require Import FunInd FMapInterface.
Require Import
Coq.FSets.FMapList
Coq.Structures.OrderedTypeEx.
Module Import MNat := FMapList.Make(Nat_as_OT).
Module Import MNatFacts := WFacts(MNat).
Module Import OTF_Nat := OrderedTypeFacts Nat_as_OT.
Module Import KOT_Nat := KeyOrderedType Nat_as_OT.
(* Consider using https://coq.inria.fr/library/Coq.FSets.FMapFacts.html *)
(* Consider using https://coq.inria.fr/library/Coq.FSets.FMapFacts.html *)
(* Consider using https://coq.inria.fr/library/Coq.FSets.FMapFacts.html *)
Definition NatToNat := MNat.t nat.
Definition NatToNatEmpty : NatToNat := MNat.empty nat.
(* We wish to show that map will have only positive values *)
Function insertNats (n: nat) (mm: NatToNat) {struct n}: NatToNat :=
match n with
| O => mm
| S (next) => insertNats next (MNat.add n n mm)
end.
Theorem insertNatsDoesNotDeleteKeys:
forall (n: nat) (k: nat) (mm: NatToNat),
MNat.In k mm -> MNat.In k (insertNats n mm).
intros n.
intros k mm.
intros kinmm.
functional induction insertNats n mm.
exact kinmm.
rewrite add_in_iff in IHn0.
assert(S next = k \/ MNat.In k mm).
auto.
apply IHn0.
exact H.
Qed.
The "principle" just means "an induction principle" - a complete set of cases that must be proved in order to prove some motive "inductively".
The difference between Function and Fixpoint in Coq is that the former creates an induction principle and recursion principle based on the given definition, and then each return value is passed in (as a lambda, if there are variables bound by case analysis or there is a recursive call's value involved). This generally computes slower. The principles generated are with respect to a generated Inductive type, each variant of which is a case of the function's call scheme. The latter Fixpoint uses Coq's limited termination analysis to justify the well-foundedness of a function's recursion*. Fixpoint is faster, because it uses OCaml's own pattern matching and direct recursion in computation.
How is the induction scheme created? First, all the function parameters are abstracted into a forall. Then, each branch of a match expression creates a new case to prove for the scheme (the number of cases multiplies for each nested match). All the "return" positions in a function are in scope of some number of match expressions' bindings; each binding is an argument to an induction case that must produce the motive on the reconstructed arguments (e.g., if in the case of a list A's cons, we have an a : A and a list_a : list A binding, so then we must produce a Motive (cons a list_a) result). If there is a recursive call with the list_a argument, then we get a further binding of an induction hypothesis of type Motive list_a.
An actual Coq implementer will probably correct me on the specifics of the above, but it's more or less how induction schemes are inferred from well-founded recursive functions.
This is all fairly rough, and better explained in the documentation on Function and Functional Scheme.
The termination analysis is maybe was too smart for its own good. It needed to be revised (by IIRC Maxime Dénès, good job) following a proof of False given (a consequence of) the univalence axiom.
I am having trouble with formalizing definitions of the following form: define an integer such that some property holds.
Let's say that I formalized the definition of the property:
Definition IsGood (x : Z) : Prop := ...
Now I need a definition of the form:
Definition Good : Z := ...
assuming that I proved that an integer with the property exists and is unique:
Lemma Lemma_GoodExistsUnique : exists! (x : Z), IsGood x.
Is there an easy way of defining Good using IsGood and Lemma_GoodExistsUnique?
Since, the property is defined on integer numbers, it seems that no additional axioms should be necessary. In any event, I don't see how adding something like the axiom of choice can help with the definition.
Also, I am having trouble with formalizing definitions of the following form (I suspect this is related to the problem I described above, but please indicate if that is not the case): for every x, there exists y, and these y are different for different x. Like, for example, how to define that there are N distinct good integer numbers using IsGood:
Definition ThereAreNGoodIntegers (N : Z) (IsGood : Z -> Prop) := ...?
In real-world mathematics, definitions like that occur every now and again, so this should not be difficult to formalize if Coq is intended to be suitable for practical mathematics.
The short answer to your first question is: in general, it is not possible, but in your particular case, yes.
In Coq's theory, propositions (i.e., Props) and their proofs have a very special status. In particular, it is in general not possible to write a choice operator that extracts the witness of an existence proof. This is done to make the theory compatible with certain axioms and principles, such as proof irrelevance, which says that all proofs of a given proposition are equal to each other. If you want to be able to do this, you need to add this choice operator as an additional axiom to your theory, as in the standard library.
However, in certain particular cases, it is possible to extract a witness out of an abstract existence proof without recurring to any additional axioms. In particular, it is possible to do this for countable types (such as Z) when the property in question is decidable. You can for instance use the choiceType interface in the Ssreflect library to get exactly what you want (look for the xchoose function).
That being said, I would usually advice against doing things in this style, because it leads to unnecessary complexity. It is probably easier to define Good directly, without resorting to the existence proof, and then prove separately that Good has the sought property.
Definition Good : Z := (* ... *)
Definition IsGood (z : Z) : Prop := (* ... *)
Lemma GoodIsGood : IsGood Good.
Proof. (* ... *) Qed.
Lemma GoodUnique : forall z : Z, IsGood z -> z = Good.
If you absolutely want to define Good with an existence proof, you can also change the proof of Lemma_GoodExistsUnique to use a connective in Type instead of Prop, since it allows you to extract the witness directly using the proj1_sig function:
Lemma Lemma_GoodExistsUnique : {z : Z | Good z /\ forall z', Good z' -> z' = z}.
Proof. (* ... *) Qed.
As for your second question, yes, it is a bit related to the first point. Once again, I would recommend that you write down a function y_from_x with type Z -> Z that will compute y given x, and then prove separately that this function relates inputs and outputs in a particular way. Then, you can say that the ys are different for different xs by proving that y_from_x is injective.
On the other hand, I'm not sure how your last example relates to this second question. If I understand what you want to do correctly, you can write something like
Definition ThereAreNGoodIntegers (N : Z) (IsGood : Z -> Prop) :=
exists zs : list Z,
Z.of_nat (length zs) = N
/\ NoDup zs
/\ Forall IsGood zs.
Here, Z.of_nat : nat -> Z is the canonical injection from naturals to integers, NoDup is a predicate asserting that a list doesn't contain repeated elements, and Forall is a higher-order predicate asserting that a given predicate (in this case, IsGood) holds of all elements of a list.
As a final note, I would advice against using Z for things that can only involve natural numbers. In your example, your using an integer to talk about the cardinality of a set, and this number is always a natural number.