l3lab/ntp-mathlib huggingface dataset:
theorem exists_rat_btwn {x y : α} (h : x < y) : ∃ q : ℚ, x < q ∧ (q : α) < y := by
  cases' exists_nat_gt (y - x)⁻¹ with n nh
  cases' exists_floor (x * n) with z zh
  refine' ⟨(z + 1 : ℤ) / n, _⟩
  have n0' := (inv_pos.2 (sub_pos.2 h)).trans nh
  have n0 := Nat.cast_pos.1 n0'
  rw [Rat.cast_div_of_ne_zero, Rat.cast_coe_nat, Rat.cast_coe_int, div_lt_iff n0']
  refine' ⟨(lt_div_iff n0').2 <| (lt_iff_lt_of_le_iff_le (zh _)).1 (lt_add_one _), _⟩
  rw [Int.cast_add, Int.cast_one]
  refine' lt_of_le_of_lt (add_le_add_right ((zh _).1 le_rfl) _) _
  rwa [← lt_sub_iff_add_lt', ← sub_mul, ← div_lt_iff' (sub_pos.2 h), one_div]
  · 

Proof state:
case intro.intro.md
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑(z + 1)).den ≠ 0

Next tactic:
rw [Rat.coe_int_den, Nat.cast_one]
theorem exists_rat_btwn {x y : α} (h : x < y) : ∃ q : ℚ, x < q ∧ (q : α) < y := by
  cases' exists_nat_gt (y - x)⁻¹ with n nh
  cases' exists_floor (x * n) with z zh
  refine' ⟨(z + 1 : ℤ) / n, _⟩
  have n0' := (inv_pos.2 (sub_pos.2 h)).trans nh
  have n0 := Nat.cast_pos.1 n0'
  rw [Rat.cast_div_of_ne_zero, Rat.cast_coe_nat, Rat.cast_coe_int, div_lt_iff n0']
  refine' ⟨(lt_div_iff n0').2 <| (lt_iff_lt_of_le_iff_le (zh _)).1 (lt_add_one _), _⟩
  rw [Int.cast_add, Int.cast_one]
  refine' lt_of_le_of_lt (add_le_add_right ((zh _).1 le_rfl) _) _
  rwa [← lt_sub_iff_add_lt', ← sub_mul, ← div_lt_iff' (sub_pos.2 h), one_div]
  · rw [Rat.coe_int_den, Nat.cast_one]
    

Proof state:
case intro.intro.md
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ 1 ≠ 0

Next tactic:
exact one_ne_zero
theorem exists_rat_btwn {x y : α} (h : x < y) : ∃ q : ℚ, x < q ∧ (q : α) < y := by
  cases' exists_nat_gt (y - x)⁻¹ with n nh
  cases' exists_floor (x * n) with z zh
  refine' ⟨(z + 1 : ℤ) / n, _⟩
  have n0' := (inv_pos.2 (sub_pos.2 h)).trans nh
  have n0 := Nat.cast_pos.1 n0'
  rw [Rat.cast_div_of_ne_zero, Rat.cast_coe_nat, Rat.cast_coe_int, div_lt_iff n0']
  refine' ⟨(lt_div_iff n0').2 <| (lt_iff_lt_of_le_iff_le (zh _)).1 (lt_add_one _), _⟩
  rw [Int.cast_add, Int.cast_one]
  refine' lt_of_le_of_lt (add_le_add_right ((zh _).1 le_rfl) _) _
  rwa [← lt_sub_iff_add_lt', ← sub_mul, ← div_lt_iff' (sub_pos.2 h), one_div]
  · rw [Rat.coe_int_den, Nat.cast_one]
    exact one_ne_zero
  · 

Proof state:
case intro.intro.nn
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑n).num ≠ 0

Next tactic:
intro H
theorem exists_rat_btwn {x y : α} (h : x < y) : ∃ q : ℚ, x < q ∧ (q : α) < y := by
  cases' exists_nat_gt (y - x)⁻¹ with n nh
  cases' exists_floor (x * n) with z zh
  refine' ⟨(z + 1 : ℤ) / n, _⟩
  have n0' := (inv_pos.2 (sub_pos.2 h)).trans nh
  have n0 := Nat.cast_pos.1 n0'
  rw [Rat.cast_div_of_ne_zero, Rat.cast_coe_nat, Rat.cast_coe_int, div_lt_iff n0']
  refine' ⟨(lt_div_iff n0').2 <| (lt_iff_lt_of_le_iff_le (zh _)).1 (lt_add_one _), _⟩
  rw [Int.cast_add, Int.cast_one]
  refine' lt_of_le_of_lt (add_le_add_right ((zh _).1 le_rfl) _) _
  rwa [← lt_sub_iff_add_lt', ← sub_mul, ← div_lt_iff' (sub_pos.2 h), one_div]
  · rw [Rat.coe_int_den, Nat.cast_one]
    exact one_ne_zero
  · intro H
    

