l3lab/ntp-mathlib huggingface dataset:
/--
The dual basis of a powerbasis `{1, x, x²...}` under the trace form is `aᵢ / f'(x)`,
with `f` being the minimal polynomial of `x` and `f / (X - x) = ∑ aᵢxⁱ`.
-/
lemma traceForm_dualBasis_powerBasis_eq [FiniteDimensional K L] [IsSeparable K L]
    (pb : PowerBasis K L) (i) :
    (Algebra.traceForm K L).dualBasis (traceForm_nondegenerate K L) pb.basis i =
      (minpolyDiv K pb.gen).coeff i / aeval pb.gen (derivative <| minpoly K pb.gen) := by
  classical
  apply ((Algebra.traceForm K L).toDual (traceForm_nondegenerate K L)).injective
  apply pb.basis.ext
  intro j
  simp only [BilinForm.toDual_def, BilinForm.apply_dualBasis_left]
  apply (algebraMap K (AlgebraicClosure K)).injective
  have := congr_arg (coeff · i) (sum_smul_minpolyDiv_eq_X_pow (AlgebraicClosure K)
    pb.adjoin_gen_eq_top (r := j) (pb.finrank.symm ▸ j.prop))
  simp only [AlgEquiv.toAlgHom_eq_coe, Polynomial.map_smul, map_div₀,
    map_pow, RingHom.coe_coe, AlgHom.coe_coe, finset_sum_coeff, coeff_smul, coeff_map, smul_eq_mul,
    coeff_X_pow, ← Fin.ext_iff, @eq_comm _ i] at this
  rw [PowerBasis.coe_basis, Algebra.traceForm_apply, RingHom.map_ite_one_zero,
  ← this, trace_eq_sum_embeddings (E := AlgebraicClosure K)]
  apply Finset.sum_congr rfl
  intro σ _
  

Proof state:
case a.a
R : Type u_1
S : Type u_2
T : Type u_3
inst✝¹⁵ : CommRing R
inst✝¹⁴ : CommRing S
inst✝¹³ : CommRing T
inst✝¹² : Algebra R S
inst✝¹¹ : Algebra R T
K : Type u_4
L : Type u_5
inst✝¹⁰ : Field K
inst✝⁹ : Field L
inst✝⁸ : Algebra K L
ι κ : Type w
inst✝⁷ : Fintype ι
F : Type u_6
inst✝⁶ : Field F
inst✝⁵ : Algebra R L
inst✝⁴ : Algebra L F
inst✝³ : Algebra R F
inst✝² : IsScalarTower R L F
pb✝ : PowerBasis K L
inst✝¹ : FiniteDimensional K L
inst✝ : IsSeparable K L
pb : PowerBasis K L
i j : Fin pb.dim
this :
  ∑ x : L →ₐ[K] AlgebraicClosure K,
      x pb.gen ^ ↑j / x ((aeval pb.gen) (derivative (minpoly K pb.gen))) * x (coeff (minpolyDiv K pb.gen) ↑i) =
    if j = i then 1 else 0
σ : L →ₐ[K] AlgebraicClosure K
a✝ : σ ∈ Finset.univ
⊢ σ pb.gen ^ ↑j / σ ((aeval pb.gen) (derivative (minpoly K pb.gen))) * σ (coeff (minpolyDiv K pb.gen) ↑i) =
    σ (coeff (minpolyDiv K pb.gen) ↑i / (aeval pb.gen) (derivative (minpoly K pb.gen)) * (fun i => pb.gen ^ ↑i) j)

Next tactic:
simp only [_root_.map_mul, map_div₀, map_pow]
/--
The dual basis of a powerbasis `{1, x, x²...}` under the trace form is `aᵢ / f'(x)`,
with `f` being the minimal polynomial of `x` and `f / (X - x) = ∑ aᵢxⁱ`.
-/
lemma traceForm_dualBasis_powerBasis_eq [FiniteDimensional K L] [IsSeparable K L]
    (pb : PowerBasis K L) (i) :
    (Algebra.traceForm K L).dualBasis (traceForm_nondegenerate K L) pb.basis i =
      (minpolyDiv K pb.gen).coeff i / aeval pb.gen (derivative <| minpoly K pb.gen) := by
  classical
  apply ((Algebra.traceForm K L).toDual (traceForm_nondegenerate K L)).injective
  apply pb.basis.ext
  intro j
  simp only [BilinForm.toDual_def, BilinForm.apply_dualBasis_left]
  apply (algebraMap K (AlgebraicClosure K)).injective
  have := congr_arg (coeff · i) (sum_smul_minpolyDiv_eq_X_pow (AlgebraicClosure K)
    pb.adjoin_gen_eq_top (r := j) (pb.finrank.symm ▸ j.prop))
  simp only [AlgEquiv.toAlgHom_eq_coe, Polynomial.map_smul, map_div₀,
    map_pow, RingHom.coe_coe, AlgHom.coe_coe, finset_sum_coeff, coeff_smul, coeff_map, smul_eq_mul,
    coeff_X_pow, ← Fin.ext_iff, @eq_comm _ i] at this
  rw [PowerBasis.coe_basis, Algebra.traceForm_apply, RingHom.map_ite_one_zero,
  ← this, trace_eq_sum_embeddings (E := AlgebraicClosure K)]
  apply Finset.sum_congr rfl
  intro σ _
  simp only [_root_.map_mul, map_div₀, map_pow]
  

