l3lab/ntp-mathlib huggingface dataset:
/-- Build a module filter basis from compatible ring and additive group filter bases. -/
def ofBases {R M : Type*} [CommRing R] [AddCommGroup M] [Module R M] (BR : RingFilterBasis R)
    (BM : AddGroupFilterBasis M) (smul : ∀ {U}, U ∈ BM → ∃ V ∈ BR, ∃ W ∈ BM, V • W ⊆ U)
    (smul_left : ∀ (x₀ : R) {U}, U ∈ BM → ∃ V ∈ BM, V ⊆ (fun x ↦ x₀ • x) ⁻¹' U)
    (smul_right : ∀ (m₀ : M) {U}, U ∈ BM → ∃ V ∈ BR, V ⊆ (fun x ↦ x • m₀) ⁻¹' U) :
    @ModuleFilterBasis R M _ BR.topology _ _ :=
  let _ := BR.topology
  { BM with
    smul' := by
      intro U U_in
      

Proof state:
R✝ : Type u_1
M✝ : Type u_2
inst✝⁶ : CommRing R✝
inst✝⁵ : TopologicalSpace R✝
inst✝⁴ : AddCommGroup M✝
inst✝³ : Module R✝ M✝
B : ModuleFilterBasis R✝ M✝
R : Type u_3
M : Type u_4
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
BR : RingFilterBasis R
BM : AddGroupFilterBasis M
smul : ∀ {U : Set M}, U ∈ BM → ∃ V ∈ BR, ∃ W ∈ BM, V • W ⊆ U
smul_left : ∀ (x₀ : R) {U : Set M}, U ∈ BM → ∃ V ∈ BM, V ⊆ (fun x => x₀ • x) ⁻¹' U
smul_right : ∀ (m₀ : M) {U : Set M}, U ∈ BM → ∃ V ∈ BR, V ⊆ (fun x => x • m₀) ⁻¹' U
x✝ : TopologicalSpace R := RingFilterBasis.topology BR
U : Set M
U_in : U ∈ AddGroupFilterBasis.toFilterBasis.sets
⊢ ∃ V ∈ 𝓝 0, ∃ W ∈ AddGroupFilterBasis.toFilterBasis.sets, V • W ⊆ U

Next tactic:
rcases smul U_in with ⟨V, V_in, W, W_in, H⟩
/-- Build a module filter basis from compatible ring and additive group filter bases. -/
def ofBases {R M : Type*} [CommRing R] [AddCommGroup M] [Module R M] (BR : RingFilterBasis R)
    (BM : AddGroupFilterBasis M) (smul : ∀ {U}, U ∈ BM → ∃ V ∈ BR, ∃ W ∈ BM, V • W ⊆ U)
    (smul_left : ∀ (x₀ : R) {U}, U ∈ BM → ∃ V ∈ BM, V ⊆ (fun x ↦ x₀ • x) ⁻¹' U)
    (smul_right : ∀ (m₀ : M) {U}, U ∈ BM → ∃ V ∈ BR, V ⊆ (fun x ↦ x • m₀) ⁻¹' U) :
    @ModuleFilterBasis R M _ BR.topology _ _ :=
  let _ := BR.topology
  { BM with
    smul' := by
      intro U U_in
      rcases smul U_in with ⟨V, V_in, W, W_in, H⟩
      

Proof state:
case intro.intro.intro.intro
R✝ : Type u_1
M✝ : Type u_2
inst✝⁶ : CommRing R✝
inst✝⁵ : TopologicalSpace R✝
inst✝⁴ : AddCommGroup M✝
inst✝³ : Module R✝ M✝
B : ModuleFilterBasis R✝ M✝
R : Type u_3
M : Type u_4
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
BR : RingFilterBasis R
BM : AddGroupFilterBasis M
smul : ∀ {U : Set M}, U ∈ BM → ∃ V ∈ BR, ∃ W ∈ BM, V • W ⊆ U
smul_left : ∀ (x₀ : R) {U : Set M}, U ∈ BM → ∃ V ∈ BM, V ⊆ (fun x => x₀ • x) ⁻¹' U
smul_right : ∀ (m₀ : M) {U : Set M}, U ∈ BM → ∃ V ∈ BR, V ⊆ (fun x => x • m₀) ⁻¹' U
x✝ : TopologicalSpace R := RingFilterBasis.topology BR
U : Set M
U_in : U ∈ AddGroupFilterBasis.toFilterBasis.sets
V : Set R
V_in : V ∈ BR
W : Set M
W_in : W ∈ BM
H : V • W ⊆ U
⊢ ∃ V ∈ 𝓝 0, ∃ W ∈ AddGroupFilterBasis.toFilterBasis.sets, V • W ⊆ U

Next tactic:
exact ⟨V, BR.toAddGroupFilterBasis.mem_nhds_zero V_in, W, W_in, H⟩
/-- Build a module filter basis from compatible ring and additive group filter bases. -/
def ofBases {R M : Type*} [CommRing R] [AddCommGroup M] [Module R M] (BR : RingFilterBasis R)
    (BM : AddGroupFilterBasis M) (smul : ∀ {U}, U ∈ BM → ∃ V ∈ BR, ∃ W ∈ BM, V • W ⊆ U)
    (smul_left : ∀ (x₀ : R) {U}, U ∈ BM → ∃ V ∈ BM, V ⊆ (fun x ↦ x₀ • x) ⁻¹' U)
    (smul_right : ∀ (m₀ : M) {U}, U ∈ BM → ∃ V ∈ BR, V ⊆ (fun x ↦ x • m₀) ⁻¹' U) :
    @ModuleFilterBasis R M _ BR.topology _ _ :=
  let _ := BR.topology
  { BM with
    smul' := by
      intro U U_in
      rcases smul U_in with ⟨V, V_in, W, W_in, H⟩
      exact ⟨V, BR.toAddGroupFilterBasis.mem_nhds_zero V_in, W, W_in, H⟩
    smul_left' := smul_left
    smul_right' := by
      

Proof state:
R✝ : Type u_1
M✝ : Type u_2
inst✝⁶ : CommRing R✝
inst✝⁵ : TopologicalSpace R✝
inst✝⁴ : AddCommGroup M✝
inst✝³ : Module R✝ M✝
B : ModuleFilterBasis R✝ M✝
R : Type u_3
M : Type u_4
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
BR : RingFilterBasis R
BM : AddGroupFilterBasis M
smul : ∀ {U : Set M}, U ∈ BM → ∃ V ∈ BR, ∃ W ∈ BM, V • W ⊆ U
smul_left : ∀ (x₀ : R) {U : Set M}, U ∈ BM → ∃ V ∈ BM, V ⊆ (fun x => x₀ • x) ⁻¹' U
smul_right : ∀ (m₀ : M) {U : Set M}, U ∈ BM → ∃ V ∈ BR, V ⊆ (fun x => x • m₀) ⁻¹' U
x✝ : TopologicalSpace R := RingFilterBasis.topology BR
⊢ ∀ (m₀ : M) {U : Set M}, U ∈ AddGroupFilterBasis.toFilterBasis.sets → ∀ᶠ (x : R) in 𝓝 0, x • m₀ ∈ U

Next tactic:
intro m₀ U U_in
/-- Build a module filter basis from compatible ring and additive group filter bases. -/
def ofBases {R M : Type*} [CommRing R] [AddCommGroup M] [Module R M] (BR : RingFilterBasis R)
    (BM : AddGroupFilterBasis M) (smul : ∀ {U}, U ∈ BM → ∃ V ∈ BR, ∃ W ∈ BM, V • W ⊆ U)
    (smul_left : ∀ (x₀ : R) {U}, U ∈ BM → ∃ V ∈ BM, V ⊆ (fun x ↦ x₀ • x) ⁻¹' U)
    (smul_right : ∀ (m₀ : M) {U}, U ∈ BM → ∃ V ∈ BR, V ⊆ (fun x ↦ x • m₀) ⁻¹' U) :
    @ModuleFilterBasis R M _ BR.topology _ _ :=
  let _ := BR.topology
  { BM with
    smul' := by
      intro U U_in
      rcases smul U_in with ⟨V, V_in, W, W_in, H⟩
      exact ⟨V, BR.toAddGroupFilterBasis.mem_nhds_zero V_in, W, W_in, H⟩
    smul_left' := smul_left
    smul_right' := by
      intro m₀ U U_in
      

Proof state:
R✝ : Type u_1
M✝ : Type u_2
inst✝⁶ : CommRing R✝
inst✝⁵ : TopologicalSpace R✝
inst✝⁴ : AddCommGroup M✝
inst✝³ : Module R✝ M✝
B : ModuleFilterBasis R✝ M✝
R : Type u_3
M : Type u_4
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
BR : RingFilterBasis R
BM : AddGroupFilterBasis M
smul : ∀ {U : Set M}, U ∈ BM → ∃ V ∈ BR, ∃ W ∈ BM, V • W ⊆ U
smul_left : ∀ (x₀ : R) {U : Set M}, U ∈ BM → ∃ V ∈ BM, V ⊆ (fun x => x₀ • x) ⁻¹' U
smul_right : ∀ (m₀ : M) {U : Set M}, U ∈ BM → ∃ V ∈ BR, V ⊆ (fun x => x • m₀) ⁻¹' U
x✝ : TopologicalSpace R := RingFilterBasis.topology BR
m₀ : M
U : Set M
U_in : U ∈ AddGroupFilterBasis.toFilterBasis.sets
⊢ ∀ᶠ (x : R) in 𝓝 0, x • m₀ ∈ U

Next tactic:
rcases smul_right m₀ U_in with ⟨V, V_in, H⟩
/-- Build a module filter basis from compatible ring and additive group filter bases. -/
def ofBases {R M : Type*} [CommRing R] [AddCommGroup M] [Module R M] (BR : RingFilterBasis R)
    (BM : AddGroupFilterBasis M) (smul : ∀ {U}, U ∈ BM → ∃ V ∈ BR, ∃ W ∈ BM, V • W ⊆ U)
    (smul_left : ∀ (x₀ : R) {U}, U ∈ BM → ∃ V ∈ BM, V ⊆ (fun x ↦ x₀ • x) ⁻¹' U)
    (smul_right : ∀ (m₀ : M) {U}, U ∈ BM → ∃ V ∈ BR, V ⊆ (fun x ↦ x • m₀) ⁻¹' U) :
    @ModuleFilterBasis R M _ BR.topology _ _ :=
  let _ := BR.topology
  { BM with
    smul' := by
      intro U U_in
      rcases smul U_in with ⟨V, V_in, W, W_in, H⟩
      exact ⟨V, BR.toAddGroupFilterBasis.mem_nhds_zero V_in, W, W_in, H⟩
    smul_left' := smul_left
    smul_right' := by
      intro m₀ U U_in
      rcases smul_right m₀ U_in with ⟨V, V_in, H⟩
      

Proof state:
case intro.intro
R✝ : Type u_1
M✝ : Type u_2
inst✝⁶ : CommRing R✝
inst✝⁵ : TopologicalSpace R✝
inst✝⁴ : AddCommGroup M✝
inst✝³ : Module R✝ M✝
B : ModuleFilterBasis R✝ M✝
R : Type u_3
M : Type u_4
inst✝² : CommRing R
inst✝¹ : AddCommGroup M
inst✝ : Module R M
BR : RingFilterBasis R
BM : AddGroupFilterBasis M
smul : ∀ {U : Set M}, U ∈ BM → ∃ V ∈ BR, ∃ W ∈ BM, V • W ⊆ U
smul_left : ∀ (x₀ : R) {U : Set M}, U ∈ BM → ∃ V ∈ BM, V ⊆ (fun x => x₀ • x) ⁻¹' U
smul_right : ∀ (m₀ : M) {U : Set M}, U ∈ BM → ∃ V ∈ BR, V ⊆ (fun x => x • m₀) ⁻¹' U
x✝ : TopologicalSpace R := RingFilterBasis.topology BR
m₀ : M
U : Set M
U_in : U ∈ AddGroupFilterBasis.toFilterBasis.sets
V : Set R
V_in : V ∈ BR
H : V ⊆ (fun x => x • m₀) ⁻¹' U
⊢ ∀ᶠ (x : R) in 𝓝 0, x • m₀ ∈ U

Next tactic:
exact mem_of_superset (BR.toAddGroupFilterBasis.mem_nhds_zero V_in) H
theorem HasBasis.eventuallyConst_iff {ι : Sort*} {p : ι → Prop} {s : ι → Set α}
    (h : l.HasBasis p s) : EventuallyConst f l ↔ ∃ i, p i ∧ ∀ x ∈ s i, ∀ y ∈ s i, f x = f y :=
  (h.map f).subsingleton_iff.trans <| by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f : α → β
ι : Sort u_5
p : ι → Prop
s : ι → Set α
h : HasBasis l p s
⊢ (∃ i, p i ∧ Set.Subsingleton (f '' s i)) ↔ ∃ i, p i ∧ ∀ x ∈ s i, ∀ y ∈ s i, f x = f y

Next tactic:
simp only [Set.Subsingleton, ball_image_iff]
theorem eventuallyConst_pred' {p : α → Prop} :
    EventuallyConst p l ↔ (p =ᶠ[l] fun _ ↦ False) ∨ (p =ᶠ[l] fun _ ↦ True) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f : α → β
p : α → Prop
⊢ EventuallyConst p l ↔ (p =ᶠ[l] fun x => False) ∨ p =ᶠ[l] fun x => True

Next tactic:
simp only [eventuallyConst_iff_exists_eventuallyEq, Prop.exists_iff]
theorem eventuallyConst_pred {p : α → Prop} :
    EventuallyConst p l ↔ (∀ᶠ x in l, p x) ∨ (∀ᶠ x in l, ¬p x) := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f : α → β
p : α → Prop
⊢ EventuallyConst p l ↔ (∀ᶠ (x : α) in l, p x) ∨ ∀ᶠ (x : α) in l, ¬p x

Next tactic:
simp [eventuallyConst_pred', or_comm, EventuallyEq]
theorem EventuallyEq.eventuallyConst_iff {g : α → β} (h : f =ᶠ[l] g) :
    EventuallyConst f l ↔ EventuallyConst g l := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f g : α → β
h : f =ᶠ[l] g
⊢ EventuallyConst f l ↔ EventuallyConst g l

Next tactic:
simp only [EventuallyConst, map_congr h]
@[to_additive]
lemma of_mulIndicator_const (h : EventuallyConst (s.mulIndicator fun _ ↦ c) l) (hc : c ≠ 1) :
    EventuallyConst s l := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f : α → β
inst✝ : One β
s : Set α
c : β
h : EventuallyConst (mulIndicator s fun x => c) l
hc : c ≠ 1
⊢ EventuallyConst s l

Next tactic:
simpa [(· ∘ ·), hc, imp_false] using h.comp (· = c)
@[to_additive]
theorem mulIndicator_const (h : EventuallyConst s l) (c : β) :
    EventuallyConst (s.mulIndicator fun _ ↦ c) l := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f : α → β
inst✝ : One β
s : Set α
c✝ : β
h : EventuallyConst s l
c : β
⊢ EventuallyConst (mulIndicator s fun x => c) l

Next tactic:
classical exact h.comp (if · then c else 1)
@[to_additive]
theorem mulIndicator_const (h : EventuallyConst s l) (c : β) :
    EventuallyConst (s.mulIndicator fun _ ↦ c) l := by
  classical 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f : α → β
inst✝ : One β
s : Set α
c✝ : β
h : EventuallyConst s l
c : β
⊢ EventuallyConst (mulIndicator s fun x => c) l

Next tactic:
exact h.comp (if · then c else 1)
@[to_additive (attr := simp)]
theorem mulIndicator_const_iff :
    EventuallyConst (s.mulIndicator fun _ ↦ c) l ↔ c = 1 ∨ EventuallyConst s l := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f : α → β
inst✝ : One β
s : Set α
c : β
⊢ EventuallyConst (mulIndicator s fun x => c) l ↔ c = 1 ∨ EventuallyConst s l

Next tactic:
rcases eq_or_ne c 1 with rfl | hc
@[to_additive (attr := simp)]
theorem mulIndicator_const_iff :
    EventuallyConst (s.mulIndicator fun _ ↦ c) l ↔ c = 1 ∨ EventuallyConst s l := by
  rcases eq_or_ne c 1 with rfl | hc <;> 

Proof state:
case inl
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f : α → β
inst✝ : One β
s : Set α
⊢ EventuallyConst (mulIndicator s fun x => 1) l ↔ 1 = 1 ∨ EventuallyConst s l

Next tactic:
simp [mulIndicator_const_iff_of_ne, *]
@[to_additive (attr := simp)]
theorem mulIndicator_const_iff :
    EventuallyConst (s.mulIndicator fun _ ↦ c) l ↔ c = 1 ∨ EventuallyConst s l := by
  rcases eq_or_ne c 1 with rfl | hc <;> 

Proof state:
case inr
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f : α → β
inst✝ : One β
s : Set α
c : β
hc : c ≠ 1
⊢ EventuallyConst (mulIndicator s fun x => c) l ↔ c = 1 ∨ EventuallyConst s l

Next tactic:
simp [mulIndicator_const_iff_of_ne, *]
lemma eventuallyConst_atTop [SemilatticeSup α] [Nonempty α] :
    EventuallyConst f atTop ↔ (∃ i, ∀ j, i ≤ j → f j = f i) :=
  (atTop_basis.eventuallyConst_iff' fun i _ ↦ left_mem_Ici).trans <| by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f : α → β
inst✝¹ : SemilatticeSup α
inst✝ : Nonempty α
⊢ (∃ i, True ∧ ∀ y ∈ Ici i, f y = f i) ↔ ∃ i, ∀ (j : α), i ≤ j → f j = f i

Next tactic:
simp only [true_and, mem_Ici]
lemma eventuallyConst_atTop_nat {f : ℕ → α} :
    EventuallyConst f atTop ↔ ∃ n, ∀ m, n ≤ m → f (m + 1) = f m := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f✝ : α → β
f : ℕ → α
⊢ EventuallyConst f atTop ↔ ∃ n, ∀ (m : ℕ), n ≤ m → f (m + 1) = f m

Next tactic:
rw [eventuallyConst_atTop]
lemma eventuallyConst_atTop_nat {f : ℕ → α} :
    EventuallyConst f atTop ↔ ∃ n, ∀ m, n ≤ m → f (m + 1) = f m := by
  rw [eventuallyConst_atTop]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f✝ : α → β
f : ℕ → α
⊢ (∃ i, ∀ (j : ℕ), i ≤ j → f j = f i) ↔ ∃ n, ∀ (m : ℕ), n ≤ m → f (m + 1) = f m

Next tactic:
refine exists_congr fun n ↦ ⟨fun h m hm ↦ ?_, fun h m hm ↦ ?_⟩
lemma eventuallyConst_atTop_nat {f : ℕ → α} :
    EventuallyConst f atTop ↔ ∃ n, ∀ m, n ≤ m → f (m + 1) = f m := by
  rw [eventuallyConst_atTop]
  refine exists_congr fun n ↦ ⟨fun h m hm ↦ ?_, fun h m hm ↦ ?_⟩
  · 

Proof state:
case refine_1
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f✝ : α → β
f : ℕ → α
n : ℕ
h : ∀ (j : ℕ), n ≤ j → f j = f n
m : ℕ
hm : n ≤ m
⊢ f (m + 1) = f m

Next tactic:
exact (h (m + 1) (hm.trans m.le_succ)).trans (h m hm).symm
lemma eventuallyConst_atTop_nat {f : ℕ → α} :
    EventuallyConst f atTop ↔ ∃ n, ∀ m, n ≤ m → f (m + 1) = f m := by
  rw [eventuallyConst_atTop]
  refine exists_congr fun n ↦ ⟨fun h m hm ↦ ?_, fun h m hm ↦ ?_⟩
  · exact (h (m + 1) (hm.trans m.le_succ)).trans (h m hm).symm
  · 

Proof state:
case refine_2
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f✝ : α → β
f : ℕ → α
n : ℕ
h : ∀ (m : ℕ), n ≤ m → f (m + 1) = f m
m : ℕ
hm : n ≤ m
⊢ f m = f n

Next tactic:
induction m, hm using Nat.le_induction with
    | base => rfl
    | succ m hm ihm => exact (h m hm).trans ihm
lemma eventuallyConst_atTop_nat {f : ℕ → α} :
    EventuallyConst f atTop ↔ ∃ n, ∀ m, n ≤ m → f (m + 1) = f m := by
  rw [eventuallyConst_atTop]
  refine exists_congr fun n ↦ ⟨fun h m hm ↦ ?_, fun h m hm ↦ ?_⟩
  · exact (h (m + 1) (hm.trans m.le_succ)).trans (h m hm).symm
  · induction m, hm using Nat.le_induction with
    

Proof state:
case refine_2.base
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f✝ : α → β
f : ℕ → α
n : ℕ
h : ∀ (m : ℕ), n ≤ m → f (m + 1) = f m
m : ℕ
⊢ f n = f n

Next tactic:
| base => rfl
lemma eventuallyConst_atTop_nat {f : ℕ → α} :
    EventuallyConst f atTop ↔ ∃ n, ∀ m, n ≤ m → f (m + 1) = f m := by
  rw [eventuallyConst_atTop]
  refine exists_congr fun n ↦ ⟨fun h m hm ↦ ?_, fun h m hm ↦ ?_⟩
  · exact (h (m + 1) (hm.trans m.le_succ)).trans (h m hm).symm
  · induction m, hm using Nat.le_induction with
    | base => 

Proof state:
case refine_2.base
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f✝ : α → β
f : ℕ → α
n : ℕ
h : ∀ (m : ℕ), n ≤ m → f (m + 1) = f m
m : ℕ
⊢ f n = f n

Next tactic:
rfl
lemma eventuallyConst_atTop_nat {f : ℕ → α} :
    EventuallyConst f atTop ↔ ∃ n, ∀ m, n ≤ m → f (m + 1) = f m := by
  rw [eventuallyConst_atTop]
  refine exists_congr fun n ↦ ⟨fun h m hm ↦ ?_, fun h m hm ↦ ?_⟩
  · exact (h (m + 1) (hm.trans m.le_succ)).trans (h m hm).symm
  · induction m, hm using Nat.le_induction with
    | base => rfl
    

Proof state:
case refine_2.succ
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f✝ : α → β
f : ℕ → α
n : ℕ
h : ∀ (m : ℕ), n ≤ m → f (m + 1) = f m
m✝ m : ℕ
hm : n ≤ m
ihm : f m = f n
⊢ f (m + 1) = f n

Next tactic:
| succ m hm ihm => exact (h m hm).trans ihm
lemma eventuallyConst_atTop_nat {f : ℕ → α} :
    EventuallyConst f atTop ↔ ∃ n, ∀ m, n ≤ m → f (m + 1) = f m := by
  rw [eventuallyConst_atTop]
  refine exists_congr fun n ↦ ⟨fun h m hm ↦ ?_, fun h m hm ↦ ?_⟩
  · exact (h (m + 1) (hm.trans m.le_succ)).trans (h m hm).symm
  · induction m, hm using Nat.le_induction with
    | base => rfl
    | succ m hm ihm => 

Proof state:
case refine_2.succ
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
l : Filter α
f✝ : α → β
f : ℕ → α
n : ℕ
h : ∀ (m : ℕ), n ≤ m → f (m + 1) = f m
m✝ m : ℕ
hm : n ≤ m
ihm : f m = f n
⊢ f (m + 1) = f n

Next tactic:
exact (h m hm).trans ihm
/-- An extensionality lemma in terms of the coercion to a pi-type.
We prove this explicitly rather than deriving it so that it is in terms of the coercion rather than
the projection `.sieves`.
-/
@[ext]
theorem ext {J₁ J₂ : GrothendieckTopology C} (h : (J₁ : ∀ X : C, Set (Sieve X)) = J₂) :
    J₁ = J₂ := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : C
S R : Sieve X
J J₁ J₂ : GrothendieckTopology C
h : J₁.sieves = J₂.sieves
⊢ J₁ = J₂

Next tactic:
cases J₁
/-- An extensionality lemma in terms of the coercion to a pi-type.
We prove this explicitly rather than deriving it so that it is in terms of the coercion rather than
the projection `.sieves`.
-/
@[ext]
theorem ext {J₁ J₂ : GrothendieckTopology C} (h : (J₁ : ∀ X : C, Set (Sieve X)) = J₂) :
    J₁ = J₂ := by
  cases J₁
  

Proof state:
case mk
C : Type u
inst✝ : Category.{v, u} C
X Y : C
S R : Sieve X
J J₂ : GrothendieckTopology C
sieves✝ : (X : C) → Set (Sieve X)
top_mem'✝ : ∀ (X : C), ⊤ ∈ sieves✝ X
pullback_stable'✝ : ∀ ⦃X Y : C⦄ ⦃S : Sieve X⦄ (f : Y ⟶ X), S ∈ sieves✝ X → Sieve.pullback f S ∈ sieves✝ Y
transitive'✝ :
  ∀ ⦃X : C⦄ ⦃S : Sieve X⦄,
    S ∈ sieves✝ X →
      ∀ (R : Sieve X), (∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, S.arrows f → Sieve.pullback f R ∈ sieves✝ Y) → R ∈ sieves✝ X
h :
  { sieves := sieves✝, top_mem' := top_mem'✝, pullback_stable' := pullback_stable'✝,
        transitive' := transitive'✝ }.sieves =
    J₂.sieves
⊢ { sieves := sieves✝, top_mem' := top_mem'✝, pullback_stable' := pullback_stable'✝, transitive' := transitive'✝ } = J₂

Next tactic:
cases J₂
/-- An extensionality lemma in terms of the coercion to a pi-type.
We prove this explicitly rather than deriving it so that it is in terms of the coercion rather than
the projection `.sieves`.
-/
@[ext]
theorem ext {J₁ J₂ : GrothendieckTopology C} (h : (J₁ : ∀ X : C, Set (Sieve X)) = J₂) :
    J₁ = J₂ := by
  cases J₁
  cases J₂
  

Proof state:
case mk.mk
C : Type u
inst✝ : Category.{v, u} C
X Y : C
S R : Sieve X
J : GrothendieckTopology C
sieves✝¹ : (X : C) → Set (Sieve X)
top_mem'✝¹ : ∀ (X : C), ⊤ ∈ sieves✝¹ X
pullback_stable'✝¹ : ∀ ⦃X Y : C⦄ ⦃S : Sieve X⦄ (f : Y ⟶ X), S ∈ sieves✝¹ X → Sieve.pullback f S ∈ sieves✝¹ Y
transitive'✝¹ :
  ∀ ⦃X : C⦄ ⦃S : Sieve X⦄,
    S ∈ sieves✝¹ X →
      ∀ (R : Sieve X), (∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, S.arrows f → Sieve.pullback f R ∈ sieves✝¹ Y) → R ∈ sieves✝¹ X
sieves✝ : (X : C) → Set (Sieve X)
top_mem'✝ : ∀ (X : C), ⊤ ∈ sieves✝ X
pullback_stable'✝ : ∀ ⦃X Y : C⦄ ⦃S : Sieve X⦄ (f : Y ⟶ X), S ∈ sieves✝ X → Sieve.pullback f S ∈ sieves✝ Y
transitive'✝ :
  ∀ ⦃X : C⦄ ⦃S : Sieve X⦄,
    S ∈ sieves✝ X →
      ∀ (R : Sieve X), (∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, S.arrows f → Sieve.pullback f R ∈ sieves✝ Y) → R ∈ sieves✝ X
h :
  { sieves := sieves✝¹, top_mem' := top_mem'✝¹, pullback_stable' := pullback_stable'✝¹,
        transitive' := transitive'✝¹ }.sieves =
    { sieves := sieves✝, top_mem' := top_mem'✝, pullback_stable' := pullback_stable'✝,
        transitive' := transitive'✝ }.sieves
⊢ { sieves := sieves✝¹, top_mem' := top_mem'✝¹, pullback_stable' := pullback_stable'✝¹, transitive' := transitive'✝¹ } =
    { sieves := sieves✝, top_mem' := top_mem'✝, pullback_stable' := pullback_stable'✝, transitive' := transitive'✝ }

Next tactic:
congr
/-- If `S` is a subset of `R`, and `S` is covering, then `R` is covering as well.

See <https://stacks.math.columbia.edu/tag/00Z5> (2), or discussion after [MM92] Chapter III,
Section 2, Definition 1.
-/
theorem superset_covering (Hss : S ≤ R) (sjx : S ∈ J X) : R ∈ J X := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : C
S R : Sieve X
J : GrothendieckTopology C
Hss : S ≤ R
sjx : S ∈ sieves J X
⊢ R ∈ sieves J X

Next tactic:
apply J.transitive sjx R fun Y f hf => _
/-- If `S` is a subset of `R`, and `S` is covering, then `R` is covering as well.

See <https://stacks.math.columbia.edu/tag/00Z5> (2), or discussion after [MM92] Chapter III,
Section 2, Definition 1.
-/
theorem superset_covering (Hss : S ≤ R) (sjx : S ∈ J X) : R ∈ J X := by
  apply J.transitive sjx R fun Y f hf => _
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : C
S R : Sieve X
J : GrothendieckTopology C
Hss : S ≤ R
sjx : S ∈ sieves J X
⊢ ∀ (Y : C) (f : Y ⟶ X), S.arrows f → Sieve.pullback f R ∈ sieves J Y

Next tactic:
intros Y f hf
/-- If `S` is a subset of `R`, and `S` is covering, then `R` is covering as well.

See <https://stacks.math.columbia.edu/tag/00Z5> (2), or discussion after [MM92] Chapter III,
Section 2, Definition 1.
-/
theorem superset_covering (Hss : S ≤ R) (sjx : S ∈ J X) : R ∈ J X := by
  apply J.transitive sjx R fun Y f hf => _
  intros Y f hf
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y✝ : C
S R : Sieve X
J : GrothendieckTopology C
Hss : S ≤ R
sjx : S ∈ sieves J X
Y : C
f : Y ⟶ X
hf : S.arrows f
⊢ Sieve.pullback f R ∈ sieves J Y

Next tactic:
apply covering_of_eq_top
/-- If `S` is a subset of `R`, and `S` is covering, then `R` is covering as well.

See <https://stacks.math.columbia.edu/tag/00Z5> (2), or discussion after [MM92] Chapter III,
Section 2, Definition 1.
-/
theorem superset_covering (Hss : S ≤ R) (sjx : S ∈ J X) : R ∈ J X := by
  apply J.transitive sjx R fun Y f hf => _
  intros Y f hf
  apply covering_of_eq_top
  

Proof state:
case a
C : Type u
inst✝ : Category.{v, u} C
X Y✝ : C
S R : Sieve X
J : GrothendieckTopology C
Hss : S ≤ R
sjx : S ∈ sieves J X
Y : C
f : Y ⟶ X
hf : S.arrows f
⊢ Sieve.pullback f R = ⊤

Next tactic:
rw [← top_le_iff, ← S.pullback_eq_top_of_mem hf]
/-- If `S` is a subset of `R`, and `S` is covering, then `R` is covering as well.

See <https://stacks.math.columbia.edu/tag/00Z5> (2), or discussion after [MM92] Chapter III,
Section 2, Definition 1.
-/
theorem superset_covering (Hss : S ≤ R) (sjx : S ∈ J X) : R ∈ J X := by
  apply J.transitive sjx R fun Y f hf => _
  intros Y f hf
  apply covering_of_eq_top
  rw [← top_le_iff, ← S.pullback_eq_top_of_mem hf]
  

Proof state:
case a
C : Type u
inst✝ : Category.{v, u} C
X Y✝ : C
S R : Sieve X
J : GrothendieckTopology C
Hss : S ≤ R
sjx : S ∈ sieves J X
Y : C
f : Y ⟶ X
hf : S.arrows f
⊢ Sieve.pullback f S ≤ Sieve.pullback f R

Next tactic:
apply Sieve.pullback_monotone _ Hss
/-- The intersection of two covering sieves is covering.

See <https://stacks.math.columbia.edu/tag/00Z5> (1), or [MM92] Chapter III,
Section 2, Definition 1 (iv).
-/
theorem intersection_covering (rj : R ∈ J X) (sj : S ∈ J X) : R ⊓ S ∈ J X := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : C
S R : Sieve X
J : GrothendieckTopology C
rj : R ∈ sieves J X
sj : S ∈ sieves J X
⊢ R ⊓ S ∈ sieves J X

Next tactic:
apply J.transitive rj _ fun Y f Hf => _
/-- The intersection of two covering sieves is covering.

See <https://stacks.math.columbia.edu/tag/00Z5> (1), or [MM92] Chapter III,
Section 2, Definition 1 (iv).
-/
theorem intersection_covering (rj : R ∈ J X) (sj : S ∈ J X) : R ⊓ S ∈ J X := by
  apply J.transitive rj _ fun Y f Hf => _
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : C
S R : Sieve X
J : GrothendieckTopology C
rj : R ∈ sieves J X
sj : S ∈ sieves J X
⊢ ∀ (Y : C) (f : Y ⟶ X), R.arrows f → Sieve.pullback f (R ⊓ S) ∈ sieves J Y

Next tactic:
intros Y f hf
/-- The intersection of two covering sieves is covering.

See <https://stacks.math.columbia.edu/tag/00Z5> (1), or [MM92] Chapter III,
Section 2, Definition 1 (iv).
-/
theorem intersection_covering (rj : R ∈ J X) (sj : S ∈ J X) : R ⊓ S ∈ J X := by
  apply J.transitive rj _ fun Y f Hf => _
  intros Y f hf
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y✝ : C
S R : Sieve X
J : GrothendieckTopology C
rj : R ∈ sieves J X
sj : S ∈ sieves J X
Y : C
f : Y ⟶ X
hf : R.arrows f
⊢ Sieve.pullback f (R ⊓ S) ∈ sieves J Y

Next tactic:
rw [Sieve.pullback_inter, R.pullback_eq_top_of_mem hf]
/-- The intersection of two covering sieves is covering.

See <https://stacks.math.columbia.edu/tag/00Z5> (1), or [MM92] Chapter III,
Section 2, Definition 1 (iv).
-/
theorem intersection_covering (rj : R ∈ J X) (sj : S ∈ J X) : R ⊓ S ∈ J X := by
  apply J.transitive rj _ fun Y f Hf => _
  intros Y f hf
  rw [Sieve.pullback_inter, R.pullback_eq_top_of_mem hf]
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y✝ : C
S R : Sieve X
J : GrothendieckTopology C
rj : R ∈ sieves J X
sj : S ∈ sieves J X
Y : C
f : Y ⟶ X
hf : R.arrows f
⊢ ⊤ ⊓ Sieve.pullback f S ∈ sieves J Y

Next tactic:
simp [sj]