Using mathcomp


mathcomp is consists of many 'parts'. Including:ˡ:

General

finset

https://github.com/math-comp/math-comp/blob/master/mathcomp/ssreflect/finset.v

Inductive set_type (T: finType): predArgType :=
| FinSet: {ffun pred T} -> set_type T.           

Essentially just the characteristic function of the set.

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)

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).               

pred

From eqtype.v:

in is usually associated with iteration. \in indicates membership.

ssrbool

ssrfun

TODO Phantom types

Mathcomp book: 6.10.1

Some notations

Bool

&& andb
││ orb
== eqb

pred

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

Page 39 mathcomp book

seq (lists)

mathcomp stdlib
[::] []
[:: a] [a]
[:: 1, 2, 3] [1,2,3]
[:: 1, 2 & l] 1 :: 2 :: l

finType

eqType

Types with decidable equality.

Subtypes:

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:

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

  1. 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:

    1. Take elements of r that satisfy P
    2. Use F to convert these elements to type R
    3. Use 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.

    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>
    

  2. 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 *)
    
  3. 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 filter P 'into the generic term'
    • big_cat: bigop involving concatenation of two sequences
    • big_ord0: base case

ordinal

tuple

n.-tuple is essentially a seq with a proof that its length is less than n.

matrix

Submatrices:

Block matrix building:

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).
  1. 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

finType

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.

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

rewrite

Perhaps most useful part of ssreflect usage.

Tactics and tacticals

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
*)

From https://www.math.nagoya-u.ac.jp/~garrigue/lecture/2017_AW/mathcomp-1.6/htmldoc/mathcomp.ssreflect.ssreflect.html:

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

Functions available:

ssreflect

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)

Given a value of reflect P b, these are useful to 'project' components:

mathcomp2

Uses Hierarchy builder (HB).

From HB Require Import structures.

Links:

Hierarchy builder (HB)

References:

Primitives in HB

https://perso.crans.org/cohen/JFLA23/hb.pdf

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

:> 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

Doubts

Resources