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

! This file was ported from Lean 3 source module topology.sets.closeds
! leanprover-community/mathlib commit 34ee86e6a59d911a8e4f89b68793ee7577ae79c7
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.Topology.Sets.Opens

/-!
# Closed sets

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

We define a few types of closed sets in a topological space.

## Main Definitions

For a topological space `α`,
* `closeds α`: The type of closed sets.
* `clopens α`: The type of clopen sets.
-/

open Order OrderDual Set

variable {ι α β : Type _} [TopologicalSpace α] [TopologicalSpace β]

namespace TopologicalSpace

/-! ### Closed sets -/

#print TopologicalSpace.Closeds /-
/-- The type of closed subsets of a topological space. -/
structure Closeds (α : Type _) [TopologicalSpace α] where
  carrier : Set α
  closed' : IsClosed carrier
#align topological_space.closeds TopologicalSpace.Closeds
-/

namespace Closeds

variable {α}

instance : SetLike (Closeds α) α where
  coe := Closeds.carrier
  coe_injective' s t h := by
    cases s
    cases t
    congr

#print TopologicalSpace.Closeds.closed /-
theorem closed (s : Closeds α) : IsClosed (s : Set α) :=
  s.closed'
#align topological_space.closeds.closed TopologicalSpace.Closeds.closed
-/

#print TopologicalSpace.Closeds.ext /-
@[ext]
protected theorem ext {s t : Closeds α} (h : (s : Set α) = t) : s = t :=
  SetLike.ext' h
#align topological_space.closeds.ext TopologicalSpace.Closeds.ext
-/

#print TopologicalSpace.Closeds.coe_mk /-
@[simp]
theorem coe_mk (s : Set α) (h) : (mk s h : Set α) = s :=
  rfl
#align topological_space.closeds.coe_mk TopologicalSpace.Closeds.coe_mk
-/

#print TopologicalSpace.Closeds.closure /-
/-- The closure of a set, as an element of `closeds`. -/
protected def closure (s : Set α) : Closeds α :=
  ⟨closure s, isClosed_closure⟩
#align topological_space.closeds.closure TopologicalSpace.Closeds.closure
-/

/- warning: topological_space.closeds.gc -> TopologicalSpace.Closeds.gc is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α], GaloisConnection.{u1, u1} (Set.{u1} α) (TopologicalSpace.Closeds.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (Set.{u1} α) (CompleteSemilatticeInf.toPartialOrder.{u1} (Set.{u1} α) (CompleteLattice.toCompleteSemilatticeInf.{u1} (Set.{u1} α) (Order.Coframe.toCompleteLattice.{u1} (Set.{u1} α) (CompleteDistribLattice.toCoframe.{u1} (Set.{u1} α) (CompleteBooleanAlgebra.toCompleteDistribLattice.{u1} (Set.{u1} α) (Set.completeBooleanAlgebra.{u1} α))))))) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (SetLike.partialOrder.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1))) (TopologicalSpace.Closeds.closure.{u1} α _inst_1) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α], GaloisConnection.{u1, u1} (Set.{u1} α) (TopologicalSpace.Closeds.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (Set.{u1} α) (CompleteSemilatticeInf.toPartialOrder.{u1} (Set.{u1} α) (CompleteLattice.toCompleteSemilatticeInf.{u1} (Set.{u1} α) (Order.Coframe.toCompleteLattice.{u1} (Set.{u1} α) (CompleteDistribLattice.toCoframe.{u1} (Set.{u1} α) (CompleteBooleanAlgebra.toCompleteDistribLattice.{u1} (Set.{u1} α) (Set.instCompleteBooleanAlgebraSet.{u1} α))))))) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (SetLike.instPartialOrder.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1))) (TopologicalSpace.Closeds.closure.{u1} α _inst_1) (SetLike.coe.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1))
Case conversion may be inaccurate. Consider using '#align topological_space.closeds.gc TopologicalSpace.Closeds.gcₓ'. -/
theorem gc : GaloisConnection Closeds.closure (coe : Closeds α → Set α) := fun s U =>
  ⟨subset_closure.trans, fun h => closure_minimal h U.closed⟩
#align topological_space.closeds.gc TopologicalSpace.Closeds.gc

/- warning: topological_space.closeds.gi -> TopologicalSpace.Closeds.gi is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α], GaloisInsertion.{u1, u1} (Set.{u1} α) (TopologicalSpace.Closeds.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (Set.{u1} α) (CompleteSemilatticeInf.toPartialOrder.{u1} (Set.{u1} α) (CompleteLattice.toCompleteSemilatticeInf.{u1} (Set.{u1} α) (Order.Coframe.toCompleteLattice.{u1} (Set.{u1} α) (CompleteDistribLattice.toCoframe.{u1} (Set.{u1} α) (CompleteBooleanAlgebra.toCompleteDistribLattice.{u1} (Set.{u1} α) (Set.completeBooleanAlgebra.{u1} α))))))) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (SetLike.partialOrder.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1))) (TopologicalSpace.Closeds.closure.{u1} α _inst_1) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α], GaloisInsertion.{u1, u1} (Set.{u1} α) (TopologicalSpace.Closeds.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (Set.{u1} α) (CompleteSemilatticeInf.toPartialOrder.{u1} (Set.{u1} α) (CompleteLattice.toCompleteSemilatticeInf.{u1} (Set.{u1} α) (Order.Coframe.toCompleteLattice.{u1} (Set.{u1} α) (CompleteDistribLattice.toCoframe.{u1} (Set.{u1} α) (CompleteBooleanAlgebra.toCompleteDistribLattice.{u1} (Set.{u1} α) (Set.instCompleteBooleanAlgebraSet.{u1} α))))))) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (SetLike.instPartialOrder.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1))) (TopologicalSpace.Closeds.closure.{u1} α _inst_1) (SetLike.coe.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1))
Case conversion may be inaccurate. Consider using '#align topological_space.closeds.gi TopologicalSpace.Closeds.giₓ'. -/
/-- The galois coinsertion between sets and opens. -/
def gi : GaloisInsertion (@Closeds.closure α _) coe
    where
  choice s hs := ⟨s, closure_eq_iff_isClosed.1 <| hs.antisymm subset_closure⟩
  gc := gc
  le_l_u _ := subset_closure
  choice_eq s hs := SetLike.coe_injective <| subset_closure.antisymm hs
#align topological_space.closeds.gi TopologicalSpace.Closeds.gi

instance : CompleteLattice (Closeds α) :=
  CompleteLattice.copy
    (GaloisInsertion.liftCompleteLattice gi)-- le
    _
    rfl-- top
    ⟨univ, isClosed_univ⟩
    rfl-- bot
    ⟨∅, isClosed_empty⟩
    (SetLike.coe_injective closure_empty.symm)
    (-- sup
    fun s t => ⟨s ∪ t, s.2.union t.2⟩)
    (funext fun s => funext fun t => SetLike.coe_injective (s.2.union t.2).closure_eq.symm)
    (-- inf
    fun s t => ⟨s ∩ t, s.2.inter t.2⟩)
    rfl-- Sup
    _
    rfl
    (-- Inf
    fun S => ⟨⋂ s ∈ S, ↑s, isClosed_binterᵢ fun s _ => s.2⟩)
    (funext fun S => SetLike.coe_injective infₛ_image.symm)

/-- The type of closed sets is inhabited, with default element the empty set. -/
instance : Inhabited (Closeds α) :=
  ⟨⊥⟩

/- warning: topological_space.closeds.coe_sup -> TopologicalSpace.Closeds.coe_sup is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] (s : TopologicalSpace.Closeds.{u1} α _inst_1) (t : TopologicalSpace.Closeds.{u1} α _inst_1), Eq.{succ u1} (Set.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))) (Sup.sup.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (SemilatticeSup.toHasSup.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Lattice.toSemilatticeSup.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (ConditionallyCompleteLattice.toLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u1} α _inst_1))))) s t)) (Union.union.{u1} (Set.{u1} α) (Set.hasUnion.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))) s) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))) t))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] (s : TopologicalSpace.Closeds.{u1} α _inst_1) (t : TopologicalSpace.Closeds.{u1} α _inst_1), Eq.{succ u1} (Set.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1) (Sup.sup.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (SemilatticeSup.toSup.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Lattice.toSemilatticeSup.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (ConditionallyCompleteLattice.toLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u1} α _inst_1))))) s t)) (Union.union.{u1} (Set.{u1} α) (Set.instUnionSet.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1) s) (SetLike.coe.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1) t))
Case conversion may be inaccurate. Consider using '#align topological_space.closeds.coe_sup TopologicalSpace.Closeds.coe_supₓ'. -/
@[simp, norm_cast]
theorem coe_sup (s t : Closeds α) : (↑(s ⊔ t) : Set α) = s ∪ t :=
  rfl
#align topological_space.closeds.coe_sup TopologicalSpace.Closeds.coe_sup

/- warning: topological_space.closeds.coe_inf -> TopologicalSpace.Closeds.coe_inf is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] (s : TopologicalSpace.Closeds.{u1} α _inst_1) (t : TopologicalSpace.Closeds.{u1} α _inst_1), Eq.{succ u1} (Set.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))) (Inf.inf.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (SemilatticeInf.toHasInf.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Lattice.toSemilatticeInf.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (ConditionallyCompleteLattice.toLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u1} α _inst_1))))) s t)) (Inter.inter.{u1} (Set.{u1} α) (Set.hasInter.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))) s) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))) t))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] (s : TopologicalSpace.Closeds.{u1} α _inst_1) (t : TopologicalSpace.Closeds.{u1} α _inst_1), Eq.{succ u1} (Set.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1) (Inf.inf.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Lattice.toInf.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (ConditionallyCompleteLattice.toLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u1} α _inst_1)))) s t)) (Inter.inter.{u1} (Set.{u1} α) (Set.instInterSet.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1) s) (SetLike.coe.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1) t))
Case conversion may be inaccurate. Consider using '#align topological_space.closeds.coe_inf TopologicalSpace.Closeds.coe_infₓ'. -/
@[simp, norm_cast]
theorem coe_inf (s t : Closeds α) : (↑(s ⊓ t) : Set α) = s ∩ t :=
  rfl
#align topological_space.closeds.coe_inf TopologicalSpace.Closeds.coe_inf

/- warning: topological_space.closeds.coe_top -> TopologicalSpace.Closeds.coe_top is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α], Eq.{succ u1} (Set.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))) (Top.top.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toHasTop.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u1} α _inst_1)))) (Set.univ.{u1} α)
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α], Eq.{succ u1} (Set.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1) (Top.top.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toTop.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u1} α _inst_1)))) (Set.univ.{u1} α)
Case conversion may be inaccurate. Consider using '#align topological_space.closeds.coe_top TopologicalSpace.Closeds.coe_topₓ'. -/
@[simp, norm_cast]
theorem coe_top : (↑(⊤ : Closeds α) : Set α) = univ :=
  rfl