Proof state:
case intro.intro.nn
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
H : ↑(↑n).num = 0
⊢ False

Next tactic:
rw [Rat.coe_nat_num, Int.cast_ofNat, Nat.cast_eq_zero] at H
theorem exists_rat_btwn {x y : α} (h : x < y) : ∃ q : ℚ, x < q ∧ (q : α) < y := by
  cases' exists_nat_gt (y - x)⁻¹ with n nh
  cases' exists_floor (x * n) with z zh
  refine' ⟨(z + 1 : ℤ) / n, _⟩
  have n0' := (inv_pos.2 (sub_pos.2 h)).trans nh
  have n0 := Nat.cast_pos.1 n0'
  rw [Rat.cast_div_of_ne_zero, Rat.cast_coe_nat, Rat.cast_coe_int, div_lt_iff n0']
  refine' ⟨(lt_div_iff n0').2 <| (lt_iff_lt_of_le_iff_le (zh _)).1 (lt_add_one _), _⟩
  rw [Int.cast_add, Int.cast_one]
  refine' lt_of_le_of_lt (add_le_add_right ((zh _).1 le_rfl) _) _
  rwa [← lt_sub_iff_add_lt', ← sub_mul, ← div_lt_iff' (sub_pos.2 h), one_div]
  · rw [Rat.coe_int_den, Nat.cast_one]
    exact one_ne_zero
  · intro H
    rw [Rat.coe_nat_num, Int.cast_ofNat, Nat.cast_eq_zero] at H
    

Proof state:
case intro.intro.nn
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
H : n = 0
⊢ False

Next tactic:
subst H
theorem exists_rat_btwn {x y : α} (h : x < y) : ∃ q : ℚ, x < q ∧ (q : α) < y := by
  cases' exists_nat_gt (y - x)⁻¹ with n nh
  cases' exists_floor (x * n) with z zh
  refine' ⟨(z + 1 : ℤ) / n, _⟩
  have n0' := (inv_pos.2 (sub_pos.2 h)).trans nh
  have n0 := Nat.cast_pos.1 n0'
  rw [Rat.cast_div_of_ne_zero, Rat.cast_coe_nat, Rat.cast_coe_int, div_lt_iff n0']
  refine' ⟨(lt_div_iff n0').2 <| (lt_iff_lt_of_le_iff_le (zh _)).1 (lt_add_one _), _⟩
  rw [Int.cast_add, Int.cast_one]
  refine' lt_of_le_of_lt (add_le_add_right ((zh _).1 le_rfl) _) _
  rwa [← lt_sub_iff_add_lt', ← sub_mul, ← div_lt_iff' (sub_pos.2 h), one_div]
  · rw [Rat.coe_int_den, Nat.cast_one]
    exact one_ne_zero
  · intro H
    rw [Rat.coe_nat_num, Int.cast_ofNat, Nat.cast_eq_zero] at H
    subst H
    

Proof state:
case intro.intro.nn
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
z : ℤ
nh : (y - x)⁻¹ < ↑0
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑0
n0' : 0 < ↑0
n0 : 0 < 0
⊢ False

Next tactic:
cases n0
theorem exists_rat_btwn {x y : α} (h : x < y) : ∃ q : ℚ, x < q ∧ (q : α) < y := by
  cases' exists_nat_gt (y - x)⁻¹ with n nh
  cases' exists_floor (x * n) with z zh
  refine' ⟨(z + 1 : ℤ) / n, _⟩
  have n0' := (inv_pos.2 (sub_pos.2 h)).trans nh
  have n0 := Nat.cast_pos.1 n0'
  rw [Rat.cast_div_of_ne_zero, Rat.cast_coe_nat, Rat.cast_coe_int, div_lt_iff n0']
  refine' ⟨(lt_div_iff n0').2 <| (lt_iff_lt_of_le_iff_le (zh _)).1 (lt_add_one _), _⟩
  rw [Int.cast_add, Int.cast_one]
  refine' lt_of_le_of_lt (add_le_add_right ((zh _).1 le_rfl) _) _
  rwa [← lt_sub_iff_add_lt', ← sub_mul, ← div_lt_iff' (sub_pos.2 h), one_div]
  · rw [Rat.coe_int_den, Nat.cast_one]
    exact one_ne_zero
  · intro H
    rw [Rat.coe_nat_num, Int.cast_ofNat, Nat.cast_eq_zero] at H
    subst H
    cases n0
  · 