Proof state:
case a.a
R : Type u_1
S : Type u_2
T : Type u_3
inst✝¹⁵ : CommRing R
inst✝¹⁴ : CommRing S
inst✝¹³ : CommRing T
inst✝¹² : Algebra R S
inst✝¹¹ : Algebra R T
K : Type u_4
L : Type u_5
inst✝¹⁰ : Field K
inst✝⁹ : Field L
inst✝⁸ : Algebra K L
ι κ : Type w
inst✝⁷ : Fintype ι
F : Type u_6
inst✝⁶ : Field F
inst✝⁵ : Algebra R L
inst✝⁴ : Algebra L F
inst✝³ : Algebra R F
inst✝² : IsScalarTower R L F
pb✝ : PowerBasis K L
inst✝¹ : FiniteDimensional K L
inst✝ : IsSeparable K L
pb : PowerBasis K L
i j : Fin pb.dim
this :
  ∑ x : L →ₐ[K] AlgebraicClosure K,
      x pb.gen ^ ↑j / x ((aeval pb.gen) (derivative (minpoly K pb.gen))) * x (coeff (minpolyDiv K pb.gen) ↑i) =
    if j = i then 1 else 0
σ : L →ₐ[K] AlgebraicClosure K
a✝ : σ ∈ Finset.univ
⊢ σ pb.gen ^ ↑j / σ ((aeval pb.gen) (derivative (minpoly K pb.gen))) * σ (coeff (minpolyDiv K pb.gen) ↑i) =
    σ (coeff (minpolyDiv K pb.gen) ↑i) / σ ((aeval pb.gen) (derivative (minpoly K pb.gen))) * σ pb.gen ^ ↑j

Next tactic:
ring
/-- Binary **rearrangement inequality**. -/
theorem mul_add_mul_le_mul_add_mul (hab : a ≤ b) (hcd : c ≤ d) : a * d + b * c ≤ a * c + b * d := by
  

Proof state:
α : Type u
β : Type u_1
inst✝¹ : StrictOrderedSemiring α
a b c d : α
inst✝ : ExistsAddOfLE α
hab : a ≤ b
hcd : c ≤ d
⊢ a * d + b * c ≤ a * c + b * d

Next tactic:
obtain ⟨b, rfl⟩ := exists_add_of_le hab
/-- Binary **rearrangement inequality**. -/
theorem mul_add_mul_le_mul_add_mul (hab : a ≤ b) (hcd : c ≤ d) : a * d + b * c ≤ a * c + b * d := by
  obtain ⟨b, rfl⟩ := exists_add_of_le hab
  

Proof state:
case intro
α : Type u
β : Type u_1
inst✝¹ : StrictOrderedSemiring α
a c d : α
inst✝ : ExistsAddOfLE α
hcd : c ≤ d
b : α
hab : a ≤ a + b
⊢ a * d + (a + b) * c ≤ a * c + (a + b) * d

Next tactic:
obtain ⟨d, rfl⟩ := exists_add_of_le hcd
/-- Binary **rearrangement inequality**. -/
theorem mul_add_mul_le_mul_add_mul (hab : a ≤ b) (hcd : c ≤ d) : a * d + b * c ≤ a * c + b * d := by
  obtain ⟨b, rfl⟩ := exists_add_of_le hab
  obtain ⟨d, rfl⟩ := exists_add_of_le hcd
  

Proof state:
case intro.intro
α : Type u
β : Type u_1
inst✝¹ : StrictOrderedSemiring α
a c : α
inst✝ : ExistsAddOfLE α
b : α
hab : a ≤ a + b
d : α
hcd : c ≤ c + d
⊢ a * (c + d) + (a + b) * c ≤ a * c + (a + b) * (c + d)

Next tactic:
rw [mul_add, add_right_comm, mul_add, ← add_assoc]
/-- Binary **rearrangement inequality**. -/
theorem mul_add_mul_le_mul_add_mul (hab : a ≤ b) (hcd : c ≤ d) : a * d + b * c ≤ a * c + b * d := by
  obtain ⟨b, rfl⟩ := exists_add_of_le hab
  obtain ⟨d, rfl⟩ := exists_add_of_le hcd
  rw [mul_add, add_right_comm, mul_add, ← add_assoc]
  

