l3lab/ntp-mathlib huggingface dataset:
/-- A version of the **Hahn-Banach theorem**: given disjoint convex sets `s`, `t` where `s` is
closed, and `t` is compact, there is a continuous linear functional which strongly separates them.
-/
theorem geometric_hahn_banach_closed_compact (hs₁ : Convex ℝ s) (hs₂ : IsClosed s)
    (ht₁ : Convex ℝ t) (ht₂ : IsCompact t) (disj : Disjoint s t) :
    ∃ (f : E →L[ℝ] ℝ) (u v : ℝ), (∀ a ∈ s, f a < u) ∧ u < v ∧ ∀ b ∈ t, v < f b :=
  let ⟨f, s, t, hs, st, ht⟩ := geometric_hahn_banach_compact_closed ht₁ ht₂ hs₁ hs₂ disj.symm
  ⟨-f, -t, -s, by simpa using ht, by simpa using st, by 

Proof state:
𝕜 : Type u_1
E : Type u_2
inst✝⁵ : TopologicalSpace E
inst✝⁴ : AddCommGroup E
inst✝³ : TopologicalAddGroup E
inst✝² : Module ℝ E
inst✝¹ : ContinuousSMul ℝ E
s✝ t✝ : Set E
x y : E
inst✝ : LocallyConvexSpace ℝ E
hs₁ : Convex ℝ s✝
hs₂ : IsClosed s✝
ht₁ : Convex ℝ t✝
ht₂ : IsCompact t✝
disj : Disjoint s✝ t✝
f : E →L[ℝ] ℝ
s t : ℝ
hs : ∀ a ∈ t✝, f a < s
st : s < t
ht : ∀ b ∈ s✝, t < f b
⊢ ∀ b ∈ t✝, -s < (-f) b

Next tactic:
simpa using hs
/-- See also `NormedSpace.eq_iff_forall_dual_eq`. -/
theorem geometric_hahn_banach_point_point [T1Space E] (hxy : x ≠ y) :
    ∃ f : E →L[ℝ] ℝ, f x < f y := by
  

Proof state:
𝕜 : Type u_1
E : Type u_2
inst✝⁶ : TopologicalSpace E
inst✝⁵ : AddCommGroup E
inst✝⁴ : TopologicalAddGroup E
inst✝³ : Module ℝ E
inst✝² : ContinuousSMul ℝ E
s t : Set E
x y : E
inst✝¹ : LocallyConvexSpace ℝ E
inst✝ : T1Space E
hxy : x ≠ y
⊢ ∃ f, f x < f y

Next tactic:
obtain ⟨f, s, t, hs, st, ht⟩ :=
    geometric_hahn_banach_compact_closed (convex_singleton x) isCompact_singleton
      (convex_singleton y) isClosed_singleton (disjoint_singleton.2 hxy)
/-- See also `NormedSpace.eq_iff_forall_dual_eq`. -/
theorem geometric_hahn_banach_point_point [T1Space E] (hxy : x ≠ y) :
    ∃ f : E →L[ℝ] ℝ, f x < f y := by
  obtain ⟨f, s, t, hs, st, ht⟩ :=
    geometric_hahn_banach_compact_closed (convex_singleton x) isCompact_singleton
      (convex_singleton y) isClosed_singleton (disjoint_singleton.2 hxy)
  

Proof state:
case intro.intro.intro.intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝⁶ : TopologicalSpace E
inst✝⁵ : AddCommGroup E
inst✝⁴ : TopologicalAddGroup E
inst✝³ : Module ℝ E
inst✝² : ContinuousSMul ℝ E
s✝ t✝ : Set E
x y : E
inst✝¹ : LocallyConvexSpace ℝ E
inst✝ : T1Space E
hxy : x ≠ y
f : E →L[ℝ] ℝ
s t : ℝ
hs : ∀ a ∈ {x}, f a < s
st : s < t
ht : ∀ b ∈ {y}, t < f b
⊢ ∃ f, f x < f y

