File: Mathlib/Data/QPF/Multivariate/Constructions/Cofix.lean

full_name: MvQPF.corecF
code: /-- `corecF` is used as a basis for defining the corecursor of `Cofix F α`. `corecF`
uses corecursion to construct the M-type generated by `q.P` and uses function on `F`
as a corecursive step -/
def corecF {α : TypeVec n} {β : Type u} (g : β → F (α.append1 β)) : β → q.P.M α 
goal: β → (MvQPF.P F).M α

full_name: MvQPF.corecF_eq
code: theorem corecF_eq {α : TypeVec n} {β : Type u} (g : β → F (α.append1 β)) (x : β) :
    M.dest q.P (corecF g x) = appendFun id (corecF g) <$$> repr (g x) 
goal: MvPFunctor.M.dest (MvQPF.P F) (MvQPF.corecF g x) = (TypeVec.id ::: MvQPF.corecF g) <$$> MvQPF.repr (g x)

full_name: MvQPF.IsPrecongr
code: /-- Characterization of desirable equivalence relations on M-types -/
def IsPrecongr {α : TypeVec n} (r : q.P.M α → q.P.M α → Prop) : Prop 
goal: Prop

full_name: MvQPF.Mcongr
code: /-- Equivalence relation on M-types representing a value of type `Cofix F` -/
def Mcongr {α : TypeVec n} (x y : q.P.M α) : Prop 
goal: Prop

full_name: MvQPF.Cofix
code: /-- Greatest fixed point of functor F. The result is a functor with one fewer parameters
than the input. For `F a b c` a ternary functor, fix F is a binary functor such that

```lean
Cofix F a b = F a b (Cofix F a b)
```
-/
def Cofix (F : TypeVec (n + 1) → Type u) [MvQPF F] (α : TypeVec n) 
goal: Type u

full_name: MvQPF.instInhabitedCofixOfAP
code: instance {α : TypeVec n} [Inhabited q.P.A] [∀ i : Fin2 n, Inhabited (α i)] :
    Inhabited (Cofix F α) 
goal: Inhabited (MvQPF.Cofix F α)

full_name: MvQPF.mRepr
code: /-- maps every element of the W type to a canonical representative -/
def mRepr {α : TypeVec n} : q.P.M α → q.P.M α 
goal: (MvQPF.P F).M α → (MvQPF.P F).M α

full_name: MvQPF.Cofix.map
code: /-- the map function for the functor `Cofix F` -/
def Cofix.map {α β : TypeVec n} (g : α ⟹ β) : Cofix F α → Cofix F β 
goal: MvQPF.Cofix F α → MvQPF.Cofix F β

full_name: MvQPF.Cofix.mvfunctor
code: instance Cofix.mvfunctor : MvFunctor (Cofix F) 
goal: MvFunctor (MvQPF.Cofix F)

full_name: MvQPF.Cofix.corec
code: /-- Corecursor for `Cofix F` -/
def Cofix.corec {α : TypeVec n} {β : Type u} (g : β → F (α.append1 β)) : β → Cofix F α 
goal: β → MvQPF.Cofix F α

full_name: MvQPF.Cofix.dest
code: /-- Destructor for `Cofix F` -/
def Cofix.dest {α : TypeVec n} : Cofix F α → F (α.append1 (Cofix F α)) 
goal: MvQPF.Cofix F α → F (α ::: MvQPF.Cofix F α)

full_name: MvQPF.Cofix.abs
code: /-- Abstraction function for `cofix F α` -/
def Cofix.abs {α} : q.P.M α → Cofix F α 
goal: (MvQPF.P F).M α → MvQPF.Cofix F α

full_name: MvQPF.Cofix.repr
code: /-- Representation function for `Cofix F α` -/
def Cofix.repr {α} : Cofix F α → q.P.M α 
goal: MvQPF.Cofix F α → (MvQPF.P F).M α

full_name: MvQPF.Cofix.corec'₁
code: /-- Corecursor for `Cofix F` -/
def Cofix.corec'₁ {α : TypeVec n} {β : Type u} (g : ∀ {X}, (β → X) → F (α.append1 X)) (x : β) :
    Cofix F α 
