l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem wittOne_pos_eq_zero (n : ℕ) (hn : 0 < n) : wittOne p n = 0 := by
  apply MvPolynomial.map_injective (Int.castRingHom ℚ) Int.cast_injective
  simp only [wittOne, wittStructureRat, RingHom.map_zero, AlgHom.map_one, RingHom.map_one,
    map_wittStructureInt]
  induction n using Nat.strong_induction_on with | h n IH => ?_
  rw [xInTermsOfW_eq]
  simp only [AlgHom.map_mul, AlgHom.map_sub, AlgHom.map_sum, AlgHom.map_pow, bind₁_X_right,
    bind₁_C_right]
  rw [sub_mul, one_mul]
  rw [Finset.sum_eq_single 0]
  · simp only [invOf_eq_inv, one_mul, inv_pow, tsub_zero, RingHom.map_one, pow_zero]
    simp only [one_pow, one_mul, xInTermsOfW_zero, sub_self, bind₁_X_right]
  · intro i hin hi0
    

Proof state:
case a.h.h₀
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
n : ℕ
IH : ∀ m < n, 0 < m → (bind₁ fun k => 1) (xInTermsOfW p ℚ m) = 0
hn : 0 < n
i : ℕ
hin : i ∈ Finset.range n
hi0 : i ≠ 0
⊢ C (↑p ^ i) * (bind₁ fun k => 1) (xInTermsOfW p ℚ i) ^ p ^ (n - i) = 0

Next tactic:
rw [Finset.mem_range] at hin
@[simp]
theorem wittOne_pos_eq_zero (n : ℕ) (hn : 0 < n) : wittOne p n = 0 := by
  apply MvPolynomial.map_injective (Int.castRingHom ℚ) Int.cast_injective
  simp only [wittOne, wittStructureRat, RingHom.map_zero, AlgHom.map_one, RingHom.map_one,
    map_wittStructureInt]
  induction n using Nat.strong_induction_on with | h n IH => ?_
  rw [xInTermsOfW_eq]
  simp only [AlgHom.map_mul, AlgHom.map_sub, AlgHom.map_sum, AlgHom.map_pow, bind₁_X_right,
    bind₁_C_right]
  rw [sub_mul, one_mul]
  rw [Finset.sum_eq_single 0]
  · simp only [invOf_eq_inv, one_mul, inv_pow, tsub_zero, RingHom.map_one, pow_zero]
    simp only [one_pow, one_mul, xInTermsOfW_zero, sub_self, bind₁_X_right]
  · intro i hin hi0
    rw [Finset.mem_range] at hin
    

Proof state:
case a.h.h₀
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
n : ℕ
IH : ∀ m < n, 0 < m → (bind₁ fun k => 1) (xInTermsOfW p ℚ m) = 0
hn : 0 < n
i : ℕ
hin : i < n
hi0 : i ≠ 0
⊢ C (↑p ^ i) * (bind₁ fun k => 1) (xInTermsOfW p ℚ i) ^ p ^ (n - i) = 0

Next tactic:
rw [IH _ hin (Nat.pos_of_ne_zero hi0), zero_pow (pow_pos hp.1.pos _), mul_zero]
@[simp]
theorem wittOne_pos_eq_zero (n : ℕ) (hn : 0 < n) : wittOne p n = 0 := by
  apply MvPolynomial.map_injective (Int.castRingHom ℚ) Int.cast_injective
  simp only [wittOne, wittStructureRat, RingHom.map_zero, AlgHom.map_one, RingHom.map_one,
    map_wittStructureInt]
  induction n using Nat.strong_induction_on with | h n IH => ?_
  rw [xInTermsOfW_eq]
  simp only [AlgHom.map_mul, AlgHom.map_sub, AlgHom.map_sum, AlgHom.map_pow, bind₁_X_right,
    bind₁_C_right]
  rw [sub_mul, one_mul]
  rw [Finset.sum_eq_single 0]
  · simp only [invOf_eq_inv, one_mul, inv_pow, tsub_zero, RingHom.map_one, pow_zero]
    simp only [one_pow, one_mul, xInTermsOfW_zero, sub_self, bind₁_X_right]
  · intro i hin hi0
    rw [Finset.mem_range] at hin
    rw [IH _ hin (Nat.pos_of_ne_zero hi0), zero_pow (pow_pos hp.1.pos _), mul_zero]
  · 