#align topological_space.closeds.coe_top TopologicalSpace.Closeds.coe_top

/- warning: topological_space.closeds.coe_bot -> TopologicalSpace.Closeds.coe_bot is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α], Eq.{succ u1} (Set.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))) (Bot.bot.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toHasBot.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u1} α _inst_1)))) (EmptyCollection.emptyCollection.{u1} (Set.{u1} α) (Set.hasEmptyc.{u1} α))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α], Eq.{succ u1} (Set.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1) (Bot.bot.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toBot.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u1} α _inst_1)))) (EmptyCollection.emptyCollection.{u1} (Set.{u1} α) (Set.instEmptyCollectionSet.{u1} α))
Case conversion may be inaccurate. Consider using '#align topological_space.closeds.coe_bot TopologicalSpace.Closeds.coe_botₓ'. -/
@[simp, norm_cast]
theorem coe_bot : (↑(⊥ : Closeds α) : Set α) = ∅ :=
  rfl
#align topological_space.closeds.coe_bot TopologicalSpace.Closeds.coe_bot

/- warning: topological_space.closeds.coe_Inf -> TopologicalSpace.Closeds.coe_infₛ is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] {S : Set.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)}, Eq.{succ u1} (Set.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))) (InfSet.infₛ.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (ConditionallyCompleteLattice.toHasInf.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u1} α _inst_1))) S)) (Set.interᵢ.{u1, succ u1} α (TopologicalSpace.Closeds.{u1} α _inst_1) (fun (i : TopologicalSpace.Closeds.{u1} α _inst_1) => Set.interᵢ.{u1, 0} α (Membership.Mem.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)) (Set.hasMem.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)) i S) (fun (H : Membership.Mem.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)) (Set.hasMem.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)) i S) => (fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))) i)))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] {S : Set.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)}, Eq.{succ u1} (Set.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1) (InfSet.infₛ.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (ConditionallyCompleteLattice.toInfSet.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u1} α _inst_1))) S)) (Set.interᵢ.{u1, succ u1} α (TopologicalSpace.Closeds.{u1} α _inst_1) (fun (i : TopologicalSpace.Closeds.{u1} α _inst_1) => Set.interᵢ.{u1, 0} α (Membership.mem.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)) (Set.instMembershipSet.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)) i S) (fun (H : Membership.mem.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)) (Set.instMembershipSet.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)) i S) => SetLike.coe.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1) i)))
Case conversion may be inaccurate. Consider using '#align topological_space.closeds.coe_Inf TopologicalSpace.Closeds.coe_infₛₓ'. -/
@[simp, norm_cast]
theorem coe_infₛ {S : Set (Closeds α)} : (↑(infₛ S) : Set α) = ⋂ i ∈ S, ↑i :=
  rfl
#align topological_space.closeds.coe_Inf TopologicalSpace.Closeds.coe_infₛ

/- warning: topological_space.closeds.coe_finset_sup -> TopologicalSpace.Closeds.coe_finset_sup is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {α : Type.{u2}} [_inst_1 : TopologicalSpace.{u2} α] (f : ι -> (TopologicalSpace.Closeds.{u2} α _inst_1)) (s : Finset.{u1} ι), Eq.{succ u2} (Set.{u2} α) ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (TopologicalSpace.Closeds.{u2} α _inst_1) (Set.{u2} α) (HasLiftT.mk.{succ u2, succ u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (Set.{u2} α) (CoeTCₓ.coe.{succ u2, succ u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (Set.{u2} α) (SetLike.Set.hasCoeT.{u2, u2} (TopologicalSpace.Closeds.{u2} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u2} α _inst_1)))) (Finset.sup.{u2, u1} (TopologicalSpace.Closeds.{u2} α _inst_1) ι (Lattice.toSemilatticeSup.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (ConditionallyCompleteLattice.toLattice.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u2} α _inst_1)))) (BoundedOrder.toOrderBot.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (Preorder.toLE.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (PartialOrder.toPreorder.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (SemilatticeSup.toPartialOrder.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (Lattice.toSemilatticeSup.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (ConditionallyCompleteLattice.toLattice.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u2} α _inst_1))))))) (CompleteLattice.toBoundedOrder.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u2} α _inst_1))) s f)) (Finset.sup.{u2, u1} (Set.{u2} α) ι (Lattice.toSemilatticeSup.{u2} (Set.{u2} α) (ConditionallyCompleteLattice.toLattice.{u2} (Set.{u2} α) (CompleteLattice.toConditionallyCompleteLattice.{u2} (Set.{u2} α) (Order.Coframe.toCompleteLattice.{u2} (Set.{u2} α) (CompleteDistribLattice.toCoframe.{u2} (Set.{u2} α) (CompleteBooleanAlgebra.toCompleteDistribLattice.{u2} (Set.{u2} α) (Set.completeBooleanAlgebra.{u2} α))))))) (GeneralizedBooleanAlgebra.toOrderBot.{u2} (Set.{u2} α) (BooleanAlgebra.toGeneralizedBooleanAlgebra.{u2} (Set.{u2} α) (Set.booleanAlgebra.{u2} α))) s (Function.comp.{succ u1, succ u2, succ u2} ι (TopologicalSpace.Closeds.{u2} α _inst_1) (Set.{u2} α) ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (TopologicalSpace.Closeds.{u2} α _inst_1) (Set.{u2} α) (HasLiftT.mk.{succ u2, succ u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (Set.{u2} α) (CoeTCₓ.coe.{succ u2, succ u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (Set.{u2} α) (SetLike.Set.hasCoeT.{u2, u2} (TopologicalSpace.Closeds.{u2} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u2} α _inst_1))))) f))
but is expected to have type
  forall {ι : Type.{u1}} {α : Type.{u2}} [_inst_1 : TopologicalSpace.{u2} α] (f : ι -> (TopologicalSpace.Closeds.{u2} α _inst_1)) (s : Finset.{u1} ι), Eq.{succ u2} (Set.{u2} α) (SetLike.coe.{u2, u2} (TopologicalSpace.Closeds.{u2} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u2} α _inst_1) (Finset.sup.{u2, u1} (TopologicalSpace.Closeds.{u2} α _inst_1) ι (Lattice.toSemilatticeSup.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (ConditionallyCompleteLattice.toLattice.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u2} α _inst_1)))) (BoundedOrder.toOrderBot.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (Preorder.toLE.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (PartialOrder.toPreorder.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (SemilatticeSup.toPartialOrder.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (Lattice.toSemilatticeSup.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (ConditionallyCompleteLattice.toLattice.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u2} α _inst_1))))))) (CompleteLattice.toBoundedOrder.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u2} α _inst_1))) s f)) (Finset.sup.{u2, u1} (Set.{u2} α) ι (Lattice.toSemilatticeSup.{u2} (Set.{u2} α) (ConditionallyCompleteLattice.toLattice.{u2} (Set.{u2} α) (CompleteLattice.toConditionallyCompleteLattice.{u2} (Set.{u2} α) (Order.Coframe.toCompleteLattice.{u2} (Set.{u2} α) (CompleteDistribLattice.toCoframe.{u2} (Set.{u2} α) (CompleteBooleanAlgebra.toCompleteDistribLattice.{u2} (Set.{u2} α) (Set.instCompleteBooleanAlgebraSet.{u2} α))))))) (BoundedOrder.toOrderBot.{u2} (Set.{u2} α) (Preorder.toLE.{u2} (Set.{u2} α) (PartialOrder.toPreorder.{u2} (Set.{u2} α) (SemilatticeSup.toPartialOrder.{u2} (Set.{u2} α) (Lattice.toSemilatticeSup.{u2} (Set.{u2} α) (ConditionallyCompleteLattice.toLattice.{u2} (Set.{u2} α) (CompleteLattice.toConditionallyCompleteLattice.{u2} (Set.{u2} α) (Order.Coframe.toCompleteLattice.{u2} (Set.{u2} α) (CompleteDistribLattice.toCoframe.{u2} (Set.{u2} α) (CompleteBooleanAlgebra.toCompleteDistribLattice.{u2} (Set.{u2} α) (Set.instCompleteBooleanAlgebraSet.{u2} α)))))))))) (CompleteLattice.toBoundedOrder.{u2} (Set.{u2} α) (Order.Coframe.toCompleteLattice.{u2} (Set.{u2} α) (CompleteDistribLattice.toCoframe.{u2} (Set.{u2} α) (CompleteBooleanAlgebra.toCompleteDistribLattice.{u2} (Set.{u2} α) (Set.instCompleteBooleanAlgebraSet.{u2} α)))))) s (Function.comp.{succ u1, succ u2, succ u2} ι (TopologicalSpace.Closeds.{u2} α _inst_1) (Set.{u2} α) (SetLike.coe.{u2, u2} (TopologicalSpace.Closeds.{u2} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u2} α _inst_1)) f))
Case conversion may be inaccurate. Consider using '#align topological_space.closeds.coe_finset_sup TopologicalSpace.Closeds.coe_finset_supₓ'. -/
@[simp, norm_cast]
theorem coe_finset_sup (f : ι → Closeds α) (s : Finset ι) :
    (↑(s.sup f) : Set α) = s.sup (coe ∘ f) :=
  map_finset_sup (⟨⟨coe, coe_sup⟩, coe_bot⟩ : SupBotHom (Closeds α) (Set α)) _ _
#align topological_space.closeds.coe_finset_sup TopologicalSpace.Closeds.coe_finset_sup

