l3lab/ntp-mathlib huggingface dataset:
/-- The composition of polynomial functions is polynomial. -/
-- Porting note: made this an instance
instance IsPoly₂.comp {h f g} [hh : IsPoly₂ p h] [hf : IsPoly p f] [hg : IsPoly p g] :
    IsPoly₂ p fun R _Rcr x y => h (f x) (g y) := by
  obtain ⟨φ, hf⟩ := hf
  obtain ⟨ψ, hg⟩ := hg
  obtain ⟨χ, hh⟩ := hh
  refine' ⟨⟨fun n ↦ bind₁ (uncurry <|
    ![fun k ↦ rename (Prod.mk (0 : Fin 2)) (φ k),
      fun k ↦ rename (Prod.mk (1 : Fin 2)) (ψ k)]) (χ n), _⟩⟩
  intros
  funext n
  

Proof state:
case mk'.intro.mk'.intro.mk'.intro.h
p : ℕ
R S : Type u
σ : Type u_1
idx : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
h : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => (aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => (aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
R✝ : Type ?u.296313
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]

Next tactic:
simp (config := { unfoldPartialApp := true }) only [peval, aeval_bind₁, Function.comp, hh, hf, hg,
    uncurry]
/-- The composition of polynomial functions is polynomial. -/
-- Porting note: made this an instance
instance IsPoly₂.comp {h f g} [hh : IsPoly₂ p h] [hf : IsPoly p f] [hg : IsPoly p g] :
    IsPoly₂ p fun R _Rcr x y => h (f x) (g y) := by
  obtain ⟨φ, hf⟩ := hf
  obtain ⟨ψ, hg⟩ := hg
  obtain ⟨χ, hh⟩ := hh
  refine' ⟨⟨fun n ↦ bind₁ (uncurry <|
    ![fun k ↦ rename (Prod.mk (0 : Fin 2)) (φ k),
      fun k ↦ rename (Prod.mk (1 : Fin 2)) (ψ k)]) (χ n), _⟩⟩
  intros
  funext n
  simp (config := { unfoldPartialApp := true }) only [peval, aeval_bind₁, Function.comp, hh, hf, hg,
    uncurry]
  

Proof state:
case mk'.intro.mk'.intro.mk'.intro.h
p : ℕ
R S : Type u
σ : Type u_1
idx : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
h : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => (aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => (aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
R✝ : Type ?u.296313
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.1 a.2) (χ n) =
    (aeval fun i =>
        (aeval fun a => Matrix.vecCons x✝.coeff ![y✝.coeff] a.1 a.2)
          (Matrix.vecCons (fun k => (rename (Prod.mk 0)) (φ k)) ![fun k => (rename (Prod.mk 1)) (ψ k)] i.1 i.2))
      (χ n)

Next tactic:
apply eval₂Hom_congr rfl _ rfl
/-- The composition of polynomial functions is polynomial. -/
-- Porting note: made this an instance
instance IsPoly₂.comp {h f g} [hh : IsPoly₂ p h] [hf : IsPoly p f] [hg : IsPoly p g] :
    IsPoly₂ p fun R _Rcr x y => h (f x) (g y) := by
  obtain ⟨φ, hf⟩ := hf
  obtain ⟨ψ, hg⟩ := hg
  obtain ⟨χ, hh⟩ := hh
  refine' ⟨⟨fun n ↦ bind₁ (uncurry <|
    ![fun k ↦ rename (Prod.mk (0 : Fin 2)) (φ k),
      fun k ↦ rename (Prod.mk (1 : Fin 2)) (ψ k)]) (χ n), _⟩⟩
  intros
  funext n
  simp (config := { unfoldPartialApp := true }) only [peval, aeval_bind₁, Function.comp, hh, hf, hg,
    uncurry]
  apply eval₂Hom_congr rfl _ rfl
  

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

Next tactic:
ext ⟨i, n⟩
/-- The composition of polynomial functions is polynomial. -/
-- Porting note: made this an instance
instance IsPoly₂.comp {h f g} [hh : IsPoly₂ p h] [hf : IsPoly p f] [hg : IsPoly p g] :
    IsPoly₂ p fun R _Rcr x y => h (f x) (g y) := by
  obtain ⟨φ, hf⟩ := hf
  obtain ⟨ψ, hg⟩ := hg
  obtain ⟨χ, hh⟩ := hh
  refine' ⟨⟨fun n ↦ bind₁ (uncurry <|
    ![fun k ↦ rename (Prod.mk (0 : Fin 2)) (φ k),
      fun k ↦ rename (Prod.mk (1 : Fin 2)) (ψ k)]) (χ n), _⟩⟩
  intros
  funext n
  simp (config := { unfoldPartialApp := true }) only [peval, aeval_bind₁, Function.comp, hh, hf, hg,
    uncurry]
  apply eval₂Hom_congr rfl _ rfl
  ext ⟨i, n⟩
  