Proof state:
case a.h.h₁
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
n : ℕ
IH : ∀ m < n, 0 < m → (bind₁ fun k => 1) (xInTermsOfW p ℚ m) = 0
hn : 0 < n
⊢ 0 ∉ Finset.range n → C (↑p ^ 0) * (bind₁ fun k => 1) (xInTermsOfW p ℚ 0) ^ p ^ (n - 0) = 0

Next tactic:
rw [Finset.mem_range]
@[simp]
theorem wittOne_pos_eq_zero (n : ℕ) (hn : 0 < n) : wittOne p n = 0 := by
  apply MvPolynomial.map_injective (Int.castRingHom ℚ) Int.cast_injective
  simp only [wittOne, wittStructureRat, RingHom.map_zero, AlgHom.map_one, RingHom.map_one,
    map_wittStructureInt]
  induction n using Nat.strong_induction_on with | h n IH => ?_
  rw [xInTermsOfW_eq]
  simp only [AlgHom.map_mul, AlgHom.map_sub, AlgHom.map_sum, AlgHom.map_pow, bind₁_X_right,
    bind₁_C_right]
  rw [sub_mul, one_mul]
  rw [Finset.sum_eq_single 0]
  · simp only [invOf_eq_inv, one_mul, inv_pow, tsub_zero, RingHom.map_one, pow_zero]
    simp only [one_pow, one_mul, xInTermsOfW_zero, sub_self, bind₁_X_right]
  · intro i hin hi0
    rw [Finset.mem_range] at hin
    rw [IH _ hin (Nat.pos_of_ne_zero hi0), zero_pow (pow_pos hp.1.pos _), mul_zero]
  · rw [Finset.mem_range]; 

Proof state:
case a.h.h₁
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
n : ℕ
IH : ∀ m < n, 0 < m → (bind₁ fun k => 1) (xInTermsOfW p ℚ m) = 0
hn : 0 < n
⊢ ¬0 < n → C (↑p ^ 0) * (bind₁ fun k => 1) (xInTermsOfW p ℚ 0) ^ p ^ (n - 0) = 0

Next tactic:
intro
@[simp]
theorem wittOne_pos_eq_zero (n : ℕ) (hn : 0 < n) : wittOne p n = 0 := by
  apply MvPolynomial.map_injective (Int.castRingHom ℚ) Int.cast_injective
  simp only [wittOne, wittStructureRat, RingHom.map_zero, AlgHom.map_one, RingHom.map_one,
    map_wittStructureInt]
  induction n using Nat.strong_induction_on with | h n IH => ?_
  rw [xInTermsOfW_eq]
  simp only [AlgHom.map_mul, AlgHom.map_sub, AlgHom.map_sum, AlgHom.map_pow, bind₁_X_right,
    bind₁_C_right]
  rw [sub_mul, one_mul]
  rw [Finset.sum_eq_single 0]
  · simp only [invOf_eq_inv, one_mul, inv_pow, tsub_zero, RingHom.map_one, pow_zero]
    simp only [one_pow, one_mul, xInTermsOfW_zero, sub_self, bind₁_X_right]
  · intro i hin hi0
    rw [Finset.mem_range] at hin
    rw [IH _ hin (Nat.pos_of_ne_zero hi0), zero_pow (pow_pos hp.1.pos _), mul_zero]
  · rw [Finset.mem_range]; intro; 

Proof state:
case a.h.h₁
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
n : ℕ
IH : ∀ m < n, 0 < m → (bind₁ fun k => 1) (xInTermsOfW p ℚ m) = 0
hn : 0 < n
a✝ : ¬0 < n
⊢ C (↑p ^ 0) * (bind₁ fun k => 1) (xInTermsOfW p ℚ 0) ^ p ^ (n - 0) = 0

