l3lab/ntp-mathlib huggingface dataset:
/-- 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
  rw [mul_comm _ C]
  

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 (C * B ^ m)) * ↑(card (C * B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ (m + n) * ↑(card A) * ↑(card C)

Next tactic:
refine' (mul_le_mul (card_mul_pow_le (mul_aux hC.1 hC.2 hCA) _)
    (card_mul_pow_le (mul_aux hC.1 hC.2 hCA) _) (zero_le _) (zero_le _)).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 _
  push_cast
  rw [mul_comm _ C]
  refine' (mul_le_mul (card_mul_pow_le (mul_aux hC.1 hC.2 hCA) _)
    (card_mul_pow_le (mul_aux hC.1 hC.2 hCA) _) (zero_le _) (zero_le _)).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 (C * B)) / ↑(card C)) ^ m * ↑(card C) * ((↑(card (C * B)) / ↑(card C)) ^ n * ↑(card C)) ≤
    (↑(card (A * B)) / ↑(card A)) ^ (m + n) * ↑(card A) * ↑(card C)

Next tactic:
rw [mul_mul_mul_comm, ← pow_add, ← mul_assoc]
/-- 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
  rw [mul_comm _ C]
  refine' (mul_le_mul (card_mul_pow_le (mul_aux hC.1 hC.2 hCA) _)
    (card_mul_pow_le (mul_aux hC.1 hC.2 hCA) _) (zero_le _) (zero_le _)).trans _
  rw [mul_mul_mul_comm, ← pow_add, ← mul_assoc]
  

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 (C * B)) / ↑(card C)) ^ (m + n) * ↑(card C) * ↑(card C) ≤
    (↑(card (A * B)) / ↑(card A)) ^ (m + n) * ↑(card A) * ↑(card C)

Next tactic:
gcongr ((?_ ^ _) * Nat.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
  rw [mul_comm _ C]
  refine' (mul_le_mul (card_mul_pow_le (mul_aux hC.1 hC.2 hCA) _)
    (card_mul_pow_le (mul_aux hC.1 hC.2 hCA) _) (zero_le _) (zero_le _)).trans _
  rw [mul_mul_mul_comm, ← pow_add, ← mul_assoc]
  gcongr ((?_ ^ _) * Nat.cast ?_) * _
  · 

Proof state:
case intro.intro.bc.h₁.hab
α : 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 (C * B)) / ↑(card C) ≤ ↑(card (A * B)) / ↑(card A)

Next tactic:
exact hCA _ 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'⟩
  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
  rw [mul_comm _ C]
  refine' (mul_le_mul (card_mul_pow_le (mul_aux hC.1 hC.2 hCA) _)
    (card_mul_pow_le (mul_aux hC.1 hC.2 hCA) _) (zero_le _) (zero_le _)).trans _
  rw [mul_mul_mul_comm, ← pow_add, ← mul_assoc]
  gcongr ((?_ ^ _) * Nat.cast ?_) * _
  · exact hCA _ hA'
  · 

Proof state:
case intro.intro.bc.h₂.h
α : 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 C ≤ card A

