import .lattice
universes u
variables {α β : Type u}

section
variables [preorder α] [preorder β]
/-- A Galois connection is a pair of functions `l` and `u` satisfying
  `l a ≤ b ↔ a ≤ u b`. They are closely connected to adjoint functors
  in category theory. -/
def galois_connection
  (l : α → β) (u : β → α) := ∀ a b, l a ≤ b ↔ a ≤ u b
structure galois_insertion (l : α → β) (u : β → α)  :=
--(choice : Πa:α, u (l a) ≤ a → β)
(gc : galois_connection l u)
(le_l_u : ∀ b:β, b ≤ l(u b))
--(choice_eq : ∀ a h, choice a h = l a)
end

variables [partial_order α] [partial_order β]
variables {l : α → β} {u : β → α}
lemma monotone_l (gc : galois_connection l u) : monotone l := λ a b q, begin apply (gc _ _).mpr, transitivity, apply q, apply (gc _ _).mp, reflexivity end
lemma monotone_u (gc : galois_connection l u) : monotone u := λ a b q, begin apply (gc _ _).mp, transitivity, apply (gc _ _).mpr, reflexivity, apply q end

def Meet_of_gi (gi : galois_insertion l u) [ms : Meet_semilattice α] : Meet_semilattice β :=
{ Meet := λ B, l (⨅₀ (set.image u B))
, π := λ B b bB, (gi.gc _ _).mpr $ Meet_semilattice.π _ _ $ ⟨b, bB, rfl⟩
, u_Meet := λ B b h, (gi.le_l_u _) ◾ (monotone_l gi.gc $ Meet_semilattice.u_Meet _ _ $ λ a ⟨g,h₁,h₂⟩, h₂ ▸ monotone_u gi.gc (h _ h₁))
}

def meet_of_gi (gi : galois_insertion l u) [ms : meet_semilattice α] : meet_semilattice β :=
{ meet := λ b₁ b₂, l (u b₁ ⊓ u b₂)
, π₁ := λ b₁ b₂, (gi.gc _ _).mpr $ meet_semilattice.π₁ _ _
, π₂ := λ b₁ b₂, (gi.gc _ _).mpr $ meet_semilattice.π₂ _ _
, u_meet := λ b b₁ b₂ h₁ h₂, (gi.le_l_u _) ◾ (monotone_l gi.gc $ meet_semilattice.u_meet _ _ _ (monotone_u gi.gc h₁) (monotone_u gi.gc h₂))
}

def join_of_gi (gi :galois_insertion l u) [js : join_semilattice α] : join_semilattice β :=
{ join := λ b₁ b₂, l (u b₁ ⊔ u b₂)
, ι₁ := λ b₁ b₂, (gi.le_l_u _) ◾ (monotone_l gi.gc $ join_semilattice.ι₁ _ _)
, ι₂ := λ b₁ b₂, (gi.le_l_u _) ◾ (monotone_l gi.gc $ join_semilattice.ι₂ _ _)
, u_join := λ b b₁ b₂ h₁ h₂, (gi.gc _ _ ).mpr $ join_semilattice.u_join _ _ _ (monotone_u gi.gc h₁) (monotone_u gi.gc h₂)
}

def Join_of_gi (gi : galois_insertion l u) [js : Join_semilattice α] : Join_semilattice β :=
{ Join := λ B, l (⨆₀ (set.image u B))
, ι := λ B b bB, (gi.le_l_u _) ◾ (monotone_l gi.gc $ Join_semilattice.ι _ _ ⟨_,bB,rfl⟩)
, u_Join := λ B b h, (gi.gc _ _).mpr $ Join_semilattice.u_Join _ _ $ λ b' ⟨a,aA,p⟩, p ▸ (monotone_u gi.gc $ h _ aA)
}

def initial_of_gi (gi : galois_insertion l u) [has_initial α] : has_initial β :=
{ bot := l (⊥)
, bot_le := λ b, (gi.gc _ _).mpr (has_initial.bot_le _)
}

def terminal_of_gi (gi : galois_insertion l u) [has_terminal α] : has_terminal β :=
{ top := l (⊤)
, le_top := λ b, (gi.le_l_u _) ◾ (monotone_l gi.gc $ has_terminal.le_top _)
}

def complete_lattice_of_gi (gi : galois_insertion l u) [complete_lattice α] : complete_lattice β :=
{ ..(Meet_of_gi gi)
, ..(Join_of_gi gi)
, ..(meet_of_gi gi)
, ..(join_of_gi gi)
, ..(initial_of_gi gi)
, ..(terminal_of_gi gi)
}


/-
Copyright (c) 2019 Yury Kudryashov. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Yury Kudryashov

! This file was ported from Lean 3 source module topology.local_extr
! leanprover-community/mathlib commit e46da4e335b8671848ac711ccb34b42538c0d800
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.Order.Filter.Extr
import Mathbin.Topology.ContinuousOn

/-!
# Local extrema of functions on topological spaces

> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
> Any changes to this file require a corresponding PR to mathlib4.

## Main definitions

This file defines special versions of `is_*_filter f a l`, `*=min/max/extr`,
from `order/filter/extr` for two kinds of filters: `nhds_within` and `nhds`.
These versions are called `is_local_*_on` and `is_local_*`, respectively.

## Main statements

Many lemmas in this file restate those from `order/filter/extr`, and you can find
a detailed documentation there. These convenience lemmas are provided only to make the dot notation
return propositions of expected types, not just `is_*_filter`.

Here is the list of statements specific to these two types of filters:

* `is_local_*.on`, `is_local_*_on.on_subset`: restrict to a subset;
* `is_local_*_on.inter` : intersect the set with another one;
* `is_*_on.localize` : a global extremum is a local extremum too.
* `is_[local_]*_on.is_local_*` : if we have `is_local_*_on f s a` and `s ∈ 𝓝 a`,
  then we have `is_local_* f a`.

-/

universe u v w x

variable {α : Type u} {β : Type v} {γ : Type w} {δ : Type x} [TopologicalSpace α]

open Set Filter

open Topology Filter

section Preorder

variable [Preorder β] [Preorder γ] (f : α → β) (s : Set α) (a : α)

#print IsLocalMinOn /-
/-- `is_local_min_on f s a` means that `f a ≤ f x` for all `x ∈ s` in some neighborhood of `a`. -/
def IsLocalMinOn :=
  IsMinFilter f (𝓝[s] a) a
#align is_local_min_on IsLocalMinOn
-/

#print IsLocalMaxOn /-
/-- `is_local_max_on f s a` means that `f x ≤ f a` for all `x ∈ s` in some neighborhood of `a`. -/
def IsLocalMaxOn :=
  IsMaxFilter f (𝓝[s] a) a
#align is_local_max_on IsLocalMaxOn
-/

#print IsLocalExtrOn /-
/-- `is_local_extr_on f s a` means `is_local_min_on f s a ∨ is_local_max_on f s a`. -/
def IsLocalExtrOn :=
  IsExtrFilter f (𝓝[s] a) a
#align is_local_extr_on IsLocalExtrOn
-/

#print IsLocalMin /-
/-- `is_local_min f a` means that `f a ≤ f x` for all `x` in some neighborhood of `a`. -/
def IsLocalMin :=
  IsMinFilter f (𝓝 a) a
#align is_local_min IsLocalMin
-/

#print IsLocalMax /-
/-- `is_local_max f a` means that `f x ≤ f a` for all `x ∈ s` in some neighborhood of `a`. -/
def IsLocalMax :=
  IsMaxFilter f (𝓝 a) a
#align is_local_max IsLocalMax
-/

#print IsLocalExtr /-
/-- `is_local_extr_on f s a` means `is_local_min_on f s a ∨ is_local_max_on f s a`. -/
def IsLocalExtr :=
  IsExtrFilter f (𝓝 a) a
#align is_local_extr IsLocalExtr
-/

variable {f s a}

#print IsLocalExtrOn.elim /-
theorem IsLocalExtrOn.elim {p : Prop} :
    IsLocalExtrOn f s a → (IsLocalMinOn f s a → p) → (IsLocalMaxOn f s a → p) → p :=
  Or.elim
#align is_local_extr_on.elim IsLocalExtrOn.elim
-/

#print IsLocalExtr.elim /-
theorem IsLocalExtr.elim {p : Prop} :
    IsLocalExtr f a → (IsLocalMin f a → p) → (IsLocalMax f a → p) → p :=
  Or.elim
#align is_local_extr.elim IsLocalExtr.elim
-/

/-! ### Restriction to (sub)sets -/

#print IsLocalMin.on /-
theorem IsLocalMin.on (h : IsLocalMin f a) (s) : IsLocalMinOn f s a :=
  h.filter_inf _
#align is_local_min.on IsLocalMin.on
-/

#print IsLocalMax.on /-
theorem IsLocalMax.on (h : IsLocalMax f a) (s) : IsLocalMaxOn f s a :=
  h.filter_inf _
#align is_local_max.on IsLocalMax.on
-/

#print IsLocalExtr.on /-
theorem IsLocalExtr.on (h : IsLocalExtr f a) (s) : IsLocalExtrOn f s a :=
  h.filter_inf _
#align is_local_extr.on IsLocalExtr.on
-/

#print IsLocalMinOn.on_subset /-
theorem IsLocalMinOn.on_subset {t : Set α} (hf : IsLocalMinOn f t a) (h : s ⊆ t) :
    IsLocalMinOn f s a :=
  hf.filter_mono <| nhdsWithin_mono a h
#align is_local_min_on.on_subset IsLocalMinOn.on_subset
-/

#print IsLocalMaxOn.on_subset /-
theorem IsLocalMaxOn.on_subset {t : Set α} (hf : IsLocalMaxOn f t a) (h : s ⊆ t) :
    IsLocalMaxOn f s a :=
  hf.filter_mono <| nhdsWithin_mono a h
#align is_local_max_on.on_subset IsLocalMaxOn.on_subset
-/

#print IsLocalExtrOn.on_subset /-
theorem IsLocalExtrOn.on_subset {t : Set α} (hf : IsLocalExtrOn f t a) (h : s ⊆ t) :
    IsLocalExtrOn f s a :=
  hf.filter_mono <| nhdsWithin_mono a h
#align is_local_extr_on.on_subset IsLocalExtrOn.on_subset
-/