Next tactic:
contradiction
@[simp]
theorem wittAdd_zero : wittAdd p 0 = X (0, 0) + X (1, 0) := by
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
⊢ wittAdd p 0 = X (0, 0) + X (1, 0)

Next tactic:
apply MvPolynomial.map_injective (Int.castRingHom ℚ) Int.cast_injective
@[simp]
theorem wittAdd_zero : wittAdd p 0 = X (0, 0) + X (1, 0) := by
  apply MvPolynomial.map_injective (Int.castRingHom ℚ) Int.cast_injective
  

Proof state:
case a
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
⊢ (map (Int.castRingHom ℚ)) (wittAdd p 0) = (map (Int.castRingHom ℚ)) (X (0, 0) + X (1, 0))

Next tactic:
simp only [wittAdd, wittStructureRat, AlgHom.map_add, RingHom.map_add, rename_X,
    xInTermsOfW_zero, map_X, wittPolynomial_zero, bind₁_X_right, map_wittStructureInt]
@[simp]
theorem wittSub_zero : wittSub p 0 = X (0, 0) - X (1, 0) := by
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
⊢ wittSub p 0 = X (0, 0) - X (1, 0)

Next tactic:
apply MvPolynomial.map_injective (Int.castRingHom ℚ) Int.cast_injective
@[simp]
theorem wittSub_zero : wittSub p 0 = X (0, 0) - X (1, 0) := by
  apply MvPolynomial.map_injective (Int.castRingHom ℚ) Int.cast_injective
  

Proof state:
case a
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
⊢ (map (Int.castRingHom ℚ)) (wittSub p 0) = (map (Int.castRingHom ℚ)) (X (0, 0) - X (1, 0))

Next tactic:
simp only [wittSub, wittStructureRat, AlgHom.map_sub, RingHom.map_sub, rename_X,
    xInTermsOfW_zero, map_X, wittPolynomial_zero, bind₁_X_right, map_wittStructureInt]
@[simp]
theorem wittMul_zero : wittMul p 0 = X (0, 0) * X (1, 0) := by
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
⊢ wittMul p 0 = X (0, 0) * X (1, 0)

Next tactic:
apply MvPolynomial.map_injective (Int.castRingHom ℚ) Int.cast_injective
@[simp]
theorem wittMul_zero : wittMul p 0 = X (0, 0) * X (1, 0) := by
  apply MvPolynomial.map_injective (Int.castRingHom ℚ) Int.cast_injective
  

Proof state:
case a
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
⊢ (map (Int.castRingHom ℚ)) (wittMul p 0) = (map (Int.castRingHom ℚ)) (X (0, 0) * X (1, 0))

Next tactic:
simp only [wittMul, wittStructureRat, rename_X, xInTermsOfW_zero, map_X, wittPolynomial_zero,
    RingHom.map_mul, bind₁_X_right, AlgHom.map_mul, map_wittStructureInt]
@[simp]
theorem wittNeg_zero : wittNeg p 0 = -X (0, 0) := by
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
⊢ wittNeg p 0 = -X (0, 0)

Next tactic:
apply MvPolynomial.map_injective (Int.castRingHom ℚ) Int.cast_injective
@[simp]
theorem wittNeg_zero : wittNeg p 0 = -X (0, 0) := by
  apply MvPolynomial.map_injective (Int.castRingHom ℚ) Int.cast_injective
  

Proof state:
case a
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
⊢ (map (Int.castRingHom ℚ)) (wittNeg p 0) = (map (Int.castRingHom ℚ)) (-X (0, 0))

Next tactic:
simp only [wittNeg, wittStructureRat, rename_X, xInTermsOfW_zero, map_X, wittPolynomial_zero,
    RingHom.map_neg, AlgHom.map_neg, bind₁_X_right, map_wittStructureInt]
@[simp]
theorem constantCoeff_wittAdd (n : ℕ) : constantCoeff (wittAdd p n) = 0 := by
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
n : ℕ
⊢ constantCoeff (wittAdd p n) = 0

