-- 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
h₁ : i ≤ n
⊢ f i - f (i + 1) = ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Tactic:
have h₂ := h₁.trans_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 : ℕ
h₁✝ : i < n + 1
h₁ : i ≤ n
h₂ : i < m
⊢ 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)
⊢ f i - f (i + 1) = ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Tactic:
dsimp [f, hf]

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)
⊢ ↑(n.choose i) * (↑(m.choose i))⁻¹ - ↑(n.choose (i + 1)) * (↑(m.choose (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) * ↑(n - i) * (↑i + 1)⁻¹ * (↑(m.choose i) * ↑(m - i) * (↑i + 1)⁻¹)⁻¹ =
    ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Tactic:
have : (m - i : ℚ) ≠ 0 := sub_ne_zero_of_ne (cast_lt.mpr h₂).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
⊢ ↑(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))⁻¹
this : ∀ i ∈ range (n + 1), f i - f (i + 1) = ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))
⊢ ∑ i ∈ range (n + 1), ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i)) = 1

Tactic:
rw [← sum_congr rfl this, sum_range_sub', hf]

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))⁻¹
this : ∀ i ∈ range (n + 1), f i - f (i + 1) = ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))
⊢ (fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹) 0 - (fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹) (n + 1) = 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
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))

Tactic:
have := congr_arg ((↑) : ℕ → ℚ) (choose_succ_right_eq m i)

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)
⊢ ↑(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:
have := congr_arg ((↑) : ℕ → ℚ) (choose_succ_right_eq n i)

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
⊢ f i - f (i + 1) = ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Tactic:
have h₃ := h₂.le

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
⊢ 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))⁻¹
this : ∀ i ∈ range (n + 1), f i - f (i + 1) = ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))
⊢ (fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹) 0 - (fun i => ↑(n.choose i) * (↑(m.choose i))⁻¹) (n + 1) = 1

Tactic:
simp [choose_self, choose_zero_right, choose_eq_zero_of_lt h]

Result:
no goals

Proof state:
m n : ℕ
h : n < m
⊢ ∑ i ∈ range (n + 1), ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i)) = 1

Tactic:
set f : ℕ → ℚ := fun i ↦ n.choose i * (m.choose i : ℚ)⁻¹ with hf

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), ↑(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 ∈ range (n + 1), f i - f (i + 1) = ↑(n.choose i) * (↑m - ↑n) / ((↑m - ↑i) * ↑(m.choose i))

Tactic:
intro i 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 ∈ 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 < 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)))

Tactic:
ring

Result:
no goals