Next tactic:
exact ⟨f, by linarith [hs x rfl, ht y rfl]⟩
/-- See also `NormedSpace.eq_iff_forall_dual_eq`. -/
theorem geometric_hahn_banach_point_point [T1Space E] (hxy : x ≠ y) :
    ∃ f : E →L[ℝ] ℝ, f x < f y := by
  obtain ⟨f, s, t, hs, st, ht⟩ :=
    geometric_hahn_banach_compact_closed (convex_singleton x) isCompact_singleton
      (convex_singleton y) isClosed_singleton (disjoint_singleton.2 hxy)
  exact ⟨f, by 

Proof state:
𝕜 : Type u_1
E : Type u_2
inst✝⁶ : TopologicalSpace E
inst✝⁵ : AddCommGroup E
inst✝⁴ : TopologicalAddGroup E
inst✝³ : Module ℝ E
inst✝² : ContinuousSMul ℝ E
s✝ t✝ : Set E
x y : E
inst✝¹ : LocallyConvexSpace ℝ E
inst✝ : T1Space E
hxy : x ≠ y
f : E →L[ℝ] ℝ
s t : ℝ
hs : ∀ a ∈ {x}, f a < s
st : s < t
ht : ∀ b ∈ {y}, t < f b
⊢ f x < f y

Next tactic:
linarith [hs x rfl, ht y rfl]
/-- A closed convex set is the intersection of the halfspaces containing it. -/
theorem iInter_halfspaces_eq (hs₁ : Convex ℝ s) (hs₂ : IsClosed s) :
    ⋂ l : E →L[ℝ] ℝ, { x | ∃ y ∈ s, l x ≤ l y } = s := by
  

Proof state:
𝕜 : Type u_1
E : Type u_2
inst✝⁵ : TopologicalSpace E
inst✝⁴ : AddCommGroup E
inst✝³ : TopologicalAddGroup E
inst✝² : Module ℝ E
inst✝¹ : ContinuousSMul ℝ E
s t : Set E
x y : E
inst✝ : LocallyConvexSpace ℝ E
hs₁ : Convex ℝ s
hs₂ : IsClosed s
⊢ ⋂ l, {x | ∃ y ∈ s, l x ≤ l y} = s

Next tactic:
rw [Set.iInter_setOf]
/-- A closed convex set is the intersection of the halfspaces containing it. -/
theorem iInter_halfspaces_eq (hs₁ : Convex ℝ s) (hs₂ : IsClosed s) :
    ⋂ l : E →L[ℝ] ℝ, { x | ∃ y ∈ s, l x ≤ l y } = s := by
  rw [Set.iInter_setOf]
  

Proof state:
𝕜 : Type u_1
E : Type u_2
inst✝⁵ : TopologicalSpace E
inst✝⁴ : AddCommGroup E
inst✝³ : TopologicalAddGroup E
inst✝² : Module ℝ E
inst✝¹ : ContinuousSMul ℝ E
s t : Set E
x y : E
inst✝ : LocallyConvexSpace ℝ E
hs₁ : Convex ℝ s
hs₂ : IsClosed s
⊢ {x | ∀ (i : E →L[ℝ] ℝ), ∃ y ∈ s, i x ≤ i y} = s

Next tactic:
refine' Set.Subset.antisymm (fun x hx => _) fun x hx l => ⟨x, hx, le_rfl⟩
/-- A closed convex set is the intersection of the halfspaces containing it. -/
theorem iInter_halfspaces_eq (hs₁ : Convex ℝ s) (hs₂ : IsClosed s) :
    ⋂ l : E →L[ℝ] ℝ, { x | ∃ y ∈ s, l x ≤ l y } = s := by
  rw [Set.iInter_setOf]
  refine' Set.Subset.antisymm (fun x hx => _) fun x hx l => ⟨x, hx, le_rfl⟩
  

