l3lab/ntp-mathlib huggingface dataset:
theorem jacobiSymNat.even_odd₇ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 7)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 3; rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]; congr
  rw [jacobiSymNat, ← Nat.mod_add_div a 2, ha, hc, Nat.zero_add, Nat.cast_mul, jacobiSym.mul_left,
    Nat.cast_two, jacobiSym.at_two hb', ZMod.χ₈_nat_mod_eight, hb,
    (by 

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 7
hc : a / 2 = c
hr : jacobiSymNat c b = r
hb' : Odd b
⊢ ZMod.χ₈ ↑7 = 1

Next tactic:
decide
theorem jacobiSymNat.even_odd₇ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 7)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 3; rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]; congr
  rw [jacobiSymNat, ← Nat.mod_add_div a 2, ha, hc, Nat.zero_add, Nat.cast_mul, jacobiSym.mul_left,
    Nat.cast_two, jacobiSym.at_two hb', ZMod.χ₈_nat_mod_eight, hb,
    (by decide : ZMod.χ₈ (7 : ℕ) = 1)]
  

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 7
hc : a / 2 = c
hr : jacobiSymNat c b = r
hb' : Odd b
⊢ 1 * jacobiSym (↑c) b = r

Next tactic:
norm_num
theorem jacobiSymNat.even_odd₇ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 7)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 3; rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]; congr
  rw [jacobiSymNat, ← Nat.mod_add_div a 2, ha, hc, Nat.zero_add, Nat.cast_mul, jacobiSym.mul_left,
    Nat.cast_two, jacobiSym.at_two hb', ZMod.χ₈_nat_mod_eight, hb,
    (by decide : ZMod.χ₈ (7 : ℕ) = 1)]
  norm_num
  

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 7
hc : a / 2 = c
hr : jacobiSymNat c b = r
hb' : Odd b
⊢ jacobiSym (↑c) b = r

Next tactic:
exact hr
theorem jacobiSymNat.even_odd₃ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 3)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 3
hc : a / 2 = c
hr : jacobiSymNat c b = r
⊢ jacobiSymNat a b = -r

Next tactic:
have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 1; rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]; congr
theorem jacobiSymNat.even_odd₃ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 3)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  have hb' : Odd b := by
    

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 3
hc : a / 2 = c
hr : jacobiSymNat c b = r
⊢ Odd b

Next tactic:
rw [← Nat.div_add_mod b 8, hb, Odd]
theorem jacobiSymNat.even_odd₃ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 3)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 3
hc : a / 2 = c
hr : jacobiSymNat c b = r
⊢ ∃ k, 8 * (b / 8) + 3 = 2 * k + 1

Next tactic:
use 4 * (b / 8) + 1
theorem jacobiSymNat.even_odd₃ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 3)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 1; 

Proof state:
case h
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 3
hc : a / 2 = c
hr : jacobiSymNat c b = r
⊢ 8 * (b / 8) + 3 = 2 * (4 * (b / 8) + 1) + 1

Next tactic:
rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]
theorem jacobiSymNat.even_odd₃ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 3)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 1; rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]; 

Proof state:
case h
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 3
hc : a / 2 = c
hr : jacobiSymNat c b = r
⊢ 8 * (b / 8) + 3 = 2 * 4 * (b / 8) + (2 * 1 + 1)

Next tactic:
congr
theorem jacobiSymNat.even_odd₃ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 3)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 1; rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]; congr
  

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 3
hc : a / 2 = c
hr : jacobiSymNat c b = r
hb' : Odd b
⊢ jacobiSymNat a b = -r

Next tactic:
rw [jacobiSymNat, ← Nat.mod_add_div a 2, ha, hc, Nat.zero_add, Nat.cast_mul, jacobiSym.mul_left,
    Nat.cast_two, jacobiSym.at_two hb', ZMod.χ₈_nat_mod_eight, hb,
    (by decide : ZMod.χ₈ (3 : ℕ) = -1)]
