[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Topology.Separation.Basic).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
theorem IsCompact.closure_of_subset {s K : Set X} (hK : IsCompact K) (h : s ⊆ K) :
    IsCompact (closure s)
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Topology.Separation.Basic.t0Space_iff_inseparable (L81-L84)
theorem t0Space_iff_inseparable (X : Type u) [TopologicalSpace X] :
    T0Space X ↔ ∀ x y : X, Inseparable x y → x = y :=
⟨fun ⟨h⟩ => h, fun h => ⟨h⟩⟩
```

-- snippet 2
```lean
-- Mathlib.Topology.Separation.Basic.t0Space_iff_not_inseparable (L85-L88)
theorem t0Space_iff_not_inseparable (X : Type u) [TopologicalSpace X] :
    T0Space X ↔ Pairwise fun x y : X => ¬Inseparable x y := by
simp only [t0Space_iff_inseparable, Ne, not_imp_not, Pairwise]
```

-- snippet 3
```lean
-- Mathlib.Topology.Separation.Basic.Inseparable (L89-L101)
theorem Inseparable.eq [T0Space X] {x y : X} (h : Inseparable x y) : x = y :=
T0Space.t0 h

/-- A topology inducing map from a T₀ space is injective. -/
protected theorem Topology.IsInducing.injective [TopologicalSpace Y] [T0Space X] {f : X → Y}
    (hf : IsInducing f) : Injective f := fun _ _ h =>
  (hf.inseparable_iff.1 <| .of_eq h).eq

/-- A topology inducing map from a T₀ space is a topological embedding. -/
protected theorem Topology.IsInducing.isEmbedding [TopologicalSpace Y] [T0Space X] {f : X → Y}
    (hf : IsInducing f) : IsEmbedding f :=
  ⟨hf, hf.injective⟩
```

-- snippet 4
```lean
-- Mathlib.Topology.Separation.Basic.isEmbedding_iff_isInducing (L102-L105)
lemma isEmbedding_iff_isInducing [TopologicalSpace Y] [T0Space X] {f : X → Y} :
    IsEmbedding f ↔ IsInducing f :=
⟨IsEmbedding.isInducing, IsInducing.isEmbedding⟩
```

-- snippet 5
```lean
-- Mathlib.Topology.Separation.Basic.t0Space_iff_nhds_injective (L106-L109)
theorem t0Space_iff_nhds_injective (X : Type u) [TopologicalSpace X] :
    T0Space X ↔ Injective (𝓝 : X → Filter X) :=
t0Space_iff_inseparable X
```

-- snippet 6
```lean
-- Mathlib.Topology.Separation.Basic.nhds_injective (L110-L112)
theorem nhds_injective [T0Space X] : Injective (𝓝 : X → Filter X) :=
(t0Space_iff_nhds_injective X).1 ‹_›
```

-- snippet 7
```lean
-- Mathlib.Topology.Separation.Basic.inseparable_iff_eq (L113-L115)
theorem inseparable_iff_eq [T0Space X] {x y : X} : Inseparable x y ↔ x = y :=
nhds_injective.eq_iff
```

-- snippet 8
```lean
-- Mathlib.Topology.Separation.Basic.nhds_eq_nhds_iff (L117-L119)
theorem nhds_eq_nhds_iff [T0Space X] {a b : X} : 𝓝 a = 𝓝 b ↔ a = b :=
nhds_injective.eq_iff
```

-- snippet 9
```lean
-- Mathlib.Topology.Separation.Basic.inseparable_eq_eq (L121-L123)
theorem inseparable_eq_eq [T0Space X] : Inseparable = @Eq X :=
funext₂ fun _ _ => propext inseparable_iff_eq
```

-- snippet 10
```lean
-- Mathlib.Topology.Separation.Basic.TopologicalSpace (L124-L130)
theorem TopologicalSpace.IsTopologicalBasis.inseparable_iff {b : Set (Set X)}
    (hb : IsTopologicalBasis b) {x y : X} : Inseparable x y ↔ ∀ s ∈ b, (x ∈ s ↔ y ∈ s) :=
⟨fun h _ hs ↦ inseparable_iff_forall_isOpen.1 h _ (hb.isOpen hs),
    fun h ↦ hb.nhds_hasBasis.eq_of_same_basis <| by
      convert hb.nhds_hasBasis using 2
      exact and_congr_right (h _)⟩
```

-- snippet 11
```lean
-- Mathlib.Topology.Separation.Basic.TopologicalSpace (L131-L134)
theorem TopologicalSpace.IsTopologicalBasis.eq_iff [T0Space X] {b : Set (Set X)}
    (hb : IsTopologicalBasis b) {x y : X} : x = y ↔ ∀ s ∈ b, (x ∈ s ↔ y ∈ s) :=
inseparable_iff_eq.symm.trans hb.inseparable_iff
```

-- snippet 12
```lean
-- Mathlib.Topology.Separation.Basic.t0Space_iff_exists_isOpen_xor'_mem (L135-L139)
theorem t0Space_iff_exists_isOpen_xor'_mem (X : Type u) [TopologicalSpace X] :
    T0Space X ↔ Pairwise fun x y => ∃ U : Set X, IsOpen U ∧ Xor' (x ∈ U) (y ∈ U) := by
simp only [t0Space_iff_not_inseparable, xor_iff_not_iff, not_forall, exists_prop,
    inseparable_iff_forall_isOpen, Pairwise]
```

-- snippet 13
```lean
-- Mathlib.Topology.Separation.Basic.exists_isOpen_xor'_mem (L140-L144)
theorem exists_isOpen_xor'_mem [T0Space X] {x y : X} (h : x ≠ y) :
    ∃ U : Set X, IsOpen U ∧ Xor' (x ∈ U) (y ∈ U) :=
