l3lab/ntp-mathlib huggingface dataset:
theorem Monotone.isBoundedUnder_le_comp_iff [Nonempty β] [LinearOrder β] [Preorder γ] [NoMaxOrder γ]
    {g : β → γ} {f : α → β} {l : Filter α} (hg : Monotone g) (hg' : Tendsto g atTop atTop) :
    IsBoundedUnder (· ≤ ·) l (g ∘ f) ↔ IsBoundedUnder (· ≤ ·) l f := by
  refine' ⟨_, fun h => h.isBoundedUnder (α := β) hg⟩
  rintro ⟨c, hc⟩; rw [eventually_map] at hc
  

Proof state:
case intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
ι' : Type u_5
inst✝³ : Nonempty β
inst✝² : LinearOrder β
inst✝¹ : Preorder γ
inst✝ : NoMaxOrder γ
g : β → γ
f : α → β
l : Filter α
hg : Monotone g
hg' : Tendsto g atTop atTop
c : γ
hc : ∀ᶠ (a : α) in l, (fun x x_1 => x ≤ x_1) ((g ∘ f) a) c
⊢ IsBoundedUnder (fun x x_1 => x ≤ x_1) l f

Next tactic:
obtain ⟨b, hb⟩ : ∃ b, ∀ a ≥ b, c < g a := eventually_atTop.1 (hg'.eventually_gt_atTop c)
theorem Monotone.isBoundedUnder_le_comp_iff [Nonempty β] [LinearOrder β] [Preorder γ] [NoMaxOrder γ]
    {g : β → γ} {f : α → β} {l : Filter α} (hg : Monotone g) (hg' : Tendsto g atTop atTop) :
    IsBoundedUnder (· ≤ ·) l (g ∘ f) ↔ IsBoundedUnder (· ≤ ·) l f := by
  refine' ⟨_, fun h => h.isBoundedUnder (α := β) hg⟩
  rintro ⟨c, hc⟩; rw [eventually_map] at hc
  obtain ⟨b, hb⟩ : ∃ b, ∀ a ≥ b, c < g a := eventually_atTop.1 (hg'.eventually_gt_atTop c)
  

Proof state:
case intro.intro
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
ι' : Type u_5
inst✝³ : Nonempty β
inst✝² : LinearOrder β
inst✝¹ : Preorder γ
inst✝ : NoMaxOrder γ
g : β → γ
f : α → β
l : Filter α
hg : Monotone g
hg' : Tendsto g atTop atTop
c : γ
hc : ∀ᶠ (a : α) in l, (fun x x_1 => x ≤ x_1) ((g ∘ f) a) c
b : β
hb : ∀ a ≥ b, c < g a
⊢ IsBoundedUnder (fun x x_1 => x ≤ x_1) l f

Next tactic:
exact ⟨b, hc.mono fun x hx => not_lt.1 fun h => (hb _ h.le).not_le hx⟩
theorem GaloisConnection.l_limsup_le [ConditionallyCompleteLattice β]
    [ConditionallyCompleteLattice γ] {f : Filter α} {v : α → β} {l : β → γ} {u : γ → β}
    (gc : GaloisConnection l u)
    (hlv : f.IsBoundedUnder (· ≤ ·) fun x => l (v x) := by isBoundedDefault)
    (hv_co : f.IsCoboundedUnder (· ≤ ·) v := by isBoundedDefault) :
    l (limsup v f) ≤ limsup (fun x => l (v x)) f := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
ι' : Type u_5
inst✝¹ : ConditionallyCompleteLattice β
inst✝ : ConditionallyCompleteLattice γ
f : Filter α
v : α → β
l : β → γ
u : γ → β
gc : GaloisConnection l u
hlv : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f fun x => l (v x)) _auto✝
hv_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f v) _auto✝
⊢ l (limsup v f) ≤ limsup (fun x => l (v x)) f

Next tactic:
refine' le_limsSup_of_le hlv fun c hc => _
theorem GaloisConnection.l_limsup_le [ConditionallyCompleteLattice β]
    [ConditionallyCompleteLattice γ] {f : Filter α} {v : α → β} {l : β → γ} {u : γ → β}
    (gc : GaloisConnection l u)
    (hlv : f.IsBoundedUnder (· ≤ ·) fun x => l (v x) := by isBoundedDefault)
    (hv_co : f.IsCoboundedUnder (· ≤ ·) v := by isBoundedDefault) :
    l (limsup v f) ≤ limsup (fun x => l (v x)) f := by
  refine' le_limsSup_of_le hlv fun c hc => _
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
ι' : Type u_5
inst✝¹ : ConditionallyCompleteLattice β
inst✝ : ConditionallyCompleteLattice γ
f : Filter α
v : α → β
l : β → γ
u : γ → β
gc : GaloisConnection l u
hlv : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f fun x => l (v x)) _auto✝
hv_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f v) _auto✝
c : γ
hc : ∀ᶠ (n : γ) in map (fun x => l (v x)) f, n ≤ c
⊢ l (limsup v f) ≤ c

