l3lab/ntp-mathlib huggingface dataset:
lemma add_scaleRoots_of_natDegree_eq (p q : R[X]) (r : R) (h : natDegree p = natDegree q) :
    r ^ (natDegree p - natDegree (p + q)) • (p + q).scaleRoots r =
      p.scaleRoots r + q.scaleRoots r := by
  ext n; 

Proof state:
case a
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
h : natDegree p = natDegree q
n : ℕ
⊢ coeff (r ^ (natDegree p - natDegree (p + q)) • scaleRoots (p + q) r) n = coeff (scaleRoots p r + scaleRoots q r) n

Next tactic:
simp only [coeff_smul, coeff_scaleRoots, coeff_add, smul_eq_mul,
    mul_comm (r ^ _), mul_assoc, ← pow_add, ← h, ← add_mul, add_comm (_ - n)]
lemma add_scaleRoots_of_natDegree_eq (p q : R[X]) (r : R) (h : natDegree p = natDegree q) :
    r ^ (natDegree p - natDegree (p + q)) • (p + q).scaleRoots r =
      p.scaleRoots r + q.scaleRoots r := by
  ext n; simp only [coeff_smul, coeff_scaleRoots, coeff_add, smul_eq_mul,
    mul_comm (r ^ _), mul_assoc, ← pow_add, ← h, ← add_mul, add_comm (_ - n)]
  

Proof state:
case a
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
h : natDegree p = natDegree q
n : ℕ
⊢ (coeff p n + coeff q n) * r ^ (natDegree p - natDegree (p + q) + (natDegree (p + q) - n)) =
    (coeff p n + coeff q n) * r ^ (natDegree p - n)

Next tactic:
cases lt_or_le (natDegree (p + q)) n with
  | inl hn => simp only [← coeff_add, coeff_eq_zero_of_natDegree_lt hn, zero_mul]
  | inr hn => rw [tsub_add_tsub_cancel (natDegree_add_le_of_degree_le le_rfl h.ge) hn]
lemma add_scaleRoots_of_natDegree_eq (p q : R[X]) (r : R) (h : natDegree p = natDegree q) :
    r ^ (natDegree p - natDegree (p + q)) • (p + q).scaleRoots r =
      p.scaleRoots r + q.scaleRoots r := by
  ext n; simp only [coeff_smul, coeff_scaleRoots, coeff_add, smul_eq_mul,
    mul_comm (r ^ _), mul_assoc, ← pow_add, ← h, ← add_mul, add_comm (_ - n)]
  

Proof state:
case a
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
h : natDegree p = natDegree q
n : ℕ
x✝ : natDegree (p + q) < n ∨ n ≤ natDegree (p + q)
⊢ (coeff p n + coeff q n) * r ^ (natDegree p - natDegree (p + q) + (natDegree (p + q) - n)) =
    (coeff p n + coeff q n) * r ^ (natDegree p - n)

Next tactic:
cases lt_or_le (natDegree (p + q)) n with
  | inl hn => simp only [← coeff_add, coeff_eq_zero_of_natDegree_lt hn, zero_mul]
  | inr hn => rw [tsub_add_tsub_cancel (natDegree_add_le_of_degree_le le_rfl h.ge) hn]
lemma add_scaleRoots_of_natDegree_eq (p q : R[X]) (r : R) (h : natDegree p = natDegree q) :
    r ^ (natDegree p - natDegree (p + q)) • (p + q).scaleRoots r =
      p.scaleRoots r + q.scaleRoots r := by
  ext n; simp only [coeff_smul, coeff_scaleRoots, coeff_add, smul_eq_mul,
    mul_comm (r ^ _), mul_assoc, ← pow_add, ← h, ← add_mul, add_comm (_ - n)]
  cases lt_or_le (natDegree (p + q)) n with
  

Proof state:
case a.inl
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
h : natDegree p = natDegree q
n : ℕ
hn : natDegree (p + q) < n
⊢ (coeff p n + coeff q n) * r ^ (natDegree p - natDegree (p + q) + (natDegree (p + q) - n)) =
    (coeff p n + coeff q n) * r ^ (natDegree p - n)

