/-
Copyright (c) 2022 Yaël Dillies. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Yaël Dillies

! This file was ported from Lean 3 source module topology.order.hom.basic
! leanprover-community/mathlib commit b6da1a0b3e7cd83b1f744c49ce48ef8c6307d2f6
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.Order.Hom.Basic
import Mathbin.Topology.ContinuousFunction.Basic

/-!
# Continuous order homomorphisms

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

This file defines continuous order homomorphisms, that is maps which are both continuous and
monotone. They are also called Priestley homomorphisms because they are the morphisms of the
category of Priestley spaces.

We use the `fun_like` design, so each type of morphisms has a companion typeclass which is meant to
be satisfied by itself and all stricter types.

## Types of morphisms

* `continuous_order_hom`: Continuous monotone functions, aka Priestley homomorphisms.

## Typeclasses

* `continuous_order_hom_class`
-/

open Function

variable {F α β γ δ : Type _}

#print ContinuousOrderHom /-
/-- The type of continuous monotone maps from `α` to `β`, aka Priestley homomorphisms. -/
structure ContinuousOrderHom (α β : Type _) [Preorder α] [Preorder β] [TopologicalSpace α]
  [TopologicalSpace β] extends OrderHom α β where
  continuous_toFun : Continuous to_fun
#align continuous_order_hom ContinuousOrderHom
-/

-- mathport name: «expr →Co »
infixr:25 " →Co " => ContinuousOrderHom

section

#print ContinuousOrderHomClass /-
/-- `continuous_order_hom_class F α β` states that `F` is a type of continuous monotone maps.

You should extend this class when you extend `continuous_order_hom`. -/
class ContinuousOrderHomClass (F : Type _) (α β : outParam <| Type _) [Preorder α] [Preorder β]
  [TopologicalSpace α] [TopologicalSpace β] extends
  RelHomClass F ((· ≤ ·) : α → α → Prop) ((· ≤ ·) : β → β → Prop) where
  map_continuous (f : F) : Continuous f
#align continuous_order_hom_class ContinuousOrderHomClass
-/

end

#print ContinuousOrderHomClass.toContinuousMapClass /-
-- See note [lower instance priority]
instance (priority := 100) ContinuousOrderHomClass.toContinuousMapClass [Preorder α] [Preorder β]
    [TopologicalSpace α] [TopologicalSpace β] [ContinuousOrderHomClass F α β] :
    ContinuousMapClass F α β :=
  { ‹ContinuousOrderHomClass F α β› with }
#align continuous_order_hom_class.to_continuous_map_class ContinuousOrderHomClass.toContinuousMapClass
-/

instance [Preorder α] [Preorder β] [TopologicalSpace α] [TopologicalSpace β]
    [ContinuousOrderHomClass F α β] : CoeTC F (α →Co β) :=
  ⟨fun f =>
    { toFun := f
      monotone' := OrderHomClass.mono f
      continuous_toFun := map_continuous f }⟩

/-! ### Top homomorphisms -/

namespace ContinuousOrderHom

variable [TopologicalSpace α] [Preorder α] [TopologicalSpace β]

section Preorder

variable [Preorder β] [TopologicalSpace γ] [Preorder γ] [TopologicalSpace δ] [Preorder δ]

#print ContinuousOrderHom.toContinuousMap /-
/-- Reinterpret a `continuous_order_hom` as a `continuous_map`. -/
def toContinuousMap (f : α →Co β) : C(α, β) :=
  { f with }
#align continuous_order_hom.to_continuous_map ContinuousOrderHom.toContinuousMap
-/

instance : ContinuousOrderHomClass (α →Co β) α β
    where
  coe f := f.toFun
  coe_injective' f g h := by
    obtain ⟨⟨_, _⟩, _⟩ := f
    obtain ⟨⟨_, _⟩, _⟩ := g
    congr
  map_rel f := f.monotone'
  map_continuous f := f.continuous_toFun

/-- Helper instance for when there's too many metavariables to apply `fun_like.has_coe_to_fun`
directly. -/
instance : CoeFun (α →Co β) fun _ => α → β :=
  FunLike.hasCoeToFun

/- warning: continuous_order_hom.to_fun_eq_coe -> ContinuousOrderHom.toFun_eq_coe is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u2} β] [_inst_4 : Preorder.{u2} β] {f : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3}, Eq.{max (succ u1) (succ u2)} (α -> β) (OrderHom.toFun.{u1, u2} α β _inst_2 _inst_4 (ContinuousOrderHom.toOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3 f)) (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (fun (_x : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) => α -> β) (ContinuousOrderHom.hasCoeToFun.{u1, u2} α β _inst_1 _inst_2 _inst_3 _inst_4) f)
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : TopologicalSpace.{u2} α] [_inst_2 : Preorder.{u2} α] [_inst_3 : TopologicalSpace.{u1} β] [_inst_4 : Preorder.{u1} β] {f : ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3}, Eq.{max (succ u2) (succ u1)} (α -> β) (OrderHom.toFun.{u2, u1} α β _inst_2 _inst_4 (ContinuousOrderHom.toOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3 f)) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α (fun (_x : α) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => β) _x) (ContinuousMapClass.toFunLike.{max u2 u1, u2, u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_1 _inst_3 (ContinuousOrderHomClass.toContinuousMapClass.{max u2 u1, u2, u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_2 _inst_4 _inst_1 _inst_3 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u2, u1} α β _inst_1 _inst_2 _inst_3 _inst_4))) f)
Case conversion may be inaccurate. Consider using '#align continuous_order_hom.to_fun_eq_coe ContinuousOrderHom.toFun_eq_coeₓ'. -/
@[simp]
theorem toFun_eq_coe {f : α →Co β} : f.toFun = (f : α → β) :=
  rfl
#align continuous_order_hom.to_fun_eq_coe ContinuousOrderHom.toFun_eq_coe

/- warning: continuous_order_hom.ext -> ContinuousOrderHom.ext is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u2} β] [_inst_4 : Preorder.{u2} β] {f : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3} {g : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3}, (forall (a : α), Eq.{succ u2} β (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (fun (_x : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) => α -> β) (ContinuousOrderHom.hasCoeToFun.{u1, u2} α β _inst_1 _inst_2 _inst_3 _inst_4) f a) (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (fun (_x : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) => α -> β) (ContinuousOrderHom.hasCoeToFun.{u1, u2} α β _inst_1 _inst_2 _inst_3 _inst_4) g a)) -> (Eq.{max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) f g)
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : TopologicalSpace.{u2} α] [_inst_2 : Preorder.{u2} α] [_inst_3 : TopologicalSpace.{u1} β] [_inst_4 : Preorder.{u1} β] {f : ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3} {g : ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3}, (forall (a : α), Eq.{succ u1} ((fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => β) a) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α (fun (_x : α) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => β) _x) (ContinuousMapClass.toFunLike.{max u2 u1, u2, u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_1 _inst_3 (ContinuousOrderHomClass.toContinuousMapClass.{max u2 u1, u2, u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_2 _inst_4 _inst_1 _inst_3 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u2, u1} α β _inst_1 _inst_2 _inst_3 _inst_4))) f a) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α (fun (_x : α) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => β) _x) (ContinuousMapClass.toFunLike.{max u2 u1, u2, u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_1 _inst_3 (ContinuousOrderHomClass.toContinuousMapClass.{max u2 u1, u2, u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_2 _inst_4 _inst_1 _inst_3 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u2, u1} α β _inst_1 _inst_2 _inst_3 _inst_4))) g a)) -> (Eq.{max (succ u2) (succ u1)} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) f g)
Case conversion may be inaccurate. Consider using '#align continuous_order_hom.ext ContinuousOrderHom.extₓ'. -/
@[ext]
theorem ext {f g : α →Co β} (h : ∀ a, f a = g a) : f = g :=
  FunLike.ext f g h
#align continuous_order_hom.ext ContinuousOrderHom.ext

/- warning: continuous_order_hom.copy -> ContinuousOrderHom.copy is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u2} β] [_inst_4 : Preorder.{u2} β] (f : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (f' : α -> β), (Eq.{max (succ u1) (succ u2)} (α -> β) f' (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (fun (_x : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) => α -> β) (ContinuousOrderHom.hasCoeToFun.{u1, u2} α β _inst_1 _inst_2 _inst_3 _inst_4) f)) -> (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3)
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u2} β] [_inst_4 : Preorder.{u2} β] (f : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (f' : α -> β), (Eq.{max (succ u1) (succ u2)} (α -> β) f' (FunLike.coe.{max (succ u1) (succ u2), succ u1, succ u2} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) α (fun (_x : α) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => β) _x) (ContinuousMapClass.toFunLike.{max u1 u2, u1, u2} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_1 _inst_3 (ContinuousOrderHomClass.toContinuousMapClass.{max u1 u2, u1, u2} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_2 _inst_4 _inst_1 _inst_3 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u1, u2} α β _inst_1 _inst_2 _inst_3 _inst_4))) f)) -> (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3)
Case conversion may be inaccurate. Consider using '#align continuous_order_hom.copy ContinuousOrderHom.copyₓ'. -/
/-- Copy of a `continuous_order_hom` with a new `continuous_map` equal to the old one. Useful to fix
definitional equalities. -/
protected def copy (f : α →Co β) (f' : α → β) (h : f' = f) : α →Co β :=
  ⟨f.toOrderHom.copy f' <| h, h.symm.subst f.continuous_toFun⟩
#align continuous_order_hom.copy ContinuousOrderHom.copy

/- warning: continuous_order_hom.coe_copy -> ContinuousOrderHom.coe_copy is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u2} β] [_inst_4 : Preorder.{u2} β] (f : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (f' : α -> β) (h : Eq.{max (succ u1) (succ u2)} (α -> β) f' (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (fun (_x : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) => α -> β) (ContinuousOrderHom.hasCoeToFun.{u1, u2} α β _inst_1 _inst_2 _inst_3 _inst_4) f)), Eq.{max (succ u1) (succ u2)} (α -> β) (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (fun (_x : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) => α -> β) (ContinuousOrderHom.hasCoeToFun.{u1, u2} α β _inst_1 _inst_2 _inst_3 _inst_4) (ContinuousOrderHom.copy.{u1, u2} α β _inst_1 _inst_2 _inst_3 _inst_4 f f' h)) f'
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : TopologicalSpace.{u2} α] [_inst_2 : Preorder.{u2} α] [_inst_3 : TopologicalSpace.{u1} β] [_inst_4 : Preorder.{u1} β] (f : ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) (f' : α -> β) (h : Eq.{max (succ u2) (succ u1)} (α -> β) f' (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α (fun (_x : α) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => β) _x) (ContinuousMapClass.toFunLike.{max u2 u1, u2, u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_1 _inst_3 (ContinuousOrderHomClass.toContinuousMapClass.{max u2 u1, u2, u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_2 _inst_4 _inst_1 _inst_3 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u2, u1} α β _inst_1 _inst_2 _inst_3 _inst_4))) f)), Eq.{max (succ u2) (succ u1)} (forall (ᾰ : α), (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => β) ᾰ) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α (fun (_x : α) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => β) _x) (ContinuousMapClass.toFunLike.{max u2 u1, u2, u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_1 _inst_3 (ContinuousOrderHomClass.toContinuousMapClass.{max u2 u1, u2, u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_2 _inst_4 _inst_1 _inst_3 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u2, u1} α β _inst_1 _inst_2 _inst_3 _inst_4))) (ContinuousOrderHom.copy.{u2, u1} α β _inst_1 _inst_2 _inst_3 _inst_4 f f' h)) f'
Case conversion may be inaccurate. Consider using '#align continuous_order_hom.coe_copy ContinuousOrderHom.coe_copyₓ'. -/
@[simp]
theorem coe_copy (f : α →Co β) (f' : α → β) (h : f' = f) : ⇑(f.copy f' h) = f' :=
  rfl
#align continuous_order_hom.coe_copy ContinuousOrderHom.coe_copy

/- warning: continuous_order_hom.copy_eq -> ContinuousOrderHom.copy_eq is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u2} β] [_inst_4 : Preorder.{u2} β] (f : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (f' : α -> β) (h : Eq.{max (succ u1) (succ u2)} (α -> β) f' (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (fun (_x : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) => α -> β) (ContinuousOrderHom.hasCoeToFun.{u1, u2} α β _inst_1 _inst_2 _inst_3 _inst_4) f)), Eq.{max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (ContinuousOrderHom.copy.{u1, u2} α β _inst_1 _inst_2 _inst_3 _inst_4 f f' h) f
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : TopologicalSpace.{u2} α] [_inst_2 : Preorder.{u2} α] [_inst_3 : TopologicalSpace.{u1} β] [_inst_4 : Preorder.{u1} β] (f : ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) (f' : α -> β) (h : Eq.{max (succ u2) (succ u1)} (α -> β) f' (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α (fun (_x : α) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => β) _x) (ContinuousMapClass.toFunLike.{max u2 u1, u2, u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_1 _inst_3 (ContinuousOrderHomClass.toContinuousMapClass.{max u2 u1, u2, u1} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_2 _inst_4 _inst_1 _inst_3 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u2, u1} α β _inst_1 _inst_2 _inst_3 _inst_4))) f)), Eq.{max (succ u2) (succ u1)} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) (ContinuousOrderHom.copy.{u2, u1} α β _inst_1 _inst_2 _inst_3 _inst_4 f f' h) f
Case conversion may be inaccurate. Consider using '#align continuous_order_hom.copy_eq ContinuousOrderHom.copy_eqₓ'. -/
theorem copy_eq (f : α →Co β) (f' : α → β) (h : f' = f) : f.copy f' h = f :=
  FunLike.ext' h
#align continuous_order_hom.copy_eq ContinuousOrderHom.copy_eq

variable (α)

#print ContinuousOrderHom.id /-
/-- `id` as a `continuous_order_hom`. -/
protected def id : α →Co α :=
  ⟨OrderHom.id, continuous_id⟩
#align continuous_order_hom.id ContinuousOrderHom.id
-/

instance : Inhabited (α →Co α) :=
  ⟨ContinuousOrderHom.id _⟩

/- warning: continuous_order_hom.coe_id -> ContinuousOrderHom.coe_id is a dubious translation:
lean 3 declaration is
  forall (α : Type.{u1}) [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α], Eq.{succ u1} (α -> α) (coeFn.{succ u1, succ u1} (ContinuousOrderHom.{u1, u1} α α _inst_2 _inst_2 _inst_1 _inst_1) (fun (_x : ContinuousOrderHom.{u1, u1} α α _inst_2 _inst_2 _inst_1 _inst_1) => α -> α) (ContinuousOrderHom.hasCoeToFun.{u1, u1} α α _inst_1 _inst_2 _inst_1 _inst_2) (ContinuousOrderHom.id.{u1} α _inst_1 _inst_2)) (id.{succ u1} α)
but is expected to have type
  forall (α : Type.{u1}) [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α], Eq.{succ u1} (forall (ᾰ : α), (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => α) ᾰ) (FunLike.coe.{succ u1, succ u1, succ u1} (ContinuousOrderHom.{u1, u1} α α _inst_2 _inst_2 _inst_1 _inst_1) α (fun (_x : α) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => α) _x) (ContinuousMapClass.toFunLike.{u1, u1, u1} (ContinuousOrderHom.{u1, u1} α α _inst_2 _inst_2 _inst_1 _inst_1) α α _inst_1 _inst_1 (ContinuousOrderHomClass.toContinuousMapClass.{u1, u1, u1} (ContinuousOrderHom.{u1, u1} α α _inst_2 _inst_2 _inst_1 _inst_1) α α _inst_2 _inst_2 _inst_1 _inst_1 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u1, u1} α α _inst_1 _inst_2 _inst_1 _inst_2))) (ContinuousOrderHom.id.{u1} α _inst_1 _inst_2)) (id.{succ u1} α)