Next tactic:
rw [Filter.eventually_map] at hc
theorem GaloisConnection.l_limsup_le [ConditionallyCompleteLattice β]
    [ConditionallyCompleteLattice γ] {f : Filter α} {v : α → β} {l : β → γ} {u : γ → β}
    (gc : GaloisConnection l u)
    (hlv : f.IsBoundedUnder (· ≤ ·) fun x => l (v x) := by isBoundedDefault)
    (hv_co : f.IsCoboundedUnder (· ≤ ·) v := by isBoundedDefault) :
    l (limsup v f) ≤ limsup (fun x => l (v x)) f := by
  refine' le_limsSup_of_le hlv fun c hc => _
  rw [Filter.eventually_map] at hc
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
ι' : Type u_5
inst✝¹ : ConditionallyCompleteLattice β
inst✝ : ConditionallyCompleteLattice γ
f : Filter α
v : α → β
l : β → γ
u : γ → β
gc : GaloisConnection l u
hlv : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f fun x => l (v x)) _auto✝
hv_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f v) _auto✝
c : γ
hc : ∀ᶠ (a : α) in f, l (v a) ≤ c
⊢ l (limsup v f) ≤ c

Next tactic:
simp_rw [gc _ _] at hc ⊢
theorem GaloisConnection.l_limsup_le [ConditionallyCompleteLattice β]
    [ConditionallyCompleteLattice γ] {f : Filter α} {v : α → β} {l : β → γ} {u : γ → β}
    (gc : GaloisConnection l u)
    (hlv : f.IsBoundedUnder (· ≤ ·) fun x => l (v x) := by isBoundedDefault)
    (hv_co : f.IsCoboundedUnder (· ≤ ·) v := by isBoundedDefault) :
    l (limsup v f) ≤ limsup (fun x => l (v x)) f := by
  refine' le_limsSup_of_le hlv fun c hc => _
  rw [Filter.eventually_map] at hc
  simp_rw [gc _ _] at hc ⊢
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
ι' : Type u_5
inst✝¹ : ConditionallyCompleteLattice β
inst✝ : ConditionallyCompleteLattice γ
f : Filter α
v : α → β
l : β → γ
u : γ → β
gc : GaloisConnection l u
hlv : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f fun x => l (v x)) _auto✝
hv_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f v) _auto✝
c : γ
hc : ∀ᶠ (a : α) in f, v a ≤ u c
⊢ limsup v f ≤ u c

Next tactic:
exact limsSup_le_of_le hv_co hc
theorem OrderIso.limsup_apply {γ} [ConditionallyCompleteLattice β] [ConditionallyCompleteLattice γ]
    {f : Filter α} {u : α → β} (g : β ≃o γ)
    (hu : f.IsBoundedUnder (· ≤ ·) u := by isBoundedDefault)
    (hu_co : f.IsCoboundedUnder (· ≤ ·) u := by isBoundedDefault)
    (hgu : f.IsBoundedUnder (· ≤ ·) fun x => g (u x) := by isBoundedDefault)
    (hgu_co : f.IsCoboundedUnder (· ≤ ·) fun x => g (u x) := by isBoundedDefault) :
    g (limsup u f) = limsup (fun x => g (u x)) f := by
  