Next tactic:
| inl hn => simp only [← coeff_add, coeff_eq_zero_of_natDegree_lt hn, zero_mul]
lemma add_scaleRoots_of_natDegree_eq (p q : R[X]) (r : R) (h : natDegree p = natDegree q) :
    r ^ (natDegree p - natDegree (p + q)) • (p + q).scaleRoots r =
      p.scaleRoots r + q.scaleRoots r := by
  ext n; simp only [coeff_smul, coeff_scaleRoots, coeff_add, smul_eq_mul,
    mul_comm (r ^ _), mul_assoc, ← pow_add, ← h, ← add_mul, add_comm (_ - n)]
  cases lt_or_le (natDegree (p + q)) n with
  | inl hn => 

Proof state:
case a.inl
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
h : natDegree p = natDegree q
n : ℕ
hn : natDegree (p + q) < n
⊢ (coeff p n + coeff q n) * r ^ (natDegree p - natDegree (p + q) + (natDegree (p + q) - n)) =
    (coeff p n + coeff q n) * r ^ (natDegree p - n)

Next tactic:
simp only [← coeff_add, coeff_eq_zero_of_natDegree_lt hn, zero_mul]
lemma add_scaleRoots_of_natDegree_eq (p q : R[X]) (r : R) (h : natDegree p = natDegree q) :
    r ^ (natDegree p - natDegree (p + q)) • (p + q).scaleRoots r =
      p.scaleRoots r + q.scaleRoots r := by
  ext n; simp only [coeff_smul, coeff_scaleRoots, coeff_add, smul_eq_mul,
    mul_comm (r ^ _), mul_assoc, ← pow_add, ← h, ← add_mul, add_comm (_ - n)]
  cases lt_or_le (natDegree (p + q)) n with
  | inl hn => simp only [← coeff_add, coeff_eq_zero_of_natDegree_lt hn, zero_mul]
  

Proof state:
case a.inr
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
h : natDegree p = natDegree q
n : ℕ
hn : n ≤ natDegree (p + q)
⊢ (coeff p n + coeff q n) * r ^ (natDegree p - natDegree (p + q) + (natDegree (p + q) - n)) =
    (coeff p n + coeff q n) * r ^ (natDegree p - n)

Next tactic:
| inr hn => rw [tsub_add_tsub_cancel (natDegree_add_le_of_degree_le le_rfl h.ge) hn]
lemma add_scaleRoots_of_natDegree_eq (p q : R[X]) (r : R) (h : natDegree p = natDegree q) :
    r ^ (natDegree p - natDegree (p + q)) • (p + q).scaleRoots r =
      p.scaleRoots r + q.scaleRoots r := by
  ext n; simp only [coeff_smul, coeff_scaleRoots, coeff_add, smul_eq_mul,
    mul_comm (r ^ _), mul_assoc, ← pow_add, ← h, ← add_mul, add_comm (_ - n)]
  cases lt_or_le (natDegree (p + q)) n with
  | inl hn => simp only [← coeff_add, coeff_eq_zero_of_natDegree_lt hn, zero_mul]
  | inr hn => 

Proof state:
case a.inr
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
h : natDegree p = natDegree q
n : ℕ
hn : n ≤ natDegree (p + q)
⊢ (coeff p n + coeff q n) * r ^ (natDegree p - natDegree (p + q) + (natDegree (p + q) - n)) =
    (coeff p n + coeff q n) * r ^ (natDegree p - n)

Next tactic:
rw [tsub_add_tsub_cancel (natDegree_add_le_of_degree_le le_rfl h.ge) hn]
lemma scaleRoots_dvd' (p q : R[X]) {r : R} (hr : IsUnit r)
    (hpq : p ∣ q) : p.scaleRoots r ∣ q.scaleRoots r := by
  

Proof state:
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
hr : IsUnit r
hpq : p ∣ q
⊢ scaleRoots p r ∣ scaleRoots q r

Next tactic:
obtain ⟨a, rfl⟩ := hpq
lemma scaleRoots_dvd' (p q : R[X]) {r : R} (hr : IsUnit r)
    (hpq : p ∣ q) : p.scaleRoots r ∣ q.scaleRoots r := by
  obtain ⟨a, rfl⟩ := hpq
  

Proof state:
case intro
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p : R[X]
r : R
hr : IsUnit r
a : R[X]
⊢ scaleRoots p r ∣ scaleRoots (p * a) r

Next tactic:
rw [← ((hr.pow (natDegree p + natDegree a - natDegree (p * a))).map
    (algebraMap R R[X])).dvd_mul_left, ← Algebra.smul_def, mul_scaleRoots]
