l3lab/ntp-mathlib huggingface dataset:
theorem nth_mul_coeff (n : ℕ) :
    ∃ f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k,
    ∀ x y : 𝕎 k, (x * y).coeff (n + 1) =
      x.coeff (n + 1) * y.coeff 0 ^ p ^ (n + 1) + y.coeff (n + 1) * x.coeff 0 ^ p ^ (n + 1) +
      f (truncateFun (n + 1) x) (truncateFun (n + 1) y) := by
  obtain ⟨f, hf⟩ := nth_mul_coeff' p k n
  use f
  intro x y
  rw [hf x y]
  

Proof state:
case h
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k
hf :
  ∀ (x y : 𝕎 k),
    f (truncateFun (n + 1) x) (truncateFun (n + 1) y) =
      coeff (x * y) (n + 1) - coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) - coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1)
x y : 𝕎 k
⊢ coeff (x * y) (n + 1) =
    coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1) + coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) +
      (coeff (x * y) (n + 1) - coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) - coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1))

Next tactic:
ring
theorem norm_exp_ofReal_mul_I (t : ℝ) : ‖exp (t * I)‖ = 1 := by
  

Proof state:
t : ℝ
⊢ ‖cexp (↑t * I)‖ = 1

Next tactic:
simp only [norm_eq_abs, abs_exp_ofReal_mul_I]
instance : DenselyNormedField ℂ where
  lt_norm_lt r₁ r₂ h₀ hr :=
    let ⟨x, h⟩ := exists_between hr
    ⟨x, by 

Proof state:
r₁ r₂ : ℝ
h₀ : 0 ≤ r₁
hr : r₁ < r₂
x : ℝ
h : r₁ < x ∧ x < r₂
⊢ r₁ < ‖↑x‖ ∧ ‖↑x‖ < r₂

Next tactic:
rwa [norm_eq_abs, abs_ofReal, abs_of_pos (h₀.trans_lt h.1)]
instance {R : Type*} [NormedField R] [NormedAlgebra R ℝ] : NormedAlgebra R ℂ where
  norm_smul_le r x := by
    

Proof state:
R : Type u_1
inst✝¹ : NormedField R
inst✝ : NormedAlgebra R ℝ
r : R
x : ℂ
⊢ ‖r • x‖ ≤ ‖r‖ * ‖x‖