/- warning: is_local_min_on.inter -> IsLocalMinOn.inter is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u2} β] {f : α -> β} {s : Set.{u1} α} {a : α}, (IsLocalMinOn.{u1, u2} α β _inst_1 _inst_2 f s a) -> (forall (t : Set.{u1} α), IsLocalMinOn.{u1, u2} α β _inst_1 _inst_2 f (Inter.inter.{u1} (Set.{u1} α) (Set.hasInter.{u1} α) s t) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u2} β] {f : α -> β} {s : Set.{u1} α} {a : α}, (IsLocalMinOn.{u1, u2} α β _inst_1 _inst_2 f s a) -> (forall (t : Set.{u1} α), IsLocalMinOn.{u1, u2} α β _inst_1 _inst_2 f (Inter.inter.{u1} (Set.{u1} α) (Set.instInterSet.{u1} α) s t) a)
Case conversion may be inaccurate. Consider using '#align is_local_min_on.inter IsLocalMinOn.interₓ'. -/
theorem IsLocalMinOn.inter (hf : IsLocalMinOn f s a) (t) : IsLocalMinOn f (s ∩ t) a :=
  hf.on_subset (inter_subset_left s t)
#align is_local_min_on.inter IsLocalMinOn.inter

/- warning: is_local_max_on.inter -> IsLocalMaxOn.inter is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u2} β] {f : α -> β} {s : Set.{u1} α} {a : α}, (IsLocalMaxOn.{u1, u2} α β _inst_1 _inst_2 f s a) -> (forall (t : Set.{u1} α), IsLocalMaxOn.{u1, u2} α β _inst_1 _inst_2 f (Inter.inter.{u1} (Set.{u1} α) (Set.hasInter.{u1} α) s t) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u2} β] {f : α -> β} {s : Set.{u1} α} {a : α}, (IsLocalMaxOn.{u1, u2} α β _inst_1 _inst_2 f s a) -> (forall (t : Set.{u1} α), IsLocalMaxOn.{u1, u2} α β _inst_1 _inst_2 f (Inter.inter.{u1} (Set.{u1} α) (Set.instInterSet.{u1} α) s t) a)
Case conversion may be inaccurate. Consider using '#align is_local_max_on.inter IsLocalMaxOn.interₓ'. -/
theorem IsLocalMaxOn.inter (hf : IsLocalMaxOn f s a) (t) : IsLocalMaxOn f (s ∩ t) a :=
  hf.on_subset (inter_subset_left s t)
#align is_local_max_on.inter IsLocalMaxOn.inter

/- warning: is_local_extr_on.inter -> IsLocalExtrOn.inter is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u2} β] {f : α -> β} {s : Set.{u1} α} {a : α}, (IsLocalExtrOn.{u1, u2} α β _inst_1 _inst_2 f s a) -> (forall (t : Set.{u1} α), IsLocalExtrOn.{u1, u2} α β _inst_1 _inst_2 f (Inter.inter.{u1} (Set.{u1} α) (Set.hasInter.{u1} α) s t) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u2} β] {f : α -> β} {s : Set.{u1} α} {a : α}, (IsLocalExtrOn.{u1, u2} α β _inst_1 _inst_2 f s a) -> (forall (t : Set.{u1} α), IsLocalExtrOn.{u1, u2} α β _inst_1 _inst_2 f (Inter.inter.{u1} (Set.{u1} α) (Set.instInterSet.{u1} α) s t) a)
Case conversion may be inaccurate. Consider using '#align is_local_extr_on.inter IsLocalExtrOn.interₓ'. -/
theorem IsLocalExtrOn.inter (hf : IsLocalExtrOn f s a) (t) : IsLocalExtrOn f (s ∩ t) a :=
  hf.on_subset (inter_subset_left s t)
#align is_local_extr_on.inter IsLocalExtrOn.inter

#print IsMinOn.localize /-
theorem IsMinOn.localize (hf : IsMinOn f s a) : IsLocalMinOn f s a :=
  hf.filter_mono <| inf_le_right
#align is_min_on.localize IsMinOn.localize
-/

#print IsMaxOn.localize /-
theorem IsMaxOn.localize (hf : IsMaxOn f s a) : IsLocalMaxOn f s a :=
  hf.filter_mono <| inf_le_right
#align is_max_on.localize IsMaxOn.localize
-/

#print IsExtrOn.localize /-
theorem IsExtrOn.localize (hf : IsExtrOn f s a) : IsLocalExtrOn f s a :=
  hf.filter_mono <| inf_le_right
#align is_extr_on.localize IsExtrOn.localize
-/

#print IsLocalMinOn.isLocalMin /-
theorem IsLocalMinOn.isLocalMin (hf : IsLocalMinOn f s a) (hs : s ∈ 𝓝 a) : IsLocalMin f a :=
  have : 𝓝 a ≤ 𝓟 s := le_principal_iff.2 hs
  hf.filter_mono <| le_inf le_rfl this
#align is_local_min_on.is_local_min IsLocalMinOn.isLocalMin
-/

#print IsLocalMaxOn.isLocalMax /-
theorem IsLocalMaxOn.isLocalMax (hf : IsLocalMaxOn f s a) (hs : s ∈ 𝓝 a) : IsLocalMax f a :=
  have : 𝓝 a ≤ 𝓟 s := le_principal_iff.2 hs
  hf.filter_mono <| le_inf le_rfl this
#align is_local_max_on.is_local_max IsLocalMaxOn.isLocalMax
-/

#print IsLocalExtrOn.isLocalExtr /-
theorem IsLocalExtrOn.isLocalExtr (hf : IsLocalExtrOn f s a) (hs : s ∈ 𝓝 a) : IsLocalExtr f a :=
  hf.elim (fun hf => (hf.IsLocalMin hs).isExtr) fun hf => (hf.IsLocalMax hs).isExtr
#align is_local_extr_on.is_local_extr IsLocalExtrOn.isLocalExtr
-/

#print IsMinOn.isLocalMin /-
theorem IsMinOn.isLocalMin (hf : IsMinOn f s a) (hs : s ∈ 𝓝 a) : IsLocalMin f a :=
  hf.localize.IsLocalMin hs
#align is_min_on.is_local_min IsMinOn.isLocalMin
-/

#print IsMaxOn.isLocalMax /-
theorem IsMaxOn.isLocalMax (hf : IsMaxOn f s a) (hs : s ∈ 𝓝 a) : IsLocalMax f a :=
  hf.localize.IsLocalMax hs
#align is_max_on.is_local_max IsMaxOn.isLocalMax
-/

#print IsExtrOn.isLocalExtr /-
theorem IsExtrOn.isLocalExtr (hf : IsExtrOn f s a) (hs : s ∈ 𝓝 a) : IsLocalExtr f a :=
  hf.localize.IsLocalExtr hs
#align is_extr_on.is_local_extr IsExtrOn.isLocalExtr
-/

/- warning: is_local_min_on.not_nhds_le_map -> IsLocalMinOn.not_nhds_le_map is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u2} β] {f : α -> β} {s : Set.{u1} α} {a : α} [_inst_4 : TopologicalSpace.{u2} β], (IsLocalMinOn.{u1, u2} α β _inst_1 _inst_2 f s a) -> (forall [_inst_5 : Filter.NeBot.{u2} β (nhdsWithin.{u2} β _inst_4 (f a) (Set.Iio.{u2} β _inst_2 (f a)))], Not (LE.le.{u2} (Filter.{u2} β) (Preorder.toLE.{u2} (Filter.{u2} β) (PartialOrder.toPreorder.{u2} (Filter.{u2} β) (Filter.partialOrder.{u2} β))) (nhds.{u2} β _inst_4 (f a)) (Filter.map.{u1, u2} α β f (nhdsWithin.{u1} α _inst_1 a s))))
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u2} β] {f : α -> β} {s : Set.{u1} α} {a : α} [_inst_4 : TopologicalSpace.{u2} β], (IsLocalMinOn.{u1, u2} α β _inst_1 _inst_2 f s a) -> (forall [_inst_5 : Filter.NeBot.{u2} β (nhdsWithin.{u2} β _inst_4 (f a) (Set.Iio.{u2} β _inst_2 (f a)))], Not (LE.le.{u2} (Filter.{u2} β) (Preorder.toLE.{u2} (Filter.{u2} β) (PartialOrder.toPreorder.{u2} (Filter.{u2} β) (Filter.instPartialOrderFilter.{u2} β))) (nhds.{u2} β _inst_4 (f a)) (Filter.map.{u1, u2} α β f (nhdsWithin.{u1} α _inst_1 a s))))
Case conversion may be inaccurate. Consider using '#align is_local_min_on.not_nhds_le_map IsLocalMinOn.not_nhds_le_mapₓ'. -/
theorem IsLocalMinOn.not_nhds_le_map [TopologicalSpace β] (hf : IsLocalMinOn f s a)
    [NeBot (𝓝[<] f a)] : ¬𝓝 (f a) ≤ map f (𝓝[s] a) := fun hle =>
  have : ∀ᶠ y in 𝓝[<] f a, f a ≤ y := (eventually_map.2 hf).filter_mono (inf_le_left.trans hle)
  let ⟨y, hy⟩ := (this.And self_mem_nhdsWithin).exists
  hy.1.not_lt hy.2
#align is_local_min_on.not_nhds_le_map IsLocalMinOn.not_nhds_le_map

/- warning: is_local_max_on.not_nhds_le_map -> IsLocalMaxOn.not_nhds_le_map is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u2} β] {f : α -> β} {s : Set.{u1} α} {a : α} [_inst_4 : TopologicalSpace.{u2} β], (IsLocalMaxOn.{u1, u2} α β _inst_1 _inst_2 f s a) -> (forall [_inst_5 : Filter.NeBot.{u2} β (nhdsWithin.{u2} β _inst_4 (f a) (Set.Ioi.{u2} β _inst_2 (f a)))], Not (LE.le.{u2} (Filter.{u2} β) (Preorder.toLE.{u2} (Filter.{u2} β) (PartialOrder.toPreorder.{u2} (Filter.{u2} β) (Filter.partialOrder.{u2} β))) (nhds.{u2} β _inst_4 (f a)) (Filter.map.{u1, u2} α β f (nhdsWithin.{u1} α _inst_1 a s))))
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u2} β] {f : α -> β} {s : Set.{u1} α} {a : α} [_inst_4 : TopologicalSpace.{u2} β], (IsLocalMaxOn.{u1, u2} α β _inst_1 _inst_2 f s a) -> (forall [_inst_5 : Filter.NeBot.{u2} β (nhdsWithin.{u2} β _inst_4 (f a) (Set.Ioi.{u2} β _inst_2 (f a)))], Not (LE.le.{u2} (Filter.{u2} β) (Preorder.toLE.{u2} (Filter.{u2} β) (PartialOrder.toPreorder.{u2} (Filter.{u2} β) (Filter.instPartialOrderFilter.{u2} β))) (nhds.{u2} β _inst_4 (f a)) (Filter.map.{u1, u2} α β f (nhdsWithin.{u1} α _inst_1 a s))))
Case conversion may be inaccurate. Consider using '#align is_local_max_on.not_nhds_le_map IsLocalMaxOn.not_nhds_le_mapₓ'. -/
theorem IsLocalMaxOn.not_nhds_le_map [TopologicalSpace β] (hf : IsLocalMaxOn f s a)
    [NeBot (𝓝[>] f a)] : ¬𝓝 (f a) ≤ map f (𝓝[s] a) :=
  @IsLocalMinOn.not_nhds_le_map α βᵒᵈ _ _ _ _ _ ‹_› hf ‹_›