Next tactic:
apply constantCoeff_wittStructureInt p _ _ n
@[simp]
theorem constantCoeff_wittAdd (n : ℕ) : constantCoeff (wittAdd p n) = 0 := by
  apply constantCoeff_wittStructureInt p _ _ n
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
n : ℕ
⊢ constantCoeff (X 0 + X 1) = 0

Next tactic:
simp only [add_zero, RingHom.map_add, constantCoeff_X]
@[simp]
theorem constantCoeff_wittSub (n : ℕ) : constantCoeff (wittSub p n) = 0 := by
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
n : ℕ
⊢ constantCoeff (wittSub p n) = 0

Next tactic:
apply constantCoeff_wittStructureInt p _ _ n
@[simp]
theorem constantCoeff_wittSub (n : ℕ) : constantCoeff (wittSub p n) = 0 := by
  apply constantCoeff_wittStructureInt p _ _ n
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
n : ℕ
⊢ constantCoeff (X 0 - X 1) = 0

Next tactic:
simp only [sub_zero, RingHom.map_sub, constantCoeff_X]
@[simp]
theorem constantCoeff_wittMul (n : ℕ) : constantCoeff (wittMul p n) = 0 := by
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
n : ℕ
⊢ constantCoeff (wittMul p n) = 0

Next tactic:
apply constantCoeff_wittStructureInt p _ _ n
@[simp]
theorem constantCoeff_wittMul (n : ℕ) : constantCoeff (wittMul p n) = 0 := by
  apply constantCoeff_wittStructureInt p _ _ n
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
n : ℕ
⊢ constantCoeff (X 0 * X 1) = 0

Next tactic:
simp only [mul_zero, RingHom.map_mul, constantCoeff_X]
@[simp]
theorem constantCoeff_wittNeg (n : ℕ) : constantCoeff (wittNeg p n) = 0 := by
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
n : ℕ
⊢ constantCoeff (wittNeg p n) = 0

Next tactic:
apply constantCoeff_wittStructureInt p _ _ n
@[simp]
theorem constantCoeff_wittNeg (n : ℕ) : constantCoeff (wittNeg p n) = 0 := by
  apply constantCoeff_wittStructureInt p _ _ n
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
n : ℕ
⊢ constantCoeff (-X 0) = 0

Next tactic:
simp only [neg_zero, RingHom.map_neg, constantCoeff_X]
@[simp]
theorem constantCoeff_wittNSMul (m : ℕ) (n : ℕ) : constantCoeff (wittNSMul p m n) = 0 := by
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
m n : ℕ
⊢ constantCoeff (wittNSMul p m n) = 0

Next tactic:
apply constantCoeff_wittStructureInt p _ _ n
@[simp]
theorem constantCoeff_wittNSMul (m : ℕ) (n : ℕ) : constantCoeff (wittNSMul p m n) = 0 := by
  apply constantCoeff_wittStructureInt p _ _ n
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
m n : ℕ
⊢ constantCoeff (m • X 0) = 0

Next tactic:
simp only [smul_zero, map_nsmul, constantCoeff_X]
@[simp]
theorem constantCoeff_wittZSMul (z : ℤ) (n : ℕ) : constantCoeff (wittZSMul p z n) = 0 := by
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
z : ℤ
n : ℕ
⊢ constantCoeff (wittZSMul p z n) = 0

Next tactic:
apply constantCoeff_wittStructureInt p _ _ n
@[simp]
theorem constantCoeff_wittZSMul (z : ℤ) (n : ℕ) : constantCoeff (wittZSMul p z n) = 0 := by
  apply constantCoeff_wittStructureInt p _ _ n
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
z : ℤ
n : ℕ
⊢ constantCoeff (z • X 0) = 0

Next tactic:
simp only [smul_zero, map_zsmul, constantCoeff_X]
@[simp]
theorem zero_coeff (n : ℕ) : (0 : 𝕎 R).coeff n = 0 :=
  show (aeval _ (wittZero p n) : R) = 0 by 

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
n : ℕ
⊢ (aeval (Function.uncurry fun i => ![].coeff)) (wittZero p n) = 0