Proof state:
case intro.intro
α : Type u
β : Type u_1
inst✝¹ : StrictOrderedSemiring α
a c : α
inst✝ : ExistsAddOfLE α
b : α
hab : a ≤ a + b
d : α
hcd : c ≤ c + d
⊢ a * c + (a + b) * c + a * d ≤ a * c + (a + b) * c + (a + b) * d

Next tactic:
exact add_le_add_left (mul_le_mul_of_nonneg_right hab <| (le_add_iff_nonneg_right _).1 hcd) _
/-- Binary **rearrangement inequality**. -/
theorem mul_add_mul_le_mul_add_mul' (hba : b ≤ a) (hdc : d ≤ c) :
    a • d + b • c ≤ a • c + b • d := by
  

Proof state:
α : Type u
β : Type u_1
inst✝¹ : StrictOrderedSemiring α
a b c d : α
inst✝ : ExistsAddOfLE α
hba : b ≤ a
hdc : d ≤ c
⊢ a • d + b • c ≤ a • c + b • d

Next tactic:
rw [add_comm (a • d), add_comm (a • c)]
/-- Binary **rearrangement inequality**. -/
theorem mul_add_mul_le_mul_add_mul' (hba : b ≤ a) (hdc : d ≤ c) :
    a • d + b • c ≤ a • c + b • d := by
  rw [add_comm (a • d), add_comm (a • c)]
  

Proof state:
α : Type u
β : Type u_1
inst✝¹ : StrictOrderedSemiring α
a b c d : α
inst✝ : ExistsAddOfLE α
hba : b ≤ a
hdc : d ≤ c
⊢ b • c + a • d ≤ b • d + a • c

Next tactic:
exact mul_add_mul_le_mul_add_mul hba hdc
/-- Binary strict **rearrangement inequality**. -/
theorem mul_add_mul_lt_mul_add_mul (hab : a < b) (hcd : c < d) : a * d + b * c < a * c + b * d := by
  

Proof state:
α : Type u
β : Type u_1
inst✝¹ : StrictOrderedSemiring α
a b c d : α
inst✝ : ExistsAddOfLE α
hab : a < b
hcd : c < d
⊢ a * d + b * c < a * c + b * d

Next tactic:
obtain ⟨b, rfl⟩ := exists_add_of_le hab.le
/-- Binary strict **rearrangement inequality**. -/
theorem mul_add_mul_lt_mul_add_mul (hab : a < b) (hcd : c < d) : a * d + b * c < a * c + b * d := by
  obtain ⟨b, rfl⟩ := exists_add_of_le hab.le
  

Proof state:
case intro
α : Type u
β : Type u_1
inst✝¹ : StrictOrderedSemiring α
a c d : α
inst✝ : ExistsAddOfLE α
hcd : c < d
b : α
hab : a < a + b
⊢ a * d + (a + b) * c < a * c + (a + b) * d

Next tactic:
obtain ⟨d, rfl⟩ := exists_add_of_le hcd.le
/-- Binary strict **rearrangement inequality**. -/
theorem mul_add_mul_lt_mul_add_mul (hab : a < b) (hcd : c < d) : a * d + b * c < a * c + b * d := by
  obtain ⟨b, rfl⟩ := exists_add_of_le hab.le
  obtain ⟨d, rfl⟩ := exists_add_of_le hcd.le
  

Proof state:
case intro.intro
α : Type u
β : Type u_1
inst✝¹ : StrictOrderedSemiring α
a c : α
inst✝ : ExistsAddOfLE α
b : α
hab : a < a + b
d : α
hcd : c < c + d
⊢ a * (c + d) + (a + b) * c < a * c + (a + b) * (c + d)

Next tactic:
rw [mul_add, add_right_comm, mul_add, ← add_assoc]
/-- Binary strict **rearrangement inequality**. -/
theorem mul_add_mul_lt_mul_add_mul (hab : a < b) (hcd : c < d) : a * d + b * c < a * c + b * d := by
  obtain ⟨b, rfl⟩ := exists_add_of_le hab.le
  obtain ⟨d, rfl⟩ := exists_add_of_le hcd.le
  rw [mul_add, add_right_comm, mul_add, ← add_assoc]
  

Proof state:
case intro.intro
α : Type u
β : Type u_1
inst✝¹ : StrictOrderedSemiring α
a c : α
inst✝ : ExistsAddOfLE α
b : α
hab : a < a + b
d : α
hcd : c < c + d
⊢ a * c + (a + b) * c + a * d < a * c + (a + b) * c + (a + b) * d

Next tactic:
exact add_lt_add_left (mul_lt_mul_of_pos_right hab <| (lt_add_iff_pos_right _).1 hcd) _
/-- Binary **rearrangement inequality**. -/
theorem mul_add_mul_lt_mul_add_mul' (hba : b < a) (hdc : d < c) :
    a • d + b • c < a • c + b • d := by
  

