l3lab/ntp-mathlib huggingface dataset:
theorem card_add_nsmul_le {α : Type*} [AddCommGroup α] [DecidableEq α] {A B : Finset α}
    (hAB : ∀ (A') (_ : A' ⊆ A), (A + B).card * A'.card ≤ (A' + B).card * A.card) (n : ℕ) :
    (A + n • B).card ≤ ((A + B).card / A.card : ℚ≥0) ^ n * A.card := by
  obtain rfl | hA := A.eq_empty_or_nonempty
  · simp
  induction' n with n ih
  · simp
  rw [succ_nsmul, ← add_assoc, _root_.pow_succ, mul_assoc, ← mul_div_right_comm, le_div_iff,
    ← cast_mul]
  

Proof state:
case inr.succ
α✝ : Type u_1
inst✝³ : CommGroup α✝
inst✝² : DecidableEq α✝
A✝ B✝ C : Finset α✝
α : Type u_2
inst✝¹ : AddCommGroup α
inst✝ : DecidableEq α
A B : Finset α
hAB : ∀ A' ⊆ A, card (A + B) * card A' ≤ card (A' + B) * card A
hA : Finset.Nonempty A
n : ℕ
ih : ↑(card (A + n • B)) ≤ (↑(card (A + B)) / ↑(card A)) ^ n * ↑(card A)
⊢ ↑(card (A + B + n • B) * card A) ≤ ↑(card (A + B)) * ((↑(card (A + B)) / ↑(card A)) ^ n * ↑(card A))
case inr.succ
α✝ : Type u_1
inst✝³ : CommGroup α✝
inst✝² : DecidableEq α✝
A✝ B✝ C : Finset α✝
α : Type u_2
inst✝¹ : AddCommGroup α
inst✝ : DecidableEq α
A B : Finset α
hAB : ∀ A' ⊆ A, card (A + B) * card A' ≤ card (A' + B) * card A
hA : Finset.Nonempty A
n : ℕ
ih : ↑(card (A + n • B)) ≤ (↑(card (A + B)) / ↑(card A)) ^ n * ↑(card A)
⊢ 0 < ↑(card A)

Next tactic:
swap
theorem card_add_nsmul_le {α : Type*} [AddCommGroup α] [DecidableEq α] {A B : Finset α}
    (hAB : ∀ (A') (_ : A' ⊆ A), (A + B).card * A'.card ≤ (A' + B).card * A.card) (n : ℕ) :
    (A + n • B).card ≤ ((A + B).card / A.card : ℚ≥0) ^ n * A.card := by
  obtain rfl | hA := A.eq_empty_or_nonempty
  · simp
  induction' n with n ih
  · simp
  rw [succ_nsmul, ← add_assoc, _root_.pow_succ, mul_assoc, ← mul_div_right_comm, le_div_iff,
    ← cast_mul]
  swap; 

Proof state:
case inr.succ
α✝ : Type u_1
inst✝³ : CommGroup α✝
inst✝² : DecidableEq α✝
A✝ B✝ C : Finset α✝
α : Type u_2
inst✝¹ : AddCommGroup α
inst✝ : DecidableEq α
A B : Finset α
hAB : ∀ A' ⊆ A, card (A + B) * card A' ≤ card (A' + B) * card A
hA : Finset.Nonempty A
n : ℕ
ih : ↑(card (A + n • B)) ≤ (↑(card (A + B)) / ↑(card A)) ^ n * ↑(card A)
⊢ 0 < ↑(card A)
case inr.succ
α✝ : Type u_1
inst✝³ : CommGroup α✝
inst✝² : DecidableEq α✝
A✝ B✝ C : Finset α✝
α : Type u_2
inst✝¹ : AddCommGroup α
inst✝ : DecidableEq α
A B : Finset α
hAB : ∀ A' ⊆ A, card (A + B) * card A' ≤ card (A' + B) * card A
hA : Finset.Nonempty A
n : ℕ
ih : ↑(card (A + n • B)) ≤ (↑(card (A + B)) / ↑(card A)) ^ n * ↑(card A)
⊢ ↑(card (A + B + n • B) * card A) ≤ ↑(card (A + B)) * ((↑(card (A + B)) / ↑(card A)) ^ n * ↑(card A))

Next tactic:
exact cast_pos.2 hA.card_pos
theorem card_add_nsmul_le {α : Type*} [AddCommGroup α] [DecidableEq α] {A B : Finset α}
    (hAB : ∀ (A') (_ : A' ⊆ A), (A + B).card * A'.card ≤ (A' + B).card * A.card) (n : ℕ) :
    (A + n • B).card ≤ ((A + B).card / A.card : ℚ≥0) ^ n * A.card := by
  obtain rfl | hA := A.eq_empty_or_nonempty
  · simp
  induction' n with n ih
  · simp
  rw [succ_nsmul, ← add_assoc, _root_.pow_succ, mul_assoc, ← mul_div_right_comm, le_div_iff,
    ← cast_mul]
  swap; exact cast_pos.2 hA.card_pos
  

Proof state:
case inr.succ
α✝ : Type u_1
inst✝³ : CommGroup α✝
inst✝² : DecidableEq α✝
A✝ B✝ C : Finset α✝
α : Type u_2
inst✝¹ : AddCommGroup α
inst✝ : DecidableEq α
A B : Finset α
hAB : ∀ A' ⊆ A, card (A + B) * card A' ≤ card (A' + B) * card A
hA : Finset.Nonempty A
n : ℕ
ih : ↑(card (A + n • B)) ≤ (↑(card (A + B)) / ↑(card A)) ^ n * ↑(card A)
⊢ ↑(card (A + B + n • B) * card A) ≤ ↑(card (A + B)) * ((↑(card (A + B)) / ↑(card A)) ^ n * ↑(card A))

Next tactic:
refine' (cast_le.2 <| add_pluennecke_petridis _ hAB).trans _
theorem card_add_nsmul_le {α : Type*} [AddCommGroup α] [DecidableEq α] {A B : Finset α}
    (hAB : ∀ (A') (_ : A' ⊆ A), (A + B).card * A'.card ≤ (A' + B).card * A.card) (n : ℕ) :
    (A + n • B).card ≤ ((A + B).card / A.card : ℚ≥0) ^ n * A.card := by
  obtain rfl | hA := A.eq_empty_or_nonempty
  · simp
  induction' n with n ih
  · simp
  rw [succ_nsmul, ← add_assoc, _root_.pow_succ, mul_assoc, ← mul_div_right_comm, le_div_iff,
    ← cast_mul]
  swap; exact cast_pos.2 hA.card_pos
  refine' (cast_le.2 <| add_pluennecke_petridis _ hAB).trans _
  

Proof state:
case inr.succ
α✝ : Type u_1
inst✝³ : CommGroup α✝
inst✝² : DecidableEq α✝
A✝ B✝ C : Finset α✝
α : Type u_2
inst✝¹ : AddCommGroup α
inst✝ : DecidableEq α
A B : Finset α
hAB : ∀ A' ⊆ A, card (A + B) * card A' ≤ card (A' + B) * card A
hA : Finset.Nonempty A
n : ℕ
ih : ↑(card (A + n • B)) ≤ (↑(card (A + B)) / ↑(card A)) ^ n * ↑(card A)
⊢ ↑(card (A + B) * card (A + n • B)) ≤ ↑(card (A + B)) * ((↑(card (A + B)) / ↑(card A)) ^ n * ↑(card A))

Next tactic:
rw [cast_mul]
theorem card_add_nsmul_le {α : Type*} [AddCommGroup α] [DecidableEq α] {A B : Finset α}
    (hAB : ∀ (A') (_ : A' ⊆ A), (A + B).card * A'.card ≤ (A' + B).card * A.card) (n : ℕ) :
    (A + n • B).card ≤ ((A + B).card / A.card : ℚ≥0) ^ n * A.card := by
  obtain rfl | hA := A.eq_empty_or_nonempty
  · simp
  induction' n with n ih
  · simp
  rw [succ_nsmul, ← add_assoc, _root_.pow_succ, mul_assoc, ← mul_div_right_comm, le_div_iff,
    ← cast_mul]
  swap; exact cast_pos.2 hA.card_pos
  refine' (cast_le.2 <| add_pluennecke_petridis _ hAB).trans _
  rw [cast_mul]
  

Proof state:
case inr.succ
α✝ : Type u_1
inst✝³ : CommGroup α✝
inst✝² : DecidableEq α✝
A✝ B✝ C : Finset α✝
α : Type u_2
inst✝¹ : AddCommGroup α
inst✝ : DecidableEq α
A B : Finset α
hAB : ∀ A' ⊆ A, card (A + B) * card A' ≤ card (A' + B) * card A
hA : Finset.Nonempty A
n : ℕ
ih : ↑(card (A + n • B)) ≤ (↑(card (A + B)) / ↑(card A)) ^ n * ↑(card A)
⊢ ↑(card (A + B)) * ↑(card (A + n • B)) ≤ ↑(card (A + B)) * ((↑(card (A + B)) / ↑(card A)) ^ n * ↑(card A))

Next tactic:
gcongr
@[to_additive existing]
theorem card_mul_pow_le (hAB : ∀ (A') (_ : A' ⊆ A), (A * B).card * A'.card ≤ (A' * B).card * A.card)
    (n : ℕ) : (A * B ^ n).card ≤ ((A * B).card / A.card : ℚ≥0) ^ n * A.card := by
  

Proof state:
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B C : Finset α
hAB : ∀ A' ⊆ A, card (A * B) * card A' ≤ card (A' * B) * card A
n : ℕ
⊢ ↑(card (A * B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ n * ↑(card A)

Next tactic:
obtain rfl | hA := A.eq_empty_or_nonempty
@[to_additive existing]
theorem card_mul_pow_le (hAB : ∀ (A') (_ : A' ⊆ A), (A * B).card * A'.card ≤ (A' * B).card * A.card)
    (n : ℕ) : (A * B ^ n).card ≤ ((A * B).card / A.card : ℚ≥0) ^ n * A.card := by
  obtain rfl | hA := A.eq_empty_or_nonempty
  · 

Proof state:
case inl
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
B C : Finset α
n : ℕ
hAB : ∀ A' ⊆ ∅, card (∅ * B) * card A' ≤ card (A' * B) * card ∅
⊢ ↑(card (∅ * B ^ n)) ≤ (↑(card (∅ * B)) / ↑(card ∅)) ^ n * ↑(card ∅)

Next tactic:
simp
@[to_additive existing]
theorem card_mul_pow_le (hAB : ∀ (A') (_ : A' ⊆ A), (A * B).card * A'.card ≤ (A' * B).card * A.card)
    (n : ℕ) : (A * B ^ n).card ≤ ((A * B).card / A.card : ℚ≥0) ^ n * A.card := by
  obtain rfl | hA := A.eq_empty_or_nonempty
  · simp
  

Proof state:
case inr
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B C : Finset α
hAB : ∀ A' ⊆ A, card (A * B) * card A' ≤ card (A' * B) * card A
n : ℕ
hA : Finset.Nonempty A
⊢ ↑(card (A * B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ n * ↑(card A)

Next tactic:
induction' n with n ih
@[to_additive existing]
theorem card_mul_pow_le (hAB : ∀ (A') (_ : A' ⊆ A), (A * B).card * A'.card ≤ (A' * B).card * A.card)
    (n : ℕ) : (A * B ^ n).card ≤ ((A * B).card / A.card : ℚ≥0) ^ n * A.card := by
  obtain rfl | hA := A.eq_empty_or_nonempty
  · simp
  induction' n with n ih
  · 

Proof state:
case inr.zero
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B C : Finset α
hAB : ∀ A' ⊆ A, card (A * B) * card A' ≤ card (A' * B) * card A
hA : Finset.Nonempty A
⊢ ↑(card (A * B ^ zero)) ≤ (↑(card (A * B)) / ↑(card A)) ^ zero * ↑(card A)

Next tactic:
simp
@[to_additive existing]
theorem card_mul_pow_le (hAB : ∀ (A') (_ : A' ⊆ A), (A * B).card * A'.card ≤ (A' * B).card * A.card)
    (n : ℕ) : (A * B ^ n).card ≤ ((A * B).card / A.card : ℚ≥0) ^ n * A.card := by
  obtain rfl | hA := A.eq_empty_or_nonempty
  · simp
  induction' n with n ih
  · simp
  

Proof state:
case inr.succ
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B C : Finset α
hAB : ∀ A' ⊆ A, card (A * B) * card A' ≤ card (A' * B) * card A
hA : Finset.Nonempty A
n : ℕ
ih : ↑(card (A * B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ n * ↑(card A)
⊢ ↑(card (A * B ^ succ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ succ n * ↑(card A)

Next tactic:
rw [_root_.pow_succ, ← mul_assoc, _root_.pow_succ, @mul_assoc ℚ≥0, ← mul_div_right_comm,
    le_div_iff, ← cast_mul]
@[to_additive existing]
theorem card_mul_pow_le (hAB : ∀ (A') (_ : A' ⊆ A), (A * B).card * A'.card ≤ (A' * B).card * A.card)
    (n : ℕ) : (A * B ^ n).card ≤ ((A * B).card / A.card : ℚ≥0) ^ n * A.card := by
  obtain rfl | hA := A.eq_empty_or_nonempty
  · simp
  induction' n with n ih
  · simp
  rw [_root_.pow_succ, ← mul_assoc, _root_.pow_succ, @mul_assoc ℚ≥0, ← mul_div_right_comm,
    le_div_iff, ← cast_mul]
  

Proof state:
case inr.succ
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B C : Finset α
hAB : ∀ A' ⊆ A, card (A * B) * card A' ≤ card (A' * B) * card A
hA : Finset.Nonempty A
n : ℕ
ih : ↑(card (A * B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ n * ↑(card A)
⊢ ↑(card (A * B * B ^ n) * card A) ≤ ↑(card (A * B)) * ((↑(card (A * B)) / ↑(card A)) ^ n * ↑(card A))
case inr.succ
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B C : Finset α
hAB : ∀ A' ⊆ A, card (A * B) * card A' ≤ card (A' * B) * card A
hA : Finset.Nonempty A
n : ℕ
ih : ↑(card (A * B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ n * ↑(card A)
⊢ 0 < ↑(card A)

Next tactic:
swap
@[to_additive existing]
theorem card_mul_pow_le (hAB : ∀ (A') (_ : A' ⊆ A), (A * B).card * A'.card ≤ (A' * B).card * A.card)
    (n : ℕ) : (A * B ^ n).card ≤ ((A * B).card / A.card : ℚ≥0) ^ n * A.card := by
  obtain rfl | hA := A.eq_empty_or_nonempty
  · simp
  induction' n with n ih
  · simp
  rw [_root_.pow_succ, ← mul_assoc, _root_.pow_succ, @mul_assoc ℚ≥0, ← mul_div_right_comm,
    le_div_iff, ← cast_mul]
  swap; 

Proof state:
case inr.succ
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B C : Finset α
hAB : ∀ A' ⊆ A, card (A * B) * card A' ≤ card (A' * B) * card A
hA : Finset.Nonempty A
n : ℕ
ih : ↑(card (A * B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ n * ↑(card A)
⊢ 0 < ↑(card A)
case inr.succ
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B C : Finset α
hAB : ∀ A' ⊆ A, card (A * B) * card A' ≤ card (A' * B) * card A
hA : Finset.Nonempty A
n : ℕ
ih : ↑(card (A * B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ n * ↑(card A)
⊢ ↑(card (A * B * B ^ n) * card A) ≤ ↑(card (A * B)) * ((↑(card (A * B)) / ↑(card A)) ^ n * ↑(card A))

Next tactic:
exact cast_pos.2 hA.card_pos
@[to_additive existing]
theorem card_mul_pow_le (hAB : ∀ (A') (_ : A' ⊆ A), (A * B).card * A'.card ≤ (A' * B).card * A.card)
    (n : ℕ) : (A * B ^ n).card ≤ ((A * B).card / A.card : ℚ≥0) ^ n * A.card := by
  obtain rfl | hA := A.eq_empty_or_nonempty
  · simp
  induction' n with n ih
  · simp
  rw [_root_.pow_succ, ← mul_assoc, _root_.pow_succ, @mul_assoc ℚ≥0, ← mul_div_right_comm,
    le_div_iff, ← cast_mul]
  swap; exact cast_pos.2 hA.card_pos
  

Proof state:
case inr.succ
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B C : Finset α
hAB : ∀ A' ⊆ A, card (A * B) * card A' ≤ card (A' * B) * card A
hA : Finset.Nonempty A
n : ℕ
ih : ↑(card (A * B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ n * ↑(card A)
⊢ ↑(card (A * B * B ^ n) * card A) ≤ ↑(card (A * B)) * ((↑(card (A * B)) / ↑(card A)) ^ n * ↑(card A))

Next tactic:
refine' (cast_le.2 <| mul_pluennecke_petridis _ hAB).trans _
@[to_additive existing]
theorem card_mul_pow_le (hAB : ∀ (A') (_ : A' ⊆ A), (A * B).card * A'.card ≤ (A' * B).card * A.card)
    (n : ℕ) : (A * B ^ n).card ≤ ((A * B).card / A.card : ℚ≥0) ^ n * A.card := by
  obtain rfl | hA := A.eq_empty_or_nonempty
  · simp
  induction' n with n ih
  · simp
  rw [_root_.pow_succ, ← mul_assoc, _root_.pow_succ, @mul_assoc ℚ≥0, ← mul_div_right_comm,
    le_div_iff, ← cast_mul]
  swap; exact cast_pos.2 hA.card_pos
  refine' (cast_le.2 <| mul_pluennecke_petridis _ hAB).trans _
  

Proof state:
case inr.succ
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B C : Finset α
hAB : ∀ A' ⊆ A, card (A * B) * card A' ≤ card (A' * B) * card A
hA : Finset.Nonempty A
n : ℕ
ih : ↑(card (A * B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ n * ↑(card A)
⊢ ↑(card (A * B) * card (A * B ^ n)) ≤ ↑(card (A * B)) * ((↑(card (A * B)) / ↑(card A)) ^ n * ↑(card A))

Next tactic:
rw [cast_mul]
@[to_additive existing]
theorem card_mul_pow_le (hAB : ∀ (A') (_ : A' ⊆ A), (A * B).card * A'.card ≤ (A' * B).card * A.card)
    (n : ℕ) : (A * B ^ n).card ≤ ((A * B).card / A.card : ℚ≥0) ^ n * A.card := by
  obtain rfl | hA := A.eq_empty_or_nonempty
  · simp
  induction' n with n ih
  · simp
  rw [_root_.pow_succ, ← mul_assoc, _root_.pow_succ, @mul_assoc ℚ≥0, ← mul_div_right_comm,
    le_div_iff, ← cast_mul]
  swap; exact cast_pos.2 hA.card_pos
  refine' (cast_le.2 <| mul_pluennecke_petridis _ hAB).trans _
  rw [cast_mul]
  

Proof state:
case inr.succ
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B C : Finset α
hAB : ∀ A' ⊆ A, card (A * B) * card A' ≤ card (A' * B) * card A
hA : Finset.Nonempty A
n : ℕ
ih : ↑(card (A * B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ n * ↑(card A)
⊢ ↑(card (A * B)) * ↑(card (A * B ^ n)) ≤ ↑(card (A * B)) * ((↑(card (A * B)) / ↑(card A)) ^ n * ↑(card A))

Next tactic:
gcongr
/-- The **Plünnecke-Ruzsa inequality**. Multiplication version. Note that this is genuinely harder
than the division version because we cannot use a double counting argument. -/
@[to_additive "The **Plünnecke-Ruzsa inequality**. Addition version. Note that this is genuinely
harder than the subtraction version because we cannot use a double counting argument."]
theorem card_pow_div_pow_le (hA : A.Nonempty) (B : Finset α) (m n : ℕ) :
    ((B ^ m / B ^ n).card) ≤ ((A * B).card / A.card : ℚ≥0) ^ (m + n) * A.card := by
  

Proof state:
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B✝ C : Finset α
hA : Finset.Nonempty A
B : Finset α
m n : ℕ
⊢ ↑(card (B ^ m / B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ (m + n) * ↑(card A)

Next tactic:
have hA' : A ∈ A.powerset.erase ∅ := mem_erase_of_ne_of_mem hA.ne_empty (mem_powerset_self _)
/-- The **Plünnecke-Ruzsa inequality**. Multiplication version. Note that this is genuinely harder
than the division version because we cannot use a double counting argument. -/
@[to_additive "The **Plünnecke-Ruzsa inequality**. Addition version. Note that this is genuinely
harder than the subtraction version because we cannot use a double counting argument."]
theorem card_pow_div_pow_le (hA : A.Nonempty) (B : Finset α) (m n : ℕ) :
    ((B ^ m / B ^ n).card) ≤ ((A * B).card / A.card : ℚ≥0) ^ (m + n) * A.card := by
  have hA' : A ∈ A.powerset.erase ∅ := mem_erase_of_ne_of_mem hA.ne_empty (mem_powerset_self _)
  

Proof state:
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B✝ C : Finset α
hA : Finset.Nonempty A
B : Finset α
m n : ℕ
hA' : A ∈ erase (powerset A) ∅
⊢ ↑(card (B ^ m / B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ (m + n) * ↑(card A)

Next tactic:
obtain ⟨C, hC, hCA⟩ :=
    exists_min_image (A.powerset.erase ∅) (fun C ↦ (C * B).card / C.card : _ → ℚ≥0) ⟨A, hA'⟩
/-- The **Plünnecke-Ruzsa inequality**. Multiplication version. Note that this is genuinely harder
than the division version because we cannot use a double counting argument. -/
@[to_additive "The **Plünnecke-Ruzsa inequality**. Addition version. Note that this is genuinely
harder than the subtraction version because we cannot use a double counting argument."]
theorem card_pow_div_pow_le (hA : A.Nonempty) (B : Finset α) (m n : ℕ) :
    ((B ^ m / B ^ n).card) ≤ ((A * B).card / A.card : ℚ≥0) ^ (m + n) * A.card := by
  have hA' : A ∈ A.powerset.erase ∅ := mem_erase_of_ne_of_mem hA.ne_empty (mem_powerset_self _)
  obtain ⟨C, hC, hCA⟩ :=
    exists_min_image (A.powerset.erase ∅) (fun C ↦ (C * B).card / C.card : _ → ℚ≥0) ⟨A, hA'⟩
  

Proof state:
case intro.intro
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B✝ C✝ : Finset α
hA : Finset.Nonempty A
B : Finset α
m n : ℕ
hA' : A ∈ erase (powerset A) ∅
C : Finset α
hC : C ∈ erase (powerset A) ∅
hCA : ∀ x' ∈ erase (powerset A) ∅, ↑(card (C * B)) / ↑(card C) ≤ ↑(card (x' * B)) / ↑(card x')
⊢ ↑(card (B ^ m / B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ (m + n) * ↑(card A)

Next tactic:
rw [mem_erase, mem_powerset, ← nonempty_iff_ne_empty] at hC
/-- The **Plünnecke-Ruzsa inequality**. Multiplication version. Note that this is genuinely harder
than the division version because we cannot use a double counting argument. -/
@[to_additive "The **Plünnecke-Ruzsa inequality**. Addition version. Note that this is genuinely
harder than the subtraction version because we cannot use a double counting argument."]
theorem card_pow_div_pow_le (hA : A.Nonempty) (B : Finset α) (m n : ℕ) :
    ((B ^ m / B ^ n).card) ≤ ((A * B).card / A.card : ℚ≥0) ^ (m + n) * A.card := by
  have hA' : A ∈ A.powerset.erase ∅ := mem_erase_of_ne_of_mem hA.ne_empty (mem_powerset_self _)
  obtain ⟨C, hC, hCA⟩ :=
    exists_min_image (A.powerset.erase ∅) (fun C ↦ (C * B).card / C.card : _ → ℚ≥0) ⟨A, hA'⟩
  rw [mem_erase, mem_powerset, ← nonempty_iff_ne_empty] at hC
  

Proof state:
case intro.intro
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B✝ C✝ : Finset α
hA : Finset.Nonempty A
B : Finset α
m n : ℕ
hA' : A ∈ erase (powerset A) ∅
C : Finset α
hC : Finset.Nonempty C ∧ C ⊆ A
hCA : ∀ x' ∈ erase (powerset A) ∅, ↑(card (C * B)) / ↑(card C) ≤ ↑(card (x' * B)) / ↑(card x')
⊢ ↑(card (B ^ m / B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ (m + n) * ↑(card A)

Next tactic:
refine' (mul_le_mul_right <| cast_pos.2 hC.1.card_pos).1 _
/-- The **Plünnecke-Ruzsa inequality**. Multiplication version. Note that this is genuinely harder
than the division version because we cannot use a double counting argument. -/
@[to_additive "The **Plünnecke-Ruzsa inequality**. Addition version. Note that this is genuinely
harder than the subtraction version because we cannot use a double counting argument."]
theorem card_pow_div_pow_le (hA : A.Nonempty) (B : Finset α) (m n : ℕ) :
    ((B ^ m / B ^ n).card) ≤ ((A * B).card / A.card : ℚ≥0) ^ (m + n) * A.card := by
  have hA' : A ∈ A.powerset.erase ∅ := mem_erase_of_ne_of_mem hA.ne_empty (mem_powerset_self _)
  obtain ⟨C, hC, hCA⟩ :=
    exists_min_image (A.powerset.erase ∅) (fun C ↦ (C * B).card / C.card : _ → ℚ≥0) ⟨A, hA'⟩
  rw [mem_erase, mem_powerset, ← nonempty_iff_ne_empty] at hC
  refine' (mul_le_mul_right <| cast_pos.2 hC.1.card_pos).1 _
  

Proof state:
case intro.intro
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B✝ C✝ : Finset α
hA : Finset.Nonempty A
B : Finset α
m n : ℕ
hA' : A ∈ erase (powerset A) ∅
C : Finset α
hC : Finset.Nonempty C ∧ C ⊆ A
hCA : ∀ x' ∈ erase (powerset A) ∅, ↑(card (C * B)) / ↑(card C) ≤ ↑(card (x' * B)) / ↑(card x')
⊢ ↑(card (B ^ m / B ^ n)) * ↑(card C) ≤ (↑(card (A * B)) / ↑(card A)) ^ (m + n) * ↑(card A) * ↑(card C)

Next tactic:
norm_cast
/-- The **Plünnecke-Ruzsa inequality**. Multiplication version. Note that this is genuinely harder
than the division version because we cannot use a double counting argument. -/
@[to_additive "The **Plünnecke-Ruzsa inequality**. Addition version. Note that this is genuinely
harder than the subtraction version because we cannot use a double counting argument."]
theorem card_pow_div_pow_le (hA : A.Nonempty) (B : Finset α) (m n : ℕ) :
    ((B ^ m / B ^ n).card) ≤ ((A * B).card / A.card : ℚ≥0) ^ (m + n) * A.card := by
  have hA' : A ∈ A.powerset.erase ∅ := mem_erase_of_ne_of_mem hA.ne_empty (mem_powerset_self _)
  obtain ⟨C, hC, hCA⟩ :=
    exists_min_image (A.powerset.erase ∅) (fun C ↦ (C * B).card / C.card : _ → ℚ≥0) ⟨A, hA'⟩
  rw [mem_erase, mem_powerset, ← nonempty_iff_ne_empty] at hC
  refine' (mul_le_mul_right <| cast_pos.2 hC.1.card_pos).1 _
  norm_cast
  

Proof state:
case intro.intro
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B✝ C✝ : Finset α
hA : Finset.Nonempty A
B : Finset α
m n : ℕ
hA' : A ∈ erase (powerset A) ∅
C : Finset α
hC : Finset.Nonempty C ∧ C ⊆ A
hCA : ∀ x' ∈ erase (powerset A) ∅, ↑(card (C * B)) / ↑(card C) ≤ ↑(card (x' * B)) / ↑(card x')
⊢ ↑(card (B ^ m / B ^ n) * card C) ≤ (↑(card (A * B)) / ↑(card A)) ^ (m + n) * ↑(card A) * ↑(card C)

Next tactic:
refine' (cast_le.2 <| card_div_mul_le_card_mul_mul_card_mul _ _ _).trans _
/-- The **Plünnecke-Ruzsa inequality**. Multiplication version. Note that this is genuinely harder
than the division version because we cannot use a double counting argument. -/
@[to_additive "The **Plünnecke-Ruzsa inequality**. Addition version. Note that this is genuinely
harder than the subtraction version because we cannot use a double counting argument."]
theorem card_pow_div_pow_le (hA : A.Nonempty) (B : Finset α) (m n : ℕ) :
    ((B ^ m / B ^ n).card) ≤ ((A * B).card / A.card : ℚ≥0) ^ (m + n) * A.card := by
  have hA' : A ∈ A.powerset.erase ∅ := mem_erase_of_ne_of_mem hA.ne_empty (mem_powerset_self _)
  obtain ⟨C, hC, hCA⟩ :=
    exists_min_image (A.powerset.erase ∅) (fun C ↦ (C * B).card / C.card : _ → ℚ≥0) ⟨A, hA'⟩
  rw [mem_erase, mem_powerset, ← nonempty_iff_ne_empty] at hC
  refine' (mul_le_mul_right <| cast_pos.2 hC.1.card_pos).1 _
  norm_cast
  refine' (cast_le.2 <| card_div_mul_le_card_mul_mul_card_mul _ _ _).trans _
  

Proof state:
case intro.intro
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B✝ C✝ : Finset α
hA : Finset.Nonempty A
B : Finset α
m n : ℕ
hA' : A ∈ erase (powerset A) ∅
C : Finset α
hC : Finset.Nonempty C ∧ C ⊆ A
hCA : ∀ x' ∈ erase (powerset A) ∅, ↑(card (C * B)) / ↑(card C) ≤ ↑(card (x' * B)) / ↑(card x')
⊢ ↑(card (B ^ m * C) * card (C * B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ (m + n) * ↑(card A) * ↑(card C)

Next tactic:
push_cast
/-- The **Plünnecke-Ruzsa inequality**. Multiplication version. Note that this is genuinely harder
than the division version because we cannot use a double counting argument. -/
@[to_additive "The **Plünnecke-Ruzsa inequality**. Addition version. Note that this is genuinely
harder than the subtraction version because we cannot use a double counting argument."]
theorem card_pow_div_pow_le (hA : A.Nonempty) (B : Finset α) (m n : ℕ) :
    ((B ^ m / B ^ n).card) ≤ ((A * B).card / A.card : ℚ≥0) ^ (m + n) * A.card := by
  have hA' : A ∈ A.powerset.erase ∅ := mem_erase_of_ne_of_mem hA.ne_empty (mem_powerset_self _)
  obtain ⟨C, hC, hCA⟩ :=
    exists_min_image (A.powerset.erase ∅) (fun C ↦ (C * B).card / C.card : _ → ℚ≥0) ⟨A, hA'⟩
  rw [mem_erase, mem_powerset, ← nonempty_iff_ne_empty] at hC
  refine' (mul_le_mul_right <| cast_pos.2 hC.1.card_pos).1 _
  norm_cast
  refine' (cast_le.2 <| card_div_mul_le_card_mul_mul_card_mul _ _ _).trans _
  push_cast
  

Proof state:
case intro.intro
α : Type u_1
inst✝¹ : CommGroup α
inst✝ : DecidableEq α
A B✝ C✝ : Finset α
hA : Finset.Nonempty A
B : Finset α
m n : ℕ
hA' : A ∈ erase (powerset A) ∅
C : Finset α
hC : Finset.Nonempty C ∧ C ⊆ A
hCA : ∀ x' ∈ erase (powerset A) ∅, ↑(card (C * B)) / ↑(card C) ≤ ↑(card (x' * B)) / ↑(card x')
⊢ ↑(card (B ^ m * C)) * ↑(card (C * B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ (m + n) * ↑(card A) * ↑(card C)

Next tactic:
rw [mul_comm _ C]