Next tactic:
simp only [wittZero_eq_zero, AlgHom.map_zero]
@[simp]
theorem one_coeff_zero : (1 : 𝕎 R).coeff 0 = 1 :=
  show (aeval _ (wittOne p 0) : R) = 1 by 

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
⊢ (aeval (Function.uncurry fun i => ![].coeff)) (wittOne p 0) = 1

Next tactic:
simp only [wittOne_zero_eq_one, AlgHom.map_one]
@[simp]
theorem one_coeff_eq_of_pos (n : ℕ) (hn : 0 < n) : coeff (1 : 𝕎 R) n = 0 :=
  show (aeval _ (wittOne p n) : R) = 0 by 

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
n : ℕ
hn : 0 < n
⊢ (aeval (Function.uncurry fun i => ![].coeff)) (wittOne p n) = 0

Next tactic:
simp only [hn, wittOne_pos_eq_zero, AlgHom.map_zero]
@[simp]
theorem v2_coeff {p' R'} (x y : WittVector p' R') (i : Fin 2) :
    (![x, y] i).coeff = ![x.coeff, y.coeff] i := by 

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
p' : ℕ
R' : Type u_2
x y : WittVector p' R'
i : Fin 2
⊢ (Matrix.vecCons x ![y] i).coeff = Matrix.vecCons x.coeff ![y.coeff] i

Next tactic:
fin_cases i
@[simp]
theorem v2_coeff {p' R'} (x y : WittVector p' R') (i : Fin 2) :
    (![x, y] i).coeff = ![x.coeff, y.coeff] i := by fin_cases i <;> 

Proof state:
case head
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
p' : ℕ
R' : Type u_2
x y : WittVector p' R'
⊢ (Matrix.vecCons x ![y] { val := 0, isLt := (_ : 0 < 2) }).coeff =
    Matrix.vecCons x.coeff ![y.coeff] { val := 0, isLt := (_ : 0 < 2) }

Next tactic:
simp
@[simp]
theorem v2_coeff {p' R'} (x y : WittVector p' R') (i : Fin 2) :
    (![x, y] i).coeff = ![x.coeff, y.coeff] i := by fin_cases i <;> 

Proof state:
case tail.head
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
p' : ℕ
R' : Type u_2
x y : WittVector p' R'
⊢ (Matrix.vecCons x ![y] { val := 1, isLt := (_ : (fun a => a < 2) 1) }).coeff =
    Matrix.vecCons x.coeff ![y.coeff] { val := 1, isLt := (_ : (fun a => a < 2) 1) }

Next tactic:
simp
theorem add_coeff (x y : 𝕎 R) (n : ℕ) : (x + y).coeff n = peval (wittAdd p n) ![x.coeff, y.coeff] :=
  by 

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
x y : 𝕎 R
n : ℕ
⊢ coeff (x + y) n = peval (wittAdd p n) ![x.coeff, y.coeff]

Next tactic:
simp [(· + ·), Add.add, eval, coeff_mk]
theorem sub_coeff (x y : 𝕎 R) (n : ℕ) : (x - y).coeff n = peval (wittSub p n) ![x.coeff, y.coeff] :=
  by 

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
x y : 𝕎 R
n : ℕ
⊢ coeff (x - y) n = peval (wittSub p n) ![x.coeff, y.coeff]

Next tactic:
simp [(· - ·), Sub.sub, eval, coeff_mk]
theorem mul_coeff (x y : 𝕎 R) (n : ℕ) : (x * y).coeff n = peval (wittMul p n) ![x.coeff, y.coeff] :=
  by 

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
x y : 𝕎 R
n : ℕ
⊢ coeff (x * y) n = peval (wittMul p n) ![x.coeff, y.coeff]

Next tactic:
simp [(· * ·), Mul.mul, eval, coeff_mk]
theorem neg_coeff (x : 𝕎 R) (n : ℕ) : (-x).coeff n = peval (wittNeg p n) ![x.coeff] := by
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
x : 𝕎 R
n : ℕ
⊢ coeff (-x) n = peval (wittNeg p n) ![x.coeff]