Proof state:
𝕜 : Type u_1
E : Type u_2
inst✝⁵ : TopologicalSpace E
inst✝⁴ : AddCommGroup E
inst✝³ : TopologicalAddGroup E
inst✝² : Module ℝ E
inst✝¹ : ContinuousSMul ℝ E
s t : Set E
x✝ y : E
inst✝ : LocallyConvexSpace ℝ E
hs₁ : Convex ℝ s
hs₂ : IsClosed s
x : E
hx : x ∈ {x | ∀ (i : E →L[ℝ] ℝ), ∃ y ∈ s, i x ≤ i y}
⊢ x ∈ s

Next tactic:
by_contra h
/-- A closed convex set is the intersection of the halfspaces containing it. -/
theorem iInter_halfspaces_eq (hs₁ : Convex ℝ s) (hs₂ : IsClosed s) :
    ⋂ l : E →L[ℝ] ℝ, { x | ∃ y ∈ s, l x ≤ l y } = s := by
  rw [Set.iInter_setOf]
  refine' Set.Subset.antisymm (fun x hx => _) fun x hx l => ⟨x, hx, le_rfl⟩
  by_contra h
  

Proof state:
𝕜 : Type u_1
E : Type u_2
inst✝⁵ : TopologicalSpace E
inst✝⁴ : AddCommGroup E
inst✝³ : TopologicalAddGroup E
inst✝² : Module ℝ E
inst✝¹ : ContinuousSMul ℝ E
s t : Set E
x✝ y : E
inst✝ : LocallyConvexSpace ℝ E
hs₁ : Convex ℝ s
hs₂ : IsClosed s
x : E
hx : x ∈ {x | ∀ (i : E →L[ℝ] ℝ), ∃ y ∈ s, i x ≤ i y}
h : x ∉ s
⊢ False

Next tactic:
obtain ⟨l, s, hlA, hl⟩ := geometric_hahn_banach_closed_point hs₁ hs₂ h
/-- A closed convex set is the intersection of the halfspaces containing it. -/
theorem iInter_halfspaces_eq (hs₁ : Convex ℝ s) (hs₂ : IsClosed s) :
    ⋂ l : E →L[ℝ] ℝ, { x | ∃ y ∈ s, l x ≤ l y } = s := by
  rw [Set.iInter_setOf]
  refine' Set.Subset.antisymm (fun x hx => _) fun x hx l => ⟨x, hx, le_rfl⟩
  by_contra h
  obtain ⟨l, s, hlA, hl⟩ := geometric_hahn_banach_closed_point hs₁ hs₂ h
  

Proof state:
case intro.intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝⁵ : TopologicalSpace E
inst✝⁴ : AddCommGroup E
inst✝³ : TopologicalAddGroup E
inst✝² : Module ℝ E
inst✝¹ : ContinuousSMul ℝ E
s✝ t : Set E
x✝ y : E
inst✝ : LocallyConvexSpace ℝ E
hs₁ : Convex ℝ s✝
hs₂ : IsClosed s✝
x : E
hx : x ∈ {x | ∀ (i : E →L[ℝ] ℝ), ∃ y ∈ s✝, i x ≤ i y}
h : x ∉ s✝
l : E →L[ℝ] ℝ
s : ℝ
hlA : ∀ a ∈ s✝, l a < s
hl : s < l x
⊢ False

Next tactic:
obtain ⟨y, hy, hxy⟩ := hx l
/-- A closed convex set is the intersection of the halfspaces containing it. -/
theorem iInter_halfspaces_eq (hs₁ : Convex ℝ s) (hs₂ : IsClosed s) :
    ⋂ l : E →L[ℝ] ℝ, { x | ∃ y ∈ s, l x ≤ l y } = s := by
  rw [Set.iInter_setOf]
  refine' Set.Subset.antisymm (fun x hx => _) fun x hx l => ⟨x, hx, le_rfl⟩
  by_contra h
  obtain ⟨l, s, hlA, hl⟩ := geometric_hahn_banach_closed_point hs₁ hs₂ h
  obtain ⟨y, hy, hxy⟩ := hx l
  

