What do the consecutive in's in Coq do and eval & red & Idtac do? - coq

I know in OCaml the syntax
let x = val in exp
means x has the value v when in expression exp.
But what does something like
let add_left_red := eval red in add_left in (* reduce add_left, but leave goal alone *)
idtac add_left_red.
I assume it does this:
gives the identifier add_left_red the output of eval red
then that add_left_red is that value in add_left
AND in idtac add_left_red
Is that what it does?
Fyi I also have no idea what that line does. Especially cuz googling eval and red gave nothing useful.
Idtac did see:
Tacticidtac ident ​ string ​ natural *
Leaves the proof unchanged and prints the given tokens. Strings and naturals are printed literally. If ident is an Ltac variable, its contents are printed; if not, it is an error.
What do those composoble blocks do?
Context whole script
Fixpoint add_left (n m : nat) : nat :=
match n with
| O => m
| S p => S (add_left p m)
end.
Lemma demo_1 :
forall (n : nat),
add_left n O = n.
Proof.
intros. (* goal : add_left n O = n *)
let add_left_red := eval red in add_left in (* reduce add_left, but leave goal alone *)
idtac add_left_red. (* print the result *)
(* Print eval. gives error *)
Print red.
Print add_left_red.
admit.
Abort.

In OCaml, there is only one notion of computation, but in Coq, we may want to play with several such notions, because we sometimes want to compute or simplify only progressively the expressions we are looking at.
So there is a command, akin to Compute which makes it possible to take a term, and compute it only partially. This command as an in keyword in the middle.
Here is an example:
Require Import Arith.
Eval cbn[fact] in fact 10.
Here the result shows the computation of fact 10, but only insofar that the multiplications it performs are exposed, but not computed themselves.
Sometimes, in a tactic you want to do just this computation, so will need to use a variant of this eval ... in ... construct (this time with a lower case initial), which is designed for use in tactics.
let x := eval cbn[fact] in (fact 10) in change (fact 10) with x.
So in your goal, fact 10 is replaced by (10 * 9 ...)
if it were in OCaml, you would not bother explaining that you want a partial computation so you would write only let x = fact 10 in ... .
So this is the reason why the keyword appears twice. The first time to separate the computation mechanism you want to apply to the expression, and the second time to separate the expression that is evaluated from the expression where the variable will be used.
Here is an example where the tactic is being used:
Require Import Arith.
Lemma toto : fact 7 = 5040.
let x := eval cbn[fact] in (fact 7) in change (fact 7) with x.
(tested with coq-8.14)

Understanding the realted Eval RED in Term is key. Do that first.
eval: ref: What do the consecutive in's in Coq do and eval & red & Idtac do?
I think its
eval RED in TERM
Example:
Require Import Arith.
Lemma toto : fact 3 = 6.
let x := (*set the output of eval RED in TERM to id/var x*)
(eval cbn[fact] in (fact 3)) (* partially reduce fact 3 *)
in (* output of "let x := (eval RED in TERM)" goes here *)
idtac x. (* final expression to evaluate with x *)
(3 * (2 * (1 * 1)))

Related

Cardinality of finFieldType / Euler's criterion