Proof state:
α : Type u_1
β : Type u_2
γ✝ : Type u_3
ι : Type u_4
ι' : Type u_5
γ : Type u_6
inst✝¹ : ConditionallyCompleteLattice β
inst✝ : ConditionallyCompleteLattice γ
f : Filter α
u : α → β
g : β ≃o γ
hu : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f u) _auto✝
hu_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f u) _auto✝
hgu : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f fun x => g (u x)) _auto✝
hgu_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f fun x => g (u x)) _auto✝
⊢ g (limsup u f) = limsup (fun x => g (u x)) f

Next tactic:
refine' le_antisymm ((OrderIso.to_galoisConnection g).l_limsup_le hgu hu_co) _
theorem OrderIso.limsup_apply {γ} [ConditionallyCompleteLattice β] [ConditionallyCompleteLattice γ]
    {f : Filter α} {u : α → β} (g : β ≃o γ)
    (hu : f.IsBoundedUnder (· ≤ ·) u := by isBoundedDefault)
    (hu_co : f.IsCoboundedUnder (· ≤ ·) u := by isBoundedDefault)
    (hgu : f.IsBoundedUnder (· ≤ ·) fun x => g (u x) := by isBoundedDefault)
    (hgu_co : f.IsCoboundedUnder (· ≤ ·) fun x => g (u x) := by isBoundedDefault) :
    g (limsup u f) = limsup (fun x => g (u x)) f := by
  refine' le_antisymm ((OrderIso.to_galoisConnection g).l_limsup_le hgu hu_co) _
  

Proof state:
α : Type u_1
β : Type u_2
γ✝ : Type u_3
ι : Type u_4
ι' : Type u_5
γ : Type u_6
inst✝¹ : ConditionallyCompleteLattice β
inst✝ : ConditionallyCompleteLattice γ
f : Filter α
u : α → β
g : β ≃o γ
hu : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f u) _auto✝
hu_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f u) _auto✝
hgu : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f fun x => g (u x)) _auto✝
hgu_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f fun x => g (u x)) _auto✝
⊢ limsup (fun x => g (u x)) f ≤ g (limsup u f)

Next tactic:
rw [← g.symm.symm_apply_apply <| limsup (fun x => g (u x)) f, g.symm_symm]
theorem OrderIso.limsup_apply {γ} [ConditionallyCompleteLattice β] [ConditionallyCompleteLattice γ]
    {f : Filter α} {u : α → β} (g : β ≃o γ)
    (hu : f.IsBoundedUnder (· ≤ ·) u := by isBoundedDefault)
    (hu_co : f.IsCoboundedUnder (· ≤ ·) u := by isBoundedDefault)
    (hgu : f.IsBoundedUnder (· ≤ ·) fun x => g (u x) := by isBoundedDefault)
    (hgu_co : f.IsCoboundedUnder (· ≤ ·) fun x => g (u x) := by isBoundedDefault) :
    g (limsup u f) = limsup (fun x => g (u x)) f := by
  refine' le_antisymm ((OrderIso.to_galoisConnection g).l_limsup_le hgu hu_co) _
  rw [← g.symm.symm_apply_apply <| limsup (fun x => g (u x)) f, g.symm_symm]
  

Proof state:
α : Type u_1
β : Type u_2
γ✝ : Type u_3
ι : Type u_4
ι' : Type u_5
γ : Type u_6
inst✝¹ : ConditionallyCompleteLattice β
inst✝ : ConditionallyCompleteLattice γ
f : Filter α
u : α → β
g : β ≃o γ
hu : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f u) _auto✝
hu_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f u) _auto✝
hgu : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f fun x => g (u x)) _auto✝
hgu_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f fun x => g (u x)) _auto✝
⊢ g ((symm g) (limsup (fun x => g (u x)) f)) ≤ g (limsup u f)

Next tactic:
refine' g.monotone _
theorem OrderIso.limsup_apply {γ} [ConditionallyCompleteLattice β] [ConditionallyCompleteLattice γ]
    {f : Filter α} {u : α → β} (g : β ≃o γ)
    (hu : f.IsBoundedUnder (· ≤ ·) u := by isBoundedDefault)
    (hu_co : f.IsCoboundedUnder (· ≤ ·) u := by isBoundedDefault)
    (hgu : f.IsBoundedUnder (· ≤ ·) fun x => g (u x) := by isBoundedDefault)
    (hgu_co : f.IsCoboundedUnder (· ≤ ·) fun x => g (u x) := by isBoundedDefault) :
    g (limsup u f) = limsup (fun x => g (u x)) f := by
  refine' le_antisymm ((OrderIso.to_galoisConnection g).l_limsup_le hgu hu_co) _
  rw [← g.symm.symm_apply_apply <| limsup (fun x => g (u x)) f, g.symm_symm]
  refine' g.monotone _
  

