I'm trying to define a notation for modulo equivalence relation:
Inductive mod_equiv : nat -> nat -> nat -> Prop :=
| mod_intro_same : forall m n, mod_equiv m n n
| mod_intro_plus_l : forall m n1 n2, mod_equiv m n1 n2 -> mod_equiv m (m + n1) n2
| mod_intro_plus_r : forall m n1 n2, mod_equiv m n1 n2 -> mod_equiv m n1 (m + n2).
(* 1 *) Notation "x == y 'mod' z" := (mod_equiv z x y) (at level 70).
(* 2 *) Notation "x == y % z" := (mod_equiv z x y) (at level 70).
(* 3 *) Notation "x == y %% z" := (mod_equiv z x y) (at level 70).
All three notations are accepted by Coq. However, I can't use the notation to state a theorem in some cases:
(* 1 *)
Theorem mod_equiv_sym : forall (m n p : nat), n == p mod m -> p == n mod m.
(* Works fine as-is, but gives error if `Arith` is imported before:
Syntax error: 'mod' expected after [constr:operconstr level 200] (in [constr:operconstr]).
*)
(*************************************)
(* 2 *)
Theorem mod_equiv_sym : forall (m n p : nat), n == p % m -> p == n % m.
(* Gives the following error:
Syntax error: '%' expected after [constr:operconstr level 200] (in [constr:operconstr]).
*)
(*************************************)
(* 3 *)
Theorem mod_equiv_sym : forall (m n p : nat), n == p %% m -> p == n %% m.
(* Works just fine. *)
The notation mod is defined under both Coq.Init.Nat and Coq.Arith.PeanoNat at top level. Why is the new notation x == y 'mod' z fine in one environment but not in the other?
The notation % seems to conflict with the built-in % notation, yet the Coq parser gives almost the same error message as the mod case, and the message isn't very helpful in either case. Is this intended behavior? IMO, if the parser can't understand a notation inside such a trivial context, the notation shouldn't have been accepted in the first place.
Your first question has an easy answer. The initial state of Coq is (in part) determined by Coq.Init.Prelude, which (as of this answer) contains the line
Require Coq.Init.Nat.
This is to say, Coq.Init.Prelude isn't imported, only made available with Require. Notations are only active if the module containing them is imported. If the notation is declared local (Local Notation ...) then even importing the module doesn't activate the notation.
The second question is trickier and delves into how Coq parses notations. Let's start with an example that works. In Coq.Init.Notations (which is actually imported in Coq.Init.Prelude), the notation "x <= y < z" is reserved.
Reserved Notation "x <= y < z" (at level 70, y at next level).
In Coq.Init.Peano (which is also imported), a meaning is given to the notation. We won't really worry about that part, since we're mostly concerned with parsing.
To see what effect reserving a notation has, you can use the vernacular command Print Grammar constr.. This will display a long list of everything that goes into parsing a constr (a basic unit of Coq's grammar). The entry for this notation is found a ways down the list.
| "70" RIGHTA
[ SELF; "?="; NEXT
[...]
| SELF; "<="; NEXT; "<"; NEXT
[...]
| SELF; "="; NEXT ]
We see that the notation is right associative (RIGHTA)1 and lives at level 70. We also see that the three variables in the notation, x, y and z are parsed at level 70 (SELF), level 71 (NEXT) and level 71 (NEXT) respectively.2
During parsing, Coq starts at level 0 and looks at the next token. Until there's a token that should be parsed at the current level, the level is increased. So notations with lower levels take precedence over those with higher level. (This is conceptually how it works - it's probably optimized a bit).
When a complex notation is found, such as after "5 <= ", the parser remembers the grammar of that notation3: SELF; "<="; NEXT; "<"; NEXT. After "5 <=", we parse y at level 71, meaning that if nothing works at less than level 71, we stop trying to parse y and move on.
After that, the next token has to be "<", then we parse z at level 71 if it is.
The great thing about levels is that it allows interaction with other notations without needing parentheses. For example, in the code 1 * 2 < 3 + 4 <= 5 * 6, we don't need parentheses because * and + are declared at lower levels (40 and 50 respectively). So when we're parsing y (at level 71), we're able to parse all of 3 + 4 before moving on to <= z. Additionally, when we parse z, we can capture 5 * 6 because * parses at a lower level than the parsing level for z.
Alright, now that we understand that, we can figure out what's going on in your case.
When Arith (or Nat) are imported, mod becomes a notation. Specifically we have a left associative notation at level 40 whose grammar is SELF; "mod"; NEXT (use Print Grammar constr. to check). When you define your mod notation, the entry is right associative at level 70 with grammar SELF; "=="; constr:operconstr LEVEL "200"; "mod"; NEXT. The middle section just means that y is parsed at level 200 (as a constr - just like everything else we've talked about).
Thus, when parsing n == p mod m, we parse n == fine, then start parsing y at level 200. Since Arith's mod is only at level 40, that's how we'll parse p mod m. But then our x == y mod z notation is left hanging. We're at the end of the statement and mod z still hasn't been parsed.
Syntax error: 'mod' expected after [constr:operconstr level 200] (in [constr:operconstr]).
(does the error make more sense now?)
If you really want to use your mod notation while still using Arith's mod notation, you'll need to parse y at a lower level. Since x mod y is at level 40, we could make y be level 39 with
Notation "x == y 'mod' z" := (mod_equiv z x y) (at level 70, y at level 39).
Since arithmetic operations are at levels 40 and above, that means that we'd need to write 5 == (3 * 4) mod 7 using parentheses.
For your "%" notation, it's going to be difficult. "%" is normally used for scope delimitation (e.g. (x + y)%nat) and binds very tightly at level 1. You could make y parse at level 0, but that means that no notations at all can be used for y without parentheses. If that's acceptable, go ahead.
Since "%%" doesn't clash with anything (in the standard library), you're free to use it here at whatever level is convenient. You may want to make y parse at a lower level (y at next level is pretty standard), but it's not necessary.
Right associativity is the default. Apparently Coq's parser doesn't have a "no associativity" option, so even if you explicitly say "no associativity", it's still registered as right associative. This doesn't often cause trouble in practice.
This is why the notation is reserved with "y at the next level". By default, variables in the middle of the notation are parsed at level 200, which can be seen by reserving a similar notation like Reserved Notation "x ^ y ^ z" (at level 70). and using Print Grammar constr. to see the parsing levels. As we'll see, this is what happens with x == y mod z.
What happens if more than one notation starts with "5 <="? The one with the lower level will obviously be taken, but if they have the same level, it tries both and backtracks if it doesn't parse. However, if one notation finishes, it doesn't backtrack even if that choice causes trouble later. I'm not sure of the exact rules, but I suspect it depends on which notation is declared first.
Related
I'm trying to overload the notation for +. The following doesn't work:
Definition my_add (n m :nat):= n + m.
Fail Notation "x + y":= (my_add x y) (at level 50, y at next level).
Fails with the message Notation "_ + _" is already defined at level 50 with arguments constr at level 50, constr at next level while it is now required to be at level 50 with arguments constr at next level, constr at next level.
Which suggests that I need to bind x at level 50.
Definition my_add (n m :nat):= n + m.
Fail Notation "x + y":= (my_add x y) (at level 50, x at level 50, y at next level).
Fail with The level of the leftmost non-terminal cannot be changed..
I'm sure I have defined this notation before, so perhaps this is a recent change to Coq, or am I forgetting something obvious?
Symbols in notations must have unique precedences and associativity. So for a preexisting notation, no annotation is necessary since it's already set:
Notation "x + y":= (my_add x y).
For some reason you can set associativity alone. You can also set both level and associativity. In any case, they have to match the preexisting values, if any.
Notation "x + y":= (my_add x y) (left associativity).
Notation "x + y":= (my_add x y) (at level 50, left associativity).
You can also use notation scopes in order to use the same symbol with different meanings, with various bells and whistles to control how they are set. See the manual.
I would like to create infix notations for (overloaded) operations. I apply the - to my knowledge - standard two-step approach in Coq:
Typeclass used for actual operator overloading (e.g. overload add
operation)
Notation scope used for definition of operator symbol
(e.g. infix notation '+')
This approach seems to work fine. E.g. overloading of the '-' symbol (which is used at least once in the predefined notation scope nat_scope) poses no problems. However, the '+' and '*' symbols (also used in the predefined notation scope nat_scope) lead to erros in certain circumstances. Is there anything special about the '+' and '*' symbols in Coq that has to be considered when adding them to a new notation scope?
Example
Let's model classical sets as predicates, i.e. as functions of type A->Prop:
Definition pred1 (a:nat) := a=1. (* pred1 corresponds to {1} *)
Definition pred2 (a:nat) := a=1 \/ a=2. (* pred2 corresponds to {1,2} *)
Union (addition) is modelled as the overloaded operation pred_add via the typeclass PredAdd and corresponding typeclass instances. For the sake of simplicity only the typeclass instance add_elem (addition of elements to sets) is provided:
Class PredAdd (X Y Z: Type) := {pred_add: X->Y->Z->Prop}.
Instance add_elem {A:Type}: PredAdd (A->Prop) (A) (A) := {
pred_add (P:A->Prop) (a:A) (x:A) := P x \/ x=a
}.
The infix notation '+' is used for the operation pred_add:
Declare Scope mypred_scope.
Notation "x + y" := (pred_add x y) (at level 50, left associativity): mypred_scope.
Open Scope mypred_scope.
Now, let's use the test case {1} + 2 = {1,2} to see what works and what does not work.
Operator overloading and infix notation '+' seem to work fine (at first glance):
Example ex1: (pred_add pred1 2) 1. unfold pred_add, pred1; simpl; auto. Qed.
Example ex2: forall (p1 p2:nat->Prop) (x:nat),
p1 = pred1 + 2 -> p2 = pred2 -> p1 x=p2 x.
unfold pred_add, pred1, pred2; intros; subst; auto.
Qed.
However, the application of notation '+' fails in certain cases.
E.g. in the following case:
Fail Example ex2: (pred1 + 2) 2.
we get the error message:
The command has indeed failed with message: The term "pred1" has type
"nat -> Prop" while it is expected to have type "Type".
Interestingly, the outcome seems to depend on the particular choice of the notation symbol.
The same example works fine with e.g. the symbol '-':
Notation "x - y" := (pred_add x y) (at level 50, left associativity): mypred_scope.
Example ex3: (pred1 - 2) 2. unfold pred_add, pred1; simpl; auto. Qed.
but fails with the notation symbol '*':
Notation "x * y" := (pred_add x y) (at level 40, left associativity): mypred_scope.
Fail Example ex4: (pred1 * 2) 2.
The command has indeed failed with message: The term "pred1" has type
"nat -> Prop" while it is expected to have type "Type".
(The symbols '-' and '*' may be a confusing choice for an add operation. But this lets us keep the example short and simple.)
Platform
Tested on Coq version: 8.15.2
+ and * are also overloaded as sum and product types in type_scope, which is automatically open on the right of :, taking precedence over the open mypred_scope. This is why the error messages say that a Type is expected. Hence on the right of : you have to reopen mypred_scope.
Delimit Scope mypred_scope with mypred.
Example ex2: (pred1 + 2)%mypred 2.
I was following (incomplete) examples in Coq 8.5p1 's reference manual in chapter 11 about the mathematical/declarative proof language. In the example below for iterated equalities (~= and =~), I got a warning Insufficient Justification for rewriting 4 into 2+2, and eventually got an error saying:
No more subgoals, but there are non-instantiated existential
variables:
?Goal : [x : R H : x = 2 _eq0 : 4 = x * x
|- 2 + 2 = 4]
You can use Grab Existential Variables.
Example:
Goal forall x, x = 2 -> x + x = x * x.
Proof.
proof. Show.
let x:R.
assume H: (x = 2). Show.
have ( 4 = 4). Show.
~= (2*2). Show.
~= (x*x) by H. Show.
=~ (2+2). Show. (*Problem Here: Insufficient Justification*)
=~ H':(x + x) by H.
thus thesis by H'.
end proof.
Fail Qed.
I'm not familiar with the mathematical proof language in Coq and couldn't understand why this happens. Can someone help explain how to fix the error?
--EDIT--
#Vinz
I had these random imports before the example:
Require Import Reals.
Require Import Fourier.
Your proof would work for nat or Z, but it fails in case of R.
From the Coq Reference Manual (v8.5):
The purpose of a declarative proof language is to take the opposite approach where intermediate states are always given by the user, but the transitions of the system are automated as much as possible.
It looks like the automation fails for 4 = 2 + 2. I don't know what kind of automation uses the declarative proof engine, but, for instance, the auto tactic is not able to prove almost all simple equalities, like this one:
Open Scope R_scope.
Goal 2 + 2 = 4. auto. Fail Qed.
And as #ejgallego points out we can prove 2 * 2 = 4 using auto only by chance:
Open Scope R_scope.
Goal 2 * 2 = 4. auto. Qed.
(* `reflexivity.` would do here *)
However, the field tactic works like a charm. So one approach would be to suggest the declarative proof engine using the field tactic:
Require Import Coq.Reals.Reals.
Open Scope R_scope.
Unset Printing Notations. (* to better understand what we prove *)
Goal forall x, x = 2 -> x + x = x * x.
Proof.
proof.
let x : R.
assume H: (x = 2).
have (4 = 4).
~= (x*x) by H.
=~ (2+2) using field. (* we're using the `field` tactic here *)
=~ H':(x + x) by H.
thus thesis by H'.
end proof.
Qed.
The problem here is that Coq's standard reals are defined in an axiomatic way.
Thus, + : R -> R -> R and *, etc... are abstract operations, and will never compute. What does this mean? It means that Coq doesn't have a rule on what to do with +, contrary for instance to the nat case, where Coq knows that:
0 + n ~> 0
S n + m ~> S (n + m)
Thus, the only way to manipulate + for the real numbers it to manually apply the corresponding axioms that characterize the operator, see:
https://coq.inria.fr/library/Coq.Reals.Rdefinitions.html
https://coq.inria.fr/library/Coq.Reals.Raxioms.html
This is what field, omega, etc... do. Even 0 + 1 = 1 is not probable by computation.
Anton's example 2 + 2 = 4 works by chance. Actually, Coq has to parse the numeral 4 to a suitable representation using the real axioms, and it turns out that 4 is parsed as Rmult (Rplus R1 R1) (Rplus R1 R1) (to be more efficient), which is the same than the left side of the previous equality.
I'm learning coq and I'm trying to make my own Point and Line data types. I'd like to make a function that returns the length of a line, but I can't seem to find the sqrt function that will return a calculation. I tried used Coq.Reals.R_sqrt, but apparently that's only used for abstract math, so it won't run the calculation.
So then I tried importing Coq.Numbers.Natural.Abstract.NSqrt and Coq.Numbers.NatInt.NZSqrt. but neither put sqrt function into the environment.
This is what I have so far...
Require Import Coq.QArith.QArith_base.
Require Import Coq.Numbers.NatInt.NZSqrt.
Require Import Coq.Numbers.Natural.Abstract.NSqrt.
Require Import Coq.ZArith.BinInt.
Inductive Point : Type :=
point : Q -> Q -> Point.
Inductive Line : Type :=
line : Point -> Point -> Line.
Definition line_fst (l:Line) :=
match l with
| line x y => x
end.
Definition line_snd (l:Line) :=
match l with
| line x y => y
end.
Definition point_fst (p:Point) :=
match p with
| point x y => x
end.
Definition point_snd (p:Point) :=
match p with
| point x y => y
end.
(* The reference sqrt was not found in the current environment. *)
Definition line_length (l:Line) :=
sqrt(
(minus (point_snd(line_fst l)) (point_fst(line_fst l)))^2
+
(minus (point_snd(line_snd l)) (point_fst(line_snd l)))^2
).
Example line_example : (
line_length (line (point 0 0) (point 0 2)) = 2
).
If you want your square root to compute, there are two things you can do.
Use the CoRN library. Then you will get real number functions that actually compute. However, those real numbers will just be functions that you can ask for approximations to a certain precision, so might not be what you are looking for. Also, I think CoRN is not terribly well maintained nowadays.
Use the natural number square root from the standard library that you already mentioned, and use that to calculate the square roots that you want to a certain precision yourself. This function you get by importingBinNat:
Coq < Require Import BinNat.
[Loading ML file z_syntax_plugin.cmxs ... done]
Coq < Eval compute in N.sqrt 1000.
= 31%N
: N
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.