lemma scaleRoots_dvd' (p q : R[X]) {r : R} (hr : IsUnit r)
    (hpq : p ∣ q) : p.scaleRoots r ∣ q.scaleRoots r := by
  obtain ⟨a, rfl⟩ := hpq
  rw [← ((hr.pow (natDegree p + natDegree a - natDegree (p * a))).map
    (algebraMap R R[X])).dvd_mul_left, ← Algebra.smul_def, mul_scaleRoots]
  

Proof state:
case intro
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p : R[X]
r : R
hr : IsUnit r
a : R[X]
⊢ scaleRoots p r ∣ scaleRoots p r * scaleRoots a r

Next tactic:
exact dvd_mul_right (scaleRoots p r) (scaleRoots a r)
lemma scaleRoots_dvd (p q : R[X]) {r : R} [NoZeroDivisors R] (hpq : p ∣ q) :
    p.scaleRoots r ∣ q.scaleRoots r := by
  

Proof state:
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝⁴ : Semiring S
inst✝³ : CommSemiring R
inst✝² : Semiring A
inst✝¹ : Field K
p q : R[X]
r : R
inst✝ : NoZeroDivisors R
hpq : p ∣ q
⊢ scaleRoots p r ∣ scaleRoots q r

Next tactic:
obtain ⟨a, rfl⟩ := hpq
lemma scaleRoots_dvd (p q : R[X]) {r : R} [NoZeroDivisors R] (hpq : p ∣ q) :
    p.scaleRoots r ∣ q.scaleRoots r := by
  obtain ⟨a, rfl⟩ := hpq
  

Proof state:
case intro
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝⁴ : Semiring S
inst✝³ : CommSemiring R
inst✝² : Semiring A
inst✝¹ : Field K
p : R[X]
r : R
inst✝ : NoZeroDivisors R
a : R[X]
⊢ scaleRoots p r ∣ scaleRoots (p * a) r

Next tactic:
rw [mul_scaleRoots_of_noZeroDivisors]
lemma scaleRoots_dvd (p q : R[X]) {r : R} [NoZeroDivisors R] (hpq : p ∣ q) :
    p.scaleRoots r ∣ q.scaleRoots r := by
  obtain ⟨a, rfl⟩ := hpq
  rw [mul_scaleRoots_of_noZeroDivisors]
  

Proof state:
case intro
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝⁴ : Semiring S
inst✝³ : CommSemiring R
inst✝² : Semiring A
inst✝¹ : Field K
p : R[X]
r : R
inst✝ : NoZeroDivisors R
a : R[X]
⊢ scaleRoots p r ∣ scaleRoots p r * scaleRoots a r

Next tactic:
exact dvd_mul_right (scaleRoots p r) (scaleRoots a r)
lemma scaleRoots_dvd_iff (p q : R[X]) {r : R} (hr : IsUnit r) :
    p.scaleRoots r ∣ q.scaleRoots r ↔ p ∣ q := by
  

Proof state:
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
hr : IsUnit r
⊢ scaleRoots p r ∣ scaleRoots q r ↔ p ∣ q

Next tactic:
refine ⟨?_ ∘ scaleRoots_dvd' _ _ (hr.unit⁻¹).isUnit, scaleRoots_dvd' p q hr⟩
lemma scaleRoots_dvd_iff (p q : R[X]) {r : R} (hr : IsUnit r) :
    p.scaleRoots r ∣ q.scaleRoots r ↔ p ∣ q := by
  refine ⟨?_ ∘ scaleRoots_dvd' _ _ (hr.unit⁻¹).isUnit, scaleRoots_dvd' p q hr⟩
  

Proof state:
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
hr : IsUnit r
⊢ scaleRoots (scaleRoots p r) ↑(IsUnit.unit hr)⁻¹ ∣ scaleRoots (scaleRoots q r) ↑(IsUnit.unit hr)⁻¹ → p ∣ q

Next tactic:
simp [← scaleRoots_mul, scaleRoots_one]
lemma isCoprime_scaleRoots (p q : R[X]) (r : R) (hr : IsUnit r) (h : IsCoprime p q) :
    IsCoprime (p.scaleRoots r) (q.scaleRoots r) := by
  

Proof state:
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
hr : IsUnit r
h : IsCoprime p q
⊢ IsCoprime (scaleRoots p r) (scaleRoots q r)