#align is_local_max_on.not_nhds_le_map IsLocalMaxOn.not_nhds_le_map

/- warning: is_local_extr_on.not_nhds_le_map -> IsLocalExtrOn.not_nhds_le_map is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u2} β] {f : α -> β} {s : Set.{u1} α} {a : α} [_inst_4 : TopologicalSpace.{u2} β], (IsLocalExtrOn.{u1, u2} α β _inst_1 _inst_2 f s a) -> (forall [_inst_5 : Filter.NeBot.{u2} β (nhdsWithin.{u2} β _inst_4 (f a) (Set.Iio.{u2} β _inst_2 (f a)))] [_inst_6 : Filter.NeBot.{u2} β (nhdsWithin.{u2} β _inst_4 (f a) (Set.Ioi.{u2} β _inst_2 (f a)))], Not (LE.le.{u2} (Filter.{u2} β) (Preorder.toLE.{u2} (Filter.{u2} β) (PartialOrder.toPreorder.{u2} (Filter.{u2} β) (Filter.partialOrder.{u2} β))) (nhds.{u2} β _inst_4 (f a)) (Filter.map.{u1, u2} α β f (nhdsWithin.{u1} α _inst_1 a s))))
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u2} β] {f : α -> β} {s : Set.{u1} α} {a : α} [_inst_4 : TopologicalSpace.{u2} β], (IsLocalExtrOn.{u1, u2} α β _inst_1 _inst_2 f s a) -> (forall [_inst_5 : Filter.NeBot.{u2} β (nhdsWithin.{u2} β _inst_4 (f a) (Set.Iio.{u2} β _inst_2 (f a)))] [_inst_6 : Filter.NeBot.{u2} β (nhdsWithin.{u2} β _inst_4 (f a) (Set.Ioi.{u2} β _inst_2 (f a)))], Not (LE.le.{u2} (Filter.{u2} β) (Preorder.toLE.{u2} (Filter.{u2} β) (PartialOrder.toPreorder.{u2} (Filter.{u2} β) (Filter.instPartialOrderFilter.{u2} β))) (nhds.{u2} β _inst_4 (f a)) (Filter.map.{u1, u2} α β f (nhdsWithin.{u1} α _inst_1 a s))))
Case conversion may be inaccurate. Consider using '#align is_local_extr_on.not_nhds_le_map IsLocalExtrOn.not_nhds_le_mapₓ'. -/
theorem IsLocalExtrOn.not_nhds_le_map [TopologicalSpace β] (hf : IsLocalExtrOn f s a)
    [NeBot (𝓝[<] f a)] [NeBot (𝓝[>] f a)] : ¬𝓝 (f a) ≤ map f (𝓝[s] a) :=
  hf.elim (fun h => h.not_nhds_le_map) fun h => h.not_nhds_le_map
#align is_local_extr_on.not_nhds_le_map IsLocalExtrOn.not_nhds_le_map

/-! ### Constant -/

#print isLocalMinOn_const /-
theorem isLocalMinOn_const {b : β} : IsLocalMinOn (fun _ => b) s a :=
  isMinFilter_const
#align is_local_min_on_const isLocalMinOn_const
-/

#print isLocalMaxOn_const /-
theorem isLocalMaxOn_const {b : β} : IsLocalMaxOn (fun _ => b) s a :=
  isMaxFilter_const
#align is_local_max_on_const isLocalMaxOn_const
-/

#print isLocalExtrOn_const /-
theorem isLocalExtrOn_const {b : β} : IsLocalExtrOn (fun _ => b) s a :=
  isExtrFilter_const
#align is_local_extr_on_const isLocalExtrOn_const
-/

#print isLocalMin_const /-
theorem isLocalMin_const {b : β} : IsLocalMin (fun _ => b) a :=
  isMinFilter_const
#align is_local_min_const isLocalMin_const
-/

#print isLocalMax_const /-
theorem isLocalMax_const {b : β} : IsLocalMax (fun _ => b) a :=
  isMaxFilter_const
#align is_local_max_const isLocalMax_const
-/

#print isLocalExtr_const /-
theorem isLocalExtr_const {b : β} : IsLocalExtr (fun _ => b) a :=
  isExtrFilter_const
#align is_local_extr_const isLocalExtr_const
-/

/-! ### Composition with (anti)monotone functions -/

#print IsLocalMin.comp_mono /-
theorem IsLocalMin.comp_mono (hf : IsLocalMin f a) {g : β → γ} (hg : Monotone g) :
    IsLocalMin (g ∘ f) a :=
  hf.comp_mono hg
#align is_local_min.comp_mono IsLocalMin.comp_mono
-/

#print IsLocalMax.comp_mono /-
theorem IsLocalMax.comp_mono (hf : IsLocalMax f a) {g : β → γ} (hg : Monotone g) :
    IsLocalMax (g ∘ f) a :=
  hf.comp_mono hg
#align is_local_max.comp_mono IsLocalMax.comp_mono
-/

#print IsLocalExtr.comp_mono /-
theorem IsLocalExtr.comp_mono (hf : IsLocalExtr f a) {g : β → γ} (hg : Monotone g) :
    IsLocalExtr (g ∘ f) a :=
  hf.comp_mono hg
#align is_local_extr.comp_mono IsLocalExtr.comp_mono
-/

#print IsLocalMin.comp_antitone /-
theorem IsLocalMin.comp_antitone (hf : IsLocalMin f a) {g : β → γ} (hg : Antitone g) :
    IsLocalMax (g ∘ f) a :=
  hf.comp_antitone hg
#align is_local_min.comp_antitone IsLocalMin.comp_antitone
-/

#print IsLocalMax.comp_antitone /-
theorem IsLocalMax.comp_antitone (hf : IsLocalMax f a) {g : β → γ} (hg : Antitone g) :
    IsLocalMin (g ∘ f) a :=
  hf.comp_antitone hg
#align is_local_max.comp_antitone IsLocalMax.comp_antitone
-/

#print IsLocalExtr.comp_antitone /-
theorem IsLocalExtr.comp_antitone (hf : IsLocalExtr f a) {g : β → γ} (hg : Antitone g) :
    IsLocalExtr (g ∘ f) a :=
  hf.comp_antitone hg
#align is_local_extr.comp_antitone IsLocalExtr.comp_antitone
-/

#print IsLocalMinOn.comp_mono /-
theorem IsLocalMinOn.comp_mono (hf : IsLocalMinOn f s a) {g : β → γ} (hg : Monotone g) :
    IsLocalMinOn (g ∘ f) s a :=
  hf.comp_mono hg
#align is_local_min_on.comp_mono IsLocalMinOn.comp_mono
-/

#print IsLocalMaxOn.comp_mono /-
theorem IsLocalMaxOn.comp_mono (hf : IsLocalMaxOn f s a) {g : β → γ} (hg : Monotone g) :
    IsLocalMaxOn (g ∘ f) s a :=
  hf.comp_mono hg
#align is_local_max_on.comp_mono IsLocalMaxOn.comp_mono
-/

#print IsLocalExtrOn.comp_mono /-
theorem IsLocalExtrOn.comp_mono (hf : IsLocalExtrOn f s a) {g : β → γ} (hg : Monotone g) :
    IsLocalExtrOn (g ∘ f) s a :=
  hf.comp_mono hg
#align is_local_extr_on.comp_mono IsLocalExtrOn.comp_mono
-/

#print IsLocalMinOn.comp_antitone /-
theorem IsLocalMinOn.comp_antitone (hf : IsLocalMinOn f s a) {g : β → γ} (hg : Antitone g) :
    IsLocalMaxOn (g ∘ f) s a :=
  hf.comp_antitone hg
#align is_local_min_on.comp_antitone IsLocalMinOn.comp_antitone
-/

#print IsLocalMaxOn.comp_antitone /-
theorem IsLocalMaxOn.comp_antitone (hf : IsLocalMaxOn f s a) {g : β → γ} (hg : Antitone g) :
    IsLocalMinOn (g ∘ f) s a :=
  hf.comp_antitone hg
#align is_local_max_on.comp_antitone IsLocalMaxOn.comp_antitone
-/

#print IsLocalExtrOn.comp_antitone /-
theorem IsLocalExtrOn.comp_antitone (hf : IsLocalExtrOn f s a) {g : β → γ} (hg : Antitone g) :
    IsLocalExtrOn (g ∘ f) s a :=
  hf.comp_antitone hg
#align is_local_extr_on.comp_antitone IsLocalExtrOn.comp_antitone
-/

#print IsLocalMin.bicomp_mono /-
theorem IsLocalMin.bicomp_mono [Preorder δ] {op : β → γ → δ}
    (hop : ((· ≤ ·) ⇒ (· ≤ ·) ⇒ (· ≤ ·)) op op) (hf : IsLocalMin f a) {g : α → γ}
    (hg : IsLocalMin g a) : IsLocalMin (fun x => op (f x) (g x)) a :=
  hf.bicomp_mono hop hg
#align is_local_min.bicomp_mono IsLocalMin.bicomp_mono
-/

#print IsLocalMax.bicomp_mono /-
theorem IsLocalMax.bicomp_mono [Preorder δ] {op : β → γ → δ}
    (hop : ((· ≤ ·) ⇒ (· ≤ ·) ⇒ (· ≤ ·)) op op) (hf : IsLocalMax f a) {g : α → γ}
    (hg : IsLocalMax g a) : IsLocalMax (fun x => op (f x) (g x)) a :=
  hf.bicomp_mono hop hg
#align is_local_max.bicomp_mono IsLocalMax.bicomp_mono
-/

#print IsLocalMinOn.bicomp_mono /-
-- No `extr` version because we need `hf` and `hg` to be of the same kind
theorem IsLocalMinOn.bicomp_mono [Preorder δ] {op : β → γ → δ}
    (hop : ((· ≤ ·) ⇒ (· ≤ ·) ⇒ (· ≤ ·)) op op) (hf : IsLocalMinOn f s a) {g : α → γ}
    (hg : IsLocalMinOn g s a) : IsLocalMinOn (fun x => op (f x) (g x)) s a :=
  hf.bicomp_mono hop hg
