l3lab/ntp-mathlib huggingface dataset:
theorem pullback_fst_image_snd_preimage (f : X ⟶ Z) (g : Y ⟶ Z) (U : Set Y) :
    (pullback.fst : pullback f g ⟶ _) '' ((pullback.snd : pullback f g ⟶ _) ⁻¹' U) =
      f ⁻¹' (g '' U) := by
  ext x
  constructor
  · rintro ⟨y, hy, rfl⟩
    exact
      ⟨(pullback.snd : pullback f g ⟶ _) y, hy,
        (ConcreteCategory.congr_hom pullback.condition y).symm⟩
  · rintro ⟨y, hy, eq⟩
    exact ⟨(TopCat.pullbackIsoProdSubtype f g).inv ⟨⟨_, _⟩, eq.symm⟩, by 

Proof state:
J : Type v
inst✝ : SmallCategory J
X Y Z : TopCat
f : X ⟶ Z
g : Y ⟶ Z
U : Set ↑Y
x : (forget TopCat).obj X
y : (forget TopCat).obj Y
hy : y ∈ U
eq : g y = f x
⊢ (pullbackIsoProdSubtype f g).inv { val := (x, y), property := (_ : f x = g y) } ∈ ⇑pullback.snd ⁻¹' U

Next tactic:
simpa
theorem pullback_fst_image_snd_preimage (f : X ⟶ Z) (g : Y ⟶ Z) (U : Set Y) :
    (pullback.fst : pullback f g ⟶ _) '' ((pullback.snd : pullback f g ⟶ _) ⁻¹' U) =
      f ⁻¹' (g '' U) := by
  ext x
  constructor
  · rintro ⟨y, hy, rfl⟩
    exact
      ⟨(pullback.snd : pullback f g ⟶ _) y, hy,
        (ConcreteCategory.congr_hom pullback.condition y).symm⟩
  · rintro ⟨y, hy, eq⟩
    exact ⟨(TopCat.pullbackIsoProdSubtype f g).inv ⟨⟨_, _⟩, eq.symm⟩, by simpa, by 

Proof state:
J : Type v
inst✝ : SmallCategory J
X Y Z : TopCat
f : X ⟶ Z
g : Y ⟶ Z
U : Set ↑Y
x : (forget TopCat).obj X
y : (forget TopCat).obj Y
hy : y ∈ U
eq : g y = f x
⊢ pullback.fst ((pullbackIsoProdSubtype f g).inv { val := (x, y), property := (_ : f x = g y) }) = x

Next tactic:
simp
theorem coinduced_of_isColimit {F : J ⥤ TopCatMax.{v, u}} (c : Cocone F) (hc : IsColimit c) :
    c.pt.str = ⨆ j, (F.obj j).str.coinduced (c.ι.app j) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TopCatMax
c : Cocone F
hc : IsColimit c
⊢ c.pt.str = ⨆ j, coinduced (⇑(c.ι.app j)) (F.obj j).str

Next tactic:
let homeo := homeoOfIso (hc.coconePointUniqueUpToIso (colimitCoconeIsColimit F))
theorem coinduced_of_isColimit {F : J ⥤ TopCatMax.{v, u}} (c : Cocone F) (hc : IsColimit c) :
    c.pt.str = ⨆ j, (F.obj j).str.coinduced (c.ι.app j) := by
  let homeo := homeoOfIso (hc.coconePointUniqueUpToIso (colimitCoconeIsColimit F))
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TopCatMax
c : Cocone F
hc : IsColimit c
homeo : ↑c.pt ≃ₜ ↑(colimitCocone F).pt := homeoOfIso (IsColimit.coconePointUniqueUpToIso hc (colimitCoconeIsColimit F))
⊢ c.pt.str = ⨆ j, coinduced (⇑(c.ι.app j)) (F.obj j).str

Next tactic:
ext
theorem coinduced_of_isColimit {F : J ⥤ TopCatMax.{v, u}} (c : Cocone F) (hc : IsColimit c) :
    c.pt.str = ⨆ j, (F.obj j).str.coinduced (c.ι.app j) := by
  let homeo := homeoOfIso (hc.coconePointUniqueUpToIso (colimitCoconeIsColimit F))
  ext
  

Proof state:
case a.h.a
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TopCatMax
c : Cocone F
hc : IsColimit c
homeo : ↑c.pt ≃ₜ ↑(colimitCocone F).pt := homeoOfIso (IsColimit.coconePointUniqueUpToIso hc (colimitCoconeIsColimit F))
x✝ : Set ↑c.pt
⊢ IsOpen x✝ ↔ IsOpen x✝

Next tactic:
refine' homeo.symm.isOpen_preimage.symm.trans (Iff.trans _ isOpen_iSup_iff.symm)
theorem coinduced_of_isColimit {F : J ⥤ TopCatMax.{v, u}} (c : Cocone F) (hc : IsColimit c) :
    c.pt.str = ⨆ j, (F.obj j).str.coinduced (c.ι.app j) := by
  let homeo := homeoOfIso (hc.coconePointUniqueUpToIso (colimitCoconeIsColimit F))
  ext
  refine' homeo.symm.isOpen_preimage.symm.trans (Iff.trans _ isOpen_iSup_iff.symm)
  

Proof state:
case a.h.a
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TopCatMax
c : Cocone F
hc : IsColimit c
homeo : ↑c.pt ≃ₜ ↑(colimitCocone F).pt := homeoOfIso (IsColimit.coconePointUniqueUpToIso hc (colimitCoconeIsColimit F))
x✝ : Set ↑c.pt
⊢ IsOpen (⇑(Homeomorph.symm homeo) ⁻¹' x✝) ↔ ∀ (i : J), IsOpen x✝

Next tactic:
exact isOpen_iSup_iff
theorem colimit_isOpen_iff (F : J ⥤ TopCatMax.{v, u}) (U : Set ((colimit F : _) : Type max v u)) :
    IsOpen U ↔ ∀ j, IsOpen (colimit.ι F j ⁻¹' U) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TopCatMax
U : Set ↑(colimit F)
⊢ IsOpen U ↔ ∀ (j : J), IsOpen (⇑(colimit.ι F j) ⁻¹' U)

Next tactic:
dsimp [topologicalSpace_coe]
theorem colimit_isOpen_iff (F : J ⥤ TopCatMax.{v, u}) (U : Set ((colimit F : _) : Type max v u)) :
    IsOpen U ↔ ∀ j, IsOpen (colimit.ι F j ⁻¹' U) := by
  dsimp [topologicalSpace_coe]
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TopCatMax
U : Set ↑(colimit F)
⊢ IsOpen U ↔ ∀ (j : J), IsOpen (⇑(colimit.ι F j) ⁻¹' U)

Next tactic:
conv_lhs => rw [colimit_topology F]
theorem colimit_isOpen_iff (F : J ⥤ TopCatMax.{v, u}) (U : Set ((colimit F : _) : Type max v u)) :
    IsOpen U ↔ ∀ j, IsOpen (colimit.ι F j ⁻¹' U) := by
  dsimp [topologicalSpace_coe]
  conv_lhs => 

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TopCatMax
U : Set ↑(colimit F)
| IsOpen U

Next tactic:
rw [colimit_topology F]
theorem colimit_isOpen_iff (F : J ⥤ TopCatMax.{v, u}) (U : Set ((colimit F : _) : Type max v u)) :
    IsOpen U ↔ ∀ j, IsOpen (colimit.ι F j ⁻¹' U) := by
  dsimp [topologicalSpace_coe]
  conv_lhs => rw [colimit_topology F]
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TopCatMax
U : Set ↑(colimit F)
⊢ IsOpen U ↔ ∀ (j : J), IsOpen (⇑(colimit.ι F j) ⁻¹' U)

Next tactic:
exact isOpen_iSup_iff
theorem coequalizer_isOpen_iff (F : WalkingParallelPair ⥤ TopCat.{u})
    (U : Set ((colimit F : _) : Type u)) :
    IsOpen U ↔ IsOpen (colimit.ι F WalkingParallelPair.one ⁻¹' U) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : WalkingParallelPair ⥤ TopCat
U : Set ↑(colimit F)
⊢ IsOpen U ↔ IsOpen (⇑(colimit.ι F WalkingParallelPair.one) ⁻¹' U)

Next tactic:
rw [colimit_isOpen_iff]
theorem coequalizer_isOpen_iff (F : WalkingParallelPair ⥤ TopCat.{u})
    (U : Set ((colimit F : _) : Type u)) :
    IsOpen U ↔ IsOpen (colimit.ι F WalkingParallelPair.one ⁻¹' U) := by
  rw [colimit_isOpen_iff]
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : WalkingParallelPair ⥤ TopCat
U : Set ↑(colimit F)
⊢ (∀ (j : WalkingParallelPair), IsOpen (⇑(colimit.ι F j) ⁻¹' U)) ↔ IsOpen (⇑(colimit.ι F WalkingParallelPair.one) ⁻¹' U)

Next tactic:
constructor
theorem coequalizer_isOpen_iff (F : WalkingParallelPair ⥤ TopCat.{u})
    (U : Set ((colimit F : _) : Type u)) :
    IsOpen U ↔ IsOpen (colimit.ι F WalkingParallelPair.one ⁻¹' U) := by
  rw [colimit_isOpen_iff]
  constructor
  · 

Proof state:
case mp
J : Type v
inst✝ : SmallCategory J
F : WalkingParallelPair ⥤ TopCat
U : Set ↑(colimit F)
⊢ (∀ (j : WalkingParallelPair), IsOpen (⇑(colimit.ι F j) ⁻¹' U)) → IsOpen (⇑(colimit.ι F WalkingParallelPair.one) ⁻¹' U)

Next tactic:
intro H
theorem coequalizer_isOpen_iff (F : WalkingParallelPair ⥤ TopCat.{u})
    (U : Set ((colimit F : _) : Type u)) :
    IsOpen U ↔ IsOpen (colimit.ι F WalkingParallelPair.one ⁻¹' U) := by
  rw [colimit_isOpen_iff]
  constructor
  · intro H
    

Proof state:
case mp
J : Type v
inst✝ : SmallCategory J
F : WalkingParallelPair ⥤ TopCat
U : Set ↑(colimit F)
H : ∀ (j : WalkingParallelPair), IsOpen (⇑(colimit.ι F j) ⁻¹' U)
⊢ IsOpen (⇑(colimit.ι F WalkingParallelPair.one) ⁻¹' U)

Next tactic:
exact H _
theorem coequalizer_isOpen_iff (F : WalkingParallelPair ⥤ TopCat.{u})
    (U : Set ((colimit F : _) : Type u)) :
    IsOpen U ↔ IsOpen (colimit.ι F WalkingParallelPair.one ⁻¹' U) := by
  rw [colimit_isOpen_iff]
  constructor
  · intro H
    exact H _
  · 

Proof state:
case mpr
J : Type v
inst✝ : SmallCategory J
F : WalkingParallelPair ⥤ TopCat
U : Set ↑(colimit F)
⊢ IsOpen (⇑(colimit.ι F WalkingParallelPair.one) ⁻¹' U) → ∀ (j : WalkingParallelPair), IsOpen (⇑(colimit.ι F j) ⁻¹' U)

Next tactic:
intro H j
theorem coequalizer_isOpen_iff (F : WalkingParallelPair ⥤ TopCat.{u})
    (U : Set ((colimit F : _) : Type u)) :
    IsOpen U ↔ IsOpen (colimit.ι F WalkingParallelPair.one ⁻¹' U) := by
  rw [colimit_isOpen_iff]
  constructor
  · intro H
    exact H _
  · intro H j
    

Proof state:
case mpr
J : Type v
inst✝ : SmallCategory J
F : WalkingParallelPair ⥤ TopCat
U : Set ↑(colimit F)
H : IsOpen (⇑(colimit.ι F WalkingParallelPair.one) ⁻¹' U)
j : WalkingParallelPair
⊢ IsOpen (⇑(colimit.ι F j) ⁻¹' U)

Next tactic:
cases j
theorem coequalizer_isOpen_iff (F : WalkingParallelPair ⥤ TopCat.{u})
    (U : Set ((colimit F : _) : Type u)) :
    IsOpen U ↔ IsOpen (colimit.ι F WalkingParallelPair.one ⁻¹' U) := by
  rw [colimit_isOpen_iff]
  constructor
  · intro H
    exact H _
  · intro H j
    cases j
    · 

Proof state:
case mpr.zero
J : Type v
inst✝ : SmallCategory J
F : WalkingParallelPair ⥤ TopCat
U : Set ↑(colimit F)
H : IsOpen (⇑(colimit.ι F WalkingParallelPair.one) ⁻¹' U)
⊢ IsOpen (⇑(colimit.ι F WalkingParallelPair.zero) ⁻¹' U)

Next tactic:
rw [← colimit.w F WalkingParallelPairHom.left]
theorem coequalizer_isOpen_iff (F : WalkingParallelPair ⥤ TopCat.{u})
    (U : Set ((colimit F : _) : Type u)) :
    IsOpen U ↔ IsOpen (colimit.ι F WalkingParallelPair.one ⁻¹' U) := by
  rw [colimit_isOpen_iff]
  constructor
  · intro H
    exact H _
  · intro H j
    cases j
    · rw [← colimit.w F WalkingParallelPairHom.left]
      

Proof state:
case mpr.zero
J : Type v
inst✝ : SmallCategory J
F : WalkingParallelPair ⥤ TopCat
U : Set ↑(colimit F)
H : IsOpen (⇑(colimit.ι F WalkingParallelPair.one) ⁻¹' U)
⊢ IsOpen (⇑(F.map WalkingParallelPairHom.left ≫ colimit.ι F WalkingParallelPair.one) ⁻¹' U)

Next tactic:
exact (F.map WalkingParallelPairHom.left).continuous_toFun.isOpen_preimage _ H
theorem coequalizer_isOpen_iff (F : WalkingParallelPair ⥤ TopCat.{u})
    (U : Set ((colimit F : _) : Type u)) :
    IsOpen U ↔ IsOpen (colimit.ι F WalkingParallelPair.one ⁻¹' U) := by
  rw [colimit_isOpen_iff]
  constructor
  · intro H
    exact H _
  · intro H j
    cases j
    · rw [← colimit.w F WalkingParallelPairHom.left]
      exact (F.map WalkingParallelPairHom.left).continuous_toFun.isOpen_preimage _ H
    · 

Proof state:
case mpr.one
J : Type v
inst✝ : SmallCategory J
F : WalkingParallelPair ⥤ TopCat
U : Set ↑(colimit F)
H : IsOpen (⇑(colimit.ι F WalkingParallelPair.one) ⁻¹' U)
⊢ IsOpen (⇑(colimit.ι F WalkingParallelPair.one) ⁻¹' U)

Next tactic:
exact H
/-- Let `X` be a normal paracompact topological space (e.g., any extended metric space). Let `E` be
a topological real vector space. Let `t : X → Set E` be a family of convex sets. Suppose that for
each point `x : X`, there exists a neighborhood `U ∈ 𝓝 X` and a function `g : X → E` that is
continuous on `U` and sends each `y ∈ U` to a point of `t y`. Then there exists a continuous map
`g : C(X, E)` such that `g x ∈ t x` for all `x`. See also
`exists_continuous_forall_mem_convex_of_local_const`. -/
theorem exists_continuous_forall_mem_convex_of_local (ht : ∀ x, Convex ℝ (t x))
    (H : ∀ x : X, ∃ U ∈ 𝓝 x, ∃ g : X → E, ContinuousOn g U ∧ ∀ y ∈ U, g y ∈ t y) :
    ∃ g : C(X, E), ∀ x, g x ∈ t x := by
  

Proof state:
ι : Type u_1
X : Type u_2
E : Type u_3
inst✝⁷ : TopologicalSpace X
inst✝⁶ : AddCommGroup E
inst✝⁵ : Module ℝ E
inst✝⁴ : NormalSpace X
inst✝³ : ParacompactSpace X
inst✝² : TopologicalSpace E
inst✝¹ : ContinuousAdd E
inst✝ : ContinuousSMul ℝ E
t : X → Set E
ht : ∀ (x : X), Convex ℝ (t x)
H : ∀ (x : X), ∃ U ∈ 𝓝 x, ∃ g, ContinuousOn g U ∧ ∀ y ∈ U, g y ∈ t y
⊢ ∃ g, ∀ (x : X), g x ∈ t x

Next tactic:
choose U hU g hgc hgt using H
/-- Let `X` be a normal paracompact topological space (e.g., any extended metric space). Let `E` be
a topological real vector space. Let `t : X → Set E` be a family of convex sets. Suppose that for
each point `x : X`, there exists a neighborhood `U ∈ 𝓝 X` and a function `g : X → E` that is
continuous on `U` and sends each `y ∈ U` to a point of `t y`. Then there exists a continuous map
`g : C(X, E)` such that `g x ∈ t x` for all `x`. See also
`exists_continuous_forall_mem_convex_of_local_const`. -/
theorem exists_continuous_forall_mem_convex_of_local (ht : ∀ x, Convex ℝ (t x))
    (H : ∀ x : X, ∃ U ∈ 𝓝 x, ∃ g : X → E, ContinuousOn g U ∧ ∀ y ∈ U, g y ∈ t y) :
    ∃ g : C(X, E), ∀ x, g x ∈ t x := by
  choose U hU g hgc hgt using H
  

Proof state:
ι : Type u_1
X : Type u_2
E : Type u_3
inst✝⁷ : TopologicalSpace X
inst✝⁶ : AddCommGroup E
inst✝⁵ : Module ℝ E
inst✝⁴ : NormalSpace X
inst✝³ : ParacompactSpace X
inst✝² : TopologicalSpace E
inst✝¹ : ContinuousAdd E
inst✝ : ContinuousSMul ℝ E
t : X → Set E
ht : ∀ (x : X), Convex ℝ (t x)
U : X → Set X
hU : ∀ (x : X), U x ∈ 𝓝 x
g : X → X → E
hgc : ∀ (x : X), ContinuousOn (g x) (U x)
hgt : ∀ (x y : X), y ∈ U x → g x y ∈ t y
⊢ ∃ g, ∀ (x : X), g x ∈ t x

Next tactic:
obtain ⟨f, hf⟩ := PartitionOfUnity.exists_isSubordinate isClosed_univ (fun x => interior (U x))
    (fun x => isOpen_interior) fun x _ => mem_iUnion.2 ⟨x, mem_interior_iff_mem_nhds.2 (hU x)⟩
/-- Let `X` be a normal paracompact topological space (e.g., any extended metric space). Let `E` be
a topological real vector space. Let `t : X → Set E` be a family of convex sets. Suppose that for
each point `x : X`, there exists a neighborhood `U ∈ 𝓝 X` and a function `g : X → E` that is
continuous on `U` and sends each `y ∈ U` to a point of `t y`. Then there exists a continuous map
`g : C(X, E)` such that `g x ∈ t x` for all `x`. See also
`exists_continuous_forall_mem_convex_of_local_const`. -/
theorem exists_continuous_forall_mem_convex_of_local (ht : ∀ x, Convex ℝ (t x))
    (H : ∀ x : X, ∃ U ∈ 𝓝 x, ∃ g : X → E, ContinuousOn g U ∧ ∀ y ∈ U, g y ∈ t y) :
    ∃ g : C(X, E), ∀ x, g x ∈ t x := by
  choose U hU g hgc hgt using H
  obtain ⟨f, hf⟩ := PartitionOfUnity.exists_isSubordinate isClosed_univ (fun x => interior (U x))
    (fun x => isOpen_interior) fun x _ => mem_iUnion.2 ⟨x, mem_interior_iff_mem_nhds.2 (hU x)⟩
  

Proof state:
case intro
ι : Type u_1
X : Type u_2
E : Type u_3
inst✝⁷ : TopologicalSpace X
inst✝⁶ : AddCommGroup E
inst✝⁵ : Module ℝ E
inst✝⁴ : NormalSpace X
inst✝³ : ParacompactSpace X
inst✝² : TopologicalSpace E
inst✝¹ : ContinuousAdd E
inst✝ : ContinuousSMul ℝ E
t : X → Set E
ht : ∀ (x : X), Convex ℝ (t x)
U : X → Set X
hU : ∀ (x : X), U x ∈ 𝓝 x
g : X → X → E
hgc : ∀ (x : X), ContinuousOn (g x) (U x)
hgt : ∀ (x y : X), y ∈ U x → g x y ∈ t y
f : PartitionOfUnity X X univ
hf : PartitionOfUnity.IsSubordinate f fun x => interior (U x)
⊢ ∃ g, ∀ (x : X), g x ∈ t x

Next tactic:
refine' ⟨⟨fun x => ∑ᶠ i, f i x • g i x,
    hf.continuous_finsum_smul (fun i => isOpen_interior) fun i => (hgc i).mono interior_subset⟩,
    fun x => f.finsum_smul_mem_convex (mem_univ x) (fun i hi => hgt _ _ _) (ht _)⟩
/-- Let `X` be a normal paracompact topological space (e.g., any extended metric space). Let `E` be
a topological real vector space. Let `t : X → Set E` be a family of convex sets. Suppose that for
each point `x : X`, there exists a neighborhood `U ∈ 𝓝 X` and a function `g : X → E` that is
continuous on `U` and sends each `y ∈ U` to a point of `t y`. Then there exists a continuous map
`g : C(X, E)` such that `g x ∈ t x` for all `x`. See also
`exists_continuous_forall_mem_convex_of_local_const`. -/
theorem exists_continuous_forall_mem_convex_of_local (ht : ∀ x, Convex ℝ (t x))
    (H : ∀ x : X, ∃ U ∈ 𝓝 x, ∃ g : X → E, ContinuousOn g U ∧ ∀ y ∈ U, g y ∈ t y) :
    ∃ g : C(X, E), ∀ x, g x ∈ t x := by
  choose U hU g hgc hgt using H
  obtain ⟨f, hf⟩ := PartitionOfUnity.exists_isSubordinate isClosed_univ (fun x => interior (U x))
    (fun x => isOpen_interior) fun x _ => mem_iUnion.2 ⟨x, mem_interior_iff_mem_nhds.2 (hU x)⟩
  refine' ⟨⟨fun x => ∑ᶠ i, f i x • g i x,
    hf.continuous_finsum_smul (fun i => isOpen_interior) fun i => (hgc i).mono interior_subset⟩,
    fun x => f.finsum_smul_mem_convex (mem_univ x) (fun i hi => hgt _ _ _) (ht _)⟩
  

Proof state:
case intro
ι : Type u_1
X : Type u_2
E : Type u_3
inst✝⁷ : TopologicalSpace X
inst✝⁶ : AddCommGroup E
inst✝⁵ : Module ℝ E
inst✝⁴ : NormalSpace X
inst✝³ : ParacompactSpace X
inst✝² : TopologicalSpace E
inst✝¹ : ContinuousAdd E
inst✝ : ContinuousSMul ℝ E
t : X → Set E
ht : ∀ (x : X), Convex ℝ (t x)
U : X → Set X
hU : ∀ (x : X), U x ∈ 𝓝 x
g : X → X → E
hgc : ∀ (x : X), ContinuousOn (g x) (U x)
hgt : ∀ (x y : X), y ∈ U x → g x y ∈ t y
f : PartitionOfUnity X X univ
hf : PartitionOfUnity.IsSubordinate f fun x => interior (U x)
x i : X
hi : (f i) x ≠ 0
⊢ x ∈ U i

Next tactic:
exact interior_subset (hf _ <| subset_closure hi)
/-- For elements `a` and `b` of a linear order, either `min a b = a` and `a ≤ b`,
    or `min a b = b` and `b < a`.
    Use cases on this lemma to automate linarith in inequalities -/
theorem min_cases (a b : α) : min a b = a ∧ a ≤ b ∨ min a b = b ∧ b < a := by
  

Proof state:
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a✝ b✝ c d a b : α
⊢ min a b = a ∧ a ≤ b ∨ min a b = b ∧ b < a

Next tactic:
by_cases h : a ≤ b
/-- For elements `a` and `b` of a linear order, either `min a b = a` and `a ≤ b`,
    or `min a b = b` and `b < a`.
    Use cases on this lemma to automate linarith in inequalities -/
theorem min_cases (a b : α) : min a b = a ∧ a ≤ b ∨ min a b = b ∧ b < a := by
  by_cases h : a ≤ b
  · 

Proof state:
case pos
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a✝ b✝ c d a b : α
h : a ≤ b
⊢ min a b = a ∧ a ≤ b ∨ min a b = b ∧ b < a

Next tactic:
left
/-- For elements `a` and `b` of a linear order, either `min a b = a` and `a ≤ b`,
    or `min a b = b` and `b < a`.
    Use cases on this lemma to automate linarith in inequalities -/
theorem min_cases (a b : α) : min a b = a ∧ a ≤ b ∨ min a b = b ∧ b < a := by
  by_cases h : a ≤ b
  · left
    

Proof state:
case pos.h
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a✝ b✝ c d a b : α
h : a ≤ b
⊢ min a b = a ∧ a ≤ b

Next tactic:
exact ⟨min_eq_left h, h⟩
/-- For elements `a` and `b` of a linear order, either `min a b = a` and `a ≤ b`,
    or `min a b = b` and `b < a`.
    Use cases on this lemma to automate linarith in inequalities -/
theorem min_cases (a b : α) : min a b = a ∧ a ≤ b ∨ min a b = b ∧ b < a := by
  by_cases h : a ≤ b
  · left
    exact ⟨min_eq_left h, h⟩
  · 

Proof state:
case neg
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a✝ b✝ c d a b : α
h : ¬a ≤ b
⊢ min a b = a ∧ a ≤ b ∨ min a b = b ∧ b < a

Next tactic:
right
/-- For elements `a` and `b` of a linear order, either `min a b = a` and `a ≤ b`,
    or `min a b = b` and `b < a`.
    Use cases on this lemma to automate linarith in inequalities -/
theorem min_cases (a b : α) : min a b = a ∧ a ≤ b ∨ min a b = b ∧ b < a := by
  by_cases h : a ≤ b
  · left
    exact ⟨min_eq_left h, h⟩
  · right
    

Proof state:
case neg.h
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a✝ b✝ c d a b : α
h : ¬a ≤ b
⊢ min a b = b ∧ b < a

Next tactic:
exact ⟨min_eq_right (le_of_lt (not_le.mp h)), not_le.mp h⟩
theorem min_eq_iff : min a b = c ↔ a = c ∧ a ≤ b ∨ b = c ∧ b ≤ a := by
  

Proof state:
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a b c d : α
⊢ min a b = c ↔ a = c ∧ a ≤ b ∨ b = c ∧ b ≤ a

Next tactic:
constructor
theorem min_eq_iff : min a b = c ↔ a = c ∧ a ≤ b ∨ b = c ∧ b ≤ a := by
  constructor
  · 

Proof state:
case mp
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a b c d : α
⊢ min a b = c → a = c ∧ a ≤ b ∨ b = c ∧ b ≤ a

Next tactic:
intro h
theorem min_eq_iff : min a b = c ↔ a = c ∧ a ≤ b ∨ b = c ∧ b ≤ a := by
  constructor
  · intro h
    

Proof state:
case mp
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a b c d : α
h : min a b = c
⊢ a = c ∧ a ≤ b ∨ b = c ∧ b ≤ a

Next tactic:
refine' Or.imp (fun h' => _) (fun h' => _) (le_total a b)
theorem min_eq_iff : min a b = c ↔ a = c ∧ a ≤ b ∨ b = c ∧ b ≤ a := by
  constructor
  · intro h
    refine' Or.imp (fun h' => _) (fun h' => _) (le_total a b) <;> 

Proof state:
case mp.refine'_1
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a b c d : α
h : min a b = c
h' : a ≤ b
⊢ a = c ∧ a ≤ b

Next tactic:
exact ⟨by simpa [h'] using h, h'⟩
theorem min_eq_iff : min a b = c ↔ a = c ∧ a ≤ b ∨ b = c ∧ b ≤ a := by
  constructor
  · intro h
    refine' Or.imp (fun h' => _) (fun h' => _) (le_total a b) <;> exact ⟨by 

Proof state:
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a b c d : α
h : min a b = c
h' : a ≤ b
⊢ a = c

Next tactic:
simpa [h'] using h
theorem min_eq_iff : min a b = c ↔ a = c ∧ a ≤ b ∨ b = c ∧ b ≤ a := by
  constructor
  · intro h
    refine' Or.imp (fun h' => _) (fun h' => _) (le_total a b) <;> 

Proof state:
case mp.refine'_2
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a b c d : α
h : min a b = c
h' : b ≤ a
⊢ b = c ∧ b ≤ a

Next tactic:
exact ⟨by simpa [h'] using h, h'⟩
theorem min_eq_iff : min a b = c ↔ a = c ∧ a ≤ b ∨ b = c ∧ b ≤ a := by
  constructor
  · intro h
    refine' Or.imp (fun h' => _) (fun h' => _) (le_total a b) <;> exact ⟨by 

Proof state:
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a b c d : α
h : min a b = c
h' : b ≤ a
⊢ b = c

Next tactic:
simpa [h'] using h
theorem min_eq_iff : min a b = c ↔ a = c ∧ a ≤ b ∨ b = c ∧ b ≤ a := by
  constructor
  · intro h
    refine' Or.imp (fun h' => _) (fun h' => _) (le_total a b) <;> exact ⟨by simpa [h'] using h, h'⟩
  · 

Proof state:
case mpr
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a b c d : α
⊢ a = c ∧ a ≤ b ∨ b = c ∧ b ≤ a → min a b = c

Next tactic:
rintro (⟨rfl, h⟩ | ⟨rfl, h⟩)
theorem min_eq_iff : min a b = c ↔ a = c ∧ a ≤ b ∨ b = c ∧ b ≤ a := by
  constructor
  · intro h
    refine' Or.imp (fun h' => _) (fun h' => _) (le_total a b) <;> exact ⟨by simpa [h'] using h, h'⟩
  · rintro (⟨rfl, h⟩ | ⟨rfl, h⟩) <;> 

Proof state:
case mpr.inl.intro
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a b d : α
h : a ≤ b
⊢ min a b = a

Next tactic:
simp [h]
theorem min_eq_iff : min a b = c ↔ a = c ∧ a ≤ b ∨ b = c ∧ b ≤ a := by
  constructor
  · intro h
    refine' Or.imp (fun h' => _) (fun h' => _) (le_total a b) <;> exact ⟨by simpa [h'] using h, h'⟩
  · rintro (⟨rfl, h⟩ | ⟨rfl, h⟩) <;> 

Proof state:
case mpr.inr.intro
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a b d : α
h : b ≤ a
⊢ min a b = b

Next tactic:
simp [h]
theorem min_lt_min_left_iff : min a c < min b c ↔ a < b ∧ a < c := by
  

Proof state:
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a b c d : α
⊢ min a c < min b c ↔ a < b ∧ a < c

Next tactic:
simp_rw [lt_min_iff, min_lt_iff, or_iff_left (lt_irrefl _)]
theorem min_lt_min_left_iff : min a c < min b c ↔ a < b ∧ a < c := by
  simp_rw [lt_min_iff, min_lt_iff, or_iff_left (lt_irrefl _)]
  

Proof state:
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a b c d : α
⊢ (a < b ∨ c < b) ∧ a < c ↔ a < b ∧ a < c

Next tactic:
exact and_congr_left fun h => or_iff_left_of_imp h.trans
theorem min_lt_min_right_iff : min a b < min a c ↔ b < c ∧ b < a := by
  

Proof state:
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a b c d : α
⊢ min a b < min a c ↔ b < c ∧ b < a

Next tactic:
simp_rw [min_comm a, min_lt_min_left_iff]
/-- An instance asserting that `max a a = a` -/
instance max_idem : IsIdempotent α max where
  idempotent := by 

Proof state:
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a b c d : α
⊢ ∀ (a : α), max a a = a

Next tactic:
simp
/-- An instance asserting that `min a a = a` -/
instance min_idem : IsIdempotent α min where
  idempotent := by 

Proof state:
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a b c d : α
⊢ ∀ (a : α), min a a = a

Next tactic:
simp
theorem MonotoneOn.map_max (hf : MonotoneOn f s) (ha : a ∈ s) (hb : b ∈ s) : f (max a b) =
    max (f a) (f b) := by
  

Proof state:
α : Type u
β : Type v
inst✝¹ : LinearOrder α
inst✝ : LinearOrder β
f : α → β
s : Set α
a b c d : α
hf : MonotoneOn f s
ha : a ∈ s
hb : b ∈ s
⊢ f (max a b) = max (f a) (f b)

Next tactic:
rcases le_total a b with h | h