Next tactic:
rw [← algebraMap_smul ℝ r x, real_smul, norm_mul, norm_eq_abs, abs_ofReal, ← Real.norm_eq_abs,
      norm_algebraMap']
theorem dist_eq_re_im (z w : ℂ) : dist z w = Real.sqrt ((z.re - w.re) ^ 2 + (z.im - w.im) ^ 2) := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
z w : ℂ
⊢ dist z w = Real.sqrt ((z.re - w.re) ^ 2 + (z.im - w.im) ^ 2)

Next tactic:
rw [sq, sq]
theorem dist_eq_re_im (z w : ℂ) : dist z w = Real.sqrt ((z.re - w.re) ^ 2 + (z.im - w.im) ^ 2) := by
  rw [sq, sq]
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
z w : ℂ
⊢ dist z w = Real.sqrt ((z.re - w.re) * (z.re - w.re) + (z.im - w.im) * (z.im - w.im))

Next tactic:
rfl
theorem dist_of_re_eq {z w : ℂ} (h : z.re = w.re) : dist z w = dist z.im w.im := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
z w : ℂ
h : z.re = w.re
⊢ dist z w = dist z.im w.im

Next tactic:
rw [dist_eq_re_im, h, sub_self, zero_pow two_pos, zero_add, Real.sqrt_sq_eq_abs, Real.dist_eq]
theorem edist_of_re_eq {z w : ℂ} (h : z.re = w.re) : edist z w = edist z.im w.im := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
z w : ℂ
h : z.re = w.re
⊢ edist z w = edist z.im w.im

Next tactic:
rw [edist_nndist, edist_nndist, nndist_of_re_eq h]
theorem dist_of_im_eq {z w : ℂ} (h : z.im = w.im) : dist z w = dist z.re w.re := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
z w : ℂ
h : z.im = w.im
⊢ dist z w = dist z.re w.re

Next tactic:
rw [dist_eq_re_im, h, sub_self, zero_pow two_pos, add_zero, Real.sqrt_sq_eq_abs, Real.dist_eq]
theorem edist_of_im_eq {z w : ℂ} (h : z.im = w.im) : edist z w = edist z.re w.re := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
z w : ℂ
h : z.im = w.im
⊢ edist z w = edist z.re w.re

Next tactic:
rw [edist_nndist, edist_nndist, nndist_of_im_eq h]
theorem dist_conj_self (z : ℂ) : dist (conj z) z = 2 * |z.im| := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
z : ℂ
⊢ dist ((starRingEnd ℂ) z) z = 2 * |z.im|

Next tactic:
rw [dist_of_re_eq (conj_re z), conj_im, dist_comm, Real.dist_eq, sub_neg_eq_add, ← two_mul,
    _root_.abs_mul, abs_of_pos (zero_lt_two' ℝ)]
theorem nndist_conj_self (z : ℂ) : nndist (conj z) z = 2 * Real.nnabs z.im :=
  NNReal.eq <| by 

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
z : ℂ
⊢ ↑(nndist ((starRingEnd ℂ) z) z) = ↑(2 * Real.nnabs z.im)

Next tactic:
rw [← dist_nndist, NNReal.coe_mul, NNReal.coe_two, Real.coe_nnabs, dist_conj_self]
theorem dist_self_conj (z : ℂ) : dist z (conj z) = 2 * |z.im| := by 

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
z : ℂ
⊢ dist z ((starRingEnd ℂ) z) = 2 * |z.im|

Next tactic:
rw [dist_comm, dist_conj_self]
theorem nndist_self_conj (z : ℂ) : nndist z (conj z) = 2 * Real.nnabs z.im := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
z : ℂ
⊢ nndist z ((starRingEnd ℂ) z) = 2 * Real.nnabs z.im

Next tactic:
rw [nndist_comm, nndist_conj_self]
@[simp 1100]
theorem norm_rat (r : ℚ) : ‖(r : ℂ)‖ = |(r : ℝ)| := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
r : ℚ
⊢ ‖↑r‖ = |↑r|

Next tactic:
rw [← ofReal_rat_cast]
@[simp 1100]
theorem norm_rat (r : ℚ) : ‖(r : ℂ)‖ = |(r : ℝ)| := by
  rw [← ofReal_rat_cast]
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
r : ℚ
⊢ ‖↑↑r‖ = |↑r|

Next tactic:
exact norm_real _
theorem norm_int_of_nonneg {n : ℤ} (hn : 0 ≤ n) : ‖(n : ℂ)‖ = n := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
n : ℤ
hn : 0 ≤ n
⊢ ‖↑n‖ = ↑n

Next tactic:
rw [norm_int, ← Int.cast_abs, _root_.abs_of_nonneg hn]
@[continuity]
theorem continuous_normSq : Continuous normSq := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
⊢ Continuous ⇑normSq

Next tactic:
simpa [← normSq_eq_abs] using continuous_abs.pow 2
@[simp, norm_cast]
theorem nnnorm_nat (n : ℕ) : ‖(n : ℂ)‖₊ = n :=
  Subtype.ext <| by 

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
n : ℕ
⊢ ↑‖↑n‖₊ = ↑↑n

Next tactic:
simp
theorem nnnorm_eq_one_of_pow_eq_one {ζ : ℂ} {n : ℕ} (h : ζ ^ n = 1) (hn : n ≠ 0) : ‖ζ‖₊ = 1 :=
  (pow_left_inj zero_le' zero_le' hn).1 $ by 

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
ζ : ℂ
n : ℕ
h : ζ ^ n = 1
hn : n ≠ 0
⊢ ‖ζ‖₊ ^ n = 1 ^ n

Next tactic:
rw [← nnnorm_pow, h, nnnorm_one, one_pow]
theorem equivRealProd_apply_le (z : ℂ) : ‖equivRealProd z‖ ≤ abs z := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
z : ℂ
⊢ ‖equivRealProd z‖ ≤ abs z

Next tactic:
simp [Prod.norm_def, abs_re_le_abs, abs_im_le_abs]
theorem equivRealProd_apply_le' (z : ℂ) : ‖equivRealProd z‖ ≤ 1 * abs z := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
z : ℂ
⊢ ‖equivRealProd z‖ ≤ 1 * abs z

Next tactic:
simpa using equivRealProd_apply_le z
theorem lipschitz_equivRealProd : LipschitzWith 1 equivRealProd := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
⊢ LipschitzWith 1 ⇑equivRealProd

Next tactic:
simpa using AddMonoidHomClass.lipschitz_of_bound equivRealProdLm 1 equivRealProd_apply_le'
theorem antilipschitz_equivRealProd : AntilipschitzWith (NNReal.sqrt 2) equivRealProd :=
  AddMonoidHomClass.antilipschitz_of_bound equivRealProdLm fun z ↦ by
    

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
z : ℂ
⊢ ‖z‖ ≤ ↑(NNReal.sqrt 2) * ‖equivRealProdLm z‖

Next tactic:
simpa only [Real.coe_sqrt, NNReal.coe_ofNat] using abs_le_sqrt_two_mul_max z
/-- The `normSq` function on `ℂ` is proper. -/
theorem tendsto_normSq_cocompact_atTop : Tendsto normSq (cocompact ℂ) atTop :=
  by 

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
⊢ Tendsto (⇑normSq) (cocompact ℂ) atTop

Next tactic:
simpa [mul_self_abs]
    using tendsto_abs_cocompact_atTop.atTop_mul_atTop tendsto_abs_cocompact_atTop
/-- Continuous linear map version of the real part function, from `ℂ` to `ℝ`. -/
def reClm : ℂ →L[ℝ] ℝ :=
  reLm.mkContinuous 1 fun x => by 

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
x : ℂ
⊢ ‖reLm x‖ ≤ 1 * ‖x‖

Next tactic:
simp [abs_re_le_abs]
/-- Continuous linear map version of the imaginary part function, from `ℂ` to `ℝ`. -/
def imClm : ℂ →L[ℝ] ℝ :=
  imLm.mkContinuous 1 fun x => by 

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
x : ℂ
⊢ ‖imLm x‖ ≤ 1 * ‖x‖

Next tactic:
simp [abs_im_le_abs]
theorem restrictScalars_one_smulRight' (x : E) :
    ContinuousLinearMap.restrictScalars ℝ ((1 : ℂ →L[ℂ] ℂ).smulRight x : ℂ →L[ℂ] E) =
      reClm.smulRight x + I • imClm.smulRight x := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
x : E
⊢ restrictScalars ℝ (smulRight 1 x) = smulRight reClm x + I • smulRight imClm x

Next tactic:
ext ⟨a, b⟩
theorem restrictScalars_one_smulRight' (x : E) :
    ContinuousLinearMap.restrictScalars ℝ ((1 : ℂ →L[ℂ] ℂ).smulRight x : ℂ →L[ℂ] E) =
      reClm.smulRight x + I • imClm.smulRight x := by
  ext ⟨a, b⟩
  

Proof state:
case h.mk
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
x : E
a b : ℝ
⊢ (restrictScalars ℝ (smulRight 1 x)) { re := a, im := b } =
    (smulRight reClm x + I • smulRight imClm x) { re := a, im := b }

Next tactic:
simp [mk_eq_add_mul_I, mul_smul, smul_comm I b x]
theorem restrictScalars_one_smulRight (x : ℂ) :
    ContinuousLinearMap.restrictScalars ℝ ((1 : ℂ →L[ℂ] ℂ).smulRight x : ℂ →L[ℂ] ℂ) =
    x • (1 : ℂ →L[ℝ] ℂ) := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
x : ℂ
⊢ restrictScalars ℝ (smulRight 1 x) = x • 1

Next tactic:
ext1 z
theorem restrictScalars_one_smulRight (x : ℂ) :
    ContinuousLinearMap.restrictScalars ℝ ((1 : ℂ →L[ℂ] ℂ).smulRight x : ℂ →L[ℂ] ℂ) =
    x • (1 : ℂ →L[ℝ] ℂ) := by
  ext1 z
  

Proof state:
case h
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
x z : ℂ
⊢ (restrictScalars ℝ (smulRight 1 x)) z = (x • 1) z

Next tactic:
dsimp
theorem restrictScalars_one_smulRight (x : ℂ) :
    ContinuousLinearMap.restrictScalars ℝ ((1 : ℂ →L[ℂ] ℂ).smulRight x : ℂ →L[ℂ] ℂ) =
    x • (1 : ℂ →L[ℝ] ℂ) := by
  ext1 z
  dsimp
  

Proof state:
case h
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
x z : ℂ
⊢ z * x = x * z

Next tactic:
apply mul_comm
theorem dist_conj_comm (z w : ℂ) : dist (conj z) w = dist z (conj w) := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
z w : ℂ
⊢ dist ((starRingEnd ℂ) z) w = dist z ((starRingEnd ℂ) w)

Next tactic:
rw [← dist_conj_conj, conj_conj]
/-- The only continuous ring homomorphisms from `ℂ` to `ℂ` are the identity and the complex
conjugation. -/
theorem ringHom_eq_id_or_conj_of_continuous {f : ℂ →+* ℂ} (hf : Continuous f) :
    f = RingHom.id ℂ ∨ f = conj := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
f : ℂ →+* ℂ
hf : Continuous ⇑f
⊢ f = RingHom.id ℂ ∨ f = starRingEnd ℂ

Next tactic:
simpa only [FunLike.ext_iff] using real_algHom_eq_id_or_conj (AlgHom.mk' f (map_real_smul f hf))
/-- The only continuous ring homomorphism from `ℝ` to `ℂ` is the identity. -/
theorem ringHom_eq_ofReal_of_continuous {f : ℝ →+* ℂ} (h : Continuous f) : f = Complex.ofReal := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
f : ℝ →+* ℂ
h : Continuous ⇑f
⊢ f = ofReal

Next tactic:
convert congr_arg AlgHom.toRingHom <| Subsingleton.elim (AlgHom.mk' f <| map_real_smul f h)
    (Algebra.ofId ℝ ℂ)
theorem eq_coe_norm_of_nonneg {z : ℂ} (hz : 0 ≤ z) : z = ↑‖z‖ := by
  

Proof state:
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
z : ℂ
hz : 0 ≤ z
⊢ z = ↑‖z‖

Next tactic:
lift z to ℝ using hz.2.symm
theorem eq_coe_norm_of_nonneg {z : ℂ} (hz : 0 ≤ z) : z = ↑‖z‖ := by
  lift z to ℝ using hz.2.symm
  

Proof state:
case intro
E : Type u_1
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace ℂ E
z : ℝ
hz : 0 ≤ ↑z
⊢ ↑z = ↑‖↑z‖

Next tactic:
rw [norm_eq_abs, abs_ofReal, _root_.abs_of_nonneg (id hz.1 : 0 ≤ z)]
@[simp, norm_cast]
theorem hasSum_ofReal {f : α → ℝ} {x : ℝ} : HasSum (fun x => (f x : 𝕜)) x ↔ HasSum f x :=
  ⟨fun h => by 

Proof state:
α : Type u_1
𝕜 : Type u_2
inst✝ : IsROrC 𝕜
f : α → ℝ
x : ℝ
h : HasSum (fun x => ↑(f x)) ↑x
⊢ HasSum f x

Next tactic:
simpa only [IsROrC.reClm_apply, IsROrC.ofReal_re] using reClm.hasSum h
@[simp, norm_cast]
theorem summable_ofReal {f : α → ℝ} : (Summable fun x => (f x : 𝕜)) ↔ Summable f :=
  ⟨fun h => by 

Proof state:
α : Type u_1
𝕜 : Type u_2
inst✝ : IsROrC 𝕜
f : α → ℝ
h : Summable fun x => ↑(f x)
⊢ Summable f

Next tactic:
simpa only [IsROrC.reClm_apply, IsROrC.ofReal_re] using reClm.summable h
@[norm_cast]
theorem ofReal_tsum (f : α → ℝ) : (↑(∑' a, f a) : 𝕜) = ∑' a, (f a : 𝕜) := by
  

Proof state:
α : Type u_1
𝕜 : Type u_2
inst✝ : IsROrC 𝕜
f : α → ℝ
⊢ ↑(∑' (a : α), f a) = ∑' (a : α), ↑(f a)

Next tactic:
by_cases h : Summable f
@[norm_cast]
theorem ofReal_tsum (f : α → ℝ) : (↑(∑' a, f a) : 𝕜) = ∑' a, (f a : 𝕜) := by
  by_cases h : Summable f
  · 

Proof state:
case pos
α : Type u_1
𝕜 : Type u_2
inst✝ : IsROrC 𝕜
f : α → ℝ
h : Summable f
⊢ ↑(∑' (a : α), f a) = ∑' (a : α), ↑(f a)

Next tactic:
exact ContinuousLinearMap.map_tsum ofRealClm h
@[norm_cast]
theorem ofReal_tsum (f : α → ℝ) : (↑(∑' a, f a) : 𝕜) = ∑' a, (f a : 𝕜) := by
  by_cases h : Summable f
  · exact ContinuousLinearMap.map_tsum ofRealClm h
  · 

Proof state:
case neg
α : Type u_1
𝕜 : Type u_2
inst✝ : IsROrC 𝕜
f : α → ℝ
h : ¬Summable f
⊢ ↑(∑' (a : α), f a) = ∑' (a : α), ↑(f a)

Next tactic:
rw [tsum_eq_zero_of_not_summable h,
      tsum_eq_zero_of_not_summable ((summable_ofReal _).not.mpr h), ofReal_zero]
theorem hasSum_iff (f : α → 𝕜) (c : 𝕜) :
    HasSum f c ↔ HasSum (fun x => re (f x)) (re c) ∧ HasSum (fun x => im (f x)) (im c) := by
  

Proof state:
α : Type u_1
𝕜 : Type u_2
inst✝ : IsROrC 𝕜
f : α → 𝕜
c : 𝕜
⊢ HasSum f c ↔ HasSum (fun x => re (f x)) (re c) ∧ HasSum (fun x => im (f x)) (im c)

Next tactic:
refine' ⟨fun h => ⟨hasSum_re _ h, hasSum_im _ h⟩, _⟩
theorem hasSum_iff (f : α → 𝕜) (c : 𝕜) :
    HasSum f c ↔ HasSum (fun x => re (f x)) (re c) ∧ HasSum (fun x => im (f x)) (im c) := by
  refine' ⟨fun h => ⟨hasSum_re _ h, hasSum_im _ h⟩, _⟩
  

Proof state:
α : Type u_1
𝕜 : Type u_2
inst✝ : IsROrC 𝕜
f : α → 𝕜
c : 𝕜
⊢ HasSum (fun x => re (f x)) (re c) ∧ HasSum (fun x => im (f x)) (im c) → HasSum f c

Next tactic:
rintro ⟨h₁, h₂⟩
theorem hasSum_iff (f : α → 𝕜) (c : 𝕜) :
    HasSum f c ↔ HasSum (fun x => re (f x)) (re c) ∧ HasSum (fun x => im (f x)) (im c) := by
  refine' ⟨fun h => ⟨hasSum_re _ h, hasSum_im _ h⟩, _⟩
  rintro ⟨h₁, h₂⟩
  

Proof state:
case intro
α : Type u_1
𝕜 : Type u_2
inst✝ : IsROrC 𝕜
f : α → 𝕜
c : 𝕜
h₁ : HasSum (fun x => re (f x)) (re c)
h₂ : HasSum (fun x => im (f x)) (im c)
⊢ HasSum f c

Next tactic:
simpa only [re_add_im] using
    ((hasSum_ofReal 𝕜).mpr h₁).add (((hasSum_ofReal 𝕜).mpr h₂).mul_right I)
theorem subset_product_image_fst [DecidableEq α] : (s ×ˢ t).image Prod.fst ⊆ s := fun i => by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s s' : Finset α
t t' : Finset β
a : α
b : β
inst✝ : DecidableEq α
i : α
⊢ i ∈ image Prod.fst (s ×ˢ t) → i ∈ s

Next tactic:
simp (config := { contextual := true }) [mem_image]
theorem subset_product_image_snd [DecidableEq β] : (s ×ˢ t).image Prod.snd ⊆ t := fun i => by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s s' : Finset α
t t' : Finset β
a : α
b : β
inst✝ : DecidableEq β
i : β
⊢ i ∈ image Prod.snd (s ×ˢ t) → i ∈ t

Next tactic:
simp (config := { contextual := true }) [mem_image]
theorem product_image_fst [DecidableEq α] (ht : t.Nonempty) : (s ×ˢ t).image Prod.fst = s := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s s' : Finset α
t t' : Finset β
a : α
b : β
inst✝ : DecidableEq α
ht : Finset.Nonempty t
⊢ image Prod.fst (s ×ˢ t) = s

Next tactic:
ext i
theorem product_image_fst [DecidableEq α] (ht : t.Nonempty) : (s ×ˢ t).image Prod.fst = s := by
  ext i
  

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
s s' : Finset α
t t' : Finset β
a : α
b : β
inst✝ : DecidableEq α
ht : Finset.Nonempty t
i : α
⊢ i ∈ image Prod.fst (s ×ˢ t) ↔ i ∈ s

Next tactic:
simp [mem_image, ht.bex]
theorem product_image_snd [DecidableEq β] (ht : s.Nonempty) : (s ×ˢ t).image Prod.snd = t := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s s' : Finset α
t t' : Finset β
a : α
b : β
inst✝ : DecidableEq β
ht : Finset.Nonempty s
⊢ image Prod.snd (s ×ˢ t) = t

Next tactic:
ext i
theorem product_image_snd [DecidableEq β] (ht : s.Nonempty) : (s ×ˢ t).image Prod.snd = t := by
  ext i
  

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
s s' : Finset α
t t' : Finset β
a : α
b : β
inst✝ : DecidableEq β
ht : Finset.Nonempty s
i : β
⊢ i ∈ image Prod.snd (s ×ˢ t) ↔ i ∈ t

Next tactic:
simp [mem_image, ht.bex]
theorem map_swap_product (s : Finset α) (t : Finset β) :
    (t ×ˢ s).map ⟨Prod.swap, Prod.swap_injective⟩ = s ×ˢ t :=
  coe_injective <| by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s✝ s' : Finset α
t✝ t' : Finset β
a : α
b : β
s : Finset α
t : Finset β
⊢ ↑(map { toFun := Prod.swap, inj' := (_ : Function.Injective Prod.swap) } (t ×ˢ s)) = ↑(s ×ˢ t)

Next tactic:
push_cast
theorem map_swap_product (s : Finset α) (t : Finset β) :
    (t ×ˢ s).map ⟨Prod.swap, Prod.swap_injective⟩ = s ×ˢ t :=
  coe_injective <| by
    push_cast
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s✝ s' : Finset α
t✝ t' : Finset β
a : α
b : β
s : Finset α
t : Finset β
⊢ ⇑{ toFun := Prod.swap, inj' := (_ : Function.Injective Prod.swap) } '' ↑t ×ˢ ↑s = ↑s ×ˢ ↑t

Next tactic:
exact Set.image_swap_prod _ _
@[simp]
theorem image_swap_product [DecidableEq (α × β)] (s : Finset α) (t : Finset β) :
    (t ×ˢ s).image Prod.swap = s ×ˢ t :=
  coe_injective <| by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s✝ s' : Finset α
t✝ t' : Finset β
a : α
b : β
inst✝ : DecidableEq (α × β)
s : Finset α
t : Finset β
⊢ ↑(image Prod.swap (t ×ˢ s)) = ↑(s ×ˢ t)

Next tactic:
push_cast
@[simp]
theorem image_swap_product [DecidableEq (α × β)] (s : Finset α) (t : Finset β) :
    (t ×ˢ s).image Prod.swap = s ×ˢ t :=
  coe_injective <| by
    push_cast
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s✝ s' : Finset α
t✝ t' : Finset β
a : α
b : β
inst✝ : DecidableEq (α × β)
s : Finset α
t : Finset β
⊢ Prod.swap '' ↑t ×ˢ ↑s = ↑s ×ˢ ↑t

Next tactic:
exact Set.image_swap_prod _ _
theorem product_eq_biUnion [DecidableEq (α × β)] (s : Finset α) (t : Finset β) :
    s ×ˢ t = s.biUnion fun a => t.image fun b => (a, b) :=
  ext fun ⟨x, y⟩ => by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s✝ s' : Finset α
t✝ t' : Finset β
a : α
b : β
inst✝ : DecidableEq (α × β)
s : Finset α
t : Finset β
x✝ : α × β
x : α
y : β
⊢ (x, y) ∈ s ×ˢ t ↔ (x, y) ∈ Finset.biUnion s fun a => image (fun b => (a, b)) t

Next tactic:
simp only [mem_product, mem_biUnion, mem_image, exists_prop, Prod.mk.inj_iff, and_left_comm,
      exists_and_left, exists_eq_right, exists_eq_left]
theorem product_eq_biUnion_right [DecidableEq (α × β)] (s : Finset α) (t : Finset β) :
    s ×ˢ t = t.biUnion fun b => s.image fun a => (a, b) :=
  ext fun ⟨x, y⟩ => by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s✝ s' : Finset α
t✝ t' : Finset β
a : α
b : β
inst✝ : DecidableEq (α × β)
s : Finset α
t : Finset β
x✝ : α × β
x : α
y : β
⊢ (x, y) ∈ s ×ˢ t ↔ (x, y) ∈ Finset.biUnion t fun b => image (fun a => (a, b)) s

Next tactic:
simp only [mem_product, mem_biUnion, mem_image, exists_prop, Prod.mk.inj_iff, and_left_comm,
      exists_and_left, exists_eq_right, exists_eq_left]
/-- See also `Finset.sup_product_left`. -/
@[simp]
theorem product_biUnion [DecidableEq γ] (s : Finset α) (t : Finset β) (f : α × β → Finset γ) :
    (s ×ˢ t).biUnion f = s.biUnion fun a => t.biUnion fun b => f (a, b) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s✝ s' : Finset α
t✝ t' : Finset β
a : α
b : β
inst✝ : DecidableEq γ
s : Finset α
t : Finset β
f : α × β → Finset γ
⊢ Finset.biUnion (s ×ˢ t) f = Finset.biUnion s fun a => Finset.biUnion t fun b => f (a, b)

Next tactic:
classical simp_rw [product_eq_biUnion, biUnion_biUnion, image_biUnion]
/-- See also `Finset.sup_product_left`. -/
@[simp]
theorem product_biUnion [DecidableEq γ] (s : Finset α) (t : Finset β) (f : α × β → Finset γ) :
    (s ×ˢ t).biUnion f = s.biUnion fun a => t.biUnion fun b => f (a, b) := by
  classical 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s✝ s' : Finset α
t✝ t' : Finset β
a : α
b : β
inst✝ : DecidableEq γ
s : Finset α
t : Finset β
f : α × β → Finset γ
⊢ Finset.biUnion (s ×ˢ t) f = Finset.biUnion s fun a => Finset.biUnion t fun b => f (a, b)

Next tactic:
simp_rw [product_eq_biUnion, biUnion_biUnion, image_biUnion]
/-- The product of two Finsets is nontrivial iff both are nonempty
  at least one of them is nontrivial. -/
lemma nontrivial_prod_iff : Nontrivial (s ×ˢ t) ↔
    s.Nonempty ∧ t.Nonempty ∧ (Nontrivial s ∨ Nontrivial t) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s s' : Finset α
t t' : Finset β
a : α
b : β
⊢ Nontrivial { x // x ∈ s ×ˢ t } ↔
    Finset.Nonempty s ∧ Finset.Nonempty t ∧ (Nontrivial { x // x ∈ s } ∨ Nontrivial { x // x ∈ t })

Next tactic:
simp_rw [← card_pos, ← one_lt_card_iff_nontrivial_coe, card_product]
/-- The product of two Finsets is nontrivial iff both are nonempty
  at least one of them is nontrivial. -/
lemma nontrivial_prod_iff : Nontrivial (s ×ˢ t) ↔
    s.Nonempty ∧ t.Nonempty ∧ (Nontrivial s ∨ Nontrivial t) := by
  simp_rw [← card_pos, ← one_lt_card_iff_nontrivial_coe, card_product]; 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s s' : Finset α
t t' : Finset β
a : α
b : β
⊢ 1 < card s * card t ↔ 0 < card s ∧ 0 < card t ∧ (1 < card s ∨ 1 < card t)

Next tactic:
apply Nat.one_lt_mul_iff
theorem filter_product (p : α → Prop) (q : β → Prop) [DecidablePred p] [DecidablePred q] :
    ((s ×ˢ t).filter fun x : α × β => p x.1 ∧ q x.2) = s.filter p ×ˢ t.filter q := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s s' : Finset α
t t' : Finset β
a : α
b : β
p : α → Prop
q : β → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
⊢ filter (fun x => p x.1 ∧ q x.2) (s ×ˢ t) = filter p s ×ˢ filter q t

Next tactic:
ext ⟨a, b⟩
theorem filter_product (p : α → Prop) (q : β → Prop) [DecidablePred p] [DecidablePred q] :
    ((s ×ˢ t).filter fun x : α × β => p x.1 ∧ q x.2) = s.filter p ×ˢ t.filter q := by
  ext ⟨a, b⟩
  

Proof state:
case a.mk
α : Type u_1
β : Type u_2
γ : Type u_3
s s' : Finset α
t t' : Finset β
a✝ : α
b✝ : β
p : α → Prop
q : β → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
a : α
b : β
⊢ (a, b) ∈ filter (fun x => p x.1 ∧ q x.2) (s ×ˢ t) ↔ (a, b) ∈ filter p s ×ˢ filter q t

Next tactic:
simp [mem_filter, mem_product, decide_eq_true_eq, and_comm, and_left_comm, and_assoc]
theorem filter_product_left (p : α → Prop) [DecidablePred p] :
    ((s ×ˢ t).filter fun x : α × β => p x.1) = s.filter p ×ˢ t := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s s' : Finset α
t t' : Finset β
a : α
b : β
p : α → Prop
inst✝ : DecidablePred p
⊢ filter (fun x => p x.1) (s ×ˢ t) = filter p s ×ˢ t

Next tactic:
simpa using filter_product p fun _ => true
theorem filter_product_right (q : β → Prop) [DecidablePred q] :
    ((s ×ˢ t).filter fun x : α × β => q x.2) = s ×ˢ t.filter q := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
s s' : Finset α
t t' : Finset β
a : α
b : β
q : β → Prop
inst✝ : DecidablePred q
⊢ filter (fun x => q x.2) (s ×ˢ t) = s ×ˢ filter q t

Next tactic:
simpa using filter_product (fun _ : α => true) q