theorem jacobiSymNat.even_odd₃ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 3)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 1; rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]; congr
  rw [jacobiSymNat, ← Nat.mod_add_div a 2, ha, hc, Nat.zero_add, Nat.cast_mul, jacobiSym.mul_left,
    Nat.cast_two, jacobiSym.at_two hb', ZMod.χ₈_nat_mod_eight, hb,
    (by 

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 3
hc : a / 2 = c
hr : jacobiSymNat c b = r
hb' : Odd b
⊢ ZMod.χ₈ ↑3 = -1

Next tactic:
decide
theorem jacobiSymNat.even_odd₃ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 3)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 1; rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]; congr
  rw [jacobiSymNat, ← Nat.mod_add_div a 2, ha, hc, Nat.zero_add, Nat.cast_mul, jacobiSym.mul_left,
    Nat.cast_two, jacobiSym.at_two hb', ZMod.χ₈_nat_mod_eight, hb,
    (by decide : ZMod.χ₈ (3 : ℕ) = -1)]
  

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 3
hc : a / 2 = c
hr : jacobiSymNat c b = r
hb' : Odd b
⊢ -1 * jacobiSym (↑c) b = -r

Next tactic:
norm_num
theorem jacobiSymNat.even_odd₃ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 3)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 1; rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]; congr
  rw [jacobiSymNat, ← Nat.mod_add_div a 2, ha, hc, Nat.zero_add, Nat.cast_mul, jacobiSym.mul_left,
    Nat.cast_two, jacobiSym.at_two hb', ZMod.χ₈_nat_mod_eight, hb,
    (by decide : ZMod.χ₈ (3 : ℕ) = -1)]
  norm_num
  

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 3
hc : a / 2 = c
hr : jacobiSymNat c b = r
hb' : Odd b
⊢ jacobiSym (↑c) b = r

Next tactic:
exact hr
theorem jacobiSymNat.even_odd₅ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 5)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 5
hc : a / 2 = c
hr : jacobiSymNat c b = r
⊢ jacobiSymNat a b = -r

Next tactic:
have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 2; rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]; congr
theorem jacobiSymNat.even_odd₅ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 5)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  have hb' : Odd b := by
    

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 5
hc : a / 2 = c
hr : jacobiSymNat c b = r
⊢ Odd b

Next tactic:
rw [← Nat.div_add_mod b 8, hb, Odd]
theorem jacobiSymNat.even_odd₅ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 5)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 5
hc : a / 2 = c
hr : jacobiSymNat c b = r
⊢ ∃ k, 8 * (b / 8) + 5 = 2 * k + 1

Next tactic:
use 4 * (b / 8) + 2
theorem jacobiSymNat.even_odd₅ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 5)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 2; 

Proof state:
case h
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 5
hc : a / 2 = c
hr : jacobiSymNat c b = r
⊢ 8 * (b / 8) + 5 = 2 * (4 * (b / 8) + 2) + 1

Next tactic:
rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]
theorem jacobiSymNat.even_odd₅ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 5)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 2; rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]; 

Proof state:
case h
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 5
hc : a / 2 = c
hr : jacobiSymNat c b = r
⊢ 8 * (b / 8) + 5 = 2 * 4 * (b / 8) + (2 * 2 + 1)

Next tactic:
congr
theorem jacobiSymNat.even_odd₅ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 5)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 2; rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]; congr
  

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 5
hc : a / 2 = c
hr : jacobiSymNat c b = r
hb' : Odd b
⊢ jacobiSymNat a b = -r

Next tactic:
rw [jacobiSymNat, ← Nat.mod_add_div a 2, ha, hc, Nat.zero_add, Nat.cast_mul, jacobiSym.mul_left,
    Nat.cast_two, jacobiSym.at_two hb', ZMod.χ₈_nat_mod_eight, hb,
    (by decide : ZMod.χ₈ (5 : ℕ) = -1)]