/- warning: topological_space.closeds.coe_finset_inf -> TopologicalSpace.Closeds.coe_finset_inf is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {α : Type.{u2}} [_inst_1 : TopologicalSpace.{u2} α] (f : ι -> (TopologicalSpace.Closeds.{u2} α _inst_1)) (s : Finset.{u1} ι), Eq.{succ u2} (Set.{u2} α) ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (TopologicalSpace.Closeds.{u2} α _inst_1) (Set.{u2} α) (HasLiftT.mk.{succ u2, succ u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (Set.{u2} α) (CoeTCₓ.coe.{succ u2, succ u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (Set.{u2} α) (SetLike.Set.hasCoeT.{u2, u2} (TopologicalSpace.Closeds.{u2} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u2} α _inst_1)))) (Finset.inf.{u2, u1} (TopologicalSpace.Closeds.{u2} α _inst_1) ι (Lattice.toSemilatticeInf.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (ConditionallyCompleteLattice.toLattice.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u2} α _inst_1)))) (BoundedOrder.toOrderTop.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (Preorder.toLE.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (PartialOrder.toPreorder.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (SemilatticeInf.toPartialOrder.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (Lattice.toSemilatticeInf.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (ConditionallyCompleteLattice.toLattice.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u2} α _inst_1))))))) (CompleteLattice.toBoundedOrder.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u2} α _inst_1))) s f)) (Finset.inf.{u2, u1} (Set.{u2} α) ι (Lattice.toSemilatticeInf.{u2} (Set.{u2} α) (ConditionallyCompleteLattice.toLattice.{u2} (Set.{u2} α) (CompleteLattice.toConditionallyCompleteLattice.{u2} (Set.{u2} α) (Order.Coframe.toCompleteLattice.{u2} (Set.{u2} α) (CompleteDistribLattice.toCoframe.{u2} (Set.{u2} α) (CompleteBooleanAlgebra.toCompleteDistribLattice.{u2} (Set.{u2} α) (Set.completeBooleanAlgebra.{u2} α))))))) (Set.orderTop.{u2} α) s (Function.comp.{succ u1, succ u2, succ u2} ι (TopologicalSpace.Closeds.{u2} α _inst_1) (Set.{u2} α) ((fun (a : Type.{u2}) (b : Type.{u2}) [self : HasLiftT.{succ u2, succ u2} a b] => self.0) (TopologicalSpace.Closeds.{u2} α _inst_1) (Set.{u2} α) (HasLiftT.mk.{succ u2, succ u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (Set.{u2} α) (CoeTCₓ.coe.{succ u2, succ u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (Set.{u2} α) (SetLike.Set.hasCoeT.{u2, u2} (TopologicalSpace.Closeds.{u2} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u2} α _inst_1))))) f))
but is expected to have type
  forall {ι : Type.{u1}} {α : Type.{u2}} [_inst_1 : TopologicalSpace.{u2} α] (f : ι -> (TopologicalSpace.Closeds.{u2} α _inst_1)) (s : Finset.{u1} ι), Eq.{succ u2} (Set.{u2} α) (SetLike.coe.{u2, u2} (TopologicalSpace.Closeds.{u2} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u2} α _inst_1) (Finset.inf.{u2, u1} (TopologicalSpace.Closeds.{u2} α _inst_1) ι (Lattice.toSemilatticeInf.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (ConditionallyCompleteLattice.toLattice.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u2} α _inst_1)))) (BoundedOrder.toOrderTop.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (Preorder.toLE.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (PartialOrder.toPreorder.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (SemilatticeInf.toPartialOrder.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (Lattice.toSemilatticeInf.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (ConditionallyCompleteLattice.toLattice.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u2} α _inst_1))))))) (CompleteLattice.toBoundedOrder.{u2} (TopologicalSpace.Closeds.{u2} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u2} α _inst_1))) s f)) (Finset.inf.{u2, u1} (Set.{u2} α) ι (Lattice.toSemilatticeInf.{u2} (Set.{u2} α) (ConditionallyCompleteLattice.toLattice.{u2} (Set.{u2} α) (CompleteLattice.toConditionallyCompleteLattice.{u2} (Set.{u2} α) (Order.Coframe.toCompleteLattice.{u2} (Set.{u2} α) (CompleteDistribLattice.toCoframe.{u2} (Set.{u2} α) (CompleteBooleanAlgebra.toCompleteDistribLattice.{u2} (Set.{u2} α) (Set.instCompleteBooleanAlgebraSet.{u2} α))))))) (Set.instOrderTopSetInstLESet.{u2} α) s (Function.comp.{succ u1, succ u2, succ u2} ι (TopologicalSpace.Closeds.{u2} α _inst_1) (Set.{u2} α) (SetLike.coe.{u2, u2} (TopologicalSpace.Closeds.{u2} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u2} α _inst_1)) f))
Case conversion may be inaccurate. Consider using '#align topological_space.closeds.coe_finset_inf TopologicalSpace.Closeds.coe_finset_infₓ'. -/
@[simp, norm_cast]
theorem coe_finset_inf (f : ι → Closeds α) (s : Finset ι) :
    (↑(s.inf f) : Set α) = s.inf (coe ∘ f) :=
  map_finset_inf (⟨⟨coe, coe_inf⟩, coe_top⟩ : InfTopHom (Closeds α) (Set α)) _ _
#align topological_space.closeds.coe_finset_inf TopologicalSpace.Closeds.coe_finset_inf

/- warning: topological_space.closeds.infi_def -> TopologicalSpace.Closeds.infᵢ_def is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] {ι : Sort.{u2}} (s : ι -> (TopologicalSpace.Closeds.{u1} α _inst_1)), Eq.{succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (infᵢ.{u1, u2} (TopologicalSpace.Closeds.{u1} α _inst_1) (ConditionallyCompleteLattice.toHasInf.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u1} α _inst_1))) ι (fun (i : ι) => s i)) (TopologicalSpace.Closeds.mk.{u1} α _inst_1 (Set.interᵢ.{u1, u2} α ι (fun (i : ι) => (fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))) (s i))) (isClosed_interᵢ.{u1, u2} α ι _inst_1 (fun (i : ι) => (fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))) (s i)) (fun (i : ι) => TopologicalSpace.Closeds.closed'.{u1} α _inst_1 (s i))))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] {ι : Sort.{u2}} (s : ι -> (TopologicalSpace.Closeds.{u1} α _inst_1)), Eq.{succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (infᵢ.{u1, u2} (TopologicalSpace.Closeds.{u1} α _inst_1) (ConditionallyCompleteLattice.toInfSet.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u1} α _inst_1))) ι (fun (i : ι) => s i)) (TopologicalSpace.Closeds.mk.{u1} α _inst_1 (Set.interᵢ.{u1, u2} α ι (fun (i : ι) => SetLike.coe.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1) (s i))) (isClosed_interᵢ.{u1, u2} α ι _inst_1 (fun (i : ι) => SetLike.coe.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1) (s i)) (fun (i : ι) => TopologicalSpace.Closeds.closed'.{u1} α _inst_1 (s i))))
Case conversion may be inaccurate. Consider using '#align topological_space.closeds.infi_def TopologicalSpace.Closeds.infᵢ_defₓ'. -/
theorem infᵢ_def {ι} (s : ι → Closeds α) :
    (⨅ i, s i) = ⟨⋂ i, s i, isClosed_interᵢ fun i => (s i).2⟩ :=
  by
  ext
  simp only [infᵢ, coe_Inf, bInter_range]
  rfl
#align topological_space.closeds.infi_def TopologicalSpace.Closeds.infᵢ_def

/- warning: topological_space.closeds.infi_mk -> TopologicalSpace.Closeds.infᵢ_mk is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] {ι : Sort.{u2}} (s : ι -> (Set.{u1} α)) (h : forall (i : ι), IsClosed.{u1} α _inst_1 (s i)), Eq.{succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (infᵢ.{u1, u2} (TopologicalSpace.Closeds.{u1} α _inst_1) (ConditionallyCompleteLattice.toHasInf.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u1} α _inst_1))) ι (fun (i : ι) => TopologicalSpace.Closeds.mk.{u1} α _inst_1 (s i) (h i))) (TopologicalSpace.Closeds.mk.{u1} α _inst_1 (Set.interᵢ.{u1, u2} α ι (fun (i : ι) => s i)) (isClosed_interᵢ.{u1, u2} α ι _inst_1 (fun (i : ι) => s i) h))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] {ι : Sort.{u2}} (s : ι -> (Set.{u1} α)) (h : forall (i : ι), IsClosed.{u1} α _inst_1 (s i)), Eq.{succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (infᵢ.{u1, u2} (TopologicalSpace.Closeds.{u1} α _inst_1) (ConditionallyCompleteLattice.toInfSet.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u1} α _inst_1))) ι (fun (i : ι) => TopologicalSpace.Closeds.mk.{u1} α _inst_1 (s i) (h i))) (TopologicalSpace.Closeds.mk.{u1} α _inst_1 (Set.interᵢ.{u1, u2} α ι (fun (i : ι) => s i)) (isClosed_interᵢ.{u1, u2} α ι _inst_1 (fun (i : ι) => s i) h))
Case conversion may be inaccurate. Consider using '#align topological_space.closeds.infi_mk TopologicalSpace.Closeds.infᵢ_mkₓ'. -/
@[simp]
theorem infᵢ_mk {ι} (s : ι → Set α) (h : ∀ i, IsClosed (s i)) :
    (⨅ i, ⟨s i, h i⟩ : Closeds α) = ⟨⋂ i, s i, isClosed_interᵢ h⟩ := by simp [infi_def]
#align topological_space.closeds.infi_mk TopologicalSpace.Closeds.infᵢ_mk

/- warning: topological_space.closeds.coe_infi -> TopologicalSpace.Closeds.coe_infᵢ is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] {ι : Sort.{u2}} (s : ι -> (TopologicalSpace.Closeds.{u1} α _inst_1)), Eq.{succ u1} (Set.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))) (infᵢ.{u1, u2} (TopologicalSpace.Closeds.{u1} α _inst_1) (ConditionallyCompleteLattice.toHasInf.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u1} α _inst_1))) ι (fun (i : ι) => s i))) (Set.interᵢ.{u1, u2} α ι (fun (i : ι) => (fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))) (s i)))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] {ι : Sort.{u2}} (s : ι -> (TopologicalSpace.Closeds.{u1} α _inst_1)), Eq.{succ u1} (Set.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1) (infᵢ.{u1, u2} (TopologicalSpace.Closeds.{u1} α _inst_1) (ConditionallyCompleteLattice.toInfSet.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u1} α _inst_1))) ι (fun (i : ι) => s i))) (Set.interᵢ.{u1, u2} α ι (fun (i : ι) => SetLike.coe.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1) (s i)))
Case conversion may be inaccurate. Consider using '#align topological_space.closeds.coe_infi TopologicalSpace.Closeds.coe_infᵢₓ'. -/
@[simp, norm_cast]
theorem coe_infᵢ {ι} (s : ι → Closeds α) : ((⨅ i, s i : Closeds α) : Set α) = ⋂ i, s i := by
  simp [infi_def]
#align topological_space.closeds.coe_infi TopologicalSpace.Closeds.coe_infᵢ