Proof state:
case h.mk
p : ℕ
R S : Type u
σ : Type u_1
idx : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
h : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => (aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => (aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
R✝ : Type ?u.296313
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).1 (i, n).2 =
    (aeval fun a => Matrix.vecCons x✝.coeff ![y✝.coeff] a.1 a.2)
      (Matrix.vecCons (fun k => (rename (Prod.mk 0)) (φ k)) ![fun k => (rename (Prod.mk 1)) (ψ k)] (i, n).1 (i, n).2)

Next tactic:
fin_cases i
/-- The composition of polynomial functions is polynomial. -/
-- Porting note: made this an instance
instance IsPoly₂.comp {h f g} [hh : IsPoly₂ p h] [hf : IsPoly p f] [hg : IsPoly p g] :
    IsPoly₂ p fun R _Rcr x y => h (f x) (g y) := by
  obtain ⟨φ, hf⟩ := hf
  obtain ⟨ψ, hg⟩ := hg
  obtain ⟨χ, hh⟩ := hh
  refine' ⟨⟨fun n ↦ bind₁ (uncurry <|
    ![fun k ↦ rename (Prod.mk (0 : Fin 2)) (φ k),
      fun k ↦ rename (Prod.mk (1 : Fin 2)) (ψ k)]) (χ n), _⟩⟩
  intros
  funext n
  simp (config := { unfoldPartialApp := true }) only [peval, aeval_bind₁, Function.comp, hh, hf, hg,
    uncurry]
  apply eval₂Hom_congr rfl _ rfl
  ext ⟨i, n⟩
  fin_cases i <;>
    

Proof state:
case h.mk.head
p : ℕ
R S : Type u
σ : Type u_1
idx : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
h : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => (aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => (aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
R✝ : Type ?u.296313
inst✝ : CommRing R✝
x✝ y✝ : 𝕎 R✝
n✝ n : ℕ
⊢ Matrix.vecCons (fun n => (aeval x✝.coeff) (φ n)) ![fun n => (aeval y✝.coeff) (ψ n)]
      ({ val := 0, isLt := (_ : 0 < 2) }, n).1 ({ val := 0, isLt := (_ : 0 < 2) }, n).2 =
    (aeval fun a => Matrix.vecCons x✝.coeff ![y✝.coeff] a.1 a.2)
      (Matrix.vecCons (fun k => (rename (Prod.mk 0)) (φ k)) ![fun k => (rename (Prod.mk 1)) (ψ k)]
        ({ val := 0, isLt := (_ : 0 < 2) }, n).1 ({ val := 0, isLt := (_ : 0 < 2) }, n).2)

Next tactic:
simp only [aeval_eq_eval₂Hom, eval₂Hom_rename, Function.comp, Matrix.cons_val_zero,
      Matrix.head_cons, Matrix.cons_val_one]
/-- The composition of polynomial functions is polynomial. -/
-- Porting note: made this an instance
instance IsPoly₂.comp {h f g} [hh : IsPoly₂ p h] [hf : IsPoly p f] [hg : IsPoly p g] :
    IsPoly₂ p fun R _Rcr x y => h (f x) (g y) := by
  obtain ⟨φ, hf⟩ := hf
  obtain ⟨ψ, hg⟩ := hg
  obtain ⟨χ, hh⟩ := hh
  refine' ⟨⟨fun n ↦ bind₁ (uncurry <|
    ![fun k ↦ rename (Prod.mk (0 : Fin 2)) (φ k),
      fun k ↦ rename (Prod.mk (1 : Fin 2)) (ψ k)]) (χ n), _⟩⟩
  intros
  funext n
  simp (config := { unfoldPartialApp := true }) only [peval, aeval_bind₁, Function.comp, hh, hf, hg,
    uncurry]
  apply eval₂Hom_congr rfl _ rfl
  ext ⟨i, n⟩
  fin_cases i <;>
    

Proof state:
case h.mk.tail.head
p : ℕ
R S : Type u
σ : Type u_1
idx : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
h : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => (aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => (aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
R✝ : Type ?u.296313
inst✝ : CommRing R✝
x✝ y✝ : 𝕎 R✝
n✝ n : ℕ
⊢ Matrix.vecCons (fun n => (aeval x✝.coeff) (φ n)) ![fun n => (aeval y✝.coeff) (ψ n)]
      ({ val := 1, isLt := (_ : (fun a => a < 2) 1) }, n).1 ({ val := 1, isLt := (_ : (fun a => a < 2) 1) }, n).2 =
    (aeval fun a => Matrix.vecCons x✝.coeff ![y✝.coeff] a.1 a.2)
      (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).1 ({ val := 1, isLt := (_ : (fun a => a < 2) 1) }, n).2)

Next tactic:
simp only [aeval_eq_eval₂Hom, eval₂Hom_rename, Function.comp, Matrix.cons_val_zero,
      Matrix.head_cons, Matrix.cons_val_one]
/-- The composition of polynomial functions is polynomial. -/
-- Porting note: made this an instance
instance IsPoly₂.comp {h f g} [hh : IsPoly₂ p h] [hf : IsPoly p f] [hg : IsPoly p g] :
    IsPoly₂ p fun R _Rcr x y => h (f x) (g y) := by
  obtain ⟨φ, hf⟩ := hf
  obtain ⟨ψ, hg⟩ := hg
  obtain ⟨χ, hh⟩ := hh
  refine' ⟨⟨fun n ↦ bind₁ (uncurry <|
    ![fun k ↦ rename (Prod.mk (0 : Fin 2)) (φ k),
      fun k ↦ rename (Prod.mk (1 : Fin 2)) (ψ k)]) (χ n), _⟩⟩
  intros
  funext n
  simp (config := { unfoldPartialApp := true }) only [peval, aeval_bind₁, Function.comp, hh, hf, hg,
    uncurry]
  apply eval₂Hom_congr rfl _ rfl
  ext ⟨i, n⟩
  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]
    -- porting note: added the rest of the proof.
    <;>
    