#align is_local_min_on.bicomp_mono IsLocalMinOn.bicomp_mono
-/

#print IsLocalMaxOn.bicomp_mono /-
theorem IsLocalMaxOn.bicomp_mono [Preorder δ] {op : β → γ → δ}
    (hop : ((· ≤ ·) ⇒ (· ≤ ·) ⇒ (· ≤ ·)) op op) (hf : IsLocalMaxOn f s a) {g : α → γ}
    (hg : IsLocalMaxOn g s a) : IsLocalMaxOn (fun x => op (f x) (g x)) s a :=
  hf.bicomp_mono hop hg
#align is_local_max_on.bicomp_mono IsLocalMaxOn.bicomp_mono
-/

/-! ### Composition with `continuous_at` -/

#print IsLocalMin.comp_continuous /-
theorem IsLocalMin.comp_continuous [TopologicalSpace δ] {g : δ → α} {b : δ}
    (hf : IsLocalMin f (g b)) (hg : ContinuousAt g b) : IsLocalMin (f ∘ g) b :=
  hg hf
#align is_local_min.comp_continuous IsLocalMin.comp_continuous
-/

#print IsLocalMax.comp_continuous /-
theorem IsLocalMax.comp_continuous [TopologicalSpace δ] {g : δ → α} {b : δ}
    (hf : IsLocalMax f (g b)) (hg : ContinuousAt g b) : IsLocalMax (f ∘ g) b :=
  hg hf
#align is_local_max.comp_continuous IsLocalMax.comp_continuous
-/

#print IsLocalExtr.comp_continuous /-
theorem IsLocalExtr.comp_continuous [TopologicalSpace δ] {g : δ → α} {b : δ}
    (hf : IsLocalExtr f (g b)) (hg : ContinuousAt g b) : IsLocalExtr (f ∘ g) b :=
  hf.comp_tendsto hg
#align is_local_extr.comp_continuous IsLocalExtr.comp_continuous
-/

#print IsLocalMin.comp_continuousOn /-
theorem IsLocalMin.comp_continuousOn [TopologicalSpace δ] {s : Set δ} {g : δ → α} {b : δ}
    (hf : IsLocalMin f (g b)) (hg : ContinuousOn g s) (hb : b ∈ s) : IsLocalMinOn (f ∘ g) s b :=
  hf.comp_tendsto (hg b hb)
#align is_local_min.comp_continuous_on IsLocalMin.comp_continuousOn
-/

#print IsLocalMax.comp_continuousOn /-
theorem IsLocalMax.comp_continuousOn [TopologicalSpace δ] {s : Set δ} {g : δ → α} {b : δ}
    (hf : IsLocalMax f (g b)) (hg : ContinuousOn g s) (hb : b ∈ s) : IsLocalMaxOn (f ∘ g) s b :=
  hf.comp_tendsto (hg b hb)
#align is_local_max.comp_continuous_on IsLocalMax.comp_continuousOn
-/

#print IsLocalExtr.comp_continuousOn /-
theorem IsLocalExtr.comp_continuousOn [TopologicalSpace δ] {s : Set δ} (g : δ → α) {b : δ}
    (hf : IsLocalExtr f (g b)) (hg : ContinuousOn g s) (hb : b ∈ s) : IsLocalExtrOn (f ∘ g) s b :=
  hf.elim (fun hf => (hf.comp_continuousOn hg hb).isExtr) fun hf =>
    (IsLocalMax.comp_continuousOn hf hg hb).isExtr
#align is_local_extr.comp_continuous_on IsLocalExtr.comp_continuousOn
-/

#print IsLocalMinOn.comp_continuousOn /-
theorem IsLocalMinOn.comp_continuousOn [TopologicalSpace δ] {t : Set α} {s : Set δ} {g : δ → α}
    {b : δ} (hf : IsLocalMinOn f t (g b)) (hst : s ⊆ g ⁻¹' t) (hg : ContinuousOn g s) (hb : b ∈ s) :
    IsLocalMinOn (f ∘ g) s b :=
  hf.comp_tendsto
    (tendsto_nhdsWithin_mono_right (image_subset_iff.mpr hst)
      (ContinuousWithinAt.tendsto_nhdsWithin_image (hg b hb)))
#align is_local_min_on.comp_continuous_on IsLocalMinOn.comp_continuousOn
-/

#print IsLocalMaxOn.comp_continuousOn /-
theorem IsLocalMaxOn.comp_continuousOn [TopologicalSpace δ] {t : Set α} {s : Set δ} {g : δ → α}
    {b : δ} (hf : IsLocalMaxOn f t (g b)) (hst : s ⊆ g ⁻¹' t) (hg : ContinuousOn g s) (hb : b ∈ s) :
    IsLocalMaxOn (f ∘ g) s b :=
  hf.comp_tendsto
    (tendsto_nhdsWithin_mono_right (image_subset_iff.mpr hst)
      (ContinuousWithinAt.tendsto_nhdsWithin_image (hg b hb)))
#align is_local_max_on.comp_continuous_on IsLocalMaxOn.comp_continuousOn
-/

#print IsLocalExtrOn.comp_continuousOn /-
theorem IsLocalExtrOn.comp_continuousOn [TopologicalSpace δ] {t : Set α} {s : Set δ} (g : δ → α)
    {b : δ} (hf : IsLocalExtrOn f t (g b)) (hst : s ⊆ g ⁻¹' t) (hg : ContinuousOn g s)
    (hb : b ∈ s) : IsLocalExtrOn (f ∘ g) s b :=
  hf.elim (fun hf => (hf.comp_continuousOn hst hg hb).isExtr) fun hf =>
    (IsLocalMaxOn.comp_continuousOn hf hst hg hb).isExtr
#align is_local_extr_on.comp_continuous_on IsLocalExtrOn.comp_continuousOn
-/

end Preorder

/-! ### Pointwise addition -/

section OrderedAddCommMonoid

variable [OrderedAddCommMonoid β] {f g : α → β} {a : α} {s : Set α} {l : Filter α}

/- warning: is_local_min.add -> IsLocalMin.add is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommMonoid.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) g a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => HAdd.hAdd.{u2, u2, u2} β β β (instHAdd.{u2} β (AddZeroClass.toHasAdd.{u2} β (AddMonoid.toAddZeroClass.{u2} β (AddCommMonoid.toAddMonoid.{u2} β (OrderedAddCommMonoid.toAddCommMonoid.{u2} β _inst_2))))) (f x) (g x)) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommMonoid.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) g a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => HAdd.hAdd.{u2, u2, u2} β β β (instHAdd.{u2} β (AddZeroClass.toAdd.{u2} β (AddMonoid.toAddZeroClass.{u2} β (AddCommMonoid.toAddMonoid.{u2} β (OrderedAddCommMonoid.toAddCommMonoid.{u2} β _inst_2))))) (f x) (g x)) a)
Case conversion may be inaccurate. Consider using '#align is_local_min.add IsLocalMin.addₓ'. -/
theorem IsLocalMin.add (hf : IsLocalMin f a) (hg : IsLocalMin g a) :
    IsLocalMin (fun x => f x + g x) a :=
  hf.add hg
#align is_local_min.add IsLocalMin.add

/- warning: is_local_max.add -> IsLocalMax.add is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommMonoid.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) g a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => HAdd.hAdd.{u2, u2, u2} β β β (instHAdd.{u2} β (AddZeroClass.toHasAdd.{u2} β (AddMonoid.toAddZeroClass.{u2} β (AddCommMonoid.toAddMonoid.{u2} β (OrderedAddCommMonoid.toAddCommMonoid.{u2} β _inst_2))))) (f x) (g x)) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommMonoid.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) g a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => HAdd.hAdd.{u2, u2, u2} β β β (instHAdd.{u2} β (AddZeroClass.toAdd.{u2} β (AddMonoid.toAddZeroClass.{u2} β (AddCommMonoid.toAddMonoid.{u2} β (OrderedAddCommMonoid.toAddCommMonoid.{u2} β _inst_2))))) (f x) (g x)) a)
Case conversion may be inaccurate. Consider using '#align is_local_max.add IsLocalMax.addₓ'. -/
theorem IsLocalMax.add (hf : IsLocalMax f a) (hg : IsLocalMax g a) :
    IsLocalMax (fun x => f x + g x) a :=
  hf.add hg
#align is_local_max.add IsLocalMax.add

/- warning: is_local_min_on.add -> IsLocalMinOn.add is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommMonoid.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) g s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => HAdd.hAdd.{u2, u2, u2} β β β (instHAdd.{u2} β (AddZeroClass.toHasAdd.{u2} β (AddMonoid.toAddZeroClass.{u2} β (AddCommMonoid.toAddMonoid.{u2} β (OrderedAddCommMonoid.toAddCommMonoid.{u2} β _inst_2))))) (f x) (g x)) s a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommMonoid.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) g s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => HAdd.hAdd.{u2, u2, u2} β β β (instHAdd.{u2} β (AddZeroClass.toAdd.{u2} β (AddMonoid.toAddZeroClass.{u2} β (AddCommMonoid.toAddMonoid.{u2} β (OrderedAddCommMonoid.toAddCommMonoid.{u2} β _inst_2))))) (f x) (g x)) s a)
Case conversion may be inaccurate. Consider using '#align is_local_min_on.add IsLocalMinOn.addₓ'. -/
theorem IsLocalMinOn.add (hf : IsLocalMinOn f s a) (hg : IsLocalMinOn g s a) :
    IsLocalMinOn (fun x => f x + g x) s a :=
  hf.add hg
#align is_local_min_on.add IsLocalMinOn.add

/- warning: is_local_max_on.add -> IsLocalMaxOn.add is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommMonoid.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) g s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => HAdd.hAdd.{u2, u2, u2} β β β (instHAdd.{u2} β (AddZeroClass.toHasAdd.{u2} β (AddMonoid.toAddZeroClass.{u2} β (AddCommMonoid.toAddMonoid.{u2} β (OrderedAddCommMonoid.toAddCommMonoid.{u2} β _inst_2))))) (f x) (g x)) s a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommMonoid.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) g s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommMonoid.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => HAdd.hAdd.{u2, u2, u2} β β β (instHAdd.{u2} β (AddZeroClass.toAdd.{u2} β (AddMonoid.toAddZeroClass.{u2} β (AddCommMonoid.toAddMonoid.{u2} β (OrderedAddCommMonoid.toAddCommMonoid.{u2} β _inst_2))))) (f x) (g x)) s a)
Case conversion may be inaccurate. Consider using '#align is_local_max_on.add IsLocalMaxOn.addₓ'. -/
theorem IsLocalMaxOn.add (hf : IsLocalMaxOn f s a) (hg : IsLocalMaxOn g s a) :
    IsLocalMaxOn (fun x => f x + g x) s a :=
  hf.add hg