Proof state:
α : Type u_1
β : Type u_2
γ✝ : Type u_3
ι : Type u_4
ι' : Type u_5
γ : Type u_6
inst✝¹ : ConditionallyCompleteLattice β
inst✝ : ConditionallyCompleteLattice γ
f : Filter α
u : α → β
g : β ≃o γ
hu : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f u) _auto✝
hu_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f u) _auto✝
hgu : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f fun x => g (u x)) _auto✝
hgu_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f fun x => g (u x)) _auto✝
⊢ (symm g) (limsup (fun x => g (u x)) f) ≤ limsup u f

Next tactic:
have hf : u = fun i => g.symm (g (u i)) := funext fun i => (g.symm_apply_apply (u i)).symm
theorem OrderIso.limsup_apply {γ} [ConditionallyCompleteLattice β] [ConditionallyCompleteLattice γ]
    {f : Filter α} {u : α → β} (g : β ≃o γ)
    (hu : f.IsBoundedUnder (· ≤ ·) u := by isBoundedDefault)
    (hu_co : f.IsCoboundedUnder (· ≤ ·) u := by isBoundedDefault)
    (hgu : f.IsBoundedUnder (· ≤ ·) fun x => g (u x) := by isBoundedDefault)
    (hgu_co : f.IsCoboundedUnder (· ≤ ·) fun x => g (u x) := by isBoundedDefault) :
    g (limsup u f) = limsup (fun x => g (u x)) f := by
  refine' le_antisymm ((OrderIso.to_galoisConnection g).l_limsup_le hgu hu_co) _
  rw [← g.symm.symm_apply_apply <| limsup (fun x => g (u x)) f, g.symm_symm]
  refine' g.monotone _
  have hf : u = fun i => g.symm (g (u i)) := funext fun i => (g.symm_apply_apply (u i)).symm
  -- Porting note: nth_rw 1 to nth_rw 2
  

Proof state:
α : Type u_1
β : Type u_2
γ✝ : Type u_3
ι : Type u_4
ι' : Type u_5
γ : Type u_6
inst✝¹ : ConditionallyCompleteLattice β
inst✝ : ConditionallyCompleteLattice γ
f : Filter α
u : α → β
g : β ≃o γ
hu : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f u) _auto✝
hu_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f u) _auto✝
hgu : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f fun x => g (u x)) _auto✝
hgu_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f fun x => g (u x)) _auto✝
hf : u = fun i => (symm g) (g (u i))
⊢ (symm g) (limsup (fun x => g (u x)) f) ≤ limsup u f

Next tactic:
nth_rw 2 [hf]
theorem OrderIso.limsup_apply {γ} [ConditionallyCompleteLattice β] [ConditionallyCompleteLattice γ]
    {f : Filter α} {u : α → β} (g : β ≃o γ)
    (hu : f.IsBoundedUnder (· ≤ ·) u := by isBoundedDefault)
    (hu_co : f.IsCoboundedUnder (· ≤ ·) u := by isBoundedDefault)
    (hgu : f.IsBoundedUnder (· ≤ ·) fun x => g (u x) := by isBoundedDefault)
    (hgu_co : f.IsCoboundedUnder (· ≤ ·) fun x => g (u x) := by isBoundedDefault) :
    g (limsup u f) = limsup (fun x => g (u x)) f := by
  refine' le_antisymm ((OrderIso.to_galoisConnection g).l_limsup_le hgu hu_co) _
  rw [← g.symm.symm_apply_apply <| limsup (fun x => g (u x)) f, g.symm_symm]
  refine' g.monotone _
  have hf : u = fun i => g.symm (g (u i)) := funext fun i => (g.symm_apply_apply (u i)).symm
  -- Porting note: nth_rw 1 to nth_rw 2
  nth_rw 2 [hf]
  

