Documentation

Mathlib.Data.PFunctor.Univariate.M

M-types #

M types are potentially infinite tree-like structures. They are defined as the greatest fixpoint of a polynomial functor.

CofixA F n is an n level approximation of an M-type

def PFunctor.Approx.head' {F : PFunctor.{u}} {n : } :
CofixA F n.succF.A

The label of the root of the tree for a non-trivial approximation of the cofix of a pfunctor.

Equations
def PFunctor.Approx.children' {F : PFunctor.{u}} {n : } (x : CofixA F n.succ) :
F.B (head' x)CofixA F n

for a non-trivial approximation, return all the subtrees of the root

Equations
inductive PFunctor.Approx.Agree {F : PFunctor.{u}} {n : } :
CofixA F nCofixA F (n + 1)Prop

Relation between two approximations of the cofix of a pfunctor that state they both contain the same data until one of them is truncated

def PFunctor.Approx.AllAgree {F : PFunctor.{u}} (x : (n : ) → CofixA F n) :

Given an infinite series of approximations approx, AllAgree approx states that they are all consistent with each other.

Equations
@[simp]
theorem PFunctor.Approx.agree_trivial {F : PFunctor.{u}} {x : CofixA F 0} {y : CofixA F 1} :
Agree x y
@[deprecated PFunctor.Approx.agree_trivial (since := "2024-12-25")]
theorem PFunctor.Approx.agree_trival {F : PFunctor.{u}} {x : CofixA F 0} {y : CofixA F 1} :
Agree x y

Alias of PFunctor.Approx.agree_trivial.

theorem PFunctor.Approx.agree_children {F : PFunctor.{u}} {n : } (x : CofixA F n.succ) (y : CofixA F (n.succ + 1)) {i : F.B (head' x)} {j : F.B (head' y)} (h₀ : HEq i j) (h₁ : Agree x y) :
theorem PFunctor.Approx.truncate_eq_of_agree {F : PFunctor.{u}} {n : } (x : CofixA F n) (y : CofixA F n.succ) (h : Agree x y) :
def PFunctor.Approx.sCorec {F : PFunctor.{u}} {X : Type w} (f : XF X) :
X(n : ) → CofixA F n

sCorec f i n creates an approximation of height n of the final coalgebra of f

Equations
theorem PFunctor.Approx.P_corec {F : PFunctor.{u}} {X : Type w} (f : XF X) (i : X) (n : ) :
Agree (sCorec f i n) (sCorec f i n.succ)

Path F provides indices to access internal nodes in Corec F

Equations
theorem PFunctor.Approx.head_succ' {F : PFunctor.{u}} (n m : ) (x : (n : ) → CofixA F n) (Hconsistent : AllAgree x) :
head' (x n.succ) = head' (x m.succ)
structure PFunctor.MIntl (F : PFunctor.{u}) :

Internal definition for M. It is needed to avoid name clashes between M.mk and M.casesOn and the declarations generated for the structure

For polynomial functor F, M F is its final coalgebra

Equations
Equations
theorem PFunctor.M.ext' (F : PFunctor.{u}) (x y : F.M) (H : ∀ (i : ), x.approx i = y.approx i) :
x = y
def PFunctor.M.corec {F : PFunctor.{u}} {X : Type u_1} (f : XF X) (i : X) :
F.M

Corecursor for the M-type defined by F.

Equations
def PFunctor.M.head {F : PFunctor.{u}} (x : F.M) :
F.A

given a tree generated by F, head gives us the first piece of data it contains

Equations
def PFunctor.M.children {F : PFunctor.{u}} (x : F.M) (i : F.B x.head) :
F.M

return all the subtrees of the root of a tree x : M F

Equations
def PFunctor.M.ichildren {F : PFunctor.{u}} [Inhabited F.M] [DecidableEq F.A] (i : F.Idx) (x : F.M) :
F.M

select a subtree using an i : F.Idx or return an arbitrary tree if i designates no subtree of x

Equations
theorem PFunctor.M.head_eq_head' {F : PFunctor.{u}} (x : F.M) (n : ) :
x.head = Approx.head' (x.approx (n + 1))
theorem PFunctor.M.head'_eq_head {F : PFunctor.{u}} (x : F.M) (n : ) :
Approx.head' (x.approx (n + 1)) = x.head
def PFunctor.M.dest {F : PFunctor.{u}} :
F.MF F.M

unfold an M-type

Equations
def PFunctor.M.Approx.sMk {F : PFunctor.{u}} (x : F F.M) (n : ) :

generates the approximations needed for M.mk

Equations
def PFunctor.M.mk {F : PFunctor.{u}} (x : F F.M) :
F.M

constructor for M-types

Equations
inductive PFunctor.M.Agree' {F : PFunctor.{u}} :
F.MF.MProp

Agree' n relates two trees of type M F that are the same up to depth n

@[simp]
theorem PFunctor.M.dest_mk {F : PFunctor.{u}} (x : F F.M) :
(M.mk x).dest = x
@[simp]
theorem PFunctor.M.mk_dest {F : PFunctor.{u}} (x : F.M) :
M.mk x.dest = x
theorem PFunctor.M.mk_inj {F : PFunctor.{u}} {x y : F F.M} (h : M.mk x = M.mk y) :
x = y
def PFunctor.M.cases {F : PFunctor.{u}} {r : F.MSort w} (f : (x : F F.M) → r (M.mk x)) (x : F.M) :
r x

destructor for M-types

Equations
def PFunctor.M.casesOn {F : PFunctor.{u}} {r : F.MSort w} (x : F.M) (f : (x : F F.M) → r (M.mk x)) :
r x

destructor for M-types

Equations
def PFunctor.M.casesOn' {F : PFunctor.{u}} {r : F.MSort w} (x : F.M) (f : (a : F.A) → (f : F.B aF.M) → r (M.mk a, f)) :
r x

destructor for M-types, similar to casesOn but also gives access directly to the root and subtrees on an M-type

Equations
theorem PFunctor.M.approx_mk {F : PFunctor.{u}} (a : F.A) (f : F.B aF.M) (i : ) :
(M.mk a, f).approx i.succ = Approx.CofixA.intro a fun (j : F.B a) => (f j).approx i
@[simp]
theorem PFunctor.M.agree'_refl {F : PFunctor.{u}} {n : } (x : F.M) :
Agree' n x x
theorem PFunctor.M.agree_iff_agree' {F : PFunctor.{u}} {n : } (x y : F.M) :
Approx.Agree (x.approx n) (y.approx (n + 1)) Agree' n x y
@[simp]
theorem PFunctor.M.cases_mk {F : PFunctor.{u}} {r : F.MSort u_2} (x : F F.M) (f : (x : F F.M) → r (M.mk x)) :
M.cases f (M.mk x) = f x
@[simp]
theorem PFunctor.M.casesOn_mk {F : PFunctor.{u}} {r : F.MSort u_2} (x : F F.M) (f : (x : F F.M) → r (M.mk x)) :
(M.mk x).casesOn f = f x
@[simp]
theorem PFunctor.M.casesOn_mk' {F : PFunctor.{u}} {r : F.MSort u_2} {a : F.A} (x : F.B aF.M) (f : (a : F.A) → (f : F.B aF.M) → r (M.mk a, f)) :
(M.mk a, x).casesOn' f = f a x
inductive PFunctor.M.IsPath {F : PFunctor.{u}} :
Approx.Path FF.MProp

IsPath p x tells us if p is a valid path through x

theorem PFunctor.M.isPath_cons {F : PFunctor.{u}} {xs : Approx.Path F} {a a' : F.A} {f : F.B aF.M} {i : F.B a'} :
IsPath (a', i :: xs) (M.mk a, f)a = a'
theorem PFunctor.M.isPath_cons' {F : PFunctor.{u}} {xs : Approx.Path F} {a : F.A} {f : F.B aF.M} {i : F.B a} :
IsPath (a, i :: xs) (M.mk a, f)IsPath xs (f i)

follow a path through a value of M F and return the subtree found at the end of the path if it is a valid path for that value and return a default tree

Equations
def PFunctor.M.iselect {F : PFunctor.{u}} [DecidableEq F.A] [Inhabited F.M] (ps : Approx.Path F) :
F.MF.A

similar to isubtree but returns the data at the end of the path instead of the whole subtree

Equations
@[simp]
theorem PFunctor.M.head_mk {F : PFunctor.{u}} (x : F F.M) :
(M.mk x).head = x.fst
theorem PFunctor.M.children_mk {F : PFunctor.{u}} {a : F.A} (x : F.B aF.M) (i : F.B (M.mk a, x).head) :
(M.mk a, x).children i = x (cast i)
@[simp]
theorem PFunctor.M.ichildren_mk {F : PFunctor.{u}} [DecidableEq F.A] [Inhabited F.M] (x : F F.M) (i : F.Idx) :
ichildren i (M.mk x) = x.iget i
@[simp]
theorem PFunctor.M.isubtree_cons {F : PFunctor.{u}} [DecidableEq F.A] [Inhabited F.M] (ps : Approx.Path F) {a : F.A} (f : F.B aF.M) {i : F.B a} :
isubtree (a, i :: ps) (M.mk a, f) = isubtree ps (f i)
@[simp]
theorem PFunctor.M.iselect_nil {F : PFunctor.{u}} [DecidableEq F.A] [Inhabited F.M] {a : F.A} (f : F.B aF.M) :
@[simp]
theorem PFunctor.M.iselect_cons {F : PFunctor.{u}} [DecidableEq F.A] [Inhabited F.M] (ps : Approx.Path F) {a : F.A} (f : F.B aF.M) {i : F.B a} :
iselect (a, i :: ps) (M.mk a, f) = iselect ps (f i)
theorem PFunctor.M.corec_def {F : PFunctor.{u}} {X : Type u_2} (f : XF X) (x₀ : X) :
M.corec f x₀ = M.mk (F.map (M.corec f) (f x₀))
theorem PFunctor.M.ext_aux {F : PFunctor.{u}} [Inhabited F.M] [DecidableEq F.A] {n : } (x y z : F.M) (hx : Agree' n z x) (hy : Agree' n z y) (hrec : ∀ (ps : Approx.Path F), n = List.length psiselect ps x = iselect ps y) :
x.approx (n + 1) = y.approx (n + 1)
theorem PFunctor.M.ext {F : PFunctor.{u}} [Inhabited F.M] [DecidableEq F.A] (x y : F.M) (H : ∀ (ps : Approx.Path F), iselect ps x = iselect ps y) :
x = y
structure PFunctor.M.IsBisimulation {F : PFunctor.{u}} (R : F.MF.MProp) :

Bisimulation is the standard proof technique for equality between infinite tree-like structures

  • head {a a' : F.A} {f : F.B aF.M} {f' : F.B a'F.M} : R (M.mk a, f) (M.mk a', f')a = a'

    The head of the trees are equal

  • tail {a : F.A} {f f' : F.B aF.M} : R (M.mk a, f) (M.mk a, f')∀ (i : F.B a), R (f i) (f' i)

    The tails are equal

theorem PFunctor.M.nth_of_bisim {F : PFunctor.{u}} (R : F.MF.MProp) [Inhabited F.M] [DecidableEq F.A] (bisim : IsBisimulation R) (s₁ s₂ : F.M) (ps : Approx.Path F) :
R s₁ s₂IsPath ps s₁ IsPath ps s₂iselect ps s₁ = iselect ps s₂ ∃ (a : F.A) (f : F.B aF.M) (f' : F.B aF.M), isubtree ps s₁ = M.mk a, f isubtree ps s₂ = M.mk a, f' ∀ (i : F.B a), R (f i) (f' i)
theorem PFunctor.M.eq_of_bisim {F : PFunctor.{u}} (R : F.MF.MProp) [Nonempty F.M] (bisim : IsBisimulation R) (s₁ s₂ : F.M) :
R s₁ s₂s₁ = s₂
def PFunctor.M.corecOn {F : PFunctor.{u}} {X : Type u_2} (x₀ : X) (f : XF X) :
F.M

corecursor for M F with swapped arguments

Equations
theorem PFunctor.M.dest_corec {P : PFunctor.{u}} {α : Type u_2} (g : αP α) (x : α) :
(M.corec g x).dest = P.map (M.corec g) (g x)
theorem PFunctor.M.bisim {P : PFunctor.{u}} (R : P.MP.MProp) (h : ∀ (x y : P.M), R x y∃ (a : P.A) (f : P.B aP.M) (f' : P.B aP.M), x.dest = a, f y.dest = a, f' ∀ (i : P.B a), R (f i) (f' i)) (x y : P.M) :
R x yx = y
theorem PFunctor.M.bisim' {P : PFunctor.{u}} {α : Type u_3} (Q : αProp) (u v : αP.M) (h : ∀ (x : α), Q x∃ (a : P.A) (f : P.B aP.M) (f' : P.B aP.M), (u x).dest = a, f (v x).dest = a, f' ∀ (i : P.B a), ∃ (x' : α), Q x' f i = u x' f' i = v x') (x : α) :
Q xu x = v x
theorem PFunctor.M.bisim_equiv {P : PFunctor.{u}} (R : P.MP.MProp) (h : ∀ (x y : P.M), R x y∃ (a : P.A) (f : P.B aP.M) (f' : P.B aP.M), x.dest = a, f y.dest = a, f' ∀ (i : P.B a), R (f i) (f' i)) (x y : P.M) :
R x yx = y
theorem PFunctor.M.corec_unique {P : PFunctor.{u}} {α : Type u_2} (g : αP α) (f : αP.M) (hyp : ∀ (x : α), (f x).dest = P.map f (g x)) :
def PFunctor.M.corec₁ {P : PFunctor.{u}} {α : Type u} (F : (X : Type u) → (αX)αP X) :
αP.M

corecursor where the state of the computation can be sent downstream in the form of a recursive call

Equations
def PFunctor.M.corec' {P : PFunctor.{u}} {α : Type u} (F : {X : Type u} → (αX)αP.M P X) (x : α) :
P.M

corecursor where it is possible to return a fully formed value at any point of the computation

Equations
  • One or more equations did not get rendered due to their size.