goal: MvQPF.Cofix F α

full_name: MvQPF.Cofix.corec'
code: /-- More flexible corecursor for `Cofix F`. Allows the return of a fully formed
value instead of making a recursive call -/
def Cofix.corec' {α : TypeVec n} {β : Type u} (g : β → F (α.append1 (Cofix F α ⊕ β))) (x : β) :
    Cofix F α 
goal: MvQPF.Cofix F α

full_name: MvQPF.Cofix.corec₁
code: /-- Corecursor for `Cofix F`. The shape allows recursive calls to
look like recursive calls. -/
def Cofix.corec₁ {α : TypeVec n} {β : Type u}
    (g : ∀ {X}, (Cofix F α → X) → (β → X) → β → F (α ::: X)) (x : β) : Cofix F α 
goal: MvQPF.Cofix F α

full_name: MvQPF.Cofix.dest_corec
code: theorem Cofix.dest_corec {α : TypeVec n} {β : Type u} (g : β → F (α.append1 β)) (x : β) :
    Cofix.dest (Cofix.corec g x) = appendFun id (Cofix.corec g) <$$> g x 
goal: (MvQPF.Cofix.corec g x).dest = (TypeVec.id ::: MvQPF.Cofix.corec g) <$$> g x

full_name: MvQPF.Cofix.mk
code: /-- constructor for `Cofix F` -/
def Cofix.mk {α : TypeVec n} : F (α.append1 <| Cofix F α) → Cofix F α 
goal: F (α ::: MvQPF.Cofix F α) → MvQPF.Cofix F α

full_name: _private.Mathlib.Data.QPF.Multivariate.Constructions.Cofix.0.MvQPF.Cofix.bisim_aux
code: private theorem Cofix.bisim_aux {α : TypeVec n} (r : Cofix F α → Cofix F α → Prop) (h' : ∀ x, r x x)
    (h : ∀ x y, r x y →
      appendFun id (Quot.mk r) <$$> Cofix.dest x = appendFun id (Quot.mk r) <$$> Cofix.dest y) :
    ∀ x y, r x y → x = y 
goal: r x y → x = y

full_name: MvQPF.Cofix.bisim_rel
code: /-- Bisimulation principle using `map` and `Quot.mk` to match and relate children of two trees. -/
theorem Cofix.bisim_rel {α : TypeVec n} (r : Cofix F α → Cofix F α → Prop)
    (h : ∀ x y, r x y →
      appendFun id (Quot.mk r) <$$> Cofix.dest x = appendFun id (Quot.mk r) <$$> Cofix.dest y) :
    ∀ x y, r x y → x = y 
goal: r x y → x = y

full_name: MvQPF.Cofix.bisim
code: /-- Bisimulation principle using `LiftR` to match and relate children of two trees. -/
theorem Cofix.bisim {α : TypeVec n} (r : Cofix F α → Cofix F α → Prop)
    (h : ∀ x y, r x y → LiftR (RelLast α r (i := _)) (Cofix.dest x) (Cofix.dest y)) :
    ∀ x y, r x y → x = y 
goal: r x y → x = y

full_name: MvQPF.Cofix.bisim₂
code: /-- Bisimulation principle using `LiftR'` to match and relate children of two trees. -/
theorem Cofix.bisim₂ {α : TypeVec n} (r : Cofix F α → Cofix F α → Prop)
    (h : ∀ x y, r x y → LiftR' (RelLast' α r) (Cofix.dest x) (Cofix.dest y)) :
    ∀ x y, r x y → x = y 
goal: r x y → x = y

full_name: MvQPF.Cofix.bisim'
code: /-- Bisimulation principle the values `⟨a,f⟩` of the polynomial functor representing
`Cofix F α` as well as an invariant `Q : β → Prop` and a state `β` generating the
left-hand side and right-hand side of the equality through functions `u v : β → Cofix F α` -/
theorem Cofix.bisim' {α : TypeVec n} {β : Type*} (Q : β → Prop) (u v : β → Cofix F α)
    (h : ∀ x, Q x → ∃ a f' f₀ f₁,
      Cofix.dest (u x) = q.abs ⟨a, q.P.appendContents f' f₀⟩ ∧
        Cofix.dest (v x) = q.abs ⟨a, q.P.appendContents f' f₁⟩ ∧
          ∀ i, ∃ x', Q x' ∧ f₀ i = u x' ∧ f₁ i = v x') :
    ∀ x, Q x → u x = v x 