/- warning: topological_space.closeds.mem_infi -> TopologicalSpace.Closeds.mem_infᵢ is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] {ι : Sort.{u2}} {x : α} {s : ι -> (TopologicalSpace.Closeds.{u1} α _inst_1)}, Iff (Membership.Mem.{u1, u1} α (TopologicalSpace.Closeds.{u1} α _inst_1) (SetLike.hasMem.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)) x (infᵢ.{u1, u2} (TopologicalSpace.Closeds.{u1} α _inst_1) (ConditionallyCompleteLattice.toHasInf.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u1} α _inst_1))) ι s)) (forall (i : ι), Membership.Mem.{u1, u1} α (TopologicalSpace.Closeds.{u1} α _inst_1) (SetLike.hasMem.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)) x (s i))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] {ι : Sort.{u2}} {x : α} {s : ι -> (TopologicalSpace.Closeds.{u1} α _inst_1)}, Iff (Membership.mem.{u1, u1} α (TopologicalSpace.Closeds.{u1} α _inst_1) (SetLike.instMembership.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1)) x (infᵢ.{u1, u2} (TopologicalSpace.Closeds.{u1} α _inst_1) (ConditionallyCompleteLattice.toInfSet.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u1} α _inst_1))) ι s)) (forall (i : ι), Membership.mem.{u1, u1} α (TopologicalSpace.Closeds.{u1} α _inst_1) (SetLike.instMembership.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1)) x (s i))
Case conversion may be inaccurate. Consider using '#align topological_space.closeds.mem_infi TopologicalSpace.Closeds.mem_infᵢₓ'. -/
@[simp]
theorem mem_infᵢ {ι} {x : α} {s : ι → Closeds α} : x ∈ infᵢ s ↔ ∀ i, x ∈ s i := by
  simp [← SetLike.mem_coe]
#align topological_space.closeds.mem_infi TopologicalSpace.Closeds.mem_infᵢ

/- warning: topological_space.closeds.mem_Inf -> TopologicalSpace.Closeds.mem_infₛ is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] {S : Set.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)} {x : α}, Iff (Membership.Mem.{u1, u1} α (TopologicalSpace.Closeds.{u1} α _inst_1) (SetLike.hasMem.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)) x (InfSet.infₛ.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (ConditionallyCompleteLattice.toHasInf.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u1} α _inst_1))) S)) (forall (s : TopologicalSpace.Closeds.{u1} α _inst_1), (Membership.Mem.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)) (Set.hasMem.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)) s S) -> (Membership.Mem.{u1, u1} α (TopologicalSpace.Closeds.{u1} α _inst_1) (SetLike.hasMem.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)) x s))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] {S : Set.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)} {x : α}, Iff (Membership.mem.{u1, u1} α (TopologicalSpace.Closeds.{u1} α _inst_1) (SetLike.instMembership.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1)) x (InfSet.infₛ.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (ConditionallyCompleteLattice.toInfSet.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toConditionallyCompleteLattice.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u1} α _inst_1))) S)) (forall (s : TopologicalSpace.Closeds.{u1} α _inst_1), (Membership.mem.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Set.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)) (Set.instMembershipSet.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)) s S) -> (Membership.mem.{u1, u1} α (TopologicalSpace.Closeds.{u1} α _inst_1) (SetLike.instMembership.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.instSetLikeCloseds.{u1} α _inst_1)) x s))
Case conversion may be inaccurate. Consider using '#align topological_space.closeds.mem_Inf TopologicalSpace.Closeds.mem_infₛₓ'. -/
@[simp]
theorem mem_infₛ {S : Set (Closeds α)} {x : α} : x ∈ infₛ S ↔ ∀ s ∈ S, x ∈ s := by
  simp_rw [infₛ_eq_infᵢ, mem_infi]
#align topological_space.closeds.mem_Inf TopologicalSpace.Closeds.mem_infₛ

instance : Coframe (Closeds α) :=
  { Closeds.completeLattice with
    infₛ := infₛ
    infᵢ_sup_le_sup_inf := fun a s =>
      (SetLike.coe_injective <| by simp only [coe_sup, coe_infi, coe_Inf, Set.union_interᵢ₂]).le }

#print TopologicalSpace.Closeds.singleton /-
/-- The term of `closeds α` corresponding to a singleton. -/
@[simps]
def singleton [T1Space α] (x : α) : Closeds α :=
  ⟨{x}, isClosed_singleton⟩
#align topological_space.closeds.singleton TopologicalSpace.Closeds.singleton
-/

end Closeds

#print TopologicalSpace.Closeds.compl /-
/-- The complement of a closed set as an open set. -/
@[simps]
def Closeds.compl (s : Closeds α) : Opens α :=
  ⟨sᶜ, s.2.isOpen_compl⟩
#align topological_space.closeds.compl TopologicalSpace.Closeds.compl
-/

#print TopologicalSpace.Opens.compl /-
/-- The complement of an open set as a closed set. -/
@[simps]
def Opens.compl (s : Opens α) : Closeds α :=
  ⟨sᶜ, s.2.isClosed_compl⟩
#align topological_space.opens.compl TopologicalSpace.Opens.compl
-/

#print TopologicalSpace.Closeds.compl_compl /-
theorem Closeds.compl_compl (s : Closeds α) : s.compl.compl = s :=
  Closeds.ext (compl_compl s)
#align topological_space.closeds.compl_compl TopologicalSpace.Closeds.compl_compl
-/

#print TopologicalSpace.Opens.compl_compl /-
theorem Opens.compl_compl (s : Opens α) : s.compl.compl = s :=
  Opens.ext (compl_compl s)
#align topological_space.opens.compl_compl TopologicalSpace.Opens.compl_compl
-/

#print TopologicalSpace.Closeds.compl_bijective /-
theorem Closeds.compl_bijective : Function.Bijective (@Closeds.compl α _) :=
  Function.bijective_iff_has_inverse.mpr ⟨Opens.compl, Closeds.compl_compl, Opens.compl_compl⟩
#align topological_space.closeds.compl_bijective TopologicalSpace.Closeds.compl_bijective
-/

#print TopologicalSpace.Opens.compl_bijective /-
theorem Opens.compl_bijective : Function.Bijective (@Opens.compl α _) :=
  Function.bijective_iff_has_inverse.mpr ⟨Closeds.compl, Opens.compl_compl, Closeds.compl_compl⟩
#align topological_space.opens.compl_bijective TopologicalSpace.Opens.compl_bijective
-/

variable (α)

/- warning: topological_space.closeds.compl_order_iso -> TopologicalSpace.Closeds.complOrderIso is a dubious translation:
lean 3 declaration is
  forall (α : Type.{u1}) [_inst_1 : TopologicalSpace.{u1} α], OrderIso.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (OrderDual.{u1} (TopologicalSpace.Opens.{u1} α _inst_1)) (Preorder.toLE.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (SetLike.partialOrder.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))) (OrderDual.hasLe.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (Preorder.toLE.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (SetLike.partialOrder.{u1, u1} (TopologicalSpace.Opens.{u1} α _inst_1) α (TopologicalSpace.Opens.setLike.{u1} α _inst_1)))))
but is expected to have type
  forall (α : Type.{u1}) [_inst_1 : TopologicalSpace.{u1} α], OrderIso.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (OrderDual.{u1} (TopologicalSpace.Opens.{u1} α _inst_1)) (Preorder.toLE.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteSemilatticeInf.toPartialOrder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toCompleteSemilatticeInf.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u1} α _inst_1))))) (OrderDual.instLEOrderDual.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (Preorder.toLE.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (CompleteSemilatticeInf.toPartialOrder.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (CompleteLattice.toCompleteSemilatticeInf.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (TopologicalSpace.Opens.instCompleteLatticeOpens.{u1} α _inst_1))))))
Case conversion may be inaccurate. Consider using '#align topological_space.closeds.compl_order_iso TopologicalSpace.Closeds.complOrderIsoₓ'. -/
/-- `closeds.compl` as an `order_iso` to the order dual of `opens α`. -/
@[simps]
def Closeds.complOrderIso : Closeds α ≃o (Opens α)ᵒᵈ
    where
  toFun := OrderDual.toDual ∘ Closeds.compl
  invFun := Opens.compl ∘ OrderDual.ofDual
  left_inv s := by simp [closeds.compl_compl]
  right_inv s := by simp [opens.compl_compl]
  map_rel_iff' s t := by
    simpa only [Equiv.coe_fn_mk, Function.comp_apply, OrderDual.toDual_le_toDual] using
      compl_subset_compl
#align topological_space.closeds.compl_order_iso TopologicalSpace.Closeds.complOrderIso

/- warning: topological_space.opens.compl_order_iso -> TopologicalSpace.Opens.complOrderIso is a dubious translation:
lean 3 declaration is
  forall (α : Type.{u1}) [_inst_1 : TopologicalSpace.{u1} α], OrderIso.{u1, u1} (TopologicalSpace.Opens.{u1} α _inst_1) (OrderDual.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)) (Preorder.toLE.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (SetLike.partialOrder.{u1, u1} (TopologicalSpace.Opens.{u1} α _inst_1) α (TopologicalSpace.Opens.setLike.{u1} α _inst_1)))) (OrderDual.hasLe.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Preorder.toLE.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (SetLike.partialOrder.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))))
but is expected to have type
  forall (α : Type.{u1}) [_inst_1 : TopologicalSpace.{u1} α], OrderIso.{u1, u1} (TopologicalSpace.Opens.{u1} α _inst_1) (OrderDual.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1)) (Preorder.toLE.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (CompleteSemilatticeInf.toPartialOrder.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (CompleteLattice.toCompleteSemilatticeInf.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (TopologicalSpace.Opens.instCompleteLatticeOpens.{u1} α _inst_1))))) (OrderDual.instLEOrderDual.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Preorder.toLE.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteSemilatticeInf.toPartialOrder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toCompleteSemilatticeInf.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u1} α _inst_1))))))
Case conversion may be inaccurate. Consider using '#align topological_space.opens.compl_order_iso TopologicalSpace.Opens.complOrderIsoₓ'. -/
/-- `opens.compl` as an `order_iso` to the order dual of `closeds α`. -/
@[simps]
def Opens.complOrderIso : Opens α ≃o (Closeds α)ᵒᵈ
    where
  toFun := OrderDual.toDual ∘ Opens.compl
  invFun := Closeds.compl ∘ OrderDual.ofDual
  left_inv s := by simp [opens.compl_compl]
  right_inv s := by simp [closeds.compl_compl]
  map_rel_iff' s t := by
    simpa only [Equiv.coe_fn_mk, Function.comp_apply, OrderDual.toDual_le_toDual] using
      compl_subset_compl
#align topological_space.opens.compl_order_iso TopologicalSpace.Opens.complOrderIso

variable {α}

