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

        Instances For
          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
          Instances For
            @[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
            Instances For
              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
              Instances For
                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.cases_on and the declarations generated for the structure

                • approx (n : ) : Approx.CofixA F n

                  An n-th level approximation, for each depth n

                • consistent : Approx.AllAgree self.approx

                  Each approximation agrees with the next

                Instances For

                  For polynomial functor F, M F is its final coalgebra

                  Equations
                  • F.M = F.MIntl
                  Instances For
                    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
                    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) :
                            Approx.head' (x.approx n.succ) = Approx.head' (x.approx m.succ)
                            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
                            theorem PFunctor.M.truncate_approx {F : PFunctor.{u}} (x : F.M) (n : ) :
                            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 = 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) :
                                    (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
                                    Instances For
                                      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
                                      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 (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 : ) :
                                          (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

                                          Instances For
                                            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)
                                            def PFunctor.M.isubtree {F : PFunctor.{u}} [DecidableEq F.A] [Inhabited F.M] :
                                            Approx.Path FF.MF.M

                                            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 : 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
                                                theorem PFunctor.M.iselect_eq_default {F : PFunctor.{u}} [DecidableEq F.A] [Inhabited F.M] (ps : Approx.Path F) (x : F.M) (h : ¬IsPath ps x) :
                                                iselect ps x = default.head
                                                @[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) :
                                                iselect [] (M.mk a, f) = a
                                                @[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] (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

                                                Instances For
                                                  theorem PFunctor.M.nth_of_bisim {F : PFunctor.{u}} (R : F.MF.MProp) [Inhabited F.M] (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
                                                  Instances For
                                                    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
                                                    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