mathcomp is consists of many 'parts'. Including:ˡ:
case eqn:H
: to remember the relation even after a case split
<name>.+1
: S
for nat
n.+1
just another notation for writing S n
1
by itself could mean the 1
of a ring.Compute 3.+1. (* = 4 : nat *)
.+2
, .+3
and .4
also available.<name>.*2
: double a nat
n.*2
would work. n.*3
is syntax error.Compute 3.*2. (* = 6%N : nat *)
Compute 3.*3. (* Syntax Error: Lexer: Undefined token *)
<name>./2
: halve a nat
(floor)
<name>^3
: exponentiation for nat
<name>.1
and <name>.2
: first and second elements of the tuple named name
<n>.-tuple
:
n
is a number2.-tuple nat
#|typ|
: cardinality of type
ffun
: finite function
\sum_ (low <= i < high)
: Represents ∀i:ℕ, i ∈ [low, high), Σ i
%/
: ??
^+
: ??
%|
: check if LHS divides RHS
Compute 8 %| 16. (* true: bool *)
|:
: ??
:&:
: ??
:==:
??
^
: exponentiation (for nat
)
Compute 3 ^ 4. (* = 81 : nat *)
n`!
: factorial (ie, n!)
[seq x <- lst | condition]
: notation for filter (fun x => condition) lst
seq
in the beginning and then it might look better.[seq x' | x <- lst]
: notation for map (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 involving bool
Notation "x =P y" := (eqP : Bool.reflect (eq x y) (eq_op x y)) : eq_scope
Curly braces are used for types with parameters.
{set A}
elim/<ind_principle>:
/<ind_principle>
is optional. It can be given if an induction principle other than the default one is to be used.https://github.com/math-comp/math-comp/blob/master/mathcomp/ssreflect/finset.v
ffun pred T
)[set: bool]
apply/setP
x \in s = false
to x \notin s
, use apply/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 to A
(from finset.v)setX
: Cartesian productcover
: 'flatten' a set of setsDescription | 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.
ffun
)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 function
f ^~ y :
fun x > f x y
From eqtype.v:
pred1
pred1 a
is fun (a:A) (b:A): bool := eqb a b
pred2
, pred3
, pred4
also availablepredC1 p
: ¬p
predC1 a
is fun (a:A) (b:A): bool := negb (eqb a b)
predU p q
: p ∪ qpredD p q
: p \ qin
is usually associated with iteration. \in
indicates membership.
rel
: Type of a kind of relations
rel: Type -> Type := T -> pred T
cancel f g
: ∀x, g (f x) = x
Mathcomp book: 6.10.1
==>
: boolean implication&& |
andb |
││ |
orb |
== |
eqb |
[pred x:T | condition]
: unary boolean predicates
T
and give bool result of the condition
P: T -> bool
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 |
[seq .. | .. ]
Page 39 mathcomp book
mathcomp | stdlib |
---|---|
[::] |
[] |
[:: a] |
[a] |
[:: 1, 2, 3] |
[1,2,3] |
[:: 1, 2 & l] |
1 :: 2 :: l |
last
: Get last element of x::l
with last x l
flatten
: 'flatten' a list of lists to a simple listenum
: like forall A:finType, list A
Types with decidable equality.
Subtypes:
subType P
: like x: T | P x
insub x: T -> option S
x:T
in another type S
which is a subtype of T
, if it exists.insubd x: T -> S
insub
except that a default value is given if there's no possible projection in the subtype.Sub x Px
: Generic constructor for a subtype\val
: Generic injection from a subtype to the supertypemathcomp | stdlib | Reason |
---|---|---|
seq |
list |
seq used to be different earlier |
erefl |
Logic.eq_refl |
MC's eq_refl is something else |
:=
)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:
match
.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 *)
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 I |
a range |
op: R -> R -> R |
an operation |
idx: R |
a neutral element |
F: I -> R |
general term (transforms I to R) |
P : pred I |
filtering predicate |
The actual operation is done like:
foldr (λi acc => if P i then op (F i) acc
else acc) idx r
Steps:
r
that satisfy P
F
to convert these elements to type R
op
to combine with accumulator value to get new accumulator.Notations:
\big[op / idx]_ (i <- r │ P) F |
bigop {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%N |
I: ℕ |
R: ℕ | ||
P: ℕ -> 𝔹 | ||
F: ℕ -> ℕ |
With upper and lower bounds:
\big[op / idx]_ ( low <= i < high │ P) F |
bigop idx op (index_iota low high) P F |
|
---|---|---|
\sum_ (low <= i < high │ P) F |
\big[+%N / 0%N]_ (low <= i < high │ P%B) F%N |
i <-r | P
means 'from r
, take elements that satisfy P
.
—
\sum_
is defined in terms of \big[ _ / _]
, which in turn is defined using bigop
.
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 ) F
is (bigop idx r (fun i => BigBody i op P%B F))
\sum_ ( i <- r | P ) F
is (\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
BigBody
constructor 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>
—
iota
and similar
Function that generates all the nat numbers within a range.
iota start count
Example:
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)
big_ord_recl
: recursion (left)
big_mkcond
: move filter P
'into the generic term'big_cat
: bigop involving concatenation of two sequencesbig_ord0
: base caseordinal
'I_n
: nat
numbers less than n
. Notation for ordinal n
.
ord_enum: nat -> seq
: enumerate all elements of type 'I_n
lift: 'I_n -> 'I_n.-1 -> 'I_n
unlift: 'I_n -> 'I_n -> option 'I_n.-1
lshift: 'I_m -> 'I_(m+n)
: Shift to left, making space in right
rshift: 'I_n -> 'I_(m+n)
: Shift to right, making space in left
n.-tuple
is essentially a seq
with a proof that its length is less than n
.
n.-tuple
is notation for tuple_of n
[tuple]
: empty tuple[tuple x1; x2; ... ; xn]
: a value of type n.-tuple
tval
: get seq
component of n.-tuple
matrix
fun_of_matrix
: get function that makes the matrix
'M[R]_ (rows, cols)
: type of rows x cols
matrix with elements of type R
.
'M[R]_ n
: type of square matrix of size n
with elements of type R
.
\matrix_ (i, j) E
: make a matrix
value from a function.
E
is 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.
Definition diagonal := \matrix_ (i < 3, j < 3) if i==j then 1 else 0.
\tr m
: find trace (ie, sum of main diagonal) of a square matrix m
.
M^T
or trmx M
: transpose of a matrix M
addmx
: matrix addition
*m
: matrix multiplication (infix operator)
a%:M
: scalar matrix with a
-s on main diagonal.
1%:M
would be identity matrix.M ^f
or map_mx
: map operation
const_mx
: constant matrix
'M_(2,3)
: 2x3 matrix of unknown type'M[int]_(2,3)
: 2x3 matrix of int
type'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 removedBlock 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 matricesCheck 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 ;
.
—
ssralg
)https://math-comp.github.io/htmldoc/mathcomp.algebra.ssralg.html
comSemiRingType
: Commutative semiring
nmodType
: Structure for additive Abelian monoidzmodType
: Structure for additive Abelian groups (ie, nmodType
with additive inverses)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)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.
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
/<lemma-name>
: simplify with <lemma-name>
and then use.//
: simplify beforehand
try done.
/=
: invokes the simpl
tactic ʳ//=
: //
followed by /=
simpl; try done.
=>
: revert a hypothesis from stack:
: move an assumption to stack (discharge)have
: like assert
. Start a new sub-proof.
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)move=> ->.
is same as move=> H; rewrite H.
{-2}n
capture all occurrences of n
except the second
rewrite {3}/foo.
(rewrite only 3th instance of foo
)rewrite
Perhaps most useful part of ssreflect usage.
rewrite /<definition>
is same as unfold <definition>
rewrite -/<definition>
is same as fold <definition>
have
unlock
move
do
: for iteration
do 1? <tactic>
: at most oncedo 2! <tactic>
: exactly twicedo ! <tactic>
: as many times as possible, but at least onceunlock
lemmaA 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.
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
eqnP
ubn
lemmas: stands for 'upper bound'—
—
Functions available:
commutative
associative
transitive
antisymmetric
reflexive
antireflexive
Some tutorials:
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 to done
tactic.Given a value of reflect P b
, these are useful to 'project' components:
Uses Hierarchy builder (HB).
From HB Require Import structures.
Links:
References:
https://perso.crans.org/cohen/JFLA23/hb.pdf
HB.mixin
HB.factory
HB.builders
: like constructor for a factory??HB.structure
HB.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.
:>
symbolCoq syntax.
https://stackoverflow.com/questions/51404367/the-coq-symbol
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.
fold
/ unfold
is usually not needed with ssreflect because rewrite
handles that as well (among many other things with its numerous flags).
eqn
is same as Nat.eqb
refine
not applicable to mathcomp? It isunder
tactic[]
in rewrite
. To override default inferred args?