Proof state:
case h.mk.head
p : ℕ
R S : Type u
σ : Type u_1
idx : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
h : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => (aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => (aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
R✝ : Type ?u.296313
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 := 0, isLt := (_ : 0 < 2) } n =
    (eval₂Hom (algebraMap ℤ R✝) fun a => Matrix.vecCons x✝.coeff ![y✝.coeff] a.1 a.2)
      (Matrix.vecCons (fun k => (rename (Prod.mk 0)) (φ k)) ![fun k => (rename (Prod.mk 1)) (ψ k)]
        { val := 0, isLt := (_ : 0 < 2) } n)

Next tactic:
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]
/-- The composition of polynomial functions is polynomial. -/
-- Porting note: made this an instance
instance IsPoly₂.comp {h f g} [hh : IsPoly₂ p h] [hf : IsPoly p f] [hg : IsPoly p g] :
    IsPoly₂ p fun R _Rcr x y => h (f x) (g y) := by
  obtain ⟨φ, hf⟩ := hf
  obtain ⟨ψ, hg⟩ := hg
  obtain ⟨χ, hh⟩ := hh
  refine' ⟨⟨fun n ↦ bind₁ (uncurry <|
    ![fun k ↦ rename (Prod.mk (0 : Fin 2)) (φ k),
      fun k ↦ rename (Prod.mk (1 : Fin 2)) (ψ k)]) (χ n), _⟩⟩
  intros
  funext n
  simp (config := { unfoldPartialApp := true }) only [peval, aeval_bind₁, Function.comp, hh, hf, hg,
    uncurry]
  apply eval₂Hom_congr rfl _ rfl
  ext ⟨i, n⟩
  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]
    -- porting note: added the rest of the proof.
    <;>
    open Matrix in
    

