Theorem: WittVector.IsPoly₂.comp
File: Mathlib/RingTheory/WittVector/IsPoly.lean

tactic: obtain ⟨φ, hf⟩ := hf
state_before: p : ℕ
R S : Type u
σ : Type ?u.544924
idx : Type ?u.544927
inst✝¹ : CommRing R
inst✝ : CommRing S
h : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
hh : IsPoly₂ p h
hf : IsPoly p f
hg : IsPoly p g
⊢ IsPoly₂ p fun R _Rcr x y => h (f x) (g y)

tactic: obtain ⟨ψ, hg⟩ := hg
state_before: case mk'.intro
p : ℕ
R S : Type u
σ : Type ?u.544924
idx : Type ?u.544927
inst✝¹ : CommRing R
inst✝ : CommRing S
h : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
hh : IsPoly₂ p h
hg : IsPoly p g
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => ↑(aeval x.coeff) (φ n)
⊢ IsPoly₂ p fun R _Rcr x y => h (f x) (g y)

tactic: obtain ⟨χ, hh⟩ := hh
state_before: case mk'.intro.mk'.intro
p : ℕ
R S : Type u
σ : Type ?u.544924
idx : Type ?u.544927
inst✝¹ : CommRing R
inst✝ : CommRing S
h : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
hh : IsPoly₂ p h
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => ↑(aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => ↑(aeval x.coeff) (ψ n)
⊢ IsPoly₂ p fun R _Rcr x y => h (f x) (g y)

tactic: refine'
  ⟨⟨fun n =>
      bind₁
        (uncurry <|
          ![fun k => rename (Prod.mk (0 : Fin 2)) (φ k), fun k =>
            rename (Prod.mk (1 : Fin 2)) (ψ k)])
        (χ n),
      _⟩⟩
state_before: case mk'.intro.mk'.intro.mk'.intro
p : ℕ
R S : Type u
σ : Type ?u.544924
idx : Type ?u.544927
inst✝¹ : CommRing R
inst✝ : CommRing S
h : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => ↑(aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => ↑(aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
⊢ IsPoly₂ p fun R _Rcr x y => h (f x) (g y)

tactic: intros
state_before: case mk'.intro.mk'.intro.mk'.intro
p : ℕ
R S : Type u
σ : Type ?u.544924
idx : Type ?u.544927
inst✝¹ : CommRing R
inst✝ : CommRing S
h : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => ↑(aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => ↑(aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
⊢ ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x y : 𝕎 R),
    (h (f x) (g y)).coeff = fun n =>
      peval
        ((fun n =>
            ↑(bind₁ (uncurry ![fun k => ↑(rename (Prod.mk 0)) (φ k), fun k => ↑(rename (Prod.mk 1)) (ψ k)])) (χ n))
          n)
        ![x.coeff, y.coeff]

tactic: funext n
state_before: case mk'.intro.mk'.intro.mk'.intro
p : ℕ
R S : Type u
σ : Type ?u.544924
idx : Type ?u.544927
inst✝² : CommRing R
inst✝¹ : CommRing S
h : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => ↑(aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => ↑(aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
R✝ : Type u_1
inst✝ : CommRing R✝
x✝ y✝ : 𝕎 R✝
⊢ (h (f x✝) (g y✝)).coeff = fun n =>
    peval
      ((fun n => ↑(bind₁ (uncurry ![fun k => ↑(rename (Prod.mk 0)) (φ k), fun k => ↑(rename (Prod.mk 1)) (ψ k)])) (χ n))
        n)
      ![x✝.coeff, y✝.coeff]

tactic: simp only [peval, aeval_bind₁, Function.comp, hh, hf, hg, uncurry]
state_before: case mk'.intro.mk'.intro.mk'.intro.h
p : ℕ
R S : Type u
σ : Type ?u.544924
idx : Type ?u.544927
inst✝² : CommRing R
inst✝¹ : CommRing S
h : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => ↑(aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => ↑(aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
R✝ : Type u_1
inst✝ : CommRing R✝
x✝ y✝ : 𝕎 R✝
n : ℕ
⊢ coeff (h (f x✝) (g y✝)) n =
    peval
      ((fun n => ↑(bind₁ (uncurry ![fun k => ↑(rename (Prod.mk 0)) (φ k), fun k => ↑(rename (Prod.mk 1)) (ψ k)])) (χ n))
        n)
      ![x✝.coeff, y✝.coeff]

tactic: apply eval₂Hom_congr rfl _ rfl
state_before: case mk'.intro.mk'.intro.mk'.intro.h
p : ℕ
R S : Type u
σ : Type ?u.544924
idx : Type ?u.544927
inst✝² : CommRing R
inst✝¹ : CommRing S
h : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => ↑(aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => ↑(aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
R✝ : Type u_1
inst✝ : CommRing R✝
x✝ y✝ : 𝕎 R✝
n : ℕ
⊢ ↑(aeval fun a => Matrix.vecCons (fun n => ↑(aeval x✝.coeff) (φ n)) ![fun n => ↑(aeval y✝.coeff) (ψ n)] a.fst a.snd)
      (χ n) =
    ↑(aeval fun i =>
          ↑(aeval fun a => Matrix.vecCons x✝.coeff ![y✝.coeff] a.fst a.snd)
            (Matrix.vecCons (fun k => ↑(rename (Prod.mk 0)) (φ k)) ![fun k => ↑(rename (Prod.mk 1)) (ψ k)] i.fst i.snd))
      (χ n)

tactic: ext ⟨i, n⟩
state_before: p : ℕ
R S : Type u
σ : Type ?u.544924
idx : Type ?u.544927
inst✝² : CommRing R
inst✝¹ : CommRing S
h : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => ↑(aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => ↑(aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
R✝ : Type u_1
inst✝ : CommRing R✝
x✝ y✝ : 𝕎 R✝
n : ℕ
⊢ (fun a => Matrix.vecCons (fun n => ↑(aeval x✝.coeff) (φ n)) ![fun n => ↑(aeval y✝.coeff) (ψ n)] a.fst a.snd) =
    fun i =>
    ↑(aeval fun a => Matrix.vecCons x✝.coeff ![y✝.coeff] a.fst a.snd)
      (Matrix.vecCons (fun k => ↑(rename (Prod.mk 0)) (φ k)) ![fun k => ↑(rename (Prod.mk 1)) (ψ k)] i.fst i.snd)

tactic: fin_cases i <;>
  simp only [aeval_eq_eval₂Hom, eval₂Hom_rename, Function.comp, Matrix.cons_val_zero,
    Matrix.head_cons, Matrix.cons_val_one]
  <;>
  open Matrix in
  simp only [algebraMap_int_eq, coe_eval₂Hom, Fin.mk_zero, Fin.mk_one, cons_val', empty_val',
    cons_val_fin_one, cons_val_zero, cons_val_one, eval₂Hom_rename, Function.comp, head_fin_const]
state_before: case h.mk
p : ℕ
R S : Type u
σ : Type ?u.544924
idx : Type ?u.544927
inst✝² : CommRing R
inst✝¹ : CommRing S
h : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => ↑(aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => ↑(aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
R✝ : Type u_1
inst✝ : CommRing R✝
x✝ y✝ : 𝕎 R✝
n✝ : ℕ
i : Fin 2
n : ℕ
⊢ Matrix.vecCons (fun n => ↑(aeval x✝.coeff) (φ n)) ![fun n => ↑(aeval y✝.coeff) (ψ n)] (i, n).fst (i, n).snd =
    ↑(aeval fun a => Matrix.vecCons x✝.coeff ![y✝.coeff] a.fst a.snd)
      (Matrix.vecCons (fun k => ↑(rename (Prod.mk 0)) (φ k)) ![fun k => ↑(rename (Prod.mk 1)) (ψ k)] (i, n).fst
        (i, n).snd)

tactic: simp only [algebraMap_int_eq, coe_eval₂Hom, Fin.mk_zero, Fin.mk_one, cons_val', empty_val',
  cons_val_fin_one, cons_val_zero, cons_val_one, eval₂Hom_rename, Function.comp, head_fin_const]
state_before: case h.mk.tail.head
p : ℕ
R S : Type u
σ : Type ?u.544924
idx : Type ?u.544927
inst✝² : CommRing R
inst✝¹ : CommRing S
h : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type u_1⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => ↑(aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => ↑(aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type u_1⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
R✝ : Type u_1
inst✝ : CommRing R✝
x✝ y✝ : 𝕎 R✝
n✝ n : ℕ
⊢ Matrix.vecCons (fun n => ↑(eval₂Hom (algebraMap ℤ R✝) x✝.coeff) (φ n))
      ![fun n => ↑(eval₂Hom (algebraMap ℤ R✝) y✝.coeff) (ψ n)] { val := 1, isLt := (_ : (fun a => a < 2) 1) } n =
    ↑(eval₂Hom (algebraMap ℤ R✝) fun a => Matrix.vecCons x✝.coeff ![y✝.coeff] a.fst a.snd)
      (Matrix.vecCons (fun k => ↑(rename (Prod.mk 0)) (φ k)) ![fun k => ↑(rename (Prod.mk 1)) (ψ k)]
        { val := 1, isLt := (_ : (fun a => a < 2) 1) } n)