#align is_local_max_on.add IsLocalMaxOn.add

end OrderedAddCommMonoid

/-! ### Pointwise negation and subtraction -/

section OrderedAddCommGroup

variable [OrderedAddCommGroup β] {f g : α → β} {a : α} {s : Set α} {l : Filter α}

/- warning: is_local_min.neg -> IsLocalMin.neg is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {a : α}, (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Neg.neg.{u2} β (SubNegMonoid.toHasNeg.{u2} β (AddGroup.toSubNegMonoid.{u2} β (AddCommGroup.toAddGroup.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2)))) (f x)) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {a : α}, (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Neg.neg.{u2} β (NegZeroClass.toNeg.{u2} β (SubNegZeroMonoid.toNegZeroClass.{u2} β (SubtractionMonoid.toSubNegZeroMonoid.{u2} β (SubtractionCommMonoid.toSubtractionMonoid.{u2} β (AddCommGroup.toDivisionAddCommMonoid.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2)))))) (f x)) a)
Case conversion may be inaccurate. Consider using '#align is_local_min.neg IsLocalMin.negₓ'. -/
theorem IsLocalMin.neg (hf : IsLocalMin f a) : IsLocalMax (fun x => -f x) a :=
  hf.neg
#align is_local_min.neg IsLocalMin.neg

/- warning: is_local_max.neg -> IsLocalMax.neg is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {a : α}, (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Neg.neg.{u2} β (SubNegMonoid.toHasNeg.{u2} β (AddGroup.toSubNegMonoid.{u2} β (AddCommGroup.toAddGroup.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2)))) (f x)) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {a : α}, (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Neg.neg.{u2} β (NegZeroClass.toNeg.{u2} β (SubNegZeroMonoid.toNegZeroClass.{u2} β (SubtractionMonoid.toSubNegZeroMonoid.{u2} β (SubtractionCommMonoid.toSubtractionMonoid.{u2} β (AddCommGroup.toDivisionAddCommMonoid.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2)))))) (f x)) a)
Case conversion may be inaccurate. Consider using '#align is_local_max.neg IsLocalMax.negₓ'. -/
theorem IsLocalMax.neg (hf : IsLocalMax f a) : IsLocalMin (fun x => -f x) a :=
  hf.neg
#align is_local_max.neg IsLocalMax.neg

/- warning: is_local_extr.neg -> IsLocalExtr.neg is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {a : α}, (IsLocalExtr.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalExtr.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Neg.neg.{u2} β (SubNegMonoid.toHasNeg.{u2} β (AddGroup.toSubNegMonoid.{u2} β (AddCommGroup.toAddGroup.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2)))) (f x)) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {a : α}, (IsLocalExtr.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalExtr.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Neg.neg.{u2} β (NegZeroClass.toNeg.{u2} β (SubNegZeroMonoid.toNegZeroClass.{u2} β (SubtractionMonoid.toSubNegZeroMonoid.{u2} β (SubtractionCommMonoid.toSubtractionMonoid.{u2} β (AddCommGroup.toDivisionAddCommMonoid.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2)))))) (f x)) a)
Case conversion may be inaccurate. Consider using '#align is_local_extr.neg IsLocalExtr.negₓ'. -/
theorem IsLocalExtr.neg (hf : IsLocalExtr f a) : IsLocalExtr (fun x => -f x) a :=
  hf.neg
#align is_local_extr.neg IsLocalExtr.neg

/- warning: is_local_min_on.neg -> IsLocalMinOn.neg is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Neg.neg.{u2} β (SubNegMonoid.toHasNeg.{u2} β (AddGroup.toSubNegMonoid.{u2} β (AddCommGroup.toAddGroup.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2)))) (f x)) s a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Neg.neg.{u2} β (NegZeroClass.toNeg.{u2} β (SubNegZeroMonoid.toNegZeroClass.{u2} β (SubtractionMonoid.toSubNegZeroMonoid.{u2} β (SubtractionCommMonoid.toSubtractionMonoid.{u2} β (AddCommGroup.toDivisionAddCommMonoid.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2)))))) (f x)) s a)
Case conversion may be inaccurate. Consider using '#align is_local_min_on.neg IsLocalMinOn.negₓ'. -/
theorem IsLocalMinOn.neg (hf : IsLocalMinOn f s a) : IsLocalMaxOn (fun x => -f x) s a :=
  hf.neg
#align is_local_min_on.neg IsLocalMinOn.neg

/- warning: is_local_max_on.neg -> IsLocalMaxOn.neg is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Neg.neg.{u2} β (SubNegMonoid.toHasNeg.{u2} β (AddGroup.toSubNegMonoid.{u2} β (AddCommGroup.toAddGroup.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2)))) (f x)) s a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Neg.neg.{u2} β (NegZeroClass.toNeg.{u2} β (SubNegZeroMonoid.toNegZeroClass.{u2} β (SubtractionMonoid.toSubNegZeroMonoid.{u2} β (SubtractionCommMonoid.toSubtractionMonoid.{u2} β (AddCommGroup.toDivisionAddCommMonoid.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2)))))) (f x)) s a)
Case conversion may be inaccurate. Consider using '#align is_local_max_on.neg IsLocalMaxOn.negₓ'. -/
theorem IsLocalMaxOn.neg (hf : IsLocalMaxOn f s a) : IsLocalMinOn (fun x => -f x) s a :=
  hf.neg
#align is_local_max_on.neg IsLocalMaxOn.neg

/- warning: is_local_extr_on.neg -> IsLocalExtrOn.neg is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalExtrOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalExtrOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Neg.neg.{u2} β (SubNegMonoid.toHasNeg.{u2} β (AddGroup.toSubNegMonoid.{u2} β (AddCommGroup.toAddGroup.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2)))) (f x)) s a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalExtrOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalExtrOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Neg.neg.{u2} β (NegZeroClass.toNeg.{u2} β (SubNegZeroMonoid.toNegZeroClass.{u2} β (SubtractionMonoid.toSubNegZeroMonoid.{u2} β (SubtractionCommMonoid.toSubtractionMonoid.{u2} β (AddCommGroup.toDivisionAddCommMonoid.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2)))))) (f x)) s a)
Case conversion may be inaccurate. Consider using '#align is_local_extr_on.neg IsLocalExtrOn.negₓ'. -/
theorem IsLocalExtrOn.neg (hf : IsLocalExtrOn f s a) : IsLocalExtrOn (fun x => -f x) s a :=
  hf.neg
#align is_local_extr_on.neg IsLocalExtrOn.neg

/- warning: is_local_min.sub -> IsLocalMin.sub is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) g a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => HSub.hSub.{u2, u2, u2} β β β (instHSub.{u2} β (SubNegMonoid.toHasSub.{u2} β (AddGroup.toSubNegMonoid.{u2} β (AddCommGroup.toAddGroup.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2))))) (f x) (g x)) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) g a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => HSub.hSub.{u2, u2, u2} β β β (instHSub.{u2} β (SubNegMonoid.toSub.{u2} β (AddGroup.toSubNegMonoid.{u2} β (AddCommGroup.toAddGroup.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2))))) (f x) (g x)) a)
Case conversion may be inaccurate. Consider using '#align is_local_min.sub IsLocalMin.subₓ'. -/
theorem IsLocalMin.sub (hf : IsLocalMin f a) (hg : IsLocalMax g a) :
    IsLocalMin (fun x => f x - g x) a :=
  hf.sub hg
#align is_local_min.sub IsLocalMin.sub

/- warning: is_local_max.sub -> IsLocalMax.sub is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) g a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => HSub.hSub.{u2, u2, u2} β β β (instHSub.{u2} β (SubNegMonoid.toHasSub.{u2} β (AddGroup.toSubNegMonoid.{u2} β (AddCommGroup.toAddGroup.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2))))) (f x) (g x)) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) g a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => HSub.hSub.{u2, u2, u2} β β β (instHSub.{u2} β (SubNegMonoid.toSub.{u2} β (AddGroup.toSubNegMonoid.{u2} β (AddCommGroup.toAddGroup.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2))))) (f x) (g x)) a)
Case conversion may be inaccurate. Consider using '#align is_local_max.sub IsLocalMax.subₓ'. -/
theorem IsLocalMax.sub (hf : IsLocalMax f a) (hg : IsLocalMin g a) :
    IsLocalMax (fun x => f x - g x) a :=
  hf.sub hg
#align is_local_max.sub IsLocalMax.sub

/- warning: is_local_min_on.sub -> IsLocalMinOn.sub is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) g s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => HSub.hSub.{u2, u2, u2} β β β (instHSub.{u2} β (SubNegMonoid.toHasSub.{u2} β (AddGroup.toSubNegMonoid.{u2} β (AddCommGroup.toAddGroup.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2))))) (f x) (g x)) s a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) g s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => HSub.hSub.{u2, u2, u2} β β β (instHSub.{u2} β (SubNegMonoid.toSub.{u2} β (AddGroup.toSubNegMonoid.{u2} β (AddCommGroup.toAddGroup.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2))))) (f x) (g x)) s a)
Case conversion may be inaccurate. Consider using '#align is_local_min_on.sub IsLocalMinOn.subₓ'. -/
theorem IsLocalMinOn.sub (hf : IsLocalMinOn f s a) (hg : IsLocalMaxOn g s a) :
    IsLocalMinOn (fun x => f x - g x) s a :=
  hf.sub hg
#align is_local_min_on.sub IsLocalMinOn.sub

/- warning: is_local_max_on.sub -> IsLocalMaxOn.sub is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) g s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => HSub.hSub.{u2, u2, u2} β β β (instHSub.{u2} β (SubNegMonoid.toHasSub.{u2} β (AddGroup.toSubNegMonoid.{u2} β (AddCommGroup.toAddGroup.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2))))) (f x) (g x)) s a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : OrderedAddCommGroup.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) g s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (OrderedAddCommGroup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => HSub.hSub.{u2, u2, u2} β β β (instHSub.{u2} β (SubNegMonoid.toSub.{u2} β (AddGroup.toSubNegMonoid.{u2} β (AddCommGroup.toAddGroup.{u2} β (OrderedAddCommGroup.toAddCommGroup.{u2} β _inst_2))))) (f x) (g x)) s a)
Case conversion may be inaccurate. Consider using '#align is_local_max_on.sub IsLocalMaxOn.subₓ'. -/
theorem IsLocalMaxOn.sub (hf : IsLocalMaxOn f s a) (hg : IsLocalMinOn g s a) :
    IsLocalMaxOn (fun x => f x - g x) s a :=
  hf.sub hg