goal: Q x → u x = v x

full_name: MvQPF.Cofix.mk_dest
code: theorem Cofix.mk_dest {α : TypeVec n} (x : Cofix F α) : Cofix.mk (Cofix.dest x) = x 
goal: MvQPF.Cofix.mk x.dest = x

full_name: MvQPF.Cofix.dest_mk
code: theorem Cofix.dest_mk {α : TypeVec n} (x : F (α.append1 <| Cofix F α)) :
    Cofix.dest (Cofix.mk x) = x 
goal: (MvQPF.Cofix.mk x).dest = x

full_name: MvQPF.Cofix.ext
code: theorem Cofix.ext {α : TypeVec n} (x y : Cofix F α) (h : x.dest = y.dest) : x = y 
goal: x = y

full_name: MvQPF.Cofix.ext_mk
code: theorem Cofix.ext_mk {α : TypeVec n} (x y : F (α ::: Cofix F α)) (h : Cofix.mk x = Cofix.mk y) :
    x = y 
goal: x = y

full_name: MvQPF.liftR_map
code: theorem liftR_map {α β : TypeVec n} {F' : TypeVec n → Type u} [MvFunctor F'] [LawfulMvFunctor F']
    (R : β ⊗ β ⟹ «repeat» n Prop) (x : F' α) (f g : α ⟹ β) (h : α ⟹ Subtype_ R)
    (hh : subtypeVal _ ⊚ h = (f ⊗' g) ⊚ prod.diag) : LiftR' R (f <$$> x) (g <$$> x) 
goal: MvFunctor.LiftR' R (f <$$> x) (g <$$> x)

full_name: MvQPF.liftR_map_last
code: theorem liftR_map_last [lawful : LawfulMvFunctor F]
    {α : TypeVec n} {ι ι'} (R : ι' → ι' → Prop)
    (x : F (α ::: ι)) (f g : ι → ι') (hh : ∀ x : ι, R (f x) (g x)) :
    LiftR' (RelLast' _ R) ((id ::: f) <$$> x) ((id ::: g) <$$> x) 
goal: MvFunctor.LiftR' (α.RelLast' R) ((TypeVec.id ::: f) <$$> x) ((TypeVec.id ::: g) <$$> x)

full_name: MvQPF.liftR_map_last'
code: theorem liftR_map_last' [LawfulMvFunctor F] {α : TypeVec n} {ι} (R : ι → ι → Prop) (x : F (α ::: ι))
    (f : ι → ι) (hh : ∀ x : ι, R (f x) x) : LiftR' (RelLast' _ R) ((id ::: f) <$$> x) x 
goal: MvFunctor.LiftR' (α.RelLast' R) ((TypeVec.id ::: f) <$$> x) x

full_name: MvQPF.Cofix.abs_repr
code: theorem Cofix.abs_repr {α} (x : Cofix F α) : Quot.mk _ (Cofix.repr x) = x 
goal: Quot.mk MvQPF.Mcongr x.repr = x

full_name: Mathlib.Tactic.MvBisim.tacticMv_bisim___With___
code: /-- tactic for proof by bisimulation -/
syntax "mv_bisim" (ppSpace colGt term) (" with" (ppSpace colGt binderIdent)+)? : tactic
goal: Lean.ParserDescr

full_name: Mathlib.Tactic.MvBisim._aux_Mathlib_Data_QPF_Multivariate_Constructions_Cofix___elabRules_Mathlib_Tactic_MvBisim_tacticMv_bisim___With____1
code: elab_rules : tactic
  | `(tactic| mv_bisim $e $[ with $ids:binderIdent*]?) => do
    let ids : TSyntaxArray `Lean.binderIdent := ids.getD #[]
    let idsn (n : ℕ) : Name :=
      match ids[n]? with
      | some s =>
        match s with
        | `(binderIdent| $n:ident) => n.getId
        | `(binderIdent| _) => `_
        | _ => unreachable!
      | none => `_
    let idss (n : ℕ) : TacticM (TSyntax `rcasesPat) := do
      match ids[n]? with
      | some s =>
        match s with
        | `(binderIdent| $n:ident) => `(rcasesPat| $n)
        | `(binderIdent| _%$b) => `(rcasesPat| _%$b)
        | _ => unreachable!
      | none => `(rcasesPat| _)
    withMainContext do
      let e ← Tactic.elabTerm e none
      let f ← liftMetaTacticAux fun g => do
        let (#[fv], g) ← g.generalize #[{ expr := e }] | unreachable!
        return (mkFVar fv, [g])
      withMainContext do
        let some (t, l, r) ← matchEq? (← getMainTarget) | throwError "goal is not an equality"
        let ex ←
          withLocalDecl (idsn 1) .default t fun v₀ =>
            withLocalDecl (idsn 2) .default t fun v₁ => do
              let x₀ ← mkEq v₀ l
              let x₁ ← mkEq v₁ r
              let xx ← mkAppM ``And #[x₀, x₁]
              let ex₁ ← mkLambdaFVars #[f] xx
              let ex₂ ← mkAppM ``Exists #[ex₁]
              mkLambdaFVars #[v₀, v₁] ex₂
        let R ← liftMetaTacticAux fun g => do
          let g₁ ← g.define (idsn 0) (← mkArrow t (← mkArrow t (mkSort .zero))) ex
          let (Rv, g₂) ← g₁.intro1P
          return (mkFVar Rv, [g₂])
        withMainContext do
          ids[0]?.forM fun s => addLocalVarInfoForBinderIdent R s
          let sR ← exprToSyntax R
          evalTactic <| ← `(tactic|
            refine MvQPF.Cofix.bisim₂ $sR ?_ _ _ ⟨_, rfl, rfl⟩;
            rintro $(← idss 1) $(← idss 2) ⟨$(← idss 3), $(← idss 4), $(← idss 5)⟩)
          liftMetaTactic fun g => return [← g.clear f.fvarId!]
    for n in [6 : ids.size] do
      let name := ids[n]!
      logWarningAt name m!"unused name: {name}"
goal: Lean.Elab.Tactic.Tactic

full_name: MvQPF.corec_roll
code: theorem corec_roll {α : TypeVec n} {X Y} {x₀ : X} (f : X → Y) (g : Y → F (α ::: X)) :
    Cofix.corec (g ∘ f) x₀ = Cofix.corec (MvFunctor.map (id ::: f) ∘ g) (f x₀) 
goal: MvQPF.Cofix.corec (g ∘ f) x₀ = MvQPF.Cofix.corec (MvFunctor.map (TypeVec.id ::: f) ∘ g) (f x₀)

full_name: MvQPF.Cofix.dest_corec'
code: theorem Cofix.dest_corec' {α : TypeVec.{u} n} {β : Type u}
    (g : β → F (α.append1 (Cofix F α ⊕ β))) (x : β) :
    Cofix.dest (Cofix.corec' g x) =
      appendFun id (Sum.elim _root_.id (Cofix.corec' g)) <$$> g x 
goal: (MvQPF.Cofix.corec' g x).dest = (TypeVec.id ::: Sum.elim id (MvQPF.Cofix.corec' g)) <$$> g x

full_name: MvQPF.Cofix.dest_corec₁
code: theorem Cofix.dest_corec₁ {α : TypeVec n} {β : Type u}
    (g : ∀ {X}, (Cofix F α → X) → (β → X) → β → F (α.append1 X)) (x : β)
    (h : ∀ (X Y) (f : Cofix F α → X) (f' : β → X) (k : X → Y),
      g (k ∘ f) (k ∘ f') x = (id ::: k) <$$> g f f' x) :
    Cofix.dest (Cofix.corec₁ (@g) x) = g id (Cofix.corec₁ @g) x 
goal: (MvQPF.Cofix.corec₁ g x).dest = g id (MvQPF.Cofix.corec₁ g) x

full_name: MvQPF.mvqpfCofix
code: instance mvqpfCofix : MvQPF (Cofix F) 
goal: MvQPF (MvQPF.Cofix F)