Next tactic:
simp [Neg.neg, eval, Matrix.cons_fin_one, coeff_mk]
theorem nsmul_coeff (m : ℕ) (x : 𝕎 R) (n : ℕ) :
    (m • x).coeff n = peval (wittNSMul p m n) ![x.coeff] := by
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
m : ℕ
x : 𝕎 R
n : ℕ
⊢ coeff (m • x) n = peval (wittNSMul p m n) ![x.coeff]

Next tactic:
simp [(· • ·), SMul.smul, eval, Matrix.cons_fin_one, coeff_mk]
theorem zsmul_coeff (m : ℤ) (x : 𝕎 R) (n : ℕ) :
    (m • x).coeff n = peval (wittZSMul p m n) ![x.coeff] := by
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
m : ℤ
x : 𝕎 R
n : ℕ
⊢ coeff (m • x) n = peval (wittZSMul p m n) ![x.coeff]

Next tactic:
simp [(· • ·), SMul.smul, eval, Matrix.cons_fin_one, coeff_mk]
theorem pow_coeff (m : ℕ) (x : 𝕎 R) (n : ℕ) : (x ^ m).coeff n = peval (wittPow p m n) ![x.coeff] :=
  by 

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
m : ℕ
x : 𝕎 R
n : ℕ
⊢ coeff (x ^ m) n = peval (wittPow p m n) ![x.coeff]

Next tactic:
simp [(· ^ ·), Pow.pow, eval, Matrix.cons_fin_one, coeff_mk]
theorem add_coeff_zero (x y : 𝕎 R) : (x + y).coeff 0 = x.coeff 0 + y.coeff 0 := by
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
x y : 𝕎 R
⊢ coeff (x + y) 0 = coeff x 0 + coeff y 0

Next tactic:
simp [add_coeff, peval]
theorem mul_coeff_zero (x y : 𝕎 R) : (x * y).coeff 0 = x.coeff 0 * y.coeff 0 := by
  

Proof state:
p : ℕ
R : Type u_1
hp : Fact (Nat.Prime p)
inst✝ : CommRing R
x y : 𝕎 R
⊢ coeff (x * y) 0 = coeff x 0 * coeff y 0

Next tactic:
simp [mul_coeff, peval]
/-- `Groupoid.inv` is involutive. -/
@[simps]
def Groupoid.invEquiv : (X ⟶ Y) ≃ (Y ⟶ X) :=
  ⟨Groupoid.inv, Groupoid.inv, fun f => by 

Proof state:
C : Type u
inst✝ : Groupoid C
X Y : C
f : X ⟶ Y
⊢ inv (inv f) = f

Next tactic:
simp
/-- `Groupoid.inv` is involutive. -/
@[simps]
def Groupoid.invEquiv : (X ⟶ Y) ≃ (Y ⟶ X) :=
  ⟨Groupoid.inv, Groupoid.inv, fun f => by simp, fun f => by 

Proof state:
C : Type u
inst✝ : Groupoid C
X Y : C
f : Y ⟶ X
⊢ inv (inv f) = f

Next tactic:
simp
instance (priority := 100) groupoidHasInvolutiveReverse : Quiver.HasInvolutiveReverse C where
  reverse' f := Groupoid.inv f
  inv' f := by
    

Proof state:
C : Type u
inst✝ : Groupoid C
X Y a✝ b✝ : C
f : a✝ ⟶ b✝
⊢ Quiver.reverse (Quiver.reverse f) = f

Next tactic:
dsimp [Quiver.reverse]
instance (priority := 100) groupoidHasInvolutiveReverse : Quiver.HasInvolutiveReverse C where
  reverse' f := Groupoid.inv f
  inv' f := by
    dsimp [Quiver.reverse]
    

Proof state:
C : Type u
inst✝ : Groupoid C
X Y a✝ b✝ : C
f : a✝ ⟶ b✝
⊢ Groupoid.inv (Groupoid.inv f) = f