#align is_local_max_on.sub IsLocalMaxOn.sub

end OrderedAddCommGroup

/-! ### Pointwise `sup`/`inf` -/

section SemilatticeSup

variable [SemilatticeSup β] {f g : α → β} {a : α} {s : Set α} {l : Filter α}

/- warning: is_local_min.sup -> IsLocalMin.sup is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : SemilatticeSup.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) g a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Sup.sup.{u2} β (SemilatticeSup.toHasSup.{u2} β _inst_2) (f x) (g x)) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : SemilatticeSup.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) g a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Sup.sup.{u2} β (SemilatticeSup.toSup.{u2} β _inst_2) (f x) (g x)) a)
Case conversion may be inaccurate. Consider using '#align is_local_min.sup IsLocalMin.supₓ'. -/
theorem IsLocalMin.sup (hf : IsLocalMin f a) (hg : IsLocalMin g a) :
    IsLocalMin (fun x => f x ⊔ g x) a :=
  hf.sup hg
#align is_local_min.sup IsLocalMin.sup

/- warning: is_local_max.sup -> IsLocalMax.sup is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : SemilatticeSup.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) g a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Sup.sup.{u2} β (SemilatticeSup.toHasSup.{u2} β _inst_2) (f x) (g x)) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : SemilatticeSup.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) g a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Sup.sup.{u2} β (SemilatticeSup.toSup.{u2} β _inst_2) (f x) (g x)) a)
Case conversion may be inaccurate. Consider using '#align is_local_max.sup IsLocalMax.supₓ'. -/
theorem IsLocalMax.sup (hf : IsLocalMax f a) (hg : IsLocalMax g a) :
    IsLocalMax (fun x => f x ⊔ g x) a :=
  hf.sup hg
#align is_local_max.sup IsLocalMax.sup

/- warning: is_local_min_on.sup -> IsLocalMinOn.sup is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : SemilatticeSup.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) g s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Sup.sup.{u2} β (SemilatticeSup.toHasSup.{u2} β _inst_2) (f x) (g x)) s a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : SemilatticeSup.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) g s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Sup.sup.{u2} β (SemilatticeSup.toSup.{u2} β _inst_2) (f x) (g x)) s a)
Case conversion may be inaccurate. Consider using '#align is_local_min_on.sup IsLocalMinOn.supₓ'. -/
theorem IsLocalMinOn.sup (hf : IsLocalMinOn f s a) (hg : IsLocalMinOn g s a) :
    IsLocalMinOn (fun x => f x ⊔ g x) s a :=
  hf.sup hg
#align is_local_min_on.sup IsLocalMinOn.sup

/- warning: is_local_max_on.sup -> IsLocalMaxOn.sup is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : SemilatticeSup.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) g s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Sup.sup.{u2} β (SemilatticeSup.toHasSup.{u2} β _inst_2) (f x) (g x)) s a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : SemilatticeSup.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) g s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeSup.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Sup.sup.{u2} β (SemilatticeSup.toSup.{u2} β _inst_2) (f x) (g x)) s a)
Case conversion may be inaccurate. Consider using '#align is_local_max_on.sup IsLocalMaxOn.supₓ'. -/
theorem IsLocalMaxOn.sup (hf : IsLocalMaxOn f s a) (hg : IsLocalMaxOn g s a) :
    IsLocalMaxOn (fun x => f x ⊔ g x) s a :=
  hf.sup hg
#align is_local_max_on.sup IsLocalMaxOn.sup

end SemilatticeSup

section SemilatticeInf

variable [SemilatticeInf β] {f g : α → β} {a : α} {s : Set α} {l : Filter α}

/- warning: is_local_min.inf -> IsLocalMin.inf is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : SemilatticeInf.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) g a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Inf.inf.{u2} β (SemilatticeInf.toHasInf.{u2} β _inst_2) (f x) (g x)) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : SemilatticeInf.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) g a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Inf.inf.{u2} β (SemilatticeInf.toInf.{u2} β _inst_2) (f x) (g x)) a)
Case conversion may be inaccurate. Consider using '#align is_local_min.inf IsLocalMin.infₓ'. -/
theorem IsLocalMin.inf (hf : IsLocalMin f a) (hg : IsLocalMin g a) :
    IsLocalMin (fun x => f x ⊓ g x) a :=
  hf.inf hg
#align is_local_min.inf IsLocalMin.inf

/- warning: is_local_max.inf -> IsLocalMax.inf is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : SemilatticeInf.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) g a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Inf.inf.{u2} β (SemilatticeInf.toHasInf.{u2} β _inst_2) (f x) (g x)) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : SemilatticeInf.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) f a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) g a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Inf.inf.{u2} β (SemilatticeInf.toInf.{u2} β _inst_2) (f x) (g x)) a)
Case conversion may be inaccurate. Consider using '#align is_local_max.inf IsLocalMax.infₓ'. -/
theorem IsLocalMax.inf (hf : IsLocalMax f a) (hg : IsLocalMax g a) :
    IsLocalMax (fun x => f x ⊓ g x) a :=
  hf.inf hg
#align is_local_max.inf IsLocalMax.inf

/- warning: is_local_min_on.inf -> IsLocalMinOn.inf is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : SemilatticeInf.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) g s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Inf.inf.{u2} β (SemilatticeInf.toHasInf.{u2} β _inst_2) (f x) (g x)) s a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : SemilatticeInf.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) g s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Inf.inf.{u2} β (SemilatticeInf.toInf.{u2} β _inst_2) (f x) (g x)) s a)
Case conversion may be inaccurate. Consider using '#align is_local_min_on.inf IsLocalMinOn.infₓ'. -/
theorem IsLocalMinOn.inf (hf : IsLocalMinOn f s a) (hg : IsLocalMinOn g s a) :
    IsLocalMinOn (fun x => f x ⊓ g x) s a :=
  hf.inf hg
#align is_local_min_on.inf IsLocalMinOn.inf

/- warning: is_local_max_on.inf -> IsLocalMaxOn.inf is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : SemilatticeInf.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) g s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Inf.inf.{u2} β (SemilatticeInf.toHasInf.{u2} β _inst_2) (f x) (g x)) s a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : SemilatticeInf.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) f s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) g s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β _inst_2)) (fun (x : α) => Inf.inf.{u2} β (SemilatticeInf.toInf.{u2} β _inst_2) (f x) (g x)) s a)
Case conversion may be inaccurate. Consider using '#align is_local_max_on.inf IsLocalMaxOn.infₓ'. -/
theorem IsLocalMaxOn.inf (hf : IsLocalMaxOn f s a) (hg : IsLocalMaxOn g s a) :
    IsLocalMaxOn (fun x => f x ⊓ g x) s a :=
  hf.inf hg
#align is_local_max_on.inf IsLocalMaxOn.inf

end SemilatticeInf

/-! ### Pointwise `min`/`max` -/

section LinearOrder

variable [LinearOrder β] {f g : α → β} {a : α} {s : Set α} {l : Filter α}

/- warning: is_local_min.min -> IsLocalMin.min is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : LinearOrder.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) f a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) g a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) (fun (x : α) => LinearOrder.min.{u2} β _inst_2 (f x) (g x)) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : LinearOrder.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) f a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) g a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) (fun (x : α) => Min.min.{u2} β (LinearOrder.toMin.{u2} β _inst_2) (f x) (g x)) a)
Case conversion may be inaccurate. Consider using '#align is_local_min.min IsLocalMin.minₓ'. -/
theorem IsLocalMin.min (hf : IsLocalMin f a) (hg : IsLocalMin g a) :
    IsLocalMin (fun x => min (f x) (g x)) a :=
  hf.min hg
#align is_local_min.min IsLocalMin.min

/- warning: is_local_max.min -> IsLocalMax.min is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : LinearOrder.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) f a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) g a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) (fun (x : α) => LinearOrder.min.{u2} β _inst_2 (f x) (g x)) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : LinearOrder.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) f a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) g a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) (fun (x : α) => Min.min.{u2} β (LinearOrder.toMin.{u2} β _inst_2) (f x) (g x)) a)
Case conversion may be inaccurate. Consider using '#align is_local_max.min IsLocalMax.minₓ'. -/
theorem IsLocalMax.min (hf : IsLocalMax f a) (hg : IsLocalMax g a) :
    IsLocalMax (fun x => min (f x) (g x)) a :=
  hf.min hg
#align is_local_max.min IsLocalMax.min

/- warning: is_local_min_on.min -> IsLocalMinOn.min is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : LinearOrder.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) f s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) g s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) (fun (x : α) => LinearOrder.min.{u2} β _inst_2 (f x) (g x)) s a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : LinearOrder.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) f s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) g s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) (fun (x : α) => Min.min.{u2} β (LinearOrder.toMin.{u2} β _inst_2) (f x) (g x)) s a)
Case conversion may be inaccurate. Consider using '#align is_local_min_on.min IsLocalMinOn.minₓ'. -/
theorem IsLocalMinOn.min (hf : IsLocalMinOn f s a) (hg : IsLocalMinOn g s a) :
    IsLocalMinOn (fun x => min (f x) (g x)) s a :=
  hf.min hg
#align is_local_min_on.min IsLocalMinOn.min

/- warning: is_local_max_on.min -> IsLocalMaxOn.min is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : LinearOrder.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) f s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) g s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) (fun (x : α) => LinearOrder.min.{u2} β _inst_2 (f x) (g x)) s a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : LinearOrder.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) f s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) g s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) (fun (x : α) => Min.min.{u2} β (LinearOrder.toMin.{u2} β _inst_2) (f x) (g x)) s a)
Case conversion may be inaccurate. Consider using '#align is_local_max_on.min IsLocalMaxOn.minₓ'. -/
theorem IsLocalMaxOn.min (hf : IsLocalMaxOn f s a) (hg : IsLocalMaxOn g s a) :
    IsLocalMaxOn (fun x => min (f x) (g x)) s a :=
  hf.min hg
#align is_local_max_on.min IsLocalMaxOn.min

/- warning: is_local_min.max -> IsLocalMin.max is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : LinearOrder.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) f a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) g a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) (fun (x : α) => LinearOrder.max.{u2} β _inst_2 (f x) (g x)) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : LinearOrder.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) f a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) g a) -> (IsLocalMin.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) (fun (x : α) => Max.max.{u2} β (LinearOrder.toMax.{u2} β _inst_2) (f x) (g x)) a)
Case conversion may be inaccurate. Consider using '#align is_local_min.max IsLocalMin.maxₓ'. -/
theorem IsLocalMin.max (hf : IsLocalMin f a) (hg : IsLocalMin g a) :
    IsLocalMin (fun x => max (f x) (g x)) a :=
  hf.max hg