Case conversion may be inaccurate. Consider using '#align continuous_order_hom.coe_id ContinuousOrderHom.coe_idₓ'. -/
@[simp]
theorem coe_id : ⇑(ContinuousOrderHom.id α) = id :=
  rfl
#align continuous_order_hom.coe_id ContinuousOrderHom.coe_id

variable {α}

/- warning: continuous_order_hom.id_apply -> ContinuousOrderHom.id_apply is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] (a : α), Eq.{succ u1} α (coeFn.{succ u1, succ u1} (ContinuousOrderHom.{u1, u1} α α _inst_2 _inst_2 _inst_1 _inst_1) (fun (_x : ContinuousOrderHom.{u1, u1} α α _inst_2 _inst_2 _inst_1 _inst_1) => α -> α) (ContinuousOrderHom.hasCoeToFun.{u1, u1} α α _inst_1 _inst_2 _inst_1 _inst_2) (ContinuousOrderHom.id.{u1} α _inst_1 _inst_2) a) a
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] (a : α), Eq.{succ u1} ((fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => α) a) (FunLike.coe.{succ u1, succ u1, succ u1} (ContinuousOrderHom.{u1, u1} α α _inst_2 _inst_2 _inst_1 _inst_1) α (fun (_x : α) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => α) _x) (ContinuousMapClass.toFunLike.{u1, u1, u1} (ContinuousOrderHom.{u1, u1} α α _inst_2 _inst_2 _inst_1 _inst_1) α α _inst_1 _inst_1 (ContinuousOrderHomClass.toContinuousMapClass.{u1, u1, u1} (ContinuousOrderHom.{u1, u1} α α _inst_2 _inst_2 _inst_1 _inst_1) α α _inst_2 _inst_2 _inst_1 _inst_1 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u1, u1} α α _inst_1 _inst_2 _inst_1 _inst_2))) (ContinuousOrderHom.id.{u1} α _inst_1 _inst_2) a) a
Case conversion may be inaccurate. Consider using '#align continuous_order_hom.id_apply ContinuousOrderHom.id_applyₓ'. -/
@[simp]
theorem id_apply (a : α) : ContinuousOrderHom.id α a = a :=
  rfl
#align continuous_order_hom.id_apply ContinuousOrderHom.id_apply

#print ContinuousOrderHom.comp /-
/-- Composition of `continuous_order_hom`s as a `continuous_order_hom`. -/
def comp (f : β →Co γ) (g : α →Co β) : ContinuousOrderHom α γ :=
  ⟨f.toOrderHom.comp g.toOrderHom, f.continuous_toFun.comp g.continuous_toFun⟩
#align continuous_order_hom.comp ContinuousOrderHom.comp
-/

/- warning: continuous_order_hom.coe_comp -> ContinuousOrderHom.coe_comp is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} {γ : Type.{u3}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u2} β] [_inst_4 : Preorder.{u2} β] [_inst_5 : TopologicalSpace.{u3} γ] [_inst_6 : Preorder.{u3} γ] (f : ContinuousOrderHom.{u2, u3} β γ _inst_4 _inst_6 _inst_3 _inst_5) (g : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3), Eq.{max (succ u1) (succ u3)} ((fun (_x : ContinuousOrderHom.{u1, u3} α γ _inst_2 _inst_6 _inst_1 _inst_5) => α -> γ) (ContinuousOrderHom.comp.{u1, u2, u3} α β γ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 f g)) (coeFn.{max (succ u1) (succ u3), max (succ u1) (succ u3)} (ContinuousOrderHom.{u1, u3} α γ _inst_2 _inst_6 _inst_1 _inst_5) (fun (_x : ContinuousOrderHom.{u1, u3} α γ _inst_2 _inst_6 _inst_1 _inst_5) => α -> γ) (ContinuousOrderHom.hasCoeToFun.{u1, u3} α γ _inst_1 _inst_2 _inst_5 _inst_6) (ContinuousOrderHom.comp.{u1, u2, u3} α β γ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 f g)) (Function.comp.{succ u1, succ u2, succ u3} α β γ (coeFn.{max (succ u2) (succ u3), max (succ u2) (succ u3)} (ContinuousOrderHom.{u2, u3} β γ _inst_4 _inst_6 _inst_3 _inst_5) (fun (_x : ContinuousOrderHom.{u2, u3} β γ _inst_4 _inst_6 _inst_3 _inst_5) => β -> γ) (ContinuousOrderHom.hasCoeToFun.{u2, u3} β γ _inst_3 _inst_4 _inst_5 _inst_6) f) (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (fun (_x : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) => α -> β) (ContinuousOrderHom.hasCoeToFun.{u1, u2} α β _inst_1 _inst_2 _inst_3 _inst_4) g))
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u3}} {γ : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u3} β] [_inst_4 : Preorder.{u3} β] [_inst_5 : TopologicalSpace.{u2} γ] [_inst_6 : Preorder.{u2} γ] (f : ContinuousOrderHom.{u3, u2} β γ _inst_4 _inst_6 _inst_3 _inst_5) (g : ContinuousOrderHom.{u1, u3} α β _inst_2 _inst_4 _inst_1 _inst_3), Eq.{max (succ u1) (succ u2)} (forall (a : α), (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => γ) a) (FunLike.coe.{max (succ u1) (succ u2), succ u1, succ u2} (ContinuousOrderHom.{u1, u2} α γ _inst_2 _inst_6 _inst_1 _inst_5) α (fun (_x : α) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => γ) _x) (ContinuousMapClass.toFunLike.{max u1 u2, u1, u2} (ContinuousOrderHom.{u1, u2} α γ _inst_2 _inst_6 _inst_1 _inst_5) α γ _inst_1 _inst_5 (ContinuousOrderHomClass.toContinuousMapClass.{max u1 u2, u1, u2} (ContinuousOrderHom.{u1, u2} α γ _inst_2 _inst_6 _inst_1 _inst_5) α γ _inst_2 _inst_6 _inst_1 _inst_5 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u1, u2} α γ _inst_1 _inst_2 _inst_5 _inst_6))) (ContinuousOrderHom.comp.{u1, u3, u2} α β γ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 f g)) (Function.comp.{succ u1, succ u3, succ u2} α β γ (FunLike.coe.{max (succ u3) (succ u2), succ u3, succ u2} (ContinuousOrderHom.{u3, u2} β γ _inst_4 _inst_6 _inst_3 _inst_5) β (fun (_x : β) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : β) => γ) _x) (ContinuousMapClass.toFunLike.{max u3 u2, u3, u2} (ContinuousOrderHom.{u3, u2} β γ _inst_4 _inst_6 _inst_3 _inst_5) β γ _inst_3 _inst_5 (ContinuousOrderHomClass.toContinuousMapClass.{max u3 u2, u3, u2} (ContinuousOrderHom.{u3, u2} β γ _inst_4 _inst_6 _inst_3 _inst_5) β γ _inst_4 _inst_6 _inst_3 _inst_5 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u3, u2} β γ _inst_3 _inst_4 _inst_5 _inst_6))) f) (FunLike.coe.{max (succ u1) (succ u3), succ u1, succ u3} (ContinuousOrderHom.{u1, u3} α β _inst_2 _inst_4 _inst_1 _inst_3) α (fun (_x : α) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => β) _x) (ContinuousMapClass.toFunLike.{max u1 u3, u1, u3} (ContinuousOrderHom.{u1, u3} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_1 _inst_3 (ContinuousOrderHomClass.toContinuousMapClass.{max u1 u3, u1, u3} (ContinuousOrderHom.{u1, u3} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_2 _inst_4 _inst_1 _inst_3 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u1, u3} α β _inst_1 _inst_2 _inst_3 _inst_4))) g))
Case conversion may be inaccurate. Consider using '#align continuous_order_hom.coe_comp ContinuousOrderHom.coe_compₓ'. -/
@[simp]
theorem coe_comp (f : β →Co γ) (g : α →Co β) : (f.comp g : α → γ) = f ∘ g :=
  rfl
#align continuous_order_hom.coe_comp ContinuousOrderHom.coe_comp

/- warning: continuous_order_hom.comp_apply -> ContinuousOrderHom.comp_apply is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} {γ : Type.{u3}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u2} β] [_inst_4 : Preorder.{u2} β] [_inst_5 : TopologicalSpace.{u3} γ] [_inst_6 : Preorder.{u3} γ] (f : ContinuousOrderHom.{u2, u3} β γ _inst_4 _inst_6 _inst_3 _inst_5) (g : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (a : α), Eq.{succ u3} γ (coeFn.{max (succ u1) (succ u3), max (succ u1) (succ u3)} (ContinuousOrderHom.{u1, u3} α γ _inst_2 _inst_6 _inst_1 _inst_5) (fun (_x : ContinuousOrderHom.{u1, u3} α γ _inst_2 _inst_6 _inst_1 _inst_5) => α -> γ) (ContinuousOrderHom.hasCoeToFun.{u1, u3} α γ _inst_1 _inst_2 _inst_5 _inst_6) (ContinuousOrderHom.comp.{u1, u2, u3} α β γ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 f g) a) (coeFn.{max (succ u2) (succ u3), max (succ u2) (succ u3)} (ContinuousOrderHom.{u2, u3} β γ _inst_4 _inst_6 _inst_3 _inst_5) (fun (_x : ContinuousOrderHom.{u2, u3} β γ _inst_4 _inst_6 _inst_3 _inst_5) => β -> γ) (ContinuousOrderHom.hasCoeToFun.{u2, u3} β γ _inst_3 _inst_4 _inst_5 _inst_6) f (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (fun (_x : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) => α -> β) (ContinuousOrderHom.hasCoeToFun.{u1, u2} α β _inst_1 _inst_2 _inst_3 _inst_4) g a))
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u3}} {γ : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u3} β] [_inst_4 : Preorder.{u3} β] [_inst_5 : TopologicalSpace.{u2} γ] [_inst_6 : Preorder.{u2} γ] (f : ContinuousOrderHom.{u3, u2} β γ _inst_4 _inst_6 _inst_3 _inst_5) (g : ContinuousOrderHom.{u1, u3} α β _inst_2 _inst_4 _inst_1 _inst_3) (a : α), Eq.{succ u2} ((fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => γ) a) (FunLike.coe.{max (succ u1) (succ u2), succ u1, succ u2} (ContinuousOrderHom.{u1, u2} α γ _inst_2 _inst_6 _inst_1 _inst_5) α (fun (_x : α) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => γ) _x) (ContinuousMapClass.toFunLike.{max u1 u2, u1, u2} (ContinuousOrderHom.{u1, u2} α γ _inst_2 _inst_6 _inst_1 _inst_5) α γ _inst_1 _inst_5 (ContinuousOrderHomClass.toContinuousMapClass.{max u1 u2, u1, u2} (ContinuousOrderHom.{u1, u2} α γ _inst_2 _inst_6 _inst_1 _inst_5) α γ _inst_2 _inst_6 _inst_1 _inst_5 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u1, u2} α γ _inst_1 _inst_2 _inst_5 _inst_6))) (ContinuousOrderHom.comp.{u1, u3, u2} α β γ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 f g) a) (FunLike.coe.{max (succ u3) (succ u2), succ u3, succ u2} (ContinuousOrderHom.{u3, u2} β γ _inst_4 _inst_6 _inst_3 _inst_5) β (fun (_x : β) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : β) => γ) _x) (ContinuousMapClass.toFunLike.{max u3 u2, u3, u2} (ContinuousOrderHom.{u3, u2} β γ _inst_4 _inst_6 _inst_3 _inst_5) β γ _inst_3 _inst_5 (ContinuousOrderHomClass.toContinuousMapClass.{max u3 u2, u3, u2} (ContinuousOrderHom.{u3, u2} β γ _inst_4 _inst_6 _inst_3 _inst_5) β γ _inst_4 _inst_6 _inst_3 _inst_5 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u3, u2} β γ _inst_3 _inst_4 _inst_5 _inst_6))) f (FunLike.coe.{max (succ u1) (succ u3), succ u1, succ u3} (ContinuousOrderHom.{u1, u3} α β _inst_2 _inst_4 _inst_1 _inst_3) α (fun (_x : α) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => β) _x) (ContinuousMapClass.toFunLike.{max u1 u3, u1, u3} (ContinuousOrderHom.{u1, u3} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_1 _inst_3 (ContinuousOrderHomClass.toContinuousMapClass.{max u1 u3, u1, u3} (ContinuousOrderHom.{u1, u3} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_2 _inst_4 _inst_1 _inst_3 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u1, u3} α β _inst_1 _inst_2 _inst_3 _inst_4))) g a))
Case conversion may be inaccurate. Consider using '#align continuous_order_hom.comp_apply ContinuousOrderHom.comp_applyₓ'. -/
@[simp]
theorem comp_apply (f : β →Co γ) (g : α →Co β) (a : α) : (f.comp g) a = f (g a) :=
  rfl
#align continuous_order_hom.comp_apply ContinuousOrderHom.comp_apply

