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.

inductive PFunctor.Approx.CofixA (F : PFunctor.{uA, uB}) :
Type (max uA uB)

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
            def PFunctor.Approx.children' {F : PFunctor.{uA, uB}} {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
              Instances For
                inductive PFunctor.Approx.Agree {F : PFunctor.{uA, uB}} {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

                Instances For

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

                  Equations
                    Instances For
                      @[simp]
                      theorem PFunctor.Approx.agree_trivial {F : PFunctor.{uA, uB}} {x : CofixA F 0} {y : CofixA F 1} :
                      Agree x y
                      theorem PFunctor.Approx.agree_children {F : PFunctor.{uA, uB}} {n : } (x : CofixA F n.succ) (y : CofixA F (n.succ + 1)) {i : F.B (head' x)} {j : F.B (head' y)} (h₀ : i j) (h₁ : Agree x y) :
                      def PFunctor.Approx.truncate {F : PFunctor.{uA, uB}} {n : } :
                      CofixA F (n + 1)CofixA F n

                      truncate a turns a into a more limited approximation

                      Equations
                        Instances For
                          theorem PFunctor.Approx.truncate_eq_of_agree {F : PFunctor.{uA, uB}} {n : } (x : CofixA F n) (y : CofixA F n.succ) (h : Agree x y) :
                          def PFunctor.Approx.sCorec {F : PFunctor.{uA, uB}} {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
                            Instances For
                              theorem PFunctor.Approx.P_corec {F : PFunctor.{uA, uB}} {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
                                Instances For
                                  theorem PFunctor.Approx.head_succ' {F : PFunctor.{uA, uB}} (n m : ) (x : (n : ) → CofixA F n) (Hconsistent : AllAgree x) :
                                  head' (x n.succ) = head' (x m.succ)
                                  structure PFunctor.MIntl (F : PFunctor.{uA, uB}) :
                                  Type (max uA uB)

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

                                  Instances For
                                    def PFunctor.M (F : PFunctor.{uA, uB}) :
                                    Type (max uA uB)

                                    For polynomial functor F, M F is its final coalgebra

                                    Equations
                                      Instances For
                                        theorem PFunctor.M.ext' (F : PFunctor.{uA, uB}) (x y : F.M) (H : ∀ (i : ), x.approx i = y.approx i) :
                                        x = y
                                        def PFunctor.M.corec {F : PFunctor.{uA, uB}} {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.{uA, uB}} (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.{uA, uB}} (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.{uA, uB}} [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
                                                        def PFunctor.M.dest {F : PFunctor.{uA, uB}} :
                                                        F.MF F.M

                                                        unfold an M-type

                                                        Equations
                                                          Instances For
                                                            def PFunctor.M.Approx.sMk {F : PFunctor.{uA, uB}} (x : F F.M) (n : ) :

                                                            generates the approximations needed for M.mk

                                                            Equations
                                                              Instances For
                                                                def PFunctor.M.mk {F : PFunctor.{uA, uB}} (x : F F.M) :
                                                                F.M

                                                                constructor for M-types

                                                                Equations
                                                                  Instances For
                                                                    inductive PFunctor.M.Agree' {F : PFunctor.{uA, uB}} :
                                                                    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.{uA, uB}} (x : F F.M) :
                                                                      (M.mk x).dest = x
                                                                      @[simp]
                                                                      theorem PFunctor.M.mk_dest {F : PFunctor.{uA, uB}} (x : F.M) :
                                                                      M.mk x.dest = x
                                                                      theorem PFunctor.M.mk_inj {F : PFunctor.{uA, uB}} {x y : F F.M} (h : M.mk x = M.mk y) :
                                                                      x = y
                                                                      def PFunctor.M.cases {F : PFunctor.{uA, uB}} {r : F.MSort w} (f : (x : F F.M) → r (M.mk x)) (x : F.M) :
                                                                      r x

                                                                      destructor for M-types

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

                                                                          destructor for M-types

                                                                          Equations
                                                                            Instances For
                                                                              def PFunctor.M.casesOn' {F : PFunctor.{uA, uB}} {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
                                                                                Instances For
                                                                                  theorem PFunctor.M.approx_mk {F : PFunctor.{uA, uB}} (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.{uA, uB}} {n : } (x : F.M) :
                                                                                  Agree' n x x
                                                                                  theorem PFunctor.M.agree_iff_agree' {F : PFunctor.{uA, uB}} {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.{uA, uB}} {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.{uA, uB}} {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.{uA, uB}} {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

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

                                                                                  Instances For
                                                                                    theorem PFunctor.M.isPath_cons {F : PFunctor.{uA, uB}} {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.{uA, uB}} {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
                                                                                      Instances For

                                                                                        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.{uA, uB}} (x : F F.M) :
                                                                                            (M.mk x).head = x.fst
                                                                                            theorem PFunctor.M.children_mk {F : PFunctor.{uA, uB}} {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.{uA, uB}} [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.{uA, uB}} [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.{uA, uB}} [DecidableEq F.A] [Inhabited F.M] {a : F.A} (f : F.B aF.M) :
                                                                                            @[simp]
                                                                                            theorem PFunctor.M.iselect_cons {F : PFunctor.{uA, uB}} [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.{uA, uB}} {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.{uA, uB}} [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.{uA, uB}} [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.{uA, uB}} (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

                                                                                            Instances For
                                                                                              theorem PFunctor.M.nth_of_bisim {F : PFunctor.{uA, uB}} (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.{uA, uB}} (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.{uA, uB}} {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.{uA, uB}} {α : Type u_2} (g : αP α) (x : α) :
                                                                                                  (M.corec g x).dest = P.map (M.corec g) (g x)
                                                                                                  theorem PFunctor.M.bisim {P : PFunctor.{uA, uB}} (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.{uA, uB}} {α : 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.{uA, uB}} (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.{uA, uB}} {α : Type u_2} (g : αP α) (f : αP.M) (hyp : ∀ (x : α), (f x).dest = P.map f (g x)) :
                                                                                                  def PFunctor.M.corec₁ {P : PFunctor.{uA, uB}} {α : 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.{uA, uB}} {α : Type u} (F : {X : Type (max u uA uB)} → (α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
                                                                                                        Instances For