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

Instances For

    default inhabitant of CofixA

    Equations
    Instances For

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

      Equations
      Instances For

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

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

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

          Instances For

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

            Equations
            Instances For

              truncate a turns a into a more limited approximation

              Equations
              Instances For
                def PFunctor.Approx.sCorec {F : PFunctor.{u}} {X : Type w} (f : XF X) :
                X(n : ) → PFunctor.Approx.CofixA F n

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

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

                  Path F provides indices to access internal nodes in Corec F

                  Equations
                  Instances For
                    Equations
                    • PFunctor.Approx.Path.inhabited = { default := [] }
                    theorem PFunctor.Approx.head_succ' {F : PFunctor.{u}} (n : ) (m : ) (x : (n : ) → PFunctor.Approx.CofixA F n) (Hconsistent : PFunctor.Approx.AllAgree x) :
                    structure PFunctor.MIntl (F : PFunctor.{u}) :

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

                    Instances For
                      theorem PFunctor.MIntl.consistent {F : PFunctor.{u}} (self : F.MIntl) :

                      Each approximation agrees with the next

                      For polynomial functor F, M F is its final coalgebra

                      Equations
                      • F.M = F.MIntl
                      Instances For
                        Equations
                        Equations
                        theorem PFunctor.M.ext' (F : PFunctor.{u}) (x : F.M) (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
                        Instances For
                          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
                          Instances For
                            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
                            Instances For
                              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
                              Instances For
                                theorem PFunctor.M.head_succ {F : PFunctor.{u}} (n : ) (m : ) (x : F.M) :
                                PFunctor.Approx.head' (x.approx n.succ) = PFunctor.Approx.head' (x.approx m.succ)
                                theorem PFunctor.M.head_eq_head' {F : PFunctor.{u}} (x : F.M) (n : ) :
                                x.head = PFunctor.Approx.head' (x.approx (n + 1))
                                theorem PFunctor.M.head'_eq_head {F : PFunctor.{u}} (x : F.M) (n : ) :
                                PFunctor.Approx.head' (x.approx (n + 1)) = x.head
                                theorem PFunctor.M.truncate_approx {F : PFunctor.{u}} (x : F.M) (n : ) :
                                PFunctor.Approx.truncate (x.approx (n + 1)) = x.approx n
                                def PFunctor.M.dest {F : PFunctor.{u}} :
                                F.MF F.M

                                unfold an M-type

                                Equations
                                • x.dest = let x := x; x.head, fun (i : F.B x.head) => x.children i
                                Instances For
                                  def PFunctor.M.Approx.sMk {F : PFunctor.{u}} (x : F F.M) (n : ) :

                                  generates the approximations needed for M.mk

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

                                    constructor for M-types

                                    Equations
                                    Instances For
                                      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

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

                                        destructor for M-types

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

                                          destructor for M-types

                                          Equations
                                          Instances For
                                            def PFunctor.M.casesOn' {F : PFunctor.{u}} {r : F.MSort w} (x : F.M) (f : (a : F.A) → (f : F.B aF.M) → r (PFunctor.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
                                            • x.casesOn' f = x.casesOn fun (x : F F.M) => match x with | a, g => f a g
                                            Instances For
                                              theorem PFunctor.M.approx_mk {F : PFunctor.{u}} (a : F.A) (f : F.B aF.M) (i : ) :
                                              (PFunctor.M.mk a, f).approx i.succ = PFunctor.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) :
                                              theorem PFunctor.M.agree_iff_agree' {F : PFunctor.{u}} {n : } (x : F.M) (y : F.M) :
                                              PFunctor.Approx.Agree (x.approx n) (y.approx (n + 1)) PFunctor.M.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 (PFunctor.M.mk 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 (PFunctor.M.mk x)) :
                                              (PFunctor.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 (PFunctor.M.mk a, f)) :
                                              (PFunctor.M.mk a, x).casesOn' f = f a x

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

                                              Instances For
                                                theorem PFunctor.M.isPath_cons {F : PFunctor.{u}} {xs : PFunctor.Approx.Path F} {a : F.A} {a' : F.A} {f : F.B aF.M} {i : F.B a'} :
                                                PFunctor.M.IsPath (a', i :: xs) (PFunctor.M.mk a, f)a = a'
                                                theorem PFunctor.M.isPath_cons' {F : PFunctor.{u}} {xs : PFunctor.Approx.Path F} {a : F.A} {f : F.B aF.M} {i : F.B a} :
                                                PFunctor.M.IsPath (a, i :: xs) (PFunctor.M.mk a, f)PFunctor.M.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
                                                Instances For
                                                  def PFunctor.M.iselect {F : PFunctor.{u}} [DecidableEq F.A] [Inhabited F.M] (ps : PFunctor.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
                                                  Instances For
                                                    @[simp]
                                                    theorem PFunctor.M.head_mk {F : PFunctor.{u}} (x : F F.M) :
                                                    (PFunctor.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 (PFunctor.M.mk a, x).head) :
                                                    (PFunctor.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) :
                                                    @[simp]
                                                    theorem PFunctor.M.isubtree_cons {F : PFunctor.{u}} [DecidableEq F.A] [Inhabited F.M] (ps : PFunctor.Approx.Path F) {a : F.A} (f : F.B aF.M) {i : F.B a} :
                                                    PFunctor.M.isubtree (a, i :: ps) (PFunctor.M.mk a, f) = PFunctor.M.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 : PFunctor.Approx.Path F) {a : F.A} (f : F.B aF.M) {i : F.B a} :
                                                    PFunctor.M.iselect (a, i :: ps) (PFunctor.M.mk a, f) = PFunctor.M.iselect ps (f i)
                                                    theorem PFunctor.M.corec_def {F : PFunctor.{u}} {X : Type u_2} (f : XF X) (x₀ : X) :
                                                    PFunctor.M.corec f x₀ = PFunctor.M.mk (F.map (PFunctor.M.corec f) (f x₀))
                                                    theorem PFunctor.M.ext_aux {F : PFunctor.{u}} [Inhabited F.M] [DecidableEq F.A] {n : } (x : F.M) (y : F.M) (z : F.M) (hx : PFunctor.M.Agree' n z x) (hy : PFunctor.M.Agree' n z y) (hrec : ∀ (ps : PFunctor.Approx.Path F), n = List.length psPFunctor.M.iselect ps x = PFunctor.M.iselect ps y) :
                                                    x.approx (n + 1) = y.approx (n + 1)
                                                    theorem PFunctor.M.ext {F : PFunctor.{u}} [Inhabited F.M] (x : F.M) (y : F.M) (H : ∀ (ps : PFunctor.Approx.Path F), PFunctor.M.iselect ps x = PFunctor.M.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 (PFunctor.M.mk a, f) (PFunctor.M.mk a', f')a = a'

                                                      The head of the trees are equal

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

                                                      The tails are equal

                                                    Instances For
                                                      theorem PFunctor.M.IsBisimulation.head {F : PFunctor.{u}} {R : F.MF.MProp} (self : PFunctor.M.IsBisimulation R) {a : F.A} {a' : F.A} {f : F.B aF.M} {f' : F.B a'F.M} :
                                                      R (PFunctor.M.mk a, f) (PFunctor.M.mk a', f')a = a'

                                                      The head of the trees are equal

                                                      theorem PFunctor.M.IsBisimulation.tail {F : PFunctor.{u}} {R : F.MF.MProp} (self : PFunctor.M.IsBisimulation R) {a : F.A} {f : F.B aF.M} {f' : F.B aF.M} :
                                                      R (PFunctor.M.mk a, f) (PFunctor.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] (bisim : PFunctor.M.IsBisimulation R) (s₁ : F.M) (s₂ : F.M) (ps : PFunctor.Approx.Path F) :
                                                      R s₁ s₂PFunctor.M.IsPath ps s₁ PFunctor.M.IsPath ps s₂PFunctor.M.iselect ps s₁ = PFunctor.M.iselect ps s₂ ∃ (a : F.A) (f : F.B aF.M) (f' : F.B aF.M), PFunctor.M.isubtree ps s₁ = PFunctor.M.mk a, f PFunctor.M.isubtree ps s₂ = PFunctor.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 : PFunctor.M.IsBisimulation R) (s₁ : F.M) (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
                                                      Instances For
                                                        theorem PFunctor.M.dest_corec {P : PFunctor.{u}} {α : Type u_2} (g : αP α) (x : α) :
                                                        (PFunctor.M.corec g x).dest = P.map (PFunctor.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 : P.M) (y : P.M) :
                                                        R x yx = y
                                                        theorem PFunctor.M.bisim' {P : PFunctor.{u}} {α : Type u_3} (Q : αProp) (u : αP.M) (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 : P.M) (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
                                                        Instances For
                                                          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.
                                                          Instances For