/- warning: continuous_order_hom.comp_assoc -> ContinuousOrderHom.comp_assoc is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} {γ : Type.{u3}} {δ : Type.{u4}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u2} β] [_inst_4 : Preorder.{u2} β] [_inst_5 : TopologicalSpace.{u3} γ] [_inst_6 : Preorder.{u3} γ] [_inst_7 : TopologicalSpace.{u4} δ] [_inst_8 : Preorder.{u4} δ] (f : ContinuousOrderHom.{u3, u4} γ δ _inst_6 _inst_8 _inst_5 _inst_7) (g : ContinuousOrderHom.{u2, u3} β γ _inst_4 _inst_6 _inst_3 _inst_5) (h : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3), Eq.{max (succ u1) (succ u4)} (ContinuousOrderHom.{u1, u4} α δ _inst_2 _inst_8 _inst_1 _inst_7) (ContinuousOrderHom.comp.{u1, u2, u4} α β δ _inst_1 _inst_2 _inst_3 _inst_4 _inst_7 _inst_8 (ContinuousOrderHom.comp.{u2, u3, u4} β γ δ _inst_3 _inst_4 _inst_5 _inst_6 _inst_7 _inst_8 f g) h) (ContinuousOrderHom.comp.{u1, u3, u4} α γ δ _inst_1 _inst_2 _inst_5 _inst_6 _inst_7 _inst_8 f (ContinuousOrderHom.comp.{u1, u2, u3} α β γ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 g h))
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u2}} {γ : Type.{u4}} {δ : Type.{u3}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u2} β] [_inst_4 : Preorder.{u2} β] [_inst_5 : TopologicalSpace.{u4} γ] [_inst_6 : Preorder.{u4} γ] [_inst_7 : TopologicalSpace.{u3} δ] [_inst_8 : Preorder.{u3} δ] (f : ContinuousOrderHom.{u4, u3} γ δ _inst_6 _inst_8 _inst_5 _inst_7) (g : ContinuousOrderHom.{u2, u4} β γ _inst_4 _inst_6 _inst_3 _inst_5) (h : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3), Eq.{max (succ u1) (succ u3)} (ContinuousOrderHom.{u1, u3} α δ _inst_2 _inst_8 _inst_1 _inst_7) (ContinuousOrderHom.comp.{u1, u2, u3} α β δ _inst_1 _inst_2 _inst_3 _inst_4 _inst_7 _inst_8 (ContinuousOrderHom.comp.{u2, u4, u3} β γ δ _inst_3 _inst_4 _inst_5 _inst_6 _inst_7 _inst_8 f g) h) (ContinuousOrderHom.comp.{u1, u4, u3} α γ δ _inst_1 _inst_2 _inst_5 _inst_6 _inst_7 _inst_8 f (ContinuousOrderHom.comp.{u1, u2, u4} α β γ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 g h))
Case conversion may be inaccurate. Consider using '#align continuous_order_hom.comp_assoc ContinuousOrderHom.comp_assocₓ'. -/
@[simp]
theorem comp_assoc (f : γ →Co δ) (g : β →Co γ) (h : α →Co β) :
    (f.comp g).comp h = f.comp (g.comp h) :=
  rfl
#align continuous_order_hom.comp_assoc ContinuousOrderHom.comp_assoc

/- warning: continuous_order_hom.comp_id -> ContinuousOrderHom.comp_id is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u2} β] [_inst_4 : Preorder.{u2} β] (f : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3), Eq.{max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (ContinuousOrderHom.comp.{u1, u1, u2} α α β _inst_1 _inst_2 _inst_1 _inst_2 _inst_3 _inst_4 f (ContinuousOrderHom.id.{u1} α _inst_1 _inst_2)) f
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : TopologicalSpace.{u2} α] [_inst_2 : Preorder.{u2} α] [_inst_3 : TopologicalSpace.{u1} β] [_inst_4 : Preorder.{u1} β] (f : ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3), Eq.{max (succ u2) (succ u1)} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) (ContinuousOrderHom.comp.{u2, u2, u1} α α β _inst_1 _inst_2 _inst_1 _inst_2 _inst_3 _inst_4 f (ContinuousOrderHom.id.{u2} α _inst_1 _inst_2)) f
Case conversion may be inaccurate. Consider using '#align continuous_order_hom.comp_id ContinuousOrderHom.comp_idₓ'. -/
@[simp]
theorem comp_id (f : α →Co β) : f.comp (ContinuousOrderHom.id α) = f :=
  ext fun a => rfl
#align continuous_order_hom.comp_id ContinuousOrderHom.comp_id

/- warning: continuous_order_hom.id_comp -> ContinuousOrderHom.id_comp is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u2} β] [_inst_4 : Preorder.{u2} β] (f : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3), Eq.{max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (ContinuousOrderHom.comp.{u1, u2, u2} α β β _inst_1 _inst_2 _inst_3 _inst_4 _inst_3 _inst_4 (ContinuousOrderHom.id.{u2} β _inst_3 _inst_4) f) f
but is expected to have type
  forall {α : Type.{u2}} {β : Type.{u1}} [_inst_1 : TopologicalSpace.{u2} α] [_inst_2 : Preorder.{u2} α] [_inst_3 : TopologicalSpace.{u1} β] [_inst_4 : Preorder.{u1} β] (f : ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3), Eq.{max (succ u2) (succ u1)} (ContinuousOrderHom.{u2, u1} α β _inst_2 _inst_4 _inst_1 _inst_3) (ContinuousOrderHom.comp.{u2, u1, u1} α β β _inst_1 _inst_2 _inst_3 _inst_4 _inst_3 _inst_4 (ContinuousOrderHom.id.{u1} β _inst_3 _inst_4) f) f
Case conversion may be inaccurate. Consider using '#align continuous_order_hom.id_comp ContinuousOrderHom.id_compₓ'. -/
@[simp]
theorem id_comp (f : α →Co β) : (ContinuousOrderHom.id β).comp f = f :=
  ext fun a => rfl
#align continuous_order_hom.id_comp ContinuousOrderHom.id_comp

/- warning: continuous_order_hom.cancel_right -> ContinuousOrderHom.cancel_right is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} {γ : Type.{u3}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u2} β] [_inst_4 : Preorder.{u2} β] [_inst_5 : TopologicalSpace.{u3} γ] [_inst_6 : Preorder.{u3} γ] {g₁ : ContinuousOrderHom.{u2, u3} β γ _inst_4 _inst_6 _inst_3 _inst_5} {g₂ : ContinuousOrderHom.{u2, u3} β γ _inst_4 _inst_6 _inst_3 _inst_5} {f : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3}, (Function.Surjective.{succ u1, succ u2} α β (coeFn.{max (succ u1) (succ u2), max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) (fun (_x : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) => α -> β) (ContinuousOrderHom.hasCoeToFun.{u1, u2} α β _inst_1 _inst_2 _inst_3 _inst_4) f)) -> (Iff (Eq.{max (succ u1) (succ u3)} (ContinuousOrderHom.{u1, u3} α γ _inst_2 _inst_6 _inst_1 _inst_5) (ContinuousOrderHom.comp.{u1, u2, u3} α β γ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 g₁ f) (ContinuousOrderHom.comp.{u1, u2, u3} α β γ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 g₂ f)) (Eq.{max (succ u2) (succ u3)} (ContinuousOrderHom.{u2, u3} β γ _inst_4 _inst_6 _inst_3 _inst_5) g₁ g₂))
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u3}} {γ : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u3} β] [_inst_4 : Preorder.{u3} β] [_inst_5 : TopologicalSpace.{u2} γ] [_inst_6 : Preorder.{u2} γ] {g₁ : ContinuousOrderHom.{u3, u2} β γ _inst_4 _inst_6 _inst_3 _inst_5} {g₂ : ContinuousOrderHom.{u3, u2} β γ _inst_4 _inst_6 _inst_3 _inst_5} {f : ContinuousOrderHom.{u1, u3} α β _inst_2 _inst_4 _inst_1 _inst_3}, (Function.Surjective.{succ u1, succ u3} α β (FunLike.coe.{max (succ u1) (succ u3), succ u1, succ u3} (ContinuousOrderHom.{u1, u3} α β _inst_2 _inst_4 _inst_1 _inst_3) α (fun (_x : α) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : α) => β) _x) (ContinuousMapClass.toFunLike.{max u1 u3, u1, u3} (ContinuousOrderHom.{u1, u3} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_1 _inst_3 (ContinuousOrderHomClass.toContinuousMapClass.{max u1 u3, u1, u3} (ContinuousOrderHom.{u1, u3} α β _inst_2 _inst_4 _inst_1 _inst_3) α β _inst_2 _inst_4 _inst_1 _inst_3 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u1, u3} α β _inst_1 _inst_2 _inst_3 _inst_4))) f)) -> (Iff (Eq.{max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α γ _inst_2 _inst_6 _inst_1 _inst_5) (ContinuousOrderHom.comp.{u1, u3, u2} α β γ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 g₁ f) (ContinuousOrderHom.comp.{u1, u3, u2} α β γ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 g₂ f)) (Eq.{max (succ u3) (succ u2)} (ContinuousOrderHom.{u3, u2} β γ _inst_4 _inst_6 _inst_3 _inst_5) g₁ g₂))
Case conversion may be inaccurate. Consider using '#align continuous_order_hom.cancel_right ContinuousOrderHom.cancel_rightₓ'. -/
theorem cancel_right {g₁ g₂ : β →Co γ} {f : α →Co β} (hf : Surjective f) :
    g₁.comp f = g₂.comp f ↔ g₁ = g₂ :=
  ⟨fun h => ext <| hf.forall.2 <| FunLike.ext_iff.1 h, congr_arg _⟩
#align continuous_order_hom.cancel_right ContinuousOrderHom.cancel_right

/- warning: continuous_order_hom.cancel_left -> ContinuousOrderHom.cancel_left is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} {β : Type.{u2}} {γ : Type.{u3}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u2} β] [_inst_4 : Preorder.{u2} β] [_inst_5 : TopologicalSpace.{u3} γ] [_inst_6 : Preorder.{u3} γ] {g : ContinuousOrderHom.{u2, u3} β γ _inst_4 _inst_6 _inst_3 _inst_5} {f₁ : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3} {f₂ : ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3}, (Function.Injective.{succ u2, succ u3} β γ (coeFn.{max (succ u2) (succ u3), max (succ u2) (succ u3)} (ContinuousOrderHom.{u2, u3} β γ _inst_4 _inst_6 _inst_3 _inst_5) (fun (_x : ContinuousOrderHom.{u2, u3} β γ _inst_4 _inst_6 _inst_3 _inst_5) => β -> γ) (ContinuousOrderHom.hasCoeToFun.{u2, u3} β γ _inst_3 _inst_4 _inst_5 _inst_6) g)) -> (Iff (Eq.{max (succ u1) (succ u3)} (ContinuousOrderHom.{u1, u3} α γ _inst_2 _inst_6 _inst_1 _inst_5) (ContinuousOrderHom.comp.{u1, u2, u3} α β γ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 g f₁) (ContinuousOrderHom.comp.{u1, u2, u3} α β γ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 g f₂)) (Eq.{max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α β _inst_2 _inst_4 _inst_1 _inst_3) f₁ f₂))
but is expected to have type
  forall {α : Type.{u1}} {β : Type.{u3}} {γ : Type.{u2}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_2 : Preorder.{u1} α] [_inst_3 : TopologicalSpace.{u3} β] [_inst_4 : Preorder.{u3} β] [_inst_5 : TopologicalSpace.{u2} γ] [_inst_6 : Preorder.{u2} γ] {g : ContinuousOrderHom.{u3, u2} β γ _inst_4 _inst_6 _inst_3 _inst_5} {f₁ : ContinuousOrderHom.{u1, u3} α β _inst_2 _inst_4 _inst_1 _inst_3} {f₂ : ContinuousOrderHom.{u1, u3} α β _inst_2 _inst_4 _inst_1 _inst_3}, (Function.Injective.{succ u3, succ u2} β γ (FunLike.coe.{max (succ u3) (succ u2), succ u3, succ u2} (ContinuousOrderHom.{u3, u2} β γ _inst_4 _inst_6 _inst_3 _inst_5) β (fun (_x : β) => (fun (x._@.Mathlib.Topology.ContinuousFunction.Basic._hyg.699 : β) => γ) _x) (ContinuousMapClass.toFunLike.{max u3 u2, u3, u2} (ContinuousOrderHom.{u3, u2} β γ _inst_4 _inst_6 _inst_3 _inst_5) β γ _inst_3 _inst_5 (ContinuousOrderHomClass.toContinuousMapClass.{max u3 u2, u3, u2} (ContinuousOrderHom.{u3, u2} β γ _inst_4 _inst_6 _inst_3 _inst_5) β γ _inst_4 _inst_6 _inst_3 _inst_5 (ContinuousOrderHom.instContinuousOrderHomClassContinuousOrderHom.{u3, u2} β γ _inst_3 _inst_4 _inst_5 _inst_6))) g)) -> (Iff (Eq.{max (succ u1) (succ u2)} (ContinuousOrderHom.{u1, u2} α γ _inst_2 _inst_6 _inst_1 _inst_5) (ContinuousOrderHom.comp.{u1, u3, u2} α β γ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 g f₁) (ContinuousOrderHom.comp.{u1, u3, u2} α β γ _inst_1 _inst_2 _inst_3 _inst_4 _inst_5 _inst_6 g f₂)) (Eq.{max (succ u1) (succ u3)} (ContinuousOrderHom.{u1, u3} α β _inst_2 _inst_4 _inst_1 _inst_3) f₁ f₂))
Case conversion may be inaccurate. Consider using '#align continuous_order_hom.cancel_left ContinuousOrderHom.cancel_leftₓ'. -/
theorem cancel_left {g : β →Co γ} {f₁ f₂ : α →Co β} (hg : Injective g) :
    g.comp f₁ = g.comp f₂ ↔ f₁ = f₂ :=
  ⟨fun h => ext fun a => hg <| by rw [← comp_apply, h, comp_apply], congr_arg _⟩
#align continuous_order_hom.cancel_left ContinuousOrderHom.cancel_left

instance : Preorder (α →Co β) :=
  Preorder.lift (coeFn : (α →Co β) → α → β)

end Preorder

instance [PartialOrder β] : PartialOrder (α →Co β) :=
  PartialOrder.lift _ FunLike.coe_injective

end ContinuousOrderHom


/-
Copyright (c) 2022 Damiano Testa. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Damiano Testa

! This file was ported from Lean 3 source module algebra.monoid_algebra.degree
! leanprover-community/mathlib commit f694c7dead66f5d4c80f446c796a5aad14707f0e
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathlib.Algebra.MonoidAlgebra.Support

/-!
# Lemmas about the `sup` and `inf` of the support of `AddMonoidAlgebra`

## TODO
The current plan is to state and prove lemmas about `Finset.sup (Finsupp.support f) D` with a
"generic" degree/weight function `D` from the grading Type `A` to a somewhat ordered Type `B`.

Next, the general lemmas get specialized for some yet-to-be-defined `degree`s.
-/

variable {R A T B ι : Type _}

namespace AddMonoidAlgebra

open Classical BigOperators

/-! ### Results about the `Finset.sup` and `Finset.inf` of `Finsupp.support` -/

section GeneralResultsAssumingSemilatticeSup

variable [SemilatticeSup B] [OrderBot B] [SemilatticeInf T] [OrderTop T]

section Semiring

variable [Semiring R]

section ExplicitDegrees

/-!

In this section, we use `degb` and `degt` to denote "degree functions" on `A` with values in
a type with *b*ot or *t*op respectively.
-/

variable (degb : A → B) (degt : A → T) (f g : AddMonoidAlgebra R A)

