mathcomp is consists of many 'parts'. Including:ˡ:
- mathcomp-algebra
- mathcomp-character
- mathcomp-field
- mathcomp-fingroup
- mathcomp-ssreflect
General
case eqn:H: to remember the relation even after a case split<name>.+1:Sfornat- ie,
n.+1just another notation for writingS n - This is probably because
1by itself could mean the1of a ring. - Eg:
Compute 3.+1. (* = 4 : nat *) .+2,.+3and.4also available.
- ie,
<name>.*2: double anat- Only
n.*2would work.n.*3is syntax error. - Eg:
Compute 3.*2. (* = 6%N : nat *) - Eg:
Compute 3.*3. (* Syntax Error: Lexer: Undefined token *)
- Only
<name>./2: halve anat(floor)<name>^3: exponentiation fornat- Looks like it's a ring operation for other types
<name>.1and<name>.2: first and second elements of the tuple namedname<n>.-tuple:- where
nis a number - Eg:
2.-tuple nat
- where
#|typ|: cardinality oftypeffun: finite function- ie, function whose domain is a finite type.
\sum_ (low <= i < high): Represents ∀i:ℕ, i ∈ [low, high), Σ i- ie, sum of all natural numbers from low and upto high.
%/: ??^+: ??%|: check if LHS divides RHSCompute 8 %| 16. (* true: bool *)
|:: ??:&:: ??:==:??^: exponentiation (fornat)- Eg:
Compute 3 ^ 4. (* = 81 : nat *)
- Eg:
n`!: factorial (ie, n!)[seq x <- lst | condition]: notation forfilter (fun x => condition) lst- Forget the
seqin the beginning and then it might look better.
- Forget the
[seq x' | x <- lst]: notation formap (fun x => x') lst=1(infix):eqfun(1-arg functional extensionality)=2(infix):eqrel(2-arg functional extensionality)=i(infix):eq_mem(extensional equality)=P(infix): reflection involvingboolNotation "x =P y" := (eqP : Bool.reflect (eq x y) (eq_op x y)) : eq_scope
Curly braces are used for types with parameters.
- Eg:
{set A}
- Eg:
elim/<ind_principle>:- where the
/<ind_principle>is optional. It can be given if an induction principle other than the default one is to be used.
- where the
finset
https://github.com/math-comp/math-comp/blob/master/mathcomp/ssreflect/finset.v
- Set membership indicated by a finite function (
ffun pred T) - Sets are defined only on finite types.
- Empty boolean set??:
[set: bool] - For set equality proofs, use
apply/setP - To change from
x \in s = falsetox \notin s, useapply/negbTE
Inductive set_type (T: finType): predArgType :=
| FinSet: {ffun pred T} -> set_type T.
Essentially just the characteristic function of the set.
mem A: the predicate corresponding toA(from finset.v)setX: Cartesian productcover: 'flatten' a set of sets
| Description | Mathcomp | Function |
|---|---|---|
| x ∈ A | x ∈ A | |
| ∅ | set0 | |
| A U B | A :│: B | setU |
| A ∩ B | A :&: B | setI |
| {X} U A | X │: A | |
| complement A | ~: A | setC |
| A \ B | A :\: B | setD |
| A \ {x} | A :\ x | |
| Powerset | powerset A | |
| Singleton {x} | set1 x | |
| Like a map fun | f @: A | imset |
| Like a map fun | f 2@: (A, B) | imset2 |
| f @-1: A | ||
| Cardinality | #│A│ | |
| A == B | A :==: B | (bool) |
| A = B | A :=: B | (Prop) |
| A != B | A :!=: B | (bool) |
| A ≠ B | A :<>: B | (Prop) |
| ?? | A :=P: B | ?? |
Example:
From mathcomp Require Import all_ssreflect.
Check [set true]: {set bool}.
Check [set true]: {set bool}.
(* [set true] : {set bool} : {set bool} *)
Check [set true; false]: {set bool}.
(* [set true; false] : {set bool} *)
Check [set true; false; false]: {set bool}.
(* [set true; false; false] : {set bool} : {set bool} *)
Compute [set true; false; false]: {set bool}.
(*
= [set x | (if
[set x0 | (if [set true] x0 then true else [set false] x0)]
x
then true
else [set false] x)]
: {set bool}
*)
More examples:
Example eg: {set bool*unit} := [set (true,tt); (false, tt)].
Check snd @: eg.
(* [set x.2 | x in eg] : {set Datatypes_unit__canonical__fintype_Finite} *)
Check snd @: eg : {set unit}.
(* [set x.2 | x in eg] : {set unit} : {set unit} *)
–
Not extraction friendly in terms of efficient computation.
finfun (ffun)
- 'functions with finite domain':
Inductive finfun_on (aT: finType) (rT: aT -> Type)
: seq aT -> Type :=
| finfun_nil: finfun_on (aT:=aT) rT [::]
| finfun_cons: forall (x : aT) (s : seq aT),
rT x ->
finfun_on (aT:=aT) rT s ->
finfun_on (aT:=aT) rT (x :: s).
injective f: f x = f y -> x = yf ^~ y\: essentially a means to flip the argument order of a 2-argument functionf ^~ y :fun x> f x y
pred
From eqtype.v:
pred1pred1 aisfun (a:A) (b:A): bool := eqb a bpred2,pred3,pred4also available
predC1 p: ¬ppredC1 aisfun (a:A) (b:A): bool := negb (eqb a b)
predU p q: p ∪ qpredD p q: p \ qpredIxpredI p1 p2 x:p1 x && p2 xpred A: Type of predicates onA- ie,
pred A : Type -> Type := A -> bool
- ie,
pred0b p: says that there is no elementxfor whichp xis true.
in is usually associated with iteration. \in indicates membership.
—
mem_pred: a variant type whose only constructor needs apred.
Variant mem_pred (T : Type) : Type :=
| Mem : pred T -> mem_pred T.
simpl_fun a b: a variant type whose only constructor needs a function of typea -> b.simpl_pred aissimpl_fun a bool
Variant simpl_fun (a b : Type) : Type :=
| SimplFun : (a -> b) -> simpl_fun a b.
disjoint
Definition says that the number of elements for which the characteristic functions of both A and B is true is zero.
Definition disjoint T (A B : mem_pred _) := @pred0b T (predI A B).
ssrbool
rel: Type of a kind of relationsrel: Type -> Type := T -> pred T
ssrfun
cancel f g: ∀x, g (f x) = x- f is applied first, then g is applied
TODO Phantom types
Mathcomp book: 6.10.1
Some notations
==>: boolean implication
Bool
&& |
andb |
││ |
orb |
== |
eqb |
pred
[pred x:T | condition]: unary boolean predicates- Accept a value of type
Tand give bool result of thecondition - Like
P: T -> bool
- Accept a value of type
N-ary notations
Arbitrary arity:
| [:: 1, 2, 3] | [1,2,3] |
| [:: 1, 2 & l] | 1 :: 2 :: l] |
| [==> b1, b2 => b3] | b1 ==> b2 ==> b3 |
| [&& true, false & true] | true && false && true |
| [││ true, false │ true] | true ││ false ││ true |
Non-arbitrary arity:
| [/\ p1, p2 & p3 ] | p1 /\ p2 /\ p3 | only upto 5 terms |
| [\/ p1, p2 │ p3 ] | p1 \/ p2 \/ p3 | only upto 4 terms |
Bracket notations
[seq .. | .. ]
Page 39 mathcomp book
seq (lists)
| mathcomp | stdlib |
|---|---|
[::] |
[] |
[:: a] |
[a] |
[:: 1, 2, 3] |
[1,2,3] |
[:: 1, 2 & l] |
1 :: 2 :: l |
last: Get last element ofx::lwithlast x l- last: A -> seq A -> A
- Clever way to ensure the list is non-empty..
flatten: 'flatten' a list of lists to a simple list
finType
enum: likeforall A:finType, list A
eqType
Types with decidable equality.
Subtypes:
subType P: likex: T | P xinsub x: T -> option S- Value corresponding to
x:Tin another typeSwhich is a subtype ofT, if it exists.
- Value corresponding to
insubd x: T -> S- Similar to
insubexcept that a default value is given if there's no possible projection in the subtype.
- Similar to
Sub x Px: Generic constructor for a subtype\val: Generic injection from a subtype to the supertype
Same as in standard coq but 'renamed'
| mathcomp | stdlib | Reason |
|---|---|---|
seq |
list |
seq used to be different earlier |
erefl |
Logic.eq_refl |
MC's eq_refl is something else |
Syntax
'let-in' construct (:=)
Can be used to have a name for an expression used multiple times.
An example from mathcomp book:
Lemma edivnP m d (ed := edivn m d):
((d>0) ==> (ed.2<md)) && (m == ed.1*d + ed.2).
where ed is defined and then used multiple times.
let:
- Seems like a concise
match. - Useful for types with only one constructor.
Example:
From mathcomp Require Import all_ssreflect all_algebra.
Inductive point: Type :=
| Point (x y z: nat).
Definition getX (p: point): nat :=
let: Point x _ _ := p in x.
Compute getX (Point 1 2 3).
(* = 1 : nat *)
Some types
bigop
Definition and notations
A special form of
foldr.The name is 'big op' because it's used to represent operations commonly denoted using upper case Greek letters. Like Σ, Π, etc.
Takes following arguments:
r: seq Ia range op: R -> R -> Ran operation idx: Ra neutral element F: I -> Rgeneral term (transforms I to R) P : pred Ifiltering predicate The actual operation is done like:
foldr (λi acc => if P i then op (F i) acc else acc) idx rSteps:
- Take elements of
rthat satisfyP - Use
Fto convert these elements to typeR - Use
opto combine with accumulator value to get new accumulator.
Notations:
\big[op / idx]_ (i <- r │ P) Fbigop {R I: Type} (idx: R) (op: R->R->R)(r: seq I) (P: pred I) (F: I->R): R\sum_ (i <- r │ P) F\big[+%N / 0%N]_ (i <- r │ P%B) F%NI: ℕ R: ℕ P: ℕ -> 𝔹 F: ℕ -> ℕ With upper and lower bounds:
\big[op / idx]_ ( low <= i < high │ P) Fbigop idx op (index_iota low high) P F\sum_ (low <= i < high │ P) F\big[+%N / 0%N]_ (low <= i < high │ P%B) F%Ni <-r | Pmeans 'fromr, take elements that satisfyP.—
\sum_is defined in terms of\big[ _ / _], which in turn is defined usingbigop.https://github.com/math-comp/math-comp/blob/mathcomp-2.0.0/mathcomp/ssreflect/bigop.v#L629
https://github.com/math-comp/math-comp/blob/mathcomp-2.0.0/mathcomp/ssreflect/bigop.v#L662
\big [ op / idx ]_ ( i <- r | P ) Fis(bigop idx r (fun i => BigBody i op P%B F))\sum_ ( i <- r | P ) Fis(\big[+%N/0%N]_(i <- r | P%B) F%N)
As for
Bigbody, it's apparently just a wrapper. From mathcomp source:The bigbody wrapper is a workaround for a quirk of the Coq pretty-printer, which would fail to redisplay the notation when the <generalterm> or <condition> do not depend on the bound index. The
BigBodyconstructor packages both in in a term in which i occurs; it also depends on the iterated <op>, as this can give more information on the expected type of the <generalterm>, thus allowing for the insertion of coercions.The general form for iterated operators is ʳ:
<bigop>_<range> <general_term>—
- Take elements of
iotaand similarFunction that generates all the nat numbers within a range.
iota start countExample:
Compute iota 2 5. (* = [:: 2%N; 3%N; 4%N; 5%N; 6%N] : seq nat *)—
index_iota:Similar to
iota, except that instead of number of elements, upper limit (exclusive) is taken as argument.Compute index_iota 2 8. (* = [:: 2; 3; 4; 5; 6; 7] : seq nat *) Compute index_iota 2 5. (* = [:: 2; 3; 4] : seq nat *)Lemmas
big_ord_recr: recursion (right)- decompose to last element and remaining
big_ord_recl: recursion (left)- decompose to first element and remaining
big_mkcond: move filterP'into the generic term'big_cat: bigop involving concatenation of two sequencesbig_ord0: base case
ordinal
'I_n:natnumbers less thann. Notation forordinal n.ord_enum: nat -> seq: enumerate all elements of type'I_nlift: 'I_n -> 'I_n.-1 -> 'I_nunlift: 'I_n -> 'I_n -> option 'I_n.-1lshift: 'I_m -> 'I_(m+n): Shift to left, making space in rightrshift: 'I_n -> 'I_(m+n): Shift to right, making space in left
tuple
n.-tuple is essentially a seq with a proof that its length is less than n.
n.-tupleis notation fortuple_of n[tuple]: empty tuple[tuple x1; x2; ... ; xn]: a value of typen.-tupletval: getseqcomponent ofn.-tuple
matrix
fun_of_matrix: get function that makes the matrix'M[R]_ (rows, cols): type ofrows x colsmatrix with elements of typeR.'M[R]_ n: type of square matrix of sizenwith elements of typeR.\matrix_ (i, j) E: make amatrixvalue from a function.Eis like a function that takes row and column indices and returns cell values.
\matrix_ (i < m, j < n) E: similar to\matrix_ (i, j)but with additional constraints.- Eg:
Definition diagonal := \matrix_ (i < 3, j < 3) if i==j then 1 else 0.
- Eg:
\tr m: find trace (ie, sum of main diagonal) of a square matrixm.M^Tortrmx M: transpose of a matrixMaddmx: matrix addition*m: matrix multiplication (infix operator)a%:M: scalar matrix witha-s on main diagonal.- ie,
1%:Mwould be identity matrix.
- ie,
M ^formap_mx: map operationconst_mx: constant matrix
'M_(2,3): 2x3 matrix of unknown type'M[int]_(2,3): 2x3 matrix ofinttype'M_n: type of square matrix of size n (element type implicit)'M[bool]_3: bool square matrix of size 3
'rV_2: row vector of size 2 (element type implicit)'cV_2: column vector of size 2 (element type implicit)
Submatrices:
row i M: Get ith rowcol j M: Get jth columnrow' i M: Get M with ith row removedcol' j M: Get M with jth column removed
Block matrix building:
row_mx Ml Mr: stack Ml and Mr horizontallycol_mx Mu Md: stack Mu and Md verticallyblock_mx Mul Mur Mdl Mdr: make a matrix with 4 other matrices
Check matrix bool 3 4.
(* 'M_(3, 4) : predArgType *)
Check 'M_(3, 4).
(*
'M_(3, 4)
: predArgType
where
?R : [ |- Type]
*)
Check 'M[bool]_(3, 4).
(* 'M_(3, 4) : predArgType *)
(* A square matrix *)
Definition M2 : 'M[int]_(2,2) := \matrix_(i,j < 2) 3%:Z.
(* A non-square matrix *)
Example eg1: 'M[int]_ (3, 7) := \matrix_(i<3, j<7) 8%:Z.
(* A row matrix *)
Example eg7: 'rV_2 :=
\row_(i<2) (if i==0 then true else false).
Lemmas
ffunE
seq
seq seems to be simply notation for list.
Print seq.
(* Notation seq := list *)
Check [:: 1; 2; 3].
(* [:: 1; 2; 3] : seq nat *)
—
Infinite sequences are also possible:
(* Finite sequence *)
Check 1 :: 2 :: 3 :: nil.
(* [:: 1; 2; 3] : seq nat *)
(* Prepending to a list 'l' *)
Check fun l => 1 :: 2 :: 3 :: l.
(*
fun l : seq nat => [:: 1, 2, 3 & l]
: seq nat -> seq nat
*)
Infinite sequence has an & at its end and its elements are separated by a , instead of ;.
—
algebra (ssralg)
https://math-comp.github.io/htmldoc/mathcomp.algebra.ssralg.html
comSemiRingType: Commutative semiring- Only in mathcomp2
nmodType: Structure for additive Abelian monoidzmodType: Structure for additive Abelian groups (ie,nmodTypewith additive inverses)
finType
ord0: smallest element of a 'In.+1ord_max: largest element of a 'In.+1lift: lift a 'In to 'In.+1 (ie, make the type 'wider' by one)unlift: 'In to 'In.-1 if possible (ie, make the type 'narrower by one)
Locking and unlocking
https://coq.inria.fr/refman/proof-engine/ssreflect-proof-language.html#locking-unlocking
Controls unfolding during a simpl in proofs. To prevent large terms showing all at once.
- Unfold locked term:
rewrite unlock
lock: forall [A : Type] (x : A), x = locked x
unlock: forall [T : Type] [x : T] (C : unlockable x), unlocked C = x
composable_lock: unit
locked: forall [A : Type], A -> A
unlocked: forall [T : Type] [v : T], unlockable v -> T
unlockable: forall [T : Type], T -> Type
Unlockable: forall [T : Type] [v unlocked : T], unlocked = v -> unlockable v
locked_with: unit -> forall T : Type, T -> T
locked_with_unlockable: forall [T : Type], unit -> forall x : T, unlockable x
unlock_with:
forall [T : Type] (k : unit) (x : T),
unlocked (locked_with_unlockable k x) = x
Proof mode
/<lemma-name>: simplify with<lemma-name>and then use.//: simplify beforehand- Equivalent to
try done.
- Equivalent to
/=: invokes thesimpltactic ʳ//=://followed by/=- Equivalent to
simpl; try done.
- Equivalent to
=>: revert a hypothesis from stack:: move an assumption to stack (discharge)have: likeassert. Start a new sub-proof.- Useful for forward reasoning.
move: move assumption to and from stackrewrite -<lemma-name>: rewrite from right to left (the minus changes the direction)rewrite !<lemma-name>: rewrite all occurrences (without the!, only 1st occurrence is rewritten)- Can rewrite with multiple theorems at once.
move=> ->.is same asmove=> H; rewrite H.{-2}ncapture all occurrences ofnexcept the second- Example:
rewrite {3}/foo.(rewrite only 3th instance offoo)
- Example:
rewrite
Perhaps most useful part of ssreflect usage.
rewrite /<definition>is same asunfold <definition>rewrite -/<definition>is same asfold <definition>
Tactics and tacticals
haveunlockmovedo: for iterationdo 1? <tactic>: at most oncedo 2! <tactic>: exactly twicedo ! <tactic>: as many times as possible, but at least once
unlock lemma
A lemma that can be used to unlock definitions?
Check unlock.
(*
unlock : forall (T : Type) (x : T) (C : unlockable x),
unlocked C = x
*)
unlockable v == interface for sealed constant definitions of v.
Naming conventions
Made uniformly in mathcomp. Makes it way easier to remember: https://github.com/math-comp/math-comp/blob/mathcomp-2.0.0/CONTRIBUTING.md#naming-conventions-for-lemmas-non-exhaustive
- reflection view lemmas end with a 'P'.
- Example:
eqnP
- Example:
ubnlemmas: stands for 'upper bound'
—
- C: Commutativity
- A: Associativity
- K: cancellation
- As in cancel the effect of a definition.
—
Functions available:
commutativeassociativetransitiveantisymmetricreflexiveantireflexive
ssreflect
Some tutorials:
- https://jfr.unibo.it/article/download/1979/1358/4452
- https://inria.hal.science/inria-00407778/document
Inductive reflect (P: Prop): bool -> Type :=
| Reflect_true : P -> reflect P true
| Reflect_false : ~P -> reflect P false.
reflect type usage is like
reflect (equality-in-Prop) (equality-in-bool)
by []is equivalent todonetactic.
Given a value of reflect P b, these are useful to 'project' components:
- elimT: .. reflect P b -> b -> P
- introT: .. reflect P b -> P -> b
- elimF: .. reflect P b -> ~b -> ~P
- introF: .. reflect P b -> ~P -> ~b
mathcomp2
Uses Hierarchy builder (HB).
From HB Require Import structures.
Links:
- Uses HB and mathcomp2 now: https://github.com/math-comp/dioid/blob/master/complete_dioid.v
Hierarchy builder (HB)
References:
- https://perso.crans.org/cohen/JFLA23/hb.pdf (slides from 2023)
- https://inria.hal.science/hal-02478907v6/document (paper)
Primitives in HB
https://perso.crans.org/cohen/JFLA23/hb.pdf
HB.mixinHB.factoryHB.builders: like constructor for a factory??HB.structureHB.instance
HB.about
From mathcomp Require Import ssralg.
HB.about comSemiRingType.
(*
HB: comSemiRingType is a structure (from "./algebra/ssralg.v", line 2502)
HB: comSemiRingType characterizing operations and axioms are:
- mulrC
HB: GRing.ComSemiRing is a factory for the following mixins:
- GRing.isNmodule
- hasChoice
- hasDecEq
- GRing.Nmodule_isSemiRing
- GRing.SemiRing_hasCommutativeMul (* new, not from inheritance *)
HB: GRing.ComSemiRing inherits from:
- eqtype.Equality
- choice.Choice
- GRing.Nmodule
- GRing.SemiRing
HB: GRing.ComSemiRing is inherited by:
- GRing.ComRing
- GRing.ComAlgebra
- GRing.ComUnitRing
- GRing.ComUnitAlgebra
- GRing.IntegralDomain
- GRing.Field
- GRing.DecidableField
- GRing.ClosedField
- GRing.SubComSemiRing
- GRing.SubComRing
- GRing.SubComUnitRing
- GRing.SubIntegralDomain
- GRing.SubField
- Num.NumDomain
- Num.ArchiNumDomain
- Num.NumField
- Num.ClosedField
- Num.RealDomain
- Num.RealField
- Num.RealClosedField
- Num.ArchiNumField
- Num.ArchiClosedField
- Num.ArchiDomain
- Num.ArchiField
- Num.ArchiRealClosedField
- FinRing.ComSemiRing
- FinRing.ComRing
- FinRing.ComUnitRing
- FinRing.IntegralDomain
- FinRing.Field
- CountRing.ComSemiRing
- CountRing.ComRing
- CountRing.ComUnitRing
- CountRing.IntegralDomain
- CountRing.Field
- CountRing.DecidableField
- CountRing.ClosedField
*)
HB.howto
Shows possible ways in which a structure can be attained for a type.
(* Show how to make [option] type a commutative semiring *)
HB.howto option comSemiRingType.
(*
HB: solutions (use 'HB.about F.Build' to see the arguments of each factory F):
- GRing.isNmodule; GRing.Nmodule_isComSemiRing
- GRing.isSemiRing; GRing.SemiRing_hasCommutativeMul
- GRing.isNmodule; GRing.Nmodule_isSemiRing;
GRing.SemiRing_hasCommutativeMul
*)
Here, 3 possible routes are shown.
Terms
- Telescope
- Phantom parameters
- Packed class
:> symbol
Coq syntax.
https://stackoverflow.com/questions/51404367/the-coq-symbol
Focusing on subgoals
Unlike usual coq, by default, mathcomp makes doesn't focus on subgoal when we use bullets.
We can use focus brackets (ie, a { , } pair). A { focuses on first sub-goal.
Could also focus on n-th subgoal with n-{ <tactics> }.
Another way is to change the setting with
Set Bullet Behavior "Strict Subproofs".
Don't use Focus. It's deprecated.
–
Info thanks to this discussion.
Info
fold/unfoldis usually not needed with ssreflect becauserewritehandles that as well (among many other things with its numerous flags).- Usage with nix: https://github.com/math-comp/math-comp/wiki/Using-nix/
eqnis same asNat.eqb
Doubts
- [ ] program obligation not applicable to mathcomp?
- [X]
refinenot applicable to mathcomp? It is - [ ]
undertactic - [ ]
[]inrewrite. To override default inferred args?
Resources
- mathcomp book
- ssreflect manual