[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
⊢ dickson k a 2 = X ^ 2 - ↑C a * (3 - ↑k)
[PROOFSTEP]
simp only [dickson, sq]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
n : ℕ
⊢ dickson k a (n + 2) = X * dickson k a (n + 1) - ↑C a * dickson k a n
[PROOFSTEP]
rw [dickson]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
n : ℕ
h : 2 ≤ n
⊢ dickson k a n = X * dickson k a (n - 1) - ↑C a * dickson k a (n - 2)
[PROOFSTEP]
obtain ⟨n, rfl⟩ := Nat.exists_eq_add_of_le h
[GOAL]
case intro
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
n : ℕ
h : 2 ≤ 2 + n
⊢ dickson k a (2 + n) = X * dickson k a (2 + n - 1) - ↑C a * dickson k a (2 + n - 2)
[PROOFSTEP]
rw [add_comm]
[GOAL]
case intro
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
n : ℕ
h : 2 ≤ 2 + n
⊢ dickson k a (n + 2) = X * dickson k a (n + 2 - 1) - ↑C a * dickson k a (n + 2 - 2)
[PROOFSTEP]
exact dickson_add_two k a n
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
f : R →+* S
⊢ map f (dickson k a 0) = dickson k (↑f a) 0
[PROOFSTEP]
simp_rw [dickson_zero, Polynomial.map_sub, Polynomial.map_nat_cast, Polynomial.map_ofNat]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
f : R →+* S
⊢ map f (dickson k a 1) = dickson k (↑f a) 1
[PROOFSTEP]
simp only [dickson_one, map_X]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
f : R →+* S
n : ℕ
⊢ map f (dickson k a (n + 2)) = dickson k (↑f a) (n + 2)
[PROOFSTEP]
simp only [dickson_add_two, Polynomial.map_sub, Polynomial.map_mul, map_X, map_C]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
f : R →+* S
n : ℕ
⊢ X * map f (dickson k a (n + 1)) - ↑C (↑f a) * map f (dickson k a n) =
    X * dickson k (↑f a) (n + 1) - ↑C (↑f a) * dickson k (↑f a) n
[PROOFSTEP]
rw [map_dickson f n, map_dickson f (n + 1)]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
⊢ dickson 2 0 0 = X ^ 0
[PROOFSTEP]
simp only [dickson_zero, pow_zero]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
⊢ 3 - ↑2 = 1
[PROOFSTEP]
norm_num
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
⊢ dickson 2 0 1 = X ^ 1
[PROOFSTEP]
simp only [dickson_one, pow_one]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
n : ℕ
⊢ dickson 2 0 (n + 2) = X ^ (n + 2)
[PROOFSTEP]
simp only [dickson_add_two, C_0, zero_mul, sub_zero]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
n : ℕ
⊢ X * dickson 2 0 (n + 1) = X ^ (n + 2)
[PROOFSTEP]
rw [dickson_two_zero (n + 1), pow_add X (n + 1) 1, mul_comm, pow_one]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a x y : R
h : x * y = 1
⊢ eval (x + y) (dickson 1 1 0) = x ^ 0 + y ^ 0
[PROOFSTEP]
suffices eval (x + y) 2 = 2 by convert this <;> norm_num
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a x y : R
h : x * y = 1
this : eval (x + y) 2 = 2
⊢ eval (x + y) (dickson 1 1 0) = x ^ 0 + y ^ 0
[PROOFSTEP]
convert this
[GOAL]
case h.e'_2.h.e'_4
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a x y : R
h : x * y = 1
this : eval (x + y) 2 = 2
⊢ dickson 1 1 0 = 2
[PROOFSTEP]
norm_num
[GOAL]
case h.e'_3
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a x y : R
h : x * y = 1
this : eval (x + y) 2 = 2
⊢ x ^ 0 + y ^ 0 = 2
[PROOFSTEP]
norm_num
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a x y : R
h : x * y = 1
⊢ eval (x + y) 2 = 2
[PROOFSTEP]
exact eval_nat_cast
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a x y : R
h : x * y = 1
⊢ eval (x + y) (dickson 1 1 1) = x ^ 1 + y ^ 1
[PROOFSTEP]
simp only [eval_X, dickson_one, pow_one]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a x y : R
h : x * y = 1
n : ℕ
⊢ eval (x + y) (dickson 1 1 (n + 2)) = x ^ (n + 2) + y ^ (n + 2)
[PROOFSTEP]
simp only [eval_sub, eval_mul, dickson_one_one_eval_add_inv x y h _, eval_X, dickson_add_two, C_1, eval_one]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a x y : R
h : x * y = 1
n : ℕ
⊢ (x + y) * (x ^ (n + 1) + y ^ (n + 1)) - 1 * (x ^ n + y ^ n) = x ^ (n + 2) + y ^ (n + 2)
[PROOFSTEP]
conv_lhs => simp only [pow_succ, add_mul, mul_add, h, ← mul_assoc, mul_comm y x, one_mul]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a x y : R
h : x * y = 1
n : ℕ
| (x + y) * (x ^ (n + 1) + y ^ (n + 1)) - 1 * (x ^ n + y ^ n)
[PROOFSTEP]
simp only [pow_succ, add_mul, mul_add, h, ← mul_assoc, mul_comm y x, one_mul]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a x y : R
h : x * y = 1
n : ℕ
| (x + y) * (x ^ (n + 1) + y ^ (n + 1)) - 1 * (x ^ n + y ^ n)
[PROOFSTEP]
simp only [pow_succ, add_mul, mul_add, h, ← mul_assoc, mul_comm y x, one_mul]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a x y : R
h : x * y = 1
n : ℕ
| (x + y) * (x ^ (n + 1) + y ^ (n + 1)) - 1 * (x ^ n + y ^ n)
[PROOFSTEP]
simp only [pow_succ, add_mul, mul_add, h, ← mul_assoc, mul_comm y x, one_mul]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a x y : R
h : x * y = 1
n : ℕ
⊢ x * x * x ^ n + x ^ n + (y ^ n + y * y * y ^ n) - (x ^ n + y ^ n) = x ^ (n + 2) + y ^ (n + 2)
[PROOFSTEP]
ring
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
inst✝ : Invertible 2
⊢ 2 * ↑C ⅟2 = 1
[PROOFSTEP]
rw [two_mul, ← C_add, invOf_two_add_invOf_two, C_1]
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
inst✝ : Invertible 2
⊢ ↑C ⅟2 * 2 = 1
[PROOFSTEP]
rw [mul_comm, two_mul_C_half_eq_one]
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
inst✝ : Invertible 2
⊢ dickson 1 1 0 = 2 * comp (Chebyshev.T R 0) (↑C ⅟2 * X)
[PROOFSTEP]
simp only [Chebyshev.T_zero, mul_one, one_comp, dickson_zero]
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
inst✝ : Invertible 2
⊢ 3 - ↑1 = 2
[PROOFSTEP]
norm_num
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
inst✝ : Invertible 2
⊢ dickson 1 1 1 = 2 * comp (Chebyshev.T R 1) (↑C ⅟2 * X)
[PROOFSTEP]
rw [dickson_one, Chebyshev.T_one, X_comp, ← mul_assoc, two_mul_C_half_eq_one, one_mul]
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
inst✝ : Invertible 2
n : ℕ
⊢ dickson 1 1 (n + 2) = 2 * comp (Chebyshev.T R (n + 2)) (↑C ⅟2 * X)
[PROOFSTEP]
rw [dickson_add_two, C_1, Chebyshev.T_add_two, dickson_one_one_eq_chebyshev_T (n + 1), dickson_one_one_eq_chebyshev_T n,
  sub_comp, mul_comp, mul_comp, X_comp, ofNat_comp]
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
inst✝ : Invertible 2
n : ℕ
⊢ X * (2 * comp (Chebyshev.T R (n + 1)) (↑C ⅟2 * X)) - 1 * (2 * comp (Chebyshev.T R n) (↑C ⅟2 * X)) =
    2 * (↑2 * (↑C ⅟2 * X) * comp (Chebyshev.T R (n + 1)) (↑C ⅟2 * X) - comp (Chebyshev.T R n) (↑C ⅟2 * X))
[PROOFSTEP]
simp_rw [← mul_assoc, Nat.cast_ofNat, two_mul_C_half_eq_one]
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
inst✝ : Invertible 2
n : ℕ
⊢ X * 2 * comp (Chebyshev.T R (n + 1)) (↑C ⅟2 * X) - 1 * 2 * comp (Chebyshev.T R n) (↑C ⅟2 * X) =
    2 * (1 * X * comp (Chebyshev.T R (n + 1)) (↑C ⅟2 * X) - comp (Chebyshev.T R n) (↑C ⅟2 * X))
[PROOFSTEP]
ring
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
inst✝ : Invertible 2
n : ℕ
⊢ Chebyshev.T R n = ↑C ⅟2 * comp (dickson 1 1 n) (2 * X)
[PROOFSTEP]
rw [dickson_one_one_eq_chebyshev_T, mul_comp, ofNat_comp, comp_assoc, mul_comp, C_comp, X_comp]
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
inst✝ : Invertible 2
n : ℕ
⊢ Chebyshev.T R n = ↑C ⅟2 * (↑2 * comp (Chebyshev.T R n) (↑C ⅟2 * (2 * X)))
[PROOFSTEP]
simp_rw [← mul_assoc, Nat.cast_ofNat, C_half_mul_two_eq_one, one_mul, comp_X]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
m n : ℕ
⊢ dickson 1 1 (m * n) = comp (dickson 1 1 m) (dickson 1 1 n)
[PROOFSTEP]
have h : (1 : R) = Int.castRingHom R 1
[GOAL]
case h
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
m n : ℕ
⊢ 1 = ↑(Int.castRingHom R) 1
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
m n : ℕ
h : 1 = ↑(Int.castRingHom R) 1
⊢ dickson 1 1 (m * n) = comp (dickson 1 1 m) (dickson 1 1 n)
[PROOFSTEP]
simp only [eq_intCast, Int.cast_one]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
m n : ℕ
h : 1 = ↑(Int.castRingHom R) 1
⊢ dickson 1 1 (m * n) = comp (dickson 1 1 m) (dickson 1 1 n)
[PROOFSTEP]
rw [h]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
m n : ℕ
h : 1 = ↑(Int.castRingHom R) 1
⊢ dickson 1 (↑(Int.castRingHom R) 1) (m * n) =
    comp (dickson 1 (↑(Int.castRingHom R) 1) m) (dickson 1 (↑(Int.castRingHom R) 1) n)
[PROOFSTEP]
simp only [← map_dickson (Int.castRingHom R), ← map_comp]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
m n : ℕ
h : 1 = ↑(Int.castRingHom R) 1
⊢ map (Int.castRingHom R) (dickson 1 1 (m * n)) = map (Int.castRingHom R) (comp (dickson 1 1 m) (dickson 1 1 n))
[PROOFSTEP]
congr 1
[GOAL]
case e_a
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
m n : ℕ
h : 1 = ↑(Int.castRingHom R) 1
⊢ dickson 1 1 (m * n) = comp (dickson 1 1 m) (dickson 1 1 n)
[PROOFSTEP]
apply map_injective (Int.castRingHom ℚ) Int.cast_injective
[GOAL]
case e_a.a
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
m n : ℕ
h : 1 = ↑(Int.castRingHom R) 1
⊢ map (Int.castRingHom ℚ) (dickson 1 1 (m * n)) = map (Int.castRingHom ℚ) (comp (dickson 1 1 m) (dickson 1 1 n))
[PROOFSTEP]
simp only [map_dickson, map_comp, eq_intCast, Int.cast_one, dickson_one_one_eq_chebyshev_T, Chebyshev.T_mul, two_mul, ←
  add_comp]
[GOAL]
case e_a.a
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
m n : ℕ
h : 1 = ↑(Int.castRingHom R) 1
⊢ comp (comp (Chebyshev.T ℚ m + Chebyshev.T ℚ m) (Chebyshev.T ℚ n)) (↑C ⅟2 * X) =
    comp (comp (Chebyshev.T ℚ m + Chebyshev.T ℚ m) (↑C ⅟2 * X)) (comp (Chebyshev.T ℚ n + Chebyshev.T ℚ n) (↑C ⅟2 * X))
[PROOFSTEP]
simp only [← two_mul, ← comp_assoc]
[GOAL]
case e_a.a
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
m n : ℕ
h : 1 = ↑(Int.castRingHom R) 1
⊢ comp (comp (2 * Chebyshev.T ℚ m) (Chebyshev.T ℚ n)) (↑C ⅟2 * X) =
    comp (comp (comp (2 * Chebyshev.T ℚ m) (↑C ⅟2 * X)) (2 * Chebyshev.T ℚ n)) (↑C ⅟2 * X)
[PROOFSTEP]
apply eval₂_congr rfl rfl
[GOAL]
case e_a.a
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
m n : ℕ
h : 1 = ↑(Int.castRingHom R) 1
⊢ comp (2 * Chebyshev.T ℚ m) (Chebyshev.T ℚ n) = comp (comp (2 * Chebyshev.T ℚ m) (↑C ⅟2 * X)) (2 * Chebyshev.T ℚ n)
[PROOFSTEP]
rw [comp_assoc]
[GOAL]
case e_a.a
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
m n : ℕ
h : 1 = ↑(Int.castRingHom R) 1
⊢ comp (2 * Chebyshev.T ℚ m) (Chebyshev.T ℚ n) = comp (2 * Chebyshev.T ℚ m) (comp (↑C ⅟2 * X) (2 * Chebyshev.T ℚ n))
[PROOFSTEP]
apply eval₂_congr rfl _ rfl
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
m n : ℕ
h : 1 = ↑(Int.castRingHom R) 1
⊢ Chebyshev.T ℚ n = comp (↑C ⅟2 * X) (2 * Chebyshev.T ℚ n)
[PROOFSTEP]
rw [mul_comp, C_comp, X_comp, ← mul_assoc, C_half_mul_two_eq_one, one_mul]
[GOAL]
R : Type u_1
S : Type u_2
inst✝¹ : CommRing R
inst✝ : CommRing S
k : ℕ
a : R
m n : ℕ
⊢ comp (dickson 1 1 m) (dickson 1 1 n) = comp (dickson 1 1 n) (dickson 1 1 m)
[PROOFSTEP]
rw [← dickson_one_one_mul, mul_comm, dickson_one_one_mul]
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
⊢ dickson 1 1 p = X ^ p
[PROOFSTEP]
obtain ⟨K, _, _, H⟩ : ∃ (K : Type) (_ : Field K), ∃ _ : CharP K p, Infinite K :=
  by
  let K := FractionRing (Polynomial (ZMod p))
  let f : ZMod p →+* K := (algebraMap _ (FractionRing _)).comp C
  have : CharP K p := by
    rw [← f.charP_iff_charP]
    infer_instance
  haveI : Infinite K :=
    Infinite.of_injective (algebraMap (Polynomial (ZMod p)) (FractionRing (Polynomial (ZMod p))))
      (IsFractionRing.injective _ _)
  refine' ⟨K, _, _, _⟩ <;> infer_instance
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
⊢ ∃ K x x, Infinite K
[PROOFSTEP]
let K := FractionRing (Polynomial (ZMod p))
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type := FractionRing (ZMod p)[X]
⊢ ∃ K x x, Infinite K
[PROOFSTEP]
let f : ZMod p →+* K := (algebraMap _ (FractionRing _)).comp C
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type := FractionRing (ZMod p)[X]
f : ZMod p →+* K := RingHom.comp (algebraMap (ZMod p)[X] (FractionRing (ZMod p)[X])) C
⊢ ∃ K x x, Infinite K
[PROOFSTEP]
have : CharP K p := by
  rw [← f.charP_iff_charP]
  infer_instance
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type := FractionRing (ZMod p)[X]
f : ZMod p →+* K := RingHom.comp (algebraMap (ZMod p)[X] (FractionRing (ZMod p)[X])) C
⊢ CharP K p
[PROOFSTEP]
rw [← f.charP_iff_charP]
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type := FractionRing (ZMod p)[X]
f : ZMod p →+* K := RingHom.comp (algebraMap (ZMod p)[X] (FractionRing (ZMod p)[X])) C
⊢ CharP (ZMod p) p
[PROOFSTEP]
infer_instance
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type := FractionRing (ZMod p)[X]
f : ZMod p →+* K := RingHom.comp (algebraMap (ZMod p)[X] (FractionRing (ZMod p)[X])) C
this : CharP K p
⊢ ∃ K x x, Infinite K
[PROOFSTEP]
haveI : Infinite K :=
  Infinite.of_injective (algebraMap (Polynomial (ZMod p)) (FractionRing (Polynomial (ZMod p))))
    (IsFractionRing.injective _ _)
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type := FractionRing (ZMod p)[X]
f : ZMod p →+* K := RingHom.comp (algebraMap (ZMod p)[X] (FractionRing (ZMod p)[X])) C
this✝ : CharP K p
this : Infinite K
⊢ ∃ K x x, Infinite K
[PROOFSTEP]
refine' ⟨K, _, _, _⟩
[GOAL]
case refine'_1
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type := FractionRing (ZMod p)[X]
f : ZMod p →+* K := RingHom.comp (algebraMap (ZMod p)[X] (FractionRing (ZMod p)[X])) C
this✝ : CharP K p
this : Infinite K
⊢ Field K
[PROOFSTEP]
infer_instance
[GOAL]
case refine'_2
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type := FractionRing (ZMod p)[X]
f : ZMod p →+* K := RingHom.comp (algebraMap (ZMod p)[X] (FractionRing (ZMod p)[X])) C
this✝ : CharP K p
this : Infinite K
⊢ CharP K p
[PROOFSTEP]
infer_instance
[GOAL]
case refine'_3
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type := FractionRing (ZMod p)[X]
f : ZMod p →+* K := RingHom.comp (algebraMap (ZMod p)[X] (FractionRing (ZMod p)[X])) C
this✝ : CharP K p
this : Infinite K
⊢ Infinite K
[PROOFSTEP]
infer_instance
[GOAL]
case intro.intro.intro
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Infinite K
⊢ dickson 1 1 p = X ^ p
[PROOFSTEP]
apply map_injective (ZMod.castHom (dvd_refl p) K) (RingHom.injective _)
[GOAL]
case intro.intro.intro.a
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Infinite K
⊢ map (ZMod.castHom (_ : p ∣ p) K) (dickson 1 1 p) = map (ZMod.castHom (_ : p ∣ p) K) (X ^ p)
[PROOFSTEP]
rw [map_dickson, Polynomial.map_pow, map_X]
[GOAL]
case intro.intro.intro.a
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Infinite K
⊢ dickson 1 (↑(ZMod.castHom (_ : p ∣ p) K) 1) p = X ^ p
[PROOFSTEP]
apply eq_of_infinite_eval_eq
[GOAL]
case intro.intro.intro.a.h
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Infinite K
⊢ Set.Infinite {x | eval x (dickson 1 (↑(ZMod.castHom (_ : p ∣ p) K) 1) p) = eval x (X ^ p)}
[PROOFSTEP]
apply @Set.Infinite.mono _ {x : K | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
[GOAL]
case intro.intro.intro.a.h.h
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Infinite K
⊢ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0} ⊆ {x | eval x (dickson 1 (↑(ZMod.castHom (_ : p ∣ p) K) 1) p) = eval x (X ^ p)}
[PROOFSTEP]
rintro _ ⟨x, rfl, hx⟩
[GOAL]
case intro.intro.intro.a.h.h.intro.intro
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Infinite K
x : K
hx : x ≠ 0
⊢ x + x⁻¹ ∈ {x | eval x (dickson 1 (↑(ZMod.castHom (_ : p ∣ p) K) 1) p) = eval x (X ^ p)}
[PROOFSTEP]
simp only [eval_X, eval_pow, Set.mem_setOf_eq, @add_pow_char K _ p,
  dickson_one_one_eval_add_inv _ _ (mul_inv_cancel hx), inv_pow, ZMod.castHom_apply, ZMod.cast_one']
  -- Now we need to show that the set of such `x` is infinite.
    -- If the set is finite, then we will show that `K` is also finite.
[GOAL]
case intro.intro.intro.a.h.a
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Infinite K
⊢ Set.Infinite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
[PROOFSTEP]
intro h
[GOAL]
case intro.intro.intro.a.h.a
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Infinite K
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
⊢ False
[PROOFSTEP]
rw [← Set.infinite_univ_iff] at H
[GOAL]
case intro.intro.intro.a.h.a
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
⊢ False
[PROOFSTEP]
apply H
[GOAL]
case intro.intro.intro.a.h.a
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
⊢ Set.Finite Set.univ
[PROOFSTEP]
suffices (Set.univ : Set K) = {x : K | ∃ y : K, x = y + y⁻¹ ∧ y ≠ 0} >>= fun x => {y | x = y + y⁻¹ ∨ y = 0}
  by
  rw [this]
  clear this
  refine'
    h.biUnion fun x _ =>
      _
        -- The following quadratic polynomial has as solutions the `y` for which `x = y + y⁻¹`.
  let φ : K[X] := X ^ 2 - C x * X + 1
  have hφ : φ ≠ 0 := by
    intro H
    have : φ.eval 0 = 0 := by rw [H, eval_zero]
    simpa [eval_X, eval_one, eval_pow, eval_sub, sub_zero, eval_add, eval_mul, mul_zero, sq, zero_add, one_ne_zero]
  classical
  convert (φ.roots ∪ {0}).toFinset.finite_toSet using 1
  ext1 y
  simp only [Multiset.mem_toFinset, Set.mem_setOf_eq, Finset.mem_coe, Multiset.mem_union, mem_roots hφ, IsRoot,
    eval_add, eval_sub, eval_pow, eval_mul, eval_X, eval_C, eval_one, Multiset.mem_singleton]
  by_cases hy : y = 0
  · simp only [hy, eq_self_iff_true, or_true_iff]
  apply or_congr _ Iff.rfl
  rw [← mul_left_inj' hy, eq_comm, ← sub_eq_zero, add_mul, inv_mul_cancel hy]
  apply eq_iff_eq_cancel_right.mpr
  ring
    -- Finally, we prove the claim that our finite union of finite sets covers all of `K`.
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
this :
  Set.univ = do
    let x ← {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
    {y | x = y + y⁻¹ ∨ y = 0}
⊢ Set.Finite Set.univ
[PROOFSTEP]
rw [this]
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
this :
  Set.univ = do
    let x ← {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
    {y | x = y + y⁻¹ ∨ y = 0}
⊢ Set.Finite do
    let x ← {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
    {y | x = y + y⁻¹ ∨ y = 0}
[PROOFSTEP]
clear this
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
⊢ Set.Finite do
    let x ← {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
    {y | x = y + y⁻¹ ∨ y = 0}
[PROOFSTEP]
refine'
  h.biUnion fun x _ =>
    _
      -- The following quadratic polynomial has as solutions the `y` for which `x = y + y⁻¹`.
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
x✝ : x ∈ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
⊢ Set.Finite ((fun x => {y | x = y + y⁻¹ ∨ y = 0}) x)
[PROOFSTEP]
let φ : K[X] := X ^ 2 - C x * X + 1
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
x✝ : x ∈ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
φ : K[X] := X ^ 2 - ↑C x * X + 1
⊢ Set.Finite ((fun x => {y | x = y + y⁻¹ ∨ y = 0}) x)
[PROOFSTEP]
have hφ : φ ≠ 0 := by
  intro H
  have : φ.eval 0 = 0 := by rw [H, eval_zero]
  simpa [eval_X, eval_one, eval_pow, eval_sub, sub_zero, eval_add, eval_mul, mul_zero, sq, zero_add, one_ne_zero]
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
x✝ : x ∈ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
φ : K[X] := X ^ 2 - ↑C x * X + 1
⊢ φ ≠ 0
[PROOFSTEP]
intro H
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H✝ : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
x✝ : x ∈ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
φ : K[X] := X ^ 2 - ↑C x * X + 1
H : φ = 0
⊢ False
[PROOFSTEP]
have : φ.eval 0 = 0 := by rw [H, eval_zero]
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H✝ : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
x✝ : x ∈ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
φ : K[X] := X ^ 2 - ↑C x * X + 1
H : φ = 0
⊢ eval 0 φ = 0
[PROOFSTEP]
rw [H, eval_zero]
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H✝ : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
x✝ : x ∈ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
φ : K[X] := X ^ 2 - ↑C x * X + 1
H : φ = 0
this : eval 0 φ = 0
⊢ False
[PROOFSTEP]
simpa [eval_X, eval_one, eval_pow, eval_sub, sub_zero, eval_add, eval_mul, mul_zero, sq, zero_add, one_ne_zero]
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
x✝ : x ∈ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
φ : K[X] := X ^ 2 - ↑C x * X + 1
hφ : φ ≠ 0
⊢ Set.Finite ((fun x => {y | x = y + y⁻¹ ∨ y = 0}) x)
[PROOFSTEP]
classical
convert (φ.roots ∪ {0}).toFinset.finite_toSet using 1
ext1 y
simp only [Multiset.mem_toFinset, Set.mem_setOf_eq, Finset.mem_coe, Multiset.mem_union, mem_roots hφ, IsRoot, eval_add,
  eval_sub, eval_pow, eval_mul, eval_X, eval_C, eval_one, Multiset.mem_singleton]
by_cases hy : y = 0
· simp only [hy, eq_self_iff_true, or_true_iff]
apply or_congr _ Iff.rfl
rw [← mul_left_inj' hy, eq_comm, ← sub_eq_zero, add_mul, inv_mul_cancel hy]
apply eq_iff_eq_cancel_right.mpr
ring
  -- Finally, we prove the claim that our finite union of finite sets covers all of `K`.
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
x✝ : x ∈ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
φ : K[X] := X ^ 2 - ↑C x * X + 1
hφ : φ ≠ 0
⊢ Set.Finite ((fun x => {y | x = y + y⁻¹ ∨ y = 0}) x)
[PROOFSTEP]
convert (φ.roots ∪ {0}).toFinset.finite_toSet using 1
[GOAL]
case h.e'_2
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
x✝ : x ∈ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
φ : K[X] := X ^ 2 - ↑C x * X + 1
hφ : φ ≠ 0
⊢ (fun x => {y | x = y + y⁻¹ ∨ y = 0}) x = ↑(Multiset.toFinset (roots φ ∪ {0}))
[PROOFSTEP]
ext1 y
[GOAL]
case h.e'_2.h
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
x✝ : x ∈ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
φ : K[X] := X ^ 2 - ↑C x * X + 1
hφ : φ ≠ 0
y : K
⊢ y ∈ (fun x => {y | x = y + y⁻¹ ∨ y = 0}) x ↔ y ∈ ↑(Multiset.toFinset (roots φ ∪ {0}))
[PROOFSTEP]
simp only [Multiset.mem_toFinset, Set.mem_setOf_eq, Finset.mem_coe, Multiset.mem_union, mem_roots hφ, IsRoot, eval_add,
  eval_sub, eval_pow, eval_mul, eval_X, eval_C, eval_one, Multiset.mem_singleton]
[GOAL]
case h.e'_2.h
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
x✝ : x ∈ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
φ : K[X] := X ^ 2 - ↑C x * X + 1
hφ : φ ≠ 0
y : K
⊢ x = y + y⁻¹ ∨ y = 0 ↔ y ^ 2 - x * y + 1 = 0 ∨ y = 0
[PROOFSTEP]
by_cases hy : y = 0
[GOAL]
case pos
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
x✝ : x ∈ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
φ : K[X] := X ^ 2 - ↑C x * X + 1
hφ : φ ≠ 0
y : K
hy : y = 0
⊢ x = y + y⁻¹ ∨ y = 0 ↔ y ^ 2 - x * y + 1 = 0 ∨ y = 0
[PROOFSTEP]
simp only [hy, eq_self_iff_true, or_true_iff]
[GOAL]
case neg
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
x✝ : x ∈ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
φ : K[X] := X ^ 2 - ↑C x * X + 1
hφ : φ ≠ 0
y : K
hy : ¬y = 0
⊢ x = y + y⁻¹ ∨ y = 0 ↔ y ^ 2 - x * y + 1 = 0 ∨ y = 0
[PROOFSTEP]
apply or_congr _ Iff.rfl
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
x✝ : x ∈ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
φ : K[X] := X ^ 2 - ↑C x * X + 1
hφ : φ ≠ 0
y : K
hy : ¬y = 0
⊢ x = y + y⁻¹ ↔ y ^ 2 - x * y + 1 = 0
[PROOFSTEP]
rw [← mul_left_inj' hy, eq_comm, ← sub_eq_zero, add_mul, inv_mul_cancel hy]
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
x✝ : x ∈ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
φ : K[X] := X ^ 2 - ↑C x * X + 1
hφ : φ ≠ 0
y : K
hy : ¬y = 0
⊢ y * y + 1 - x * y = 0 ↔ y ^ 2 - x * y + 1 = 0
[PROOFSTEP]
apply eq_iff_eq_cancel_right.mpr
[GOAL]
case a
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
x✝ : x ∈ {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
φ : K[X] := X ^ 2 - ↑C x * X + 1
hφ : φ ≠ 0
y : K
hy : ¬y = 0
⊢ y * y + 1 - x * y = y ^ 2 - x * y + 1
[PROOFSTEP]
ring
  -- Finally, we prove the claim that our finite union of finite sets covers all of `K`.
[GOAL]
case intro.intro.intro.a.h.a
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
⊢ Set.univ = do
    let x ← {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
    {y | x = y + y⁻¹ ∨ y = 0}
[PROOFSTEP]
apply (Set.eq_univ_of_forall _).symm
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
⊢ ∀ (x : K),
    x ∈ do
      let x ← {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
      {y | x = y + y⁻¹ ∨ y = 0}
[PROOFSTEP]
intro x
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
⊢ x ∈ do
    let x ← {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
    {y | x = y + y⁻¹ ∨ y = 0}
[PROOFSTEP]
simp only [exists_prop, Set.mem_iUnion, Set.bind_def, Ne.def, Set.mem_setOf_eq]
[GOAL]
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
⊢ ∃ i, (∃ y, i = y + y⁻¹ ∧ ¬y = 0) ∧ (i = x + x⁻¹ ∨ x = 0)
[PROOFSTEP]
by_cases hx : x = 0
[GOAL]
case pos
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
hx : x = 0
⊢ ∃ i, (∃ y, i = y + y⁻¹ ∧ ¬y = 0) ∧ (i = x + x⁻¹ ∨ x = 0)
[PROOFSTEP]
simp only [hx, and_true_iff, eq_self_iff_true, inv_zero, or_true_iff]
[GOAL]
case pos
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
hx : x = 0
⊢ ∃ i y, i = y + y⁻¹ ∧ ¬y = 0
[PROOFSTEP]
exact ⟨_, 1, rfl, one_ne_zero⟩
[GOAL]
case neg
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
hx : ¬x = 0
⊢ ∃ i, (∃ y, i = y + y⁻¹ ∧ ¬y = 0) ∧ (i = x + x⁻¹ ∨ x = 0)
[PROOFSTEP]
simp only [hx, or_false_iff, exists_eq_right]
[GOAL]
case neg
R : Type u_1
S : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing S
k : ℕ
a : R
p : ℕ
inst✝ : Fact (Nat.Prime p)
K : Type
w✝¹ : Field K
w✝ : CharP K p
H : Set.Infinite Set.univ
h : Set.Finite {x | ∃ y, x = y + y⁻¹ ∧ y ≠ 0}
x : K
hx : ¬x = 0
⊢ ∃ y, x + x⁻¹ = y + y⁻¹ ∧ ¬y = 0
[PROOFSTEP]
exact ⟨_, rfl, hx⟩
[GOAL]
R : Type u_1
S : Type u_2
inst✝³ : CommRing R
inst✝² : CommRing S
k : ℕ
a : R
p : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP R p
⊢ dickson 1 1 p = X ^ p
[PROOFSTEP]
have h : (1 : R) = ZMod.castHom (dvd_refl p) R 1
[GOAL]
case h
R : Type u_1
S : Type u_2
inst✝³ : CommRing R
inst✝² : CommRing S
k : ℕ
a : R
p : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP R p
⊢ 1 = ↑(ZMod.castHom (_ : p ∣ p) R) 1
R : Type u_1
S : Type u_2
inst✝³ : CommRing R
inst✝² : CommRing S
k : ℕ
a : R
p : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP R p
h : 1 = ↑(ZMod.castHom (_ : p ∣ p) R) 1
⊢ dickson 1 1 p = X ^ p
[PROOFSTEP]
simp only [ZMod.castHom_apply, ZMod.cast_one']
[GOAL]
R : Type u_1
S : Type u_2
inst✝³ : CommRing R
inst✝² : CommRing S
k : ℕ
a : R
p : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : CharP R p
h : 1 = ↑(ZMod.castHom (_ : p ∣ p) R) 1
⊢ dickson 1 1 p = X ^ p
[PROOFSTEP]
rw [h, ← map_dickson (ZMod.castHom (dvd_refl p) R), dickson_one_one_zmod_p, Polynomial.map_pow, map_X]


[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a : M
⊢ prod (a :: l) = foldl (fun x x_1 => x * x_1) (a * 1) l
[PROOFSTEP]
simp only [List.prod, foldl_cons, one_mul, mul_one]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a : M
⊢ prod (l₁ ++ l₂) = foldl (fun x x_1 => x * x_1) (foldl (fun x x_1 => x * x_1) 1 l₁ * 1) l₂
[PROOFSTEP]
simp [List.prod]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a : M
⊢ prod (concat l a) = prod l * a
[PROOFSTEP]
rw [concat_eq_append, prod_append, prod_singleton]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l✝ l₁ l₂ : List M
a : M
l : List (List M)
⊢ prod (join l) = prod (map prod l)
[PROOFSTEP]
induction l <;> [rfl; simp only [*, List.join, map, prod_append, prod_cons]]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l✝ l₁ l₂ : List M
a : M
l : List (List M)
⊢ prod (join l) = prod (map prod l)
[PROOFSTEP]
induction l
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a : M
⊢ prod (join []) = prod (map prod [])
[PROOFSTEP]
rfl
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a : M
head✝ : List M
tail✝ : List (List M)
tail_ih✝ : prod (join tail✝) = prod (map prod tail✝)
⊢ prod (join (head✝ :: tail✝)) = prod (map prod (head✝ :: tail✝))
[PROOFSTEP]
simp only [*, List.join, map, prod_append, prod_cons]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l✝ l₁ l₂ : List M
a✝ a : M
l : List M
⊢ prod (a :: l) = foldr (fun x x_1 => x * x_1) 1 (a :: l)
[PROOFSTEP]
rw [prod_cons, foldr_cons, prod_eq_foldr]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a✝ : M
n : ℕ
a : M
⊢ prod (replicate n a) = a ^ n
[PROOFSTEP]
induction' n with n ih
[GOAL]
case zero
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a✝ a : M
⊢ prod (replicate Nat.zero a) = a ^ Nat.zero
[PROOFSTEP]
rw [pow_zero]
[GOAL]
case zero
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a✝ a : M
⊢ prod (replicate Nat.zero a) = 1
[PROOFSTEP]
rfl
[GOAL]
case succ
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a✝ a : M
n : ℕ
ih : prod (replicate n a) = a ^ n
⊢ prod (replicate (Nat.succ n) a) = a ^ Nat.succ n
[PROOFSTEP]
rw [replicate_succ, prod_cons, ih, pow_succ]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l✝ l₁ l₂ : List M
a : M
l : List M
m : M
h : ∀ (x : M), x ∈ l → x = m
⊢ prod l = m ^ length l
[PROOFSTEP]
rw [← prod_replicate, ← List.eq_replicate.mpr ⟨rfl, h⟩]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l✝¹ l₁ l₂ : List M
a✝ : M
l✝ : List ι
r : M → N → Prop
f : ι → M
g : ι → N
h₁ : r 1 1
h₂ : ∀ ⦃i : ι⦄ ⦃a : M⦄ ⦃b : N⦄, r a b → r (f i * a) (g i * b)
a : ι
l : List ι
hl : r (prod (map f l)) (prod (map g l))
⊢ r (prod (map f (a :: l))) (prod (map g (a :: l)))
[PROOFSTEP]
simp only [map_cons, prod_cons, h₂ hl]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝³ : Monoid M
inst✝² : Monoid N
inst✝¹ : Monoid P
l✝ l₁ l₂ : List M
a : M
l : List M
F : Type u_9
inst✝ : MonoidHomClass F M N
f : F
⊢ prod (map (↑f) l) = ↑f (prod l)
[PROOFSTEP]
simp only [prod, foldl_map, ← map_one f]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝³ : Monoid M
inst✝² : Monoid N
inst✝¹ : Monoid P
l✝ l₁ l₂ : List M
a : M
l : List M
F : Type u_9
inst✝ : MonoidHomClass F M N
f : F
⊢ foldl (fun x y => x * ↑f y) (↑f 1) l = ↑f (foldl (fun x x_1 => x * x_1) 1 l)
[PROOFSTEP]
exact l.foldl_hom f (· * ·) (· * f ·) 1 (fun x y => (map_mul f x y).symm)
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l✝ l₁ l₂ : List M
a : M
l : List ι
f : M → N → P
hf : ∀ (a b : M) (c d : N), f (a * b) (c * d) = f a c * f b d
hf' : f 1 1 = 1
f₁ : ι → M
f₂ : ι → N
⊢ prod (map (fun i => f (f₁ i) (f₂ i)) l) = f (prod (map f₁ l)) (prod (map f₂ l))
[PROOFSTEP]
simp only [prod, foldl_map]
  -- Porting note: next 3 lines used to be
    -- convert l.foldl_hom₂ (fun a b => f a b) _ _ _ _ _ fun a b i => _
    -- · exact hf'.symm
    -- · exact hf _ _ _ _
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l✝ l₁ l₂ : List M
a : M
l : List ι
f : M → N → P
hf : ∀ (a b : M) (c d : N), f (a * b) (c * d) = f a c * f b d
hf' : f 1 1 = 1
f₁ : ι → M
f₂ : ι → N
⊢ foldl (fun x y => x * f (f₁ y) (f₂ y)) 1 l = f (foldl (fun x y => x * f₁ y) 1 l) (foldl (fun x y => x * f₂ y) 1 l)
[PROOFSTEP]
rw [← l.foldl_hom₂ (fun a b => f a b), hf']
[GOAL]
case h
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l✝ l₁ l₂ : List M
a : M
l : List ι
f : M → N → P
hf : ∀ (a b : M) (c d : N), f (a * b) (c * d) = f a c * f b d
hf' : f 1 1 = 1
f₁ : ι → M
f₂ : ι → N
⊢ ∀ (a : M) (b : N) (i : ι), f (a * f₁ i) (b * f₂ i) = f a b * f (f₁ i) (f₂ i)
[PROOFSTEP]
intros
[GOAL]
case h
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l✝ l₁ l₂ : List M
a : M
l : List ι
f : M → N → P
hf : ∀ (a b : M) (c d : N), f (a * b) (c * d) = f a c * f b d
hf' : f 1 1 = 1
f₁ : ι → M
f₂ : ι → N
a✝ : M
b✝ : N
i✝ : ι
⊢ f (a✝ * f₁ i✝) (b✝ * f₂ i✝) = f a✝ b✝ * f (f₁ i✝) (f₂ i✝)
[PROOFSTEP]
exact hf _ _ _ _
[GOAL]
ι : Type u_1
α✝ : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁴ : Monoid M
inst✝³ : Monoid N
inst✝² : Monoid P
l✝ l₁ l₂ : List M
a : M
α : Type u_9
inst✝¹ : CommMonoid α
inst✝ : HasDistribNeg α
l : List α
⊢ prod (map Neg.neg l) = (-1) ^ length l * prod l
[PROOFSTEP]
simpa only [id_eq, neg_mul, one_mul, map_const', prod_replicate, map_id] using @prod_map_mul α α _ l (fun _ => -1) id
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G✝ : Type u_7
R : Type u_8
inst✝³ : Monoid M
inst✝² : Monoid N
inst✝¹ : Monoid P
l l₁ l₂ : List M
a : M
L : List ι
f : ι → M
G : Type u_9
inst✝ : MonoidHomClass G M N
g : G
⊢ prod (map (↑g ∘ f) L) = ↑g (prod (map f L))
[PROOFSTEP]
rw [← prod_hom, map_map]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a : M
x✝ : ∀ (m : M), m ∈ [] → IsUnit m
⊢ IsUnit (prod [])
[PROOFSTEP]
simp
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a h : M
t : List M
u : ∀ (m : M), m ∈ h :: t → IsUnit m
⊢ IsUnit (prod (h :: t))
[PROOFSTEP]
simp only [List.prod_cons]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a h : M
t : List M
u : ∀ (m : M), m ∈ h :: t → IsUnit m
⊢ IsUnit (h * prod t)
[PROOFSTEP]
exact IsUnit.mul (u h (mem_cons_self h t)) (prod_isUnit fun m mt => u m (mem_cons_of_mem h mt))
[GOAL]
ι : Type u_1
α✝ : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝³ : Monoid M
inst✝² : Monoid N
inst✝¹ : Monoid P
l l₁ l₂ : List M
a : M
α : Type u_9
inst✝ : CommMonoid α
L : List α
⊢ IsUnit (prod L) ↔ ∀ (m : α), m ∈ L → IsUnit m
[PROOFSTEP]
refine' ⟨fun h => _, prod_isUnit⟩
[GOAL]
ι : Type u_1
α✝ : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝³ : Monoid M
inst✝² : Monoid N
inst✝¹ : Monoid P
l l₁ l₂ : List M
a : M
α : Type u_9
inst✝ : CommMonoid α
L : List α
h : IsUnit (prod L)
⊢ ∀ (m : α), m ∈ L → IsUnit m
[PROOFSTEP]
induction' L with m L ih
[GOAL]
case nil
ι : Type u_1
α✝ : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝³ : Monoid M
inst✝² : Monoid N
inst✝¹ : Monoid P
l l₁ l₂ : List M
a : M
α : Type u_9
inst✝ : CommMonoid α
L : List α
h✝ : IsUnit (prod L)
h : IsUnit (prod [])
⊢ ∀ (m : α), m ∈ [] → IsUnit m
[PROOFSTEP]
exact fun m' h' => False.elim (not_mem_nil m' h')
[GOAL]
case cons
ι : Type u_1
α✝ : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝³ : Monoid M
inst✝² : Monoid N
inst✝¹ : Monoid P
l l₁ l₂ : List M
a : M
α : Type u_9
inst✝ : CommMonoid α
L✝ : List α
h✝ : IsUnit (prod L✝)
m : α
L : List α
ih : IsUnit (prod L) → ∀ (m : α), m ∈ L → IsUnit m
h : IsUnit (prod (m :: L))
⊢ ∀ (m_1 : α), m_1 ∈ m :: L → IsUnit m_1
[PROOFSTEP]
rw [prod_cons, IsUnit.mul_iff] at h
[GOAL]
case cons
ι : Type u_1
α✝ : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝³ : Monoid M
inst✝² : Monoid N
inst✝¹ : Monoid P
l l₁ l₂ : List M
a : M
α : Type u_9
inst✝ : CommMonoid α
L✝ : List α
h✝ : IsUnit (prod L✝)
m : α
L : List α
ih : IsUnit (prod L) → ∀ (m : α), m ∈ L → IsUnit m
h : IsUnit m ∧ IsUnit (prod L)
⊢ ∀ (m_1 : α), m_1 ∈ m :: L → IsUnit m_1
[PROOFSTEP]
exact fun m' h' => Or.elim (eq_or_mem_of_mem_cons h') (fun H => H.substr h.1) fun H => ih h.2 _ H
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a : M
i : ℕ
⊢ prod (take i []) * prod (drop i []) = prod []
[PROOFSTEP]
simp [Nat.zero_le]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a : M
L : List M
⊢ prod (take 0 L) * prod (drop 0 L) = prod L
[PROOFSTEP]
simp
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a h : M
t : List M
n : ℕ
⊢ prod (take (n + 1) (h :: t)) * prod (drop (n + 1) (h :: t)) = prod (h :: t)
[PROOFSTEP]
dsimp
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a h : M
t : List M
n : ℕ
⊢ prod (h :: take n t) * prod (drop n t) = prod (h :: t)
[PROOFSTEP]
rw [prod_cons, prod_cons, mul_assoc, prod_take_mul_prod_drop t]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a : M
i : ℕ
p : i < length []
⊢ prod (take (i + 1) []) = prod (take i []) * nthLe [] i p
[PROOFSTEP]
cases p
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a h : M
t : List M
n : ℕ
p : n + 1 < length (h :: t)
⊢ prod (take (n + 1 + 1) (h :: t)) = prod (take (n + 1) (h :: t)) * nthLe (h :: t) (n + 1) p
[PROOFSTEP]
dsimp
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a h : M
t : List M
n : ℕ
p : n + 1 < length (h :: t)
⊢ prod (h :: take (n + 1) t) = prod (h :: take n t) * nthLe (h :: t) (n + 1) p
[PROOFSTEP]
rw [prod_cons, prod_cons, prod_take_succ t n (Nat.lt_of_succ_lt_succ p), mul_assoc, nthLe_cons,
  dif_neg (Nat.add_one_ne_zero _)]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a h : M
t : List M
n : ℕ
p : n + 1 < length (h :: t)
⊢ h * (prod (take n t) * nthLe t n (_ : n < length t)) =
    h * (prod (take n t) * nthLe t (n + 1 - 1) (_ : n + 1 - 1 < length t))
[PROOFSTEP]
simp
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a : M
L : List M
h : prod L ≠ 1
⊢ 0 < length L
[PROOFSTEP]
cases L
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a : M
h : prod [] ≠ 1
⊢ 0 < length []
[PROOFSTEP]
contrapose h
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a : M
h : ¬0 < length []
⊢ ¬prod [] ≠ 1
[PROOFSTEP]
simp
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a head✝ : M
tail✝ : List M
h : prod (head✝ :: tail✝) ≠ 1
⊢ 0 < length (head✝ :: tail✝)
[PROOFSTEP]
simp
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a✝ x : M
xs : List M
a : M
⊢ prod (set (x :: xs) 0 a) =
    (prod (take 0 (x :: xs)) * if 0 < length (x :: xs) then a else 1) * prod (drop (0 + 1) (x :: xs))
[PROOFSTEP]
simp [set]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a✝ x : M
xs : List M
i : ℕ
a : M
⊢ prod (set (x :: xs) (i + 1) a) =
    (prod (take (i + 1) (x :: xs)) * if i + 1 < length (x :: xs) then a else 1) * prod (drop (i + 1 + 1) (x :: xs))
[PROOFSTEP]
simp [set, prod_set xs i a, mul_assoc, Nat.succ_eq_add_one]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a : M
x✝¹ : ℕ
x✝ : M
⊢ prod (set [] x✝¹ x✝) = (prod (take x✝¹ []) * if x✝¹ < length [] then x✝ else 1) * prod (drop (x✝¹ + 1) [])
[PROOFSTEP]
simp [set, (Nat.zero_le _).not_lt, Nat.zero_le]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l✝ l₁ l₂ : List M
a : M
l : List M
⊢ Option.getD (get? l 0) 1 * prod (tail l) = prod l
[PROOFSTEP]
cases l
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a : M
⊢ Option.getD (get? [] 0) 1 * prod (tail []) = prod []
[PROOFSTEP]
simp
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l l₁ l₂ : List M
a head✝ : M
tail✝ : List M
⊢ Option.getD (get? (head✝ :: tail✝) 0) 1 * prod (tail (head✝ :: tail✝)) = prod (head✝ :: tail✝)
[PROOFSTEP]
simp
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝³ : Monoid M
inst✝² : Monoid N
inst✝¹ : Monoid P
l✝ l₁ l₂ : List M
a : M
inst✝ : Inhabited M
l : List M
h : l ≠ []
⊢ headI l * prod (tail l) = prod l
[PROOFSTEP]
cases l <;> [contradiction; simp]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝³ : Monoid M
inst✝² : Monoid N
inst✝¹ : Monoid P
l✝ l₁ l₂ : List M
a : M
inst✝ : Inhabited M
l : List M
h : l ≠ []
⊢ headI l * prod (tail l) = prod l
[PROOFSTEP]
cases l
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝³ : Monoid M
inst✝² : Monoid N
inst✝¹ : Monoid P
l l₁ l₂ : List M
a : M
inst✝ : Inhabited M
h : [] ≠ []
⊢ headI [] * prod (tail []) = prod []
[PROOFSTEP]
contradiction
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝³ : Monoid M
inst✝² : Monoid N
inst✝¹ : Monoid P
l l₁ l₂ : List M
a : M
inst✝ : Inhabited M
head✝ : M
tail✝ : List M
h : head✝ :: tail✝ ≠ []
⊢ headI (head✝ :: tail✝) * prod (tail (head✝ :: tail✝)) = prod (head✝ :: tail✝)
[PROOFSTEP]
simp
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l✝ l₁ l₂ : List M
a : M
l : List M
y : M
h : ∀ (x : M), x ∈ l → Commute y x
⊢ Commute y (prod l)
[PROOFSTEP]
induction' l with z l IH
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l✝ l₁ l₂ : List M
a : M
l : List M
y : M
h✝ : ∀ (x : M), x ∈ l → Commute y x
h : ∀ (x : M), x ∈ [] → Commute y x
⊢ Commute y (prod [])
[PROOFSTEP]
simp
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l✝¹ l₁ l₂ : List M
a : M
l✝ : List M
y : M
h✝ : ∀ (x : M), x ∈ l✝ → Commute y x
z : M
l : List M
IH : (∀ (x : M), x ∈ l → Commute y x) → Commute y (prod l)
h : ∀ (x : M), x ∈ z :: l → Commute y x
⊢ Commute y (prod (z :: l))
[PROOFSTEP]
rw [List.forall_mem_cons] at h
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l✝¹ l₁ l₂ : List M
a : M
l✝ : List M
y : M
h✝ : ∀ (x : M), x ∈ l✝ → Commute y x
z : M
l : List M
IH : (∀ (x : M), x ∈ l → Commute y x) → Commute y (prod l)
h : Commute y z ∧ ∀ (x : M), x ∈ l → Commute y x
⊢ Commute y (prod (z :: l))
[PROOFSTEP]
rw [List.prod_cons]
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : Monoid M
inst✝¹ : Monoid N
inst✝ : Monoid P
l✝¹ l₁ l₂ : List M
a : M
l✝ : List M
y : M
h✝ : ∀ (x : M), x ∈ l✝ → Commute y x
z : M
l : List M
IH : (∀ (x : M), x ∈ l → Commute y x) → Commute y (prod l)
h : Commute y z ∧ ∀ (x : M), x ∈ l → Commute y x
⊢ Commute y (z * prod l)
[PROOFSTEP]
exact Commute.mul_right h.1 (IH h.2)
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝ l₂✝ : List M
a : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁ l₂ : List M
h : Forall₂ (fun x x_1 => x ≤ x_1) l₁ l₂
⊢ prod l₁ ≤ prod l₂
[PROOFSTEP]
induction' h with a b la lb hab ih ih'
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝ l₂✝ : List M
a : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁ l₂ : List M
⊢ prod [] ≤ prod []
[PROOFSTEP]
rfl
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝ l₂✝ : List M
a✝ : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁ l₂ : List M
a b : M
la lb : List M
hab : a ≤ b
ih : Forall₂ (fun x x_1 => x ≤ x_1) la lb
ih' : prod la ≤ prod lb
⊢ prod (a :: la) ≤ prod (b :: lb)
[PROOFSTEP]
simpa only [prod_cons] using mul_le_mul' hab ih'
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝ l₂✝ : List M
a : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁ l₂ : List M
h : l₁ <+ l₂
h₁ : ∀ (a : M), a ∈ l₂ → 1 ≤ a
⊢ prod l₁ ≤ prod l₂
[PROOFSTEP]
induction h
[GOAL]
case slnil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝ l₂✝ : List M
a : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁ l₂ : List M
h₁ : ∀ (a : M), a ∈ [] → 1 ≤ a
⊢ prod [] ≤ prod []
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝¹ l₂✝¹ : List M
a : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁ l₂ l₁✝ l₂✝ : List M
a✝¹ : M
a✝ : l₁✝ <+ l₂✝
a_ih✝ : (∀ (a : M), a ∈ l₂✝ → 1 ≤ a) → prod l₁✝ ≤ prod l₂✝
h₁ : ∀ (a : M), a ∈ a✝¹ :: l₂✝ → 1 ≤ a
⊢ prod l₁✝ ≤ prod (a✝¹ :: l₂✝)
case cons₂
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝¹ l₂✝¹ : List M
a : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁ l₂ l₁✝ l₂✝ : List M
a✝¹ : M
a✝ : l₁✝ <+ l₂✝
a_ih✝ : (∀ (a : M), a ∈ l₂✝ → 1 ≤ a) → prod l₁✝ ≤ prod l₂✝
h₁ : ∀ (a : M), a ∈ a✝¹ :: l₂✝ → 1 ≤ a
⊢ prod (a✝¹ :: l₁✝) ≤ prod (a✝¹ :: l₂✝)
[PROOFSTEP]
case slnil => rfl
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝ l₂✝ : List M
a : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁ l₂ : List M
h₁ : ∀ (a : M), a ∈ [] → 1 ≤ a
⊢ prod [] ≤ prod []
[PROOFSTEP]
case slnil => rfl
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝ l₂✝ : List M
a : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁ l₂ : List M
h₁ : ∀ (a : M), a ∈ [] → 1 ≤ a
⊢ prod [] ≤ prod []
[PROOFSTEP]
rfl
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝¹ l₂✝¹ : List M
a : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁ l₂ l₁✝ l₂✝ : List M
a✝¹ : M
a✝ : l₁✝ <+ l₂✝
a_ih✝ : (∀ (a : M), a ∈ l₂✝ → 1 ≤ a) → prod l₁✝ ≤ prod l₂✝
h₁ : ∀ (a : M), a ∈ a✝¹ :: l₂✝ → 1 ≤ a
⊢ prod l₁✝ ≤ prod (a✝¹ :: l₂✝)
case cons₂
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝¹ l₂✝¹ : List M
a : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁ l₂ l₁✝ l₂✝ : List M
a✝¹ : M
a✝ : l₁✝ <+ l₂✝
a_ih✝ : (∀ (a : M), a ∈ l₂✝ → 1 ≤ a) → prod l₁✝ ≤ prod l₂✝
h₁ : ∀ (a : M), a ∈ a✝¹ :: l₂✝ → 1 ≤ a
⊢ prod (a✝¹ :: l₁✝) ≤ prod (a✝¹ :: l₂✝)
[PROOFSTEP]
case cons l₁ l₂ a _ ih' =>
  simp only [prod_cons, forall_mem_cons] at h₁ ⊢
  exact (ih' h₁.2).trans (le_mul_of_one_le_left' h₁.1)
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝¹ l₂✝¹ : List M
a✝¹ : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁✝ l₂✝ l₁ l₂ : List M
a : M
a✝ : l₁ <+ l₂
ih' : (∀ (a : M), a ∈ l₂ → 1 ≤ a) → prod l₁ ≤ prod l₂
h₁ : ∀ (a_1 : M), a_1 ∈ a :: l₂ → 1 ≤ a_1
⊢ prod l₁ ≤ prod (a :: l₂)
[PROOFSTEP]
case cons l₁ l₂ a _ ih' =>
  simp only [prod_cons, forall_mem_cons] at h₁ ⊢
  exact (ih' h₁.2).trans (le_mul_of_one_le_left' h₁.1)
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝¹ l₂✝¹ : List M
a✝¹ : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁✝ l₂✝ l₁ l₂ : List M
a : M
a✝ : l₁ <+ l₂
ih' : (∀ (a : M), a ∈ l₂ → 1 ≤ a) → prod l₁ ≤ prod l₂
h₁ : ∀ (a_1 : M), a_1 ∈ a :: l₂ → 1 ≤ a_1
⊢ prod l₁ ≤ prod (a :: l₂)
[PROOFSTEP]
simp only [prod_cons, forall_mem_cons] at h₁ ⊢
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝¹ l₂✝¹ : List M
a✝¹ : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁✝ l₂✝ l₁ l₂ : List M
a : M
a✝ : l₁ <+ l₂
ih' : (∀ (a : M), a ∈ l₂ → 1 ≤ a) → prod l₁ ≤ prod l₂
h₁ : 1 ≤ a ∧ ∀ (x : M), x ∈ l₂ → 1 ≤ x
⊢ prod l₁ ≤ a * prod l₂
[PROOFSTEP]
exact (ih' h₁.2).trans (le_mul_of_one_le_left' h₁.1)
[GOAL]
case cons₂
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝¹ l₂✝¹ : List M
a : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁ l₂ l₁✝ l₂✝ : List M
a✝¹ : M
a✝ : l₁✝ <+ l₂✝
a_ih✝ : (∀ (a : M), a ∈ l₂✝ → 1 ≤ a) → prod l₁✝ ≤ prod l₂✝
h₁ : ∀ (a : M), a ∈ a✝¹ :: l₂✝ → 1 ≤ a
⊢ prod (a✝¹ :: l₁✝) ≤ prod (a✝¹ :: l₂✝)
[PROOFSTEP]
case cons₂ l₁ l₂ a _ ih' =>
  simp only [prod_cons, forall_mem_cons] at h₁ ⊢
  exact mul_le_mul_left' (ih' h₁.2) _
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝¹ l₂✝¹ : List M
a✝¹ : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁✝ l₂✝ l₁ l₂ : List M
a : M
a✝ : l₁ <+ l₂
ih' : (∀ (a : M), a ∈ l₂ → 1 ≤ a) → prod l₁ ≤ prod l₂
h₁ : ∀ (a_1 : M), a_1 ∈ a :: l₂ → 1 ≤ a_1
⊢ prod (a :: l₁) ≤ prod (a :: l₂)
[PROOFSTEP]
case cons₂ l₁ l₂ a _ ih' =>
  simp only [prod_cons, forall_mem_cons] at h₁ ⊢
  exact mul_le_mul_left' (ih' h₁.2) _
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝¹ l₂✝¹ : List M
a✝¹ : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁✝ l₂✝ l₁ l₂ : List M
a : M
a✝ : l₁ <+ l₂
ih' : (∀ (a : M), a ∈ l₂ → 1 ≤ a) → prod l₁ ≤ prod l₂
h₁ : ∀ (a_1 : M), a_1 ∈ a :: l₂ → 1 ≤ a_1
⊢ prod (a :: l₁) ≤ prod (a :: l₂)
[PROOFSTEP]
simp only [prod_cons, forall_mem_cons] at h₁ ⊢
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l l₁✝¹ l₂✝¹ : List M
a✝¹ : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l₁✝ l₂✝ l₁ l₂ : List M
a : M
a✝ : l₁ <+ l₂
ih' : (∀ (a : M), a ∈ l₂ → 1 ≤ a) → prod l₁ ≤ prod l₂
h₁ : 1 ≤ a ∧ ∀ (x : M), x ∈ l₂ → 1 ≤ x
⊢ a * prod l₁ ≤ a * prod l₂
[PROOFSTEP]
exact mul_le_mul_left' (ih' h₁.2) _
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l✝ l₁ l₂ : List M
a : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l : List ι
f g : ι → M
h : ∀ (i : ι), i ∈ l → f i ≤ g i
⊢ Forall₂ (fun x x_1 => x ≤ x_1) (map f l) (map g l)
[PROOFSTEP]
simpa
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁷ : Monoid M
inst✝⁶ : Monoid N
inst✝⁵ : Monoid P
l✝ l₁ l₂ : List M
a : M
inst✝⁴ : Preorder M
inst✝³ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x < x_1
inst✝² : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x < x_1
inst✝ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l : List ι
f g : ι → M
h₁ : ∀ (i : ι), i ∈ l → f i ≤ g i
h₂ : ∃ i, i ∈ l ∧ f i < g i
⊢ prod (map f l) < prod (map g l)
[PROOFSTEP]
induction' l with i l ihl
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁷ : Monoid M
inst✝⁶ : Monoid N
inst✝⁵ : Monoid P
l✝ l₁ l₂ : List M
a : M
inst✝⁴ : Preorder M
inst✝³ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x < x_1
inst✝² : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x < x_1
inst✝ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l : List ι
f g : ι → M
h₁✝ : ∀ (i : ι), i ∈ l → f i ≤ g i
h₂✝ : ∃ i, i ∈ l ∧ f i < g i
h₁ : ∀ (i : ι), i ∈ [] → f i ≤ g i
h₂ : ∃ i, i ∈ [] ∧ f i < g i
⊢ prod (map f []) < prod (map g [])
[PROOFSTEP]
rcases h₂ with ⟨_, ⟨⟩, _⟩
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁷ : Monoid M
inst✝⁶ : Monoid N
inst✝⁵ : Monoid P
l✝¹ l₁ l₂ : List M
a : M
inst✝⁴ : Preorder M
inst✝³ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x < x_1
inst✝² : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x < x_1
inst✝ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l✝ : List ι
f g : ι → M
h₁✝ : ∀ (i : ι), i ∈ l✝ → f i ≤ g i
h₂✝ : ∃ i, i ∈ l✝ ∧ f i < g i
i : ι
l : List ι
ihl : (∀ (i : ι), i ∈ l → f i ≤ g i) → (∃ i, i ∈ l ∧ f i < g i) → prod (map f l) < prod (map g l)
h₁ : ∀ (i_1 : ι), i_1 ∈ i :: l → f i_1 ≤ g i_1
h₂ : ∃ i_1, i_1 ∈ i :: l ∧ f i_1 < g i_1
⊢ prod (map f (i :: l)) < prod (map g (i :: l))
[PROOFSTEP]
simp only [forall_mem_cons, exists_mem_cons, map_cons, prod_cons] at h₁ h₂ ⊢
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁷ : Monoid M
inst✝⁶ : Monoid N
inst✝⁵ : Monoid P
l✝¹ l₁ l₂ : List M
a : M
inst✝⁴ : Preorder M
inst✝³ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x < x_1
inst✝² : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x < x_1
inst✝ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l✝ : List ι
f g : ι → M
h₁✝ : ∀ (i : ι), i ∈ l✝ → f i ≤ g i
h₂✝ : ∃ i, i ∈ l✝ ∧ f i < g i
i : ι
l : List ι
ihl : (∀ (i : ι), i ∈ l → f i ≤ g i) → (∃ i, i ∈ l ∧ f i < g i) → prod (map f l) < prod (map g l)
h₁ : f i ≤ g i ∧ ∀ (x : ι), x ∈ l → f x ≤ g x
h₂ : f i < g i ∨ ∃ x, x ∈ l ∧ f x < g x
⊢ f i * prod (map f l) < g i * prod (map g l)
[PROOFSTEP]
cases h₂
[GOAL]
case cons.inl
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁷ : Monoid M
inst✝⁶ : Monoid N
inst✝⁵ : Monoid P
l✝¹ l₁ l₂ : List M
a : M
inst✝⁴ : Preorder M
inst✝³ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x < x_1
inst✝² : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x < x_1
inst✝ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l✝ : List ι
f g : ι → M
h₁✝ : ∀ (i : ι), i ∈ l✝ → f i ≤ g i
h₂ : ∃ i, i ∈ l✝ ∧ f i < g i
i : ι
l : List ι
ihl : (∀ (i : ι), i ∈ l → f i ≤ g i) → (∃ i, i ∈ l ∧ f i < g i) → prod (map f l) < prod (map g l)
h₁ : f i ≤ g i ∧ ∀ (x : ι), x ∈ l → f x ≤ g x
h✝ : f i < g i
⊢ f i * prod (map f l) < g i * prod (map g l)
[PROOFSTEP]
exact mul_lt_mul_of_lt_of_le ‹_› (prod_le_prod' h₁.2)
[GOAL]
case cons.inr
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁷ : Monoid M
inst✝⁶ : Monoid N
inst✝⁵ : Monoid P
l✝¹ l₁ l₂ : List M
a : M
inst✝⁴ : Preorder M
inst✝³ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x < x_1
inst✝² : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x < x_1
inst✝ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l✝ : List ι
f g : ι → M
h₁✝ : ∀ (i : ι), i ∈ l✝ → f i ≤ g i
h₂ : ∃ i, i ∈ l✝ ∧ f i < g i
i : ι
l : List ι
ihl : (∀ (i : ι), i ∈ l → f i ≤ g i) → (∃ i, i ∈ l ∧ f i < g i) → prod (map f l) < prod (map g l)
h₁ : f i ≤ g i ∧ ∀ (x : ι), x ∈ l → f x ≤ g x
h✝ : ∃ x, x ∈ l ∧ f x < g x
⊢ f i * prod (map f l) < g i * prod (map g l)
[PROOFSTEP]
exact mul_lt_mul_of_le_of_lt h₁.1 <| ihl h₁.2 ‹_›
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l✝ l₁ l₂ : List M
a : M
inst✝² : Preorder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l : List M
n : M
h : ∀ (x : M), x ∈ l → x ≤ n
⊢ prod l ≤ n ^ length l
[PROOFSTEP]
simpa only [map_id'', map_const', prod_replicate] using prod_le_prod' h
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l✝ l₁ l₂ : List M
a : M
inst✝² : LinearOrder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l : List ι
f g : ι → M
h : prod (map f l) < prod (map g l)
⊢ ∃ i, i ∈ l ∧ f i < g i
[PROOFSTEP]
contrapose! h
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁵ : Monoid M
inst✝⁴ : Monoid N
inst✝³ : Monoid P
l✝ l₁ l₂ : List M
a : M
inst✝² : LinearOrder M
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l : List ι
f g : ι → M
h : ∀ (i : ι), i ∈ l → g i ≤ f i
⊢ prod (map g l) ≤ prod (map f l)
[PROOFSTEP]
exact prod_le_prod' h
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁷ : Monoid M
inst✝⁶ : Monoid N
inst✝⁵ : Monoid P
l✝ l₁ l₂ : List M
a : M
inst✝⁴ : LinearOrder M
inst✝³ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x < x_1
inst✝² : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x < x_1
inst✝ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l : List ι
hl : l ≠ []
f g : ι → M
h : prod (map f l) ≤ prod (map g l)
⊢ ∃ x, x ∈ l ∧ f x ≤ g x
[PROOFSTEP]
contrapose! h
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁷ : Monoid M
inst✝⁶ : Monoid N
inst✝⁵ : Monoid P
l✝ l₁ l₂ : List M
a : M
inst✝⁴ : LinearOrder M
inst✝³ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x < x_1
inst✝² : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
inst✝¹ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x < x_1
inst✝ : CovariantClass M M (Function.swap fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l : List ι
hl : l ≠ []
f g : ι → M
h : ∀ (x : ι), x ∈ l → g x < f x
⊢ prod (map g l) < prod (map f l)
[PROOFSTEP]
exact prod_lt_prod_of_ne_nil hl _ _ h
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁴ : Monoid M
inst✝³ : Monoid N
inst✝² : Monoid P
l✝ l₁ l₂ : List M
a : M
inst✝¹ : Preorder M
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l : List M
hl₁ : ∀ (x : M), x ∈ l → 1 ≤ x
⊢ 1 ≤ prod l
[PROOFSTEP]
induction' l with hd tl ih
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁴ : Monoid M
inst✝³ : Monoid N
inst✝² : Monoid P
l✝ l₁ l₂ : List M
a : M
inst✝¹ : Preorder M
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l : List M
hl₁✝ : ∀ (x : M), x ∈ l → 1 ≤ x
hl₁ : ∀ (x : M), x ∈ [] → 1 ≤ x
⊢ 1 ≤ prod []
[PROOFSTEP]
rfl
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁴ : Monoid M
inst✝³ : Monoid N
inst✝² : Monoid P
l✝ l₁ l₂ : List M
a : M
inst✝¹ : Preorder M
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l : List M
hl₁✝ : ∀ (x : M), x ∈ l → 1 ≤ x
hd : M
tl : List M
ih : (∀ (x : M), x ∈ tl → 1 ≤ x) → 1 ≤ prod tl
hl₁ : ∀ (x : M), x ∈ hd :: tl → 1 ≤ x
⊢ 1 ≤ prod (hd :: tl)
[PROOFSTEP]
rw [prod_cons]
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝⁴ : Monoid M
inst✝³ : Monoid N
inst✝² : Monoid P
l✝ l₁ l₂ : List M
a : M
inst✝¹ : Preorder M
inst✝ : CovariantClass M M (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1
l : List M
hl₁✝ : ∀ (x : M), x ∈ l → 1 ≤ x
hd : M
tl : List M
ih : (∀ (x : M), x ∈ tl → 1 ≤ x) → 1 ≤ prod tl
hl₁ : ∀ (x : M), x ∈ hd :: tl → 1 ≤ x
⊢ 1 ≤ hd * prod tl
[PROOFSTEP]
exact one_le_mul (hl₁ hd (mem_cons_self hd tl)) (ih fun x h => hl₁ x (mem_cons_of_mem hd h))
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : MonoidWithZero M₀
L : List M₀
h : 0 ∈ L
⊢ prod L = 0
[PROOFSTEP]
induction' L with a L ihL
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : MonoidWithZero M₀
L : List M₀
h✝ : 0 ∈ L
h : 0 ∈ []
⊢ prod [] = 0
[PROOFSTEP]
exact absurd h (not_mem_nil _)
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : MonoidWithZero M₀
L✝ : List M₀
h✝ : 0 ∈ L✝
a : M₀
L : List M₀
ihL : 0 ∈ L → prod L = 0
h : 0 ∈ a :: L
⊢ prod (a :: L) = 0
[PROOFSTEP]
rw [prod_cons]
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : MonoidWithZero M₀
L✝ : List M₀
h✝ : 0 ∈ L✝
a : M₀
L : List M₀
ihL : 0 ∈ L → prod L = 0
h : 0 ∈ a :: L
⊢ a * prod L = 0
[PROOFSTEP]
cases' mem_cons.1 h with ha hL
[GOAL]
case cons.inl
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : MonoidWithZero M₀
L✝ : List M₀
h✝ : 0 ∈ L✝
a : M₀
L : List M₀
ihL : 0 ∈ L → prod L = 0
h : 0 ∈ a :: L
ha : 0 = a
⊢ a * prod L = 0
case cons.inr
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : MonoidWithZero M₀
L✝ : List M₀
h✝ : 0 ∈ L✝
a : M₀
L : List M₀
ihL : 0 ∈ L → prod L = 0
h : 0 ∈ a :: L
hL : 0 ∈ L
⊢ a * prod L = 0
[PROOFSTEP]
exacts [mul_eq_zero_of_left ha.symm _, mul_eq_zero_of_right _ (ihL hL)]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : MonoidWithZero M₀
inst✝¹ : Nontrivial M₀
inst✝ : NoZeroDivisors M₀
L : List M₀
⊢ prod L = 0 ↔ 0 ∈ L
[PROOFSTEP]
induction' L with a L ihL
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : MonoidWithZero M₀
inst✝¹ : Nontrivial M₀
inst✝ : NoZeroDivisors M₀
⊢ prod [] = 0 ↔ 0 ∈ []
[PROOFSTEP]
simp
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : MonoidWithZero M₀
inst✝¹ : Nontrivial M₀
inst✝ : NoZeroDivisors M₀
a : M₀
L : List M₀
ihL : prod L = 0 ↔ 0 ∈ L
⊢ prod (a :: L) = 0 ↔ 0 ∈ a :: L
[PROOFSTEP]
rw [prod_cons, mul_eq_zero, ihL, mem_cons, eq_comm]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : Group G
⊢ (prod [])⁻¹ = prod (reverse (map (fun x => x⁻¹) []))
[PROOFSTEP]
simp
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : Group G
x : G
xs : List G
⊢ (prod (x :: xs))⁻¹ = prod (reverse (map (fun x => x⁻¹) (x :: xs)))
[PROOFSTEP]
simp [prod_inv_reverse xs]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : Group G
⊢ ∀ (L : List G), prod (reverse L) = (prod (map (fun x => x⁻¹) L))⁻¹
[PROOFSTEP]
simp [prod_inv_reverse]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : Group G
x : G
xs : List G
x✝ : 0 < length (x :: xs)
⊢ prod (drop (0 + 1) (x :: xs)) = (nthLe (x :: xs) 0 x✝)⁻¹ * prod (drop 0 (x :: xs))
[PROOFSTEP]
simp [nthLe]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : CommGroup G
⊢ (prod [])⁻¹ = prod (map (fun x => x⁻¹) [])
[PROOFSTEP]
simp
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : CommGroup G
x : G
xs : List G
⊢ (prod (x :: xs))⁻¹ = prod (map (fun x => x⁻¹) (x :: xs))
[PROOFSTEP]
simp [mul_comm, prod_inv xs]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : CommGroup G
L : List G
n : ℕ
a : G
⊢ prod (set L n a) = prod L * if hn : n < length L then (nthLe L n hn)⁻¹ * a else 1
[PROOFSTEP]
refine (prod_set L n a).trans ?_
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : CommGroup G
L : List G
n : ℕ
a : G
⊢ (prod (take n L) * if n < length L then a else 1) * prod (drop (n + 1) L) =
    prod L * if hn : n < length L then (nthLe L n hn)⁻¹ * a else 1
[PROOFSTEP]
split_ifs with hn
[GOAL]
case pos
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : CommGroup G
L : List G
n : ℕ
a : G
hn : n < length L
⊢ prod (take n L) * a * prod (drop (n + 1) L) = prod L * ((nthLe L n hn)⁻¹ * a)
[PROOFSTEP]
rw [mul_comm _ a, mul_assoc a, prod_drop_succ L n hn, mul_comm _ (drop n L).prod, ← mul_assoc (take n L).prod,
  prod_take_mul_prod_drop, mul_comm a, mul_assoc]
[GOAL]
case neg
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : CommGroup G
L : List G
n : ℕ
a : G
hn : ¬n < length L
⊢ prod (take n L) * 1 * prod (drop (n + 1) L) = prod L * 1
[PROOFSTEP]
simp only [take_all_of_le (le_of_not_lt hn), prod_nil, mul_one, drop_eq_nil_of_le ((le_of_not_lt hn).trans n.le_succ)]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : LeftCancelMonoid M
L L' : List M
h : length L = length L'
h' : ∀ (i : ℕ), i ≤ length L → prod (take i L) = prod (take i L')
⊢ L = L'
[PROOFSTEP]
refine ext_get h fun i h₁ h₂ => ?_
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : LeftCancelMonoid M
L L' : List M
h : length L = length L'
h' : ∀ (i : ℕ), i ≤ length L → prod (take i L) = prod (take i L')
i : ℕ
h₁ : i < length L
h₂ : i < length L'
⊢ get L { val := i, isLt := h₁ } = get L' { val := i, isLt := h₂ }
[PROOFSTEP]
have : (L.take (i + 1)).prod = (L'.take (i + 1)).prod := h' _ (Nat.succ_le_of_lt h₁)
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : LeftCancelMonoid M
L L' : List M
h : length L = length L'
h' : ∀ (i : ℕ), i ≤ length L → prod (take i L) = prod (take i L')
i : ℕ
h₁ : i < length L
h₂ : i < length L'
this : prod (take (i + 1) L) = prod (take (i + 1) L')
⊢ get L { val := i, isLt := h₁ } = get L' { val := i, isLt := h₂ }
[PROOFSTEP]
rw [prod_take_succ L i h₁, prod_take_succ L' i h₂, h' i (le_of_lt h₁)] at this
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : LeftCancelMonoid M
L L' : List M
h : length L = length L'
h' : ∀ (i : ℕ), i ≤ length L → prod (take i L) = prod (take i L')
i : ℕ
h₁ : i < length L
h₂ : i < length L'
this : prod (take i L') * nthLe L i h₁ = prod (take i L') * nthLe L' i h₂
⊢ get L { val := i, isLt := h₁ } = get L' { val := i, isLt := h₂ }
[PROOFSTEP]
convert mul_left_cancel this
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : CanonicallyOrderedMonoid M
L : List M
⊢ Monotone fun i => prod (take i L)
[PROOFSTEP]
refine' monotone_nat_of_le_succ fun n => _
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : CanonicallyOrderedMonoid M
L : List M
n : ℕ
⊢ prod (take n L) ≤ prod (take (n + 1) L)
[PROOFSTEP]
cases' lt_or_le n L.length with h h
[GOAL]
case inl
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : CanonicallyOrderedMonoid M
L : List M
n : ℕ
h : n < length L
⊢ prod (take n L) ≤ prod (take (n + 1) L)
[PROOFSTEP]
rw [prod_take_succ _ _ h]
[GOAL]
case inl
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : CanonicallyOrderedMonoid M
L : List M
n : ℕ
h : n < length L
⊢ prod (take n L) ≤ prod (take n L) * nthLe L n h
[PROOFSTEP]
exact le_self_mul
[GOAL]
case inr
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : CanonicallyOrderedMonoid M
L : List M
n : ℕ
h : length L ≤ n
⊢ prod (take n L) ≤ prod (take (n + 1) L)
[PROOFSTEP]
simp [take_all_of_le h, take_all_of_le (le_trans h (Nat.le_succ _))]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
b : M
h : ∀ (x : M), x ∈ [b] → 1 < x
x✝ : [b] ≠ []
⊢ 1 < prod [b]
[PROOFSTEP]
simpa using h
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
a b : M
l : List M
hl₁ : ∀ (x : M), x ∈ a :: b :: l → 1 < x
x✝ : a :: b :: l ≠ []
⊢ 1 < prod (a :: b :: l)
[PROOFSTEP]
simp only [forall_eq_or_imp, List.mem_cons] at hl₁
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
a b : M
l : List M
x✝ : a :: b :: l ≠ []
hl₁ : 1 < a ∧ 1 < b ∧ ∀ (a : M), a ∈ l → 1 < a
⊢ 1 < prod (a :: b :: l)
[PROOFSTEP]
rw [List.prod_cons]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
a b : M
l : List M
x✝ : a :: b :: l ≠ []
hl₁ : 1 < a ∧ 1 < b ∧ ∀ (a : M), a ∈ l → 1 < a
⊢ 1 < a * prod (b :: l)
[PROOFSTEP]
apply one_lt_mul_of_lt_of_le' hl₁.1
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
a b : M
l : List M
x✝ : a :: b :: l ≠ []
hl₁ : 1 < a ∧ 1 < b ∧ ∀ (a : M), a ∈ l → 1 < a
⊢ 1 ≤ prod (b :: l)
[PROOFSTEP]
apply le_of_lt ((b :: l).one_lt_prod_of_one_lt _ (l.cons_ne_nil b))
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
a b : M
l : List M
x✝ : a :: b :: l ≠ []
hl₁ : 1 < a ∧ 1 < b ∧ ∀ (a : M), a ∈ l → 1 < a
⊢ ∀ (x : M), x ∈ b :: l → 1 < x
[PROOFSTEP]
intro x hx
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
a b : M
l : List M
x✝ : a :: b :: l ≠ []
hl₁ : 1 < a ∧ 1 < b ∧ ∀ (a : M), a ∈ l → 1 < a
x : M
hx : x ∈ b :: l
⊢ 1 < x
[PROOFSTEP]
cases hx
[GOAL]
case head
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
a b : M
l : List M
x✝ : a :: b :: l ≠ []
hl₁ : 1 < a ∧ 1 < b ∧ ∀ (a : M), a ∈ l → 1 < a
⊢ 1 < b
[PROOFSTEP]
exact hl₁.2.1
[GOAL]
case tail
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
a b : M
l : List M
x✝ : a :: b :: l ≠ []
hl₁ : 1 < a ∧ 1 < b ∧ ∀ (a : M), a ∈ l → 1 < a
x : M
a✝ : Mem x l
⊢ 1 < x
[PROOFSTEP]
exact hl₁.2.2 _ ‹_›
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
l : List M
hl₁ : ∀ (x : M), x ∈ l → 1 ≤ x
⊢ ∀ (x : M), x ∈ l → x ≤ prod l
[PROOFSTEP]
induction l
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
hl₁ : ∀ (x : M), x ∈ [] → 1 ≤ x
⊢ ∀ (x : M), x ∈ [] → x ≤ prod []
[PROOFSTEP]
simp
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
head✝ : M
tail✝ : List M
tail_ih✝ : (∀ (x : M), x ∈ tail✝ → 1 ≤ x) → ∀ (x : M), x ∈ tail✝ → x ≤ prod tail✝
hl₁ : ∀ (x : M), x ∈ head✝ :: tail✝ → 1 ≤ x
⊢ ∀ (x : M), x ∈ head✝ :: tail✝ → x ≤ prod (head✝ :: tail✝)
[PROOFSTEP]
simp_rw [prod_cons, forall_mem_cons] at hl₁ ⊢
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
head✝ : M
tail✝ : List M
tail_ih✝ : (∀ (x : M), x ∈ tail✝ → 1 ≤ x) → ∀ (x : M), x ∈ tail✝ → x ≤ prod tail✝
hl₁ : 1 ≤ head✝ ∧ ∀ (x : M), x ∈ tail✝ → 1 ≤ x
⊢ head✝ ≤ head✝ * prod tail✝ ∧ ∀ (x : M), x ∈ tail✝ → x ≤ head✝ * prod tail✝
[PROOFSTEP]
constructor
[GOAL]
case cons.left
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
head✝ : M
tail✝ : List M
tail_ih✝ : (∀ (x : M), x ∈ tail✝ → 1 ≤ x) → ∀ (x : M), x ∈ tail✝ → x ≤ prod tail✝
hl₁ : 1 ≤ head✝ ∧ ∀ (x : M), x ∈ tail✝ → 1 ≤ x
⊢ head✝ ≤ head✝ * prod tail✝
case cons.right
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
head✝ : M
tail✝ : List M
tail_ih✝ : (∀ (x : M), x ∈ tail✝ → 1 ≤ x) → ∀ (x : M), x ∈ tail✝ → x ≤ prod tail✝
hl₁ : 1 ≤ head✝ ∧ ∀ (x : M), x ∈ tail✝ → 1 ≤ x
⊢ ∀ (x : M), x ∈ tail✝ → x ≤ head✝ * prod tail✝
[PROOFSTEP]
case cons.left => exact le_mul_of_one_le_right' (one_le_prod_of_one_le hl₁.2)
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
head✝ : M
tail✝ : List M
tail_ih✝ : (∀ (x : M), x ∈ tail✝ → 1 ≤ x) → ∀ (x : M), x ∈ tail✝ → x ≤ prod tail✝
hl₁ : 1 ≤ head✝ ∧ ∀ (x : M), x ∈ tail✝ → 1 ≤ x
⊢ head✝ ≤ head✝ * prod tail✝
[PROOFSTEP]
case cons.left => exact le_mul_of_one_le_right' (one_le_prod_of_one_le hl₁.2)
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
head✝ : M
tail✝ : List M
tail_ih✝ : (∀ (x : M), x ∈ tail✝ → 1 ≤ x) → ∀ (x : M), x ∈ tail✝ → x ≤ prod tail✝
hl₁ : 1 ≤ head✝ ∧ ∀ (x : M), x ∈ tail✝ → 1 ≤ x
⊢ head✝ ≤ head✝ * prod tail✝
[PROOFSTEP]
exact le_mul_of_one_le_right' (one_le_prod_of_one_le hl₁.2)
[GOAL]
case cons.right
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
head✝ : M
tail✝ : List M
tail_ih✝ : (∀ (x : M), x ∈ tail✝ → 1 ≤ x) → ∀ (x : M), x ∈ tail✝ → x ≤ prod tail✝
hl₁ : 1 ≤ head✝ ∧ ∀ (x : M), x ∈ tail✝ → 1 ≤ x
⊢ ∀ (x : M), x ∈ tail✝ → x ≤ head✝ * prod tail✝
[PROOFSTEP]
case cons.right hd tl ih => exact fun x H => le_mul_of_one_le_of_le hl₁.1 (ih hl₁.right x H)
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
hd : M
tl : List M
ih : (∀ (x : M), x ∈ tl → 1 ≤ x) → ∀ (x : M), x ∈ tl → x ≤ prod tl
hl₁ : 1 ≤ hd ∧ ∀ (x : M), x ∈ tl → 1 ≤ x
⊢ ∀ (x : M), x ∈ tl → x ≤ hd * prod tl
[PROOFSTEP]
case cons.right hd tl ih => exact fun x H => le_mul_of_one_le_of_le hl₁.1 (ih hl₁.right x H)
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : OrderedCommMonoid M
hd : M
tl : List M
ih : (∀ (x : M), x ∈ tl → 1 ≤ x) → ∀ (x : M), x ∈ tl → x ≤ prod tl
hl₁ : 1 ≤ hd ∧ ∀ (x : M), x ∈ tl → 1 ≤ x
⊢ ∀ (x : M), x ∈ tl → x ≤ hd * prod tl
[PROOFSTEP]
exact fun x H => le_mul_of_one_le_of_le hl₁.1 (ih hl₁.right x H)
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : Monoid M
l : List M
hl : ∀ (x : M), x ∈ l → x = 1
⊢ prod l = 1
[PROOFSTEP]
induction' l with i l hil
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : Monoid M
l : List M
hl✝ : ∀ (x : M), x ∈ l → x = 1
hl : ∀ (x : M), x ∈ [] → x = 1
⊢ prod [] = 1
[PROOFSTEP]
rfl
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : Monoid M
l✝ : List M
hl✝ : ∀ (x : M), x ∈ l✝ → x = 1
i : M
l : List M
hil : (∀ (x : M), x ∈ l → x = 1) → prod l = 1
hl : ∀ (x : M), x ∈ i :: l → x = 1
⊢ prod (i :: l) = 1
[PROOFSTEP]
rw [List.prod_cons, hil fun x hx => hl _ (mem_cons_of_mem i hx), hl _ (mem_cons_self i l), one_mul]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : Monoid M
l : List M
h : prod l ≠ 1
⊢ ∃ x, x ∈ l ∧ x ≠ 1
[PROOFSTEP]
simpa only [not_forall, exists_prop] using mt prod_eq_one h
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : AddMonoid M
inst✝¹ : AddMonoid N
inst✝ : LinearOrder N
f : M → N
h0 : f 0 ≤ 0
hadd : ∀ (x y : M), f (x + y) ≤ max (f x) (f y)
l : List M
⊢ f (sum l) ≤ foldr max 0 (map f l)
[PROOFSTEP]
induction' l with hd tl IH
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : AddMonoid M
inst✝¹ : AddMonoid N
inst✝ : LinearOrder N
f : M → N
h0 : f 0 ≤ 0
hadd : ∀ (x y : M), f (x + y) ≤ max (f x) (f y)
⊢ f (sum []) ≤ foldr max 0 (map f [])
[PROOFSTEP]
simpa using h0
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : AddMonoid M
inst✝¹ : AddMonoid N
inst✝ : LinearOrder N
f : M → N
h0 : f 0 ≤ 0
hadd : ∀ (x y : M), f (x + y) ≤ max (f x) (f y)
hd : M
tl : List M
IH : f (sum tl) ≤ foldr max 0 (map f tl)
⊢ f (sum (hd :: tl)) ≤ foldr max 0 (map f (hd :: tl))
[PROOFSTEP]
simp only [List.sum_cons, List.foldr_map, List.foldr] at IH ⊢
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝² : AddMonoid M
inst✝¹ : AddMonoid N
inst✝ : LinearOrder N
f : M → N
h0 : f 0 ≤ 0
hadd : ∀ (x y : M), f (x + y) ≤ max (f x) (f y)
hd : M
tl : List M
IH : f (sum tl) ≤ foldr (fun x y => max (f x) y) 0 tl
⊢ f (hd + sum tl) ≤ max (f hd) (foldr (fun x y => max (f x) y) 0 tl)
[PROOFSTEP]
exact (hadd _ _).trans (max_le_max le_rfl IH)
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝¹ : DecidableEq M
inst✝ : CommMonoid M
a b : M
l : List M
h : a ∈ b :: l
⊢ a * prod (List.erase (b :: l) a) = prod (b :: l)
[PROOFSTEP]
obtain rfl | ⟨ne, h⟩ := Decidable.List.eq_or_ne_mem_of_mem h
[GOAL]
case inl
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝¹ : DecidableEq M
inst✝ : CommMonoid M
a : M
l : List M
h : a ∈ a :: l
⊢ a * prod (List.erase (a :: l) a) = prod (a :: l)
[PROOFSTEP]
simp only [List.erase, if_pos, prod_cons, beq_self_eq_true]
[GOAL]
case inr.intro
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝¹ : DecidableEq M
inst✝ : CommMonoid M
a b : M
l : List M
h✝ : a ∈ b :: l
ne : a ≠ b
h : a ∈ l
⊢ a * prod (List.erase (b :: l) a) = prod (b :: l)
[PROOFSTEP]
simp only [List.erase, beq_false_of_ne ne.symm, prod_cons, prod_erase h, mul_left_comm a b]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝¹ : DecidableEq ι
inst✝ : CommMonoid M
f : ι → M
a b : ι
l : List ι
h : a ∈ b :: l
⊢ f a * prod (map f (List.erase (b :: l) a)) = prod (map f (b :: l))
[PROOFSTEP]
obtain rfl | ⟨ne, h⟩ := Decidable.List.eq_or_ne_mem_of_mem h
[GOAL]
case inl
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝¹ : DecidableEq ι
inst✝ : CommMonoid M
f : ι → M
a : ι
l : List ι
h : a ∈ a :: l
⊢ f a * prod (map f (List.erase (a :: l) a)) = prod (map f (a :: l))
[PROOFSTEP]
simp only [map, erase_cons_head, prod_cons]
[GOAL]
case inr.intro
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝¹ : DecidableEq ι
inst✝ : CommMonoid M
f : ι → M
a b : ι
l : List ι
h✝ : a ∈ b :: l
ne : a ≠ b
h : a ∈ l
⊢ f a * prod (map f (List.erase (b :: l) a)) = prod (map f (b :: l))
[PROOFSTEP]
simp only [map, erase_cons_tail _ ne.symm, prod_cons, prod_map_erase _ h, mul_left_comm (f a) (f b)]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : StrictOrderedSemiring R
l : List R
h : ∀ (a : R), a ∈ l → 0 < a
⊢ 0 < prod l
[PROOFSTEP]
induction' l with a l ih
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : StrictOrderedSemiring R
l : List R
h✝ : ∀ (a : R), a ∈ l → 0 < a
h : ∀ (a : R), a ∈ [] → 0 < a
⊢ 0 < prod []
[PROOFSTEP]
simp
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : StrictOrderedSemiring R
l✝ : List R
h✝ : ∀ (a : R), a ∈ l✝ → 0 < a
a : R
l : List R
ih : (∀ (a : R), a ∈ l → 0 < a) → 0 < prod l
h : ∀ (a_1 : R), a_1 ∈ a :: l → 0 < a_1
⊢ 0 < prod (a :: l)
[PROOFSTEP]
rw [prod_cons]
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : StrictOrderedSemiring R
l✝ : List R
h✝ : ∀ (a : R), a ∈ l✝ → 0 < a
a : R
l : List R
ih : (∀ (a : R), a ∈ l → 0 < a) → 0 < prod l
h : ∀ (a_1 : R), a_1 ∈ a :: l → 0 < a_1
⊢ 0 < a * prod l
[PROOFSTEP]
exact mul_pos (h _ <| mem_cons_self _ _) (ih fun a ha => h a <| mem_cons_of_mem _ ha)
[GOAL]
ι : Type u_1
α✝ : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
α : Type u_9
inst✝¹ : CanonicallyOrderedCommSemiring α
inst✝ : Nontrivial α
⊢ 0 < prod [] ↔ ∀ (x : α), x ∈ [] → 0 < x
[PROOFSTEP]
simp
[GOAL]
ι : Type u_1
α✝ : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
α : Type u_9
inst✝¹ : CanonicallyOrderedCommSemiring α
inst✝ : Nontrivial α
x : α
xs : List α
⊢ 0 < prod (x :: xs) ↔ ∀ (x_1 : α), x_1 ∈ x :: xs → 0 < x_1
[PROOFSTEP]
simp_rw [prod_cons, forall_mem_cons, CanonicallyOrderedCommSemiring.mul_pos, list_prod_pos]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
L : List ℕ
⊢ headI L + sum (tail L) = sum L
[PROOFSTEP]
cases L
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
⊢ headI [] + sum (tail []) = sum []
[PROOFSTEP]
simp
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
head✝ : ℕ
tail✝ : List ℕ
⊢ headI (head✝ :: tail✝) + sum (tail (head✝ :: tail✝)) = sum (head✝ :: tail✝)
[PROOFSTEP]
simp
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
L : List ℕ
⊢ sum (tail L) = sum L - headI L
[PROOFSTEP]
rw [← headI_add_tail_sum L, add_comm, @add_tsub_cancel_right]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : DivInvMonoid α
a b : α
l : List α
⊢ alternatingProd (a :: b :: l) = a / b * alternatingProd l
[PROOFSTEP]
rw [div_eq_mul_inv, alternatingProd_cons_cons']
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : CommGroup α
a : α
⊢ alternatingProd [a] = a * (alternatingProd [])⁻¹
[PROOFSTEP]
rw [alternatingProd_nil, inv_one, mul_one, alternatingProd_singleton]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : CommGroup α
a b : α
l : List α
⊢ alternatingProd (a :: b :: l) = a * (alternatingProd (b :: l))⁻¹
[PROOFSTEP]
rw [alternatingProd_cons_cons', alternatingProd_cons' b l, mul_inv, inv_inv, mul_assoc]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
inst✝ : CommGroup α
a : α
l : List α
⊢ alternatingProd (a :: l) = a / alternatingProd l
[PROOFSTEP]
rw [div_eq_mul_inv, alternatingProd_cons']
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
l : List ℕ
n : ℕ
⊢ sum l % n = sum (map (fun x => x % n) l) % n
[PROOFSTEP]
induction l
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
n : ℕ
⊢ sum [] % n = sum (map (fun x => x % n) []) % n
[PROOFSTEP]
simp [Nat.add_mod, *]
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
n head✝ : ℕ
tail✝ : List ℕ
tail_ih✝ : sum tail✝ % n = sum (map (fun x => x % n) tail✝) % n
⊢ sum (head✝ :: tail✝) % n = sum (map (fun x => x % n) (head✝ :: tail✝)) % n
[PROOFSTEP]
simp [Nat.add_mod, *]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
l : List ℕ
n : ℕ
⊢ prod l % n = prod (map (fun x => x % n) l) % n
[PROOFSTEP]
induction l
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
n : ℕ
⊢ prod [] % n = prod (map (fun x => x % n) []) % n
[PROOFSTEP]
simp [Nat.mul_mod, *]
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
n head✝ : ℕ
tail✝ : List ℕ
tail_ih✝ : prod tail✝ % n = prod (map (fun x => x % n) tail✝) % n
⊢ prod (head✝ :: tail✝) % n = prod (map (fun x => x % n) (head✝ :: tail✝)) % n
[PROOFSTEP]
simp [Nat.mul_mod, *]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
l : List ℤ
n : ℤ
⊢ sum l % n = sum (map (fun x => x % n) l) % n
[PROOFSTEP]
induction l
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
n : ℤ
⊢ sum [] % n = sum (map (fun x => x % n) []) % n
[PROOFSTEP]
simp [Int.add_emod, *]
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
n head✝ : ℤ
tail✝ : List ℤ
tail_ih✝ : sum tail✝ % n = sum (map (fun x => x % n) tail✝) % n
⊢ sum (head✝ :: tail✝) % n = sum (map (fun x => x % n) (head✝ :: tail✝)) % n
[PROOFSTEP]
simp [Int.add_emod, *]
[GOAL]
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
l : List ℤ
n : ℤ
⊢ prod l % n = prod (map (fun x => x % n) l) % n
[PROOFSTEP]
induction l
[GOAL]
case nil
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
n : ℤ
⊢ prod [] % n = prod (map (fun x => x % n) []) % n
[PROOFSTEP]
simp [Int.mul_emod, *]
[GOAL]
case cons
ι : Type u_1
α : Type u_2
M : Type u_3
N : Type u_4
P : Type u_5
M₀ : Type u_6
G : Type u_7
R : Type u_8
n head✝ : ℤ
tail✝ : List ℤ
tail_ih✝ : prod tail✝ % n = prod (map (fun x => x % n) tail✝) % n
⊢ prod (head✝ :: tail✝) % n = prod (map (fun x => x % n) (head✝ :: tail✝)) % n
[PROOFSTEP]
simp [Int.mul_emod, *]