Next tactic:
obtain ⟨a, b, e⟩ := h
lemma isCoprime_scaleRoots (p q : R[X]) (r : R) (hr : IsUnit r) (h : IsCoprime p q) :
    IsCoprime (p.scaleRoots r) (q.scaleRoots r) := by
  obtain ⟨a, b, e⟩ := h
  

Proof state:
case intro.intro
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
hr : IsUnit r
a b : R[X]
e : a * p + b * q = 1
⊢ IsCoprime (scaleRoots p r) (scaleRoots q r)

Next tactic:
let s : R := ↑hr.unit⁻¹
lemma isCoprime_scaleRoots (p q : R[X]) (r : R) (hr : IsUnit r) (h : IsCoprime p q) :
    IsCoprime (p.scaleRoots r) (q.scaleRoots r) := by
  obtain ⟨a, b, e⟩ := h
  let s : R := ↑hr.unit⁻¹
  

Proof state:
case intro.intro
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
hr : IsUnit r
a b : R[X]
e : a * p + b * q = 1
s : R := ↑(IsUnit.unit hr)⁻¹
⊢ IsCoprime (scaleRoots p r) (scaleRoots q r)

Next tactic:
have : natDegree (a * p) = natDegree (b * q)
lemma isCoprime_scaleRoots (p q : R[X]) (r : R) (hr : IsUnit r) (h : IsCoprime p q) :
    IsCoprime (p.scaleRoots r) (q.scaleRoots r) := by
  obtain ⟨a, b, e⟩ := h
  let s : R := ↑hr.unit⁻¹
  have : natDegree (a * p) = natDegree (b * q)
  · 

Proof state:
case this
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
hr : IsUnit r
a b : R[X]
e : a * p + b * q = 1
s : R := ↑(IsUnit.unit hr)⁻¹
⊢ natDegree (a * p) = natDegree (b * q)

Next tactic:
apply natDegree_eq_of_natDegree_add_eq_zero
lemma isCoprime_scaleRoots (p q : R[X]) (r : R) (hr : IsUnit r) (h : IsCoprime p q) :
    IsCoprime (p.scaleRoots r) (q.scaleRoots r) := by
  obtain ⟨a, b, e⟩ := h
  let s : R := ↑hr.unit⁻¹
  have : natDegree (a * p) = natDegree (b * q)
  · apply natDegree_eq_of_natDegree_add_eq_zero
    

Proof state:
case this.H
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
hr : IsUnit r
a b : R[X]
e : a * p + b * q = 1
s : R := ↑(IsUnit.unit hr)⁻¹
⊢ natDegree (a * p + b * q) = 0

Next tactic:
rw [e, natDegree_one]
lemma isCoprime_scaleRoots (p q : R[X]) (r : R) (hr : IsUnit r) (h : IsCoprime p q) :
    IsCoprime (p.scaleRoots r) (q.scaleRoots r) := by
  obtain ⟨a, b, e⟩ := h
  let s : R := ↑hr.unit⁻¹
  have : natDegree (a * p) = natDegree (b * q)
  · apply natDegree_eq_of_natDegree_add_eq_zero
    rw [e, natDegree_one]
  

Proof state:
case intro.intro
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
hr : IsUnit r
a b : R[X]
e : a * p + b * q = 1
s : R := ↑(IsUnit.unit hr)⁻¹
this : natDegree (a * p) = natDegree (b * q)
⊢ IsCoprime (scaleRoots p r) (scaleRoots q r)

Next tactic:
use s ^ natDegree (a * p) • s ^ (natDegree a + natDegree p - natDegree (a * p)) • a.scaleRoots r
lemma isCoprime_scaleRoots (p q : R[X]) (r : R) (hr : IsUnit r) (h : IsCoprime p q) :
    IsCoprime (p.scaleRoots r) (q.scaleRoots r) := by
  obtain ⟨a, b, e⟩ := h
  let s : R := ↑hr.unit⁻¹
  have : natDegree (a * p) = natDegree (b * q)
  · apply natDegree_eq_of_natDegree_add_eq_zero
    rw [e, natDegree_one]
  use s ^ natDegree (a * p) • s ^ (natDegree a + natDegree p - natDegree (a * p)) • a.scaleRoots r
  

Proof state:
case h
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
hr : IsUnit r
a b : R[X]
e : a * p + b * q = 1
s : R := ↑(IsUnit.unit hr)⁻¹
this : natDegree (a * p) = natDegree (b * q)
⊢ ∃ b,
    s ^ natDegree (a * p) • s ^ (natDegree a + natDegree p - natDegree (a * p)) • scaleRoots a r * scaleRoots p r +
        b * scaleRoots q r =
      1