I am trying to prove a very limited form of Euler's criterion:
Variable F : finFieldType.
Hypothesis HF : (1 != -1 :> F).
Lemma euler (a : F) : a^+(#|F|.-1./2) = -1 -> forall x, x^+2 != a.
I have the bulk of the proof done already, but I am left with odd (#|F|.-1) = 0, that is, #|F|.-1 is even. (I'm not interested in characteristic 2). I can't seem to find useful facts in the math comp library about the cardinality of finFieldTypes. For example, I would expect a lemma saying there exists a p such that prime p and #|F| = p. Am I missing something here?
By the way, I could also have totally missed an already existing proof of Euler's criterion in the math comp library itself.
I am not aware of a proof of Euler's criterion, but I found two lemmas, in finfield, that give you the two results that you expected in order to finish your proof (the second one may not be presented as you expected):
First, you have the following lemma which gives you the prime p corresponding to the characteristic of your field F (as long as it is a finFieldType):
Lemma finCharP : {p | prime p & p \in [char F]}.
Then, another lemma gives you the cardinality argument :
Let n := logn p #|R|.
Lemma card_primeChar : #|R| = (p ^ n)%N.
The problem with the second lemma is that your field should be recognized as a PrimeCharType, which roughly corresponds to a ringType with an explicit characteristic. But given the first lemma, you are able to give such a structure to your field (which canonically has a ringType), on the fly. A possible proof could be the following
Lemma odd_card : ~~ odd (#|F|.-1).
Proof.
suff : odd (#|F|) by have /ltnW/prednK {1}<- /= := finRing_gt1 F.
have [p prime_p char_F] := (finCharP F); set F_pC := PrimeCharType p_char.
have H : #|F| = #|F_primeChar| by []; rewrite H card_primeChar -H odd_exp => {H F_pC}.
apply/orP; right; have := HF; apply: contraR=> /(prime_oddPn prime_p) p_eq2.
by move: char_F; rewrite p_eq2=> /oppr_char2 ->.
Qed.

'else' in definitions - Coq

First of all I'm new to proof theory and coq, so I'd appreciate answers to be easy to understand.
I'm trying to build up definitions to eventually define prime numbers; I'm currently trying to define divisibility, and in my definition I've written the true cases.
Every nat is divisible with 1.
Every nat is divisible with itself.
And my inductive case (applyable when '(i > j)' ):
Every nat 'i' is divisible by 'j' if '(i - j)' is divisible by 'j'.
Now in some of my subsequent lemmas I need that everything not fulfilling this is false.
How would I go about encoding this in my definition?
I'm thinking something alike, when none of the above is applicable --> false.
- In a sense an else statement for definitions.
In constructive logic, which Coq is built upon, a proposition is only considered "true" when we have direct evidence, i.e. proof. So, one doesn't need such "else" part, because anything that cannot be constructed is in a sense false. If none of the cases for your "is divisible by" relation are applicable, you'll be able to prove your statement by contradiction, i.e. derive False.
For example, if we have this definition of divisibility:
(* we assume 0 divides 0 *)
Inductive divides (m : nat) : nat -> Prop :=
| div_zero: divides m 0
| div_add: forall n, divides m n -> divides m (m + n).
Notation "( x | y )" := (divides x y) (at level 0).
Then we can prove the fact that 3 does not divide 5, using inversion, which handles the impossible cases:
Fact three_does_not_divide_five:
~(3 | 5).
Proof.
intro H. inversion H. inversion H2.
Qed.
Note: we can check that our divides relation captures the notion of divisibility by introducing an alternative ("obvious") definition:
Definition divides' x y := exists z, y = z*x.
Notation "( x |' y )" := (divides' x y) (at level 0).
and proving their equivalence:
Theorem divides_iff_divides' (m n : nat) :
(m | n) <-> (m |' n).
Admitted. (* it's not hard *)
A different approach is to define divisibility from with division and remainder:
Define a divn : nat -> nat -> nat * nat operation that divides two numbers and returns the remainder.
Then, divisibility is expressed as "remainder is equal to 0". You'll need to work out some details, such as what happens with 0.
Then, a falsified divisibility hypothesis amounts to a false equality which can be usually solved by congruence. You can manipulate the equality with the standard theory for the remainder.
This is the approach used in the math-comp library, see http://math-comp.github.io/math-comp/htmldoc/mathcomp.ssreflect.div.html

`No more subgoals, but there are non-instantiated existential variables` in Coq proof language?

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.

Counting number of different elements in a list in Coq

I'm trying to write a function that takes a list of natural numbers and returns as output the amount of different elements in it. For example, if I have the list [1,2,2,4,1], my function DifElem should output "3". I've tried many things, the closest I've gotten is this:
Fixpoint DifElem (l : list nat) : nat :=
match l with
| [] => 0
| m::tm =>
let n := listWidth tm in
if (~ In m tm) then S n else n
end.
My logic is this: if m is not in the tail of the list then add one to the counter. If it is, do not add to the counter, so I'll only be counting once: when it's the last time it appears. I get the error:
Error: The term "~ In m tm" has type "Prop"
which is not a (co-)inductive type.
In is part of Coq's list standard library Coq.Lists.List. It is defined there as:
Fixpoint In (a:A) (l:list A) : Prop :=
match l with
| [] => False
| b :: m => b = a \/ In a m
end.
I think I don't understand well enough how to use If then statements in definitions, Coq's documentation was not helpful enough.
I also tried this definition with nodup from the same library:
Definition Width (A : list nat ) := length (nodup ( A ) ).
In this case what I get as error is:
The term "A" has type "list nat" while it is expected to have
type "forall x y : ?A0, {x = y} + {x <> y}".
And I'm quiet confused as to what's going on here. I'd appreciate your help to solve this issue.
You seem to be confusing propositions (Prop) and booleans (bool). I'll try to explain in simple terms: a proposition is something you prove (according to Martin-Lof's interpretation it is a set of proofs), and a boolean is a datatype which can hold only 2 values (true / false). Booleans can be useful in computations, when there are only two possible outcomes and no addition information is not needed. You can find more on this topic in this answer by #Ptival or a thorough section on this in the Software Foundations book by B.C. Pierce et al. (see Propositions and Booleans section).
Actually, nodup is the way to go here, but Coq wants you to provide a way of deciding on equality of the elements of the input list. If you take a look at the definition of nodup:
Hypothesis decA: forall x y : A, {x = y} + {x <> y}.
Fixpoint nodup (l : list A) : list A :=
match l with
| [] => []
| x::xs => if in_dec decA x xs then nodup xs else x::(nodup xs)
end.
you'll notice a hypothesis decA, which becomes an additional argument to the nodup function, so you need to pass eq_nat_dec (decidable equality fot nats), for example, like this: nodup eq_nat_dec l.
So, here is a possible solution:
Require Import Coq.Arith.Arith.
Require Import Coq.Lists.List.
Import ListNotations.
Definition count_uniques (l : list nat) : nat :=
length (nodup eq_nat_dec l).
Eval compute in count_uniques [1; 2; 2; 4; 1].
(* = 3 : nat *)
Note: The nodup function works since Coq v8.5.
In addition to Anton's solution using the standard library I'd like to remark that mathcomp provides specially good support for this use case along with a quite complete theory on count and uniq. Your function becomes:
From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq.
Definition count_uniques (T : eqType) (s : seq T) := size (undup s).
In fact, I think the count_uniques name is redundant, I'd prefer to directly use size (undup s) where needed.
Using sets:
Require Import MSets.
Require List. Import ListNotations.
Module NatSet := Make Nat_as_OT.
Definition no_dup l := List.fold_left (fun s x => NatSet.add x s) l NatSet.empty.
Definition count_uniques l := NatSet.cardinal (no_dup l).
Eval compute in count_uniques [1; 2; 2; 4; 1].

Eval compute is incomplete when own decidability is used in Coq

The Eval compute command does not always evaluate to a simple expression.
Consider the code:
Require Import Coq.Lists.List.
Require Import Coq.Arith.Peano_dec.
Import ListNotations.
Inductive I : Set := a : nat -> I | b : nat -> nat -> I.
Lemma I_eq_dec : forall x y : I, {x = y}+{x <> y}.
Proof.
repeat decide equality.
Qed.
And, if I execute the following command:
Eval compute in (if (In_dec eq_nat_dec 10 [3;4;5]) then 1 else 2).
Coq tells me that the result is 2. However, when I execute the following expression:
Eval compute in (if (In_dec I_eq_dec (a 2) [(a 1);(a 2)]) then 1 else 2).
I get a long expression where the In-predicate seems to be unfolded, but no result is given.
What do I have to change to obtain the answer 1 in the last Eval compute line ?
In Coq there are two terminator commands for proof scripts: Qed and Defined. The difference between them is that the former creates opaque terms, which cannot be unfolded, even by Eval compute. The latter creates transparent terms, which can then be unfolded as usual. Thus, you just have to put Defined in the place of Qed.:
Require Import Coq.Lists.List.
Require Import Coq.Arith.Peano_dec.
Import ListNotations.
Inductive I : Set := a : nat -> I | b : nat -> nat -> I.
Lemma I_eq_dec : forall x y : I, {x = y}+{x <> y}.
Proof.
repeat decide equality.
Defined.
Eval compute in (if (In_dec I_eq_dec (a 2) [(a 1);(a 2)]) then 1 else 2).
I personally find the sumbool type {A} + {B} not very nice for expressing decidable propositions, precisely because proofs and computation are too tangled together; in particular, proofs affect how terms reduce. I find it better to follow the Ssreflect style, separate proofs and computation and relate them via a special predicate:
Inductive reflect (P : Prop) : bool -> Set :=
| ReflectT of P : reflect P true
| ReflectF of ~ P : reflect P false.
this gives a convenient way for saying that a boolean computation returns true iff some property is true. Ssreflect provides support for conveniently switching between the computational boolean view and the logical view.
If you want to evaluate your proofs, you need to make them transparent. You do that by finishing them with the Defined command. The Qed command makes them opaque, meaning it discards their computational content.