/- warning: topological_space.closeds.is_atom_iff -> TopologicalSpace.Closeds.isAtom_iff is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_3 : T1Space.{u1} α _inst_1] {s : TopologicalSpace.Closeds.{u1} α _inst_1}, Iff (IsAtom.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (SetLike.partialOrder.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1))) (BoundedOrder.toOrderBot.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Preorder.toLE.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (SetLike.partialOrder.{u1, u1} (TopologicalSpace.Closeds.{u1} α _inst_1) α (TopologicalSpace.Closeds.setLike.{u1} α _inst_1)))) (CompleteLattice.toBoundedOrder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.completeLattice.{u1} α _inst_1))) s) (Exists.{succ u1} α (fun (x : α) => Eq.{succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) s (TopologicalSpace.Closeds.singleton.{u1} α _inst_1 _inst_3 x)))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_3 : T1Space.{u1} α _inst_1] {s : TopologicalSpace.Closeds.{u1} α _inst_1}, Iff (IsAtom.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteSemilatticeInf.toPartialOrder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toCompleteSemilatticeInf.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u1} α _inst_1)))) (BoundedOrder.toOrderBot.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (Preorder.toLE.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteSemilatticeInf.toPartialOrder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (CompleteLattice.toCompleteSemilatticeInf.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u1} α _inst_1))))) (CompleteLattice.toBoundedOrder.{u1} (TopologicalSpace.Closeds.{u1} α _inst_1) (TopologicalSpace.Closeds.instCompleteLatticeCloseds.{u1} α _inst_1))) s) (Exists.{succ u1} α (fun (x : α) => Eq.{succ u1} (TopologicalSpace.Closeds.{u1} α _inst_1) s (TopologicalSpace.Closeds.singleton.{u1} α _inst_1 _inst_3 x)))
Case conversion may be inaccurate. Consider using '#align topological_space.closeds.is_atom_iff TopologicalSpace.Closeds.isAtom_iffₓ'. -/
/-- in a `t1_space`, atoms of `closeds α` are precisely the `closeds.singleton`s. -/
theorem Closeds.isAtom_iff [T1Space α] {s : Closeds α} : IsAtom s ↔ ∃ x, s = Closeds.singleton x :=
  by
  have : IsAtom (s : Set α) ↔ IsAtom s :=
    by
    refine' closeds.gi.is_atom_iff' rfl (fun t ht => _) s
    obtain ⟨x, rfl⟩ := t.is_atom_iff.mp ht
    exact closure_singleton
  simpa only [← this, (s : Set α).isAtom_iff, SetLike.ext_iff, Set.ext_iff]
#align topological_space.closeds.is_atom_iff TopologicalSpace.Closeds.isAtom_iff

/- warning: topological_space.opens.is_coatom_iff -> TopologicalSpace.Opens.isCoatom_iff is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_3 : T1Space.{u1} α _inst_1] {s : TopologicalSpace.Opens.{u1} α _inst_1}, Iff (IsCoatom.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (SetLike.partialOrder.{u1, u1} (TopologicalSpace.Opens.{u1} α _inst_1) α (TopologicalSpace.Opens.setLike.{u1} α _inst_1))) (BoundedOrder.toOrderTop.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (Preorder.toLE.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (SetLike.partialOrder.{u1, u1} (TopologicalSpace.Opens.{u1} α _inst_1) α (TopologicalSpace.Opens.setLike.{u1} α _inst_1)))) (CompleteLattice.toBoundedOrder.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (TopologicalSpace.Opens.completeLattice.{u1} α _inst_1))) s) (Exists.{succ u1} α (fun (x : α) => Eq.{succ u1} (TopologicalSpace.Opens.{u1} α _inst_1) s (TopologicalSpace.Closeds.compl.{u1} α _inst_1 (TopologicalSpace.Closeds.singleton.{u1} α _inst_1 _inst_3 x))))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] [_inst_3 : T1Space.{u1} α _inst_1] {s : TopologicalSpace.Opens.{u1} α _inst_1}, Iff (IsCoatom.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (CompleteSemilatticeInf.toPartialOrder.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (CompleteLattice.toCompleteSemilatticeInf.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (TopologicalSpace.Opens.instCompleteLatticeOpens.{u1} α _inst_1)))) (BoundedOrder.toOrderTop.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (Preorder.toLE.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (PartialOrder.toPreorder.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (CompleteSemilatticeInf.toPartialOrder.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (CompleteLattice.toCompleteSemilatticeInf.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (TopologicalSpace.Opens.instCompleteLatticeOpens.{u1} α _inst_1))))) (CompleteLattice.toBoundedOrder.{u1} (TopologicalSpace.Opens.{u1} α _inst_1) (TopologicalSpace.Opens.instCompleteLatticeOpens.{u1} α _inst_1))) s) (Exists.{succ u1} α (fun (x : α) => Eq.{succ u1} (TopologicalSpace.Opens.{u1} α _inst_1) s (TopologicalSpace.Closeds.compl.{u1} α _inst_1 (TopologicalSpace.Closeds.singleton.{u1} α _inst_1 _inst_3 x))))
Case conversion may be inaccurate. Consider using '#align topological_space.opens.is_coatom_iff TopologicalSpace.Opens.isCoatom_iffₓ'. -/
/- ./././Mathport/Syntax/Translate/Tactic/Builtin.lean:73:14: unsupported tactic `congrm #[[expr «expr∃ , »((x), _)]] -/
/-- in a `t1_space`, coatoms of `opens α` are precisely complements of singletons:
`(closeds.singleton x).compl`. -/
theorem Opens.isCoatom_iff [T1Space α] {s : Opens α} :
    IsCoatom s ↔ ∃ x, s = (Closeds.singleton x).compl :=
  by
  rw [← s.compl_compl, ← isAtom_dual_iff_isCoatom]
  change IsAtom (closeds.compl_order_iso α s.compl) ↔ _
  rw [(closeds.compl_order_iso α).isAtom_iff, closeds.is_atom_iff]
  trace
    "./././Mathport/Syntax/Translate/Tactic/Builtin.lean:73:14: unsupported tactic `congrm #[[expr «expr∃ , »((x), _)]]"
  exact closeds.compl_bijective.injective.eq_iff.symm
#align topological_space.opens.is_coatom_iff TopologicalSpace.Opens.isCoatom_iff

/-! ### Clopen sets -/

#print TopologicalSpace.Clopens /-
/-- The type of clopen sets of a topological space. -/
structure Clopens (α : Type _) [TopologicalSpace α] where
  carrier : Set α
  clopen' : IsClopen carrier
#align topological_space.clopens TopologicalSpace.Clopens
-/

namespace Clopens

instance : SetLike (Clopens α) α where
  coe s := s.carrier
  coe_injective' s t h := by
    cases s
    cases t
    congr

#print TopologicalSpace.Clopens.clopen /-
theorem clopen (s : Clopens α) : IsClopen (s : Set α) :=
  s.clopen'
#align topological_space.clopens.clopen TopologicalSpace.Clopens.clopen
-/

#print TopologicalSpace.Clopens.toOpens /-
/-- Reinterpret a compact open as an open. -/
@[simps]
def toOpens (s : Clopens α) : Opens α :=
  ⟨s, s.clopen.IsOpen⟩
#align topological_space.clopens.to_opens TopologicalSpace.Clopens.toOpens
-/

#print TopologicalSpace.Clopens.ext /-
@[ext]
protected theorem ext {s t : Clopens α} (h : (s : Set α) = t) : s = t :=
  SetLike.ext' h
#align topological_space.clopens.ext TopologicalSpace.Clopens.ext
-/

#print TopologicalSpace.Clopens.coe_mk /-
@[simp]
theorem coe_mk (s : Set α) (h) : (mk s h : Set α) = s :=
  rfl
#align topological_space.clopens.coe_mk TopologicalSpace.Clopens.coe_mk
-/

instance : Sup (Clopens α) :=
  ⟨fun s t => ⟨s ∪ t, s.clopen.union t.clopen⟩⟩

instance : Inf (Clopens α) :=
  ⟨fun s t => ⟨s ∩ t, s.clopen.inter t.clopen⟩⟩

instance : Top (Clopens α) :=
  ⟨⟨⊤, isClopen_univ⟩⟩

instance : Bot (Clopens α) :=
  ⟨⟨⊥, isClopen_empty⟩⟩

instance : SDiff (Clopens α) :=
  ⟨fun s t => ⟨s \ t, s.clopen.diffₓ t.clopen⟩⟩

instance : HasCompl (Clopens α) :=
  ⟨fun s => ⟨sᶜ, s.clopen.compl⟩⟩

instance : BooleanAlgebra (Clopens α) :=
  SetLike.coe_injective.BooleanAlgebra _ (fun _ _ => rfl) (fun _ _ => rfl) rfl rfl (fun _ => rfl)
    fun _ _ => rfl

/- warning: topological_space.clopens.coe_sup -> TopologicalSpace.Clopens.coe_sup is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] (s : TopologicalSpace.Clopens.{u1} α _inst_1) (t : TopologicalSpace.Clopens.{u1} α _inst_1), Eq.{succ u1} (Set.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.setLike.{u1} α _inst_1)))) (Sup.sup.{u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (TopologicalSpace.Clopens.hasSup.{u1} α _inst_1) s t)) (Union.union.{u1} (Set.{u1} α) (Set.hasUnion.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.setLike.{u1} α _inst_1)))) s) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.setLike.{u1} α _inst_1)))) t))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] (s : TopologicalSpace.Clopens.{u1} α _inst_1) (t : TopologicalSpace.Clopens.{u1} α _inst_1), Eq.{succ u1} (Set.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.instSetLikeClopens.{u1} α _inst_1) (Sup.sup.{u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (TopologicalSpace.Clopens.instSupClopens.{u1} α _inst_1) s t)) (Union.union.{u1} (Set.{u1} α) (Set.instUnionSet.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.instSetLikeClopens.{u1} α _inst_1) s) (SetLike.coe.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.instSetLikeClopens.{u1} α _inst_1) t))
Case conversion may be inaccurate. Consider using '#align topological_space.clopens.coe_sup TopologicalSpace.Clopens.coe_supₓ'. -/
@[simp]
theorem coe_sup (s t : Clopens α) : (↑(s ⊔ t) : Set α) = s ∪ t :=
  rfl
#align topological_space.clopens.coe_sup TopologicalSpace.Clopens.coe_sup

/- warning: topological_space.clopens.coe_inf -> TopologicalSpace.Clopens.coe_inf is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] (s : TopologicalSpace.Clopens.{u1} α _inst_1) (t : TopologicalSpace.Clopens.{u1} α _inst_1), Eq.{succ u1} (Set.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.setLike.{u1} α _inst_1)))) (Inf.inf.{u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (TopologicalSpace.Clopens.hasInf.{u1} α _inst_1) s t)) (Inter.inter.{u1} (Set.{u1} α) (Set.hasInter.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.setLike.{u1} α _inst_1)))) s) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.setLike.{u1} α _inst_1)))) t))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] (s : TopologicalSpace.Clopens.{u1} α _inst_1) (t : TopologicalSpace.Clopens.{u1} α _inst_1), Eq.{succ u1} (Set.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.instSetLikeClopens.{u1} α _inst_1) (Inf.inf.{u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (TopologicalSpace.Clopens.instInfClopens.{u1} α _inst_1) s t)) (Inter.inter.{u1} (Set.{u1} α) (Set.instInterSet.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.instSetLikeClopens.{u1} α _inst_1) s) (SetLike.coe.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.instSetLikeClopens.{u1} α _inst_1) t))
Case conversion may be inaccurate. Consider using '#align topological_space.clopens.coe_inf TopologicalSpace.Clopens.coe_infₓ'. -/
@[simp]
theorem coe_inf (s t : Clopens α) : (↑(s ⊓ t) : Set α) = s ∩ t :=
  rfl