theorem sup_support_add_le : (f + g).support.sup degb ≤ f.support.sup degb ⊔ g.support.sup degb :=
  (Finset.sup_mono Finsupp.support_add).trans_eq Finset.sup_union
#align add_monoid_algebra.sup_support_add_le AddMonoidAlgebra.sup_support_add_le

theorem le_inf_support_add : f.support.inf degt ⊓ g.support.inf degt ≤ (f + g).support.inf degt :=
  sup_support_add_le (fun a : A => OrderDual.toDual (degt a)) f g
#align add_monoid_algebra.le_inf_support_add AddMonoidAlgebra.le_inf_support_add

end ExplicitDegrees

section AddOnly

variable [Add A] [Add B] [Add T] [CovariantClass B B (· + ·) (· ≤ ·)]
  [CovariantClass B B (Function.swap (· + ·)) (· ≤ ·)] [CovariantClass T T (· + ·) (· ≤ ·)]
  [CovariantClass T T (Function.swap (· + ·)) (· ≤ ·)]

theorem sup_support_mul_le {degb : A → B} (degbm : ∀ {a b}, degb (a + b) ≤ degb a + degb b)
    (f g : AddMonoidAlgebra R A) :
    (f * g).support.sup degb ≤ f.support.sup degb + g.support.sup degb := by
  refine' (Finset.sup_mono <| support_mul _ _).trans _
  simp_rw [Finset.sup_bunionᵢ, Finset.sup_singleton]
  refine' Finset.sup_le fun fd fds => Finset.sup_le fun gd gds => degbm.trans <| add_le_add _ _ <;>
    exact Finset.le_sup ‹_›
#align add_monoid_algebra.sup_support_mul_le AddMonoidAlgebra.sup_support_mul_le

theorem le_inf_support_mul {degt : A → T} (degtm : ∀ {a b}, degt a + degt b ≤ degt (a + b))
    (f g : AddMonoidAlgebra R A) :
    f.support.inf degt + g.support.inf degt ≤ (f * g).support.inf degt := by
    refine' OrderDual.ofDual_le_ofDual.mpr <| sup_support_mul_le (_) f g
    intros a b
    exact OrderDual.ofDual_le_ofDual.mp degtm
#align add_monoid_algebra.le_inf_support_mul AddMonoidAlgebra.le_inf_support_mul

end AddOnly

section AddMonoids

variable [AddMonoid A] [AddMonoid B] [CovariantClass B B (· + ·) (· ≤ ·)]
  [CovariantClass B B (Function.swap (· + ·)) (· ≤ ·)] [AddMonoid T]
  [CovariantClass T T (· + ·) (· ≤ ·)] [CovariantClass T T (Function.swap (· + ·)) (· ≤ ·)]
  {degb : A → B} {degt : A → T}

theorem sup_support_list_prod_le (degb0 : degb 0 ≤ 0)
    (degbm : ∀ a b, degb (a + b) ≤ degb a + degb b) :
    ∀ l : List (AddMonoidAlgebra R A),
      l.prod.support.sup degb ≤ (l.map fun f : AddMonoidAlgebra R A => f.support.sup degb).sum
  | [] => by
    rw [List.map_nil, Finset.sup_le_iff, List.prod_nil, List.sum_nil]
    exact fun a ha => by rwa [Finset.mem_singleton.mp (Finsupp.support_single_subset ha)]
  | f::fs => by
    rw [List.prod_cons, List.map_cons, List.sum_cons]
    exact (sup_support_mul_le (@fun a b => degbm a b) _ _).trans
        (add_le_add_left (sup_support_list_prod_le degb0 degbm fs) _)
#align add_monoid_algebra.sup_support_list_prod_le AddMonoidAlgebra.sup_support_list_prod_le

theorem le_inf_support_list_prod (degt0 : 0 ≤ degt 0)
    (degtm : ∀ a b, degt a + degt b ≤ degt (a + b)) (l : List (AddMonoidAlgebra R A)) :
    (l.map fun f : AddMonoidAlgebra R A => f.support.inf degt).sum ≤ l.prod.support.inf degt := by
  refine' OrderDual.ofDual_le_ofDual.mpr _
  refine' sup_support_list_prod_le _ _ l
  · refine' (OrderDual.ofDual_le_ofDual.mp _)
    exact degt0
  · refine' (fun a b => OrderDual.ofDual_le_ofDual.mp _)
    exact degtm a b
#align add_monoid_algebra.le_inf_support_list_prod AddMonoidAlgebra.le_inf_support_list_prod

theorem sup_support_pow_le (degb0 : degb 0 ≤ 0) (degbm : ∀ a b, degb (a + b) ≤ degb a + degb b)
    (n : ℕ) (f : AddMonoidAlgebra R A) : (f ^ n).support.sup degb ≤ n • f.support.sup degb := by
  rw [← List.prod_replicate, ← List.sum_replicate]
  refine' (sup_support_list_prod_le degb0 degbm _).trans_eq _
  rw [List.map_replicate]
#align add_monoid_algebra.sup_support_pow_le AddMonoidAlgebra.sup_support_pow_le

theorem le_inf_support_pow (degt0 : 0 ≤ degt 0) (degtm : ∀ a b, degt a + degt b ≤ degt (a + b))
    (n : ℕ) (f : AddMonoidAlgebra R A) : n • f.support.inf degt ≤ (f ^ n).support.inf degt := by
  refine' OrderDual.ofDual_le_ofDual.mpr <| sup_support_pow_le (OrderDual.ofDual_le_ofDual.mp _)
      (fun a b => OrderDual.ofDual_le_ofDual.mp _) n f
  exact degt0
  exact degtm _ _
#align add_monoid_algebra.le_inf_support_pow AddMonoidAlgebra.le_inf_support_pow

end AddMonoids

end Semiring

section CommutativeLemmas

variable [CommSemiring R] [AddCommMonoid A] [AddCommMonoid B] [CovariantClass B B (· + ·) (· ≤ ·)]
  [CovariantClass B B (Function.swap (· + ·)) (· ≤ ·)] [AddCommMonoid T]
  [CovariantClass T T (· + ·) (· ≤ ·)] [CovariantClass T T (Function.swap (· + ·)) (· ≤ ·)]
  {degb : A → B} {degt : A → T}

theorem sup_support_multiset_prod_le (degb0 : degb 0 ≤ 0)
    (degbm : ∀ a b, degb (a + b) ≤ degb a + degb b) (m : Multiset (AddMonoidAlgebra R A)) :
    m.prod.support.sup degb ≤ (m.map fun f : AddMonoidAlgebra R A => f.support.sup degb).sum := by
  induction m using Quot.inductionOn
  rw [Multiset.quot_mk_to_coe'', Multiset.coe_map, Multiset.coe_sum, Multiset.coe_prod]
  exact sup_support_list_prod_le degb0 degbm _
#align add_monoid_algebra.sup_support_multiset_prod_le AddMonoidAlgebra.sup_support_multiset_prod_le

theorem le_inf_support_multiset_prod (degt0 : 0 ≤ degt 0)
    (degtm : ∀ a b, degt a + degt b ≤ degt (a + b)) (m : Multiset (AddMonoidAlgebra R A)) :
    (m.map fun f : AddMonoidAlgebra R A => f.support.inf degt).sum ≤ m.prod.support.inf degt := by
  refine' OrderDual.ofDual_le_ofDual.mpr <|
    sup_support_multiset_prod_le (OrderDual.ofDual_le_ofDual.mp _)
      (fun a b => OrderDual.ofDual_le_ofDual.mp (_)) m
  exact degt0
  exact degtm _ _
#align add_monoid_algebra.le_inf_support_multiset_prod AddMonoidAlgebra.le_inf_support_multiset_prod

theorem sup_support_finset_prod_le (degb0 : degb 0 ≤ 0)
    (degbm : ∀ a b, degb (a + b) ≤ degb a + degb b) (s : Finset ι) (f : ι → AddMonoidAlgebra R A) :
    (∏ i in s, f i).support.sup degb ≤ ∑ i in s, (f i).support.sup degb :=
  (sup_support_multiset_prod_le degb0 degbm _).trans_eq <| congr_arg _ <| Multiset.map_map _ _ _
#align add_monoid_algebra.sup_support_finset_prod_le AddMonoidAlgebra.sup_support_finset_prod_le

theorem le_inf_support_finset_prod (degt0 : 0 ≤ degt 0)
    (degtm : ∀ a b, degt a + degt b ≤ degt (a + b)) (s : Finset ι) (f : ι → AddMonoidAlgebra R A) :
    (∑ i in s, (f i).support.inf degt) ≤ (∏ i in s, f i).support.inf degt :=
  le_of_eq_of_le (by rw [Multiset.map_map]; rfl) (le_inf_support_multiset_prod degt0 degtm _)
#align add_monoid_algebra.le_inf_support_finset_prod AddMonoidAlgebra.le_inf_support_finset_prod

end CommutativeLemmas

end GeneralResultsAssumingSemilatticeSup

end AddMonoidAlgebra


import set_theory.cardinal

-- Cantor’s Theorem

universe u

open cardinal

theorem t063 : ∀(a : cardinal.{u}), a < 2 ^ a
:= cantor


-- import data.finset.basic
-- import data.finset.lattice
-- import data.multiset.lattice
-- import topology.compacts
-- import topology.instances.complex
-- import data.int.basic
import data.finset
import tactic
import data.int.basic

/-
  Diamond - Shurman
  exercise 4.9.2 (a)
-/

/--
  For each integer m, we define the set

      { n ∈ `ℤᵈ   | max(n₁, ..., n_d) ≤ N }
-/
definition S' (N: ℕ ) (d: ℕ) : finset (fin d → ℤ) :=

  fintype.pi_finset (λ a, finset.Ico_ℤ (- N) (N+1))

/--
  For each integer m, we define the set

      { n ∈ `ℤᵈ   | max(|n₁|, ..., |n_d|) = N}