#align is_local_min.max IsLocalMin.max

/- warning: is_local_max.max -> IsLocalMax.max is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : LinearOrder.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) f a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) g a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) (fun (x : α) => LinearOrder.max.{u2} β _inst_2 (f x) (g x)) a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : LinearOrder.{u2} β] {f : α -> β} {g : α -> β} {a : α}, (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) f a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) g a) -> (IsLocalMax.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) (fun (x : α) => Max.max.{u2} β (LinearOrder.toMax.{u2} β _inst_2) (f x) (g x)) a)
Case conversion may be inaccurate. Consider using '#align is_local_max.max IsLocalMax.maxₓ'. -/
theorem IsLocalMax.max (hf : IsLocalMax f a) (hg : IsLocalMax g a) :
    IsLocalMax (fun x => max (f x) (g x)) a :=
  hf.max hg
#align is_local_max.max IsLocalMax.max

/- warning: is_local_min_on.max -> IsLocalMinOn.max is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : LinearOrder.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) f s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) g s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) (fun (x : α) => LinearOrder.max.{u2} β _inst_2 (f x) (g x)) s a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : LinearOrder.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) f s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) g s a) -> (IsLocalMinOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) (fun (x : α) => Max.max.{u2} β (LinearOrder.toMax.{u2} β _inst_2) (f x) (g x)) s a)
Case conversion may be inaccurate. Consider using '#align is_local_min_on.max IsLocalMinOn.maxₓ'. -/
theorem IsLocalMinOn.max (hf : IsLocalMinOn f s a) (hg : IsLocalMinOn g s a) :
    IsLocalMinOn (fun x => max (f x) (g x)) s a :=
  hf.max hg
#align is_local_min_on.max IsLocalMinOn.max

/- warning: is_local_max_on.max -> IsLocalMaxOn.max is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : LinearOrder.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) f s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) g s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (LinearOrder.toLattice.{u2} β _inst_2)))) (fun (x : α) => LinearOrder.max.{u2} β _inst_2 (f x) (g x)) s a)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : LinearOrder.{u2} β] {f : α -> β} {g : α -> β} {a : α} {s : Set.{u1} α}, (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) f s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) g s a) -> (IsLocalMaxOn.{u1, u2} α β _inst_1 (PartialOrder.toPreorder.{u2} β (SemilatticeInf.toPartialOrder.{u2} β (Lattice.toSemilatticeInf.{u2} β (DistribLattice.toLattice.{u2} β (instDistribLattice.{u2} β _inst_2))))) (fun (x : α) => Max.max.{u2} β (LinearOrder.toMax.{u2} β _inst_2) (f x) (g x)) s a)
Case conversion may be inaccurate. Consider using '#align is_local_max_on.max IsLocalMaxOn.maxₓ'. -/
theorem IsLocalMaxOn.max (hf : IsLocalMaxOn f s a) (hg : IsLocalMaxOn g s a) :
    IsLocalMaxOn (fun x => max (f x) (g x)) s a :=
  hf.max hg
#align is_local_max_on.max IsLocalMaxOn.max

end LinearOrder

section Eventually

/-! ### Relation with `eventually` comparisons of two functions -/

variable [Preorder β] {s : Set α}

#print Filter.EventuallyLE.isLocalMaxOn /-
theorem Filter.EventuallyLE.isLocalMaxOn {f g : α → β} {a : α} (hle : g ≤ᶠ[𝓝[s] a] f)
    (hfga : f a = g a) (h : IsLocalMaxOn f s a) : IsLocalMaxOn g s a :=
  hle.IsMaxFilter hfga h
#align filter.eventually_le.is_local_max_on Filter.EventuallyLE.isLocalMaxOn
-/

#print IsLocalMaxOn.congr /-
theorem IsLocalMaxOn.congr {f g : α → β} {a : α} (h : IsLocalMaxOn f s a) (heq : f =ᶠ[𝓝[s] a] g)
    (hmem : a ∈ s) : IsLocalMaxOn g s a :=
  h.congr HEq <| HEq.eq_of_nhdsWithin hmem
#align is_local_max_on.congr IsLocalMaxOn.congr
-/

#print Filter.EventuallyEq.isLocalMaxOn_iff /-
theorem Filter.EventuallyEq.isLocalMaxOn_iff {f g : α → β} {a : α} (heq : f =ᶠ[𝓝[s] a] g)
    (hmem : a ∈ s) : IsLocalMaxOn f s a ↔ IsLocalMaxOn g s a :=
  HEq.isMaxFilter_iff <| HEq.eq_of_nhdsWithin hmem
#align filter.eventually_eq.is_local_max_on_iff Filter.EventuallyEq.isLocalMaxOn_iff
-/

#print Filter.EventuallyLE.isLocalMinOn /-
theorem Filter.EventuallyLE.isLocalMinOn {f g : α → β} {a : α} (hle : f ≤ᶠ[𝓝[s] a] g)
    (hfga : f a = g a) (h : IsLocalMinOn f s a) : IsLocalMinOn g s a :=
  hle.IsMinFilter hfga h
#align filter.eventually_le.is_local_min_on Filter.EventuallyLE.isLocalMinOn
-/

#print IsLocalMinOn.congr /-
theorem IsLocalMinOn.congr {f g : α → β} {a : α} (h : IsLocalMinOn f s a) (heq : f =ᶠ[𝓝[s] a] g)
    (hmem : a ∈ s) : IsLocalMinOn g s a :=
  h.congr HEq <| HEq.eq_of_nhdsWithin hmem
#align is_local_min_on.congr IsLocalMinOn.congr
-/

#print Filter.EventuallyEq.isLocalMinOn_iff /-
theorem Filter.EventuallyEq.isLocalMinOn_iff {f g : α → β} {a : α} (heq : f =ᶠ[𝓝[s] a] g)
    (hmem : a ∈ s) : IsLocalMinOn f s a ↔ IsLocalMinOn g s a :=
  HEq.isMinFilter_iff <| HEq.eq_of_nhdsWithin hmem
#align filter.eventually_eq.is_local_min_on_iff Filter.EventuallyEq.isLocalMinOn_iff
-/

#print IsLocalExtrOn.congr /-
theorem IsLocalExtrOn.congr {f g : α → β} {a : α} (h : IsLocalExtrOn f s a) (heq : f =ᶠ[𝓝[s] a] g)
    (hmem : a ∈ s) : IsLocalExtrOn g s a :=
  h.congr HEq <| HEq.eq_of_nhdsWithin hmem
#align is_local_extr_on.congr IsLocalExtrOn.congr
-/

#print Filter.EventuallyEq.isLocalExtrOn_iff /-
theorem Filter.EventuallyEq.isLocalExtrOn_iff {f g : α → β} {a : α} (heq : f =ᶠ[𝓝[s] a] g)
    (hmem : a ∈ s) : IsLocalExtrOn f s a ↔ IsLocalExtrOn g s a :=
  HEq.isExtrFilter_iff <| HEq.eq_of_nhdsWithin hmem
#align filter.eventually_eq.is_local_extr_on_iff Filter.EventuallyEq.isLocalExtrOn_iff
-/

#print Filter.EventuallyLE.isLocalMax /-
theorem Filter.EventuallyLE.isLocalMax {f g : α → β} {a : α} (hle : g ≤ᶠ[𝓝 a] f) (hfga : f a = g a)
    (h : IsLocalMax f a) : IsLocalMax g a :=
  hle.IsMaxFilter hfga h
#align filter.eventually_le.is_local_max Filter.EventuallyLE.isLocalMax
-/

#print IsLocalMax.congr /-
theorem IsLocalMax.congr {f g : α → β} {a : α} (h : IsLocalMax f a) (heq : f =ᶠ[𝓝 a] g) :
    IsLocalMax g a :=
  h.congr HEq HEq.eq_of_nhds
#align is_local_max.congr IsLocalMax.congr
-/

#print Filter.EventuallyEq.isLocalMax_iff /-
theorem Filter.EventuallyEq.isLocalMax_iff {f g : α → β} {a : α} (heq : f =ᶠ[𝓝 a] g) :
    IsLocalMax f a ↔ IsLocalMax g a :=
  HEq.isMaxFilter_iff HEq.eq_of_nhds
#align filter.eventually_eq.is_local_max_iff Filter.EventuallyEq.isLocalMax_iff
-/

#print Filter.EventuallyLE.isLocalMin /-
theorem Filter.EventuallyLE.isLocalMin {f g : α → β} {a : α} (hle : f ≤ᶠ[𝓝 a] g) (hfga : f a = g a)
    (h : IsLocalMin f a) : IsLocalMin g a :=
  hle.IsMinFilter hfga h
#align filter.eventually_le.is_local_min Filter.EventuallyLE.isLocalMin
-/

#print IsLocalMin.congr /-
theorem IsLocalMin.congr {f g : α → β} {a : α} (h : IsLocalMin f a) (heq : f =ᶠ[𝓝 a] g) :
    IsLocalMin g a :=
  h.congr HEq HEq.eq_of_nhds
#align is_local_min.congr IsLocalMin.congr
-/

#print Filter.EventuallyEq.isLocalMin_iff /-
theorem Filter.EventuallyEq.isLocalMin_iff {f g : α → β} {a : α} (heq : f =ᶠ[𝓝 a] g) :
    IsLocalMin f a ↔ IsLocalMin g a :=
  HEq.isMinFilter_iff HEq.eq_of_nhds
#align filter.eventually_eq.is_local_min_iff Filter.EventuallyEq.isLocalMin_iff
-/

#print IsLocalExtr.congr /-
theorem IsLocalExtr.congr {f g : α → β} {a : α} (h : IsLocalExtr f a) (heq : f =ᶠ[𝓝 a] g) :
    IsLocalExtr g a :=
  h.congr HEq HEq.eq_of_nhds
#align is_local_extr.congr IsLocalExtr.congr
-/

#print Filter.EventuallyEq.isLocalExtr_iff /-
theorem Filter.EventuallyEq.isLocalExtr_iff {f g : α → β} {a : α} (heq : f =ᶠ[𝓝 a] g) :
    IsLocalExtr f a ↔ IsLocalExtr g a :=
  HEq.isExtrFilter_iff HEq.eq_of_nhds
#align filter.eventually_eq.is_local_extr_iff Filter.EventuallyEq.isLocalExtr_iff
-/

end Eventually