#align topological_space.clopens.coe_inf TopologicalSpace.Clopens.coe_inf

/- warning: topological_space.clopens.coe_top -> TopologicalSpace.Clopens.coe_top is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α], Eq.{succ u1} (Set.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.setLike.{u1} α _inst_1)))) (Top.top.{u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (TopologicalSpace.Clopens.hasTop.{u1} α _inst_1))) (Set.univ.{u1} α)
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α], Eq.{succ u1} (Set.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.instSetLikeClopens.{u1} α _inst_1) (Top.top.{u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (TopologicalSpace.Clopens.instTopClopens.{u1} α _inst_1))) (Set.univ.{u1} α)
Case conversion may be inaccurate. Consider using '#align topological_space.clopens.coe_top TopologicalSpace.Clopens.coe_topₓ'. -/
@[simp]
theorem coe_top : (↑(⊤ : Clopens α) : Set α) = univ :=
  rfl
#align topological_space.clopens.coe_top TopologicalSpace.Clopens.coe_top

/- warning: topological_space.clopens.coe_bot -> TopologicalSpace.Clopens.coe_bot is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α], Eq.{succ u1} (Set.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.setLike.{u1} α _inst_1)))) (Bot.bot.{u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (TopologicalSpace.Clopens.hasBot.{u1} α _inst_1))) (EmptyCollection.emptyCollection.{u1} (Set.{u1} α) (Set.hasEmptyc.{u1} α))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α], Eq.{succ u1} (Set.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.instSetLikeClopens.{u1} α _inst_1) (Bot.bot.{u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (TopologicalSpace.Clopens.instBotClopens.{u1} α _inst_1))) (EmptyCollection.emptyCollection.{u1} (Set.{u1} α) (Set.instEmptyCollectionSet.{u1} α))
Case conversion may be inaccurate. Consider using '#align topological_space.clopens.coe_bot TopologicalSpace.Clopens.coe_botₓ'. -/
@[simp]
theorem coe_bot : (↑(⊥ : Clopens α) : Set α) = ∅ :=
  rfl
#align topological_space.clopens.coe_bot TopologicalSpace.Clopens.coe_bot

/- warning: topological_space.clopens.coe_sdiff -> TopologicalSpace.Clopens.coe_sdiff is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] (s : TopologicalSpace.Clopens.{u1} α _inst_1) (t : TopologicalSpace.Clopens.{u1} α _inst_1), Eq.{succ u1} (Set.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.setLike.{u1} α _inst_1)))) (SDiff.sdiff.{u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (TopologicalSpace.Clopens.hasSdiff.{u1} α _inst_1) s t)) (SDiff.sdiff.{u1} (Set.{u1} α) (BooleanAlgebra.toHasSdiff.{u1} (Set.{u1} α) (Set.booleanAlgebra.{u1} α)) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.setLike.{u1} α _inst_1)))) s) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.setLike.{u1} α _inst_1)))) t))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] (s : TopologicalSpace.Clopens.{u1} α _inst_1) (t : TopologicalSpace.Clopens.{u1} α _inst_1), Eq.{succ u1} (Set.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.instSetLikeClopens.{u1} α _inst_1) (SDiff.sdiff.{u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (TopologicalSpace.Clopens.instSDiffClopens.{u1} α _inst_1) s t)) (SDiff.sdiff.{u1} (Set.{u1} α) (Set.instSDiffSet.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.instSetLikeClopens.{u1} α _inst_1) s) (SetLike.coe.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.instSetLikeClopens.{u1} α _inst_1) t))
Case conversion may be inaccurate. Consider using '#align topological_space.clopens.coe_sdiff TopologicalSpace.Clopens.coe_sdiffₓ'. -/
@[simp]
theorem coe_sdiff (s t : Clopens α) : (↑(s \ t) : Set α) = s \ t :=
  rfl
#align topological_space.clopens.coe_sdiff TopologicalSpace.Clopens.coe_sdiff

/- warning: topological_space.clopens.coe_compl -> TopologicalSpace.Clopens.coe_compl is a dubious translation:
lean 3 declaration is
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] (s : TopologicalSpace.Clopens.{u1} α _inst_1), Eq.{succ u1} (Set.{u1} α) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.setLike.{u1} α _inst_1)))) (HasCompl.compl.{u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (TopologicalSpace.Clopens.hasCompl.{u1} α _inst_1) s)) (HasCompl.compl.{u1} (Set.{u1} α) (BooleanAlgebra.toHasCompl.{u1} (Set.{u1} α) (Set.booleanAlgebra.{u1} α)) ((fun (a : Type.{u1}) (b : Type.{u1}) [self : HasLiftT.{succ u1, succ u1} a b] => self.0) (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (HasLiftT.mk.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (CoeTCₓ.coe.{succ u1, succ u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (Set.{u1} α) (SetLike.Set.hasCoeT.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.setLike.{u1} α _inst_1)))) s))
but is expected to have type
  forall {α : Type.{u1}} [_inst_1 : TopologicalSpace.{u1} α] (s : TopologicalSpace.Clopens.{u1} α _inst_1), Eq.{succ u1} (Set.{u1} α) (SetLike.coe.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.instSetLikeClopens.{u1} α _inst_1) (HasCompl.compl.{u1} (TopologicalSpace.Clopens.{u1} α _inst_1) (TopologicalSpace.Clopens.instHasComplClopens.{u1} α _inst_1) s)) (HasCompl.compl.{u1} (Set.{u1} α) (BooleanAlgebra.toHasCompl.{u1} (Set.{u1} α) (Set.instBooleanAlgebraSet.{u1} α)) (SetLike.coe.{u1, u1} (TopologicalSpace.Clopens.{u1} α _inst_1) α (TopologicalSpace.Clopens.instSetLikeClopens.{u1} α _inst_1) s))
Case conversion may be inaccurate. Consider using '#align topological_space.clopens.coe_compl TopologicalSpace.Clopens.coe_complₓ'. -/
@[simp]
theorem coe_compl (s : Clopens α) : (↑(sᶜ) : Set α) = sᶜ :=
  rfl
#align topological_space.clopens.coe_compl TopologicalSpace.Clopens.coe_compl

instance : Inhabited (Clopens α) :=
  ⟨⊥⟩

end Clopens

end TopologicalSpace


-- Topology facts about ℂ

import data.complex.basic
import data.real.basic
import data.real.nnreal
import data.real.pi.bounds
import data.set.basic
import topology.metric_space.basic

import simple
import tactics

open metric (ball closed_ball)
open filter (at_top)
open_locale real nnreal topological_space

noncomputable theory

lemma open_has_cball {s : set ℂ} (o : is_open s) (z ∈ s) : ∃ r : ℝ≥0, r > 0 ∧ closed_ball z r ⊆ s := begin
  rw metric.is_open_iff at o,
  have oz := o z H,
  rcases oz with ⟨t,ht,bs⟩,
  set r : ℝ≥0 := (t / 2).to_nnreal,
  existsi r,
  split,
  refine real.to_nnreal_pos.mp _,
  simp, linarith,
  calc closed_ball z r ⊆ ball z t : metric.closed_ball_subset_ball _
  ... ⊆ s : bs,
  calc ↑r = t/2 : real.coe_to_nnreal (t/2) (by linarith)
  ... < t : by bound
end

lemma nhd_has_ball {z : ℂ} {s : set ℂ} (h : s ∈ 𝓝 z) : ∃ r, r > 0 ∧ metric.ball z r ⊆ s := begin
  rcases mem_nhds_iff.mp h with ⟨so,os,iso,zso⟩,
  rcases metric.is_open_iff.mp iso z zso with ⟨r,rp,rb⟩,
  existsi r, constructor, assumption,
  transitivity so, assumption, assumption
end

-- If something is true near c, it is true at c
lemma filter.eventually.self {A : Type} [topological_space A] {p : A → Prop} {x : A}
    (h : ∀ᶠ y in nhds x, p y) : p x := begin
  rcases eventually_nhds_iff.mp h with ⟨s,ps,_,xs⟩,
  exact ps x xs,
end

-- Continuous functions achieve their supremum on compact sets
lemma continuous_on.compact_max {A B : Type} [topological_space A] [topological_space B]
    [conditionally_complete_linear_order B] [order_topology B]
    {f : A → B} {s : set A} (fc : continuous_on f s) (cs : is_compact s) (sn : s.nonempty)
    : ∃ x, x ∈ s ∧ is_max_on f s x := begin
  have ic := is_compact.image_of_continuous_on cs fc,
  have ss := is_compact.Sup_mem ic (set.nonempty_image_iff.mpr sn),
  rcases (set.mem_image _ _ _).mp ss with ⟨x,xs,xm⟩,
  existsi [x, xs],
  rw is_max_on_iff, intros y ys, rw xm,
  exact le_cSup ic.bdd_above ((set.mem_image _ _ _).mpr ⟨y,ys,rfl⟩),
end

-- Continuous functions on compact sets are bounded
lemma continuous_on.bounded {X : Type} [topological_space X]
    {f : X → ℝ} {s : set X} (fc : continuous_on f s) (sc : is_compact s)
    : ∃ b : ℝ, b ≥ 0 ∧ ∀ x, x ∈ s → f x ≤ b := begin
  by_cases n : s.nonempty, {
    rcases fc.compact_max sc n with ⟨x,xs,xm⟩,
    use [max 0 (f x), by bound], intros y ys, exact trans (xm ys) (by bound),
  }, {
    rw set.not_nonempty_iff_eq_empty at n,
    existsi [(0 : ℝ), le_refl _], simp [n],
  },
end

-- Continuous functions on compact sets have bounded norm
lemma continuous_on.bounded_norm {X Y : Type} [topological_space X] [normed_add_comm_group Y]
    {f : X → Y} {s : set X} (fc : continuous_on f s) (sc : is_compact s)
    : ∃ b : ℝ, b ≥ 0 ∧ ∀ x, x ∈ s → ∥f x∥ ≤ b := begin
  by_cases n : s.nonempty, {
    have nc : continuous_on (λ x, ∥f x∥) s := continuous_norm.comp_continuous_on fc,
    rcases nc.compact_max sc n with ⟨x,xs,xm⟩,
    existsi [∥f x∥, norm_nonneg _], intros y ys, exact xm ys,
  }, {
    rw set.not_nonempty_iff_eq_empty at n,
    existsi [(0 : ℝ), le_refl _], simp [n],
  }
end