theorem jacobiSymNat.even_odd₅ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 5)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 2; rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]; congr
  rw [jacobiSymNat, ← Nat.mod_add_div a 2, ha, hc, Nat.zero_add, Nat.cast_mul, jacobiSym.mul_left,
    Nat.cast_two, jacobiSym.at_two hb', ZMod.χ₈_nat_mod_eight, hb,
    (by 

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 5
hc : a / 2 = c
hr : jacobiSymNat c b = r
hb' : Odd b
⊢ ZMod.χ₈ ↑5 = -1

Next tactic:
decide
theorem jacobiSymNat.even_odd₅ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 5)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 2; rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]; congr
  rw [jacobiSymNat, ← Nat.mod_add_div a 2, ha, hc, Nat.zero_add, Nat.cast_mul, jacobiSym.mul_left,
    Nat.cast_two, jacobiSym.at_two hb', ZMod.χ₈_nat_mod_eight, hb,
    (by decide : ZMod.χ₈ (5 : ℕ) = -1)]
  

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 5
hc : a / 2 = c
hr : jacobiSymNat c b = r
hb' : Odd b
⊢ -1 * jacobiSym (↑c) b = -r

Next tactic:
norm_num
theorem jacobiSymNat.even_odd₅ (a b c : ℕ) (r : ℤ) (ha : a % 2 = 0) (hb : b % 8 = 5)
    (hc : a / 2 = c) (hr : jacobiSymNat c b = r) : jacobiSymNat a b = -r := by
  have hb' : Odd b := by
    rw [← Nat.div_add_mod b 8, hb, Odd]
    use 4 * (b / 8) + 2; rw [Nat.mul_add, ← Nat.mul_assoc, Nat.add_assoc]; congr
  rw [jacobiSymNat, ← Nat.mod_add_div a 2, ha, hc, Nat.zero_add, Nat.cast_mul, jacobiSym.mul_left,
    Nat.cast_two, jacobiSym.at_two hb', ZMod.χ₈_nat_mod_eight, hb,
    (by decide : ZMod.χ₈ (5 : ℕ) = -1)]
  norm_num
  

Proof state:
a b c : ℕ
r : ℤ
ha : a % 2 = 0
hb : b % 8 = 5
hc : a / 2 = c
hr : jacobiSymNat c b = r
hb' : Odd b
⊢ jacobiSym (↑c) b = r

Next tactic:
exact hr
/-- Use quadratic reciproity to reduce to smaller `b`. -/
theorem jacobiSymNat.qr₁ (a b : ℕ) (r : ℤ) (ha : a % 4 = 1) (hb : b % 2 = 1)
    (hr : jacobiSymNat b a = r) : jacobiSymNat a b = r := by
  

Proof state:
a b : ℕ
r : ℤ
ha : a % 4 = 1
hb : b % 2 = 1
hr : jacobiSymNat b a = r
⊢ jacobiSymNat a b = r

Next tactic:
rwa [jacobiSymNat, jacobiSym.quadratic_reciprocity_one_mod_four ha (Nat.odd_iff.mpr hb)]
theorem jacobiSymNat.qr₁' (a b : ℕ) (r : ℤ) (ha : a % 2 = 1) (hb : b % 4 = 1)
    (hr : jacobiSymNat b a = r) : jacobiSymNat a b = r := by
  

Proof state:
a b : ℕ
r : ℤ
ha : a % 2 = 1
hb : b % 4 = 1
hr : jacobiSymNat b a = r
⊢ jacobiSymNat a b = r

Next tactic:
rwa [jacobiSymNat, ← jacobiSym.quadratic_reciprocity_one_mod_four hb (Nat.odd_iff.mpr ha)]
theorem jacobiSymNat.qr₃ (a b : ℕ) (r : ℤ) (ha : a % 4 = 3) (hb : b % 4 = 3)
    (hr : jacobiSymNat b a = r) : jacobiSymNat a b = -r := by
  

Proof state:
a b : ℕ
r : ℤ
ha : a % 4 = 3
hb : b % 4 = 3
hr : jacobiSymNat b a = r
⊢ jacobiSymNat a b = -r

Next tactic:
rwa [jacobiSymNat, jacobiSym.quadratic_reciprocity_three_mod_four ha hb, neg_inj]
protected theorem dist_self (x : Completion α) : dist x x = 0 := by
  

Proof state:
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x : Completion α
⊢ dist x x = 0

Next tactic:
refine' induction_on x _ _
protected theorem dist_self (x : Completion α) : dist x x = 0 := by
  refine' induction_on x _ _
  · 

Proof state:
case refine'_1
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x : Completion α
⊢ IsClosed {a | dist a a = 0}