Next tactic:
exact card_le_of_subset hC.2
/-- The **Plünnecke-Ruzsa inequality**. Subtraction version. -/
@[to_additive "The **Plünnecke-Ruzsa inequality**. Subtraction version."]
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:
rw [← card_inv, inv_div', ← inv_pow, ← inv_pow, div_eq_mul_inv A]
/-- The **Plünnecke-Ruzsa inequality**. Subtraction version. -/
@[to_additive "The **Plünnecke-Ruzsa inequality**. Subtraction version."]
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
  rw [← card_inv, inv_div', ← inv_pow, ← inv_pow, div_eq_mul_inv A]
  

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:
exact card_pow_div_pow_le hA _ _ _
/-- Special case of the **Plünnecke-Ruzsa inequality**. Multiplication version. -/
@[to_additive "Special case of the **Plünnecke-Ruzsa inequality**. Addition version."]
theorem card_pow_le (hA : A.Nonempty) (B : Finset α) (n : ℕ) :
    (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 α
hA : Finset.Nonempty A
B : Finset α
n : ℕ
⊢ ↑(card (B ^ n)) ≤ (↑(card (A * B)) / ↑(card A)) ^ n * ↑(card A)

Next tactic:
simpa only [_root_.pow_zero, div_one] using card_pow_div_pow_le hA _ _ 0
/-- Special case of the **Plünnecke-Ruzsa inequality**. Division version. -/
@[to_additive "Special case of the **Plünnecke-Ruzsa inequality**. Subtraction version."]
theorem card_pow_le' (hA : A.Nonempty) (B : Finset α) (n : ℕ) :
    (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 α
hA : Finset.Nonempty A
B : Finset α
n : ℕ
⊢ ↑(card (B ^ n)) ≤ (↑(card (A / B)) / ↑(card A)) ^ n * ↑(card A)

Next tactic:
simpa only [_root_.pow_zero, div_one] using card_pow_div_pow_le' hA _ _ 0
/-- Just a computational lemma we need for the next main proof. -/
protected theorem compExactValue_correctness_of_stream_eq_some_aux_comp {a : K} (b c : K)
    (fract_a_ne_zero : Int.fract a ≠ 0) :
    ((⌊a⌋ : K) * b + c) / Int.fract a + b = (b * a + c) / Int.fract a := by
  

Proof state:
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
a b c : K
fract_a_ne_zero : Int.fract a ≠ 0
⊢ (↑⌊a⌋ * b + c) / Int.fract a + b = (b * a + c) / Int.fract a

Next tactic:
field_simp [fract_a_ne_zero]
/-- Just a computational lemma we need for the next main proof. -/
protected theorem compExactValue_correctness_of_stream_eq_some_aux_comp {a : K} (b c : K)
    (fract_a_ne_zero : Int.fract a ≠ 0) :
    ((⌊a⌋ : K) * b + c) / Int.fract a + b = (b * a + c) / Int.fract a := by
  field_simp [fract_a_ne_zero]
  

Proof state:
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
a b c : K
fract_a_ne_zero : Int.fract a ≠ 0
⊢ ↑⌊a⌋ * b + c + b * Int.fract a = b * a + c

Next tactic:
rw [Int.fract]
/-- Just a computational lemma we need for the next main proof. -/
protected theorem compExactValue_correctness_of_stream_eq_some_aux_comp {a : K} (b c : K)
    (fract_a_ne_zero : Int.fract a ≠ 0) :
    ((⌊a⌋ : K) * b + c) / Int.fract a + b = (b * a + c) / Int.fract a := by
  field_simp [fract_a_ne_zero]
  rw [Int.fract]
  

Proof state:
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
a b c : K
fract_a_ne_zero : Int.fract a ≠ 0
⊢ ↑⌊a⌋ * b + c + b * (a - ↑⌊a⌋) = b * a + c

Next tactic:
ring
/-- Shows the correctness of `compExactValue` in case the continued fraction
`GeneralizedContinuedFraction.of v` did not terminate at position `n`. That is, we obtain the
value `v` if we pass the two successive (auxiliary) continuants at positions `n` and `n + 1` as well
as the fractional part at `IntFractPair.stream n` to `compExactValue`.

The correctness might be seen more readily if one uses `convergents'` to evaluate the continued
fraction. Here is an example to illustrate the idea:

Let `(v : ℚ) := 3.4`. We have
- `GeneralizedContinuedFraction.IntFractPair.stream v 0 = some ⟨3, 0.4⟩`, and
- `GeneralizedContinuedFraction.IntFractPair.stream v 1 = some ⟨2, 0.5⟩`.
Now `(GeneralizedContinuedFraction.of v).convergents' 1 = 3 + 1/2`, and our fractional term at
position `2` is `0.5`. We hence have `v = 3 + 1/(2 + 0.5) = 3 + 1/2.5 = 3.4`. This computation
corresponds exactly to the one using the recurrence equation in `compExactValue`.
-/
theorem compExactValue_correctness_of_stream_eq_some :
    ∀ {ifp_n : IntFractPair K}, IntFractPair.stream v n = some ifp_n →
      v = compExactValue ((of v).continuantsAux n) ((of v).continuantsAux <| n + 1) ifp_n.fr := by
  

Proof state:
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
⊢ ∀ {ifp_n : IntFractPair K},
    IntFractPair.stream v n = some ifp_n →
      v = compExactValue (continuantsAux (of v) n) (continuantsAux (of v) (n + 1)) ifp_n.fr

Next tactic:
let g := of v
/-- Shows the correctness of `compExactValue` in case the continued fraction
`GeneralizedContinuedFraction.of v` did not terminate at position `n`. That is, we obtain the
value `v` if we pass the two successive (auxiliary) continuants at positions `n` and `n + 1` as well
as the fractional part at `IntFractPair.stream n` to `compExactValue`.

The correctness might be seen more readily if one uses `convergents'` to evaluate the continued
fraction. Here is an example to illustrate the idea:

Let `(v : ℚ) := 3.4`. We have
- `GeneralizedContinuedFraction.IntFractPair.stream v 0 = some ⟨3, 0.4⟩`, and
- `GeneralizedContinuedFraction.IntFractPair.stream v 1 = some ⟨2, 0.5⟩`.
Now `(GeneralizedContinuedFraction.of v).convergents' 1 = 3 + 1/2`, and our fractional term at
position `2` is `0.5`. We hence have `v = 3 + 1/(2 + 0.5) = 3 + 1/2.5 = 3.4`. This computation
corresponds exactly to the one using the recurrence equation in `compExactValue`.
-/
theorem compExactValue_correctness_of_stream_eq_some :
    ∀ {ifp_n : IntFractPair K}, IntFractPair.stream v n = some ifp_n →
      v = compExactValue ((of v).continuantsAux n) ((of v).continuantsAux <| n + 1) ifp_n.fr := by
  let g := of v
  

Proof state:
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
g : GeneralizedContinuedFraction K := of v
⊢ ∀ {ifp_n : IntFractPair K},
    IntFractPair.stream v n = some ifp_n →
      v = compExactValue (continuantsAux (of v) n) (continuantsAux (of v) (n + 1)) ifp_n.fr

Next tactic:
induction' n with n IH
/-- Shows the correctness of `compExactValue` in case the continued fraction
`GeneralizedContinuedFraction.of v` did not terminate at position `n`. That is, we obtain the
value `v` if we pass the two successive (auxiliary) continuants at positions `n` and `n + 1` as well
as the fractional part at `IntFractPair.stream n` to `compExactValue`.

The correctness might be seen more readily if one uses `convergents'` to evaluate the continued
fraction. Here is an example to illustrate the idea:

Let `(v : ℚ) := 3.4`. We have
- `GeneralizedContinuedFraction.IntFractPair.stream v 0 = some ⟨3, 0.4⟩`, and
- `GeneralizedContinuedFraction.IntFractPair.stream v 1 = some ⟨2, 0.5⟩`.
Now `(GeneralizedContinuedFraction.of v).convergents' 1 = 3 + 1/2`, and our fractional term at
position `2` is `0.5`. We hence have `v = 3 + 1/(2 + 0.5) = 3 + 1/2.5 = 3.4`. This computation
corresponds exactly to the one using the recurrence equation in `compExactValue`.
-/
theorem compExactValue_correctness_of_stream_eq_some :
    ∀ {ifp_n : IntFractPair K}, IntFractPair.stream v n = some ifp_n →
      v = compExactValue ((of v).continuantsAux n) ((of v).continuantsAux <| n + 1) ifp_n.fr := by
  let g := of v
  induction' n with n IH
  · 

Proof state:
case zero
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
g : GeneralizedContinuedFraction K := of v
⊢ ∀ {ifp_n : IntFractPair K},
    IntFractPair.stream v Nat.zero = some ifp_n →
      v = compExactValue (continuantsAux (of v) Nat.zero) (continuantsAux (of v) (Nat.zero + 1)) ifp_n.fr

Next tactic:
intro ifp_zero stream_zero_eq
/-- Shows the correctness of `compExactValue` in case the continued fraction
`GeneralizedContinuedFraction.of v` did not terminate at position `n`. That is, we obtain the
value `v` if we pass the two successive (auxiliary) continuants at positions `n` and `n + 1` as well
as the fractional part at `IntFractPair.stream n` to `compExactValue`.

The correctness might be seen more readily if one uses `convergents'` to evaluate the continued
fraction. Here is an example to illustrate the idea:

Let `(v : ℚ) := 3.4`. We have
- `GeneralizedContinuedFraction.IntFractPair.stream v 0 = some ⟨3, 0.4⟩`, and
- `GeneralizedContinuedFraction.IntFractPair.stream v 1 = some ⟨2, 0.5⟩`.
Now `(GeneralizedContinuedFraction.of v).convergents' 1 = 3 + 1/2`, and our fractional term at
position `2` is `0.5`. We hence have `v = 3 + 1/(2 + 0.5) = 3 + 1/2.5 = 3.4`. This computation
corresponds exactly to the one using the recurrence equation in `compExactValue`.
-/
theorem compExactValue_correctness_of_stream_eq_some :
    ∀ {ifp_n : IntFractPair K}, IntFractPair.stream v n = some ifp_n →
      v = compExactValue ((of v).continuantsAux n) ((of v).continuantsAux <| n + 1) ifp_n.fr := by
  let g := of v
  induction' n with n IH
  · intro ifp_zero stream_zero_eq
    -- Nat.zero
    

Proof state:
case zero
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
g : GeneralizedContinuedFraction K := of v
ifp_zero : IntFractPair K
stream_zero_eq : IntFractPair.stream v Nat.zero = some ifp_zero
⊢ v = compExactValue (continuantsAux (of v) Nat.zero) (continuantsAux (of v) (Nat.zero + 1)) ifp_zero.fr

Next tactic:
have : IntFractPair.of v = ifp_zero := by
      have : IntFractPair.stream v 0 = some (IntFractPair.of v) := rfl
      simpa only [Nat.zero_eq, this, Option.some.injEq] using stream_zero_eq
/-- Shows the correctness of `compExactValue` in case the continued fraction
`GeneralizedContinuedFraction.of v` did not terminate at position `n`. That is, we obtain the
value `v` if we pass the two successive (auxiliary) continuants at positions `n` and `n + 1` as well
as the fractional part at `IntFractPair.stream n` to `compExactValue`.

The correctness might be seen more readily if one uses `convergents'` to evaluate the continued
fraction. Here is an example to illustrate the idea:

Let `(v : ℚ) := 3.4`. We have
- `GeneralizedContinuedFraction.IntFractPair.stream v 0 = some ⟨3, 0.4⟩`, and
- `GeneralizedContinuedFraction.IntFractPair.stream v 1 = some ⟨2, 0.5⟩`.
Now `(GeneralizedContinuedFraction.of v).convergents' 1 = 3 + 1/2`, and our fractional term at
position `2` is `0.5`. We hence have `v = 3 + 1/(2 + 0.5) = 3 + 1/2.5 = 3.4`. This computation
corresponds exactly to the one using the recurrence equation in `compExactValue`.
-/
theorem compExactValue_correctness_of_stream_eq_some :
    ∀ {ifp_n : IntFractPair K}, IntFractPair.stream v n = some ifp_n →
      v = compExactValue ((of v).continuantsAux n) ((of v).continuantsAux <| n + 1) ifp_n.fr := by
  let g := of v
  induction' n with n IH
  · intro ifp_zero stream_zero_eq
    -- Nat.zero
    have : IntFractPair.of v = ifp_zero := by
      

Proof state:
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
g : GeneralizedContinuedFraction K := of v
ifp_zero : IntFractPair K
stream_zero_eq : IntFractPair.stream v Nat.zero = some ifp_zero
⊢ IntFractPair.of v = ifp_zero

Next tactic:
have : IntFractPair.stream v 0 = some (IntFractPair.of v) := rfl
/-- Shows the correctness of `compExactValue` in case the continued fraction
`GeneralizedContinuedFraction.of v` did not terminate at position `n`. That is, we obtain the
value `v` if we pass the two successive (auxiliary) continuants at positions `n` and `n + 1` as well
as the fractional part at `IntFractPair.stream n` to `compExactValue`.

The correctness might be seen more readily if one uses `convergents'` to evaluate the continued
fraction. Here is an example to illustrate the idea:

Let `(v : ℚ) := 3.4`. We have
- `GeneralizedContinuedFraction.IntFractPair.stream v 0 = some ⟨3, 0.4⟩`, and
- `GeneralizedContinuedFraction.IntFractPair.stream v 1 = some ⟨2, 0.5⟩`.
Now `(GeneralizedContinuedFraction.of v).convergents' 1 = 3 + 1/2`, and our fractional term at
position `2` is `0.5`. We hence have `v = 3 + 1/(2 + 0.5) = 3 + 1/2.5 = 3.4`. This computation
corresponds exactly to the one using the recurrence equation in `compExactValue`.
-/
theorem compExactValue_correctness_of_stream_eq_some :
    ∀ {ifp_n : IntFractPair K}, IntFractPair.stream v n = some ifp_n →
      v = compExactValue ((of v).continuantsAux n) ((of v).continuantsAux <| n + 1) ifp_n.fr := by
  let g := of v
  induction' n with n IH
  · intro ifp_zero stream_zero_eq
    -- Nat.zero
    have : IntFractPair.of v = ifp_zero := by
      have : IntFractPair.stream v 0 = some (IntFractPair.of v) := rfl
      

Proof state:
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
g : GeneralizedContinuedFraction K := of v
ifp_zero : IntFractPair K
stream_zero_eq : IntFractPair.stream v Nat.zero = some ifp_zero
this : IntFractPair.stream v 0 = some (IntFractPair.of v)
⊢ IntFractPair.of v = ifp_zero

Next tactic:
simpa only [Nat.zero_eq, this, Option.some.injEq] using stream_zero_eq
/-- Shows the correctness of `compExactValue` in case the continued fraction
`GeneralizedContinuedFraction.of v` did not terminate at position `n`. That is, we obtain the
value `v` if we pass the two successive (auxiliary) continuants at positions `n` and `n + 1` as well
as the fractional part at `IntFractPair.stream n` to `compExactValue`.

The correctness might be seen more readily if one uses `convergents'` to evaluate the continued
fraction. Here is an example to illustrate the idea:

Let `(v : ℚ) := 3.4`. We have
- `GeneralizedContinuedFraction.IntFractPair.stream v 0 = some ⟨3, 0.4⟩`, and
- `GeneralizedContinuedFraction.IntFractPair.stream v 1 = some ⟨2, 0.5⟩`.
Now `(GeneralizedContinuedFraction.of v).convergents' 1 = 3 + 1/2`, and our fractional term at
position `2` is `0.5`. We hence have `v = 3 + 1/(2 + 0.5) = 3 + 1/2.5 = 3.4`. This computation
corresponds exactly to the one using the recurrence equation in `compExactValue`.
-/
theorem compExactValue_correctness_of_stream_eq_some :
    ∀ {ifp_n : IntFractPair K}, IntFractPair.stream v n = some ifp_n →
      v = compExactValue ((of v).continuantsAux n) ((of v).continuantsAux <| n + 1) ifp_n.fr := by
  let g := of v
  induction' n with n IH
  · intro ifp_zero stream_zero_eq
    -- Nat.zero
    have : IntFractPair.of v = ifp_zero := by
      have : IntFractPair.stream v 0 = some (IntFractPair.of v) := rfl
      simpa only [Nat.zero_eq, this, Option.some.injEq] using stream_zero_eq
    

Proof state:
case zero
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
g : GeneralizedContinuedFraction K := of v
ifp_zero : IntFractPair K
stream_zero_eq : IntFractPair.stream v Nat.zero = some ifp_zero
this : IntFractPair.of v = ifp_zero
⊢ v = compExactValue (continuantsAux (of v) Nat.zero) (continuantsAux (of v) (Nat.zero + 1)) ifp_zero.fr

Next tactic:
cases this