Next tactic:
use s ^ natDegree (a * p) • s ^ (natDegree b + natDegree q - natDegree (b * q)) • b.scaleRoots r
lemma isCoprime_scaleRoots (p q : R[X]) (r : R) (hr : IsUnit r) (h : IsCoprime p q) :
    IsCoprime (p.scaleRoots r) (q.scaleRoots r) := by
  obtain ⟨a, b, e⟩ := h
  let s : R := ↑hr.unit⁻¹
  have : natDegree (a * p) = natDegree (b * q)
  · apply natDegree_eq_of_natDegree_add_eq_zero
    rw [e, natDegree_one]
  use s ^ natDegree (a * p) • s ^ (natDegree a + natDegree p - natDegree (a * p)) • a.scaleRoots r
  use s ^ natDegree (a * p) • s ^ (natDegree b + natDegree q - natDegree (b * q)) • b.scaleRoots r
  

Proof state:
case h
R : Type u_1
S : Type u_2
A : Type u_3
K : Type u_4
inst✝³ : Semiring S
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Field K
p q : R[X]
r : R
hr : IsUnit r
a b : R[X]
e : a * p + b * q = 1
s : R := ↑(IsUnit.unit hr)⁻¹
this : natDegree (a * p) = natDegree (b * q)
⊢ s ^ natDegree (a * p) • s ^ (natDegree a + natDegree p - natDegree (a * p)) • scaleRoots a r * scaleRoots p r +
      s ^ natDegree (a * p) • s ^ (natDegree b + natDegree q - natDegree (b * q)) • scaleRoots b r * scaleRoots q r =
    1

Next tactic:
simp only [smul_mul_assoc, ← mul_scaleRoots, smul_smul, Units.smul_def, mul_assoc,
    ← mul_pow, IsUnit.val_inv_mul, one_pow, mul_one, ← smul_add, one_smul, e, natDegree_one,
    one_scaleRoots, ← add_scaleRoots_of_natDegree_eq _ _ _ this, tsub_zero]
theorem isEquipartition_iff_card_parts_eq_average :
    P.IsEquipartition ↔
      ∀ a : Finset α,
        a ∈ P.parts → a.card = s.card / P.parts.card ∨ a.card = s.card / P.parts.card + 1 :=
  by 

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
P : Finpartition s
⊢ IsEquipartition P ↔
    ∀ a ∈ P.parts,
      Finset.card a = Finset.card s / Finset.card P.parts ∨ Finset.card a = Finset.card s / Finset.card P.parts + 1

Next tactic:
simp_rw [IsEquipartition, Finset.equitableOn_iff, P.sum_card_parts]
theorem IsEquipartition.average_le_card_part (hP : P.IsEquipartition) (ht : t ∈ P.parts) :
    s.card / P.parts.card ≤ t.card := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
P : Finpartition s
hP : IsEquipartition P
ht : t ∈ P.parts
⊢ Finset.card s / Finset.card P.parts ≤ Finset.card t

Next tactic:
rw [← P.sum_card_parts]
theorem IsEquipartition.average_le_card_part (hP : P.IsEquipartition) (ht : t ∈ P.parts) :
    s.card / P.parts.card ≤ t.card := by
  rw [← P.sum_card_parts]
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
P : Finpartition s
hP : IsEquipartition P
ht : t ∈ P.parts
⊢ (Finset.sum P.parts fun i => Finset.card i) / Finset.card P.parts ≤ Finset.card t

Next tactic:
exact Finset.EquitableOn.le hP ht
theorem IsEquipartition.card_part_le_average_add_one (hP : P.IsEquipartition) (ht : t ∈ P.parts) :
    t.card ≤ s.card / P.parts.card + 1 := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
P : Finpartition s
hP : IsEquipartition P
ht : t ∈ P.parts
⊢ Finset.card t ≤ Finset.card s / Finset.card P.parts + 1

Next tactic:
rw [← P.sum_card_parts]
theorem IsEquipartition.card_part_le_average_add_one (hP : P.IsEquipartition) (ht : t ∈ P.parts) :
    t.card ≤ s.card / P.parts.card + 1 := by
  rw [← P.sum_card_parts]
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
P : Finpartition s
hP : IsEquipartition P
ht : t ∈ P.parts
⊢ Finset.card t ≤ (Finset.sum P.parts fun i => Finset.card i) / Finset.card P.parts + 1