Next tactic:
refine' isClosed_eq _ continuous_const
protected theorem dist_self (x : Completion α) : dist x x = 0 := by
  refine' induction_on x _ _
  · refine' isClosed_eq _ continuous_const
    

Proof state:
case refine'_1
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x : Completion α
⊢ Continuous fun a => dist a a

Next tactic:
exact Completion.continuous_dist continuous_id continuous_id
protected theorem dist_self (x : Completion α) : dist x x = 0 := by
  refine' induction_on x _ _
  · refine' isClosed_eq _ continuous_const
    exact Completion.continuous_dist continuous_id continuous_id
  · 

Proof state:
case refine'_2
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x : Completion α
⊢ ∀ (a : α), dist (↑α a) (↑α a) = 0

Next tactic:
intro a
protected theorem dist_self (x : Completion α) : dist x x = 0 := by
  refine' induction_on x _ _
  · refine' isClosed_eq _ continuous_const
    exact Completion.continuous_dist continuous_id continuous_id
  · intro a
    

Proof state:
case refine'_2
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x : Completion α
a : α
⊢ dist (↑α a) (↑α a) = 0

Next tactic:
rw [Completion.dist_eq, dist_self]
protected theorem dist_comm (x y : Completion α) : dist x y = dist y x := by
  

Proof state:
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x y : Completion α
⊢ dist x y = dist y x

Next tactic:
refine' induction_on₂ x y _ _
protected theorem dist_comm (x y : Completion α) : dist x y = dist y x := by
  refine' induction_on₂ x y _ _
  · 

Proof state:
case refine'_1
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x y : Completion α
⊢ IsClosed {x | dist x.1 x.2 = dist x.2 x.1}

Next tactic:
exact isClosed_eq (Completion.continuous_dist continuous_fst continuous_snd)
        (Completion.continuous_dist continuous_snd continuous_fst)
protected theorem dist_comm (x y : Completion α) : dist x y = dist y x := by
  refine' induction_on₂ x y _ _
  · exact isClosed_eq (Completion.continuous_dist continuous_fst continuous_snd)
        (Completion.continuous_dist continuous_snd continuous_fst)
  · 

Proof state:
case refine'_2
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x y : Completion α
⊢ ∀ (a b : α), dist (↑α a) (↑α b) = dist (↑α b) (↑α a)

Next tactic:
intro a b
protected theorem dist_comm (x y : Completion α) : dist x y = dist y x := by
  refine' induction_on₂ x y _ _
  · exact isClosed_eq (Completion.continuous_dist continuous_fst continuous_snd)
        (Completion.continuous_dist continuous_snd continuous_fst)
  · intro a b
    

Proof state:
case refine'_2
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x y : Completion α
a b : α
⊢ dist (↑α a) (↑α b) = dist (↑α b) (↑α a)

Next tactic:
rw [Completion.dist_eq, Completion.dist_eq, dist_comm]
protected theorem dist_triangle (x y z : Completion α) : dist x z ≤ dist x y + dist y z := by
  

Proof state:
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x y z : Completion α
⊢ dist x z ≤ dist x y + dist y z

Next tactic:
refine' induction_on₃ x y z _ _
protected theorem dist_triangle (x y z : Completion α) : dist x z ≤ dist x y + dist y z := by
  refine' induction_on₃ x y z _ _
  · 

Proof state:
case refine'_1
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x y z : Completion α
⊢ IsClosed {x | dist x.1 x.2.2 ≤ dist x.1 x.2.1 + dist x.2.1 x.2.2}

Next tactic:
refine' isClosed_le _ (Continuous.add _ _)
protected theorem dist_triangle (x y z : Completion α) : dist x z ≤ dist x y + dist y z := by
  refine' induction_on₃ x y z _ _
  · refine' isClosed_le _ (Continuous.add _ _) <;>
      

Proof state:
case refine'_1.refine'_1
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x y z : Completion α
⊢ Continuous fun x => dist x.1 x.2.2

Next tactic:
apply_rules [Completion.continuous_dist, Continuous.fst, Continuous.snd, continuous_id]
protected theorem dist_triangle (x y z : Completion α) : dist x z ≤ dist x y + dist y z := by
  refine' induction_on₃ x y z _ _
  · refine' isClosed_le _ (Continuous.add _ _) <;>
      