-/
definition S (N: ℕ ) (d: ℕ) : finset (fin d → ℤ) :=
    finset.filter (λ n, ∃ (i : fin d), (n i).nat_abs = N) (S' N d)
     -- {n | ∀ i, (n i).nat_abs ≤ m  ∧ ∃ (i : fin d), n i = m}

definition S_aux (N: ℕ)(d:ℕ)(i: fin d): finset (fin d → ℤ) :=
  fintype.pi_finset (λ a, if a = i then {-N, N} else finset.Ico_ℤ (- N) (N+1))
  --finset.filter (λ n, (n i).nat_abs = N) (S' N d)

lemma S_is_union (N: ℕ)(d: ℕ) : S N d =  finset.bind finset.univ (λ i, S_aux N d i):=
  begin
    ext1,
    split,
    {intro hx,
    norm_num at *,
    unfold S at *,
    simp at hx,
    cases hx,
    unfold S_aux,
    cases hx_right,
    use hx_right_w,
    simp,
    intro,
    split_ifs,
    unfold S' at *,
    norm_num,
    rw or_comm,
    rw ←hx_right_h,
    norm_num at *,
    specialize hx_left a_1,
    rw h,
    exact int.nat_abs_eq _,
    unfold S' at *,
    norm_num at *,
    specialize hx_left a_1,
    exact hx_left,
    },
    intro hx,
    unfold S_aux at *,
    unfold S,
    simp at *,
    split,
    unfold S',
    cases hx,
    norm_num,
    intro a1,
    specialize hx_h a1,
    by_cases a1=hx_w,
    --finish,
    split_ifs at *,
    norm_num at hx_h,
    cases hx_h,
    split,
    finish,
    linarith,
    split,
    linarith,
    linarith,
    split_ifs at *,
    norm_num at *,
    cases hx_h,
    split,
    linarith,
    linarith,
    cases hx,
    use hx_w,
    specialize hx_h hx_w,
    split_ifs at *,
    norm_num at hx_h,
    cases hx_h,
    finish,
    finish,
    norm_num at hx_h,
    cases hx_h,
    finish,
    finish,
  end

lemma S_aux_card (N: ℕ)(d: ℕ)(i: fin d): (S_aux N d i).card ≤ 2 * (2 * N + 1) ^ (d -1) :=
begin
    unfold S_aux,
    --norm_num,
    have : (λ (a : fin d), (ite (a = i) {-↑N, ↑N} (finset.Ico_ℤ (-↑N) (↑N + 1))).card) =
           λ (a : fin d), (ite (a = i) ({-↑N, ↑N}: finset ℤ).card (finset.Ico_ℤ (-↑N) (↑N + 1)).card),
      ext,
      split_ifs;
      refl,
    sorry
  /-  norm_num,
    rw this,
    simp,
    cases N,
    simp, -- N = 0 ⇒ {-N , N}.card = 1
    simp, -- N ≠ 0 ⇒ {-N , N}.card = 2
    have : (-1: ℤ) + -N ≠  ↑N + 1,
      linarith,
    have : ({-1 + -↑N, ↑N + 1}: finset ℤ).card = 2,
     finish,
    rw this,
    ring,
    have : finset.univ.prod (λ (x : fin d), ite (x = i) 2 ((2:ℤ) * ↑N + 3).to_nat)
              = (finset.prod (finset.filter (λ (x : fin d), (x = i)) finset.univ) (λ a,2))
              * (finset.prod (finset.filter (λ (x : fin d), (x ≠ i)) finset.univ) (λ a,((2:ℤ) * ↑N + 3).to_nat)),
    {
      apply finset.prod_apply_ite _ _ (λ x, x),--(λ a,2)(λ a,((2:ℤ) * ↑N + 3).to_nat) (λ x,x),
    },
    rw this,
    simp,
    cases d,
    exact dec_trivial,
    refine le_of_eq _,
    congr,
    have : (finset.filter (λ (x : fin d.succ), x = i) finset.univ) = ({i}: finset (fin d.succ)),
      ext1,
      split,{
      norm_num},
      {
      intro ha,
      cases ha,
      norm_num,
      exact ha,
      norm_num,
      exfalso,
      cases ha,
      },
    rw this,
    norm_num,
    have : (finset.filter (λ (x : fin d.succ), x ≠ i) finset.univ) = ((finset.erase (finset.univ :finset (fin d.succ)) i)),
      ext1,
      split,{
      norm_num},
      {
      intro ha,
      norm_num at ha,
      norm_num,
      exact ha,
      },
    rw this,
    rw finset.card_erase_of_mem,
    norm_num,
    norm_num,
    -/
end

open_locale big_operators

open finset

lemma S_card_le (N: ℕ)(d: ℕ) :  finset.card (S N d) ≤ 2* d * (2 * N + 1) ^ (d -1) :=
begin
  calc finset.card (S N d) = finset.card (finset.bind finset.univ (λ i, S_aux N d i)) : by rw S_is_union N d
                  ...      ≤ ∑ i,           finset.card (S_aux N d i)                 : card_bind_le
                  ...      ≤  ∑ i:fin d,     2*(2*N+1)^(d-1)                          : sorry -- sum_le_sum (λ x hx, S_aux_card N d x)
                  ...      = 2*d*(2*N+1)^(d-1)                                        : by finish
end


/-
Copyright (c) 2017 Johannes Hölzl. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Johannes Hölzl, Mario Carneiro

! This file was ported from Lean 3 source module topology.order
! leanprover-community/mathlib commit bcfa726826abd57587355b4b5b7e78ad6527b7e4
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathlib.Topology.Basic

/-!
# Ordering on topologies and (co)induced topologies

Topologies on a fixed type `α` are ordered, by reverse inclusion.  That is, for topologies `t₁` and
`t₂` on `α`, we write `t₁ ≤ t₂` if every set open in `t₂` is also open in `t₁`.  (One also calls
`t₁` *finer* than `t₂`, and `t₂` *coarser* than `t₁`.)

Any function `f : α → β` induces

* `TopologicalSpace.induced f : TopologicalSpace β → TopologicalSpace α`;
* `TopologicalSpace.coinduced f : TopologicalSpace α → TopologicalSpace β`.

Continuity, the ordering on topologies and (co)induced topologies are related as follows:

* The identity map `(α, t₁) → (α, t₂)` is continuous iff `t₁ ≤ t₂`.
* A map `f : (α, t) → (β, u)` is continuous
  * iff `t ≤ TopologicalSpace.induced f u` (`continuous_iff_le_induced`)
  * iff `TopologicalSpace.coinduced f t ≤ u` (`continuous_iff_coinduced_le`).

Topologies on `α` form a complete lattice, with `⊥` the discrete topology and `⊤` the indiscrete
topology.

For a function `f : α → β`, `(TopologicalSpace.coinduced f, TopologicalSpace.induced f)` is a Galois
connection between topologies on `α` and topologies on `β`.

## Implementation notes

There is a Galois insertion between topologies on `α` (with the inclusion ordering) and all
collections of sets in `α`. The complete lattice structure on topologies on `α` is defined as the
reverse of the one obtained via this Galois insertion. More precisely, we use the corresponding
Galois coinsertion between topologies on `α` (with the reversed inclusion ordering) and collections
of sets in `α` (with the reversed inclusion ordering).

## Tags

finer, coarser, induced topology, coinduced topology
-/

open Function Set Filter Topology

universe u v w

namespace TopologicalSpace

variable {α : Type u}

/-- The open sets of the least topology containing a collection of basic sets. -/
inductive GenerateOpen (g : Set (Set α)) : Set α → Prop
  | basic : ∀ s ∈ g, GenerateOpen g s
  | univ : GenerateOpen g univ
  | inter : ∀ s t, GenerateOpen g s → GenerateOpen g t → GenerateOpen g (s ∩ t)
  | unionₛ : ∀ S : Set (Set α), (∀ s ∈ S, GenerateOpen g s) → GenerateOpen g (⋃₀ S)
#align topological_space.generate_open TopologicalSpace.GenerateOpen

/-- The smallest topological space containing the collection `g` of basic sets -/
def generateFrom (g : Set (Set α)) : TopologicalSpace α where
  IsOpen := GenerateOpen g
  isOpen_univ := GenerateOpen.univ
  isOpen_inter := GenerateOpen.inter
  isOpen_unionₛ := GenerateOpen.unionₛ
#align topological_space.generate_from TopologicalSpace.generateFrom

theorem isOpen_generateFrom_of_mem {g : Set (Set α)} {s : Set α} (hs : s ∈ g) :
    IsOpen[generateFrom g] s :=
  GenerateOpen.basic s hs
#align topological_space.is_open_generate_from_of_mem TopologicalSpace.isOpen_generateFrom_of_mem

theorem nhds_generateFrom {g : Set (Set α)} {a : α} :
    @nhds α (generateFrom g) a = ⨅ s ∈ { s | a ∈ s ∧ s ∈ g }, 𝓟 s := by
  letI := generateFrom g
  rw [nhds_def]
  refine le_antisymm (binfᵢ_mono fun s ⟨as, sg⟩ => ⟨as, .basic _ sg⟩) ?_
  refine le_infᵢ₂ fun s ⟨ha, hs⟩ => ?_; clear ‹s ∈ { s | a ∈ s ∧ IsOpen s }›
  induction hs
  case basic hs => exact infᵢ₂_le _ ⟨ha, hs⟩
  case univ => exact le_top.trans_eq principal_univ.symm
  case inter hs ht => exact (le_inf (hs ha.1) (ht ha.2)).trans_eq inf_principal
  case unionₛ _S hS =>
    let ⟨t, htS, hat⟩ := ha
    exact (hS t htS hat).trans (principal_mono.2 <| subset_unionₛ_of_mem htS)
#align topological_space.nhds_generate_from TopologicalSpace.nhds_generateFrom

theorem tendsto_nhds_generateFrom {β : Type _} {m : α → β} {f : Filter α} {g : Set (Set β)} {b : β}
    (h : ∀ s ∈ g, b ∈ s → m ⁻¹' s ∈ f) : Tendsto m f (@nhds β (generateFrom g) b) := by
  rw [nhds_generateFrom]
  exact tendsto_infᵢ.2 fun s => tendsto_infᵢ.2 fun ⟨hbs, hsg⟩ => tendsto_principal.2 <| h s hsg hbs
#align topological_space.tendsto_nhds_generate_from TopologicalSpace.tendsto_nhds_generateFrom

/-- Construct a topology on α given the filter of neighborhoods of each point of α. -/
protected def mkOfNhds (n : α → Filter α) : TopologicalSpace α where
  IsOpen s := ∀ a ∈ s, s ∈ n a
  isOpen_univ _ _ := univ_mem
  isOpen_inter := fun _s _t hs ht x ⟨hxs, hxt⟩ => inter_mem (hs x hxs) (ht x hxt)
  isOpen_unionₛ := fun _s hs _a ⟨x, hx, hxa⟩ =>
    mem_of_superset (hs x hx _ hxa) (subset_unionₛ_of_mem hx)
#align topological_space.mk_of_nhds TopologicalSpace.mkOfNhds

theorem nhds_mkOfNhds (n : α → Filter α) (a : α) (h₀ : pure ≤ n)
    (h₁ : ∀ a s, s ∈ n a → ∃ t ∈ n a, t ⊆ s ∧ ∀ a' ∈ t, s ∈ n a') :
    @nhds α (TopologicalSpace.mkOfNhds n) a = n a := by
  letI := TopologicalSpace.mkOfNhds n
  apply le_antisymm <;> intros s hs
  · have h₀ : { b | s ∈ n b } ⊆ s := fun b hb => mem_pure.1 <| h₀ b hb
    have h₁ : { b | s ∈ n b } ∈ 𝓝 a := by
      refine' IsOpen.mem_nhds (fun b (hb : s ∈ n b) => _) hs
      rcases h₁ _ _ hb with ⟨t, ht, -, h⟩
      exact mem_of_superset ht h
    exact mem_of_superset h₁ h₀
  · rcases mem_nhds_iff.1 hs with ⟨t, hts, ht, hat⟩
    exact (n a).sets_of_superset (ht _ hat) hts
#align topological_space.nhds_mk_of_nhds TopologicalSpace.nhds_mkOfNhds

theorem nhds_mkOfNhds_single [DecidableEq α] {a₀ : α} {l : Filter α} (h : pure a₀ ≤ l) (b : α) :
    @nhds α (TopologicalSpace.mkOfNhds (update pure a₀ l)) b =
      (update pure a₀ l : α → Filter α) b := by
  refine' nhds_mkOfNhds _ _ (le_update_iff.mpr ⟨h, fun _ _ => le_rfl⟩) fun a s hs => _
  rcases eq_or_ne a a₀ with (rfl | ha)
  · refine' ⟨s, hs, Subset.rfl, fun b hb => _⟩
    rcases eq_or_ne b a with (rfl | hb)
    · exact hs
    · rwa [update_noteq hb]
  · have hs' := hs
    rw [update_noteq ha] at hs⊢
    exact ⟨{a}, rfl, singleton_subset_iff.mpr hs, forall_eq.2 hs'⟩
#align topological_space.nhds_mk_of_nhds_single TopologicalSpace.nhds_mkOfNhds_single

theorem nhds_mkOfNhds_filterBasis (B : α → FilterBasis α) (a : α) (h₀ : ∀ (x), ∀ n ∈ B x, x ∈ n)
    (h₁ : ∀ (x), ∀ n ∈ B x, ∃ n₁ ∈ B x, n₁ ⊆ n ∧ ∀ x' ∈ n₁, ∃ n₂ ∈ B x', n₂ ⊆ n) :
    @nhds α (TopologicalSpace.mkOfNhds fun x => (B x).filter) a = (B a).filter := by
  rw [TopologicalSpace.nhds_mkOfNhds] <;> intro x n hn <;>
    obtain ⟨m, hm₁, hm₂⟩ := (B x).mem_filter_iff.mp hn
  · exact hm₂ (h₀ _ _ hm₁)
  · obtain ⟨n₁, hn₁, hn₂, hn₃⟩ := h₁ x m hm₁
    refine'
      ⟨n₁, (B x).mem_filter_of_mem hn₁, hn₂.trans hm₂, fun x' hx' => (B x').mem_filter_iff.mp _⟩
    obtain ⟨n₂, hn₄, hn₅⟩ := hn₃ x' hx'
    exact ⟨n₂, hn₄, hn₅.trans hm₂⟩
#align topological_space.nhds_mk_of_nhds_filter_basis TopologicalSpace.nhds_mkOfNhds_filterBasis

section Lattice

variable {α : Type u} {β : Type v}

/-- The ordering on topologies on the type `α`. `t ≤ s` if every set open in `s` is also open in `t`
(`t` is finer than `s`). -/
instance : PartialOrder (TopologicalSpace α) :=
  { PartialOrder.lift (fun t => OrderDual.toDual IsOpen[t]) (fun _ _ => topologicalSpace_eq) with
    le := fun s t => ∀ U, IsOpen[t] U → IsOpen[s] U }

protected theorem le_def {α} {t s : TopologicalSpace α} : t ≤ s ↔ IsOpen[s] ≤ IsOpen[t] :=
  Iff.rfl
#align topological_space.le_def TopologicalSpace.le_def

theorem le_generateFrom_iff_subset_isOpen {g : Set (Set α)} {t : TopologicalSpace α} :
    t ≤ generateFrom g ↔ g ⊆ { s | IsOpen[t] s } :=
  ⟨fun ht s hs => ht _ <| .basic s hs, fun hg _s hs =>
    hs.recOn (fun _ h => hg h) isOpen_univ (fun _ _ _ _ => IsOpen.inter) fun _ _ => isOpen_unionₛ⟩
#align topological_space.le_generate_from_iff_subset_is_open TopologicalSpace.le_generateFrom_iff_subset_isOpen

/-- If `s` equals the collection of open sets in the topology it generates, then `s` defines a
topology. -/
protected def mkOfClosure (s : Set (Set α)) (hs : { u | GenerateOpen s u } = s) :
    TopologicalSpace α where
  IsOpen u := u ∈ s
  isOpen_univ := hs ▸ TopologicalSpace.GenerateOpen.univ
  isOpen_inter := hs ▸ TopologicalSpace.GenerateOpen.inter
  isOpen_unionₛ := hs ▸ TopologicalSpace.GenerateOpen.unionₛ
#align topological_space.mk_of_closure TopologicalSpace.mkOfClosure

theorem mkOfClosure_sets {s : Set (Set α)} {hs : { u | GenerateOpen s u } = s} :
    TopologicalSpace.mkOfClosure s hs = generateFrom s :=
  topologicalSpace_eq hs.symm
#align topological_space.mk_of_closure_sets TopologicalSpace.mkOfClosure_sets

theorem gc_generateFrom (α) :
    GaloisConnection (fun t : TopologicalSpace α => OrderDual.toDual { s | IsOpen[t] s })
      (generateFrom ∘ OrderDual.ofDual) := fun _ _ =>
  le_generateFrom_iff_subset_isOpen.symm

/-- The Galois coinsertion between `TopologicalSpace α` and `(Set (Set α))ᵒᵈ` whose lower part sends
  a topology to its collection of open subsets, and whose upper part sends a collection of subsets
  of `α` to the topology they generate. -/
def gciGenerateFrom (α : Type _) :
    GaloisCoinsertion (fun t : TopologicalSpace α => OrderDual.toDual { s | IsOpen[t] s })
      (generateFrom ∘ OrderDual.ofDual) where
  gc := gc_generateFrom α
  u_l_le _ s hs := TopologicalSpace.GenerateOpen.basic s hs
  choice g hg := TopologicalSpace.mkOfClosure g
    (Subset.antisymm hg <| le_generateFrom_iff_subset_isOpen.1 <| le_rfl)
  choice_eq _ _ := mkOfClosure_sets
#align gi_generate_from TopologicalSpace.gciGenerateFrom

/-- Topologies on `α` form a complete lattice, with `⊥` the discrete topology
  and `⊤` the indiscrete topology. The infimum of a collection of topologies
  is the topology generated by all their open sets, while the supremum is the
  topology whose open sets are those sets open in every member of the collection. -/
instance : CompleteLattice (TopologicalSpace α) := (gciGenerateFrom α).liftCompleteLattice

@[mono]
theorem generateFrom_anti {α} {g₁ g₂ : Set (Set α)} (h : g₁ ⊆ g₂) :
    generateFrom g₂ ≤ generateFrom g₁ :=
  (gc_generateFrom _).monotone_u h
#align topological_space.generate_from_anti TopologicalSpace.generateFrom_anti

theorem generateFrom_setOf_isOpen (t : TopologicalSpace α) :
    generateFrom { s | IsOpen[t] s } = t :=
  (gciGenerateFrom α).u_l_eq t
#align topological_space.generate_from_set_of_is_open TopologicalSpace.generateFrom_setOf_isOpen

theorem leftInverse_generateFrom :
    LeftInverse generateFrom fun t : TopologicalSpace α => { s | IsOpen[t] s } :=
  (gciGenerateFrom α).u_l_leftInverse
#align topological_space.left_inverse_generate_from TopologicalSpace.leftInverse_generateFrom

theorem generateFrom_surjective : Surjective (generateFrom : Set (Set α) → TopologicalSpace α) :=
  (gciGenerateFrom α).u_surjective
#align topological_space.generate_from_surjective TopologicalSpace.generateFrom_surjective

theorem setOf_isOpen_injective : Injective fun t : TopologicalSpace α => { s | IsOpen[t] s } :=
  (gciGenerateFrom α).l_injective
#align topological_space.set_of_is_open_injective TopologicalSpace.setOf_isOpen_injective

end Lattice

end TopologicalSpace

section Lattice

variable {t t₁ t₂ : TopologicalSpace α} {s : Set α}

theorem IsOpen.mono (hs : IsOpen[t₂] s) (h : t₁ ≤ t₂) : IsOpen[t₁] s := h s hs
#align is_open.mono IsOpen.mono

theorem IsClosed.mono (hs : IsClosed[t₂] s) (h : t₁ ≤ t₂) : IsClosed[t₁] s :=
  (@isOpen_compl_iff α t₁ s).mp <| hs.isOpen_compl.mono h
#align is_closed.mono IsClosed.mono

theorem isOpen_implies_isOpen_iff : (∀ s, IsOpen[t₁] s → IsOpen[t₂] s) ↔ t₂ ≤ t₁ :=
  Iff.rfl
#align is_open_implies_is_open_iff isOpen_implies_isOpen_iff

/-- The only open sets in the indiscrete topology are the empty set and the whole space. -/
theorem TopologicalSpace.isOpen_top_iff {α} (U : Set α) : IsOpen[⊤] U ↔ U = ∅ ∨ U = univ :=
  ⟨fun h => by
    induction h
    case basic h => exact False.elim h
    case univ => exact .inr rfl
    case inter h₁ h₂ =>
      rcases h₁ with (rfl | rfl) <;> rcases h₂ with (rfl | rfl) <;> simp
    case unionₛ _ ih => exact unionₛ_mem_empty_univ ih,
    by
      rintro (rfl | rfl)
      exacts [@isOpen_empty _ ⊤, @isOpen_univ _ ⊤]⟩
#align topological_space.is_open_top_iff TopologicalSpace.isOpen_top_iff

/-- A topological space is discrete if every set is open, that is,
  its topology equals the discrete topology `⊥`. -/
class DiscreteTopology (α : Type _) [t : TopologicalSpace α] : Prop where
  /-- The `TopologicalSpace` structure on a type with discrete topology is equal to `⊥`. -/
  eq_bot : t = ⊥
#align discrete_topology DiscreteTopology

theorem discreteTopology_bot (α : Type _) : @DiscreteTopology α ⊥ :=
  @DiscreteTopology.mk α ⊥ rfl
#align discrete_topology_bot discreteTopology_bot

@[simp]
theorem isOpen_discrete [TopologicalSpace α] [DiscreteTopology α] (s : Set α) : IsOpen s :=
  (@DiscreteTopology.eq_bot α _).symm ▸ trivial
#align is_open_discrete isOpen_discrete

@[simp]
theorem isClosed_discrete [TopologicalSpace α] [DiscreteTopology α] (s : Set α) : IsClosed s :=
  ⟨isOpen_discrete _⟩
#align is_closed_discrete isClosed_discrete

@[nontriviality, continuity]
theorem continuous_of_discreteTopology [TopologicalSpace α] [DiscreteTopology α]
    [TopologicalSpace β] {f : α → β} : Continuous f :=
  continuous_def.2 fun _ _ => isOpen_discrete _
#align continuous_of_discrete_topology continuous_of_discreteTopology

@[simp]
theorem nhds_discrete (α : Type _) [TopologicalSpace α] [DiscreteTopology α] : @nhds α _ = pure :=
  le_antisymm (fun _ s hs => (isOpen_discrete s).mem_nhds hs) pure_le_nhds
#align nhds_discrete nhds_discrete

theorem mem_nhds_discrete [TopologicalSpace α] [DiscreteTopology α] {x : α} {s : Set α} :
    s ∈ 𝓝 x ↔ x ∈ s := by rw [nhds_discrete, mem_pure]
#align mem_nhds_discrete mem_nhds_discrete

theorem le_of_nhds_le_nhds (h : ∀ x, @nhds α t₁ x ≤ @nhds α t₂ x) : t₁ ≤ t₂ := fun s => by
  rw [@isOpen_iff_mem_nhds _ t₁, @isOpen_iff_mem_nhds α t₂]
  exact fun hs a ha => h _ (hs _ ha)
#align le_of_nhds_le_nhds le_of_nhds_le_nhds

theorem eq_of_nhds_eq_nhds (h : ∀ x, @nhds α t₁ x = @nhds α t₂ x) : t₁ = t₂ :=
  le_antisymm (le_of_nhds_le_nhds fun x => (h x).le)
    (le_of_nhds_le_nhds fun x => (h x).ge)
#align eq_of_nhds_eq_nhds eq_of_nhds_eq_nhds

theorem eq_bot_of_singletons_open {t : TopologicalSpace α} (h : ∀ x, IsOpen[t] {x}) : t = ⊥ :=
  bot_unique fun s _ => bunionᵢ_of_singleton s ▸ isOpen_bunionᵢ fun x _ => h x
#align eq_bot_of_singletons_open eq_bot_of_singletons_open

theorem forall_open_iff_discrete {X : Type _} [TopologicalSpace X] :
    (∀ s : Set X, IsOpen s) ↔ DiscreteTopology X :=
  ⟨fun h => ⟨eq_bot_of_singletons_open fun _ => h _⟩, @isOpen_discrete _ _⟩
#align forall_open_iff_discrete forall_open_iff_discrete

theorem singletons_open_iff_discrete {X : Type _} [TopologicalSpace X] :
    (∀ a : X, IsOpen ({a} : Set X)) ↔ DiscreteTopology X :=
  ⟨fun h => ⟨eq_bot_of_singletons_open h⟩, fun a _ => @isOpen_discrete _ _ a _⟩
#align singletons_open_iff_discrete singletons_open_iff_discrete

theorem discreteTopology_iff_singleton_mem_nhds [TopologicalSpace α] :
    DiscreteTopology α ↔ ∀ x : α, {x} ∈ 𝓝 x := by
  simp only [← singletons_open_iff_discrete, isOpen_iff_mem_nhds, mem_singleton_iff, forall_eq]
#align discrete_topology_iff_singleton_mem_nhds discreteTopology_iff_singleton_mem_nhds

/-- This lemma characterizes discrete topological spaces as those whose singletons are
neighbourhoods. -/
theorem discreteTopology_iff_nhds [TopologicalSpace α] :
    DiscreteTopology α ↔ ∀ x : α, 𝓝 x = pure x := by
  simp only [discreteTopology_iff_singleton_mem_nhds, ← nhds_neBot.le_pure_iff, le_pure_iff]
#align discrete_topology_iff_nhds discreteTopology_iff_nhds

theorem discreteTopology_iff_nhds_ne [TopologicalSpace α] :
    DiscreteTopology α ↔ ∀ x : α, 𝓝[≠] x = ⊥ := by
  simp only [discreteTopology_iff_singleton_mem_nhds, nhdsWithin, inf_principal_eq_bot, compl_compl]
#align discrete_topology_iff_nhds_ne discreteTopology_iff_nhds_ne

end Lattice

section GaloisConnection

variable {α β γ : Type _}

/-- Given `f : α → β` and a topology on `β`, the induced topology on `α` is the collection of
  sets that are preimages of some open set in `β`. This is the coarsest topology that
  makes `f` continuous. -/
def TopologicalSpace.induced {α : Type u} {β : Type v} (f : α → β) (t : TopologicalSpace β) :
    TopologicalSpace α where
  IsOpen s := ∃ s', IsOpen s' ∧ f ⁻¹' s' = s
  isOpen_univ := ⟨univ, isOpen_univ, preimage_univ⟩
  isOpen_inter := by
    rintro s₁ s₂ ⟨s'₁, hs₁, rfl⟩ ⟨s'₂, hs₂, rfl⟩
    exact ⟨s'₁ ∩ s'₂, hs₁.inter hs₂, preimage_inter⟩
  isOpen_unionₛ S h := by
    choose! g hgo hfg using h
    refine ⟨⋃ s ∈ S, g s, isOpen_bunionᵢ fun s hs => hgo s hs, ?_⟩
    rw [preimage_unionᵢ₂, unionₛ_eq_bunionᵢ]
    exact unionᵢ₂_congr hfg
#align topological_space.induced TopologicalSpace.induced

theorem isOpen_induced_iff [t : TopologicalSpace β] {s : Set α} {f : α → β} :
    IsOpen[t.induced f] s ↔ ∃ t, IsOpen t ∧ f ⁻¹' t = s :=
  Iff.rfl
#align is_open_induced_iff isOpen_induced_iff

theorem isClosed_induced_iff [t : TopologicalSpace β] {s : Set α} {f : α → β} :
    IsClosed[t.induced f] s ↔ ∃ t, IsClosed t ∧ f ⁻¹' t = s := by
  letI := t.induced f
  simp only [← isOpen_compl_iff, isOpen_induced_iff]
  exact compl_surjective.exists.trans (by simp only [preimage_compl, compl_inj_iff])
#align is_closed_induced_iff isClosed_induced_iff

/-- Given `f : α → β` and a topology on `α`, the coinduced topology on `β` is defined
  such that `s : Set β` is open if the preimage of `s` is open. This is the finest topology that
  makes `f` continuous. -/
def TopologicalSpace.coinduced {α : Type u} {β : Type v} (f : α → β) (t : TopologicalSpace α) :
    TopologicalSpace β where
  IsOpen s := IsOpen[t] (f ⁻¹' s)
  isOpen_univ := t.isOpen_univ
  isOpen_inter s₁ s₂ h₁ h₂ := h₁.inter h₂
  isOpen_unionₛ s h := by simpa only [preimage_unionₛ] using isOpen_bunionᵢ h
#align topological_space.coinduced TopologicalSpace.coinduced

theorem isOpen_coinduced {t : TopologicalSpace α} {s : Set β} {f : α → β} :
    IsOpen[t.coinduced f] s ↔ IsOpen (f ⁻¹' s) :=
  Iff.rfl
#align is_open_coinduced isOpen_coinduced

theorem preimage_nhds_coinduced [TopologicalSpace α] {π : α → β} {s : Set β} {a : α}
    (hs : s ∈ @nhds β (TopologicalSpace.coinduced π ‹_›) (π a)) : π ⁻¹' s ∈ 𝓝 a := by
  letI := TopologicalSpace.coinduced π ‹_›
  rcases mem_nhds_iff.mp hs with ⟨V, hVs, V_op, mem_V⟩
  exact mem_nhds_iff.mpr ⟨π ⁻¹' V, Set.preimage_mono hVs, V_op, mem_V⟩
#align preimage_nhds_coinduced preimage_nhds_coinduced

variable {t t₁ t₂ : TopologicalSpace α} {t' : TopologicalSpace β} {f : α → β} {g : β → α}

theorem Continuous.coinduced_le (h : Continuous[t, t'] f) : t.coinduced f ≤ t' :=
  (@continuous_def α β t t').1 h
#align continuous.coinduced_le Continuous.coinduced_le

theorem coinduced_le_iff_le_induced {f : α → β} {tα : TopologicalSpace α}
    {tβ : TopologicalSpace β} : tα.coinduced f ≤ tβ ↔ tα ≤ tβ.induced f :=
  ⟨fun h _s ⟨_t, ht, hst⟩ => hst ▸ h _ ht, fun h s hs => h _ ⟨s, hs, rfl⟩⟩
#align coinduced_le_iff_le_induced coinduced_le_iff_le_induced

theorem Continuous.le_induced (h : Continuous[t, t'] f) : t ≤ t'.induced f :=
  coinduced_le_iff_le_induced.1 h.coinduced_le
#align continuous.le_induced Continuous.le_induced

theorem gc_coinduced_induced (f : α → β) :
    GaloisConnection (TopologicalSpace.coinduced f) (TopologicalSpace.induced f) := fun _ _ =>
  coinduced_le_iff_le_induced
#align gc_coinduced_induced gc_coinduced_induced

theorem induced_mono (h : t₁ ≤ t₂) : t₁.induced g ≤ t₂.induced g :=
  (gc_coinduced_induced g).monotone_u h
#align induced_mono induced_mono

theorem coinduced_mono (h : t₁ ≤ t₂) : t₁.coinduced f ≤ t₂.coinduced f :=
  (gc_coinduced_induced f).monotone_l h
#align coinduced_mono coinduced_mono

@[simp]
theorem induced_top : (⊤ : TopologicalSpace α).induced g = ⊤ :=
  (gc_coinduced_induced g).u_top
#align induced_top induced_top

@[simp]
theorem induced_inf : (t₁ ⊓ t₂).induced g = t₁.induced g ⊓ t₂.induced g :=
  (gc_coinduced_induced g).u_inf
#align induced_inf induced_inf

@[simp]
theorem induced_infᵢ {ι : Sort w} {t : ι → TopologicalSpace α} :
    (⨅ i, t i).induced g = ⨅ i, (t i).induced g :=
  (gc_coinduced_induced g).u_infᵢ
#align induced_infi induced_infᵢ

@[simp]
theorem coinduced_bot : (⊥ : TopologicalSpace α).coinduced f = ⊥ :=
  (gc_coinduced_induced f).l_bot
#align coinduced_bot coinduced_bot

@[simp]
theorem coinduced_sup : (t₁ ⊔ t₂).coinduced f = t₁.coinduced f ⊔ t₂.coinduced f :=
  (gc_coinduced_induced f).l_sup
#align coinduced_sup coinduced_sup

@[simp]
theorem coinduced_supᵢ {ι : Sort w} {t : ι → TopologicalSpace α} :
    (⨆ i, t i).coinduced f = ⨆ i, (t i).coinduced f :=
  (gc_coinduced_induced f).l_supᵢ
#align coinduced_supr coinduced_supᵢ

theorem induced_id [t : TopologicalSpace α] : t.induced id = t :=
  topologicalSpace_eq <|
    funext fun s => propext <| ⟨fun ⟨_, hs, h⟩ => h ▸ hs, fun hs => ⟨s, hs, rfl⟩⟩
#align induced_id induced_id

theorem induced_compose [tγ : TopologicalSpace γ] {f : α → β} {g : β → γ} :
    (tγ.induced g).induced f = tγ.induced (g ∘ f) :=
  topologicalSpace_eq <|
    funext fun _ =>
      propext <|
        ⟨fun ⟨_, ⟨s, hs, h₂⟩, h₁⟩ => h₁ ▸ h₂ ▸ ⟨s, hs, rfl⟩, fun ⟨s, hs, h⟩ =>
          ⟨preimage g s, ⟨s, hs, rfl⟩, h ▸ rfl⟩⟩
#align induced_compose induced_compose

theorem induced_const [t : TopologicalSpace α] {x : α} : (t.induced fun _ : β => x) = ⊤ :=
  le_antisymm le_top (@continuous_const β α ⊤ t x).le_induced
#align induced_const induced_const

theorem coinduced_id [t : TopologicalSpace α] : t.coinduced id = t :=
  topologicalSpace_eq rfl
#align coinduced_id coinduced_id

theorem coinduced_compose [tα : TopologicalSpace α] {f : α → β} {g : β → γ} :
    (tα.coinduced f).coinduced g = tα.coinduced (g ∘ f) :=
  topologicalSpace_eq rfl
#align coinduced_compose coinduced_compose

theorem Equiv.induced_symm {α β : Type _} (e : α ≃ β) :
    TopologicalSpace.induced e.symm = TopologicalSpace.coinduced e := by
  ext t U
  rw [isOpen_induced_iff, isOpen_coinduced]
  simp only [e.symm.preimage_eq_iff_eq_image, exists_eq_right, ← preimage_equiv_eq_image_symm]
#align equiv.induced_symm Equiv.induced_symm

theorem Equiv.coinduced_symm {α β : Type _} (e : α ≃ β) :
    TopologicalSpace.coinduced e.symm = TopologicalSpace.induced e :=
  e.symm.induced_symm.symm
#align equiv.coinduced_symm Equiv.coinduced_symm

end GaloisConnection

-- constructions using the complete lattice structure
section Constructions

open TopologicalSpace

variable {α : Type u} {β : Type v}

instance inhabitedTopologicalSpace {α : Type u} : Inhabited (TopologicalSpace α) :=
  ⟨⊥⟩
#align inhabited_topological_space inhabitedTopologicalSpace

instance (priority := 100) Subsingleton.uniqueTopologicalSpace [Subsingleton α] :
    Unique (TopologicalSpace α) where
  default := ⊥
  uniq t :=
    eq_bot_of_singletons_open fun x =>
      Subsingleton.set_cases (@isOpen_empty _ t) (@isOpen_univ _ t) ({x} : Set α)
#align subsingleton.unique_topological_space Subsingleton.uniqueTopologicalSpace

instance (priority := 100) Subsingleton.discreteTopology [t : TopologicalSpace α] [Subsingleton α] :
    DiscreteTopology α :=
  ⟨Unique.eq_default t⟩
#align subsingleton.discrete_topology Subsingleton.discreteTopology

instance : TopologicalSpace Empty := ⊥
instance : DiscreteTopology Empty := ⟨rfl⟩

instance : TopologicalSpace PEmpty := ⊥
instance : DiscreteTopology PEmpty := ⟨rfl⟩

instance : TopologicalSpace PUnit := ⊥
instance : DiscreteTopology PUnit := ⟨rfl⟩

instance : TopologicalSpace Bool := ⊥
instance : DiscreteTopology Bool := ⟨rfl⟩

instance : TopologicalSpace ℕ := ⊥
instance : DiscreteTopology ℕ := ⟨rfl⟩

instance : TopologicalSpace ℤ := ⊥
instance : DiscreteTopology ℤ := ⟨rfl⟩

instance {n} : TopologicalSpace (Fin n) := ⊥
instance {n} : DiscreteTopology (Fin n) := ⟨rfl⟩

instance sierpinskiSpace : TopologicalSpace Prop :=
  generateFrom {{True}}
#align sierpinski_space sierpinskiSpace

theorem continuous_empty_function [TopologicalSpace α] [TopologicalSpace β] [IsEmpty β]
    (f : α → β) : Continuous f :=
  letI := Function.isEmpty f
  continuous_of_discreteTopology
#align continuous_empty_function continuous_empty_function

theorem le_generateFrom {t : TopologicalSpace α} {g : Set (Set α)} (h : ∀ s ∈ g, IsOpen s) :
    t ≤ generateFrom g :=
  le_generateFrom_iff_subset_isOpen.2 h
#align le_generate_from le_generateFrom

theorem induced_generateFrom_eq {α β} {b : Set (Set β)} {f : α → β} :
    (generateFrom b).induced f = generateFrom (preimage f '' b) :=
  le_antisymm (le_generateFrom <| ball_image_iff.2 fun s hs => ⟨s, GenerateOpen.basic _ hs, rfl⟩)
    (coinduced_le_iff_le_induced.1 <| le_generateFrom fun _s hs => .basic _ (mem_image_of_mem _ hs))
#align induced_generate_from_eq induced_generateFrom_eq

theorem le_induced_generateFrom {α β} [t : TopologicalSpace α] {b : Set (Set β)} {f : α → β}
    (h : ∀ a : Set β, a ∈ b → IsOpen (f ⁻¹' a)) : t ≤ induced f (generateFrom b) := by
  rw [induced_generateFrom_eq]
  apply le_generateFrom
  simp only [mem_image, and_imp, forall_apply_eq_imp_iff₂, exists_imp]
  exact h
#align le_induced_generate_from le_induced_generateFrom

/-- This construction is left adjoint to the operation sending a topology on `α`
  to its neighborhood filter at a fixed point `a : α`. -/
def nhdsAdjoint (a : α) (f : Filter α) : TopologicalSpace α where
  IsOpen s := a ∈ s → s ∈ f
  isOpen_univ _ := univ_mem
  isOpen_inter := fun _s _t hs ht ⟨has, hat⟩ => inter_mem (hs has) (ht hat)
  isOpen_unionₛ := fun _k hk ⟨u, hu, hau⟩ => mem_of_superset (hk u hu hau) (subset_unionₛ_of_mem hu)
#align nhds_adjoint nhdsAdjoint

theorem gc_nhds (a : α) : GaloisConnection (nhdsAdjoint a) fun t => @nhds α t a := fun f t => by
  rw [le_nhds_iff]
  exact ⟨fun H s hs has => H _ has hs, fun H s has hs => H _ hs has⟩
#align gc_nhds gc_nhds

theorem nhds_mono {t₁ t₂ : TopologicalSpace α} {a : α} (h : t₁ ≤ t₂) :
    @nhds α t₁ a ≤ @nhds α t₂ a :=
  (gc_nhds a).monotone_u h
#align nhds_mono nhds_mono

theorem le_iff_nhds {α : Type _} (t t' : TopologicalSpace α) :
    t ≤ t' ↔ ∀ x, @nhds α t x ≤ @nhds α t' x :=
  ⟨fun h _ => nhds_mono h, le_of_nhds_le_nhds⟩
#align le_iff_nhds le_iff_nhds

theorem nhdsAdjoint_nhds {α : Type _} (a : α) (f : Filter α) :
    @nhds α (nhdsAdjoint a f) a = pure a ⊔ f := by
  letI := nhdsAdjoint a f
  ext U
  rw [mem_nhds_iff]
  constructor
  · rintro ⟨t, htU, ht, hat⟩
    exact ⟨htU hat, mem_of_superset (ht hat) htU⟩
  · rintro ⟨haU, hU⟩
    exact ⟨U, Subset.rfl, fun _ => hU, haU⟩
#align nhds_adjoint_nhds nhdsAdjoint_nhds

theorem nhdsAdjoint_nhds_of_ne {α : Type _} (a : α) (f : Filter α) {b : α} (h : b ≠ a) :
    @nhds α (nhdsAdjoint a f) b = pure b := by
  letI := nhdsAdjoint a f
  apply le_antisymm
  · intro U hU
    rw [mem_nhds_iff]
    use {b}
    simp only [and_true_iff, singleton_subset_iff, mem_singleton]
    refine' ⟨hU, fun ha => (h.symm ha).elim⟩
  · exact @pure_le_nhds α (nhdsAdjoint a f) b
#align nhds_adjoint_nhds_of_ne nhdsAdjoint_nhds_of_ne

theorem isOpen_singleton_nhdsAdjoint {α : Type _} {a b : α} (f : Filter α) (hb : b ≠ a) :
    IsOpen[nhdsAdjoint a f] {b} := by
  letI := nhdsAdjoint a f
  rw [isOpen_singleton_iff_nhds_eq_pure]
  exact nhdsAdjoint_nhds_of_ne a f hb
#align is_open_singleton_nhds_adjoint isOpen_singleton_nhdsAdjoint

theorem le_nhdsAdjoint_iff' {α : Type _} (a : α) (f : Filter α) (t : TopologicalSpace α) :
    t ≤ nhdsAdjoint a f ↔ @nhds α t a ≤ pure a ⊔ f ∧ ∀ b, b ≠ a → @nhds α t b = pure b := by
  rw [le_iff_nhds]
  constructor
  · intro h
    constructor
    · specialize h a
      rwa [nhdsAdjoint_nhds] at h
    · intro b hb
      apply le_antisymm _ (pure_le_nhds b)
      specialize h b
      rwa [nhdsAdjoint_nhds_of_ne a f hb] at h
  · rintro ⟨h, h'⟩ b
    by_cases hb : b = a
    · rwa [hb, nhdsAdjoint_nhds]
    · simp [nhdsAdjoint_nhds_of_ne a f hb, h' b hb]
#align le_nhds_adjoint_iff' le_nhdsAdjoint_iff'

theorem le_nhdsAdjoint_iff {α : Type _} (a : α) (f : Filter α) (t : TopologicalSpace α) :
    t ≤ nhdsAdjoint a f ↔ @nhds α t a ≤ pure a ⊔ f ∧ ∀ b, b ≠ a → IsOpen[t] {b} := by
  change _ ↔ _ ∧ ∀ b : α, b ≠ a → IsOpen {b}
  rw [le_nhdsAdjoint_iff', and_congr_right_iff]
  refine fun _ => forall_congr' fun b => ?_
  rw [@isOpen_singleton_iff_nhds_eq_pure α t b]
#align le_nhds_adjoint_iff le_nhdsAdjoint_iff

theorem nhds_infᵢ {ι : Sort _} {t : ι → TopologicalSpace α} {a : α} :
    @nhds α (infᵢ t) a = ⨅ i, @nhds α (t i) a :=
  (gc_nhds a).u_infᵢ
#align nhds_infi nhds_infᵢ

theorem nhds_infₛ {s : Set (TopologicalSpace α)} {a : α} :
    @nhds α (infₛ s) a = ⨅ t ∈ s, @nhds α t a :=
  (gc_nhds a).u_infₛ
#align nhds_Inf nhds_infₛ

-- porting note: todo: timeouts without `b₁ := t₁`
theorem nhds_inf {t₁ t₂ : TopologicalSpace α} {a : α} :
    @nhds α (t₁ ⊓ t₂) a = @nhds α t₁ a ⊓ @nhds α t₂ a :=
  GaloisConnection.u_inf (b₁ := t₁) (gc_nhds a)
#align nhds_inf nhds_inf

theorem nhds_top {a : α} : @nhds α ⊤ a = ⊤ :=
  (gc_nhds a).u_top
#align nhds_top nhds_top

theorem isOpen_sup {t₁ t₂ : TopologicalSpace α} {s : Set α} :
    IsOpen[t₁ ⊔ t₂] s ↔ IsOpen[t₁] s ∧ IsOpen[t₂] s :=
  Iff.rfl
#align is_open_sup isOpen_sup

open TopologicalSpace

variable {γ : Type _} {f : α → β} {ι : Sort _}

theorem continuous_iff_coinduced_le {t₁ : TopologicalSpace α} {t₂ : TopologicalSpace β} :
    Continuous[t₁, t₂] f ↔ coinduced f t₁ ≤ t₂ :=
  continuous_def
#align continuous_iff_coinduced_le continuous_iff_coinduced_le

theorem continuous_iff_le_induced {t₁ : TopologicalSpace α} {t₂ : TopologicalSpace β} :
    Continuous[t₁, t₂] f ↔ t₁ ≤ induced f t₂ :=
  Iff.trans continuous_iff_coinduced_le (gc_coinduced_induced f _ _)
#align continuous_iff_le_induced continuous_iff_le_induced

theorem continuous_generateFrom {t : TopologicalSpace α} {b : Set (Set β)}
    (h : ∀ s ∈ b, IsOpen (f ⁻¹' s)) :
    Continuous[t, generateFrom b] f :=
  continuous_iff_coinduced_le.2 <| le_generateFrom h
#align continuous_generated_from continuous_generateFrom

@[continuity]
theorem continuous_induced_dom {t : TopologicalSpace β} : Continuous[induced f t, t] f :=
  continuous_iff_le_induced.2 le_rfl
#align continuous_induced_dom continuous_induced_dom

theorem continuous_induced_rng {g : γ → α} {t₂ : TopologicalSpace β} {t₁ : TopologicalSpace γ} :
    Continuous[t₁, induced f t₂] g ↔ Continuous[t₁, t₂] (f ∘ g) := by
  simp only [continuous_iff_le_induced, induced_compose]
#align continuous_induced_rng continuous_induced_rng

theorem continuous_coinduced_rng {t : TopologicalSpace α} :
    Continuous[t, coinduced f t] f :=
  continuous_iff_coinduced_le.2 le_rfl
#align continuous_coinduced_rng continuous_coinduced_rng

theorem continuous_coinduced_dom {g : β → γ} {t₁ : TopologicalSpace α} {t₂ : TopologicalSpace γ} :
    Continuous[coinduced f t₁, t₂] g ↔ Continuous[t₁, t₂] (g ∘ f) := by
  simp only [continuous_iff_coinduced_le, coinduced_compose]
#align continuous_coinduced_dom continuous_coinduced_dom

theorem continuous_le_dom {t₁ t₂ : TopologicalSpace α} {t₃ : TopologicalSpace β} (h₁ : t₂ ≤ t₁)
    (h₂ : Continuous[t₁, t₃] f) : Continuous[t₂, t₃] f := by
  rw [continuous_iff_le_induced] at h₂ ⊢
  exact le_trans h₁ h₂
#align continuous_le_dom continuous_le_dom

theorem continuous_le_rng {t₁ : TopologicalSpace α} {t₂ t₃ : TopologicalSpace β} (h₁ : t₂ ≤ t₃)
    (h₂ : Continuous[t₁, t₂] f) : Continuous[t₁, t₃] f := by
  rw [continuous_iff_coinduced_le] at h₂ ⊢
  exact le_trans h₂ h₁
#align continuous_le_rng continuous_le_rng

theorem continuous_sup_dom {t₁ t₂ : TopologicalSpace α} {t₃ : TopologicalSpace β} :
    Continuous[t₁ ⊔ t₂, t₃] f ↔ Continuous[t₁, t₃] f ∧ Continuous[t₂, t₃] f := by
  simp only [continuous_iff_le_induced, sup_le_iff]
#align continuous_sup_dom continuous_sup_dom

theorem continuous_sup_rng_left {t₁ : TopologicalSpace α} {t₃ t₂ : TopologicalSpace β} :
    Continuous[t₁, t₂] f → Continuous[t₁, t₂ ⊔ t₃] f :=
  continuous_le_rng le_sup_left
#align continuous_sup_rng_left continuous_sup_rng_left

theorem continuous_sup_rng_right {t₁ : TopologicalSpace α} {t₃ t₂ : TopologicalSpace β} :
    Continuous[t₁, t₃] f → Continuous[t₁, t₂ ⊔ t₃] f :=
  continuous_le_rng le_sup_right
#align continuous_sup_rng_right continuous_sup_rng_right

theorem continuous_supₛ_dom {T : Set (TopologicalSpace α)} {t₂ : TopologicalSpace β} :
    Continuous[supₛ T, t₂] f ↔ ∀ t ∈ T, Continuous[t, t₂] f := by
  simp only [continuous_iff_le_induced, supₛ_le_iff]
#align continuous_Sup_dom continuous_supₛ_dom

theorem continuous_supₛ_rng {t₁ : TopologicalSpace α} {t₂ : Set (TopologicalSpace β)}
    {t : TopologicalSpace β} (h₁ : t ∈ t₂) (hf : Continuous[t₁, t] f) :
    Continuous[t₁, supₛ t₂] f :=
  continuous_iff_coinduced_le.2 <| le_supₛ_of_le h₁ <| continuous_iff_coinduced_le.1 hf
#align continuous_Sup_rng continuous_supₛ_rng

theorem continuous_supᵢ_dom {t₁ : ι → TopologicalSpace α} {t₂ : TopologicalSpace β} :
    Continuous[supᵢ t₁, t₂] f ↔ ∀ i, Continuous[t₁ i, t₂] f := by
  simp only [continuous_iff_le_induced, supᵢ_le_iff]
#align continuous_supr_dom continuous_supᵢ_dom

theorem continuous_supᵢ_rng {t₁ : TopologicalSpace α} {t₂ : ι → TopologicalSpace β} {i : ι}
    (h : Continuous[t₁, t₂ i] f) : Continuous[t₁, supᵢ t₂] f :=
  continuous_supₛ_rng ⟨i, rfl⟩ h
#align continuous_supr_rng continuous_supᵢ_rng

theorem continuous_inf_rng {t₁ : TopologicalSpace α} {t₂ t₃ : TopologicalSpace β} :
    Continuous[t₁, t₂ ⊓ t₃] f ↔ Continuous[t₁, t₂] f ∧ Continuous[t₁, t₃] f := by
  simp only [continuous_iff_coinduced_le, le_inf_iff]
#align continuous_inf_rng continuous_inf_rng

theorem continuous_inf_dom_left {t₁ t₂ : TopologicalSpace α} {t₃ : TopologicalSpace β} :
    Continuous[t₁, t₃] f → Continuous[t₁ ⊓ t₂, t₃] f :=
  continuous_le_dom inf_le_left
#align continuous_inf_dom_left continuous_inf_dom_left

theorem continuous_inf_dom_right {t₁ t₂ : TopologicalSpace α} {t₃ : TopologicalSpace β} :
    Continuous[t₂, t₃] f → Continuous[t₁ ⊓ t₂, t₃] f :=
  continuous_le_dom inf_le_right
#align continuous_inf_dom_right continuous_inf_dom_right

theorem continuous_infₛ_dom {t₁ : Set (TopologicalSpace α)} {t₂ : TopologicalSpace β}
    {t : TopologicalSpace α} (h₁ : t ∈ t₁) :
    Continuous[t, t₂] f → Continuous[infₛ t₁, t₂] f :=
  continuous_le_dom <| infₛ_le h₁
#align continuous_Inf_dom continuous_infₛ_dom

theorem continuous_infₛ_rng {t₁ : TopologicalSpace α} {T : Set (TopologicalSpace β)} :
    Continuous[t₁, infₛ T] f ↔ ∀ t ∈ T, Continuous[t₁, t] f := by
  simp only [continuous_iff_coinduced_le, le_infₛ_iff]
#align continuous_Inf_rng continuous_infₛ_rng

theorem continuous_infᵢ_dom {t₁ : ι → TopologicalSpace α} {t₂ : TopologicalSpace β} {i : ι} :
    Continuous[t₁ i, t₂] f → Continuous[infᵢ t₁, t₂] f :=
  continuous_le_dom <| infᵢ_le _ _
#align continuous_infi_dom continuous_infᵢ_dom

theorem continuous_infᵢ_rng {t₁ : TopologicalSpace α} {t₂ : ι → TopologicalSpace β} :
    Continuous[t₁, infᵢ t₂] f ↔ ∀ i, Continuous[t₁, t₂ i] f := by
  simp only [continuous_iff_coinduced_le, le_infᵢ_iff]
#align continuous_infi_rng continuous_infᵢ_rng

@[continuity]
theorem continuous_bot {t : TopologicalSpace β} : Continuous[⊥, t] f :=
  continuous_iff_le_induced.2 bot_le
#align continuous_bot continuous_bot

@[continuity]
theorem continuous_top {t : TopologicalSpace α} : Continuous[t, ⊤] f :=
  continuous_iff_coinduced_le.2 le_top
#align continuous_top continuous_top

theorem continuous_id_iff_le {t t' : TopologicalSpace α} : Continuous[t, t'] id ↔ t ≤ t' :=
  @continuous_def _ _ t t' id
#align continuous_id_iff_le continuous_id_iff_le

theorem continuous_id_of_le {t t' : TopologicalSpace α} (h : t ≤ t') : Continuous[t, t'] id :=
  continuous_id_iff_le.2 h
#align continuous_id_of_le continuous_id_of_le

-- 𝓝 in the induced topology
theorem mem_nhds_induced [T : TopologicalSpace α] (f : β → α) (a : β) (s : Set β) :
    s ∈ @nhds β (TopologicalSpace.induced f T) a ↔ ∃ u ∈ 𝓝 (f a), f ⁻¹' u ⊆ s := by
  letI := T.induced f
  simp only [mem_nhds_iff, isOpen_induced_iff, exists_prop, Set.mem_setOf_eq]
  constructor
  · rintro ⟨u, usub, ⟨v, openv, rfl⟩, au⟩
    exact ⟨v, ⟨v, Subset.rfl, openv, au⟩, usub⟩
  · rintro ⟨u, ⟨v, vsubu, openv, amem⟩, finvsub⟩
    exact ⟨f ⁻¹' v, (Set.preimage_mono vsubu).trans finvsub, ⟨⟨v, openv, rfl⟩, amem⟩⟩
#align mem_nhds_induced mem_nhds_induced

theorem nhds_induced [T : TopologicalSpace α] (f : β → α) (a : β) :
    @nhds β (TopologicalSpace.induced f T) a = comap f (𝓝 (f a)) := by
  ext s
  rw [mem_nhds_induced, mem_comap]
#align nhds_induced nhds_induced

theorem induced_iff_nhds_eq [tα : TopologicalSpace α] [tβ : TopologicalSpace β] (f : β → α) :
    tβ = tα.induced f ↔ ∀ b, 𝓝 b = comap f (𝓝 <| f b) :=
  ⟨fun h a => h.symm ▸ nhds_induced f a, fun h =>
    eq_of_nhds_eq_nhds fun x => by rw [h, nhds_induced]⟩
#align induced_iff_nhds_eq induced_iff_nhds_eq

theorem map_nhds_induced_of_surjective [T : TopologicalSpace α] {f : β → α} (hf : Surjective f)
    (a : β) : map f (@nhds β (TopologicalSpace.induced f T) a) = 𝓝 (f a) := by
  rw [nhds_induced, map_comap_of_surjective hf]
#align map_nhds_induced_of_surjective map_nhds_induced_of_surjective

end Constructions

section Induced

open TopologicalSpace

variable {α : Type _} {β : Type _}

variable [t : TopologicalSpace β] {f : α → β}

theorem isOpen_induced_eq {s : Set α} :
    IsOpen[induced f t] s ↔ s ∈ preimage f '' { s | IsOpen s } :=
  Iff.rfl
#align is_open_induced_eq isOpen_induced_eq

theorem isOpen_induced {s : Set β} (h : IsOpen s) : IsOpen[induced f t] (f ⁻¹' s) :=
  ⟨s, h, rfl⟩
#align is_open_induced isOpen_induced

theorem map_nhds_induced_eq (a : α) : map f (@nhds α (induced f t) a) = 𝓝[range f] f a := by
  rw [nhds_induced, Filter.map_comap, nhdsWithin]
#align map_nhds_induced_eq map_nhds_induced_eq

theorem map_nhds_induced_of_mem {a : α} (h : range f ∈ 𝓝 (f a)) :
    map f (@nhds α (induced f t) a) = 𝓝 (f a) := by rw [nhds_induced, Filter.map_comap_of_mem h]
#align map_nhds_induced_of_mem map_nhds_induced_of_mem

theorem closure_induced [t : TopologicalSpace β] {f : α → β} {a : α} {s : Set α} :
    a ∈ @closure α (t.induced f) s ↔ f a ∈ closure (f '' s) := by
  letI := t.induced f
  simp only [mem_closure_iff_frequently, nhds_induced, frequently_comap, mem_image, and_comm]
#align closure_induced closure_induced

theorem isClosed_induced_iff' [t : TopologicalSpace β] {f : α → β} {s : Set α} :
    IsClosed[t.induced f] s ↔ ∀ a, f a ∈ closure (f '' s) → a ∈ s := by
  letI := t.induced f
  simp only [← closure_subset_iff_isClosed, subset_def, closure_induced]
#align is_closed_induced_iff' isClosed_induced_iff'

end Induced

section Sierpinski

variable {α : Type _} [TopologicalSpace α]

@[simp]
theorem isOpen_singleton_true : IsOpen ({True} : Set Prop) :=
  TopologicalSpace.GenerateOpen.basic _ (mem_singleton _)
#align is_open_singleton_true isOpen_singleton_true

@[simp]
theorem nhds_true : 𝓝 True = pure True :=
  le_antisymm (le_pure_iff.2 <| isOpen_singleton_true.mem_nhds <| mem_singleton _) (pure_le_nhds _)
#align nhds_true nhds_true

@[simp]
theorem nhds_false : 𝓝 False = ⊤ :=
  TopologicalSpace.nhds_generateFrom.trans <| by simp [@and_comm (_ ∈ _)]
#align nhds_false nhds_false

theorem tendsto_nhds_true {l : Filter α} {p : α → Prop} :
    Tendsto p l (𝓝 True) ↔ ∀ᶠ x in l, p x := by simp

theorem tendsto_nhds_Prop {l : Filter α} {p : α → Prop} {q : Prop} :
    Tendsto p l (𝓝 q) ↔ (q → ∀ᶠ x in l, p x) := by
  by_cases q <;> simp [*]

theorem continuous_Prop {p : α → Prop} : Continuous p ↔ IsOpen { x | p x } := by
  simp only [continuous_iff_continuousAt, ContinuousAt, tendsto_nhds_Prop, isOpen_iff_mem_nhds]; rfl
#align continuous_Prop continuous_Prop

theorem isOpen_iff_continuous_mem {s : Set α} : IsOpen s ↔ Continuous (· ∈ s) :=
  continuous_Prop.symm
#align is_open_iff_continuous_mem isOpen_iff_continuous_mem

end Sierpinski

section infᵢ

open TopologicalSpace

variable {α : Type u} {ι : Sort v}

theorem generateFrom_union (a₁ a₂ : Set (Set α)) :
    generateFrom (a₁ ∪ a₂) = generateFrom a₁ ⊓ generateFrom a₂ :=
  (gc_generateFrom α).u_inf
#align generate_from_union generateFrom_union

theorem setOf_isOpen_sup (t₁ t₂ : TopologicalSpace α) :
    { s | IsOpen[t₁ ⊔ t₂] s } = { s | IsOpen[t₁] s } ∩ { s | IsOpen[t₂] s } :=
  rfl
#align set_of_is_open_sup setOf_isOpen_sup

theorem generateFrom_unionᵢ {f : ι → Set (Set α)} :
    generateFrom (⋃ i, f i) = ⨅ i, generateFrom (f i) :=
  (gc_generateFrom α).u_infᵢ
#align generate_from_Union generateFrom_unionᵢ

theorem setOf_isOpen_supᵢ {t : ι → TopologicalSpace α} :
    { s | IsOpen[⨆ i, t i] s } = ⋂ i, { s | IsOpen[t i] s } :=
  (gc_generateFrom α).l_supᵢ
#align set_of_is_open_supr setOf_isOpen_supᵢ

theorem generateFrom_unionₛ {S : Set (Set (Set α))} :
    generateFrom (⋃₀ S) = ⨅ s ∈ S, generateFrom s :=
  (gc_generateFrom α).u_infₛ
#align generate_from_sUnion generateFrom_unionₛ

theorem setOf_isOpen_supₛ {T : Set (TopologicalSpace α)} :
    { s | IsOpen[supₛ T] s } = ⋂ t ∈ T, { s | IsOpen[t] s } :=
  (gc_generateFrom α).l_supₛ
#align set_of_is_open_Sup setOf_isOpen_supₛ

theorem generateFrom_union_isOpen (a b : TopologicalSpace α) :
    generateFrom ({ s | IsOpen[a] s } ∪ { s | IsOpen[b] s }) = a ⊓ b :=
  (gciGenerateFrom α).u_inf_l _ _
#align generate_from_union_is_open generateFrom_union_isOpen

theorem generateFrom_unionᵢ_isOpen (f : ι → TopologicalSpace α) :
    generateFrom (⋃ i, { s | IsOpen[f i] s }) = ⨅ i, f i :=
  (gciGenerateFrom α).u_infᵢ_l _
#align generate_from_Union_is_open generateFrom_unionᵢ_isOpen

theorem generateFrom_inter (a b : TopologicalSpace α) :
    generateFrom ({ s | IsOpen[a] s } ∩ { s | IsOpen[b] s }) = a ⊔ b :=
  (gciGenerateFrom α).u_sup_l _ _
#align generate_from_inter generateFrom_inter

theorem generateFrom_interᵢ (f : ι → TopologicalSpace α) :
    generateFrom (⋂ i, { s | IsOpen[f i] s }) = ⨆ i, f i :=
  (gciGenerateFrom α).u_supᵢ_l _
#align generate_from_Inter generateFrom_interᵢ

theorem generateFrom_interᵢ_of_generateFrom_eq_self (f : ι → Set (Set α))
    (hf : ∀ i, { s | IsOpen[generateFrom (f i)] s } = f i) :
    generateFrom (⋂ i, f i) = ⨆ i, generateFrom (f i) :=
  (gciGenerateFrom α).u_supᵢ_of_lu_eq_self f hf
#align generate_from_Inter_of_generate_from_eq_self generateFrom_interᵢ_of_generateFrom_eq_self

variable {t : ι → TopologicalSpace α}

theorem isOpen_supᵢ_iff {s : Set α} : IsOpen[⨆ i, t i] s ↔ ∀ i, IsOpen[t i] s :=
  show s ∈ {s | IsOpen[supᵢ t] s} ↔ s ∈ { x : Set α | ∀ i : ι, IsOpen[t i] x } by
    simp [setOf_isOpen_supᵢ]
#align is_open_supr_iff isOpen_supᵢ_iff

theorem isClosed_supᵢ_iff {s : Set α} : IsClosed[⨆ i, t i] s ↔ ∀ i, IsClosed[t i] s := by
  simp [← @isOpen_compl_iff _ (⨆ i, t i), ← @isOpen_compl_iff _ (t _), isOpen_supᵢ_iff]
#align is_closed_supr_iff isClosed_supᵢ_iff

end infᵢ