Next tactic:
simp
instance functorMapReverse {D : Type*} [Groupoid D] (F : C ⥤ D) : F.toPrefunctor.MapReverse where
  map_reverse' f := by
    

Proof state:
C : Type u
inst✝¹ : Groupoid C
X Y : C
D : Type u_1
inst✝ : Groupoid D
F : C ⥤ D
u✝ v✝ : C
f : u✝ ⟶ v✝
⊢ F.map (Quiver.reverse f) = Quiver.reverse (F.map f)

Next tactic:
simp only [Quiver.reverse, Quiver.HasReverse.reverse', Groupoid.inv_eq_inv,
      Functor.map_inv]
/-- In a groupoid, isomorphisms are equivalent to morphisms. -/
def Groupoid.isoEquivHom : (X ≅ Y) ≃ (X ⟶ Y) where
  toFun := Iso.hom
  invFun f := ⟨f, Groupoid.inv f, (by 

Proof state:
C : Type u
inst✝ : Groupoid C
X Y : C
f : X ⟶ Y
⊢ f ≫ inv f = 𝟙 X

Next tactic:
aesop_cat
/-- In a groupoid, isomorphisms are equivalent to morphisms. -/
def Groupoid.isoEquivHom : (X ≅ Y) ≃ (X ⟶ Y) where
  toFun := Iso.hom
  invFun f := ⟨f, Groupoid.inv f, (by aesop_cat), (by 

Proof state:
C : Type u
inst✝ : Groupoid C
X Y : C
f : X ⟶ Y
⊢ inv f ≫ f = 𝟙 Y

Next tactic:
aesop_cat
instance groupoidPi {I : Type u} {J : I → Type u₂} [∀ i, Groupoid.{v} (J i)] :
    Groupoid.{max u v} (∀ i : I, J i) where
  inv f := fun i : I => Groupoid.inv (f i)
  comp_inv := fun f => by funext i; apply Groupoid.comp_inv
  inv_comp := fun f => by 

Proof state:
I : Type u
J : I → Type u₂
inst✝ : (i : I) → Groupoid (J i)
X✝ Y✝ : (i : I) → J i
f : X✝ ⟶ Y✝
⊢ (fun {X Y} f i => Groupoid.inv (f i)) f ≫ f = 𝟙 Y✝

Next tactic:
funext i
instance groupoidPi {I : Type u} {J : I → Type u₂} [∀ i, Groupoid.{v} (J i)] :
    Groupoid.{max u v} (∀ i : I, J i) where
  inv f := fun i : I => Groupoid.inv (f i)
  comp_inv := fun f => by funext i; apply Groupoid.comp_inv
  inv_comp := fun f => by funext i; 

Proof state:
case h
I : Type u
J : I → Type u₂
inst✝ : (i : I) → Groupoid (J i)
X✝ Y✝ : (i : I) → J i
f : X✝ ⟶ Y✝
i : I
⊢ ((fun {X Y} f i => Groupoid.inv (f i)) f ≫ f) i = 𝟙 Y✝ i

Next tactic:
apply Groupoid.inv_comp
instance groupoidPi {I : Type u} {J : I → Type u₂} [∀ i, Groupoid.{v} (J i)] :
    Groupoid.{max u v} (∀ i : I, J i) where
  inv f := fun i : I => Groupoid.inv (f i)
  comp_inv := fun f => by 

Proof state:
I : Type u
J : I → Type u₂
inst✝ : (i : I) → Groupoid (J i)
X✝ Y✝ : (i : I) → J i
f : X✝ ⟶ Y✝
⊢ f ≫ (fun {X Y} f i => Groupoid.inv (f i)) f = 𝟙 X✝

Next tactic:
funext i
instance groupoidPi {I : Type u} {J : I → Type u₂} [∀ i, Groupoid.{v} (J i)] :
    Groupoid.{max u v} (∀ i : I, J i) where
  inv f := fun i : I => Groupoid.inv (f i)
  comp_inv := fun f => by funext i; 

Proof state:
case h
I : Type u
J : I → Type u₂
inst✝ : (i : I) → Groupoid (J i)
X✝ Y✝ : (i : I) → J i
f : X✝ ⟶ Y✝
i : I
⊢ (f ≫ (fun {X Y} f i => Groupoid.inv (f i)) f) i = 𝟙 X✝ i

Next tactic:
apply Groupoid.comp_inv
instance : Group (N ⋊[φ] G) where
  mul_assoc a b c := SemidirectProduct.ext _ _ (by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
a b c : N ⋊[φ] G
⊢ (a * b * c).left = (a * (b * c)).left

Next tactic:
simp [mul_assoc]
instance : Group (N ⋊[φ] G) where
  mul_assoc a b c := SemidirectProduct.ext _ _ (by simp [mul_assoc]) (by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
a b c : N ⋊[φ] G
⊢ (a * b * c).right = (a * (b * c)).right

Next tactic:
simp [mul_assoc]
instance : Group (N ⋊[φ] G) where
  mul_assoc a b c := SemidirectProduct.ext _ _ (by simp [mul_assoc]) (by simp [mul_assoc])
  one_mul a := SemidirectProduct.ext _ _ (by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
a : N ⋊[φ] G
⊢ (1 * a).left = a.left

Next tactic:
simp
instance : Group (N ⋊[φ] G) where
  mul_assoc a b c := SemidirectProduct.ext _ _ (by simp [mul_assoc]) (by simp [mul_assoc])
  one_mul a := SemidirectProduct.ext _ _ (by simp) (one_mul a.2)
  mul_one a := SemidirectProduct.ext _ _ (by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
a : N ⋊[φ] G
⊢ (a * 1).left = a.left

Next tactic:
simp
instance : Group (N ⋊[φ] G) where
  mul_assoc a b c := SemidirectProduct.ext _ _ (by simp [mul_assoc]) (by simp [mul_assoc])
  one_mul a := SemidirectProduct.ext _ _ (by simp) (one_mul a.2)
  mul_one a := SemidirectProduct.ext _ _ (by simp) (mul_one _)
  mul_left_inv a := SemidirectProduct.ext _ _ (by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
a : N ⋊[φ] G
⊢ (a⁻¹ * a).left = 1.left

Next tactic:
simp
instance : Group (N ⋊[φ] G) where
  mul_assoc a b c := SemidirectProduct.ext _ _ (by simp [mul_assoc]) (by simp [mul_assoc])
  one_mul a := SemidirectProduct.ext _ _ (by simp) (one_mul a.2)
  mul_one a := SemidirectProduct.ext _ _ (by simp) (mul_one _)
  mul_left_inv a := SemidirectProduct.ext _ _ (by simp) (by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
a : N ⋊[φ] G
⊢ (a⁻¹ * a).right = 1.right

Next tactic:
simp
/-- The canonical map `N →* N ⋊[φ] G` sending `n` to `⟨n, 1⟩` -/
def inl : N →* N ⋊[φ] G where
  toFun n := ⟨n, 1⟩
  map_one' := rfl
  map_mul' := by 

Proof state:
N : Type u_1
G : Type u_2
H : Type u_3
inst✝² : Group N
inst✝¹ : Group G
inst✝ : Group H
φ : G →* MulAut N
⊢ ∀ (x y : N),
    OneHom.toFun
        { toFun := fun n => { left := n, right := 1 },
          map_one' := (_ : (fun n => { left := n, right := 1 }) 1 = (fun n => { left := n, right := 1 }) 1) }
        (x * y) =
      OneHom.toFun
          { toFun := fun n => { left := n, right := 1 },
            map_one' := (_ : (fun n => { left := n, right := 1 }) 1 = (fun n => { left := n, right := 1 }) 1) }
          x *
        OneHom.toFun
          { toFun := fun n => { left := n, right := 1 },
            map_one' := (_ : (fun n => { left := n, right := 1 }) 1 = (fun n => { left := n, right := 1 }) 1) }
          y

Next tactic:
intros