Proof state:
case intro.intro.intro.intro.intro
𝕜 : Type u_1
E : Type u_2
inst✝⁵ : TopologicalSpace E
inst✝⁴ : AddCommGroup E
inst✝³ : TopologicalAddGroup E
inst✝² : Module ℝ E
inst✝¹ : ContinuousSMul ℝ E
s✝ t : Set E
x✝ y✝ : E
inst✝ : LocallyConvexSpace ℝ E
hs₁ : Convex ℝ s✝
hs₂ : IsClosed s✝
x : E
hx : x ∈ {x | ∀ (i : E →L[ℝ] ℝ), ∃ y ∈ s✝, i x ≤ i y}
h : x ∉ s✝
l : E →L[ℝ] ℝ
s : ℝ
hlA : ∀ a ∈ s✝, l a < s
hl : s < l x
y : E
hy : y ∈ s✝
hxy : l x ≤ l y
⊢ False

Next tactic:
exact ((hxy.trans_lt (hlA y hy)).trans hl).not_le le_rfl
@[simp]
theorem destutter'_cons_pos (h : R b a) : (a :: l).destutter' R b = b :: l.destutter' R a := by
  

Proof state:
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a b : α
h : R b a
⊢ destutter' R b (a :: l) = b :: destutter' R a l