/-
Copyright (c) 2021 Kevin Buzzard. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author : Kevin Buzzard
-/

import tactic -- imports all the Lean tactics

/-!

# Logic in Lean, example sheet 5 : "iff" (`↔`)

We learn about how to manipulate `P ↔ Q` in Lean.

## Tactics

You'll need to know about the tactics from the previous sheets,
and also the following two new tactics:

* `refl`
* `rw`

-/

variables (P Q R S : Prop)

example : P ↔ P :=
begin
  sorry
end

example : (P ↔ Q) → (Q ↔ P) :=
begin
  sorry
end

example : (P ↔ Q) ↔ (Q ↔ P) :=
begin
  sorry
end

example : (P ↔ Q) → (Q ↔ R) → (P ↔ R) :=
begin
  sorry
end

example : P ∧ Q ↔ Q ∧ P :=
begin
  sorry
end

example : ((P ∧ Q) ∧ R) ↔ (P ∧ (Q ∧ R)) :=
begin
  sorry
end

example : P ↔ (P ∧ true) :=
begin
  sorry
end

example : false ↔ (P ∧ false) :=
begin
  sorry
end

example : (P ↔ Q) → (R ↔ S) → (P ∧ R ↔ Q ∧ S) :=
begin
  sorry
end

example : ¬ (P ↔ ¬ P) :=
begin
  sorry,
end


/-
Copyright (c) 2020 Yury G. Kudryashov. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Yury G. Kudryashov, Johannes Hölzl
-/
import order.conditionally_complete_lattice.basic
import order.rel_iso.basic

/-!
# Order continuity

> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
> Any changes to this file require a corresponding PR to mathlib4.

We say that a function is *left order continuous* if it sends all least upper bounds
to least upper bounds. The order dual notion is called *right order continuity*.

For monotone functions `ℝ → ℝ` these notions correspond to the usual left and right continuity.

We prove some basic lemmas (`map_sup`, `map_Sup` etc) and prove that an `rel_iso` is both left
and right order continuous.
-/

universes u v w x

variables {α : Type u} {β : Type v} {γ : Type w} {ι : Sort x}

open function order_dual set

/-!
### Definitions
-/

/-- A function `f` between preorders is left order continuous if it preserves all suprema.  We
define it using `is_lub` instead of `Sup` so that the proof works both for complete lattices and
conditionally complete lattices. -/
def left_ord_continuous [preorder α] [preorder β] (f : α → β) :=
∀ ⦃s : set α⦄ ⦃x⦄, is_lub s x → is_lub (f '' s) (f x)

/-- A function `f` between preorders is right order continuous if it preserves all infima.  We
define it using `is_glb` instead of `Inf` so that the proof works both for complete lattices and
conditionally complete lattices. -/
def right_ord_continuous [preorder α] [preorder β] (f : α → β) :=
∀ ⦃s : set α⦄ ⦃x⦄, is_glb s x → is_glb (f '' s) (f x)

namespace left_ord_continuous

section preorder

variables (α) [preorder α] [preorder β] [preorder γ] {g : β → γ} {f : α → β}

protected lemma id : left_ord_continuous (id : α → α) := λ s x h, by simpa only [image_id] using h

variable {α}

protected lemma order_dual : left_ord_continuous f → right_ord_continuous (to_dual ∘ f ∘ of_dual) :=
id

lemma map_is_greatest (hf : left_ord_continuous f) {s : set α} {x : α} (h : is_greatest s x):
  is_greatest (f '' s) (f x) :=
⟨mem_image_of_mem f h.1, (hf h.is_lub).1⟩

lemma comp (hg : left_ord_continuous g) (hf : left_ord_continuous f) :
  left_ord_continuous (g ∘ f) :=
λ s x h, by simpa only [image_image] using hg (hf h)

protected lemma iterate {f : α → α} (hf : left_ord_continuous f) (n : ℕ) :
  left_ord_continuous (f^[n]) :=
nat.rec_on n (left_ord_continuous.id α) $ λ n ihn, ihn.comp hf

end preorder

section semilattice_sup

variables [semilattice_sup α] [semilattice_sup β] {f : α → β}

lemma map_sup (hf : left_ord_continuous f) (x y : α) :
  f (x ⊔ y) = f x ⊔ f y :=
(hf is_lub_pair).unique $ by simp only [image_pair, is_lub_pair]

lemma le_iff (hf : left_ord_continuous f) (h : injective f) {x y} :
  f x ≤ f y ↔ x ≤ y :=
by simp only [← sup_eq_right, ← hf.map_sup, h.eq_iff]

lemma lt_iff (hf : left_ord_continuous f) (h : injective f) {x y} :
  f x < f y ↔ x < y :=
by simp only [lt_iff_le_not_le, hf.le_iff h]

variable (f)

/-- Convert an injective left order continuous function to an order embedding. -/
def to_order_embedding (hf : left_ord_continuous f) (h : injective f) :
  α ↪o β :=
⟨⟨f, h⟩, λ x y, hf.le_iff h⟩

variable {f}

@[simp] lemma coe_to_order_embedding (hf : left_ord_continuous f) (h : injective f) :
  ⇑(hf.to_order_embedding f h) = f := rfl

end semilattice_sup

section complete_lattice

variables [complete_lattice α] [complete_lattice β] {f : α → β}

lemma map_Sup' (hf : left_ord_continuous f) (s : set α) :
  f (Sup s) = Sup (f '' s) :=
(hf $ is_lub_Sup s).Sup_eq.symm

lemma map_Sup (hf : left_ord_continuous f) (s : set α) :
  f (Sup s) = ⨆ x ∈ s, f x :=
by rw [hf.map_Sup', Sup_image]

lemma map_supr (hf : left_ord_continuous f) (g : ι → α) :
  f (⨆ i, g i) = ⨆ i, f (g i) :=
by simp only [supr, hf.map_Sup', ← range_comp]

end complete_lattice

section conditionally_complete_lattice

variables [conditionally_complete_lattice α] [conditionally_complete_lattice β] [nonempty ι]
  {f : α → β}

lemma map_cSup (hf : left_ord_continuous f) {s : set α} (sne : s.nonempty) (sbdd : bdd_above s) :
  f (Sup s) = Sup (f '' s) :=
((hf $ is_lub_cSup sne sbdd).cSup_eq $ sne.image f).symm

lemma map_csupr (hf : left_ord_continuous f) {g : ι → α} (hg : bdd_above (range g)) :
  f (⨆ i, g i) = ⨆ i, f (g i) :=
by simp only [supr, hf.map_cSup (range_nonempty _) hg, ← range_comp]

end conditionally_complete_lattice

end left_ord_continuous

namespace right_ord_continuous

section preorder

variables (α) [preorder α] [preorder β] [preorder γ] {g : β → γ} {f : α → β}

protected lemma id : right_ord_continuous (id : α → α) := λ s x h, by simpa only [image_id] using h

variable {α}

protected lemma order_dual : right_ord_continuous f → left_ord_continuous (to_dual ∘ f ∘ of_dual) :=
id

lemma map_is_least (hf : right_ord_continuous f) {s : set α} {x : α} (h : is_least s x):
  is_least (f '' s) (f x) :=
hf.order_dual.map_is_greatest h

lemma mono (hf : right_ord_continuous f) : monotone f :=
hf.order_dual.mono.dual

lemma comp (hg : right_ord_continuous g) (hf : right_ord_continuous f) :
  right_ord_continuous (g ∘ f) :=
hg.order_dual.comp hf.order_dual

protected lemma iterate {f : α → α} (hf : right_ord_continuous f) (n : ℕ) :
  right_ord_continuous (f^[n]) :=
hf.order_dual.iterate n

end preorder

section semilattice_inf

variables [semilattice_inf α] [semilattice_inf β] {f : α → β}

lemma map_inf (hf : right_ord_continuous f) (x y : α) :
  f (x ⊓ y) = f x ⊓ f y :=
hf.order_dual.map_sup x y

lemma le_iff (hf : right_ord_continuous f) (h : injective f) {x y} :
  f x ≤ f y ↔ x ≤ y :=
hf.order_dual.le_iff h

lemma lt_iff (hf : right_ord_continuous f) (h : injective f) {x y} :
  f x < f y ↔ x < y :=
hf.order_dual.lt_iff h

variable (f)

/-- Convert an injective left order continuous function to a `order_embedding`. -/
def to_order_embedding (hf : right_ord_continuous f) (h : injective f) : α ↪o β :=
⟨⟨f, h⟩, λ x y, hf.le_iff h⟩

variable {f}

@[simp] lemma coe_to_order_embedding (hf : right_ord_continuous f) (h : injective f) :
  ⇑(hf.to_order_embedding f h) = f := rfl

end semilattice_inf

section complete_lattice

variables [complete_lattice α] [complete_lattice β] {f : α → β}

lemma map_Inf' (hf : right_ord_continuous f) (s : set α) :
  f (Inf s) = Inf (f '' s) :=
hf.order_dual.map_Sup' s

lemma map_Inf (hf : right_ord_continuous f) (s : set α) :
  f (Inf s) = ⨅ x ∈ s, f x :=
hf.order_dual.map_Sup s

lemma map_infi (hf : right_ord_continuous f) (g : ι → α) :
  f (⨅ i, g i) = ⨅ i, f (g i) :=
hf.order_dual.map_supr g

end complete_lattice

section conditionally_complete_lattice

variables [conditionally_complete_lattice α] [conditionally_complete_lattice β] [nonempty ι]
  {f : α → β}

lemma map_cInf (hf : right_ord_continuous f) {s : set α} (sne : s.nonempty) (sbdd : bdd_below s) :
  f (Inf s) = Inf (f '' s) :=
hf.order_dual.map_cSup sne sbdd

lemma map_cinfi (hf : right_ord_continuous f) {g : ι → α} (hg : bdd_below (range g)) :
  f (⨅ i, g i) = ⨅ i, f (g i) :=
hf.order_dual.map_csupr hg

end conditionally_complete_lattice

end right_ord_continuous

namespace order_iso

section preorder

variables [preorder α] [preorder β] (e : α ≃o β)
  {s : set α} {x : α}

protected lemma left_ord_continuous : left_ord_continuous e :=
λ s x hx,
⟨monotone.mem_upper_bounds_image (λ x y, e.map_rel_iff.2) hx.1,
  λ y hy, e.rel_symm_apply.1 $ (is_lub_le_iff hx).2 $ λ x' hx', e.rel_symm_apply.2 $ hy $
    mem_image_of_mem _ hx'⟩

protected lemma right_ord_continuous : right_ord_continuous e :=
order_iso.left_ord_continuous e.dual

end preorder

end order_iso