Proof state:
case intro.intro.nd
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑n).den ≠ 0

Next tactic:
rw [Rat.coe_nat_den, Nat.cast_one]
theorem exists_rat_btwn {x y : α} (h : x < y) : ∃ q : ℚ, x < q ∧ (q : α) < y := by
  cases' exists_nat_gt (y - x)⁻¹ with n nh
  cases' exists_floor (x * n) with z zh
  refine' ⟨(z + 1 : ℤ) / n, _⟩
  have n0' := (inv_pos.2 (sub_pos.2 h)).trans nh
  have n0 := Nat.cast_pos.1 n0'
  rw [Rat.cast_div_of_ne_zero, Rat.cast_coe_nat, Rat.cast_coe_int, div_lt_iff n0']
  refine' ⟨(lt_div_iff n0').2 <| (lt_iff_lt_of_le_iff_le (zh _)).1 (lt_add_one _), _⟩
  rw [Int.cast_add, Int.cast_one]
  refine' lt_of_le_of_lt (add_le_add_right ((zh _).1 le_rfl) _) _
  rwa [← lt_sub_iff_add_lt', ← sub_mul, ← div_lt_iff' (sub_pos.2 h), one_div]
  · rw [Rat.coe_int_den, Nat.cast_one]
    exact one_ne_zero
  · intro H
    rw [Rat.coe_nat_num, Int.cast_ofNat, Nat.cast_eq_zero] at H
    subst H
    cases n0
  · rw [Rat.coe_nat_den, Nat.cast_one]
    

Proof state:
case intro.intro.nd
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ 1 ≠ 0

Next tactic:
exact one_ne_zero
theorem exists_pos_rat_lt {x : α} (x0 : 0 < x) : ∃ q : ℚ, 0 < q ∧ (q : α) < x := by
  

Proof state:
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y ε x : α
x0 : 0 < x
⊢ ∃ q, 0 < q ∧ ↑q < x

Next tactic:
simpa only [Rat.cast_pos] using exists_rat_btwn x0
theorem archimedean_iff_nat_lt : Archimedean α ↔ ∀ x : α, ∃ n : ℕ, x < n :=
  ⟨@exists_nat_gt α _, fun H =>
    ⟨fun x y y0 =>
      (H (x / y)).imp fun n h => le_of_lt <| by 

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
H : ∀ (x : α), ∃ n, x < ↑n
x y : α
y0 : 0 < y
n : ℕ
h : x / y < ↑n
⊢ x < n • y

Next tactic:
rwa [div_lt_iff y0, ← nsmul_eq_mul] at h
theorem archimedean_iff_int_lt : Archimedean α ↔ ∀ x : α, ∃ n : ℤ, x < n :=
  ⟨@exists_int_gt α _, by
    

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
⊢ (∀ (x : α), ∃ n, x < ↑n) → Archimedean α

Next tactic:
rw [archimedean_iff_nat_lt]
theorem archimedean_iff_int_lt : Archimedean α ↔ ∀ x : α, ∃ n : ℤ, x < n :=
  ⟨@exists_int_gt α _, by
    rw [archimedean_iff_nat_lt]
    

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
⊢ (∀ (x : α), ∃ n, x < ↑n) → ∀ (x : α), ∃ n, x < ↑n

Next tactic:
intro h x
theorem archimedean_iff_int_lt : Archimedean α ↔ ∀ x : α, ∃ n : ℤ, x < n :=
  ⟨@exists_int_gt α _, by
    rw [archimedean_iff_nat_lt]
    intro h x
    

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
h : ∀ (x : α), ∃ n, x < ↑n
x : α
⊢ ∃ n, x < ↑n

Next tactic:
obtain ⟨n, h⟩ := h x
theorem archimedean_iff_int_lt : Archimedean α ↔ ∀ x : α, ∃ n : ℤ, x < n :=
  ⟨@exists_int_gt α _, by
    rw [archimedean_iff_nat_lt]
    intro h x
    obtain ⟨n, h⟩ := h x
    

Proof state:
case intro
α : Type u_1
inst✝ : LinearOrderedField α
h✝ : ∀ (x : α), ∃ n, x < ↑n
x : α
n : ℤ
h : x < ↑n
⊢ ∃ n, x < ↑n