Proof state:
α : Type u
β : Type u_1
inst✝¹ : StrictOrderedSemiring α
a b c d : α
inst✝ : ExistsAddOfLE α
hba : b < a
hdc : d < c
⊢ a • d + b • c < a • c + b • d

Next tactic:
rw [add_comm (a • d), add_comm (a • c)]
/-- Binary **rearrangement inequality**. -/
theorem mul_add_mul_lt_mul_add_mul' (hba : b < a) (hdc : d < c) :
    a • d + b • c < a • c + b • d := by
  rw [add_comm (a • d), add_comm (a • c)]
  

Proof state:
α : Type u
β : Type u_1
inst✝¹ : StrictOrderedSemiring α
a b c d : α
inst✝ : ExistsAddOfLE α
hba : b < a
hdc : d < c
⊢ b • c + a • d < b • d + a • c

Next tactic:
exact mul_add_mul_lt_mul_add_mul hba hdc
instance (priority := 100) toCovariantClassMulLE : CovariantClass α α (· * ·) (· ≤ ·) := by
  

Proof state:
α : Type u
β : Type u_1
inst✝ : CanonicallyOrderedCommSemiring α
a b : α
⊢ CovariantClass α α (fun x x_1 => x * x_1) fun x x_1 => x ≤ x_1

Next tactic:
refine' ⟨fun a b c h => _⟩
instance (priority := 100) toCovariantClassMulLE : CovariantClass α α (· * ·) (· ≤ ·) := by
  refine' ⟨fun a b c h => _⟩
  

Proof state:
α : Type u
β : Type u_1
inst✝ : CanonicallyOrderedCommSemiring α
a✝ b✝ a b c : α
h : b ≤ c
⊢ a * b ≤ a * c

Next tactic:
rcases exists_add_of_le h with ⟨c, rfl⟩
instance (priority := 100) toCovariantClassMulLE : CovariantClass α α (· * ·) (· ≤ ·) := by
  refine' ⟨fun a b c h => _⟩
  rcases exists_add_of_le h with ⟨c, rfl⟩
  

Proof state:
case intro
α : Type u
β : Type u_1
inst✝ : CanonicallyOrderedCommSemiring α
a✝ b✝ a b c : α
h : b ≤ b + c
⊢ a * b ≤ a * (b + c)

Next tactic:
rw [mul_add]
instance (priority := 100) toCovariantClassMulLE : CovariantClass α α (· * ·) (· ≤ ·) := by
  refine' ⟨fun a b c h => _⟩
  rcases exists_add_of_le h with ⟨c, rfl⟩
  rw [mul_add]
  

Proof state:
case intro
α : Type u
β : Type u_1
inst✝ : CanonicallyOrderedCommSemiring α
a✝ b✝ a b c : α
h : b ≤ b + c
⊢ a * b ≤ a * b + a * c

Next tactic:
apply self_le_add_right
@[simp]
theorem mul_pos : 0 < a * b ↔ 0 < a ∧ 0 < b := by
  

Proof state:
α : Type u
β : Type u_1
inst✝ : CanonicallyOrderedCommSemiring α
a b : α
⊢ 0 < a * b ↔ 0 < a ∧ 0 < b

Next tactic:
simp only [pos_iff_ne_zero, ne_eq, mul_eq_zero, not_or]
protected theorem mul_tsub (h : AddLECancellable (a * c)) : a * (b - c) = a * b - a * c := by
  

Proof state:
α : Type u
β : Type u_1
inst✝³ : CanonicallyOrderedCommSemiring α
a b c : α
inst✝² : Sub α
inst✝¹ : OrderedSub α
inst✝ : IsTotal α fun x x_1 => x ≤ x_1
h : AddLECancellable (a * c)
⊢ a * (b - c) = a * b - a * c

Next tactic:
cases' total_of (· ≤ ·) b c with hbc hcb
protected theorem mul_tsub (h : AddLECancellable (a * c)) : a * (b - c) = a * b - a * c := by
  cases' total_of (· ≤ ·) b c with hbc hcb
  · 

Proof state:
case inl
α : Type u
β : Type u_1
inst✝³ : CanonicallyOrderedCommSemiring α
a b c : α
inst✝² : Sub α
inst✝¹ : OrderedSub α
inst✝ : IsTotal α fun x x_1 => x ≤ x_1
h : AddLECancellable (a * c)
hbc : b ≤ c
⊢ a * (b - c) = a * b - a * c