Proof state:
α : Type u_1
β : Type u_2
γ✝ : Type u_3
ι : Type u_4
ι' : Type u_5
γ : Type u_6
inst✝¹ : ConditionallyCompleteLattice β
inst✝ : ConditionallyCompleteLattice γ
f : Filter α
u : α → β
g : β ≃o γ
hu : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f u) _auto✝
hu_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f u) _auto✝
hgu : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f fun x => g (u x)) _auto✝
hgu_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f fun x => g (u x)) _auto✝
hf : u = fun i => (symm g) (g (u i))
⊢ (symm g) (limsup (fun x => g (u x)) f) ≤ limsup (fun i => (symm g) (g (u i))) f

Next tactic:
refine' (OrderIso.to_galoisConnection g.symm).l_limsup_le _ hgu_co
theorem OrderIso.limsup_apply {γ} [ConditionallyCompleteLattice β] [ConditionallyCompleteLattice γ]
    {f : Filter α} {u : α → β} (g : β ≃o γ)
    (hu : f.IsBoundedUnder (· ≤ ·) u := by isBoundedDefault)
    (hu_co : f.IsCoboundedUnder (· ≤ ·) u := by isBoundedDefault)
    (hgu : f.IsBoundedUnder (· ≤ ·) fun x => g (u x) := by isBoundedDefault)
    (hgu_co : f.IsCoboundedUnder (· ≤ ·) fun x => g (u x) := by isBoundedDefault) :
    g (limsup u f) = limsup (fun x => g (u x)) f := by
  refine' le_antisymm ((OrderIso.to_galoisConnection g).l_limsup_le hgu hu_co) _
  rw [← g.symm.symm_apply_apply <| limsup (fun x => g (u x)) f, g.symm_symm]
  refine' g.monotone _
  have hf : u = fun i => g.symm (g (u i)) := funext fun i => (g.symm_apply_apply (u i)).symm
  -- Porting note: nth_rw 1 to nth_rw 2
  nth_rw 2 [hf]
  refine' (OrderIso.to_galoisConnection g.symm).l_limsup_le _ hgu_co
  

Proof state:
α : Type u_1
β : Type u_2
γ✝ : Type u_3
ι : Type u_4
ι' : Type u_5
γ : Type u_6
inst✝¹ : ConditionallyCompleteLattice β
inst✝ : ConditionallyCompleteLattice γ
f : Filter α
u : α → β
g : β ≃o γ
hu : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f u) _auto✝
hu_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f u) _auto✝
hgu : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f fun x => g (u x)) _auto✝
hgu_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f fun x => g (u x)) _auto✝
hf : u = fun i => (symm g) (g (u i))
⊢ IsBoundedUnder (fun x x_1 => x ≤ x_1) f fun x => (symm g) (g (u x))

Next tactic:
simp_rw [g.symm_apply_apply]
theorem OrderIso.limsup_apply {γ} [ConditionallyCompleteLattice β] [ConditionallyCompleteLattice γ]
    {f : Filter α} {u : α → β} (g : β ≃o γ)
    (hu : f.IsBoundedUnder (· ≤ ·) u := by isBoundedDefault)
    (hu_co : f.IsCoboundedUnder (· ≤ ·) u := by isBoundedDefault)
    (hgu : f.IsBoundedUnder (· ≤ ·) fun x => g (u x) := by isBoundedDefault)
    (hgu_co : f.IsCoboundedUnder (· ≤ ·) fun x => g (u x) := by isBoundedDefault) :
    g (limsup u f) = limsup (fun x => g (u x)) f := by
  refine' le_antisymm ((OrderIso.to_galoisConnection g).l_limsup_le hgu hu_co) _
  rw [← g.symm.symm_apply_apply <| limsup (fun x => g (u x)) f, g.symm_symm]
  refine' g.monotone _
  have hf : u = fun i => g.symm (g (u i)) := funext fun i => (g.symm_apply_apply (u i)).symm
  -- Porting note: nth_rw 1 to nth_rw 2
  nth_rw 2 [hf]
  refine' (OrderIso.to_galoisConnection g.symm).l_limsup_le _ hgu_co
  simp_rw [g.symm_apply_apply]
  