Next tactic:
exact Finset.EquitableOn.le_add_one hP ht
theorem bot_isEquipartition : (⊥ : Finpartition s).IsEquipartition :=
  Set.equitableOn_iff_exists_eq_eq_add_one.2 ⟨1, by 

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
P : Finpartition s
⊢ ∀ a ∈ ↑⊥.parts, Finset.card a = 1 ∨ Finset.card a = 1 + 1

Next tactic:
simp
theorem indiscrete_isEquipartition {hs : s ≠ ∅} : (indiscrete hs).IsEquipartition := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
P : Finpartition s
hs : s ≠ ∅
⊢ IsEquipartition (indiscrete hs)

Next tactic:
rw [IsEquipartition, indiscrete_parts, coe_singleton]
theorem indiscrete_isEquipartition {hs : s ≠ ∅} : (indiscrete hs).IsEquipartition := by
  rw [IsEquipartition, indiscrete_parts, coe_singleton]
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s t : Finset α
P : Finpartition s
hs : s ≠ ∅
⊢ Set.EquitableOn {s} Finset.card

Next tactic:
exact Set.equitableOn_singleton s _
/-- A σ-compact Hausdorff topological manifold over a finite dimensional real vector space is
metrizable. -/
theorem ManifoldWithCorners.metrizableSpace {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E]
    [FiniteDimensional ℝ E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners ℝ E H)
    (M : Type*) [TopologicalSpace M] [ChartedSpace H M] [SigmaCompactSpace M] [T2Space M] :
    MetrizableSpace M := by
  

Proof state:
E : Type u_1
inst✝⁷ : NormedAddCommGroup E
inst✝⁶ : NormedSpace ℝ E
inst✝⁵ : FiniteDimensional ℝ E
H : Type u_2
inst✝⁴ : TopologicalSpace H
I : ModelWithCorners ℝ E H
M : Type u_3
inst✝³ : TopologicalSpace M
inst✝² : ChartedSpace H M
inst✝¹ : SigmaCompactSpace M
inst✝ : T2Space M
⊢ MetrizableSpace M

Next tactic:
haveI := I.locallyCompactSpace
/-- A σ-compact Hausdorff topological manifold over a finite dimensional real vector space is
metrizable. -/
theorem ManifoldWithCorners.metrizableSpace {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E]
    [FiniteDimensional ℝ E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners ℝ E H)
    (M : Type*) [TopologicalSpace M] [ChartedSpace H M] [SigmaCompactSpace M] [T2Space M] :
    MetrizableSpace M := by
  haveI := I.locallyCompactSpace; 

Proof state:
E : Type u_1
inst✝⁷ : NormedAddCommGroup E
inst✝⁶ : NormedSpace ℝ E
inst✝⁵ : FiniteDimensional ℝ E
H : Type u_2
inst✝⁴ : TopologicalSpace H
I : ModelWithCorners ℝ E H
M : Type u_3
inst✝³ : TopologicalSpace M
inst✝² : ChartedSpace H M
inst✝¹ : SigmaCompactSpace M
inst✝ : T2Space M
this : LocallyCompactSpace H
⊢ MetrizableSpace M

Next tactic:
haveI := ChartedSpace.locallyCompactSpace H M
/-- A σ-compact Hausdorff topological manifold over a finite dimensional real vector space is
metrizable. -/
theorem ManifoldWithCorners.metrizableSpace {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E]
    [FiniteDimensional ℝ E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners ℝ E H)
    (M : Type*) [TopologicalSpace M] [ChartedSpace H M] [SigmaCompactSpace M] [T2Space M] :
    MetrizableSpace M := by
  haveI := I.locallyCompactSpace; haveI := ChartedSpace.locallyCompactSpace H M
  

Proof state:
E : Type u_1
inst✝⁷ : NormedAddCommGroup E
inst✝⁶ : NormedSpace ℝ E
inst✝⁵ : FiniteDimensional ℝ E
H : Type u_2
inst✝⁴ : TopologicalSpace H
I : ModelWithCorners ℝ E H
M : Type u_3
inst✝³ : TopologicalSpace M
inst✝² : ChartedSpace H M
inst✝¹ : SigmaCompactSpace M
inst✝ : T2Space M
this✝ : LocallyCompactSpace H
this : LocallyCompactSpace M
⊢ MetrizableSpace M