Proof state:
case h.mk.head
p : ℕ
R S : Type u
σ : Type u_1
idx : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
h : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => (aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => (aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
R✝ : Type ?u.296313
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 := 0, isLt := (_ : 0 < 2) } n =
    (eval₂Hom (algebraMap ℤ R✝) fun a => Matrix.vecCons x✝.coeff ![y✝.coeff] a.1 a.2)
      (Matrix.vecCons (fun k => (rename (Prod.mk 0)) (φ k)) ![fun k => (rename (Prod.mk 1)) (ψ k)]
        { val := 0, isLt := (_ : 0 < 2) } n)

Next 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]
/-- The composition of polynomial functions is polynomial. -/
-- Porting note: made this an instance
instance IsPoly₂.comp {h f g} [hh : IsPoly₂ p h] [hf : IsPoly p f] [hg : IsPoly p g] :
    IsPoly₂ p fun R _Rcr x y => h (f x) (g y) := by
  obtain ⟨φ, hf⟩ := hf
  obtain ⟨ψ, hg⟩ := hg
  obtain ⟨χ, hh⟩ := hh
  refine' ⟨⟨fun n ↦ bind₁ (uncurry <|
    ![fun k ↦ rename (Prod.mk (0 : Fin 2)) (φ k),
      fun k ↦ rename (Prod.mk (1 : Fin 2)) (ψ k)]) (χ n), _⟩⟩
  intros
  funext n
  simp (config := { unfoldPartialApp := true }) only [peval, aeval_bind₁, Function.comp, hh, hf, hg,
    uncurry]
  apply eval₂Hom_congr rfl _ rfl
  ext ⟨i, n⟩
  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]
    -- porting note: added the rest of the proof.
    <;>
    

Proof state:
case h.mk.tail.head
p : ℕ
R S : Type u
σ : Type u_1
idx : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
h : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => (aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => (aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
R✝ : Type ?u.296313
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.1 a.2)
      (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)

Next tactic:
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]
/-- The composition of polynomial functions is polynomial. -/
-- Porting note: made this an instance
instance IsPoly₂.comp {h f g} [hh : IsPoly₂ p h] [hf : IsPoly p f] [hg : IsPoly p g] :
    IsPoly₂ p fun R _Rcr x y => h (f x) (g y) := by
  obtain ⟨φ, hf⟩ := hf
  obtain ⟨ψ, hg⟩ := hg
  obtain ⟨χ, hh⟩ := hh
  refine' ⟨⟨fun n ↦ bind₁ (uncurry <|
    ![fun k ↦ rename (Prod.mk (0 : Fin 2)) (φ k),
      fun k ↦ rename (Prod.mk (1 : Fin 2)) (ψ k)]) (χ n), _⟩⟩
  intros
  funext n
  simp (config := { unfoldPartialApp := true }) only [peval, aeval_bind₁, Function.comp, hh, hf, hg,
    uncurry]
  apply eval₂Hom_congr rfl _ rfl
  ext ⟨i, n⟩
  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]
    -- porting note: added the rest of the proof.
    <;>
    open Matrix in
    

Proof state:
case h.mk.tail.head
p : ℕ
R S : Type u
σ : Type u_1
idx : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
h : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
f g : ⦃R : Type ?u.296313⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial ℕ ℤ
hf : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (f x).coeff = fun n => (aeval x.coeff) (φ n)
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => (aeval x.coeff) (ψ n)
χ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hh : ∀ ⦃R : Type ?u.296313⦄ [inst : CommRing R] (x y : 𝕎 R), (h x y).coeff = fun n => peval (χ n) ![x.coeff, y.coeff]
R✝ : Type ?u.296313
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.1 a.2)
      (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)

Next 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]
/-- The composition of a polynomial function with a binary polynomial function is polynomial. -/
-- Porting note: made this an instance
instance IsPoly.comp₂ {g f} [hg : IsPoly p g] [hf : IsPoly₂ p f] :
    IsPoly₂ p fun R _Rcr x y => g (f x y) := by
  

Proof state:
p : ℕ
R S : Type u
σ : Type u_1
idx : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
g : ⦃R : Type ?u.356423⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
f : ⦃R : Type ?u.356423⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
hg : IsPoly p g
hf : IsPoly₂ p f
⊢ IsPoly₂ p fun R _Rcr x y => g (f x y)

Next tactic:
obtain ⟨φ, hf⟩ := hf
/-- The composition of a polynomial function with a binary polynomial function is polynomial. -/
-- Porting note: made this an instance
instance IsPoly.comp₂ {g f} [hg : IsPoly p g] [hf : IsPoly₂ p f] :
    IsPoly₂ p fun R _Rcr x y => g (f x y) := by
  obtain ⟨φ, hf⟩ := hf
  

Proof state:
case mk'.intro
p : ℕ
R S : Type u
σ : Type u_1
idx : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
g : ⦃R : Type ?u.356423⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
f : ⦃R : Type ?u.356423⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
hg : IsPoly p g
φ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hf : ∀ ⦃R : Type ?u.356423⦄ [inst : CommRing R] (x y : 𝕎 R), (f x y).coeff = fun n => peval (φ n) ![x.coeff, y.coeff]
⊢ IsPoly₂ p fun R _Rcr x y => g (f x y)

