-- Mathlib/Combinatorics/SetFamily/AhlswedeZhang.lean
private lemma binomial_sum_eq (h : n < m) :
    ∑ i ∈ range (n + 1), (n.choose i * (m - n) / ((m - i) * m.choose i) : ℚ) = 1

Proof state:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
i : ℕ
h₁ : i < n + 1
⊢ f i - f (i + 1) = ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Tactic:
have h₁ := le_of_lt_succ h₁

Result:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
i : ℕ
h₁✝ : i < n + 1
h₁ : i ≤ n
⊢ f i - f (i + 1) = ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Proof state:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
i : ℕ
h₁✝ : i < n + 1
h₁ : i ≤ n
h₂ : i < m
h₃ : i ≤ m
hi₄ : ↑i + 1 ≠ 0
this✝ : ↑(m.choose (i + 1)) * (↑i + 1) = ↑(m.choose i) * ↑(m - i)
this : ↑(n.choose (i + 1) * (i + 1)) = ↑(n.choose i * (n - i))
⊢ ↑(n.choose i) * (↑(m.choose i))⁻¹ - ↑(n.choose (i + 1)) * (↑(m.choose i) * ↑(m - i) * (↑i + 1)⁻¹)⁻¹ =
    ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Tactic:
push_cast at this

Result:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
i : ℕ
h₁✝ : i < n + 1
h₁ : i ≤ n
h₂ : i < m
h₃ : i ≤ m
hi₄ : ↑i + 1 ≠ 0
this✝ : ↑(m.choose (i + 1)) * (↑i + 1) = ↑(m.choose i) * ↑(m - i)
this : ↑(n.choose (i + 1)) * (↑i + 1) = ↑(n.choose i) * ↑(n - i)
⊢ ↑(n.choose i) * (↑(m.choose i))⁻¹ - ↑(n.choose (i + 1)) * (↑(m.choose i) * ↑(m - i) * (↑i + 1)⁻¹)⁻¹ =
    ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Proof state:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
i : ℕ
h₁✝ : i < n + 1
h₁ : i ≤ n
h₂ : i < m
h₃ : i ≤ m
hi₄ : ↑i + 1 ≠ 0
this✝ : ↑(m.choose (i + 1)) * (↑i + 1) = ↑(m.choose i) * ↑(m - i)
this : ↑(n.choose (i + 1)) * (↑i + 1) = ↑(n.choose i) * ↑(n - i)
⊢ ↑(n.choose i) * (↑(m.choose i))⁻¹ - ↑(n.choose (i + 1)) * (↑(m.choose i) * ↑(m - i) * (↑i + 1)⁻¹)⁻¹ =
    ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Tactic:
rw [(eq_mul_inv_iff_mul_eq₀ hi₄).mpr this]

Result:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
i : ℕ
h₁✝ : i < n + 1
h₁ : i ≤ n
h₂ : i < m
h₃ : i ≤ m
hi₄ : ↑i + 1 ≠ 0
this✝ : ↑(m.choose (i + 1)) * (↑i + 1) = ↑(m.choose i) * ↑(m - i)
this : ↑(n.choose (i + 1)) * (↑i + 1) = ↑(n.choose i) * ↑(n - i)
⊢ ↑(n.choose i) * (↑(m.choose i))⁻¹ -
      ↑(n.choose i) * ↑(n - i) * (↑i + 1)⁻¹ * (↑(m.choose i) * ↑(m - i) * (↑i + 1)⁻¹)⁻¹ =
    ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Proof state:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
i : ℕ
h₁✝ : i < n + 1
h₁ : i ≤ n
h₂ : i < m
h₃ : i ≤ m
hi₄ : ↑i + 1 ≠ 0
this : ↑(m.choose (i + 1) * (i + 1)) = ↑(m.choose i * (m - i))
⊢ f i - f (i + 1) = ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Tactic:
push_cast at this

Result:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
i : ℕ
h₁✝ : i < n + 1
h₁ : i ≤ n
h₂ : i < m
h₃ : i ≤ m
hi₄ : ↑i + 1 ≠ 0
this : ↑(m.choose (i + 1)) * (↑i + 1) = ↑(m.choose i) * ↑(m - i)
⊢ f i - f (i + 1) = ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Proof state:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
i : ℕ
h₁✝ : i < n + 1
h₁ : i ≤ n
h₂ : i < m
h₃ : i ≤ m
hi₄ : ↑i + 1 ≠ 0
this✝¹ : ↑(m.choose (i + 1)) * (↑i + 1) = ↑(m.choose i) * ↑(m - i)
this✝ : ↑(n.choose (i + 1)) * (↑i + 1) = ↑(n.choose i) * ↑(n - i)
this : ↑m - ↑i ≠ 0
⊢ ↑(n.choose i) * (↑(m.choose i))⁻¹ -
      ↑(n.choose i) * ↑(n - i) * (↑i + 1)⁻¹ * (↑(m.choose i) * ↑(m - i) * (↑i + 1)⁻¹)⁻¹ =
    ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Tactic:
have : (m.choose i : ℚ) ≠ 0 := cast_ne_zero.2 (choose_pos h₂.le).ne'

Result:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
i : ℕ
h₁✝ : i < n + 1
h₁ : i ≤ n
h₂ : i < m
h₃ : i ≤ m
hi₄ : ↑i + 1 ≠ 0
this✝² : ↑(m.choose (i + 1)) * (↑i + 1) = ↑(m.choose i) * ↑(m - i)
this✝¹ : ↑(n.choose (i + 1)) * (↑i + 1) = ↑(n.choose i) * ↑(n - i)
this✝ : ↑m - ↑i ≠ 0
this : ↑(m.choose i) ≠ 0
⊢ ↑(n.choose i) * (↑(m.choose i))⁻¹ -
      ↑(n.choose i) * ↑(n - i) * (↑i + 1)⁻¹ * (↑(m.choose i) * ↑(m - i) * (↑i + 1)⁻¹)⁻¹ =
    ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Proof state:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
⊢ ∑ i ∈ range (n + 1), ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i)) = 1

Tactic:
suffices ∀ i ∈ range (n + 1), f i - f (i + 1) = n.choose i * (m - n) / ((m - i) * m.choose i) by
  rw [← sum_congr rfl this, sum_range_sub', hf]
  simp [choose_self, choose_zero_right, choose_eq_zero_of_lt h]

Result:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
⊢ ∀ i ∈ range (n + 1), f i - f (i + 1) = ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Proof state:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
i : ℕ
h₁ : i ∈ range (n + 1)
⊢ f i - f (i + 1) = ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Tactic:
rw [mem_range] at h₁

Result:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
i : ℕ
h₁ : i < n + 1
⊢ f i - f (i + 1) = ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Proof state:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
i : ℕ
h₁✝ : i < n + 1
h₁ : i ≤ n
h₂ : i < m
h₃ : i ≤ m
hi₄ : ↑i + 1 ≠ 0
this✝² : ↑(m.choose (i + 1)) * (↑i + 1) = ↑(m.choose i) * ↑(m - i)
this✝¹ : ↑(n.choose (i + 1)) * (↑i + 1) = ↑(n.choose i) * ↑(n - i)
this✝ : ↑m - ↑i ≠ 0
this : ↑(m.choose i) ≠ 0
⊢ ↑(n.choose i) * (↑(m.choose i))⁻¹ -
      ↑(n.choose i) * ↑(n - i) * (↑i + 1)⁻¹ * (↑(m.choose i) * ↑(m - i) * (↑i + 1)⁻¹)⁻¹ =
    ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Tactic:
field_simp

Result:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
i : ℕ
h₁✝ : i < n + 1
h₁ : i ≤ n
h₂ : i < m
h₃ : i ≤ m
hi₄ : ↑i + 1 ≠ 0
this✝² : ↑(m.choose (i + 1)) * (↑i + 1) = ↑(m.choose i) * ↑(m - i)
this✝¹ : ↑(n.choose (i + 1)) * (↑i + 1) = ↑(n.choose i) * ↑(n - i)
this✝ : ↑m - ↑i ≠ 0
this : ↑(m.choose i) ≠ 0
⊢ (↑(n.choose i) * (↑(m.choose i) * (↑m - ↑i)) - ↑(m.choose i) * (↑(n.choose i) * (↑n - ↑i))) *
      ((↑m - ↑i) * ↑(m.choose i)) =
    ↑(n.choose i) * (↑m - ↑n) * (↑(m.choose i) * (↑(m.choose i) * (↑m - ↑i)))

Proof state:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
i : ℕ
h₁✝ : i < n + 1
h₁ : i ≤ n
h₂ : i < m
h₃ : i ≤ m
⊢ f i - f (i + 1) = ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Tactic:
have hi₄ : (i + 1 : ℚ) ≠ 0 := i.cast_add_one_ne_zero

Result:
m n : ℕ
h : n < m
f : ℕ → ℚ := fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
hf : f = fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹
i : ℕ
h₁✝ : i < n + 1
h₁ : i ≤ n
h₂ : i < m
h₃ : i ≤ m
hi₄ : ↑i + 1 ≠ 0
⊢ f i - f (i + 1) = ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))