Proof state:
α : Type u_1
β : Type u_2
γ✝ : Type u_3
ι : Type u_4
ι' : Type u_5
γ : Type u_6
inst✝¹ : ConditionallyCompleteLattice β
inst✝ : ConditionallyCompleteLattice γ
f : Filter α
u : α → β
g : β ≃o γ
hu : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f u) _auto✝
hu_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f u) _auto✝
hgu : autoParam (IsBoundedUnder (fun x x_1 => x ≤ x_1) f fun x => g (u x)) _auto✝
hgu_co : autoParam (IsCoboundedUnder (fun x x_1 => x ≤ x_1) f fun x => g (u x)) _auto✝
hf : u = fun i => (symm g) (g (u i))
⊢ IsBoundedUnder (fun x x_1 => x ≤ x_1) f fun x => u x

Next tactic:
exact hu
/-- A coercion from a congruence relation to its underlying binary relation. -/
instance : FunLike (RingCon R) R fun _ => R → Prop :=
  { coe := fun c => c.r,
    coe_injective' := fun x y h => by
      

Proof state:
α : Type u_1
R : Type u_2
inst✝¹ : Add R
inst✝ : Mul R
c x y : RingCon R
h : (fun c => Setoid.r) x = (fun c => Setoid.r) y
⊢ x = y

Next tactic:
rcases x with ⟨⟨x, _⟩, _⟩
/-- A coercion from a congruence relation to its underlying binary relation. -/
instance : FunLike (RingCon R) R fun _ => R → Prop :=
  { coe := fun c => c.r,
    coe_injective' := fun x y h => by
      rcases x with ⟨⟨x, _⟩, _⟩
      

Proof state:
case mk.mk
α : Type u_1
R : Type u_2
inst✝¹ : Add R
inst✝ : Mul R
c y : RingCon R
x : Setoid R
mul'✝ : ∀ {w x_1 y z : R}, Setoid.r w x_1 → Setoid.r y z → Setoid.r (w * y) (x_1 * z)
add'✝ : ∀ {w x_1 y z : R}, Setoid.r w x_1 → Setoid.r y z → Setoid.r (w + y) (x_1 + z)
h : (fun c => Setoid.r) { toCon := { toSetoid := x, mul' := mul'✝ }, add' := add'✝ } = (fun c => Setoid.r) y
⊢ { toCon := { toSetoid := x, mul' := mul'✝ }, add' := add'✝ } = y

Next tactic:
rcases y with ⟨⟨y, _⟩, _⟩
/-- A coercion from a congruence relation to its underlying binary relation. -/
instance : FunLike (RingCon R) R fun _ => R → Prop :=
  { coe := fun c => c.r,
    coe_injective' := fun x y h => by
      rcases x with ⟨⟨x, _⟩, _⟩
      rcases y with ⟨⟨y, _⟩, _⟩
      

Proof state:
case mk.mk.mk.mk
α : Type u_1
R : Type u_2
inst✝¹ : Add R
inst✝ : Mul R
c : RingCon R
x : Setoid R
mul'✝¹ : ∀ {w x_1 y z : R}, Setoid.r w x_1 → Setoid.r y z → Setoid.r (w * y) (x_1 * z)
add'✝¹ : ∀ {w x_1 y z : R}, Setoid.r w x_1 → Setoid.r y z → Setoid.r (w + y) (x_1 + z)
y : Setoid R
mul'✝ : ∀ {w x y_1 z : R}, Setoid.r w x → Setoid.r y_1 z → Setoid.r (w * y_1) (x * z)
add'✝ : ∀ {w x y_1 z : R}, Setoid.r w x → Setoid.r y_1 z → Setoid.r (w + y_1) (x + z)
h :
  (fun c => Setoid.r) { toCon := { toSetoid := x, mul' := mul'✝¹ }, add' := add'✝¹ } =
    (fun c => Setoid.r) { toCon := { toSetoid := y, mul' := mul'✝ }, add' := add'✝ }
⊢ { toCon := { toSetoid := x, mul' := mul'✝¹ }, add' := add'✝¹ } =
    { toCon := { toSetoid := y, mul' := mul'✝ }, add' := add'✝ }

Next tactic:
congr!
/-- A coercion from a congruence relation to its underlying binary relation. -/
instance : FunLike (RingCon R) R fun _ => R → Prop :=
  { coe := fun c => c.r,
    coe_injective' := fun x y h => by
      rcases x with ⟨⟨x, _⟩, _⟩
      rcases y with ⟨⟨y, _⟩, _⟩
      congr!
      

Proof state:
case mk.mk.mk.mk.h.e'_4.h.e'_3
α : Type u_1
R : Type u_2
inst✝¹ : Add R
inst✝ : Mul R
c : RingCon R
x : Setoid R
mul'✝¹ : ∀ {w x_1 y z : R}, Setoid.r w x_1 → Setoid.r y z → Setoid.r (w * y) (x_1 * z)
add'✝¹ : ∀ {w x_1 y z : R}, Setoid.r w x_1 → Setoid.r y z → Setoid.r (w + y) (x_1 + z)
y : Setoid R
mul'✝ : ∀ {w x y_1 z : R}, Setoid.r w x → Setoid.r y_1 z → Setoid.r (w * y_1) (x * z)
add'✝ : ∀ {w x y_1 z : R}, Setoid.r w x → Setoid.r y_1 z → Setoid.r (w + y_1) (x + z)
h :
  (fun c => Setoid.r) { toCon := { toSetoid := x, mul' := mul'✝¹ }, add' := add'✝¹ } =
    (fun c => Setoid.r) { toCon := { toSetoid := y, mul' := mul'✝ }, add' := add'✝ }
⊢ x = y

Next tactic:
rw [Setoid.ext_iff,(show x.Rel = y.Rel from h)]
/-- A coercion from a congruence relation to its underlying binary relation. -/
instance : FunLike (RingCon R) R fun _ => R → Prop :=
  { coe := fun c => c.r,
    coe_injective' := fun x y h => by
      rcases x with ⟨⟨x, _⟩, _⟩
      rcases y with ⟨⟨y, _⟩, _⟩
      congr!
      rw [Setoid.ext_iff,(show x.Rel = y.Rel from h)]
      

Proof state:
case mk.mk.mk.mk.h.e'_4.h.e'_3
α : Type u_1
R : Type u_2
inst✝¹ : Add R
inst✝ : Mul R
c : RingCon R
x : Setoid R
mul'✝¹ : ∀ {w x_1 y z : R}, Setoid.r w x_1 → Setoid.r y z → Setoid.r (w * y) (x_1 * z)
add'✝¹ : ∀ {w x_1 y z : R}, Setoid.r w x_1 → Setoid.r y z → Setoid.r (w + y) (x_1 + z)
y : Setoid R
mul'✝ : ∀ {w x y_1 z : R}, Setoid.r w x → Setoid.r y_1 z → Setoid.r (w * y_1) (x * z)
add'✝ : ∀ {w x y_1 z : R}, Setoid.r w x → Setoid.r y_1 z → Setoid.r (w + y_1) (x + z)
h :
  (fun c => Setoid.r) { toCon := { toSetoid := x, mul' := mul'✝¹ }, add' := add'✝¹ } =
    (fun c => Setoid.r) { toCon := { toSetoid := y, mul' := mul'✝ }, add' := add'✝ }
⊢ ∀ (a b : R), Setoid.Rel y a b ↔ Setoid.Rel y a b

Next tactic:
simp
/-- Extensionality rule for congruence relations. -/
theorem ext {c d : RingCon R} (H : ∀ x y, c x y ↔ d x y) : c = d :=
  ext' <| by 

Proof state:
α : Type u_1
R : Type u_2
inst✝¹ : Add R
inst✝ : Mul R
c✝ c d : RingCon R
H : ∀ (x y : R), c x y ↔ d x y
⊢ ⇑c = ⇑d

Next tactic:
ext
/-- Extensionality rule for congruence relations. -/
theorem ext {c d : RingCon R} (H : ∀ x y, c x y ↔ d x y) : c = d :=
  ext' <| by ext; 

Proof state:
case h.h.a
α : Type u_1
R : Type u_2
inst✝¹ : Add R
inst✝ : Mul R
c✝ c d : RingCon R
H : ∀ (x y : R), c x y ↔ d x y
x✝¹ x✝ : R
⊢ c x✝¹ x✝ ↔ d x✝¹ x✝

Next tactic:
apply H
/-- The infimum of a set of congruence relations is the same as the infimum of the set's image
    under the map to the underlying equivalence relation. -/
theorem sInf_toSetoid (S : Set (RingCon R)) : (sInf S).toSetoid = sInf ((·.toSetoid) '' S) :=
  Setoid.ext' fun x y =>
    ⟨fun h r ⟨c, hS, hr⟩ => by 

Proof state:
α : Type u_1
R : Type u_2
inst✝¹ : Add R
inst✝ : Mul R
S : Set (RingCon R)
x y : R
h : Setoid.Rel (sInf S).toSetoid x y
r : Setoid R
x✝ : r ∈ (fun x => x.toSetoid) '' S
c : RingCon R
hS : c ∈ S
hr : (fun x => x.toSetoid) c = r
⊢ Setoid.Rel r x y

Next tactic:
rw [← hr]
/-- The infimum of a set of congruence relations is the same as the infimum of the set's image
    under the map to the underlying equivalence relation. -/
theorem sInf_toSetoid (S : Set (RingCon R)) : (sInf S).toSetoid = sInf ((·.toSetoid) '' S) :=
  Setoid.ext' fun x y =>
    ⟨fun h r ⟨c, hS, hr⟩ => by rw [← hr]; 

Proof state:
α : Type u_1
R : Type u_2
inst✝¹ : Add R
inst✝ : Mul R
S : Set (RingCon R)
x y : R
h : Setoid.Rel (sInf S).toSetoid x y
r : Setoid R
x✝ : r ∈ (fun x => x.toSetoid) '' S
c : RingCon R
hS : c ∈ S
hr : (fun x => x.toSetoid) c = r
⊢ Setoid.Rel ((fun x => x.toSetoid) c) x y

Next tactic:
exact h c hS
/-- The infimum of a set of congruence relations is the same as the infimum of the set's image
    under the map to the underlying binary relation. -/
@[simp, norm_cast]
theorem coe_sInf (S : Set (RingCon R)) : ⇑(sInf S) = sInf ((⇑) '' S) := by
  

Proof state:
α : Type u_1
R : Type u_2
inst✝¹ : Add R
inst✝ : Mul R
S : Set (RingCon R)
⊢ ⇑(sInf S) = sInf (FunLike.coe '' S)

Next tactic:
ext
/-- The infimum of a set of congruence relations is the same as the infimum of the set's image
    under the map to the underlying binary relation. -/
@[simp, norm_cast]
theorem coe_sInf (S : Set (RingCon R)) : ⇑(sInf S) = sInf ((⇑) '' S) := by
  ext; 

Proof state:
case h.h.a
α : Type u_1
R : Type u_2
inst✝¹ : Add R
inst✝ : Mul R
S : Set (RingCon R)
x✝¹ x✝ : R
⊢ (sInf S) x✝¹ x✝ ↔ sInf (FunLike.coe '' S) x✝¹ x✝

Next tactic:
simp only [sInf_image, iInf_apply, iInf_Prop_eq]
/-- The infimum of a set of congruence relations is the same as the infimum of the set's image
    under the map to the underlying binary relation. -/
@[simp, norm_cast]
theorem coe_sInf (S : Set (RingCon R)) : ⇑(sInf S) = sInf ((⇑) '' S) := by
  ext; simp only [sInf_image, iInf_apply, iInf_Prop_eq]; 

Proof state:
case h.h.a
α : Type u_1
R : Type u_2
inst✝¹ : Add R
inst✝ : Mul R
S : Set (RingCon R)
x✝¹ x✝ : R
⊢ (sInf S) x✝¹ x✝ ↔ ∀ i ∈ S, i x✝¹ x✝

Next tactic:
rfl
@[simp, norm_cast]
theorem coe_iInf {ι : Sort*} (f : ι → RingCon R) : ⇑(iInf f) = ⨅ i, ⇑(f i) := by
  

Proof state:
α : Type u_1
R : Type u_2
inst✝¹ : Add R
inst✝ : Mul R
ι : Sort u_3
f : ι → RingCon R
⊢ ⇑(iInf f) = ⨅ i, ⇑(f i)

Next tactic:
rw [iInf, coe_sInf, ← Set.range_comp, sInf_range, Function.comp]