Next tactic:
refine' ⟨n.toNat, h.trans_le _⟩
theorem archimedean_iff_int_lt : Archimedean α ↔ ∀ x : α, ∃ n : ℤ, x < n :=
  ⟨@exists_int_gt α _, by
    rw [archimedean_iff_nat_lt]
    intro h x
    obtain ⟨n, h⟩ := h x
    refine' ⟨n.toNat, h.trans_le _⟩
    

Proof state:
case intro
α : Type u_1
inst✝ : LinearOrderedField α
h✝ : ∀ (x : α), ∃ n, x < ↑n
x : α
n : ℤ
h : x < ↑n
⊢ ↑n ≤ ↑(toNat n)

Next tactic:
exact mod_cast Int.self_le_toNat _
theorem archimedean_iff_rat_lt : Archimedean α ↔ ∀ x : α, ∃ q : ℚ, x < q :=
  ⟨@exists_rat_gt α _, fun H =>
    archimedean_iff_nat_lt.2 fun x =>
      let ⟨q, h⟩ := H x
      ⟨⌈q⌉₊,
        lt_of_lt_of_le h <| by
          

Proof state:
α : Type u_1
inst✝ : LinearOrderedField α
H : ∀ (x : α), ∃ q, x < ↑q
x : α
q : ℚ
h : x < ↑q
⊢ ↑q ≤ ↑⌈q⌉₊

Next tactic:
simpa only [Rat.cast_coe_nat] using (@Rat.cast_le α _ _ _).2 (Nat.le_ceil _)
instance : Archimedean ℕ :=
  ⟨fun n m m0 => ⟨n, by
    

Proof state:
α : Type u_1
n m : ℕ
m0 : 0 < m
⊢ n ≤ n • m

Next tactic:
rw [← mul_one n, smul_eq_mul, mul_assoc, one_mul m]
instance : Archimedean ℕ :=
  ⟨fun n m m0 => ⟨n, by
    rw [← mul_one n, smul_eq_mul, mul_assoc, one_mul m]
    

Proof state:
α : Type u_1
n m : ℕ
m0 : 0 < m
⊢ n * 1 ≤ n * m