Next tactic:
haveI := I.secondCountableTopology
/-- A σ-compact Hausdorff topological manifold over a finite dimensional real vector space is
metrizable. -/
theorem ManifoldWithCorners.metrizableSpace {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E]
    [FiniteDimensional ℝ E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners ℝ E H)
    (M : Type*) [TopologicalSpace M] [ChartedSpace H M] [SigmaCompactSpace M] [T2Space M] :
    MetrizableSpace M := by
  haveI := I.locallyCompactSpace; haveI := ChartedSpace.locallyCompactSpace H M
  haveI := I.secondCountableTopology
  

Proof state:
E : Type u_1
inst✝⁷ : NormedAddCommGroup E
inst✝⁶ : NormedSpace ℝ E
inst✝⁵ : FiniteDimensional ℝ E
H : Type u_2
inst✝⁴ : TopologicalSpace H
I : ModelWithCorners ℝ E H
M : Type u_3
inst✝³ : TopologicalSpace M
inst✝² : ChartedSpace H M
inst✝¹ : SigmaCompactSpace M
inst✝ : T2Space M
this✝¹ : LocallyCompactSpace H
this✝ : LocallyCompactSpace M
this : SecondCountableTopology H
⊢ MetrizableSpace M

Next tactic:
haveI := ChartedSpace.secondCountable_of_sigma_compact H M
/-- A σ-compact Hausdorff topological manifold over a finite dimensional real vector space is
metrizable. -/
theorem ManifoldWithCorners.metrizableSpace {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E]
    [FiniteDimensional ℝ E] {H : Type*} [TopologicalSpace H] (I : ModelWithCorners ℝ E H)
    (M : Type*) [TopologicalSpace M] [ChartedSpace H M] [SigmaCompactSpace M] [T2Space M] :
    MetrizableSpace M := by
  haveI := I.locallyCompactSpace; haveI := ChartedSpace.locallyCompactSpace H M
  haveI := I.secondCountableTopology
  haveI := ChartedSpace.secondCountable_of_sigma_compact H M
  

Proof state:
E : Type u_1
inst✝⁷ : NormedAddCommGroup E
inst✝⁶ : NormedSpace ℝ E
inst✝⁵ : FiniteDimensional ℝ E
H : Type u_2
inst✝⁴ : TopologicalSpace H
I : ModelWithCorners ℝ E H
M : Type u_3
inst✝³ : TopologicalSpace M
inst✝² : ChartedSpace H M
inst✝¹ : SigmaCompactSpace M
inst✝ : T2Space M
this✝² : LocallyCompactSpace H
this✝¹ : LocallyCompactSpace M
this✝ : SecondCountableTopology H
this : SecondCountableTopology M
⊢ MetrizableSpace M

Next tactic:
exact metrizableSpace_of_t3_second_countable M
theorem isBounded_prod : IsBounded (s ×ˢ t) ↔ s = ∅ ∨ t = ∅ ∨ IsBounded s ∧ IsBounded t := by
  

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
π : ι → Type u_4
inst✝³ : Fintype ι
inst✝² : Bornology α
inst✝¹ : Bornology β
inst✝ : (i : ι) → Bornology (π i)
s : Set α
t : Set β
S : (i : ι) → Set (π i)
⊢ IsBounded (s ×ˢ t) ↔ s = ∅ ∨ t = ∅ ∨ IsBounded s ∧ IsBounded t

Next tactic:
rcases s.eq_empty_or_nonempty with (rfl | hs)
theorem isBounded_prod : IsBounded (s ×ˢ t) ↔ s = ∅ ∨ t = ∅ ∨ IsBounded s ∧ IsBounded t := by
  rcases s.eq_empty_or_nonempty with (rfl | hs); · 

Proof state:
case inl
α : Type u_1
β : Type u_2
ι : Type u_3
π : ι → Type u_4
inst✝³ : Fintype ι
inst✝² : Bornology α
inst✝¹ : Bornology β
inst✝ : (i : ι) → Bornology (π i)
t : Set β
S : (i : ι) → Set (π i)
⊢ IsBounded (∅ ×ˢ t) ↔ ∅ = ∅ ∨ t = ∅ ∨ IsBounded ∅ ∧ IsBounded t

Next tactic:
simp