Next tactic:
obtain ⟨ψ, hg⟩ := hg
/-- The composition of a polynomial function with a binary polynomial function is polynomial. -/
-- Porting note: made this an instance
instance IsPoly.comp₂ {g f} [hg : IsPoly p g] [hf : IsPoly₂ p f] :
    IsPoly₂ p fun R _Rcr x y => g (f x y) := by
  obtain ⟨φ, hf⟩ := hf
  obtain ⟨ψ, hg⟩ := hg
  

Proof state:
case mk'.intro.mk'.intro
p : ℕ
R S : Type u
σ : Type u_1
idx : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
g : ⦃R : Type ?u.356423⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
f : ⦃R : Type ?u.356423⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hf : ∀ ⦃R : Type ?u.356423⦄ [inst : CommRing R] (x y : 𝕎 R), (f x y).coeff = fun n => peval (φ n) ![x.coeff, y.coeff]
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type ?u.356423⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => (aeval x.coeff) (ψ n)
⊢ IsPoly₂ p fun R _Rcr x y => g (f x y)

Next tactic:
use fun n => bind₁ φ (ψ n)
/-- The composition of a polynomial function with a binary polynomial function is polynomial. -/
-- Porting note: made this an instance
instance IsPoly.comp₂ {g f} [hg : IsPoly p g] [hf : IsPoly₂ p f] :
    IsPoly₂ p fun R _Rcr x y => g (f x y) := by
  obtain ⟨φ, hf⟩ := hf
  obtain ⟨ψ, hg⟩ := hg
  use fun n => bind₁ φ (ψ n)
  

Proof state:
case h
p : ℕ
R S : Type u
σ : Type u_1
idx : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
g : ⦃R : Type ?u.356423⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
f : ⦃R : Type ?u.356423⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hf : ∀ ⦃R : Type ?u.356423⦄ [inst : CommRing R] (x y : 𝕎 R), (f x y).coeff = fun n => peval (φ n) ![x.coeff, y.coeff]
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type ?u.356423⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => (aeval x.coeff) (ψ n)
⊢ ∀ ⦃R : Type ?u.356423⦄ [inst : CommRing R] (x y : 𝕎 R),
    (g (f x y)).coeff = fun n => peval ((bind₁ φ) (ψ n)) ![x.coeff, y.coeff]

Next tactic:
intros
/-- The composition of a polynomial function with a binary polynomial function is polynomial. -/
-- Porting note: made this an instance
instance IsPoly.comp₂ {g f} [hg : IsPoly p g] [hf : IsPoly₂ p f] :
    IsPoly₂ p fun R _Rcr x y => g (f x y) := by
  obtain ⟨φ, hf⟩ := hf
  obtain ⟨ψ, hg⟩ := hg
  use fun n => bind₁ φ (ψ n)
  intros
  

Proof state:
case h
p : ℕ
R S : Type u
σ : Type u_1
idx : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
g : ⦃R : Type ?u.356423⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R
f : ⦃R : Type ?u.356423⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
φ : ℕ → MvPolynomial (Fin 2 × ℕ) ℤ
hf : ∀ ⦃R : Type ?u.356423⦄ [inst : CommRing R] (x y : 𝕎 R), (f x y).coeff = fun n => peval (φ n) ![x.coeff, y.coeff]
ψ : ℕ → MvPolynomial ℕ ℤ
hg : ∀ ⦃R : Type ?u.356423⦄ [inst : CommRing R] (x : 𝕎 R), (g x).coeff = fun n => (aeval x.coeff) (ψ n)
R✝ : Type ?u.356423
inst✝ : CommRing R✝
x✝ y✝ : 𝕎 R✝
⊢ (g (f x✝ y✝)).coeff = fun n => peval ((bind₁ φ) (ψ n)) ![x✝.coeff, y✝.coeff]

Next tactic:
simp only [peval, aeval_bind₁, Function.comp, hg, hf]
/-- The diagonal `λ x, f x x` of a polynomial function `f` is polynomial. -/
-- Porting note: made this an instance
instance IsPoly₂.diag {f} [hf : IsPoly₂ p f] : IsPoly p fun R _Rcr x => f x x := by
  

Proof state:
p : ℕ
R S : Type u
σ : Type u_1
idx : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
f : ⦃R : Type ?u.374137⦄ → [inst : CommRing R] → 𝕎 R → 𝕎 R → 𝕎 R
hf : IsPoly₂ p f
⊢ IsPoly p fun R _Rcr x => f x x

Next tactic:
obtain ⟨φ, hf⟩ := hf