Proof state:
case refine'_1.refine'_2
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x y z : Completion α
⊢ Continuous fun x => dist x.1 x.2.1

Next tactic:
apply_rules [Completion.continuous_dist, Continuous.fst, Continuous.snd, continuous_id]
protected theorem dist_triangle (x y z : Completion α) : dist x z ≤ dist x y + dist y z := by
  refine' induction_on₃ x y z _ _
  · refine' isClosed_le _ (Continuous.add _ _) <;>
      

Proof state:
case refine'_1.refine'_3
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x y z : Completion α
⊢ Continuous fun x => dist x.2.1 x.2.2

Next tactic:
apply_rules [Completion.continuous_dist, Continuous.fst, Continuous.snd, continuous_id]
protected theorem dist_triangle (x y z : Completion α) : dist x z ≤ dist x y + dist y z := by
  refine' induction_on₃ x y z _ _
  · refine' isClosed_le _ (Continuous.add _ _) <;>
      apply_rules [Completion.continuous_dist, Continuous.fst, Continuous.snd, continuous_id]
  · 

Proof state:
case refine'_2
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x y z : Completion α
⊢ ∀ (a b c : α), dist (↑α a) (↑α c) ≤ dist (↑α a) (↑α b) + dist (↑α b) (↑α c)

Next tactic:
intro a b c
protected theorem dist_triangle (x y z : Completion α) : dist x z ≤ dist x y + dist y z := by
  refine' induction_on₃ x y z _ _
  · refine' isClosed_le _ (Continuous.add _ _) <;>
      apply_rules [Completion.continuous_dist, Continuous.fst, Continuous.snd, continuous_id]
  · intro a b c
    

Proof state:
case refine'_2
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x y z : Completion α
a b c : α
⊢ dist (↑α a) (↑α c) ≤ dist (↑α a) (↑α b) + dist (↑α b) (↑α c)

Next tactic:
rw [Completion.dist_eq, Completion.dist_eq, Completion.dist_eq]
protected theorem dist_triangle (x y z : Completion α) : dist x z ≤ dist x y + dist y z := by
  refine' induction_on₃ x y z _ _
  · refine' isClosed_le _ (Continuous.add _ _) <;>
      apply_rules [Completion.continuous_dist, Continuous.fst, Continuous.snd, continuous_id]
  · intro a b c
    rw [Completion.dist_eq, Completion.dist_eq, Completion.dist_eq]
    

Proof state:
case refine'_2
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
x y z : Completion α
a b c : α
⊢ dist a c ≤ dist a b + dist b c

Next tactic:
exact dist_triangle a b c
/-- Elements of the uniformity (defined generally for completions) can be characterized in terms
of the distance. -/
protected theorem mem_uniformity_dist (s : Set (Completion α × Completion α)) :
    s ∈ 𝓤 (Completion α) ↔ ∃ ε > 0, ∀ {a b}, dist a b < ε → (a, b) ∈ s := by
  

Proof state:
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
s : Set (Completion α × Completion α)
⊢ s ∈ 𝓤 (Completion α) ↔ ∃ ε > 0, ∀ {a b : Completion α}, dist a b < ε → (a, b) ∈ s

Next tactic:
constructor
/-- Elements of the uniformity (defined generally for completions) can be characterized in terms
of the distance. -/
protected theorem mem_uniformity_dist (s : Set (Completion α × Completion α)) :
    s ∈ 𝓤 (Completion α) ↔ ∃ ε > 0, ∀ {a b}, dist a b < ε → (a, b) ∈ s := by
  constructor
  · /- Start from an entourage `s`. It contains a closed entourage `t`. Its pullback in `α` is an
      entourage, so it contains an `ε`-neighborhood of the diagonal by definition of the entourages
      in metric spaces. Then `t` contains an `ε`-neighborhood of the diagonal in `Completion α`, as
      closed properties pass to the completion. -/
    

Proof state:
case mp
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
s : Set (Completion α × Completion α)
⊢ s ∈ 𝓤 (Completion α) → ∃ ε > 0, ∀ {a b : Completion α}, dist a b < ε → (a, b) ∈ s