(t0Space_iff_exists_isOpen_xor'_mem X).1 ‹_› h

/-- Specialization forms a partial order on a t0 topological space. -/
```

-- snippet 14
```lean
-- Mathlib.Topology.Separation.Basic.specializationOrder (L146-L148)
def specializationOrder (X) [TopologicalSpace X] [T0Space X] : PartialOrder X :=
{ specializationPreorder X, PartialOrder.lift (OrderDual.toDual ∘ 𝓝) nhds_injective with }
```

-- snippet 15
```lean
-- Mathlib.Topology.Separation.Basic.SeparationQuotient (L149-L152)
instance SeparationQuotient.instT0Space : T0Space (SeparationQuotient X) :=
⟨fun x y => Quotient.inductionOn₂' x y fun _ _ h =>
    SeparationQuotient.mk_eq_mk.2 <| SeparationQuotient.isInducing_mk.inseparable_iff.1 h⟩
```

-- snippet 16
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.completelyRegularSpace_inf (L154-L158)
lemma completelyRegularSpace_inf {X : Type*} {t₁ t₂ : TopologicalSpace X}
    (ht₁ : @CompletelyRegularSpace X t₁) (ht₂ : @CompletelyRegularSpace X t₂) :
    @CompletelyRegularSpace X (t₁ ⊓ t₂) := by
rw [inf_eq_iInf]; apply completelyRegularSpace_iInf; simp [*]
```

-- snippet 17
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.completelyRegularSpace_iff_isOpen (L72-L78)
lemma completelyRegularSpace_iff_isOpen : CompletelyRegularSpace X ↔
    ∀ (x : X), ∀ K : Set X, IsOpen K → x ∈ K →
      ∃ f : X → I, Continuous f ∧ f x = 0 ∧ EqOn f 1 Kᶜ := by
conv_lhs => tactic =>
    simp_rw +singlePass [completelyRegularSpace_iff, compl_surjective.forall, isClosed_compl_iff,
      mem_compl_iff, not_not]
```

-- snippet 18
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.Topology (L109-L120)
lemma Topology.IsInducing.completelyRegularSpace
    {Y : Type v} [TopologicalSpace Y] [CompletelyRegularSpace Y]
    {f : X → Y} (hf : IsInducing f) : CompletelyRegularSpace X where
  completely_regular x K hK hxK := by
rw [hf.isClosed_iff] at hK
    obtain ⟨K, hK, rfl⟩ := hK
    rw [mem_preimage] at hxK
    obtain ⟨g, hcf, egfx, hgK⟩ := CompletelyRegularSpace.completely_regular _ _ hK hxK
    refine ⟨g ∘ f, hcf.comp hf.continuous, egfx, ?_⟩
    conv => arg 2; equals (1 : Y → ↥I) ∘ f => rfl
    exact hgK.comp_right <| mapsTo_preimage _ _
```

-- snippet 19
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.t35Space_iff_isEmbedding_stoneCechUnit (L270-L273)
lemma t35Space_iff_isEmbedding_stoneCechUnit :
    T35Space X ↔ IsEmbedding (stoneCechUnit : X → StoneCech X) where
  mp _ := isEmbedding_stoneCechUnit
mpr hs := hs.t35Space
```

-- snippet 20
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.isDenseInducing_stoneCechUnit (L186-L190)
lemma isDenseInducing_stoneCechUnit [CompletelyRegularSpace X] :
    IsDenseInducing (stoneCechUnit : X → StoneCech X) where
  toIsInducing := isInducing_stoneCechUnit
dense := denseRange_stoneCechUnit
```

-- snippet 21
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.separatesPoints_continuous_of_t35Space (L239-L245)
lemma separatesPoints_continuous_of_t35Space [T35Space X] :
    SeparatesPoints {f : X → ℝ | Continuous f} := by
intro x y x_ne_y
  obtain ⟨f, f_cont, f_zero, f_one⟩ :=
    CompletelyRegularSpace.completely_regular x {y} isClosed_singleton x_ne_y
  exact ⟨fun x ↦ f x, continuous_subtype_val.comp f_cont, by simp_all⟩
```

-- snippet 22
```lean
-- Mathlib.Topology.Separation.Connected.PreconnectedSpace (L30-L35)
theorem PreconnectedSpace.trivial_of_discrete [PreconnectedSpace X] [DiscreteTopology X] :
    Subsingleton X := by
by_contra! ⟨x, y, hxy⟩
  rw [Ne, ← mem_singleton_iff, (isClopen_discrete _).eq_univ <| singleton_nonempty y] at hxy
  exact hxy (mem_univ x)
```

-- snippet 23
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.isDenseEmbedding_stoneCechUnit (L265-L269)
lemma isDenseEmbedding_stoneCechUnit [T35Space X] :
    IsDenseEmbedding (stoneCechUnit : X → StoneCech X) where
  toIsDenseInducing := isDenseInducing_stoneCechUnit
injective := injective_stoneCechUnit_of_t35Space
```

-- snippet 24
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.isInducing_stoneCechUnit (L169-L185)
lemma isInducing_stoneCechUnit [CompletelyRegularSpace X] :
    IsInducing (stoneCechUnit : X → StoneCech X) := by
rw [isInducing_iff_nhds]
  intro x
  apply le_antisymm
  · rw [← map_le_iff_le_comap]; exact continuous_stoneCechUnit.continuousAt
  · simp_rw [le_nhds_iff, ((nhds_basis_opens _).comap _).mem_iff, and_assoc]
    intro U hxU hU
    obtain ⟨f, hf, efx, hfU⟩ :=
      CompletelyRegularSpace.completely_regular_isOpen x U hU hxU
    conv at hfU => equals Uᶜ ⊆ f ⁻¹' {1} => simp [EqOn, subset_def]
    rw [← compl_subset_comm, ← preimage_compl, ← stoneCechExtend_extends hf, preimage_comp] at hfU
    refine ⟨stoneCechExtend hf ⁻¹' {1}ᶜ, ?_,
      isOpen_compl_singleton.preimage (continuous_stoneCechExtend hf), hfU⟩
    rw [mem_preimage, stoneCechExtend_stoneCechUnit, efx, mem_compl_iff, mem_singleton_iff]
    simp
```

-- snippet 25
```lean
-- Mathlib.Topology.Separation.DisjointCover.exists_finite_nonempty_disjoint_clopen_cover (L56-L78)
lemma exists_finite_nonempty_disjoint_clopen_cover (hU : IsOpenCover U) :
    ∃ (n : ℕ) (W : Fin n → Clopens X), (∀ j, W j ≠ ⊥ ∧ ∃ i, (W j : Set X) ⊆ U i)
    ∧ (univ : Set X) ⊆ ⋃ j, ↑(W j) ∧ Pairwise (Disjoint on W) := by
classical
  obtain ⟨n, V, hVle, hVun⟩ := hU.exists_finite_clopen_cover
  obtain ⟨W, hWle, hWun, hWd⟩ := Fintype.exists_disjointed_le V
  simp only [← SetLike.coe_set_eq, Clopens.coe_finset_sup, Finset.mem_univ, iUnion_true] at hWun
  let t : Finset (Fin n) := {j | W j ≠ ⊥}
  refine ⟨#t, fun k ↦ W (t.equivFin.symm k), fun k ↦ ⟨?_, ?_⟩, fun x hx ↦ ?_, ?_⟩
  · exact (Finset.mem_filter.mp (t.equivFin.symm k).2).2
  · exact match hVle (t.equivFin.symm k) with | ⟨i, hi⟩ => ⟨i, subset_trans (hWle _) hi⟩
  · obtain ⟨j, hj⟩ := mem_iUnion.mp <| (hWun ▸ hVun) hx
    have : W j ≠ ⊥ := by simpa [← SetLike.coe_ne_coe, ← Set.nonempty_iff_ne_empty] using ⟨x, hj⟩
    exact mem_iUnion.mpr ⟨t.equivFin ⟨j, Finset.mem_filter.mpr ⟨Finset.mem_univ _, this⟩⟩, by simpa⟩
  · exact hWd.comp_of_injective <| Subtype.val_injective.comp t.equivFin.symm.injective

end TopologicalSpace.IsOpenCover

namespace TopologicalSpace
variable {X : Type*} [TopologicalSpace X] {S : Set (X × X)}

/-- If `S` is any neighbourhood of the diagonal in a topological space `X`, any point of `X` has an
open neighbourhood `U` such that `U ×ˢ U ⊆ S`. -/
```

-- snippet 26
```lean
-- Mathlib.Topology.Separation.DisjointCover.exists_disjoint_nonempty_clopen_cover_of_mem_nhds_diagonal (L127-L139)
lemma exists_disjoint_nonempty_clopen_cover_of_mem_nhds_diagonal (hS : S ∈ nhdsSet (diagonal V)) :
    ∃ (n : ℕ) (D : Fin n → Clopens X), (∀ i, D i ≠ ⊥) ∧ (∀ i, ∀ y ∈ D i, ∀ z ∈ D i, (f y, f z) ∈ S)
    ∧ (univ : Set X) ⊆ ⋃ i, D i ∧ Pairwise (Disjoint on D) := by
have : (f.prodMap f) ⁻¹' S ∈ nhdsSet (diagonal X) := by
    rw [mem_nhdsSet_iff_forall] at hS ⊢
    rintro ⟨x, y⟩ (rfl : x = y)
    exact (map_continuous _).continuousAt.preimage_mem_nhds (hS _ rfl)
  exact exists_finite_disjoint_nonempty_clopen_cover_of_mem_nhds_diagonal_of_profinite this

/--
For any continuous function `f : X → V`, with `X` profinite, and `S` a neighbourhood of the
diagonal in `V × V`, the function `f` can be `S`-approximated by a function factoring through
`Fin n`, for some `n`. -/
```

-- snippet 27
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.NormalSpace (L93-L108)
instance NormalSpace.instCompletelyRegularSpace [NormalSpace X] [R0Space X] :
    CompletelyRegularSpace X := by
rw [completelyRegularSpace_iff]
  intro x K hK hx
  have cx : IsClosed (closure {x}) := isClosed_closure
  have d : Disjoint (closure {x}) K := by
    rw [Set.disjoint_iff]
    intro a ⟨hax, haK⟩
    exact hx ((specializes_iff_mem_closure.mpr hax).symm.mem_closed hK haK)
  let ⟨⟨f, cf⟩, hfx, hfK, hficc⟩ := exists_continuous_zero_one_of_isClosed cx hK d
  let g : X → I := fun x => ⟨f x, hficc x⟩
  have cg : Continuous g := cf.subtype_mk hficc
  have hgx : g x = 0 := Subtype.ext (hfx (subset_closure (mem_singleton x)))
  have hgK : EqOn g 1 K := fun k hk => Subtype.ext (hfK hk)
  exact ⟨g, cg, hgx, hgK⟩
```

-- snippet 28
```lean
-- Mathlib.Topology.Separation.DisjointCover.exists_finite_open_cover_prod_subset_of_mem_nhds_diagonal_of_compact (L92-L126)
lemma exists_finite_open_cover_prod_subset_of_mem_nhds_diagonal_of_compact
    (hS : S ∈ nhdsSet (diagonal X)) :
    ∃ (t : Finset X) (U : t → Opens X), IsOpenCover U ∧ ∀ i, (U i : Set X) ×ˢ U i ⊆ S := by
choose U hUo hUx hUp using exists_open_prod_subset_of_mem_nhds_diagonal hS
  obtain ⟨t, ht⟩ := isCompact_univ.elim_finite_subcover _ hUo (fun x _ ↦ mem_iUnion.mpr ⟨_, hUx x⟩)
  refine ⟨t, fun i ↦ ⟨_, hUo i⟩, .of_sets _ ?_, (hUp ·)⟩
  simpa [iUnion_subtype, ← univ_subset_iff] using ht

variable [TotallyDisconnectedSpace X] [T2Space X]

/-- If `S` is any neighbourhood of the diagonal in a profinite topological space `X`, then there
exists a finite cover of `X` by disjoint nonempty clopens `U i` with `U i ×ˢ U i ⊆ S` for all `i`.
-/
private lemma exists_finite_disjoint_nonempty_clopen_cover_of_mem_nhds_diagonal_of_profinite
    (hS : S ∈ nhdsSet (diagonal X)) :
    ∃ (n : ℕ) (D : Fin n → Clopens X), (∀ i, D i ≠ ⊥) ∧ (∀ i, ∀ y ∈ D i, ∀ z ∈ D i, (y, z) ∈ S)
    ∧ (univ : Set X) ⊆ ⋃ i, D i ∧ Pairwise (Disjoint on D) := by
  obtain ⟨t, U, hUc, hUS⟩ := exists_finite_open_cover_prod_subset_of_mem_nhds_diagonal_of_compact hS
  -- Now refine it to a disjoint covering.
  obtain ⟨n, W, hW₁, hW₂, hW₃⟩ := hUc.exists_finite_nonempty_disjoint_clopen_cover
  refine ⟨n, W, fun j ↦ (hW₁ j).1, fun j y hy z hz ↦ ?_, hW₂, hW₃⟩
  exact match (hW₁ j).2 with | ⟨i, hi⟩ => hUS i ⟨hi hy, hi hz⟩

end TopologicalSpace

namespace ContinuousMap

variable {X V : Type*} [TopologicalSpace X] [TopologicalSpace V] [TotallyDisconnectedSpace X]
  [T2Space X] [CompactSpace X] {S : Set (V × V)} (f : C(X, V))

/--
For any continuous function `f : X → V`, with `X` profinite, and `S` a neighbourhood of the
diagonal in `V × V`, there exists a finite cover of `X` by pairwise-disjoint nonempty clopens, on
each of which `f` varies within `S`.
-/
```

-- snippet 29
```lean
-- Mathlib.Topology.Separation.DisjointCover.exists_finite_clopen_cover (L40-L55)
lemma exists_finite_clopen_cover (hU : IsOpenCover U) : ∃ (n : ℕ) (V : Fin n → Clopens X),
    (∀ j, ∃ i, (V j : Set X) ⊆ U i) ∧ univ ⊆ ⋃ j, (V j : Set X) := by
-- Choose an index `r x` for each point in `X` such that `∀ x, x ∈ U (r x)`.
  choose r hr using hU.exists_mem
  -- Choose a clopen neighbourhood `V x` of each `x` contained in `U (r x)`.
  choose V hV hVx hVU using fun x ↦ compact_exists_isClopen_in_isOpen (U _).isOpen (hr x)
  -- Apply compactness to extract a finite subset of the `V`s which covers `X`.
  obtain ⟨t, ht⟩ : ∃ t, univ ⊆ ⋃ i ∈ t, V i :=
    isCompact_univ.elim_finite_subcover V (fun x ↦ (hV x).2) (fun x _ ↦ mem_iUnion.mpr ⟨x, hVx x⟩)
  -- Biject it noncanonically with `Fin n` for some `n`.
  refine ⟨_, fun j ↦ ⟨_, hV (t.equivFin.symm j)⟩, fun j ↦ ⟨_, hVU _⟩, fun x hx ↦ ?_⟩
  obtain ⟨m, hm, hm'⟩ := mem_iUnion₂.mp (ht hx)
  exact Set.mem_iUnion_of_mem (t.equivFin ⟨m, hm⟩) (by simpa)

/-- Any open cover of a profinite space can be refined to a finite cover by pairwise disjoint
nonempty clopens. -/
```

-- snippet 30
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.completelyRegularSpace_iInf (L129-L153)
lemma completelyRegularSpace_iInf {ι X : Type*} {t : ι → TopologicalSpace X}
    (ht : ∀ i, @CompletelyRegularSpace X (t i)) : @CompletelyRegularSpace X (⨅ i, t i) := by
letI := (⨅ i, t i) -- register this as default topological space to reduce `@`s
  rw [completelyRegularSpace_iff_isOpen]
  intro x K hK hxK
  simp_rw [← hK.mem_nhds_iff, nhds_iInf, mem_iInf, exists_finite_iff_finset,
    Finset.coe_sort_coe] at hxK; clear hK
  obtain ⟨I', V, hV, rfl⟩ := hxK
  simp only [mem_nhds_iff] at hV
  choose U hUV hU hxU using hV
  replace hU := fun (i : ↥I') =>
    @CompletelyRegularSpace.completely_regular_isOpen _ (t i) (ht i) x (U i) (hU i) (hxU i)
  clear hxU
  choose fs hfs hxfs hfsU using hU
  use I'.attach.sup fs
  constructorm* _ ∧ _
  · solve_by_elim [Continuous.finset_sup, continuous_iInf_dom]
  · simpa [show (0 : ↥I) = ⊥ from rfl] using hxfs
  · simp only [EqOn, Pi.one_apply, show (1 : ↥I) = ⊤ from rfl] at hfsU ⊢
    conv => equals ∀ x i, x ∈ (V i)ᶜ → ∃ b, fs b x = ⊤ => simp [Finset.sup_eq_top_iff]
    intro x i hxi
    specialize hfsU i (by tauto_set)
    exists i

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 31
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.completelyRegularSpace_iff_isInducing_stoneCechUnit (L191-L196)
lemma completelyRegularSpace_iff_isInducing_stoneCechUnit :
    CompletelyRegularSpace X ↔ IsInducing (stoneCechUnit : X → StoneCech X) where
  mp _ := isInducing_stoneCechUnit
mpr hs := hs.completelyRegularSpace

open TopologicalSpace Cardinal in
```

-- snippet 32
```lean
-- Mathlib.Topology.Separation.DisjointCover.exists_finite_approximation_of_mem_nhds_diagonal (L140-L161)
lemma exists_finite_approximation_of_mem_nhds_diagonal (hS : S ∈ nhdsSet (diagonal V)) :
    ∃ (n : ℕ) (g : X → Fin n) (h : Fin n → V), Continuous g ∧ ∀ x, (f x, h (g x)) ∈ S := by
obtain ⟨n, E, hEne, hES, hEuniv, hEdis⟩ :=
    exists_disjoint_nonempty_clopen_cover_of_mem_nhds_diagonal f hS
  have h_uniq (x) : ∃! i, x ∈ E i := by
    refine match mem_iUnion.mp (hEuniv <| mem_univ x) with
      | ⟨i, hi⟩ => ⟨i, hi, fun j hj ↦ hEdis.eq ?_⟩
    simpa [← Clopens.coe_disjoint, not_disjoint_iff] using ⟨x, hj, hi⟩
  choose g hg hg' using h_uniq -- for each `x`, `g x` is the unique `i` such that `x ∈ E i`
  have h_ex (i) : ∃ x, x ∈ E i := by
    simpa [← SetLike.coe_set_eq, ← nonempty_iff_ne_empty] using hEne i
  choose r hr using h_ex -- for each `i`, choose an `r i ∈ E i`
  refine ⟨n, g, f ∘ r, continuous_discrete_rng.mpr fun j ↦ ?_, fun x ↦ (hES _) _ (hg _) _ (hr _)⟩
  convert (E j).isOpen
  exact Set.ext fun x ↦ ⟨fun hj ↦ hj ▸ hg x, fun hx ↦ (hg' _ _ hx).symm⟩

/--
If `f` is a continuous map from a profinite space to a topological space with a commutative monoid
structure, then we can approximate `f` by finite products of indicator functions of clopen sets.

(Note no compatibility is assumed between the monoid structure on `V` and the topology.)
-/
```

-- snippet 33
```lean
-- Mathlib.Topology.Separation.DisjointCover.exists_open_prod_subset_of_mem_nhds_diagonal (L79-L91)
lemma exists_open_prod_subset_of_mem_nhds_diagonal (hS : S ∈ nhdsSet (diagonal X)) (x : X) :
    ∃ U : Set X, IsOpen U ∧ x ∈ U ∧ U ×ˢ U ⊆ S := by
have : S ∈ 𝓝 (x, x) := mem_nhdsSet_iff_forall.mp hS _ rfl
  obtain ⟨u, v, huo, hux, hvo, hvx, H⟩ := by rwa [mem_nhds_prod_iff'] at this
  exact ⟨_, huo.inter hvo, ⟨hux, hvx⟩, fun p hp ↦ H ⟨hp.1.1, hp.2.2⟩⟩

variable [CompactSpace X]

/-- If `S` is any neighbourhood of the diagonal in a compact topological space `X`, then there
exists a finite cover of `X` by opens `U i` such that `U i ×ˢ U i ⊆ S` for all `i`.

That the indexing set is a finset of `X` is an artifact of the proof; it could be any finite type.
-/
```

-- snippet 34
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.completelyRegularSpace_induced (L124-L128)
lemma completelyRegularSpace_induced
    {X Y : Type*} {t : TopologicalSpace Y} (ht : @CompletelyRegularSpace Y t)
    (f : X → Y) : @CompletelyRegularSpace X (t.induced f) :=
@IsInducing.completelyRegularSpace _ (t.induced f) _ t _ _ (IsInducing.induced f)
```

-- snippet 35
```lean
-- Mathlib.Topology.Separation.AlexandrovDiscrete.nhdsKer_eq_of_t1Space (L22-L24)
lemma nhdsKer_eq_of_t1Space [T1Space X] (s : Set X) : nhdsKer s = s := by
ext; simp [mem_nhdsKer_iff_specializes]
```

-- snippet 36
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.isEmbedding_stoneCechUnit (L260-L264)
lemma isEmbedding_stoneCechUnit [T35Space X] :
    IsEmbedding (stoneCechUnit : X → StoneCech X) where
  toIsInducing := isInducing_stoneCechUnit
injective := injective_stoneCechUnit_of_t35Space
```

-- snippet 37
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.CompletelyRegularSpace (L79-L83)
lemma CompletelyRegularSpace.completely_regular_isOpen [CompletelyRegularSpace X] :
    ∀ (x : X), ∀ K : Set X, IsOpen K → x ∈ K →
      ∃ f : X → I, Continuous f ∧ f x = 0 ∧ EqOn f 1 Kᶜ :=
completelyRegularSpace_iff_isOpen.mp inferInstance
```

-- snippet 38
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.injective_stoneCechUnit_of_t35Space (L253-L259)
lemma injective_stoneCechUnit_of_t35Space [T35Space X] :
    Function.Injective (stoneCechUnit : X → StoneCech X) := by
intro a b hab
  contrapose hab
  obtain ⟨f, fc, fab⟩ := separatesPoints_continuous_of_t35Space_Icc hab
  exact fun q ↦ fab (eq_if_stoneCechUnit_eq fc q)
```

-- snippet 39
```lean
-- Mathlib.Topology.Separation.Connected.IsPreconnected (L36-L41)
theorem IsPreconnected.infinite_of_nontrivial [T1Space X] {s : Set X} (h : IsPreconnected s)
    (hs : s.Nontrivial) : s.Infinite := by
refine mt (fun hf => (subsingleton_coe s).mp ?_) (not_subsingleton_iff.mpr hs)
  haveI := @Finite.instDiscreteTopology s _ _ hf.to_subtype
  exact @PreconnectedSpace.trivial_of_discrete _ _ (Subtype.preconnectedSpace h) _
```

-- snippet 40
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.separatesPoints_continuous_of_t35Space_Icc (L246-L252)
lemma separatesPoints_continuous_of_t35Space_Icc [T35Space X] :
    SeparatesPoints {f : X → I | Continuous f} := by
intro x y x_ne_y
  obtain ⟨f, f_cont, f_zero, f_one⟩ :=
    CompletelyRegularSpace.completely_regular x {y} isClosed_singleton x_ne_y
  exact ⟨f, f_cont, by simp_all⟩
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Topology.Separation.Basic).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
theorem IsCompact.closure_of_subset {s K : Set X} (hK : IsCompact K) (h : s ⊆ K) :
    IsCompact (closure s)
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Topology.Separation.Basic.t0Space_iff_inseparable (L81-L84)
theorem t0Space_iff_inseparable (X : Type u) [TopologicalSpace X] :
    T0Space X ↔ ∀ x y : X, Inseparable x y → x = y :=
⟨fun ⟨h⟩ => h, fun h => ⟨h⟩⟩
```

-- snippet 2
```lean
-- Mathlib.Topology.Separation.Basic.t0Space_iff_not_inseparable (L85-L88)
theorem t0Space_iff_not_inseparable (X : Type u) [TopologicalSpace X] :
    T0Space X ↔ Pairwise fun x y : X => ¬Inseparable x y := by
simp only [t0Space_iff_inseparable, Ne, not_imp_not, Pairwise]
```

-- snippet 3
```lean
-- Mathlib.Topology.Separation.Basic.Inseparable (L89-L101)
theorem Inseparable.eq [T0Space X] {x y : X} (h : Inseparable x y) : x = y :=
T0Space.t0 h

/-- A topology inducing map from a T₀ space is injective. -/
protected theorem Topology.IsInducing.injective [TopologicalSpace Y] [T0Space X] {f : X → Y}
    (hf : IsInducing f) : Injective f := fun _ _ h =>
  (hf.inseparable_iff.1 <| .of_eq h).eq

/-- A topology inducing map from a T₀ space is a topological embedding. -/
protected theorem Topology.IsInducing.isEmbedding [TopologicalSpace Y] [T0Space X] {f : X → Y}
    (hf : IsInducing f) : IsEmbedding f :=
  ⟨hf, hf.injective⟩
```

-- snippet 4
```lean
-- Mathlib.Topology.Separation.Basic.isEmbedding_iff_isInducing (L102-L105)
lemma isEmbedding_iff_isInducing [TopologicalSpace Y] [T0Space X] {f : X → Y} :
    IsEmbedding f ↔ IsInducing f :=
⟨IsEmbedding.isInducing, IsInducing.isEmbedding⟩
```

-- snippet 5
```lean
-- Mathlib.Topology.Separation.Basic.t0Space_iff_nhds_injective (L106-L109)
theorem t0Space_iff_nhds_injective (X : Type u) [TopologicalSpace X] :
    T0Space X ↔ Injective (𝓝 : X → Filter X) :=
t0Space_iff_inseparable X
```

-- snippet 6
```lean
-- Mathlib.Topology.Separation.Basic.nhds_injective (L110-L112)
theorem nhds_injective [T0Space X] : Injective (𝓝 : X → Filter X) :=
(t0Space_iff_nhds_injective X).1 ‹_›
```

-- snippet 7
```lean
-- Mathlib.Topology.Separation.Basic.inseparable_iff_eq (L113-L115)
theorem inseparable_iff_eq [T0Space X] {x y : X} : Inseparable x y ↔ x = y :=
nhds_injective.eq_iff
```

-- snippet 8
```lean
-- Mathlib.Topology.Separation.Basic.nhds_eq_nhds_iff (L117-L119)
theorem nhds_eq_nhds_iff [T0Space X] {a b : X} : 𝓝 a = 𝓝 b ↔ a = b :=
nhds_injective.eq_iff
```

-- snippet 9
```lean
-- Mathlib.Topology.Separation.Basic.inseparable_eq_eq (L121-L123)
theorem inseparable_eq_eq [T0Space X] : Inseparable = @Eq X :=
funext₂ fun _ _ => propext inseparable_iff_eq
```

-- snippet 10
```lean
-- Mathlib.Topology.Separation.Basic.TopologicalSpace (L124-L130)
theorem TopologicalSpace.IsTopologicalBasis.inseparable_iff {b : Set (Set X)}
    (hb : IsTopologicalBasis b) {x y : X} : Inseparable x y ↔ ∀ s ∈ b, (x ∈ s ↔ y ∈ s) :=
⟨fun h _ hs ↦ inseparable_iff_forall_isOpen.1 h _ (hb.isOpen hs),
    fun h ↦ hb.nhds_hasBasis.eq_of_same_basis <| by
      convert hb.nhds_hasBasis using 2
      exact and_congr_right (h _)⟩
```

-- snippet 11
```lean
-- Mathlib.Topology.Separation.Basic.TopologicalSpace (L131-L134)
theorem TopologicalSpace.IsTopologicalBasis.eq_iff [T0Space X] {b : Set (Set X)}
    (hb : IsTopologicalBasis b) {x y : X} : x = y ↔ ∀ s ∈ b, (x ∈ s ↔ y ∈ s) :=
inseparable_iff_eq.symm.trans hb.inseparable_iff
```

-- snippet 12
```lean
-- Mathlib.Topology.Separation.Basic.t0Space_iff_exists_isOpen_xor'_mem (L135-L139)
theorem t0Space_iff_exists_isOpen_xor'_mem (X : Type u) [TopologicalSpace X] :
    T0Space X ↔ Pairwise fun x y => ∃ U : Set X, IsOpen U ∧ Xor' (x ∈ U) (y ∈ U) := by
simp only [t0Space_iff_not_inseparable, xor_iff_not_iff, not_forall, exists_prop,
    inseparable_iff_forall_isOpen, Pairwise]
```

-- snippet 13
```lean
-- Mathlib.Topology.Separation.Basic.exists_isOpen_xor'_mem (L140-L144)
theorem exists_isOpen_xor'_mem [T0Space X] {x y : X} (h : x ≠ y) :
    ∃ U : Set X, IsOpen U ∧ Xor' (x ∈ U) (y ∈ U) :=
(t0Space_iff_exists_isOpen_xor'_mem X).1 ‹_› h

/-- Specialization forms a partial order on a t0 topological space. -/
```

-- snippet 14
```lean
-- Mathlib.Topology.Separation.Basic.specializationOrder (L146-L148)
def specializationOrder (X) [TopologicalSpace X] [T0Space X] : PartialOrder X :=
{ specializationPreorder X, PartialOrder.lift (OrderDual.toDual ∘ 𝓝) nhds_injective with }
```

-- snippet 15
```lean
-- Mathlib.Topology.Separation.Basic.SeparationQuotient (L149-L152)
instance SeparationQuotient.instT0Space : T0Space (SeparationQuotient X) :=
⟨fun x y => Quotient.inductionOn₂' x y fun _ _ h =>
    SeparationQuotient.mk_eq_mk.2 <| SeparationQuotient.isInducing_mk.inseparable_iff.1 h⟩
```

-- snippet 16
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.completelyRegularSpace_inf (L154-L158)
lemma completelyRegularSpace_inf {X : Type*} {t₁ t₂ : TopologicalSpace X}
    (ht₁ : @CompletelyRegularSpace X t₁) (ht₂ : @CompletelyRegularSpace X t₂) :
    @CompletelyRegularSpace X (t₁ ⊓ t₂) := by
rw [inf_eq_iInf]; apply completelyRegularSpace_iInf; simp [*]
```

-- snippet 17
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.completelyRegularSpace_iff_isOpen (L72-L78)
lemma completelyRegularSpace_iff_isOpen : CompletelyRegularSpace X ↔
    ∀ (x : X), ∀ K : Set X, IsOpen K → x ∈ K →
      ∃ f : X → I, Continuous f ∧ f x = 0 ∧ EqOn f 1 Kᶜ := by
conv_lhs => tactic =>
    simp_rw +singlePass [completelyRegularSpace_iff, compl_surjective.forall, isClosed_compl_iff,
      mem_compl_iff, not_not]
```

-- snippet 18
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.Topology (L109-L120)
lemma Topology.IsInducing.completelyRegularSpace
    {Y : Type v} [TopologicalSpace Y] [CompletelyRegularSpace Y]
    {f : X → Y} (hf : IsInducing f) : CompletelyRegularSpace X where
  completely_regular x K hK hxK := by
rw [hf.isClosed_iff] at hK
    obtain ⟨K, hK, rfl⟩ := hK
    rw [mem_preimage] at hxK
    obtain ⟨g, hcf, egfx, hgK⟩ := CompletelyRegularSpace.completely_regular _ _ hK hxK
    refine ⟨g ∘ f, hcf.comp hf.continuous, egfx, ?_⟩
    conv => arg 2; equals (1 : Y → ↥I) ∘ f => rfl
    exact hgK.comp_right <| mapsTo_preimage _ _
```

-- snippet 19
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.t35Space_iff_isEmbedding_stoneCechUnit (L270-L273)
lemma t35Space_iff_isEmbedding_stoneCechUnit :
    T35Space X ↔ IsEmbedding (stoneCechUnit : X → StoneCech X) where
  mp _ := isEmbedding_stoneCechUnit
mpr hs := hs.t35Space
```

-- snippet 20
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.isDenseInducing_stoneCechUnit (L186-L190)
lemma isDenseInducing_stoneCechUnit [CompletelyRegularSpace X] :
    IsDenseInducing (stoneCechUnit : X → StoneCech X) where
  toIsInducing := isInducing_stoneCechUnit
dense := denseRange_stoneCechUnit
```

-- snippet 21
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.separatesPoints_continuous_of_t35Space (L239-L245)
lemma separatesPoints_continuous_of_t35Space [T35Space X] :
    SeparatesPoints {f : X → ℝ | Continuous f} := by
intro x y x_ne_y
  obtain ⟨f, f_cont, f_zero, f_one⟩ :=
    CompletelyRegularSpace.completely_regular x {y} isClosed_singleton x_ne_y
  exact ⟨fun x ↦ f x, continuous_subtype_val.comp f_cont, by simp_all⟩
```

-- snippet 22
```lean
-- Mathlib.Topology.Separation.Connected.PreconnectedSpace (L30-L35)
theorem PreconnectedSpace.trivial_of_discrete [PreconnectedSpace X] [DiscreteTopology X] :
    Subsingleton X := by
by_contra! ⟨x, y, hxy⟩
  rw [Ne, ← mem_singleton_iff, (isClopen_discrete _).eq_univ <| singleton_nonempty y] at hxy
  exact hxy (mem_univ x)
```

-- snippet 23
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.isDenseEmbedding_stoneCechUnit (L265-L269)
lemma isDenseEmbedding_stoneCechUnit [T35Space X] :
    IsDenseEmbedding (stoneCechUnit : X → StoneCech X) where
  toIsDenseInducing := isDenseInducing_stoneCechUnit
injective := injective_stoneCechUnit_of_t35Space
```

-- snippet 24
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.isInducing_stoneCechUnit (L169-L185)
lemma isInducing_stoneCechUnit [CompletelyRegularSpace X] :
    IsInducing (stoneCechUnit : X → StoneCech X) := by
rw [isInducing_iff_nhds]
  intro x
  apply le_antisymm
  · rw [← map_le_iff_le_comap]; exact continuous_stoneCechUnit.continuousAt
  · simp_rw [le_nhds_iff, ((nhds_basis_opens _).comap _).mem_iff, and_assoc]
    intro U hxU hU
    obtain ⟨f, hf, efx, hfU⟩ :=
      CompletelyRegularSpace.completely_regular_isOpen x U hU hxU
    conv at hfU => equals Uᶜ ⊆ f ⁻¹' {1} => simp [EqOn, subset_def]
    rw [← compl_subset_comm, ← preimage_compl, ← stoneCechExtend_extends hf, preimage_comp] at hfU
    refine ⟨stoneCechExtend hf ⁻¹' {1}ᶜ, ?_,
      isOpen_compl_singleton.preimage (continuous_stoneCechExtend hf), hfU⟩
    rw [mem_preimage, stoneCechExtend_stoneCechUnit, efx, mem_compl_iff, mem_singleton_iff]
    simp
```

-- snippet 25
```lean
-- Mathlib.Topology.Separation.DisjointCover.exists_finite_nonempty_disjoint_clopen_cover (L56-L78)
lemma exists_finite_nonempty_disjoint_clopen_cover (hU : IsOpenCover U) :
    ∃ (n : ℕ) (W : Fin n → Clopens X), (∀ j, W j ≠ ⊥ ∧ ∃ i, (W j : Set X) ⊆ U i)
    ∧ (univ : Set X) ⊆ ⋃ j, ↑(W j) ∧ Pairwise (Disjoint on W) := by
classical
  obtain ⟨n, V, hVle, hVun⟩ := hU.exists_finite_clopen_cover
  obtain ⟨W, hWle, hWun, hWd⟩ := Fintype.exists_disjointed_le V
  simp only [← SetLike.coe_set_eq, Clopens.coe_finset_sup, Finset.mem_univ, iUnion_true] at hWun
  let t : Finset (Fin n) := {j | W j ≠ ⊥}
  refine ⟨#t, fun k ↦ W (t.equivFin.symm k), fun k ↦ ⟨?_, ?_⟩, fun x hx ↦ ?_, ?_⟩
  · exact (Finset.mem_filter.mp (t.equivFin.symm k).2).2
  · exact match hVle (t.equivFin.symm k) with | ⟨i, hi⟩ => ⟨i, subset_trans (hWle _) hi⟩
  · obtain ⟨j, hj⟩ := mem_iUnion.mp <| (hWun ▸ hVun) hx
    have : W j ≠ ⊥ := by simpa [← SetLike.coe_ne_coe, ← Set.nonempty_iff_ne_empty] using ⟨x, hj⟩
    exact mem_iUnion.mpr ⟨t.equivFin ⟨j, Finset.mem_filter.mpr ⟨Finset.mem_univ _, this⟩⟩, by simpa⟩
  · exact hWd.comp_of_injective <| Subtype.val_injective.comp t.equivFin.symm.injective

end TopologicalSpace.IsOpenCover

namespace TopologicalSpace
variable {X : Type*} [TopologicalSpace X] {S : Set (X × X)}

/-- If `S` is any neighbourhood of the diagonal in a topological space `X`, any point of `X` has an
open neighbourhood `U` such that `U ×ˢ U ⊆ S`. -/
```

-- snippet 26
```lean
-- Mathlib.Topology.Separation.DisjointCover.exists_disjoint_nonempty_clopen_cover_of_mem_nhds_diagonal (L127-L139)
lemma exists_disjoint_nonempty_clopen_cover_of_mem_nhds_diagonal (hS : S ∈ nhdsSet (diagonal V)) :
    ∃ (n : ℕ) (D : Fin n → Clopens X), (∀ i, D i ≠ ⊥) ∧ (∀ i, ∀ y ∈ D i, ∀ z ∈ D i, (f y, f z) ∈ S)
    ∧ (univ : Set X) ⊆ ⋃ i, D i ∧ Pairwise (Disjoint on D) := by
have : (f.prodMap f) ⁻¹' S ∈ nhdsSet (diagonal X) := by
    rw [mem_nhdsSet_iff_forall] at hS ⊢
    rintro ⟨x, y⟩ (rfl : x = y)
    exact (map_continuous _).continuousAt.preimage_mem_nhds (hS _ rfl)
  exact exists_finite_disjoint_nonempty_clopen_cover_of_mem_nhds_diagonal_of_profinite this

/--
For any continuous function `f : X → V`, with `X` profinite, and `S` a neighbourhood of the
diagonal in `V × V`, the function `f` can be `S`-approximated by a function factoring through
`Fin n`, for some `n`. -/
```

-- snippet 27
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.NormalSpace (L93-L108)
instance NormalSpace.instCompletelyRegularSpace [NormalSpace X] [R0Space X] :
    CompletelyRegularSpace X := by
rw [completelyRegularSpace_iff]
  intro x K hK hx
  have cx : IsClosed (closure {x}) := isClosed_closure
  have d : Disjoint (closure {x}) K := by
    rw [Set.disjoint_iff]
    intro a ⟨hax, haK⟩
    exact hx ((specializes_iff_mem_closure.mpr hax).symm.mem_closed hK haK)
  let ⟨⟨f, cf⟩, hfx, hfK, hficc⟩ := exists_continuous_zero_one_of_isClosed cx hK d
  let g : X → I := fun x => ⟨f x, hficc x⟩
  have cg : Continuous g := cf.subtype_mk hficc
  have hgx : g x = 0 := Subtype.ext (hfx (subset_closure (mem_singleton x)))
  have hgK : EqOn g 1 K := fun k hk => Subtype.ext (hfK hk)
  exact ⟨g, cg, hgx, hgK⟩
```

-- snippet 28
```lean
-- Mathlib.Topology.Separation.DisjointCover.exists_finite_open_cover_prod_subset_of_mem_nhds_diagonal_of_compact (L92-L126)
lemma exists_finite_open_cover_prod_subset_of_mem_nhds_diagonal_of_compact
    (hS : S ∈ nhdsSet (diagonal X)) :
    ∃ (t : Finset X) (U : t → Opens X), IsOpenCover U ∧ ∀ i, (U i : Set X) ×ˢ U i ⊆ S := by
choose U hUo hUx hUp using exists_open_prod_subset_of_mem_nhds_diagonal hS
  obtain ⟨t, ht⟩ := isCompact_univ.elim_finite_subcover _ hUo (fun x _ ↦ mem_iUnion.mpr ⟨_, hUx x⟩)
  refine ⟨t, fun i ↦ ⟨_, hUo i⟩, .of_sets _ ?_, (hUp ·)⟩
  simpa [iUnion_subtype, ← univ_subset_iff] using ht

variable [TotallyDisconnectedSpace X] [T2Space X]

/-- If `S` is any neighbourhood of the diagonal in a profinite topological space `X`, then there
exists a finite cover of `X` by disjoint nonempty clopens `U i` with `U i ×ˢ U i ⊆ S` for all `i`.
-/
private lemma exists_finite_disjoint_nonempty_clopen_cover_of_mem_nhds_diagonal_of_profinite
    (hS : S ∈ nhdsSet (diagonal X)) :
    ∃ (n : ℕ) (D : Fin n → Clopens X), (∀ i, D i ≠ ⊥) ∧ (∀ i, ∀ y ∈ D i, ∀ z ∈ D i, (y, z) ∈ S)
    ∧ (univ : Set X) ⊆ ⋃ i, D i ∧ Pairwise (Disjoint on D) := by
  obtain ⟨t, U, hUc, hUS⟩ := exists_finite_open_cover_prod_subset_of_mem_nhds_diagonal_of_compact hS
  -- Now refine it to a disjoint covering.
  obtain ⟨n, W, hW₁, hW₂, hW₃⟩ := hUc.exists_finite_nonempty_disjoint_clopen_cover
  refine ⟨n, W, fun j ↦ (hW₁ j).1, fun j y hy z hz ↦ ?_, hW₂, hW₃⟩
  exact match (hW₁ j).2 with | ⟨i, hi⟩ => hUS i ⟨hi hy, hi hz⟩

end TopologicalSpace

namespace ContinuousMap

variable {X V : Type*} [TopologicalSpace X] [TopologicalSpace V] [TotallyDisconnectedSpace X]
  [T2Space X] [CompactSpace X] {S : Set (V × V)} (f : C(X, V))

/--
For any continuous function `f : X → V`, with `X` profinite, and `S` a neighbourhood of the
diagonal in `V × V`, there exists a finite cover of `X` by pairwise-disjoint nonempty clopens, on
each of which `f` varies within `S`.
-/
```

-- snippet 29
```lean
-- Mathlib.Topology.Separation.DisjointCover.exists_finite_clopen_cover (L40-L55)
lemma exists_finite_clopen_cover (hU : IsOpenCover U) : ∃ (n : ℕ) (V : Fin n → Clopens X),
    (∀ j, ∃ i, (V j : Set X) ⊆ U i) ∧ univ ⊆ ⋃ j, (V j : Set X) := by
-- Choose an index `r x` for each point in `X` such that `∀ x, x ∈ U (r x)`.
  choose r hr using hU.exists_mem
  -- Choose a clopen neighbourhood `V x` of each `x` contained in `U (r x)`.
  choose V hV hVx hVU using fun x ↦ compact_exists_isClopen_in_isOpen (U _).isOpen (hr x)
  -- Apply compactness to extract a finite subset of the `V`s which covers `X`.
  obtain ⟨t, ht⟩ : ∃ t, univ ⊆ ⋃ i ∈ t, V i :=
    isCompact_univ.elim_finite_subcover V (fun x ↦ (hV x).2) (fun x _ ↦ mem_iUnion.mpr ⟨x, hVx x⟩)
  -- Biject it noncanonically with `Fin n` for some `n`.
  refine ⟨_, fun j ↦ ⟨_, hV (t.equivFin.symm j)⟩, fun j ↦ ⟨_, hVU _⟩, fun x hx ↦ ?_⟩
  obtain ⟨m, hm, hm'⟩ := mem_iUnion₂.mp (ht hx)
  exact Set.mem_iUnion_of_mem (t.equivFin ⟨m, hm⟩) (by simpa)

/-- Any open cover of a profinite space can be refined to a finite cover by pairwise disjoint
nonempty clopens. -/
```

-- snippet 30
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.completelyRegularSpace_iInf (L129-L153)
lemma completelyRegularSpace_iInf {ι X : Type*} {t : ι → TopologicalSpace X}
    (ht : ∀ i, @CompletelyRegularSpace X (t i)) : @CompletelyRegularSpace X (⨅ i, t i) := by
letI := (⨅ i, t i) -- register this as default topological space to reduce `@`s
  rw [completelyRegularSpace_iff_isOpen]
  intro x K hK hxK
  simp_rw [← hK.mem_nhds_iff, nhds_iInf, mem_iInf, exists_finite_iff_finset,
    Finset.coe_sort_coe] at hxK; clear hK
  obtain ⟨I', V, hV, rfl⟩ := hxK
  simp only [mem_nhds_iff] at hV
  choose U hUV hU hxU using hV
  replace hU := fun (i : ↥I') =>
    @CompletelyRegularSpace.completely_regular_isOpen _ (t i) (ht i) x (U i) (hU i) (hxU i)
  clear hxU
  choose fs hfs hxfs hfsU using hU
  use I'.attach.sup fs
  constructorm* _ ∧ _
  · solve_by_elim [Continuous.finset_sup, continuous_iInf_dom]
  · simpa [show (0 : ↥I) = ⊥ from rfl] using hxfs
  · simp only [EqOn, Pi.one_apply, show (1 : ↥I) = ⊤ from rfl] at hfsU ⊢
    conv => equals ∀ x i, x ∈ (V i)ᶜ → ∃ b, fs b x = ⊤ => simp [Finset.sup_eq_top_iff]
    intro x i hxi
    specialize hfsU i (by tauto_set)
    exists i

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 31
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.completelyRegularSpace_iff_isInducing_stoneCechUnit (L191-L196)
lemma completelyRegularSpace_iff_isInducing_stoneCechUnit :
    CompletelyRegularSpace X ↔ IsInducing (stoneCechUnit : X → StoneCech X) where
  mp _ := isInducing_stoneCechUnit
mpr hs := hs.completelyRegularSpace

open TopologicalSpace Cardinal in
```

-- snippet 32
```lean
-- Mathlib.Topology.Separation.DisjointCover.exists_finite_approximation_of_mem_nhds_diagonal (L140-L161)
lemma exists_finite_approximation_of_mem_nhds_diagonal (hS : S ∈ nhdsSet (diagonal V)) :
    ∃ (n : ℕ) (g : X → Fin n) (h : Fin n → V), Continuous g ∧ ∀ x, (f x, h (g x)) ∈ S := by
obtain ⟨n, E, hEne, hES, hEuniv, hEdis⟩ :=
    exists_disjoint_nonempty_clopen_cover_of_mem_nhds_diagonal f hS
  have h_uniq (x) : ∃! i, x ∈ E i := by
    refine match mem_iUnion.mp (hEuniv <| mem_univ x) with
      | ⟨i, hi⟩ => ⟨i, hi, fun j hj ↦ hEdis.eq ?_⟩
    simpa [← Clopens.coe_disjoint, not_disjoint_iff] using ⟨x, hj, hi⟩
  choose g hg hg' using h_uniq -- for each `x`, `g x` is the unique `i` such that `x ∈ E i`
  have h_ex (i) : ∃ x, x ∈ E i := by
    simpa [← SetLike.coe_set_eq, ← nonempty_iff_ne_empty] using hEne i
  choose r hr using h_ex -- for each `i`, choose an `r i ∈ E i`
  refine ⟨n, g, f ∘ r, continuous_discrete_rng.mpr fun j ↦ ?_, fun x ↦ (hES _) _ (hg _) _ (hr _)⟩
  convert (E j).isOpen
  exact Set.ext fun x ↦ ⟨fun hj ↦ hj ▸ hg x, fun hx ↦ (hg' _ _ hx).symm⟩

/--
If `f` is a continuous map from a profinite space to a topological space with a commutative monoid
structure, then we can approximate `f` by finite products of indicator functions of clopen sets.

(Note no compatibility is assumed between the monoid structure on `V` and the topology.)
-/
```

-- snippet 33
```lean
-- Mathlib.Topology.Separation.DisjointCover.exists_open_prod_subset_of_mem_nhds_diagonal (L79-L91)
lemma exists_open_prod_subset_of_mem_nhds_diagonal (hS : S ∈ nhdsSet (diagonal X)) (x : X) :
    ∃ U : Set X, IsOpen U ∧ x ∈ U ∧ U ×ˢ U ⊆ S := by
have : S ∈ 𝓝 (x, x) := mem_nhdsSet_iff_forall.mp hS _ rfl
  obtain ⟨u, v, huo, hux, hvo, hvx, H⟩ := by rwa [mem_nhds_prod_iff'] at this
  exact ⟨_, huo.inter hvo, ⟨hux, hvx⟩, fun p hp ↦ H ⟨hp.1.1, hp.2.2⟩⟩

variable [CompactSpace X]

/-- If `S` is any neighbourhood of the diagonal in a compact topological space `X`, then there
exists a finite cover of `X` by opens `U i` such that `U i ×ˢ U i ⊆ S` for all `i`.

That the indexing set is a finset of `X` is an artifact of the proof; it could be any finite type.
-/
```

-- snippet 34
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.completelyRegularSpace_induced (L124-L128)
lemma completelyRegularSpace_induced
    {X Y : Type*} {t : TopologicalSpace Y} (ht : @CompletelyRegularSpace Y t)
    (f : X → Y) : @CompletelyRegularSpace X (t.induced f) :=
@IsInducing.completelyRegularSpace _ (t.induced f) _ t _ _ (IsInducing.induced f)
```

-- snippet 35
```lean
-- Mathlib.Topology.Separation.AlexandrovDiscrete.nhdsKer_eq_of_t1Space (L22-L24)
lemma nhdsKer_eq_of_t1Space [T1Space X] (s : Set X) : nhdsKer s = s := by
ext; simp [mem_nhdsKer_iff_specializes]
```

-- snippet 36
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.isEmbedding_stoneCechUnit (L260-L264)
lemma isEmbedding_stoneCechUnit [T35Space X] :
    IsEmbedding (stoneCechUnit : X → StoneCech X) where
  toIsInducing := isInducing_stoneCechUnit
injective := injective_stoneCechUnit_of_t35Space
```

-- snippet 37
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.CompletelyRegularSpace (L79-L83)
lemma CompletelyRegularSpace.completely_regular_isOpen [CompletelyRegularSpace X] :
    ∀ (x : X), ∀ K : Set X, IsOpen K → x ∈ K →
      ∃ f : X → I, Continuous f ∧ f x = 0 ∧ EqOn f 1 Kᶜ :=
completelyRegularSpace_iff_isOpen.mp inferInstance
```

-- snippet 38
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.injective_stoneCechUnit_of_t35Space (L253-L259)
lemma injective_stoneCechUnit_of_t35Space [T35Space X] :
    Function.Injective (stoneCechUnit : X → StoneCech X) := by
intro a b hab
  contrapose hab
  obtain ⟨f, fc, fab⟩ := separatesPoints_continuous_of_t35Space_Icc hab
  exact fun q ↦ fab (eq_if_stoneCechUnit_eq fc q)
```

-- snippet 39
```lean
-- Mathlib.Topology.Separation.Connected.IsPreconnected (L36-L41)
theorem IsPreconnected.infinite_of_nontrivial [T1Space X] {s : Set X} (h : IsPreconnected s)
    (hs : s.Nontrivial) : s.Infinite := by
refine mt (fun hf => (subsingleton_coe s).mp ?_) (not_subsingleton_iff.mpr hs)
  haveI := @Finite.instDiscreteTopology s _ _ hf.to_subtype
  exact @PreconnectedSpace.trivial_of_discrete _ _ (Subtype.preconnectedSpace h) _
```

-- snippet 40
```lean
-- Mathlib.Topology.Separation.CompletelyRegular.separatesPoints_continuous_of_t35Space_Icc (L246-L252)
lemma separatesPoints_continuous_of_t35Space_Icc [T35Space X] :
    SeparatesPoints {f : X → I | Continuous f} := by
intro x y x_ne_y
  obtain ⟨f, f_cont, f_zero, f_one⟩ :=
    CompletelyRegularSpace.completely_regular x {y} isClosed_singleton x_ne_y
  exact ⟨f, f_cont, by simp_all⟩
```
[/INST]


[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Algebra.Order.Interval.Set.Group).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
theorem add_mem_Ioc_iff_right : a + b ∈ Set.Ioc c d ↔ b ∈ Set.Ioc (c - a) (d - a)
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.inv_mem_Icc_iff (L32-L34)
theorem inv_mem_Icc_iff : a⁻¹ ∈ Set.Icc c d ↔ a ∈ Set.Icc d⁻¹ c⁻¹ :=
and_comm.trans <| and_congr inv_le' le_inv'
```

-- snippet 2
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.inv_mem_Ico_iff (L36-L38)
theorem inv_mem_Ico_iff : a⁻¹ ∈ Set.Ico c d ↔ a ∈ Set.Ioc d⁻¹ c⁻¹ :=
and_comm.trans <| and_congr inv_lt' le_inv'
```

-- snippet 3
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.inv_mem_Ioc_iff (L40-L42)
theorem inv_mem_Ioc_iff : a⁻¹ ∈ Set.Ioc c d ↔ a ∈ Set.Ico d⁻¹ c⁻¹ :=
and_comm.trans <| and_congr inv_le' lt_inv'
```

-- snippet 4
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.inv_mem_Ioo_iff (L44-L54)
theorem inv_mem_Ioo_iff : a⁻¹ ∈ Set.Ioo c d ↔ a ∈ Set.Ioo d⁻¹ c⁻¹ :=
and_comm.trans <| and_congr inv_lt' lt_inv'

end OrderedCommGroup

section OrderedAddCommGroup

variable [AddCommGroup α] [PartialOrder α] [IsOrderedAddMonoid α] {a b c d : α}

/-! `add_mem_Ixx_iff_left` -/
```

-- snippet 5
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.add_mem_Icc_iff_left (L55-L57)
theorem add_mem_Icc_iff_left : a + b ∈ Set.Icc c d ↔ a ∈ Set.Icc (c - b) (d - b) :=
(and_congr sub_le_iff_le_add le_sub_iff_add_le).symm
```

-- snippet 6
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.add_mem_Ico_iff_left (L58-L60)
theorem add_mem_Ico_iff_left : a + b ∈ Set.Ico c d ↔ a ∈ Set.Ico (c - b) (d - b) :=
(and_congr sub_le_iff_le_add lt_sub_iff_add_lt).symm
```

-- snippet 7
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.add_mem_Ioc_iff_left (L61-L63)
theorem add_mem_Ioc_iff_left : a + b ∈ Set.Ioc c d ↔ a ∈ Set.Ioc (c - b) (d - b) :=
(and_congr sub_lt_iff_lt_add le_sub_iff_add_le).symm
```

-- snippet 8
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.add_mem_Ioo_iff_left (L64-L68)
theorem add_mem_Ioo_iff_left : a + b ∈ Set.Ioo c d ↔ a ∈ Set.Ioo (c - b) (d - b) :=
(and_congr sub_lt_iff_lt_add lt_sub_iff_add_lt).symm

/-! `add_mem_Ixx_iff_right` -/
```

-- snippet 9
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.add_mem_Icc_iff_right (L69-L71)
theorem add_mem_Icc_iff_right : a + b ∈ Set.Icc c d ↔ b ∈ Set.Icc (c - a) (d - a) :=
(and_congr sub_le_iff_le_add' le_sub_iff_add_le').symm
```

-- snippet 10
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.add_mem_Ico_iff_right (L72-L74)
theorem add_mem_Ico_iff_right : a + b ∈ Set.Ico c d ↔ b ∈ Set.Ico (c - a) (d - a) :=
(and_congr sub_le_iff_le_add' lt_sub_iff_add_lt').symm
```

-- snippet 11
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.add_mem_Ioo_iff_right (L78-L82)
theorem add_mem_Ioo_iff_right : a + b ∈ Set.Ioo c d ↔ b ∈ Set.Ioo (c - a) (d - a) :=
(and_congr sub_lt_iff_lt_add' lt_sub_iff_add_lt').symm

/-! `sub_mem_Ixx_iff_left` -/
```

-- snippet 12
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.sub_mem_Icc_iff_left (L83-L85)
theorem sub_mem_Icc_iff_left : a - b ∈ Set.Icc c d ↔ a ∈ Set.Icc (c + b) (d + b) :=
and_congr le_sub_iff_add_le sub_le_iff_le_add
```

-- snippet 13
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.sub_mem_Ico_iff_left (L86-L88)
theorem sub_mem_Ico_iff_left : a - b ∈ Set.Ico c d ↔ a ∈ Set.Ico (c + b) (d + b) :=
and_congr le_sub_iff_add_le sub_lt_iff_lt_add
```

-- snippet 14
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.sub_mem_Ioc_iff_left (L89-L91)
theorem sub_mem_Ioc_iff_left : a - b ∈ Set.Ioc c d ↔ a ∈ Set.Ioc (c + b) (d + b) :=
and_congr lt_sub_iff_add_lt sub_le_iff_le_add
```

-- snippet 15
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.sub_mem_Ioo_iff_left (L92-L96)
theorem sub_mem_Ioo_iff_left : a - b ∈ Set.Ioo c d ↔ a ∈ Set.Ioo (c + b) (d + b) :=
and_congr lt_sub_iff_add_lt sub_lt_iff_lt_add

/-! `sub_mem_Ixx_iff_right` -/
```

-- snippet 16
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.Simps (L80-L84)
def Simps.apply (f : AbsoluteValue R S) : R → S :=
f

initialize_simps_projections AbsoluteValue (toFun → apply)
```

-- snippet 17
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.sub_le_add (L235-L237)
lemma sub_le_add (a b : R) : abv (a - b) ≤ abv a + abv b := by
simpa only [← sub_eq_add_neg, AbsoluteValue.map_neg] using abv.add_le a (-b)
```

-- snippet 18
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.coe_toMonoidWithZeroHom (L169-L172)
theorem coe_toMonoidWithZeroHom : ⇑abv.toMonoidWithZeroHom = abv :=
rfl

/-- Absolute values from a nontrivial `R` to a linear ordered ring preserve `*` and `1`. -/
```

-- snippet 19
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.funLike (L55-L58)
instance funLike : FunLike (AbsoluteValue R S) R S where
  coe f := f.toFun
coe_injective' f g h := by obtain ⟨⟨_, _⟩, _⟩ := f; obtain ⟨⟨_, _⟩, _⟩ := g; congr
```

-- snippet 20
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.mulHomClass (L62-L64)
instance mulHomClass : MulHomClass (AbsoluteValue R S) R S :=
{ AbsoluteValue.zeroHomClass (R := R) (S := S) with map_mul := fun f => f.map_mul' }
```

-- snippet 21
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.monoidWithZeroHomClass (L159-L164)
instance monoidWithZeroHomClass : MonoidWithZeroHomClass (AbsoluteValue R S) R S :=
{ AbsoluteValue.mulHomClass with
    map_zero := fun f => f.map_zero
    map_one := fun f => f.map_one }

/-- Absolute values from a nontrivial `R` to a linear ordered ring preserve `*`, `0` and `1`. -/
```

-- snippet 22
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.trivial_apply (L319-L334)
lemma trivial_apply {x : R} (hx : x ≠ 0) : AbsoluteValue.trivial (S := S) x = 1 :=
if_neg hx

end trivial

section nontrivial

section OrderedSemiring

variable {R : Type*} [Semiring R] {S : Type*} [Semiring S] [PartialOrder S] [IsOrderedRing S]

/-- An absolute value on a semiring `R` without zero divisors is *nontrivial* if it takes
a value `≠ 1` on a nonzero element.

This has the advantage over `v ≠ .trivial` that it does not require decidability
of `· = 0` in `R`. -/
```

-- snippet 23
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.coe_mk (L72-L74)
theorem coe_mk (f : R →ₙ* S) {h₁ h₂ h₃} : (AbsoluteValue.mk f h₁ h₂ h₃ : R → S) = f :=
rfl
```

-- snippet 24
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.toMonoidHom (L173-L175)
def toMonoidHom : R →* S :=
abv
```

-- snippet 25
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.apply_nat_le_self (L186-L206)
lemma apply_nat_le_self [IsOrderedRing S] (n : ℕ) : abv n ≤ n := by
cases subsingleton_or_nontrivial R
  · simp [Subsingleton.eq_zero (n : R)]
  induction n with
  | zero => simp
  | succ n ih =>
  · grw [Nat.cast_succ, Nat.cast_succ, abv.add_le, abv.map_one, ih]

end IsDomain

end Semiring

end OrderedSemiring

section OrderedRing

section Ring

variable {R S : Type*} [Ring R] [Ring S] [PartialOrder S] [IsOrderedRing S]
  (abv : AbsoluteValue R S)
```

-- snippet 26
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.listSum_le (L102-L106)
lemma listSum_le [AddLeftMono S] (l : List R) : abv l.sum ≤ (l.map abv).sum := by
induction l with
  | nil => simp
  | cons head tail ih => exact (abv.add_le ..).trans <| add_le_add_right ih (abv head)
```

-- snippet 27
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.ext (L76-L79)
theorem ext ⦃f g : AbsoluteValue R S⦄ : (∀ x, f x = g x) → f = g :=
DFunLike.ext _ _

/-- See Note [custom simps projection]. -/
```

-- snippet 28
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.apply_natAbs_eq (L250-L255)
lemma apply_natAbs_eq (x : ℤ) : abv (natAbs x) = abv x := by
obtain ⟨_, rfl | rfl⟩ := Int.eq_nat_or_neg x <;> simp

open Int in
/-- Values of an absolute value coincide on the image of `ℕ` in `R`
if and only if they coincide on the image of `ℤ` in `R`. -/
```

-- snippet 29
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.trivial (L300-L317)
def trivial : AbsoluteValue R S where
  toFun x := if x = 0 then 0 else 1
map_mul' x y := by
    rcases eq_or_ne x 0 with rfl | hx
    · simp
    rcases eq_or_ne y 0 with rfl | hy
    · simp
    simp [hx, hy]
  nonneg' x := by rcases eq_or_ne x 0 with hx | hx <;> simp [hx]
  eq_zero' x := by rcases eq_or_ne x 0 with hx | hx <;> simp [hx]
  add_le' x y := by
    rcases eq_or_ne x 0 with rfl | hx
    · simp
    rcases eq_or_ne y 0 with rfl | hy
    · simp
    simp only [hx, ↓reduceIte, hy, one_add_one_eq_two]
    rcases eq_or_ne (x + y) 0 with hxy | hxy <;> simp [hxy, one_le_two]
```

-- snippet 30
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.nonnegHomClass (L65-L67)
instance nonnegHomClass : NonnegHomClass (AbsoluteValue R S) R S :=
{ AbsoluteValue.zeroHomClass (R := R) (S := S) with apply_nonneg := fun f => f.nonneg' }
```

-- snippet 31
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.addGroupSeminormClass (L238-L242)
instance addGroupSeminormClass : AddGroupSeminormClass (AbsoluteValue R S) R S where
  toSubadditiveHomClass := AbsoluteValue.subadditiveHomClass
map_zero := AbsoluteValue.map_zero
  map_neg_eq_map f a := AbsoluteValue.map_neg f a
```

-- snippet 32
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.eq_on_nat_iff_eq_on_int (L256-L268)
lemma eq_on_nat_iff_eq_on_int {f g : AbsoluteValue R S} :
    (∀ n : ℕ, f n = g n) ↔ ∀ n : ℤ, f n = g n := by
refine ⟨fun h z ↦ ?_, fun a n ↦ mod_cast a n⟩
  obtain ⟨n, rfl | rfl⟩ := Int.eq_nat_or_neg z <;> simp [h n]

end OrderedCommRing

section LinearOrderedRing

variable {R S : Type*} [Semiring R] [Ring S] [LinearOrder S] [IsStrictOrderedRing S]
  (abv : AbsoluteValue R S)

/-- `AbsoluteValue.abs` is `abs` as a bundled `AbsoluteValue`. -/
```

-- snippet 33
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.map_one_of_isLeftRegular (L124-L126)
theorem map_one_of_isLeftRegular (h : IsLeftRegular (abv 1)) : abv 1 = 1 :=
h <| by simp [← abv.map_mul]
```

-- snippet 34
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.coe_toMulHom (L86-L88)
theorem coe_toMulHom : ⇑abv.toMulHom = abv :=
rfl
```

-- snippet 35
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.zeroHomClass (L59-L61)
instance zeroHomClass : ZeroHomClass (AbsoluteValue R S) R S where
  map_zero f := (f.eq_zero' _).2 rfl
```

-- snippet 36
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.subadditiveHomClass (L68-L70)
instance subadditiveHomClass : SubadditiveHomClass (AbsoluteValue R S) R S :=
{ AbsoluteValue.zeroHomClass (R := R) (S := S) with map_add_le_add := fun f => f.add_le' }
```

-- snippet 37
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abs_abv_sub_le_abv_sub (L288-L299)
theorem abs_abv_sub_le_abv_sub (a b : R) : abs (abv a - abv b) ≤ abv (a - b) :=
abs_sub_le_iff.2 ⟨abv.le_sub _ _, by rw [abv.map_sub]; apply abv.le_sub⟩

end LinearOrderedCommRing

section trivial

variable {R : Type*} [Semiring R] [DecidablePred fun x : R ↦ x = 0] [NoZeroDivisors R]
variable {S : Type*} [Semiring S] [PartialOrder S] [IsOrderedRing S] [Nontrivial S]

/-- The *trivial* absolute value takes the value `1` on all nonzero elements. -/
protected
```

-- snippet 38
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.coe_toMonoidHom (L177-L179)
theorem coe_toMonoidHom : ⇑abv.toMonoidHom = abv :=
rfl
```

-- snippet 39
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.map_sub_eq_zero_iff (L141-L154)
theorem map_sub_eq_zero_iff (a b : R) : abv (a - b) = 0 ↔ a = b :=
abv.eq_zero.trans sub_eq_zero

end Ring

section Semiring

section IsDomain

-- all of these are true for `NoZeroDivisors S`; but it doesn't work smoothly with the
-- `IsDomain`/`IsCancelMulZero` API
variable {R S : Type*} [Semiring R] [Semiring S] [PartialOrder S] (abv : AbsoluteValue R S)
variable [IsDomain S] [Nontrivial R]
```

-- snippet 40
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.toMonoidWithZeroHom (L165-L167)
def toMonoidWithZeroHom : R →*₀ S :=
abv
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Algebra.Order.Interval.Set.Group).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
theorem add_mem_Ioc_iff_right : a + b ∈ Set.Ioc c d ↔ b ∈ Set.Ioc (c - a) (d - a)
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.inv_mem_Icc_iff (L32-L34)
theorem inv_mem_Icc_iff : a⁻¹ ∈ Set.Icc c d ↔ a ∈ Set.Icc d⁻¹ c⁻¹ :=
and_comm.trans <| and_congr inv_le' le_inv'
```

-- snippet 2
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.inv_mem_Ico_iff (L36-L38)
theorem inv_mem_Ico_iff : a⁻¹ ∈ Set.Ico c d ↔ a ∈ Set.Ioc d⁻¹ c⁻¹ :=
and_comm.trans <| and_congr inv_lt' le_inv'
```

-- snippet 3
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.inv_mem_Ioc_iff (L40-L42)
theorem inv_mem_Ioc_iff : a⁻¹ ∈ Set.Ioc c d ↔ a ∈ Set.Ico d⁻¹ c⁻¹ :=
and_comm.trans <| and_congr inv_le' lt_inv'
```

-- snippet 4
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.inv_mem_Ioo_iff (L44-L54)
theorem inv_mem_Ioo_iff : a⁻¹ ∈ Set.Ioo c d ↔ a ∈ Set.Ioo d⁻¹ c⁻¹ :=
and_comm.trans <| and_congr inv_lt' lt_inv'

end OrderedCommGroup

section OrderedAddCommGroup

variable [AddCommGroup α] [PartialOrder α] [IsOrderedAddMonoid α] {a b c d : α}

/-! `add_mem_Ixx_iff_left` -/
```

-- snippet 5
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.add_mem_Icc_iff_left (L55-L57)
theorem add_mem_Icc_iff_left : a + b ∈ Set.Icc c d ↔ a ∈ Set.Icc (c - b) (d - b) :=
(and_congr sub_le_iff_le_add le_sub_iff_add_le).symm
```

-- snippet 6
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.add_mem_Ico_iff_left (L58-L60)
theorem add_mem_Ico_iff_left : a + b ∈ Set.Ico c d ↔ a ∈ Set.Ico (c - b) (d - b) :=
(and_congr sub_le_iff_le_add lt_sub_iff_add_lt).symm
```

-- snippet 7
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.add_mem_Ioc_iff_left (L61-L63)
theorem add_mem_Ioc_iff_left : a + b ∈ Set.Ioc c d ↔ a ∈ Set.Ioc (c - b) (d - b) :=
(and_congr sub_lt_iff_lt_add le_sub_iff_add_le).symm
```

-- snippet 8
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.add_mem_Ioo_iff_left (L64-L68)
theorem add_mem_Ioo_iff_left : a + b ∈ Set.Ioo c d ↔ a ∈ Set.Ioo (c - b) (d - b) :=
(and_congr sub_lt_iff_lt_add lt_sub_iff_add_lt).symm

/-! `add_mem_Ixx_iff_right` -/
```

-- snippet 9
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.add_mem_Icc_iff_right (L69-L71)
theorem add_mem_Icc_iff_right : a + b ∈ Set.Icc c d ↔ b ∈ Set.Icc (c - a) (d - a) :=
(and_congr sub_le_iff_le_add' le_sub_iff_add_le').symm
```

-- snippet 10
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.add_mem_Ico_iff_right (L72-L74)
theorem add_mem_Ico_iff_right : a + b ∈ Set.Ico c d ↔ b ∈ Set.Ico (c - a) (d - a) :=
(and_congr sub_le_iff_le_add' lt_sub_iff_add_lt').symm
```

-- snippet 11
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.add_mem_Ioo_iff_right (L78-L82)
theorem add_mem_Ioo_iff_right : a + b ∈ Set.Ioo c d ↔ b ∈ Set.Ioo (c - a) (d - a) :=
(and_congr sub_lt_iff_lt_add' lt_sub_iff_add_lt').symm

/-! `sub_mem_Ixx_iff_left` -/
```

-- snippet 12
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.sub_mem_Icc_iff_left (L83-L85)
theorem sub_mem_Icc_iff_left : a - b ∈ Set.Icc c d ↔ a ∈ Set.Icc (c + b) (d + b) :=
and_congr le_sub_iff_add_le sub_le_iff_le_add
```

-- snippet 13
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.sub_mem_Ico_iff_left (L86-L88)
theorem sub_mem_Ico_iff_left : a - b ∈ Set.Ico c d ↔ a ∈ Set.Ico (c + b) (d + b) :=
and_congr le_sub_iff_add_le sub_lt_iff_lt_add
```

-- snippet 14
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.sub_mem_Ioc_iff_left (L89-L91)
theorem sub_mem_Ioc_iff_left : a - b ∈ Set.Ioc c d ↔ a ∈ Set.Ioc (c + b) (d + b) :=
and_congr lt_sub_iff_add_lt sub_le_iff_le_add
```

-- snippet 15
```lean
-- Mathlib.Algebra.Order.Interval.Set.Group.sub_mem_Ioo_iff_left (L92-L96)
theorem sub_mem_Ioo_iff_left : a - b ∈ Set.Ioo c d ↔ a ∈ Set.Ioo (c + b) (d + b) :=
and_congr lt_sub_iff_add_lt sub_lt_iff_lt_add

/-! `sub_mem_Ixx_iff_right` -/
```

-- snippet 16
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.Simps (L80-L84)
def Simps.apply (f : AbsoluteValue R S) : R → S :=
f

initialize_simps_projections AbsoluteValue (toFun → apply)
```

-- snippet 17
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.sub_le_add (L235-L237)
lemma sub_le_add (a b : R) : abv (a - b) ≤ abv a + abv b := by
simpa only [← sub_eq_add_neg, AbsoluteValue.map_neg] using abv.add_le a (-b)
```

-- snippet 18
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.coe_toMonoidWithZeroHom (L169-L172)
theorem coe_toMonoidWithZeroHom : ⇑abv.toMonoidWithZeroHom = abv :=
rfl

/-- Absolute values from a nontrivial `R` to a linear ordered ring preserve `*` and `1`. -/
```

-- snippet 19
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.funLike (L55-L58)
instance funLike : FunLike (AbsoluteValue R S) R S where
  coe f := f.toFun
coe_injective' f g h := by obtain ⟨⟨_, _⟩, _⟩ := f; obtain ⟨⟨_, _⟩, _⟩ := g; congr
```

-- snippet 20
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.mulHomClass (L62-L64)
instance mulHomClass : MulHomClass (AbsoluteValue R S) R S :=
{ AbsoluteValue.zeroHomClass (R := R) (S := S) with map_mul := fun f => f.map_mul' }
```

-- snippet 21
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.monoidWithZeroHomClass (L159-L164)
instance monoidWithZeroHomClass : MonoidWithZeroHomClass (AbsoluteValue R S) R S :=
{ AbsoluteValue.mulHomClass with
    map_zero := fun f => f.map_zero
    map_one := fun f => f.map_one }

/-- Absolute values from a nontrivial `R` to a linear ordered ring preserve `*`, `0` and `1`. -/
```

-- snippet 22
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.trivial_apply (L319-L334)
lemma trivial_apply {x : R} (hx : x ≠ 0) : AbsoluteValue.trivial (S := S) x = 1 :=
if_neg hx

end trivial

section nontrivial

section OrderedSemiring

variable {R : Type*} [Semiring R] {S : Type*} [Semiring S] [PartialOrder S] [IsOrderedRing S]

/-- An absolute value on a semiring `R` without zero divisors is *nontrivial* if it takes
a value `≠ 1` on a nonzero element.

This has the advantage over `v ≠ .trivial` that it does not require decidability
of `· = 0` in `R`. -/
```

-- snippet 23
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.coe_mk (L72-L74)
theorem coe_mk (f : R →ₙ* S) {h₁ h₂ h₃} : (AbsoluteValue.mk f h₁ h₂ h₃ : R → S) = f :=
rfl
```

-- snippet 24
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.toMonoidHom (L173-L175)
def toMonoidHom : R →* S :=
abv
```

-- snippet 25
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.apply_nat_le_self (L186-L206)
lemma apply_nat_le_self [IsOrderedRing S] (n : ℕ) : abv n ≤ n := by
cases subsingleton_or_nontrivial R
  · simp [Subsingleton.eq_zero (n : R)]
  induction n with
  | zero => simp
  | succ n ih =>
  · grw [Nat.cast_succ, Nat.cast_succ, abv.add_le, abv.map_one, ih]

end IsDomain

end Semiring

end OrderedSemiring

section OrderedRing

section Ring

variable {R S : Type*} [Ring R] [Ring S] [PartialOrder S] [IsOrderedRing S]
  (abv : AbsoluteValue R S)
```

-- snippet 26
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.listSum_le (L102-L106)
lemma listSum_le [AddLeftMono S] (l : List R) : abv l.sum ≤ (l.map abv).sum := by
induction l with
  | nil => simp
  | cons head tail ih => exact (abv.add_le ..).trans <| add_le_add_right ih (abv head)
```

-- snippet 27
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.ext (L76-L79)
theorem ext ⦃f g : AbsoluteValue R S⦄ : (∀ x, f x = g x) → f = g :=
DFunLike.ext _ _

/-- See Note [custom simps projection]. -/
```

-- snippet 28
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.apply_natAbs_eq (L250-L255)
lemma apply_natAbs_eq (x : ℤ) : abv (natAbs x) = abv x := by
obtain ⟨_, rfl | rfl⟩ := Int.eq_nat_or_neg x <;> simp

open Int in
/-- Values of an absolute value coincide on the image of `ℕ` in `R`
if and only if they coincide on the image of `ℤ` in `R`. -/
```

-- snippet 29
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.trivial (L300-L317)
def trivial : AbsoluteValue R S where
  toFun x := if x = 0 then 0 else 1
map_mul' x y := by
    rcases eq_or_ne x 0 with rfl | hx
    · simp
    rcases eq_or_ne y 0 with rfl | hy
    · simp
    simp [hx, hy]
  nonneg' x := by rcases eq_or_ne x 0 with hx | hx <;> simp [hx]
  eq_zero' x := by rcases eq_or_ne x 0 with hx | hx <;> simp [hx]
  add_le' x y := by
    rcases eq_or_ne x 0 with rfl | hx
    · simp
    rcases eq_or_ne y 0 with rfl | hy
    · simp
    simp only [hx, ↓reduceIte, hy, one_add_one_eq_two]
    rcases eq_or_ne (x + y) 0 with hxy | hxy <;> simp [hxy, one_le_two]
```

-- snippet 30
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.nonnegHomClass (L65-L67)
instance nonnegHomClass : NonnegHomClass (AbsoluteValue R S) R S :=
{ AbsoluteValue.zeroHomClass (R := R) (S := S) with apply_nonneg := fun f => f.nonneg' }
```

-- snippet 31
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.addGroupSeminormClass (L238-L242)
instance addGroupSeminormClass : AddGroupSeminormClass (AbsoluteValue R S) R S where
  toSubadditiveHomClass := AbsoluteValue.subadditiveHomClass
map_zero := AbsoluteValue.map_zero
  map_neg_eq_map f a := AbsoluteValue.map_neg f a
```

-- snippet 32
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.eq_on_nat_iff_eq_on_int (L256-L268)
lemma eq_on_nat_iff_eq_on_int {f g : AbsoluteValue R S} :
    (∀ n : ℕ, f n = g n) ↔ ∀ n : ℤ, f n = g n := by
refine ⟨fun h z ↦ ?_, fun a n ↦ mod_cast a n⟩
  obtain ⟨n, rfl | rfl⟩ := Int.eq_nat_or_neg z <;> simp [h n]

end OrderedCommRing

section LinearOrderedRing

variable {R S : Type*} [Semiring R] [Ring S] [LinearOrder S] [IsStrictOrderedRing S]
  (abv : AbsoluteValue R S)

/-- `AbsoluteValue.abs` is `abs` as a bundled `AbsoluteValue`. -/
```

-- snippet 33
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.map_one_of_isLeftRegular (L124-L126)
theorem map_one_of_isLeftRegular (h : IsLeftRegular (abv 1)) : abv 1 = 1 :=
h <| by simp [← abv.map_mul]
```

-- snippet 34
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.coe_toMulHom (L86-L88)
theorem coe_toMulHom : ⇑abv.toMulHom = abv :=
rfl
```

-- snippet 35
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.zeroHomClass (L59-L61)
instance zeroHomClass : ZeroHomClass (AbsoluteValue R S) R S where
  map_zero f := (f.eq_zero' _).2 rfl
```

-- snippet 36
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.subadditiveHomClass (L68-L70)
instance subadditiveHomClass : SubadditiveHomClass (AbsoluteValue R S) R S :=
{ AbsoluteValue.zeroHomClass (R := R) (S := S) with map_add_le_add := fun f => f.add_le' }
```

-- snippet 37
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.abs_abv_sub_le_abv_sub (L288-L299)
theorem abs_abv_sub_le_abv_sub (a b : R) : abs (abv a - abv b) ≤ abv (a - b) :=
abs_sub_le_iff.2 ⟨abv.le_sub _ _, by rw [abv.map_sub]; apply abv.le_sub⟩

end LinearOrderedCommRing

section trivial

variable {R : Type*} [Semiring R] [DecidablePred fun x : R ↦ x = 0] [NoZeroDivisors R]
variable {S : Type*} [Semiring S] [PartialOrder S] [IsOrderedRing S] [Nontrivial S]

/-- The *trivial* absolute value takes the value `1` on all nonzero elements. -/
protected
```

-- snippet 38
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.coe_toMonoidHom (L177-L179)
theorem coe_toMonoidHom : ⇑abv.toMonoidHom = abv :=
rfl
```

-- snippet 39
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.map_sub_eq_zero_iff (L141-L154)
theorem map_sub_eq_zero_iff (a b : R) : abv (a - b) = 0 ↔ a = b :=
abv.eq_zero.trans sub_eq_zero

end Ring

section Semiring

section IsDomain

-- all of these are true for `NoZeroDivisors S`; but it doesn't work smoothly with the
-- `IsDomain`/`IsCancelMulZero` API
variable {R S : Type*} [Semiring R] [Semiring S] [PartialOrder S] (abv : AbsoluteValue R S)
variable [IsDomain S] [Nontrivial R]
```

-- snippet 40
```lean
-- Mathlib.Algebra.Order.AbsoluteValue.Basic.toMonoidWithZeroHom (L165-L167)
def toMonoidWithZeroHom : R →*₀ S :=
abv
```
[/INST]

mistral-common:Tekken v15 (Mistral chat template, [INST]/[SYSTEM_PROMPT])


[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Order.BooleanAlgebra.Basic).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
instance OrderDual.instBooleanAlgebra : BooleanAlgebra αᵒᵈ where
  __
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.sup_inf_sdiff (L53-L55)
theorem sup_inf_sdiff (x y : α) : x ⊓ y ⊔ x \ y = x :=
GeneralizedBooleanAlgebra.sup_inf_sdiff _ _
```

-- snippet 2
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.inf_inf_sdiff (L57-L59)
theorem inf_inf_sdiff (x y : α) : x ⊓ y ⊓ x \ y = ⊥ :=
GeneralizedBooleanAlgebra.inf_inf_sdiff _ _
```

-- snippet 3
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.sup_sdiff_inf (L61-L62)
theorem sup_sdiff_inf (x y : α) : x \ y ⊔ x ⊓ y = x := by rw [sup_comm, sup_inf_sdiff]
```

-- snippet 4
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.inf_sdiff_inf (L64-L66)
theorem inf_sdiff_inf (x y : α) : x \ y ⊓ (x ⊓ y) = ⊥ := by rw [inf_comm, inf_inf_sdiff]
-- see Note [lower instance priority]
```

-- snippet 5
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.disjoint_inf_sdiff (L73-L76)
theorem disjoint_inf_sdiff : Disjoint (x ⊓ y) (x \ y) :=
disjoint_iff_inf_le.mpr (inf_inf_sdiff x y).le

-- TODO: in distributive lattices, relative complements are unique when they exist
```

-- snippet 6
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.sdiff_unique (L77-L97)
theorem sdiff_unique (s : x ⊓ y ⊔ z = x) (i : x ⊓ y ⊓ z = ⊥) : x \ y = z := by
conv_rhs at s => rw [← sup_inf_sdiff x y, sup_comm]
  rw [sup_comm] at s
  conv_rhs at i => rw [← inf_inf_sdiff x y, inf_comm]
  rw [inf_comm] at i
  exact (eq_of_inf_eq_sup_eq i s).symm

-- Use `sdiff_le`
private theorem sdiff_le' : x \ y ≤ x :=
  calc
    x \ y ≤ x ⊓ y ⊔ x \ y := le_sup_right
    _ = x := sup_inf_sdiff x y

set_option backward.privateInPublic true in
-- Use `sdiff_sup_self`
private theorem sdiff_sup_self' : y \ x ⊔ x = y ⊔ x :=
  calc
    y \ x ⊔ x = y \ x ⊔ (x ⊔ x ⊓ y) := by rw [sup_inf_self]
    _ = y ⊓ x ⊔ y \ x ⊔ x := by ac_rfl
    _ = y ⊔ x := by rw [sup_inf_sdiff]
```

-- snippet 7
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.sdiff_inf_sdiff (L99-L109)
theorem sdiff_inf_sdiff : x \ y ⊓ y \ x = ⊥ :=
Eq.symm <|
    calc
      ⊥ = x ⊓ (y ⊓ x ⊔ y \ x) ⊓ x \ y := by rw [← inf_inf_sdiff, sup_inf_sdiff]
      _ = (x ⊓ (y ⊓ x) ⊔ x ⊓ y \ x) ⊓ x \ y := by rw [inf_sup_left]
      _ = (y ⊓ (x ⊓ x) ⊔ x ⊓ y \ x) ⊓ x \ y := by ac_rfl
      _ = x ⊓ y \ x ⊓ x \ y := by
          rw [inf_idem, inf_sup_right, ← inf_comm x y, inf_inf_sdiff, bot_sup_eq]
      _ = x ⊓ x \ y ⊓ y \ x := by ac_rfl
      _ = x \ y ⊓ y \ x := by rw [inf_of_le_right sdiff_le']
```

-- snippet 8
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.disjoint_sdiff_sdiff (L110-L112)
theorem disjoint_sdiff_sdiff : Disjoint (x \ y) (y \ x) :=
disjoint_iff_inf_le.mpr sdiff_inf_sdiff.le
```

-- snippet 9
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.inf_sdiff_self_right (L114-L118)
theorem inf_sdiff_self_right : x ⊓ y \ x = ⊥ :=
calc
    x ⊓ y \ x = (x ⊓ y ⊔ x \ y) ⊓ y \ x := by rw [sup_inf_sdiff]
    _ = ⊥ := by rw [inf_sup_right, inf_comm x y, inf_inf_sdiff, sdiff_inf_sdiff, bot_sup_eq]
```

-- snippet 10
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.inf_sdiff_self_left (L120-L124)
theorem inf_sdiff_self_left : y \ x ⊓ x = ⊥ := by rw [inf_comm, inf_sdiff_self_right]
set_option backward.privateInPublic true in
set_option backward.privateInPublic.warn false in
-- see Note [lower instance priority]
```

-- snippet 11
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.disjoint_sdiff_self_left (L145-L147)
theorem disjoint_sdiff_self_left : Disjoint (y \ x) x :=
disjoint_iff_inf_le.mpr inf_sdiff_self_left.le
```

-- snippet 12
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.disjoint_sdiff_self_right (L148-L150)
theorem disjoint_sdiff_self_right : Disjoint x (y \ x) :=
disjoint_iff_inf_le.mpr inf_sdiff_self_right.le
```

-- snippet 13
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.le_sdiff (L151-L154)
lemma le_sdiff : x ≤ y \ z ↔ x ≤ y ∧ Disjoint x z :=
⟨fun h ↦ ⟨h.trans sdiff_le, disjoint_sdiff_self_left.mono_left h⟩, fun h ↦
    by rw [← h.2.sdiff_eq_left]; exact sdiff_le_sdiff_right h.1⟩
```

-- snippet 14
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.Disjoint (L160-L173)
theorem Disjoint.sdiff_eq_of_sup_eq (hi : Disjoint x z) (hs : x ⊔ z = y) : y \ x = z :=
have h : y ⊓ x = x := inf_eq_right.2 <| le_sup_left.trans hs.le
  sdiff_unique (by rw [h, hs]) (by rw [h, hi.eq_bot])

protected theorem Disjoint.sdiff_unique (hd : Disjoint x z) (hz : z ≤ y) (hs : y ≤ x ⊔ z) :
    y \ x = z :=
  sdiff_unique
    (by
      rw [← inf_eq_right] at hs
      rwa [sup_inf_right, inf_sup_right, sup_comm x, inf_sup_self, inf_comm, sup_comm z,
        hs, sup_eq_left])
    (by rw [inf_assoc, hd.eq_bot, inf_bot_eq])

-- cf. `IsCompl.disjoint_left_iff` and `IsCompl.disjoint_right_iff`
```

-- snippet 15
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.disjoint_sdiff_iff_le (L174-L183)
theorem disjoint_sdiff_iff_le (hz : z ≤ y) (hx : x ≤ y) : Disjoint z (y \ x) ↔ z ≤ x :=
⟨fun H =>
    le_of_inf_le_sup_le (le_trans H.le_bot bot_le)
      (by
        rw [sup_sdiff_cancel_right hx]
        grw [sdiff_le]
        rw [sup_eq_right.2 hz]),
    fun H => disjoint_sdiff_self_right.mono_left H⟩

-- cf. `IsCompl.le_left_iff` and `IsCompl.le_right_iff`
```

-- snippet 16
```lean
-- Mathlib.Order.BooleanAlgebra.Set.sdiff_inter_right_comm (L47-L48)
lemma sdiff_inter_right_comm (s t u : Set α) : s \ t ∩ u = (s ∩ u) \ t := sdiff_inf_right_comm ..
```

-- snippet 17
```lean
-- Mathlib.Order.BooleanAlgebra.Set.compl_univ (L106-L108)
theorem compl_univ : (univ : Set α)ᶜ = ∅ :=
compl_top
```

-- snippet 18
```lean
-- Mathlib.Order.BooleanAlgebra.Set.diff_diff_eq_sdiff_union (L58-L59)
theorem diff_diff_eq_sdiff_union (h : u ⊆ s) : s \ (t \ u) = s \ t ∪ u := sdiff_sdiff_eq_sdiff_sup h
```

-- snippet 19
```lean
-- Mathlib.Order.BooleanAlgebra.Set.inter_diff_distrib_left (L60-L62)
theorem inter_diff_distrib_left (s t u : Set α) : s ∩ (t \ u) = (s ∩ t) \ (s ∩ u) :=
inf_sdiff_distrib_left _ _ _
```

-- snippet 20
```lean
-- Mathlib.Order.BooleanAlgebra.Set.notMem_compl_iff (L83-L85)
theorem notMem_compl_iff {x : α} : x ∉ sᶜ ↔ x ∈ s :=
not_not
```

-- snippet 21
```lean
-- Mathlib.Order.BooleanAlgebra.Set.compl_def (L71-L73)
theorem compl_def (s : Set α) : sᶜ = { x | x ∉ s } :=
rfl
```

-- snippet 22
```lean
-- Mathlib.Order.BooleanAlgebra.Set.compl_inter (L102-L104)
theorem compl_inter (s t : Set α) : (s ∩ t)ᶜ = sᶜ ∪ tᶜ :=
compl_inf
```

-- snippet 23
```lean
-- Mathlib.Order.BooleanAlgebra.Set.mem_compl (L74-L76)
theorem mem_compl {s : Set α} {x : α} (h : x ∉ s) : x ∈ sᶜ :=
h
```

-- snippet 24
```lean
-- Mathlib.Order.BooleanAlgebra.Set.inter_diff_assoc (L44-L46)
lemma inter_diff_assoc (a b c : Set α) : (a ∩ b) \ c = a ∩ (b \ c) := inf_sdiff_assoc ..
/-- See also `Set.inter_diff_assoc`. -/
```

-- snippet 25
```lean
-- Mathlib.Order.BooleanAlgebra.Set.compl_setOf (L77-L79)
theorem compl_setOf {α} (p : α → Prop) : { a | p a }ᶜ = { a | ¬p a } :=
rfl
```

-- snippet 26
```lean
-- Mathlib.Order.BooleanAlgebra.Set.inter_compl_self (L87-L89)
theorem inter_compl_self (s : Set α) : s ∩ sᶜ = ∅ :=
inf_compl_eq_bot
```

-- snippet 27
```lean
-- Mathlib.Order.BooleanAlgebra.Defs.PUnit (L148-L163)
instance PUnit.instBooleanAlgebra : BooleanAlgebra PUnit where
  __ := PUnit.instBiheytingAlgebra
le_sup_inf := by simp
  inf_compl_le_bot _ := trivial
  top_le_sup_compl _ := trivial

namespace DistribLattice

variable (α) [DistribLattice α]

/--
An alternative constructor for Boolean algebras:
a distributive lattice that is complemented is a Boolean algebra.

This is not an instance, because it creates data using choice.
-/
```

-- snippet 28
```lean
-- Mathlib.Order.BooleanAlgebra.Set.instBooleanAlgebra (L40-L43)
instance instBooleanAlgebra : BooleanAlgebra (Set α) :=
fast_instance% { (inferInstance : BooleanAlgebra (α → Prop)) with }

/-- See also `Set.sdiff_inter_right_comm`. -/
```

-- snippet 29
```lean
-- Mathlib.Order.BooleanAlgebra.Defs.Prop (L126-L133)
instance Prop.instBooleanAlgebra : BooleanAlgebra Prop where
  __ := Prop.instHeytingAlgebra
__ := GeneralizedHeytingAlgebra.toDistribLattice
  compl := Not
  himp_eq _ _ := propext imp_iff_or_not
  inf_compl_le_bot _ H := H.2 H.1
  top_le_sup_compl p _ := Classical.em p
```

-- snippet 30
```lean
-- Mathlib.Order.BooleanAlgebra.Set.inter_sdiff_left_comm (L49-L50)
lemma inter_sdiff_left_comm (s t u : Set α) : s ∩ (t \ u) = t ∩ (s \ u) := inf_sdiff_left_comm ..
```

-- snippet 31
```lean
-- Mathlib.Order.BooleanAlgebra.Set.diff_union_diff_cancel' (L55-L57)
theorem diff_union_diff_cancel' (hi : s ∩ u ⊆ t) (hu : t ⊆ s ∪ u) : (s \ t) ∪ (t \ u) = s \ u :=
sdiff_sup_sdiff_cancel' hi hu
```

-- snippet 32
```lean
-- Mathlib.Order.BooleanAlgebra.Defs.booleanAlgebraOfComplemented (L166-L172)
def booleanAlgebraOfComplemented [BoundedOrder α] [ComplementedLattice α] : BooleanAlgebra α where
  __ := ((inferInstance : BoundedOrder α))
compl a := Classical.choose <| exists_isCompl a
  inf_compl_le_bot a := (Classical.choose_spec (exists_isCompl a)).disjoint.le_bot
  top_le_sup_compl a := (Classical.choose_spec (exists_isCompl a)).codisjoint.top_le

end DistribLattice
```

-- snippet 33
```lean
-- Mathlib.Order.BooleanAlgebra.Set.compl_union (L99-L101)
theorem compl_union (s t : Set α) : (s ∪ t)ᶜ = sᶜ ∩ tᶜ :=
compl_sup
```

-- snippet 34
```lean
-- Mathlib.Order.BooleanAlgebra.Set.diff_union_diff_cancel (L51-L54)
theorem diff_union_diff_cancel (hts : t ⊆ s) (hut : u ⊆ t) : s \ t ∪ t \ u = s \ u :=
sdiff_sup_sdiff_cancel hts hut

/-- A version of `diff_union_diff_cancel` with more general hypotheses. -/
```

-- snippet 35
```lean
-- Mathlib.Order.BooleanAlgebra.Set.compl_inter_self (L91-L93)
theorem compl_inter_self (s : Set α) : sᶜ ∩ s = ∅ :=
compl_inf_eq_bot
```

-- snippet 36
```lean
-- Mathlib.Order.BooleanAlgebra.Set.diff_inter_distrib_right (L66-L70)
theorem diff_inter_distrib_right (s t r : Set α) : (t ∩ r) \ s = (t \ s) ∩ (r \ s) :=
inf_sdiff

/-! ### Lemmas about complement -/
```

-- snippet 37
```lean
-- Mathlib.Order.BooleanAlgebra.Set.notMem_of_mem_compl (L80-L82)
theorem notMem_of_mem_compl {s : Set α} {x : α} (h : x ∈ sᶜ) : x ∉ s :=
h
```

-- snippet 38
```lean
-- Mathlib.Order.BooleanAlgebra.Set.compl_empty (L95-L97)
theorem compl_empty : (∅ : Set α)ᶜ = univ :=
compl_bot
```

-- snippet 39
```lean
-- Mathlib.Order.BooleanAlgebra.Defs.Bool (L134-L139)
instance Bool.instBooleanAlgebra : BooleanAlgebra Bool where
  __ := instBoundedOrder
compl := not
  inf_compl_le_bot a := a.and_not_self.le
  top_le_sup_compl a := a.or_not_self.ge
```

-- snippet 40
```lean
-- Mathlib.Order.BooleanAlgebra.Set.inter_diff_distrib_right (L63-L65)
theorem inter_diff_distrib_right (s t u : Set α) : (s \ t) ∩ u = (s ∩ u) \ (t ∩ u) :=
inf_sdiff_distrib_right _ _ _
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.Order.BooleanAlgebra.Basic).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
instance OrderDual.instBooleanAlgebra : BooleanAlgebra αᵒᵈ where
  __
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.sup_inf_sdiff (L53-L55)
theorem sup_inf_sdiff (x y : α) : x ⊓ y ⊔ x \ y = x :=
GeneralizedBooleanAlgebra.sup_inf_sdiff _ _
```

-- snippet 2
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.inf_inf_sdiff (L57-L59)
theorem inf_inf_sdiff (x y : α) : x ⊓ y ⊓ x \ y = ⊥ :=
GeneralizedBooleanAlgebra.inf_inf_sdiff _ _
```

-- snippet 3
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.sup_sdiff_inf (L61-L62)
theorem sup_sdiff_inf (x y : α) : x \ y ⊔ x ⊓ y = x := by rw [sup_comm, sup_inf_sdiff]
```

-- snippet 4
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.inf_sdiff_inf (L64-L66)
theorem inf_sdiff_inf (x y : α) : x \ y ⊓ (x ⊓ y) = ⊥ := by rw [inf_comm, inf_inf_sdiff]
-- see Note [lower instance priority]
```

-- snippet 5
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.disjoint_inf_sdiff (L73-L76)
theorem disjoint_inf_sdiff : Disjoint (x ⊓ y) (x \ y) :=
disjoint_iff_inf_le.mpr (inf_inf_sdiff x y).le

-- TODO: in distributive lattices, relative complements are unique when they exist
```

-- snippet 6
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.sdiff_unique (L77-L97)
theorem sdiff_unique (s : x ⊓ y ⊔ z = x) (i : x ⊓ y ⊓ z = ⊥) : x \ y = z := by
conv_rhs at s => rw [← sup_inf_sdiff x y, sup_comm]
  rw [sup_comm] at s
  conv_rhs at i => rw [← inf_inf_sdiff x y, inf_comm]
  rw [inf_comm] at i
  exact (eq_of_inf_eq_sup_eq i s).symm

-- Use `sdiff_le`
private theorem sdiff_le' : x \ y ≤ x :=
  calc
    x \ y ≤ x ⊓ y ⊔ x \ y := le_sup_right
    _ = x := sup_inf_sdiff x y

set_option backward.privateInPublic true in
-- Use `sdiff_sup_self`
private theorem sdiff_sup_self' : y \ x ⊔ x = y ⊔ x :=
  calc
    y \ x ⊔ x = y \ x ⊔ (x ⊔ x ⊓ y) := by rw [sup_inf_self]
    _ = y ⊓ x ⊔ y \ x ⊔ x := by ac_rfl
    _ = y ⊔ x := by rw [sup_inf_sdiff]
```

-- snippet 7
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.sdiff_inf_sdiff (L99-L109)
theorem sdiff_inf_sdiff : x \ y ⊓ y \ x = ⊥ :=
Eq.symm <|
    calc
      ⊥ = x ⊓ (y ⊓ x ⊔ y \ x) ⊓ x \ y := by rw [← inf_inf_sdiff, sup_inf_sdiff]
      _ = (x ⊓ (y ⊓ x) ⊔ x ⊓ y \ x) ⊓ x \ y := by rw [inf_sup_left]
      _ = (y ⊓ (x ⊓ x) ⊔ x ⊓ y \ x) ⊓ x \ y := by ac_rfl
      _ = x ⊓ y \ x ⊓ x \ y := by
          rw [inf_idem, inf_sup_right, ← inf_comm x y, inf_inf_sdiff, bot_sup_eq]
      _ = x ⊓ x \ y ⊓ y \ x := by ac_rfl
      _ = x \ y ⊓ y \ x := by rw [inf_of_le_right sdiff_le']
```

-- snippet 8
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.disjoint_sdiff_sdiff (L110-L112)
theorem disjoint_sdiff_sdiff : Disjoint (x \ y) (y \ x) :=
disjoint_iff_inf_le.mpr sdiff_inf_sdiff.le
```

-- snippet 9
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.inf_sdiff_self_right (L114-L118)
theorem inf_sdiff_self_right : x ⊓ y \ x = ⊥ :=
calc
    x ⊓ y \ x = (x ⊓ y ⊔ x \ y) ⊓ y \ x := by rw [sup_inf_sdiff]
    _ = ⊥ := by rw [inf_sup_right, inf_comm x y, inf_inf_sdiff, sdiff_inf_sdiff, bot_sup_eq]
```

-- snippet 10
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.inf_sdiff_self_left (L120-L124)
theorem inf_sdiff_self_left : y \ x ⊓ x = ⊥ := by rw [inf_comm, inf_sdiff_self_right]
set_option backward.privateInPublic true in
set_option backward.privateInPublic.warn false in
-- see Note [lower instance priority]
```

-- snippet 11
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.disjoint_sdiff_self_left (L145-L147)
theorem disjoint_sdiff_self_left : Disjoint (y \ x) x :=
disjoint_iff_inf_le.mpr inf_sdiff_self_left.le
```

-- snippet 12
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.disjoint_sdiff_self_right (L148-L150)
theorem disjoint_sdiff_self_right : Disjoint x (y \ x) :=
disjoint_iff_inf_le.mpr inf_sdiff_self_right.le
```

-- snippet 13
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.le_sdiff (L151-L154)
lemma le_sdiff : x ≤ y \ z ↔ x ≤ y ∧ Disjoint x z :=
⟨fun h ↦ ⟨h.trans sdiff_le, disjoint_sdiff_self_left.mono_left h⟩, fun h ↦
    by rw [← h.2.sdiff_eq_left]; exact sdiff_le_sdiff_right h.1⟩
```

-- snippet 14
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.Disjoint (L160-L173)
theorem Disjoint.sdiff_eq_of_sup_eq (hi : Disjoint x z) (hs : x ⊔ z = y) : y \ x = z :=
have h : y ⊓ x = x := inf_eq_right.2 <| le_sup_left.trans hs.le
  sdiff_unique (by rw [h, hs]) (by rw [h, hi.eq_bot])

protected theorem Disjoint.sdiff_unique (hd : Disjoint x z) (hz : z ≤ y) (hs : y ≤ x ⊔ z) :
    y \ x = z :=
  sdiff_unique
    (by
      rw [← inf_eq_right] at hs
      rwa [sup_inf_right, inf_sup_right, sup_comm x, inf_sup_self, inf_comm, sup_comm z,
        hs, sup_eq_left])
    (by rw [inf_assoc, hd.eq_bot, inf_bot_eq])

-- cf. `IsCompl.disjoint_left_iff` and `IsCompl.disjoint_right_iff`
```

-- snippet 15
```lean
-- Mathlib.Order.BooleanAlgebra.Basic.disjoint_sdiff_iff_le (L174-L183)
theorem disjoint_sdiff_iff_le (hz : z ≤ y) (hx : x ≤ y) : Disjoint z (y \ x) ↔ z ≤ x :=
⟨fun H =>
    le_of_inf_le_sup_le (le_trans H.le_bot bot_le)
      (by
        rw [sup_sdiff_cancel_right hx]
        grw [sdiff_le]
        rw [sup_eq_right.2 hz]),
    fun H => disjoint_sdiff_self_right.mono_left H⟩

-- cf. `IsCompl.le_left_iff` and `IsCompl.le_right_iff`
```

-- snippet 16
```lean
-- Mathlib.Order.BooleanAlgebra.Set.sdiff_inter_right_comm (L47-L48)
lemma sdiff_inter_right_comm (s t u : Set α) : s \ t ∩ u = (s ∩ u) \ t := sdiff_inf_right_comm ..
```

-- snippet 17
```lean
-- Mathlib.Order.BooleanAlgebra.Set.compl_univ (L106-L108)
theorem compl_univ : (univ : Set α)ᶜ = ∅ :=
compl_top
```

-- snippet 18
```lean
-- Mathlib.Order.BooleanAlgebra.Set.diff_diff_eq_sdiff_union (L58-L59)
theorem diff_diff_eq_sdiff_union (h : u ⊆ s) : s \ (t \ u) = s \ t ∪ u := sdiff_sdiff_eq_sdiff_sup h
```

-- snippet 19
```lean
-- Mathlib.Order.BooleanAlgebra.Set.inter_diff_distrib_left (L60-L62)
theorem inter_diff_distrib_left (s t u : Set α) : s ∩ (t \ u) = (s ∩ t) \ (s ∩ u) :=
inf_sdiff_distrib_left _ _ _
```

-- snippet 20
```lean
-- Mathlib.Order.BooleanAlgebra.Set.notMem_compl_iff (L83-L85)
theorem notMem_compl_iff {x : α} : x ∉ sᶜ ↔ x ∈ s :=
not_not
```

-- snippet 21
```lean
-- Mathlib.Order.BooleanAlgebra.Set.compl_def (L71-L73)
theorem compl_def (s : Set α) : sᶜ = { x | x ∉ s } :=
rfl
```

-- snippet 22
```lean
-- Mathlib.Order.BooleanAlgebra.Set.compl_inter (L102-L104)
theorem compl_inter (s t : Set α) : (s ∩ t)ᶜ = sᶜ ∪ tᶜ :=
compl_inf
```

-- snippet 23
```lean
-- Mathlib.Order.BooleanAlgebra.Set.mem_compl (L74-L76)
theorem mem_compl {s : Set α} {x : α} (h : x ∉ s) : x ∈ sᶜ :=
h
```

-- snippet 24
```lean
-- Mathlib.Order.BooleanAlgebra.Set.inter_diff_assoc (L44-L46)
lemma inter_diff_assoc (a b c : Set α) : (a ∩ b) \ c = a ∩ (b \ c) := inf_sdiff_assoc ..
/-- See also `Set.inter_diff_assoc`. -/
```

-- snippet 25
```lean
-- Mathlib.Order.BooleanAlgebra.Set.compl_setOf (L77-L79)
theorem compl_setOf {α} (p : α → Prop) : { a | p a }ᶜ = { a | ¬p a } :=
rfl
```

-- snippet 26
```lean
-- Mathlib.Order.BooleanAlgebra.Set.inter_compl_self (L87-L89)
theorem inter_compl_self (s : Set α) : s ∩ sᶜ = ∅ :=
inf_compl_eq_bot
```

-- snippet 27
```lean
-- Mathlib.Order.BooleanAlgebra.Defs.PUnit (L148-L163)
instance PUnit.instBooleanAlgebra : BooleanAlgebra PUnit where
  __ := PUnit.instBiheytingAlgebra
le_sup_inf := by simp
  inf_compl_le_bot _ := trivial
  top_le_sup_compl _ := trivial

namespace DistribLattice

variable (α) [DistribLattice α]

/--
An alternative constructor for Boolean algebras:
a distributive lattice that is complemented is a Boolean algebra.

This is not an instance, because it creates data using choice.
-/
```

-- snippet 28
```lean
-- Mathlib.Order.BooleanAlgebra.Set.instBooleanAlgebra (L40-L43)
instance instBooleanAlgebra : BooleanAlgebra (Set α) :=
fast_instance% { (inferInstance : BooleanAlgebra (α → Prop)) with }

/-- See also `Set.sdiff_inter_right_comm`. -/
```

-- snippet 29
```lean
-- Mathlib.Order.BooleanAlgebra.Defs.Prop (L126-L133)
instance Prop.instBooleanAlgebra : BooleanAlgebra Prop where
  __ := Prop.instHeytingAlgebra
__ := GeneralizedHeytingAlgebra.toDistribLattice
  compl := Not
  himp_eq _ _ := propext imp_iff_or_not
  inf_compl_le_bot _ H := H.2 H.1
  top_le_sup_compl p _ := Classical.em p
```

-- snippet 30
```lean
-- Mathlib.Order.BooleanAlgebra.Set.inter_sdiff_left_comm (L49-L50)
lemma inter_sdiff_left_comm (s t u : Set α) : s ∩ (t \ u) = t ∩ (s \ u) := inf_sdiff_left_comm ..
```

-- snippet 31
```lean
-- Mathlib.Order.BooleanAlgebra.Set.diff_union_diff_cancel' (L55-L57)
theorem diff_union_diff_cancel' (hi : s ∩ u ⊆ t) (hu : t ⊆ s ∪ u) : (s \ t) ∪ (t \ u) = s \ u :=
sdiff_sup_sdiff_cancel' hi hu
```

-- snippet 32
```lean
-- Mathlib.Order.BooleanAlgebra.Defs.booleanAlgebraOfComplemented (L166-L172)
def booleanAlgebraOfComplemented [BoundedOrder α] [ComplementedLattice α] : BooleanAlgebra α where
  __ := ((inferInstance : BoundedOrder α))
compl a := Classical.choose <| exists_isCompl a
  inf_compl_le_bot a := (Classical.choose_spec (exists_isCompl a)).disjoint.le_bot
  top_le_sup_compl a := (Classical.choose_spec (exists_isCompl a)).codisjoint.top_le

end DistribLattice
```

-- snippet 33
```lean
-- Mathlib.Order.BooleanAlgebra.Set.compl_union (L99-L101)
theorem compl_union (s t : Set α) : (s ∪ t)ᶜ = sᶜ ∩ tᶜ :=
compl_sup
```

-- snippet 34
```lean
-- Mathlib.Order.BooleanAlgebra.Set.diff_union_diff_cancel (L51-L54)
theorem diff_union_diff_cancel (hts : t ⊆ s) (hut : u ⊆ t) : s \ t ∪ t \ u = s \ u :=
sdiff_sup_sdiff_cancel hts hut

/-- A version of `diff_union_diff_cancel` with more general hypotheses. -/
```

-- snippet 35
```lean
-- Mathlib.Order.BooleanAlgebra.Set.compl_inter_self (L91-L93)
theorem compl_inter_self (s : Set α) : sᶜ ∩ s = ∅ :=
compl_inf_eq_bot
```

-- snippet 36
```lean
-- Mathlib.Order.BooleanAlgebra.Set.diff_inter_distrib_right (L66-L70)
theorem diff_inter_distrib_right (s t r : Set α) : (t ∩ r) \ s = (t \ s) ∩ (r \ s) :=
inf_sdiff

/-! ### Lemmas about complement -/
```

-- snippet 37
```lean
-- Mathlib.Order.BooleanAlgebra.Set.notMem_of_mem_compl (L80-L82)
theorem notMem_of_mem_compl {s : Set α} {x : α} (h : x ∈ sᶜ) : x ∉ s :=
h
```

-- snippet 38
```lean
-- Mathlib.Order.BooleanAlgebra.Set.compl_empty (L95-L97)
theorem compl_empty : (∅ : Set α)ᶜ = univ :=
compl_bot
```

-- snippet 39
```lean
-- Mathlib.Order.BooleanAlgebra.Defs.Bool (L134-L139)
instance Bool.instBooleanAlgebra : BooleanAlgebra Bool where
  __ := instBoundedOrder
compl := not
  inf_compl_le_bot a := a.and_not_self.le
  top_le_sup_compl a := a.or_not_self.ge
```

-- snippet 40
```lean
-- Mathlib.Order.BooleanAlgebra.Set.inter_diff_distrib_right (L63-L65)
theorem inter_diff_distrib_right (s t u : Set α) : (s \ t) ∩ u = (s ∩ u) \ (t ∩ u) :=
inf_sdiff_distrib_right _ _ _
```
[/INST]