Next tactic:
rw [destutter', if_pos h]
@[simp]
theorem destutter'_cons_neg (h : ¬R b a) : (a :: l).destutter' R b = l.destutter' R b := by
  

Proof state:
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a b : α
h : ¬R b a
⊢ destutter' R b (a :: l) = destutter' R b l

Next tactic:
rw [destutter', if_neg h]
@[simp]
theorem destutter'_singleton : [b].destutter' R a = if R a b then [a, b] else [a] := by
  

Proof state:
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a b : α
⊢ destutter' R a [b] = if R a b then [a, b] else [a]

Next tactic:
split_ifs with h
@[simp]
theorem destutter'_singleton : [b].destutter' R a = if R a b then [a, b] else [a] := by
  split_ifs with h <;> 

Proof state:
case pos
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a b : α
h : R a b
⊢ destutter' R a [b] = [a, b]

Next tactic:
simp! [h]
@[simp]
theorem destutter'_singleton : [b].destutter' R a = if R a b then [a, b] else [a] := by
  split_ifs with h <;> 

Proof state:
case neg
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a b : α
h : ¬R a b
⊢ destutter' R a [b] = [a]

Next tactic:
simp! [h]
theorem destutter'_sublist (a) : l.destutter' R a <+ a :: l := by
  

Proof state:
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b a : α
⊢ destutter' R a l <+ a :: l

Next tactic:
induction' l with b l hl generalizing a
theorem destutter'_sublist (a) : l.destutter' R a <+ a :: l := by
  induction' l with b l hl generalizing a
  · 

Proof state:
case nil
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b a : α
⊢ destutter' R a [] <+ [a]

Next tactic:
simp
theorem destutter'_sublist (a) : l.destutter' R a <+ a :: l := by
  induction' l with b l hl generalizing a
  · simp
  

Proof state:
case cons
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ b : α
l : List α
hl : ∀ (a : α), destutter' R a l <+ a :: l
a : α
⊢ destutter' R a (b :: l) <+ a :: b :: l

Next tactic:
rw [destutter']
theorem destutter'_sublist (a) : l.destutter' R a <+ a :: l := by
  induction' l with b l hl generalizing a
  · simp
  rw [destutter']
  

Proof state:
case cons
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ b : α
l : List α
hl : ∀ (a : α), destutter' R a l <+ a :: l
a : α
⊢ (if R a b then a :: destutter' R b l else destutter' R a l) <+ a :: b :: l

Next tactic:
split_ifs
theorem destutter'_sublist (a) : l.destutter' R a <+ a :: l := by
  induction' l with b l hl generalizing a
  · simp
  rw [destutter']
  split_ifs
  · 

Proof state:
case pos
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ b : α
l : List α
hl : ∀ (a : α), destutter' R a l <+ a :: l
a : α
h✝ : R a b
⊢ a :: destutter' R b l <+ a :: b :: l

Next tactic:
exact Sublist.cons₂ a (hl b)
theorem destutter'_sublist (a) : l.destutter' R a <+ a :: l := by
  induction' l with b l hl generalizing a
  · simp
  rw [destutter']
  split_ifs
  · exact Sublist.cons₂ a (hl b)
  · 

Proof state:
case neg
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ b : α
l : List α
hl : ∀ (a : α), destutter' R a l <+ a :: l
a : α
h✝ : ¬R a b
⊢ destutter' R a l <+ a :: b :: l

Next tactic:
exact (hl a).trans ((l.sublist_cons b).cons_cons a)
theorem mem_destutter' (a) : a ∈ l.destutter' R a := by
  

Proof state:
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b a : α
⊢ a ∈ destutter' R a l

Next tactic:
induction' l with b l hl
theorem mem_destutter' (a) : a ∈ l.destutter' R a := by
  induction' l with b l hl
  · 

Proof state:
case nil
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b a : α
⊢ a ∈ destutter' R a []

Next tactic:
simp
theorem mem_destutter' (a) : a ∈ l.destutter' R a := by
  induction' l with b l hl
  · simp
  

Proof state:
case cons
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ a b : α
l : List α
hl : a ∈ destutter' R a l
⊢ a ∈ destutter' R a (b :: l)

Next tactic:
rw [destutter']
theorem mem_destutter' (a) : a ∈ l.destutter' R a := by
  induction' l with b l hl
  · simp
  rw [destutter']
  

Proof state:
case cons
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ a b : α
l : List α
hl : a ∈ destutter' R a l
⊢ a ∈ if R a b then a :: destutter' R b l else destutter' R a l

Next tactic:
split_ifs
theorem mem_destutter' (a) : a ∈ l.destutter' R a := by
  induction' l with b l hl
  · simp
  rw [destutter']
  split_ifs
  · 

Proof state:
case pos
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ a b : α
l : List α
hl : a ∈ destutter' R a l
h✝ : R a b
⊢ a ∈ a :: destutter' R b l

Next tactic:
simp
theorem mem_destutter' (a) : a ∈ l.destutter' R a := by
  induction' l with b l hl
  · simp
  rw [destutter']
  split_ifs
  · simp
  · 

Proof state:
case neg
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ a b : α
l : List α
hl : a ∈ destutter' R a l
h✝ : ¬R a b
⊢ a ∈ destutter' R a l

Next tactic:
assumption
theorem destutter'_is_chain : ∀ l : List α, ∀ {a b}, R a b → (l.destutter' R b).Chain R a
  | [], a, b, h => chain_singleton.mpr h
  | c :: l, a, b, h => by
    

Proof state:
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ c : α
l : List α
a b : α
h : R a b
⊢ Chain R a (destutter' R b (c :: l))

Next tactic:
rw [destutter']
theorem destutter'_is_chain : ∀ l : List α, ∀ {a b}, R a b → (l.destutter' R b).Chain R a
  | [], a, b, h => chain_singleton.mpr h
  | c :: l, a, b, h => by
    rw [destutter']
    

Proof state:
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ c : α
l : List α
a b : α
h : R a b
⊢ Chain R a (if R b c then b :: destutter' R c l else destutter' R b l)

Next tactic:
split_ifs with hbc
theorem destutter'_is_chain : ∀ l : List α, ∀ {a b}, R a b → (l.destutter' R b).Chain R a
  | [], a, b, h => chain_singleton.mpr h
  | c :: l, a, b, h => by
    rw [destutter']
    split_ifs with hbc
    · 

Proof state:
case pos
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ c : α
l : List α
a b : α
h : R a b
hbc : R b c
⊢ Chain R a (b :: destutter' R c l)

Next tactic:
rw [chain_cons]
theorem destutter'_is_chain : ∀ l : List α, ∀ {a b}, R a b → (l.destutter' R b).Chain R a
  | [], a, b, h => chain_singleton.mpr h
  | c :: l, a, b, h => by
    rw [destutter']
    split_ifs with hbc
    · rw [chain_cons]
      

Proof state:
case pos
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ c : α
l : List α
a b : α
h : R a b
hbc : R b c
⊢ R a b ∧ Chain R b (destutter' R c l)

Next tactic:
exact ⟨h, destutter'_is_chain l hbc⟩
theorem destutter'_is_chain : ∀ l : List α, ∀ {a b}, R a b → (l.destutter' R b).Chain R a
  | [], a, b, h => chain_singleton.mpr h
  | c :: l, a, b, h => by
    rw [destutter']
    split_ifs with hbc
    · rw [chain_cons]
      exact ⟨h, destutter'_is_chain l hbc⟩
    · 

Proof state:
case neg
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ c : α
l : List α
a b : α
h : R a b
hbc : ¬R b c
⊢ Chain R a (destutter' R b l)

Next tactic:
exact destutter'_is_chain l h
theorem destutter'_is_chain' (a) : (l.destutter' R a).Chain' R := by
  

Proof state:
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b a : α
⊢ Chain' R (destutter' R a l)

Next tactic:
induction' l with b l hl generalizing a
theorem destutter'_is_chain' (a) : (l.destutter' R a).Chain' R := by
  induction' l with b l hl generalizing a
  · 

Proof state:
case nil
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b a : α
⊢ Chain' R (destutter' R a [])

Next tactic:
simp
theorem destutter'_is_chain' (a) : (l.destutter' R a).Chain' R := by
  induction' l with b l hl generalizing a
  · simp
  

Proof state:
case cons
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ b : α
l : List α
hl : ∀ (a : α), Chain' R (destutter' R a l)
a : α
⊢ Chain' R (destutter' R a (b :: l))

Next tactic:
rw [destutter']
theorem destutter'_is_chain' (a) : (l.destutter' R a).Chain' R := by
  induction' l with b l hl generalizing a
  · simp
  rw [destutter']
  

Proof state:
case cons
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ b : α
l : List α
hl : ∀ (a : α), Chain' R (destutter' R a l)
a : α
⊢ Chain' R (if R a b then a :: destutter' R b l else destutter' R a l)

Next tactic:
split_ifs with h
theorem destutter'_is_chain' (a) : (l.destutter' R a).Chain' R := by
  induction' l with b l hl generalizing a
  · simp
  rw [destutter']
  split_ifs with h
  · 

Proof state:
case pos
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ b : α
l : List α
hl : ∀ (a : α), Chain' R (destutter' R a l)
a : α
h : R a b
⊢ Chain' R (a :: destutter' R b l)

Next tactic:
exact destutter'_is_chain R l h
theorem destutter'_is_chain' (a) : (l.destutter' R a).Chain' R := by
  induction' l with b l hl generalizing a
  · simp
  rw [destutter']
  split_ifs with h
  · exact destutter'_is_chain R l h
  · 

Proof state:
case neg
α : Type u_1
l✝ : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b✝ b : α
l : List α
hl : ∀ (a : α), Chain' R (destutter' R a l)
a : α
h : ¬R a b
⊢ Chain' R (destutter' R a l)

Next tactic:
exact hl a
theorem destutter'_of_chain (h : l.Chain R a) : l.destutter' R a = a :: l := by
  

Proof state:
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a b : α
h : Chain R a l
⊢ destutter' R a l = a :: l

Next tactic:
induction' l with b l hb generalizing a
theorem destutter'_of_chain (h : l.Chain R a) : l.destutter' R a = a :: l := by
  induction' l with b l hb generalizing a
  · 

Proof state:
case nil
α : Type u_1
R : α → α → Prop
inst✝ : DecidableRel R
b a : α
h : Chain R a []
⊢ destutter' R a [] = [a]

Next tactic:
simp
theorem destutter'_of_chain (h : l.Chain R a) : l.destutter' R a = a :: l := by
  induction' l with b l hb generalizing a
  · simp
  

Proof state:
case cons
α : Type u_1
R : α → α → Prop
inst✝ : DecidableRel R
b✝ b : α
l : List α
hb : ∀ {a : α}, Chain R a l → destutter' R a l = a :: l
a : α
h : Chain R a (b :: l)
⊢ destutter' R a (b :: l) = a :: b :: l

Next tactic:
obtain ⟨h, hc⟩ := chain_cons.mp h
theorem destutter'_of_chain (h : l.Chain R a) : l.destutter' R a = a :: l := by
  induction' l with b l hb generalizing a
  · simp
  obtain ⟨h, hc⟩ := chain_cons.mp h
  

Proof state:
case cons.intro
α : Type u_1
R : α → α → Prop
inst✝ : DecidableRel R
b✝ b : α
l : List α
hb : ∀ {a : α}, Chain R a l → destutter' R a l = a :: l
a : α
h✝ : Chain R a (b :: l)
h : R a b
hc : Chain R b l
⊢ destutter' R a (b :: l) = a :: b :: l

Next tactic:
rw [l.destutter'_cons_pos h, hb hc]
@[simp]
theorem destutter'_eq_self_iff (a) : l.destutter' R a = a :: l ↔ l.Chain R a :=
  ⟨fun h => by
    

Proof state:
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b a : α
h : destutter' R a l = a :: l
⊢ Chain R a l

Next tactic:
suffices Chain' R (a::l) by
      assumption
@[simp]
theorem destutter'_eq_self_iff (a) : l.destutter' R a = a :: l ↔ l.Chain R a :=
  ⟨fun h => by
    suffices Chain' R (a::l) by
      

Proof state:
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b a : α
h : destutter' R a l = a :: l
this : Chain' R (a :: l)
⊢ Chain R a l

Next tactic:
assumption
@[simp]
theorem destutter'_eq_self_iff (a) : l.destutter' R a = a :: l ↔ l.Chain R a :=
  ⟨fun h => by
    suffices Chain' R (a::l) by
      assumption
    

Proof state:
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b a : α
h : destutter' R a l = a :: l
⊢ Chain' R (a :: l)

Next tactic:
rw [← h]
@[simp]
theorem destutter'_eq_self_iff (a) : l.destutter' R a = a :: l ↔ l.Chain R a :=
  ⟨fun h => by
    suffices Chain' R (a::l) by
      assumption
    rw [← h]
    

Proof state:
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a✝ b a : α
h : destutter' R a l = a :: l
⊢ Chain' R (destutter' R a l)

Next tactic:
exact l.destutter'_is_chain' R a
@[simp]
theorem destutter_eq_self_iff : ∀ l : List α, l.destutter R = l ↔ l.Chain' R
  | [] => by 

Proof state:
α : Type u_1
l : List α
R : α → α → Prop
inst✝ : DecidableRel R
a b : α
⊢ destutter R [] = [] ↔ Chain' R []

Next tactic:
simp
instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X)
    where
  factors {Y Z} f g hg := by
    

Proof state:
X : Type u_1
Y Z : CompHaus
f : of (Ultrafilter X) ⟶ Z
g : Y ⟶ Z
hg : Epi g
⊢ ∃ f', f' ≫ g = f

Next tactic:
rw [epi_iff_surjective] at hg
instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X)
    where
  factors {Y Z} f g hg := by
    rw [epi_iff_surjective] at hg
    

Proof state:
X : Type u_1
Y Z : CompHaus
f : of (Ultrafilter X) ⟶ Z
g : Y ⟶ Z
hg : Surjective ⇑g
⊢ ∃ f', f' ≫ g = f

Next tactic:
obtain ⟨g', hg'⟩ := hg.hasRightInverse
instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X)
    where
  factors {Y Z} f g hg := by
    rw [epi_iff_surjective] at hg
    obtain ⟨g', hg'⟩ := hg.hasRightInverse
    

Proof state:
case intro
X : Type u_1
Y Z : CompHaus
f : of (Ultrafilter X) ⟶ Z
g : Y ⟶ Z
hg : Surjective ⇑g
g' : (forget CompHaus).obj Z → (forget CompHaus).obj Y
hg' : Function.RightInverse g' ⇑g
⊢ ∃ f', f' ≫ g = f

Next tactic:
let t : X → Y := g' ∘ f ∘ (pure : X → Ultrafilter X)
instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X)
    where
  factors {Y Z} f g hg := by
    rw [epi_iff_surjective] at hg
    obtain ⟨g', hg'⟩ := hg.hasRightInverse
    let t : X → Y := g' ∘ f ∘ (pure : X → Ultrafilter X)
    

Proof state:
case intro
X : Type u_1
Y Z : CompHaus
f : of (Ultrafilter X) ⟶ Z
g : Y ⟶ Z
hg : Surjective ⇑g
g' : (forget CompHaus).obj Z → (forget CompHaus).obj Y
hg' : Function.RightInverse g' ⇑g
t : X → ↑Y.toTop := g' ∘ ⇑f ∘ pure
⊢ ∃ f', f' ≫ g = f

Next tactic:
let h : Ultrafilter X → Y := Ultrafilter.extend t
instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X)
    where
  factors {Y Z} f g hg := by
    rw [epi_iff_surjective] at hg
    obtain ⟨g', hg'⟩ := hg.hasRightInverse
    let t : X → Y := g' ∘ f ∘ (pure : X → Ultrafilter X)
    let h : Ultrafilter X → Y := Ultrafilter.extend t
    

Proof state:
case intro
X : Type u_1
Y Z : CompHaus
f : of (Ultrafilter X) ⟶ Z
g : Y ⟶ Z
hg : Surjective ⇑g
g' : (forget CompHaus).obj Z → (forget CompHaus).obj Y
hg' : Function.RightInverse g' ⇑g
t : X → ↑Y.toTop := g' ∘ ⇑f ∘ pure
h : Ultrafilter X → ↑Y.toTop := Ultrafilter.extend t
⊢ ∃ f', f' ≫ g = f

Next tactic:
have hh : Continuous h := continuous_ultrafilter_extend _
instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X)
    where
  factors {Y Z} f g hg := by
    rw [epi_iff_surjective] at hg
    obtain ⟨g', hg'⟩ := hg.hasRightInverse
    let t : X → Y := g' ∘ f ∘ (pure : X → Ultrafilter X)
    let h : Ultrafilter X → Y := Ultrafilter.extend t
    have hh : Continuous h := continuous_ultrafilter_extend _
    

Proof state:
case intro
X : Type u_1
Y Z : CompHaus
f : of (Ultrafilter X) ⟶ Z
g : Y ⟶ Z
hg : Surjective ⇑g
g' : (forget CompHaus).obj Z → (forget CompHaus).obj Y
hg' : Function.RightInverse g' ⇑g
t : X → ↑Y.toTop := g' ∘ ⇑f ∘ pure
h : Ultrafilter X → ↑Y.toTop := Ultrafilter.extend t
hh : Continuous h
⊢ ∃ f', f' ≫ g = f

Next tactic:
use ⟨h, hh⟩
instance projective_ultrafilter (X : Type*) : Projective (of <| Ultrafilter X)
    where
  factors {Y Z} f g hg := by
    rw [epi_iff_surjective] at hg
    obtain ⟨g', hg'⟩ := hg.hasRightInverse
    let t : X → Y := g' ∘ f ∘ (pure : X → Ultrafilter X)
    let h : Ultrafilter X → Y := Ultrafilter.extend t
    have hh : Continuous h := continuous_ultrafilter_extend _
    use ⟨h, hh⟩
    

Proof state:
case h
X : Type u_1
Y Z : CompHaus
f : of (Ultrafilter X) ⟶ Z
g : Y ⟶ Z
hg : Surjective ⇑g
g' : (forget CompHaus).obj Z → (forget CompHaus).obj Y
hg' : Function.RightInverse g' ⇑g
t : X → ↑Y.toTop := g' ∘ ⇑f ∘ pure
h : Ultrafilter X → ↑Y.toTop := Ultrafilter.extend t
hh : Continuous h
⊢ ContinuousMap.mk h ≫ g = f

Next tactic:
apply Faithful.map_injective (F := forget CompHaus)