Next tactic:
intro hs
/-- Elements of the uniformity (defined generally for completions) can be characterized in terms
of the distance. -/
protected theorem mem_uniformity_dist (s : Set (Completion α × Completion α)) :
    s ∈ 𝓤 (Completion α) ↔ ∃ ε > 0, ∀ {a b}, dist a b < ε → (a, b) ∈ s := by
  constructor
  · /- Start from an entourage `s`. It contains a closed entourage `t`. Its pullback in `α` is an
      entourage, so it contains an `ε`-neighborhood of the diagonal by definition of the entourages
      in metric spaces. Then `t` contains an `ε`-neighborhood of the diagonal in `Completion α`, as
      closed properties pass to the completion. -/
    intro hs
    

Proof state:
case mp
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
s : Set (Completion α × Completion α)
hs : s ∈ 𝓤 (Completion α)
⊢ ∃ ε > 0, ∀ {a b : Completion α}, dist a b < ε → (a, b) ∈ s

Next tactic:
rcases mem_uniformity_isClosed hs with ⟨t, ht, ⟨tclosed, ts⟩⟩
/-- Elements of the uniformity (defined generally for completions) can be characterized in terms
of the distance. -/
protected theorem mem_uniformity_dist (s : Set (Completion α × Completion α)) :
    s ∈ 𝓤 (Completion α) ↔ ∃ ε > 0, ∀ {a b}, dist a b < ε → (a, b) ∈ s := by
  constructor
  · /- Start from an entourage `s`. It contains a closed entourage `t`. Its pullback in `α` is an
      entourage, so it contains an `ε`-neighborhood of the diagonal by definition of the entourages
      in metric spaces. Then `t` contains an `ε`-neighborhood of the diagonal in `Completion α`, as
      closed properties pass to the completion. -/
    intro hs
    rcases mem_uniformity_isClosed hs with ⟨t, ht, ⟨tclosed, ts⟩⟩
    

Proof state:
case mp.intro.intro.intro
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
s : Set (Completion α × Completion α)
hs : s ∈ 𝓤 (Completion α)
t : Set (Completion α × Completion α)
ht : t ∈ 𝓤 (Completion α)
tclosed : IsClosed t
ts : t ⊆ s
⊢ ∃ ε > 0, ∀ {a b : Completion α}, dist a b < ε → (a, b) ∈ s

Next tactic:
have A : { x : α × α | (↑x.1, ↑x.2) ∈ t } ∈ uniformity α :=
      uniformContinuous_def.1 (uniformContinuous_coe α) t ht
/-- Elements of the uniformity (defined generally for completions) can be characterized in terms
of the distance. -/
protected theorem mem_uniformity_dist (s : Set (Completion α × Completion α)) :
    s ∈ 𝓤 (Completion α) ↔ ∃ ε > 0, ∀ {a b}, dist a b < ε → (a, b) ∈ s := by
  constructor
  · /- Start from an entourage `s`. It contains a closed entourage `t`. Its pullback in `α` is an
      entourage, so it contains an `ε`-neighborhood of the diagonal by definition of the entourages
      in metric spaces. Then `t` contains an `ε`-neighborhood of the diagonal in `Completion α`, as
      closed properties pass to the completion. -/
    intro hs
    rcases mem_uniformity_isClosed hs with ⟨t, ht, ⟨tclosed, ts⟩⟩
    have A : { x : α × α | (↑x.1, ↑x.2) ∈ t } ∈ uniformity α :=
      uniformContinuous_def.1 (uniformContinuous_coe α) t ht
    

Proof state:
case mp.intro.intro.intro
α : Type u
β : Type v
inst✝ : PseudoMetricSpace α
s : Set (Completion α × Completion α)
hs : s ∈ 𝓤 (Completion α)
t : Set (Completion α × Completion α)
ht : t ∈ 𝓤 (Completion α)
tclosed : IsClosed t
ts : t ⊆ s
A : {x | (↑α x.1, ↑α x.2) ∈ t} ∈ 𝓤 α
⊢ ∃ ε > 0, ∀ {a b : Completion α}, dist a b < ε → (a, b) ∈ s

Next tactic:
rcases mem_uniformity_dist.1 A with ⟨ε, εpos, hε⟩