Next tactic:
rw [tsub_eq_zero_iff_le.2 hbc, mul_zero, tsub_eq_zero_iff_le.2 (mul_le_mul_left' hbc a)]
protected theorem mul_tsub (h : AddLECancellable (a * c)) : a * (b - c) = a * b - a * c := by
  cases' total_of (· ≤ ·) b c with hbc hcb
  · rw [tsub_eq_zero_iff_le.2 hbc, mul_zero, tsub_eq_zero_iff_le.2 (mul_le_mul_left' hbc a)]
  · 

Proof state:
case inr
α : Type u
β : Type u_1
inst✝³ : CanonicallyOrderedCommSemiring α
a b c : α
inst✝² : Sub α
inst✝¹ : OrderedSub α
inst✝ : IsTotal α fun x x_1 => x ≤ x_1
h : AddLECancellable (a * c)
hcb : c ≤ b
⊢ a * (b - c) = a * b - a * c

Next tactic:
apply h.eq_tsub_of_add_eq
protected theorem mul_tsub (h : AddLECancellable (a * c)) : a * (b - c) = a * b - a * c := by
  cases' total_of (· ≤ ·) b c with hbc hcb
  · rw [tsub_eq_zero_iff_le.2 hbc, mul_zero, tsub_eq_zero_iff_le.2 (mul_le_mul_left' hbc a)]
  · apply h.eq_tsub_of_add_eq
    

Proof state:
case inr
α : Type u
β : Type u_1
inst✝³ : CanonicallyOrderedCommSemiring α
a b c : α
inst✝² : Sub α
inst✝¹ : OrderedSub α
inst✝ : IsTotal α fun x x_1 => x ≤ x_1
h : AddLECancellable (a * c)
hcb : c ≤ b
⊢ a * (b - c) + a * c = a * b

Next tactic:
rw [← mul_add, tsub_add_cancel_of_le hcb]
protected theorem tsub_mul (h : AddLECancellable (b * c)) : (a - b) * c = a * c - b * c := by
  

Proof state:
α : Type u
β : Type u_1
inst✝³ : CanonicallyOrderedCommSemiring α
a b c : α
inst✝² : Sub α
inst✝¹ : OrderedSub α
inst✝ : IsTotal α fun x x_1 => x ≤ x_1
h : AddLECancellable (b * c)
⊢ (a - b) * c = a * c - b * c

Next tactic:
simp only [mul_comm _ c] at *
protected theorem tsub_mul (h : AddLECancellable (b * c)) : (a - b) * c = a * c - b * c := by
  simp only [mul_comm _ c] at *
  

Proof state:
α : Type u
β : Type u_1
inst✝³ : CanonicallyOrderedCommSemiring α
a b c : α
inst✝² : Sub α
inst✝¹ : OrderedSub α
inst✝ : IsTotal α fun x x_1 => x ≤ x_1
h : AddLECancellable (c * b)
⊢ c * (a - b) = c * a - c * b

Next tactic:
exact h.mul_tsub
@[simp]
theorem zero_mk (d) (h : d ≠ 0) (w) : mk' 0 d h w = 0 := by 

Proof state:
d : ℕ
h : d ≠ 0
w : Nat.Coprime (Int.natAbs 0) d
⊢ mk' 0 d = 0

Next tactic:
congr
@[simp]
lemma num_eq_zero {q : ℚ} : q.num = 0 ↔ q = 0 := by
  

Proof state:
q : ℚ
⊢ q.num = 0 ↔ q = 0

Next tactic:
induction q
@[simp]
lemma num_eq_zero {q : ℚ} : q.num = 0 ↔ q = 0 := by
  induction q
  

Proof state:
case mk'
num✝ : ℤ
den✝ : ℕ
den_nz✝ : den✝ ≠ 0
reduced✝ : Nat.Coprime (Int.natAbs num✝) den✝
⊢ (mk' num✝ den✝).num = 0 ↔ mk' num✝ den✝ = 0

Next tactic:
constructor
@[simp]
lemma num_eq_zero {q : ℚ} : q.num = 0 ↔ q = 0 := by
  induction q
  constructor
  · 

Proof state:
case mk'.mp
num✝ : ℤ
den✝ : ℕ
den_nz✝ : den✝ ≠ 0
reduced✝ : Nat.Coprime (Int.natAbs num✝) den✝
⊢ (mk' num✝ den✝).num = 0 → mk' num✝ den✝ = 0

Next tactic:
rintro rfl
@[simp]
lemma num_eq_zero {q : ℚ} : q.num = 0 ↔ q = 0 := by
  induction q
  constructor
  · rintro rfl
    

Proof state:
case mk'.mp
den✝ : ℕ
den_nz✝ : den✝ ≠ 0
reduced✝ : Nat.Coprime (Int.natAbs 0) den✝
⊢ mk' 0 den✝ = 0

Next tactic:
exact zero_mk _ _ _
@[simp]
lemma num_eq_zero {q : ℚ} : q.num = 0 ↔ q = 0 := by
  induction q
  constructor
  · rintro rfl
    exact zero_mk _ _ _
  · 

Proof state:
case mk'.mpr
num✝ : ℤ
den✝ : ℕ
den_nz✝ : den✝ ≠ 0
reduced✝ : Nat.Coprime (Int.natAbs num✝) den✝
⊢ mk' num✝ den✝ = 0 → (mk' num✝ den✝).num = 0

Next tactic:
exact congr_arg num
@[simp]
theorem divInt_eq_zero {a b : ℤ} (b0 : b ≠ 0) : a /. b = 0 ↔ a = 0 := by
  

Proof state:
a b : ℤ
b0 : b ≠ 0
⊢ a /. b = 0 ↔ a = 0

Next tactic:
rw [← zero_divInt b, divInt_eq_iff b0 b0, zero_mul, mul_eq_zero, or_iff_left b0]
/-- Define a (dependent) function or prove `∀ r : ℚ, p r` by dealing with rational
numbers of the form `n /. d` with `0 < d` and coprime `n`, `d`. -/
@[elab_as_elim]
def numDenCasesOn.{u} {C : ℚ → Sort u} :
    ∀ (a : ℚ) (_ : ∀ n d, 0 < d → (Int.natAbs n).Coprime d → C (n /. d)), C a
  | ⟨n, d, h, c⟩, H => by 

Proof state:
C : ℚ → Sort u
n : ℤ
d : ℕ
h : d ≠ 0
c : Nat.Coprime (Int.natAbs n) d
H : (n : ℤ) → (d : ℕ) → 0 < d → Nat.Coprime (Int.natAbs n) d → C (n /. ↑d)
⊢ C (mk' n d)

Next tactic:
rw [num_den']
/-- Define a (dependent) function or prove `∀ r : ℚ, p r` by dealing with rational
numbers of the form `n /. d` with `0 < d` and coprime `n`, `d`. -/
@[elab_as_elim]
def numDenCasesOn.{u} {C : ℚ → Sort u} :
    ∀ (a : ℚ) (_ : ∀ n d, 0 < d → (Int.natAbs n).Coprime d → C (n /. d)), C a
  | ⟨n, d, h, c⟩, H => by rw [num_den']; 

Proof state:
C : ℚ → Sort u
n : ℤ
d : ℕ
h : d ≠ 0
c : Nat.Coprime (Int.natAbs n) d
H : (n : ℤ) → (d : ℕ) → 0 < d → Nat.Coprime (Int.natAbs n) d → C (n /. ↑d)
⊢ C (n /. ↑d)

Next tactic:
exact H n d (Nat.pos_of_ne_zero h) c
theorem lift_binop_eq (f : ℚ → ℚ → ℚ) (f₁ : ℤ → ℤ → ℤ → ℤ → ℤ) (f₂ : ℤ → ℤ → ℤ → ℤ → ℤ)
    (fv :
      ∀ {n₁ d₁ h₁ c₁ n₂ d₂ h₂ c₂},
        f ⟨n₁, d₁, h₁, c₁⟩ ⟨n₂, d₂, h₂, c₂⟩ = f₁ n₁ d₁ n₂ d₂ /. f₂ n₁ d₁ n₂ d₂)
    (f0 : ∀ {n₁ d₁ n₂ d₂}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0) (a b c d : ℤ)
    (b0 : b ≠ 0) (d0 : d ≠ 0)
    (H :
      ∀ {n₁ d₁ n₂ d₂}, a * d₁ = n₁ * b → c * d₂ = n₂ * d →
        f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂) :
    f (a /. b) (c /. d) = f₁ a b c d /. f₂ a b c d := by
  

Proof state:
f : ℚ → ℚ → ℚ
f₁ f₂ : ℤ → ℤ → ℤ → ℤ → ℤ
fv :
  ∀ {n₁ : ℤ} {d₁ : ℕ} {h₁ : d₁ ≠ 0} {c₁ : Nat.Coprime (Int.natAbs n₁) d₁} {n₂ : ℤ} {d₂ : ℕ} {h₂ : d₂ ≠ 0}
    {c₂ : Nat.Coprime (Int.natAbs n₂) d₂}, f (mk' n₁ d₁) (mk' n₂ d₂) = f₁ n₁ (↑d₁) n₂ ↑d₂ /. f₂ n₁ (↑d₁) n₂ ↑d₂
f0 : ∀ {n₁ d₁ n₂ d₂ : ℤ}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0
a b c d : ℤ
b0 : b ≠ 0
d0 : d ≠ 0
H : ∀ {n₁ d₁ n₂ d₂ : ℤ}, a * d₁ = n₁ * b → c * d₂ = n₂ * d → f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂
⊢ f (a /. b) (c /. d) = f₁ a b c d /. f₂ a b c d

Next tactic:
generalize ha : a /. b = x
theorem lift_binop_eq (f : ℚ → ℚ → ℚ) (f₁ : ℤ → ℤ → ℤ → ℤ → ℤ) (f₂ : ℤ → ℤ → ℤ → ℤ → ℤ)
    (fv :
      ∀ {n₁ d₁ h₁ c₁ n₂ d₂ h₂ c₂},
        f ⟨n₁, d₁, h₁, c₁⟩ ⟨n₂, d₂, h₂, c₂⟩ = f₁ n₁ d₁ n₂ d₂ /. f₂ n₁ d₁ n₂ d₂)
    (f0 : ∀ {n₁ d₁ n₂ d₂}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0) (a b c d : ℤ)
    (b0 : b ≠ 0) (d0 : d ≠ 0)
    (H :
      ∀ {n₁ d₁ n₂ d₂}, a * d₁ = n₁ * b → c * d₂ = n₂ * d →
        f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂) :
    f (a /. b) (c /. d) = f₁ a b c d /. f₂ a b c d := by
  generalize ha : a /. b = x; 

Proof state:
f : ℚ → ℚ → ℚ
f₁ f₂ : ℤ → ℤ → ℤ → ℤ → ℤ
fv :
  ∀ {n₁ : ℤ} {d₁ : ℕ} {h₁ : d₁ ≠ 0} {c₁ : Nat.Coprime (Int.natAbs n₁) d₁} {n₂ : ℤ} {d₂ : ℕ} {h₂ : d₂ ≠ 0}
    {c₂ : Nat.Coprime (Int.natAbs n₂) d₂}, f (mk' n₁ d₁) (mk' n₂ d₂) = f₁ n₁ (↑d₁) n₂ ↑d₂ /. f₂ n₁ (↑d₁) n₂ ↑d₂
f0 : ∀ {n₁ d₁ n₂ d₂ : ℤ}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0
a b c d : ℤ
b0 : b ≠ 0
d0 : d ≠ 0
H : ∀ {n₁ d₁ n₂ d₂ : ℤ}, a * d₁ = n₁ * b → c * d₂ = n₂ * d → f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂
x : ℚ
ha : a /. b = x
⊢ f x (c /. d) = f₁ a b c d /. f₂ a b c d

Next tactic:
cases' x with n₁ d₁ h₁ c₁
theorem lift_binop_eq (f : ℚ → ℚ → ℚ) (f₁ : ℤ → ℤ → ℤ → ℤ → ℤ) (f₂ : ℤ → ℤ → ℤ → ℤ → ℤ)
    (fv :
      ∀ {n₁ d₁ h₁ c₁ n₂ d₂ h₂ c₂},
        f ⟨n₁, d₁, h₁, c₁⟩ ⟨n₂, d₂, h₂, c₂⟩ = f₁ n₁ d₁ n₂ d₂ /. f₂ n₁ d₁ n₂ d₂)
    (f0 : ∀ {n₁ d₁ n₂ d₂}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0) (a b c d : ℤ)
    (b0 : b ≠ 0) (d0 : d ≠ 0)
    (H :
      ∀ {n₁ d₁ n₂ d₂}, a * d₁ = n₁ * b → c * d₂ = n₂ * d →
        f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂) :
    f (a /. b) (c /. d) = f₁ a b c d /. f₂ a b c d := by
  generalize ha : a /. b = x; cases' x with n₁ d₁ h₁ c₁; 

Proof state:
case mk'
f : ℚ → ℚ → ℚ
f₁ f₂ : ℤ → ℤ → ℤ → ℤ → ℤ
fv :
  ∀ {n₁ : ℤ} {d₁ : ℕ} {h₁ : d₁ ≠ 0} {c₁ : Nat.Coprime (Int.natAbs n₁) d₁} {n₂ : ℤ} {d₂ : ℕ} {h₂ : d₂ ≠ 0}
    {c₂ : Nat.Coprime (Int.natAbs n₂) d₂}, f (mk' n₁ d₁) (mk' n₂ d₂) = f₁ n₁ (↑d₁) n₂ ↑d₂ /. f₂ n₁ (↑d₁) n₂ ↑d₂
f0 : ∀ {n₁ d₁ n₂ d₂ : ℤ}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0
a b c d : ℤ
b0 : b ≠ 0
d0 : d ≠ 0
H : ∀ {n₁ d₁ n₂ d₂ : ℤ}, a * d₁ = n₁ * b → c * d₂ = n₂ * d → f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
c₁ : Nat.Coprime (Int.natAbs n₁) d₁
ha : a /. b = mk' n₁ d₁
⊢ f (mk' n₁ d₁) (c /. d) = f₁ a b c d /. f₂ a b c d

Next tactic:
rw [num_den'] at ha
theorem lift_binop_eq (f : ℚ → ℚ → ℚ) (f₁ : ℤ → ℤ → ℤ → ℤ → ℤ) (f₂ : ℤ → ℤ → ℤ → ℤ → ℤ)
    (fv :
      ∀ {n₁ d₁ h₁ c₁ n₂ d₂ h₂ c₂},
        f ⟨n₁, d₁, h₁, c₁⟩ ⟨n₂, d₂, h₂, c₂⟩ = f₁ n₁ d₁ n₂ d₂ /. f₂ n₁ d₁ n₂ d₂)
    (f0 : ∀ {n₁ d₁ n₂ d₂}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0) (a b c d : ℤ)
    (b0 : b ≠ 0) (d0 : d ≠ 0)
    (H :
      ∀ {n₁ d₁ n₂ d₂}, a * d₁ = n₁ * b → c * d₂ = n₂ * d →
        f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂) :
    f (a /. b) (c /. d) = f₁ a b c d /. f₂ a b c d := by
  generalize ha : a /. b = x; cases' x with n₁ d₁ h₁ c₁; rw [num_den'] at ha
  

Proof state:
case mk'
f : ℚ → ℚ → ℚ
f₁ f₂ : ℤ → ℤ → ℤ → ℤ → ℤ
fv :
  ∀ {n₁ : ℤ} {d₁ : ℕ} {h₁ : d₁ ≠ 0} {c₁ : Nat.Coprime (Int.natAbs n₁) d₁} {n₂ : ℤ} {d₂ : ℕ} {h₂ : d₂ ≠ 0}
    {c₂ : Nat.Coprime (Int.natAbs n₂) d₂}, f (mk' n₁ d₁) (mk' n₂ d₂) = f₁ n₁ (↑d₁) n₂ ↑d₂ /. f₂ n₁ (↑d₁) n₂ ↑d₂
f0 : ∀ {n₁ d₁ n₂ d₂ : ℤ}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0
a b c d : ℤ
b0 : b ≠ 0
d0 : d ≠ 0
H : ∀ {n₁ d₁ n₂ d₂ : ℤ}, a * d₁ = n₁ * b → c * d₂ = n₂ * d → f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
c₁ : Nat.Coprime (Int.natAbs n₁) d₁
ha : a /. b = n₁ /. ↑d₁
⊢ f (mk' n₁ d₁) (c /. d) = f₁ a b c d /. f₂ a b c d

Next tactic:
generalize hc : c /. d = x
theorem lift_binop_eq (f : ℚ → ℚ → ℚ) (f₁ : ℤ → ℤ → ℤ → ℤ → ℤ) (f₂ : ℤ → ℤ → ℤ → ℤ → ℤ)
    (fv :
      ∀ {n₁ d₁ h₁ c₁ n₂ d₂ h₂ c₂},
        f ⟨n₁, d₁, h₁, c₁⟩ ⟨n₂, d₂, h₂, c₂⟩ = f₁ n₁ d₁ n₂ d₂ /. f₂ n₁ d₁ n₂ d₂)
    (f0 : ∀ {n₁ d₁ n₂ d₂}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0) (a b c d : ℤ)
    (b0 : b ≠ 0) (d0 : d ≠ 0)
    (H :
      ∀ {n₁ d₁ n₂ d₂}, a * d₁ = n₁ * b → c * d₂ = n₂ * d →
        f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂) :
    f (a /. b) (c /. d) = f₁ a b c d /. f₂ a b c d := by
  generalize ha : a /. b = x; cases' x with n₁ d₁ h₁ c₁; rw [num_den'] at ha
  generalize hc : c /. d = x; 

Proof state:
case mk'
f : ℚ → ℚ → ℚ
f₁ f₂ : ℤ → ℤ → ℤ → ℤ → ℤ
fv :
  ∀ {n₁ : ℤ} {d₁ : ℕ} {h₁ : d₁ ≠ 0} {c₁ : Nat.Coprime (Int.natAbs n₁) d₁} {n₂ : ℤ} {d₂ : ℕ} {h₂ : d₂ ≠ 0}
    {c₂ : Nat.Coprime (Int.natAbs n₂) d₂}, f (mk' n₁ d₁) (mk' n₂ d₂) = f₁ n₁ (↑d₁) n₂ ↑d₂ /. f₂ n₁ (↑d₁) n₂ ↑d₂
f0 : ∀ {n₁ d₁ n₂ d₂ : ℤ}, d₁ ≠ 0 → d₂ ≠ 0 → f₂ n₁ d₁ n₂ d₂ ≠ 0
a b c d : ℤ
b0 : b ≠ 0
d0 : d ≠ 0
H : ∀ {n₁ d₁ n₂ d₂ : ℤ}, a * d₁ = n₁ * b → c * d₂ = n₂ * d → f₁ n₁ d₁ n₂ d₂ * f₂ a b c d = f₁ a b c d * f₂ n₁ d₁ n₂ d₂
n₁ : ℤ
d₁ : ℕ
h₁ : d₁ ≠ 0
c₁ : Nat.Coprime (Int.natAbs n₁) d₁
ha : a /. b = n₁ /. ↑d₁
x : ℚ
hc : c /. d = x
⊢ f (mk' n₁ d₁) x = f₁ a b c d /. f₂ a b c d

Next tactic:
cases' x with n₂ d₂ h₂ c₂