Next tactic:
exact Nat.mul_le_mul_left n (by linarith)
instance : Archimedean ℕ :=
  ⟨fun n m m0 => ⟨n, by
    rw [← mul_one n, smul_eq_mul, mul_assoc, one_mul m]
    exact Nat.mul_le_mul_left n (by 

Proof state:
α : Type u_1
n m : ℕ
m0 : 0 < m
⊢ 1 ≤ m

Next tactic:
linarith
instance : Archimedean ℤ :=
  ⟨fun n m m0 =>
    ⟨n.toNat,
      le_trans (Int.self_le_toNat _) <| by
        

Proof state:
α : Type u_1
n m : ℤ
m0 : 0 < m
⊢ ↑(toNat n) ≤ toNat n • m

Next tactic:
simpa only [nsmul_eq_mul, zero_add, mul_one] using
          mul_le_mul_of_nonneg_left (Int.add_one_le_iff.2 m0) (Int.ofNat_zero_le n.toNat)
instance : Archimedean ℚ :=
  archimedean_iff_rat_le.2 fun q => ⟨q, by 

Proof state:
α : Type u_1
q : ℚ
⊢ q ≤ ↑q

Next tactic:
rw [Rat.cast_id]
/-- A linear ordered field that is a floor ring is archimedean. -/
instance (priority := 100) FloorRing.archimedean (α) [LinearOrderedField α] [FloorRing α] :
    Archimedean α := by
  

Proof state:
α✝ : Type u_1
α : Type ?u.94268
inst✝¹ : LinearOrderedField α
inst✝ : FloorRing α
⊢ Archimedean α

Next tactic:
rw [archimedean_iff_int_le]
/-- A linear ordered field that is a floor ring is archimedean. -/
instance (priority := 100) FloorRing.archimedean (α) [LinearOrderedField α] [FloorRing α] :
    Archimedean α := by
  rw [archimedean_iff_int_le]
  

Proof state:
α✝ : Type u_1
α : Type ?u.94268
inst✝¹ : LinearOrderedField α
inst✝ : FloorRing α
⊢ ∀ (x : α), ∃ n, x ≤ ↑n

Next tactic:
exact fun x => ⟨⌈x⌉, Int.le_ceil x⟩
@[simp]
theorem whiskerLeft_eqToHom {a b c : B} (f : a ⟶ b) {g h : b ⟶ c} (η : g = h) :
    f ◁ eqToHom η = eqToHom (congr_arg₂ (· ≫ ·) rfl η) := by
  

Proof state:
B : Type u
inst✝ : Bicategory B
a b c : B
f : a ⟶ b
g h : b ⟶ c
η : g = h
⊢ f ◁ eqToHom η = eqToHom (_ : f ≫ g = f ≫ h)

Next tactic:
cases η
@[simp]
theorem whiskerLeft_eqToHom {a b c : B} (f : a ⟶ b) {g h : b ⟶ c} (η : g = h) :
    f ◁ eqToHom η = eqToHom (congr_arg₂ (· ≫ ·) rfl η) := by
  cases η
  

Proof state:
case refl
B : Type u
inst✝ : Bicategory B
a b c : B
f : a ⟶ b
g : b ⟶ c
⊢ f ◁ eqToHom (_ : g = g) = eqToHom (_ : f ≫ g = f ≫ g)

Next tactic:
simp only [whiskerLeft_id, eqToHom_refl]
@[simp]
theorem eqToHom_whiskerRight {a b c : B} {f g : a ⟶ b} (η : f = g) (h : b ⟶ c) :
    eqToHom η ▷ h = eqToHom (congr_arg₂ (· ≫ ·) η rfl) := by
  

Proof state:
B : Type u
inst✝ : Bicategory B
a b c : B
f g : a ⟶ b
η : f = g
h : b ⟶ c
⊢ eqToHom η ▷ h = eqToHom (_ : f ≫ h = g ≫ h)

Next tactic:
cases η
@[simp]
theorem eqToHom_whiskerRight {a b c : B} {f g : a ⟶ b} (η : f = g) (h : b ⟶ c) :
    eqToHom η ▷ h = eqToHom (congr_arg₂ (· ≫ ·) η rfl) := by
  cases η
  

Proof state:
case refl
B : Type u
inst✝ : Bicategory B
a b c : B
f : a ⟶ b
h : b ⟶ c
⊢ eqToHom (_ : f = f) ▷ h = eqToHom (_ : f ≫ h = f ≫ h)

Next tactic:
simp only [id_whiskerRight, eqToHom_refl]
/--
The sieve of morphisms which factor through a given morphism `f`.
This is equal to `Sieve.generate (Presieve.singleton f)`, but has
more convenient definitional properties.
-/
def Sieve.generateSingleton {X Y : C} (f : Y ⟶ X) : Sieve X where
  arrows Z := { g | ∃ (e : Z ⟶ Y), e ≫ f = g }
  downward_closed := by
    

Proof state:
C : Type u_1
inst✝ : Category.{?u.903, u_1} C
X Y : C
f : Y ⟶ X
⊢ ∀ {Y_1 Z : C} {f_1 : Y_1 ⟶ X},
    (fun Z => {g | ∃ e, e ≫ f = g}) Y_1 f_1 → ∀ (g : Z ⟶ Y_1), (fun Z => {g | ∃ e, e ≫ f = g}) Z (g ≫ f_1)

Next tactic:
rintro W Z g ⟨e,rfl⟩ q
/--
The sieve of morphisms which factor through a given morphism `f`.
This is equal to `Sieve.generate (Presieve.singleton f)`, but has
more convenient definitional properties.
-/
def Sieve.generateSingleton {X Y : C} (f : Y ⟶ X) : Sieve X where
  arrows Z := { g | ∃ (e : Z ⟶ Y), e ≫ f = g }
  downward_closed := by
    rintro W Z g ⟨e,rfl⟩ q
    

Proof state:
case intro
C : Type u_1
inst✝ : Category.{?u.903, u_1} C
X Y : C
f : Y ⟶ X
W Z : C
e : W ⟶ Y
q : Z ⟶ W
⊢ setOf (fun g => ∃ e, e ≫ f = g) (q ≫ e ≫ f)

Next tactic:
exact ⟨q ≫ e, by simp⟩
/--
The sieve of morphisms which factor through a given morphism `f`.
This is equal to `Sieve.generate (Presieve.singleton f)`, but has
more convenient definitional properties.
-/
def Sieve.generateSingleton {X Y : C} (f : Y ⟶ X) : Sieve X where
  arrows Z := { g | ∃ (e : Z ⟶ Y), e ≫ f = g }
  downward_closed := by
    rintro W Z g ⟨e,rfl⟩ q
    exact ⟨q ≫ e, by 

Proof state:
C : Type u_1
inst✝ : Category.{?u.903, u_1} C
X Y : C
f : Y ⟶ X
W Z : C
e : W ⟶ Y
q : Z ⟶ W
⊢ (q ≫ e) ≫ f = q ≫ e ≫ f

Next tactic:
simp
lemma Sieve.generateSingleton_eq {X Y : C} (f : Y ⟶ X) :
    Sieve.generate (Presieve.singleton f) = Sieve.generateSingleton f := by
  

Proof state:
C : Type u_1
inst✝ : Category.{u_2, u_1} C
X Y : C
f : Y ⟶ X
⊢ generate (Presieve.singleton f) = generateSingleton f

Next tactic:
ext Z g
lemma Sieve.generateSingleton_eq {X Y : C} (f : Y ⟶ X) :
    Sieve.generate (Presieve.singleton f) = Sieve.generateSingleton f := by
  ext Z g
  

Proof state:
case h
C : Type u_1
inst✝ : Category.{u_2, u_1} C
X Y : C
f : Y ⟶ X
Z : C
g : Z ⟶ X
⊢ (generate (Presieve.singleton f)).arrows g ↔ (generateSingleton f).arrows g

Next tactic:
constructor
lemma Sieve.generateSingleton_eq {X Y : C} (f : Y ⟶ X) :
    Sieve.generate (Presieve.singleton f) = Sieve.generateSingleton f := by
  ext Z g
  constructor
  · 

Proof state:
case h.mp
C : Type u_1
inst✝ : Category.{u_2, u_1} C
X Y : C
f : Y ⟶ X
Z : C
g : Z ⟶ X
⊢ (generate (Presieve.singleton f)).arrows g → (generateSingleton f).arrows g

Next tactic:
rintro ⟨W,i,p,⟨⟩,rfl⟩
lemma Sieve.generateSingleton_eq {X Y : C} (f : Y ⟶ X) :
    Sieve.generate (Presieve.singleton f) = Sieve.generateSingleton f := by
  ext Z g
  constructor
  · rintro ⟨W,i,p,⟨⟩,rfl⟩
    

Proof state:
case h.mp.intro.intro.intro.intro.mk
C : Type u_1
inst✝ : Category.{u_2, u_1} C
X Y✝ : C
f : Y✝ ⟶ X
Z Y : C
i : Z ⟶ Y✝
⊢ (generateSingleton f).arrows (i ≫ f)

Next tactic:
exact ⟨i,rfl⟩
lemma Sieve.generateSingleton_eq {X Y : C} (f : Y ⟶ X) :
    Sieve.generate (Presieve.singleton f) = Sieve.generateSingleton f := by
  ext Z g
  constructor
  · rintro ⟨W,i,p,⟨⟩,rfl⟩
    exact ⟨i,rfl⟩
  · 

Proof state:
case h.mpr
C : Type u_1
inst✝ : Category.{u_2, u_1} C
X Y : C
f : Y ⟶ X
Z : C
g : Z ⟶ X
⊢ (generateSingleton f).arrows g → (generate (Presieve.singleton f)).arrows g

Next tactic:
rintro ⟨g,h⟩
lemma Sieve.generateSingleton_eq {X Y : C} (f : Y ⟶ X) :
    Sieve.generate (Presieve.singleton f) = Sieve.generateSingleton f := by
  ext Z g
  constructor
  · rintro ⟨W,i,p,⟨⟩,rfl⟩
    exact ⟨i,rfl⟩
  · rintro ⟨g,h⟩
    

Proof state:
case h.mpr.intro
C : Type u_1
inst✝ : Category.{u_2, u_1} C
X Y : C
f : Y ⟶ X
Z : C
g✝ : Z ⟶ X
g : Z ⟶ Y
h : g ≫ f = g✝
⊢ (generate (Presieve.singleton f)).arrows g✝

Next tactic:
exact ⟨Y,g,f,⟨⟩,h⟩
instance epiOfEffectiveEpi {X Y : C} (f : Y ⟶ X) [EffectiveEpi f] : Epi f := by
  

Proof state:
C : Type u_1
inst✝¹ : Category.{?u.7605, u_1} C
X Y : C
f : Y ⟶ X
inst✝ : EffectiveEpi f
⊢ Epi f

Next tactic:
constructor
instance epiOfEffectiveEpi {X Y : C} (f : Y ⟶ X) [EffectiveEpi f] : Epi f := by
  constructor
  

Proof state:
case left_cancellation
C : Type u_1
inst✝¹ : Category.{?u.7605, u_1} C
X Y : C
f : Y ⟶ X
inst✝ : EffectiveEpi f
⊢ ∀ {Z : C} (g h : X ⟶ Z), f ≫ g = f ≫ h → g = h

Next tactic:
intro W m₁ m₂ h
instance epiOfEffectiveEpi {X Y : C} (f : Y ⟶ X) [EffectiveEpi f] : Epi f := by
  constructor
  intro W m₁ m₂ h
  

Proof state:
case left_cancellation
C : Type u_1
inst✝¹ : Category.{?u.7605, u_1} C
X Y : C
f : Y ⟶ X
inst✝ : EffectiveEpi f
W : C
m₁ m₂ : X ⟶ W
h : f ≫ m₁ = f ≫ m₂
⊢ m₁ = m₂

Next tactic:
have : m₂ = EffectiveEpi.desc f (f ≫ m₂)
    (fun {Z} g₁ g₂ h => by simp only [← Category.assoc, h]) := EffectiveEpi.uniq _ _ _ _ rfl
instance epiOfEffectiveEpi {X Y : C} (f : Y ⟶ X) [EffectiveEpi f] : Epi f := by
  constructor
  intro W m₁ m₂ h
  have : m₂ = EffectiveEpi.desc f (f ≫ m₂)
    (fun {Z} g₁ g₂ h => by 

Proof state:
C : Type u_1
inst✝¹ : Category.{?u.7605, u_1} C
X Y : C
f : Y ⟶ X
inst✝ : EffectiveEpi f
W : C
m₁ m₂ : X ⟶ W
h✝ : f ≫ m₁ = f ≫ m₂
Z : C
g₁ g₂ : Z ⟶ Y
h : g₁ ≫ f = g₂ ≫ f
⊢ g₁ ≫ f ≫ m₂ = g₂ ≫ f ≫ m₂

Next tactic:
simp only [← Category.assoc, h]
instance epiOfEffectiveEpi {X Y : C} (f : Y ⟶ X) [EffectiveEpi f] : Epi f := by
  constructor
  intro W m₁ m₂ h
  have : m₂ = EffectiveEpi.desc f (f ≫ m₂)
    (fun {Z} g₁ g₂ h => by simp only [← Category.assoc, h]) := EffectiveEpi.uniq _ _ _ _ rfl
  

Proof state:
case left_cancellation
C : Type u_1
inst✝¹ : Category.{?u.7605, u_1} C
X Y : C
f : Y ⟶ X
inst✝ : EffectiveEpi f
W : C
m₁ m₂ : X ⟶ W
h : f ≫ m₁ = f ≫ m₂
this : m₂ = EffectiveEpi.desc f (f ≫ m₂) (_ : ∀ {Z : C} (g₁ g₂ : Z ⟶ Y), g₁ ≫ f = g₂ ≫ f → g₁ ≫ f ≫ m₂ = g₂ ≫ f ≫ m₂)
⊢ m₁ = m₂

Next tactic:
rw [this]
instance epiOfEffectiveEpi {X Y : C} (f : Y ⟶ X) [EffectiveEpi f] : Epi f := by
  constructor
  intro W m₁ m₂ h
  have : m₂ = EffectiveEpi.desc f (f ≫ m₂)
    (fun {Z} g₁ g₂ h => by simp only [← Category.assoc, h]) := EffectiveEpi.uniq _ _ _ _ rfl
  rw [this]
  

Proof state:
case left_cancellation
C : Type u_1
inst✝¹ : Category.{?u.7605, u_1} C
X Y : C
f : Y ⟶ X
inst✝ : EffectiveEpi f
W : C
m₁ m₂ : X ⟶ W
h : f ≫ m₁ = f ≫ m₂
this : m₂ = EffectiveEpi.desc f (f ≫ m₂) (_ : ∀ {Z : C} (g₁ g₂ : Z ⟶ Y), g₁ ≫ f = g₂ ≫ f → g₁ ≫ f ≫ m₂ = g₂ ≫ f ≫ m₂)
⊢ m₁ = EffectiveEpi.desc f (f ≫ m₂) (_ : ∀ {Z : C} (g₁ g₂ : Z ⟶ Y), g₁ ≫ f = g₂ ≫ f → g₁ ≫ f ≫ m₂ = g₂ ≫ f ≫ m₂)

Next tactic:
exact EffectiveEpi.uniq _ _ _ _ h
/--
Implementation: This is a construction which will be used in the proof that
the sieve generated by a single arrow is effective epimorphic if and only if
the arrow is an effective epi.
-/
def isColimitOfEffectiveEpiStruct {X Y : C} (f : Y ⟶ X) (Hf : EffectiveEpiStruct f) :
    IsColimit (Sieve.generateSingleton f : Presieve X).cocone :=
  letI D := FullSubcategory fun T : Over X => Sieve.generateSingleton f T.hom
  letI F : D ⥤ _ := (Sieve.generateSingleton f).arrows.diagram
  { desc := fun S => Hf.desc (S.ι.app ⟨Over.mk f, ⟨𝟙 _, by 

Proof state:
C : Type u_1
inst✝ : Category.{?u.8651, u_1} C
X Y : C
f : Y ⟶ X
Hf : EffectiveEpiStruct f
D : Type (max u_1 ?u.8651) := FullSubcategory fun T => (Sieve.generateSingleton f).arrows T.hom
F : D ⥤ C := Presieve.diagram (Sieve.generateSingleton f).arrows
S : Cocone (Presieve.diagram (Sieve.generateSingleton f).arrows)
⊢ 𝟙 ((𝟭 C).obj (Over.mk f).left) ≫ f = (Over.mk f).hom

Next tactic:
simp
/--
Implementation: This is a construction which will be used in the proof that
the sieve generated by a single arrow is effective epimorphic if and only if
the arrow is an effective epi.
-/
def isColimitOfEffectiveEpiStruct {X Y : C} (f : Y ⟶ X) (Hf : EffectiveEpiStruct f) :
    IsColimit (Sieve.generateSingleton f : Presieve X).cocone :=
  letI D := FullSubcategory fun T : Over X => Sieve.generateSingleton f T.hom
  letI F : D ⥤ _ := (Sieve.generateSingleton f).arrows.diagram
  { desc := fun S => Hf.desc (S.ι.app ⟨Over.mk f, ⟨𝟙 _, by simp⟩⟩) <| by
      

Proof state:
C : Type u_1
inst✝ : Category.{?u.8651, u_1} C
X Y : C
f : Y ⟶ X
Hf : EffectiveEpiStruct f
D : Type (max u_1 ?u.8651) := FullSubcategory fun T => (Sieve.generateSingleton f).arrows T.hom
F : D ⥤ C := Presieve.diagram (Sieve.generateSingleton f).arrows
S : Cocone (Presieve.diagram (Sieve.generateSingleton f).arrows)
⊢ ∀ {Z : C} (g₁ g₂ : Z ⟶ Y),
    g₁ ≫ f = g₂ ≫ f →
      g₁ ≫ S.ι.app { obj := Over.mk f, property := (_ : ∃ e, e ≫ f = (Over.mk f).hom) } =
        g₂ ≫ S.ι.app { obj := Over.mk f, property := (_ : ∃ e, e ≫ f = (Over.mk f).hom) }

Next tactic:
intro Z g₁ g₂ h
/--
Implementation: This is a construction which will be used in the proof that
the sieve generated by a single arrow is effective epimorphic if and only if
the arrow is an effective epi.
-/
def isColimitOfEffectiveEpiStruct {X Y : C} (f : Y ⟶ X) (Hf : EffectiveEpiStruct f) :
    IsColimit (Sieve.generateSingleton f : Presieve X).cocone :=
  letI D := FullSubcategory fun T : Over X => Sieve.generateSingleton f T.hom
  letI F : D ⥤ _ := (Sieve.generateSingleton f).arrows.diagram
  { desc := fun S => Hf.desc (S.ι.app ⟨Over.mk f, ⟨𝟙 _, by simp⟩⟩) <| by
      intro Z g₁ g₂ h
      

Proof state:
C : Type u_1
inst✝ : Category.{?u.8651, u_1} C
X Y : C
f : Y ⟶ X
Hf : EffectiveEpiStruct f
D : Type (max u_1 ?u.8651) := FullSubcategory fun T => (Sieve.generateSingleton f).arrows T.hom
F : D ⥤ C := Presieve.diagram (Sieve.generateSingleton f).arrows
S : Cocone (Presieve.diagram (Sieve.generateSingleton f).arrows)
Z : C
g₁ g₂ : Z ⟶ Y
h : g₁ ≫ f = g₂ ≫ f
⊢ g₁ ≫ S.ι.app { obj := Over.mk f, property := (_ : ∃ e, e ≫ f = (Over.mk f).hom) } =
    g₂ ≫ S.ι.app { obj := Over.mk f, property := (_ : ∃ e, e ≫ f = (Over.mk f).hom) }

Next tactic:
let Y' : D := ⟨Over.mk f, 𝟙 _, by simp⟩