-- Uniform cauchy sequences are cauchy sequences at points
lemma uniform_cauchy_seq_on.cauchy_seq {X Y : Type} [topological_space X] [metric_space Y]
    {f : ℕ → X → Y} {s : set X} (u : uniform_cauchy_seq_on f at_top s)
    : ∀ x, x ∈ s → cauchy_seq (λ n, f n x) := begin
  intros x xs,
  rw metric.cauchy_seq_iff,
  rw metric.uniform_cauchy_seq_on_iff at u,
  intros e ep, rcases u e ep with ⟨N,H⟩,
  existsi N, intros a aN b bN,
  exact H a aN b bN x xs,
end

-- Uniform cauchy sequences on compact sets are uniformly bounded
lemma uniform_cauchy_seq_on.bounded {X Y : Type} [topological_space X] [normed_add_comm_group Y]
    {f : ℕ → X → Y} {s : set X} (u : uniform_cauchy_seq_on f at_top s) (fc : ∀ n, continuous_on (f n) s) (sc : is_compact s)
    : ∃ b : ℝ, b ≥ 0 ∧ ∀ n x, x ∈ s → ∥f n x∥ ≤ b := begin
  set c := λ n, classical.some ((fc n).bounded_norm sc),
  have cs : ∀ n, 0 ≤ c n ∧ ∀ x, x ∈ s → ∥f n x∥ ≤ c n := λ n, classical.some_spec ((fc n).bounded_norm sc),
  rw metric.uniform_cauchy_seq_on_iff at u,
  rcases u 1 (by norm_num) with ⟨N,H⟩, clear u,
  set bs := finset.image c (finset.range (N+1)),
  have c0 : c 0 ∈ bs, { simp, existsi 0, simp },
  set b := 1 + bs.max' ⟨_,c0⟩,
  existsi b, constructor, {
    bound [trans (cs 0).1 (finset.le_max' _ _ c0)],
  }, {
    intros n x xs,
    by_cases nN : n ≤ N, {
      have cn : c n ∈ bs, { simp, existsi n, simp [nat.lt_add_one_iff.mpr nN] },
      exact trans ((cs n).2 x xs) (trans (finset.le_max' _ _ cn) (by bound)),
    }, {
      simp at nN,
      specialize H N (by bound) n (by bound) x xs,
      have cN : c N ∈ bs, { simp, existsi N, simp },
      have bN := trans ((cs N).2 x xs) (finset.le_max' _ _ cN),
      rw dist_eq_norm at H,
      calc ∥f n x∥ = ∥f N x - (f N x - f n x)∥ : by abel
      ... ≤ ∥f N x∥ + ∥f N x - f n x∥ : by bound
      ... ≤ bs.max' _ + 1 : by bound
      ... = 1 + bs.max' _ : by abel
      ... = b : rfl,
    }
  },
end

-- Functions from empty spaces are continuous
lemma is_empty.continuous {A B : Type} [topological_space A] [topological_space B]
    [is_empty A] (f : A → B) : continuous f := begin
  rw continuous_def, intros s o,
  have e : f ⁻¹' s = ∅, { apply set.subset_eq_empty (set.subset_univ _), simp, apply_instance },
  simp [e],
end


/-
Copyright (c) 2021 Ashvni Narayanan. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Ashvni Narayanan, Anne Baanen
-/

import ring_theory.dedekind_domain.integral_closure
import algebra.char_p.algebra

/-!
# Number fields
This file defines a number field, the ring of integers corresponding to it and includes some
basic facts about the embeddings into an algebraic closed field.

## Main definitions
 - `number_field` defines a number field as a field which has characteristic zero and is finite
    dimensional over ℚ.
 - `ring_of_integers` defines the ring of integers (or number ring) corresponding to a number field
    as the integral closure of ℤ in the number field.

## Main Result
 - `eq_roots`: let `x ∈ K` with `K` number field and let `A` be an algebraic closed field of
    char. 0, then the images of `x` by the embeddings of `K` in `A` are exactly the roots in
    `A` of the minimal polynomial of `x` over `ℚ`.

## Implementation notes
The definitions that involve a field of fractions choose a canonical field of fractions,
but are independent of that choice.

## References
* [D. Marcus, *Number Fields*][marcus1977number]
* [J.W.S. Cassels, A. Frölich, *Algebraic Number Theory*][cassels1967algebraic]
* [P. Samuel, *Algebraic Theory of Numbers*][samuel1970algebraic]

## Tags
number field, ring of integers
-/

/-- A number field is a field which has characteristic zero and is finite
dimensional over ℚ. -/
class number_field (K : Type*) [field K] : Prop :=
[to_char_zero : char_zero K]
[to_finite_dimensional : finite_dimensional ℚ K]

open function
open_locale classical big_operators

/-- `ℤ` with its usual ring structure is not a field. -/
lemma int.not_is_field : ¬ is_field ℤ :=
λ h, int.not_even_one $ (h.mul_inv_cancel two_ne_zero).imp $ λ a, (by rw ← two_mul; exact eq.symm)

namespace number_field

variables (K L : Type*) [field K] [field L] [nf : number_field K]

include nf

-- See note [lower instance priority]
attribute [priority 100, instance] number_field.to_char_zero number_field.to_finite_dimensional

protected lemma is_algebraic : algebra.is_algebraic ℚ K := algebra.is_algebraic_of_finite _ _

omit nf

/-- The ring of integers (or number ring) corresponding to a number field
is the integral closure of ℤ in the number field. -/
def ring_of_integers := integral_closure ℤ K

localized "notation `𝓞` := number_field.ring_of_integers" in number_field

lemma mem_ring_of_integers (x : K) : x ∈ 𝓞 K ↔ is_integral ℤ x := iff.rfl

/-- Given an algebra between two fields, create an algebra between their two rings of integers.

For now, this is not an instance by default as it creates an equal-but-not-defeq diamond with
`algebra.id` when `K = L`. This is caused by `x = ⟨x, x.prop⟩` not being defeq on subtypes. This
will likely change in Lean 4. -/
def ring_of_integers_algebra [algebra K L] : algebra (𝓞 K) (𝓞 L) := ring_hom.to_algebra
{ to_fun := λ k, ⟨algebra_map K L k, is_integral.algebra_map k.2⟩,
  map_zero' := subtype.ext $ by simp only [subtype.coe_mk, subalgebra.coe_zero, map_zero],
  map_one'  := subtype.ext $ by simp only [subtype.coe_mk, subalgebra.coe_one, map_one],
  map_add' := λ x y, subtype.ext $ by simp only [map_add, subalgebra.coe_add, subtype.coe_mk],
  map_mul' := λ x y, subtype.ext $ by simp only [subalgebra.coe_mul, map_mul, subtype.coe_mk] }

namespace ring_of_integers

variables {K}

instance [number_field K] : is_fraction_ring (𝓞 K) K :=
integral_closure.is_fraction_ring_of_finite_extension ℚ _

instance : is_integral_closure (𝓞 K) ℤ K :=
integral_closure.is_integral_closure _ _

instance [number_field K] : is_integrally_closed (𝓞 K) :=
integral_closure.is_integrally_closed_of_finite_extension ℚ

lemma is_integral_coe (x : 𝓞 K) : is_integral ℤ (x : K) :=
x.2

/-- The ring of integers of `K` are equivalent to any integral closure of `ℤ` in `K` -/
protected noncomputable def equiv (R : Type*) [comm_ring R] [algebra R K]
  [is_integral_closure R ℤ K] : 𝓞 K ≃+* R :=
(is_integral_closure.equiv ℤ R K _).symm.to_ring_equiv

variables (K)

instance [number_field K] : char_zero (𝓞 K) := char_zero.of_module _ K

/-- The ring of integers of a number field is not a field. -/
lemma not_is_field [number_field K] : ¬ is_field (𝓞 K) :=
begin
  have h_inj : function.injective ⇑(algebra_map ℤ (𝓞 K)),
  { exact ring_hom.injective_int (algebra_map ℤ (𝓞 K)) },
  intro hf,
  exact int.not_is_field
    (((is_integral_closure.is_integral_algebra ℤ K).is_field_iff_is_field h_inj).mpr hf)
end

instance [number_field K] : is_dedekind_domain (𝓞 K) :=
is_integral_closure.is_dedekind_domain ℤ ℚ K _

end ring_of_integers

end number_field

namespace rat

open number_field

local attribute [instance] subsingleton_rat_module

instance rat.number_field : number_field ℚ :=
{ to_char_zero := infer_instance,
  to_finite_dimensional :=
    -- The vector space structure of `ℚ` over itself can arise in multiple ways:
    -- all fields are vector spaces over themselves (used in `rat.finite_dimensional`)
    -- all char 0 fields have a canonical embedding of `ℚ` (used in `number_field`).
    -- Show that these coincide:
    by convert (infer_instance : finite_dimensional ℚ ℚ), }

/-- The ring of integers of `ℚ` as a number field is just `ℤ`. -/
noncomputable def ring_of_integers_equiv : ring_of_integers ℚ ≃+* ℤ :=
ring_of_integers.equiv ℤ

end rat

namespace adjoin_root

section

open_locale polynomial

local attribute [-instance] algebra_rat

/-- The quotient of `ℚ[X]` by the ideal generated by an irreducible polynomial of `ℚ[X]`
is a number field. -/
instance {f : ℚ[X]} [hf : irreducible f] : number_field (adjoin_root f) :=
{ to_char_zero := char_zero_of_injective_algebra_map (algebra_map ℚ _).injective,
  to_finite_dimensional := begin
   let := (adjoin_root.power_basis (irreducible.ne_zero hf : f ≠ 0)),
   convert power_basis.finite_dimensional this,
   haveI : subsingleton (algebra ℚ (adjoin_root f)) := algebra_rat_subsingleton,
   exact subsingleton.elim _ _,
  end }

end

end adjoin_root

namespace number_field.embeddings

section number_field

open set finite_dimensional polynomial

variables {K L : Type*} [field K] [field L]
variables [number_field K] [number_field L]  (x : K)

variables {A : Type*} [field A] [char_zero A]

/-- There are finitely many embeddings of a number field. -/
noncomputable instance : fintype (K →+* A) := fintype.of_equiv (K →ₐ[ℚ] A)
ring_hom.equiv_rat_alg_hom.symm

variables [is_alg_closed A]

/-- The number of embeddings of a number field is its finrank. -/
lemma card : fintype.card (K →+* A) = finrank ℚ K :=
by rw [fintype.of_equiv_card ring_hom.equiv_rat_alg_hom.symm, alg_hom.card]

/-- For `x ∈ K`, with `K` a number field, the images of `x` by the embeddings of `K` are exactly
the roots of the minimal polynomial of `x` over `ℚ` -/
lemma eq_roots : range (λ φ : K →+* A, φ x) = (minpoly ℚ x).root_set A :=
begin
  have hx : is_integral ℚ x := is_separable.is_integral ℚ x,
  ext a, split,
  { rintro ⟨φ, hφ⟩,
    rw [mem_root_set_iff, ←hφ],
    { let ψ := ring_hom.equiv_rat_alg_hom φ,
      show (aeval (ψ x)) (minpoly ℚ x) = 0,
      rw aeval_alg_hom_apply ψ x (minpoly ℚ x),
      simp only [minpoly.aeval, map_zero], },
    exact minpoly.ne_zero hx, },
  { intro ha,
    let Qx := adjoin_root (minpoly ℚ x),
    haveI : irreducible (minpoly ℚ x) := minpoly.irreducible hx,
    have hK : (aeval x) (minpoly ℚ x) = 0, { exact minpoly.aeval _ _, },
    have hA : (aeval a) (minpoly ℚ x) = 0,
    { rw [aeval_def, ←eval_map, ←mem_root_set_iff'],
      exact ha,
      refine polynomial.monic.ne_zero _,
      exact polynomial.monic.map (algebra_map ℚ A) (minpoly.monic hx), },
    let ψ : Qx →+* A := adjoin_root.lift (algebra_map ℚ A) a hA,
    letI : algebra Qx A := ring_hom.to_algebra ψ,
    letI : algebra Qx K := ring_hom.to_algebra (adjoin_root.lift (algebra_map ℚ K) x hK),
    let φ₀ : K →ₐ[Qx] A := is_alg_closed.lift _,
    swap,
    { refine algebra.is_algebraic_of_larger_base ℚ Qx _,
      exact number_field.is_algebraic _, },
    let φ := φ₀.to_ring_hom,
    use φ,
    rw (_ : x = (algebra_map Qx K) (adjoin_root.root (minpoly ℚ x))),
    { rw (_ : a = ψ (adjoin_root.root (minpoly ℚ x))),
      refine alg_hom.commutes _ _,
      exact (adjoin_root.lift_root hA).symm, },
    exact (adjoin_root.lift_root hK).symm, },
end

end number_field

end number_field.embeddings


import .love10_denotational_semantics_demo

/- # LoVe Homework 10: Denotational Semantics

Homework must be done individually. -/

set_option pp.beta true
set_option pp.generalized_field_notation false

namespace LoVe

/- ## Question 1 (7 points): Denotational Semantics of DOWHILE -/

namespace do_while

/- Consider the following DOWHILE language: -/

inductive stmt : Type
| skip     : stmt
| assign   : string → (state → ℕ) → stmt
| seq      : stmt → stmt → stmt
| unless   : stmt → (state → Prop) → stmt
| while    : (state → Prop) → stmt → stmt
| do_while : stmt → (state → Prop) → stmt

infixr ` ;; ` : 90 := stmt.seq

/- The `skip`, `assign`, `seq`, and `while constructs are as for the WHILE
language.

`unless S b` executes `S` if `b` is false in the current state; otherwise, it
does nothing. This statement is inspired by Perl's `unless` conditional.

`do_while S b` first executes `S`. Then, if `b` is true in the resulting state,
it re-enters the loop and executes `S` again, and continues executing `S` until
`b` becomes `false`. The semantics is almost the same as `while b S`, except
that `p` is always executed at least once, even if the condition is not true
initially. This statement is inspired by C's and Java's `do { … } while (…)`
loop.

1.1 (2 points). Give a denotational semantics of DOWHILE.

Hint: Your definition should make it easy to prove lemma `do_while_while` in
question 1.2. -/

def denote : stmt → set (state × state)
| stmt.skip           := Id
-- enter the missing cases here

notation `⟦` S `⟧`:= denote S

/- 1.2 (1 point). Prove the following correspondence between `do_while` and
`while`. -/

lemma do_while_while (S : stmt) (b : state → Prop) :
  ⟦stmt.do_while S b⟧ = ⟦S⟧ ◯ ⟦stmt.while b S⟧ :=
sorry

/- 1.3 (4 points). Prove the following lemmas.

Hint: For all of these, short proofs are possible. -/

lemma lfp_const {α : Type} [complete_lattice α] (a : α) :
  lfp (λX, a) = a :=
sorry

lemma while_false (S : stmt) :
  ⟦stmt.while (λ_, false) S⟧ = Id :=
sorry

lemma comp_Id {α : Type} (r : set (α × α)) :
  r ◯ Id = r :=
sorry

lemma do_while_false (S : stmt) :
  ⟦stmt.do_while S (λ_, false)⟧ = ⟦S⟧ :=
sorry

end do_while

/- ## Question 2 (2 points + 2 bonus points): Kleene's Theorem

We can compute the fixpoint by iteration by taking the union of all finite
iterations of `f`:

    `lfp f = ⋃i, (f ^^ i) ∅`

where

    `f ^^ i = f ∘ ⋯ ∘ f`

iterates the function `f` `i` times. However, the above characterization of
`lfp` only holds for continuous functions, a concept we will introduce below. -/

def iterate {α : Type} (f : α → α) : ℕ → α → α
| 0       a := a
| (n + 1) a := f (iterate n a)

notation f`^^`n := iterate f n

/- 2.1 (2 points). Fill in the missing proofs below. -/

def Union {α : Type} (s : ℕ → set α) : set α :=
{a | ∃n, a ∈ s n}

lemma Union_le {α : Type} {s : ℕ → set α} (A : set α) (h : ∀i, s i ≤ A) :
  Union s ≤ A :=
sorry

/- A continuous function `f` is a function that commutes with the union of any
monotone sequence `s`: -/

def continuous {α : Type} (f : set α → set α) : Prop :=
∀s : ℕ → set α, monotone s → f (Union s) = Union (λi, f (s i))

/- We need to prove that each continuous function is monotone. To achieve this,
we will need the following sequence: -/

def bi_seq {α : Type} (A B : set α) : ℕ → set α
| 0       := A
| (n + 1) := B

/- For example, `bi_seq A B` is the sequence A, B, B, B, …. -/

lemma monotone_bi_seq {α : Type} (A B : set α) (h : A ≤ B) :
  monotone (bi_seq A B)
| 0       0       _ := le_refl _
| 0       (n + 1) _ := h
| (n + 1) (m + 1) _ := le_refl _

lemma Union_bi_seq {α : Type} (A B : set α) (ha : A ≤ B) :
  Union (bi_seq A B) = B :=
begin
  apply le_antisymm,
  { sorry },
  { sorry }
end

lemma monotone_of_continuous {α : Type} (f : set α → set α)
    (hf : continuous f) :
  monotone f :=
sorry

/- 2.2 (1 bonus point). Provide the following proof, using a similar case
distinction as for `monotone_bi_seq` above. -/

lemma monotone_iterate {α : Type} (f : set α → set α) (hf : monotone f) :
  monotone (λi, (f ^^ i) ∅) :=
sorry

/- 2.3 (1 bonus point). Prove the main theorem. A proof sketch is given below.

We break the proof into two proofs of inclusion.

Case 1. `lfp f ≤ Union (λi, (f ^^ i) ∅)`: The key is to use the lemma `lfp_le`
together with continuity of `f`.

Case 2. `Union (λi, (f ^^ i) ∅) ≤ lfp f`: The lemma `Union_le` gives us a
natural number `i`, on which you can perform induction. We also need the lemma
`lfp_eq` to unfold one iteration of `lfp f`. -/

lemma lfp_Kleene {α : Type} (f : set α → set α) (hf : continuous f) :
  lfp f = Union (λi, (f ^^ i) ∅) :=
sorry

end LoVe


import algebra.group.basic
import data.zmod.basic
import data.equiv.basic
import tactic
import data.set.basic

import .cayleys

variables {G₁ : Type*} {G₂ : Type*} [group G₁] [group G₂]

open equiv function set

def hom_induces_group (f : G₁ →* G₂) : group (range f) :=
{ mul := has_mul.mul,
  mul_assoc := mul_assoc,
  one := has_one.one,
  one_mul := one_mul,
  mul_one := mul_one,
  inv := has_inv.inv,
  mul_left_inv := mul_left_inv,
}

def ψ (h : G₁ ≃* G₂): perm G₁ → perm G₂ := λ θ,
{ to_fun := h.1 ∘ θ.1 ∘ h.2,
  inv_fun := h.1 ∘ θ.2 ∘ h.2,
  left_inv := begin
    intro x,
    calc (h.to_fun ∘ θ.inv_fun ∘ h.inv_fun) ((h.to_fun ∘ θ.to_fun ∘ h.inv_fun) x)
          = (h.to_fun ∘ θ.inv_fun ∘ (h.inv_fun ∘ h.to_fun) ∘ θ.to_fun ∘ h.inv_fun) x : rfl
      ... = (h.to_fun ∘ θ.inv_fun ∘ id ∘ θ.to_fun ∘ h.inv_fun) x : by rw left_inverse.id h.3
      ... = (h.to_fun ∘ (θ.inv_fun ∘ θ.to_fun) ∘ h.inv_fun) x : rfl
      ... = (h.to_fun ∘ id ∘ h.inv_fun) x : by rw left_inverse.id θ.3
      ... = (h.to_fun ∘ h.inv_fun) x : rfl
      ... = id x : by rw right_inverse.id h.4,
  end,
  right_inv := begin
    intro x,
    calc (h.to_fun ∘ θ.to_fun ∘ h.inv_fun) ((h.to_fun ∘ θ.inv_fun ∘ h.inv_fun) x)
          = (h.to_fun ∘ θ.to_fun ∘ (h.inv_fun ∘ h.to_fun) ∘ θ.inv_fun ∘ h.inv_fun) x : rfl
      ... = (h.to_fun ∘ θ.to_fun ∘ id ∘ θ.inv_fun ∘ h.inv_fun) x : by rw left_inverse.id h.3
      ... = (h.to_fun ∘ (θ.to_fun ∘ θ.inv_fun) ∘ h.inv_fun) x : rfl
      ... = (h.to_fun ∘ id ∘ h.inv_fun) x : by rw right_inverse.id θ.4
      ... = (h.to_fun ∘ h.inv_fun) x : rfl
      ... = id x : by rw right_inverse.id h.4,
  end,
}

lemma embedding_diagram_com (h : G₁ ≃* G₂)
  : (ψ h) ∘ (lift_to_perm G₁).1 = (lift_to_perm G₂).1 ∘ h.1 := begin
  ext g x,
  have H₁ : ((ψ h ∘ (lift_to_perm G₁).to_fun) g) x = (h.1 g) * x,
    calc ((ψ h ∘ (lift_to_perm G₁).to_fun) g) x
          = h.1 (g * (h.2 x)) : rfl
      ... = (h.1 g) * (h.1 (h.2 x)) : mul_equiv.map_mul h g (h.inv_fun x)
      ... = (h.1 g) * ((h.1 ∘ h.2) x) : rfl
      ... = (h.1 g) * (id x) : by rw right_inverse.id h.4,
  have H₂ : (((lift_to_perm G₂).to_fun ∘ h.1) g) x = (h.1 g) * x := rfl,
  rw [H₁, H₂],
end