← Visual paper

HardnessBilevel/Framework/Berge.lean

d1032f4c70da9b037605c2f444ce2450900e5a76 · GitHub

  1. import HardnessBilevel.Framework.Basic
  2. import HardnessBilevel.Framework.Value
  3. import HardnessBilevel.Framework.Semicont
  4. /-!
  5. # Berge-type results: Theorem 2.8, Corollary 2.9 (blueprint §4.D, ids `berge.*`)
  6. Generic setting: topological spaces `X Y`, `P Q : X → Y → ℝ` jointly continuous
  7. (`Continuous (Function.uncurry P)`), `S : Set Y` compact.
  8. * `berge.isClosed_graph`: `isClosed_argminSet_graph` (needs only `hQ` and `S` closed);
  9. sequence/filter form `berge.outer_semicont`: `argminSet_outer_semicont`.
  10. * `berge.argmin_nonempty`: `argminSet_nonempty_of_isCompact`.
  11. * `berge.argmin_isCompact`: `argminSet_isCompact_of_continuous`.
  12. * `berge.exists_isMinOn`: `exists_isMinOn_argminSet`.
  13. * `berge.value_attained`: `valueFun_attained`, `valueFun_ne_top_of_isCompact`,
  14. `valueFun_ne_bot_of_isCompact` (the latter unconditional).
  15. * `berge.isClosed_sublevel`: `isClosed_valueFun_sublevel` (unconditional).
  16. * `berge.lsc`: `lowerSemicontinuous_valueFun` (unconditional, no `S.Nonempty`).
  17. * `berge.bdd_on_compact`: `valueFun_bddOn_compact`.
  18. * `berge.cor29`: `cor29`.
  19. * `berge.pess`: `upperSemicontinuous_pvalueFun` (unconditional), `pvalueFun_attained`,
  20. `pvalueFun_ne_top_of_isCompact`, `pvalueFun_ne_bot_of_isCompact`, `pvalueFun_bddOn_compact`,
  21. `cor29_pess`.
  22. Deviations (strengthenings only): no `[T2Space Y]` is needed anywhere (the sublevel-set argument
  23. works inside `X × ↥S`, where the argmin condition is closed without `S` being closed); the
  24. outer-semicontinuity statement is for an arbitrary non-trivial filter instead of `atTop` on `ℕ`;
  25. `isClosed_valueFun_sublevel`, `valueFun_ne_bot_of_isCompact` need no `S.Nonempty`.
  26. -/
  27. namespace Bilevel
  28. open Filter Topology Set
  29. variable {X : Type*} {Y : Type*} [TopologicalSpace X] [TopologicalSpace Y]
  30. {P Q : X → Y → ℝ} {S : Set Y}
  31. /-- A section of a jointly continuous function is continuous. -/
  32. theorem continuous_section_of_uncurry (hQ : Continuous (Function.uncurry Q)) (x : X) :
  33. Continuous (Q x) :=
  34. hQ.comp (Continuous.prodMk_right x)
  35. /-- `berge.isClosed_graph` (Thm 2.8 (i)): the graph of `Θ = argminSet Q S` is closed. -/
  36. theorem isClosed_argminSet_graph (hQ : Continuous (Function.uncurry Q)) (hS : IsClosed S) :
  37. IsClosed {p : X × Y | p.2 ∈ argminSet Q S p.1} := by
  38. have h : {p : X × Y | p.2 ∈ argminSet Q S p.1} =
  39. Prod.snd ⁻¹' S ∩ ⋂ y' ∈ S, {p : X × Y | Q p.1 p.2 ≤ Q p.1 y'} := by
  40. ext p
  41. simp [argminSet]
  42. rw [h]
  43. refine (hS.preimage continuous_snd).inter (isClosed_biInter fun y' _ => ?_)
  44. exact isClosed_le hQ (hQ.comp (continuous_fst.prodMk continuous_const))
  45. /-- `berge.outer_semicont` (Def 2.7, sequence/filter form). -/
  46. theorem argminSet_outer_semicont (hQ : Continuous (Function.uncurry Q)) (hS : IsClosed S)
  47. {ι : Type*} {l : Filter ι} [l.NeBot] {xk : ι → X} {yk : ι → Y} {x : X} {y : Y}
  48. (hx : Tendsto xk l (𝓝 x)) (hy : Tendsto yk l (𝓝 y))
  49. (hk : ∀ k, yk k ∈ argminSet Q S (xk k)) : y ∈ argminSet Q S x :=
  50. (isClosed_argminSet_graph hQ hS).mem_of_tendsto (hx.prodMk_nhds hy) (Eventually.of_forall hk)
  51. /-- `berge.argmin_nonempty`. -/
  52. theorem argminSet_nonempty_of_isCompact (hQ : Continuous (Function.uncurry Q))
  53. (hS : IsCompact S) (hne : S.Nonempty) (x : X) : (argminSet Q S x).Nonempty := by
  54. obtain ⟨y, hy, hmin⟩ := hS.exists_isMinOn hne (continuous_section_of_uncurry hQ x).continuousOn
  55. exact ⟨y, mem_argminSet_iff.2 ⟨hy, hmin⟩⟩
  56. /-- `berge.argmin_isCompact`. -/
  57. theorem argminSet_isCompact_of_continuous (hQ : Continuous (Function.uncurry Q))
  58. (hS : IsCompact S) (x : X) : IsCompact (argminSet Q S x) :=
  59. argminSet_isCompact (continuous_section_of_uncurry hQ x) hS
  60. /-- `berge.exists_isMinOn`. -/
  61. theorem exists_isMinOn_argminSet (hP : Continuous (Function.uncurry P))
  62. (hQ : Continuous (Function.uncurry Q)) (hS : IsCompact S) (hne : S.Nonempty) (x : X) :
  63. ∃ y₀ ∈ argminSet Q S x, IsMinOn (P x) (argminSet Q S x) y₀ :=
  64. (argminSet_isCompact_of_continuous hQ hS x).exists_isMinOn
  65. (argminSet_nonempty_of_isCompact hQ hS hne x) (continuous_section_of_uncurry hP x).continuousOn
  66. /-- `berge.value_attained`. -/
  67. theorem valueFun_attained (hP : Continuous (Function.uncurry P))
  68. (hQ : Continuous (Function.uncurry Q)) (hS : IsCompact S) (hne : S.Nonempty) (x : X) :
  69. ∃ y₀ ∈ argminSet Q S x, valueFun P Q S x = ((P x y₀ : ℝ) : EReal) := by
  70. obtain ⟨y₀, hy₀, hmin⟩ := exists_isMinOn_argminSet hP hQ hS hne x
  71. exact ⟨y₀, hy₀, valueFun_eq_of_isMinOn hy₀ hmin⟩
  72. /-- `berge.value_attained`, consequence: `valueFun ≠ ⊤`. -/
  73. theorem valueFun_ne_top_of_isCompact (hP : Continuous (Function.uncurry P))
  74. (hQ : Continuous (Function.uncurry Q)) (hS : IsCompact S) (hne : S.Nonempty) (x : X) :
  75. valueFun P Q S x ≠ ⊤ := by
  76. obtain ⟨y₀, -, h⟩ := valueFun_attained hP hQ hS hne x
  77. rw [h]
  78. exact EReal.coe_ne_top _
  79. /-- `berge.value_attained`, consequence: `valueFun ≠ ⊥` (no nonemptiness needed: for `S = ∅`
  80. the value is `⊤`). -/
  81. theorem valueFun_ne_bot_of_isCompact (hP : Continuous (Function.uncurry P))
  82. (hQ : Continuous (Function.uncurry Q)) (hS : IsCompact S) (x : X) :
  83. valueFun P Q S x ≠ ⊥ := by
  84. rcases S.eq_empty_or_nonempty with h | hne
  85. · have : valueFun P Q S x = ⊤ :=
  86. valueFun_eq_top_iff.2 (Set.subset_empty_iff.1 (h ▸ argminSet_subset))
  87. rw [this]
  88. exact top_ne_bot
  89. · obtain ⟨y₀, -, h⟩ := valueFun_attained hP hQ hS hne x
  90. rw [h]
  91. exact EReal.coe_ne_bot _
  92. /-- `berge.isClosed_sublevel`: real sublevel sets of the optimistic value function are closed
  93. (unconditionally; for `S = ∅` they are empty). -/
  94. theorem isClosed_valueFun_sublevel (hP : Continuous (Function.uncurry P))
  95. (hQ : Continuous (Function.uncurry Q)) (hS : IsCompact S) (r : ℝ) :
  96. IsClosed {x | valueFun P Q S x ≤ (r : EReal)} := by
  97. rcases S.eq_empty_or_nonempty with h | hne
  98. · have : {x | valueFun P Q S x ≤ (r : EReal)} = ∅ := by
  99. ext x
  100. have hx : valueFun P Q S x = ⊤ :=
  101. valueFun_eq_top_iff.2 (Set.subset_empty_iff.1 (h ▸ argminSet_subset))
  102. simp only [mem_ofPred_eq, hx, top_le_iff, mem_empty_iff_false, iff_false]
  103. exact EReal.coe_ne_top r
  104. rw [this]
  105. exact isClosed_empty
  106. have : CompactSpace S := isCompact_iff_compactSpace.mp hS
  107. let C : Set (X × S) :=
  108. (⋂ y' ∈ S, {p : X × S | Q p.1 p.2 ≤ Q p.1 y'}) ∩ {p : X × S | P p.1 p.2 ≤ r}
  109. have hC : IsClosed C := by
  110. have hv : Continuous fun p : X × S => (p.1, (p.2 : Y)) :=
  111. continuous_fst.prodMk (continuous_subtype_val.comp continuous_snd)
  112. refine (isClosed_biInter fun y' _ => ?_).inter ?_
  113. · exact isClosed_le (hQ.comp hv) (hQ.comp (continuous_fst.prodMk continuous_const))
  114. · exact isClosed_le (hP.comp hv) continuous_const
  115. have himg : Prod.fst '' C = {x | valueFun P Q S x ≤ (r : EReal)} := by
  116. ext x
  117. constructor
  118. · rintro ⟨⟨x', ⟨y, hyS⟩⟩, hpC, rfl⟩
  119. simp only [C, mem_inter_iff, mem_iInter, mem_ofPred_eq] at hpC
  120. have hy : y ∈ argminSet Q S x' := ⟨hyS, hpC.1⟩
  121. exact (valueFun_le_coe_of_mem hy).trans (EReal.coe_le_coe_iff.2 hpC.2)
  122. · intro hx
  123. obtain ⟨y₀, hy₀, heq⟩ := valueFun_attained hP hQ hS hne x
  124. have hle : P x y₀ ≤ r := by
  125. have hx' : valueFun P Q S x ≤ (r : EReal) := hx
  126. rw [heq] at hx'
  127. exact EReal.coe_le_coe_iff.1 hx'
  128. refine ⟨(x, ⟨y₀, hy₀.1⟩), ?_, rfl⟩
  129. simp only [C, mem_inter_iff, mem_iInter, mem_ofPred_eq]
  130. exact ⟨hy₀.2, hle⟩
  131. rw [← himg]
  132. exact isClosedMap_fst_of_compactSpace C hC
  133. /-- `berge.lsc` (Cor 2.9, lsc part): the optimistic value function is lower semicontinuous,
  134. unconditionally (no `S.Nonempty`). -/
  135. theorem lowerSemicontinuous_valueFun (hP : Continuous (Function.uncurry P))
  136. (hQ : Continuous (Function.uncurry Q)) (hS : IsCompact S) :
  137. LowerSemicontinuous (valueFun P Q S) := by
  138. rw [lowerSemicontinuous_iff_isClosed_preimage]
  139. intro a
  140. induction a using EReal.rec with
  141. | bot =>
  142. have : valueFun P Q S ⁻¹' Iic ⊥ = ∅ := by
  143. ext x
  144. simp only [mem_preimage, mem_Iic, le_bot_iff, mem_empty_iff_false, iff_false]
  145. exact valueFun_ne_bot_of_isCompact hP hQ hS x
  146. rw [this]
  147. exact isClosed_empty
  148. | coe r => exact isClosed_valueFun_sublevel hP hQ hS r
  149. | top =>
  150. rw [Iic_top, preimage_univ]
  151. exact isClosed_univ
  152. /-- Generic boundedness on compacts for a function attained by `P` at points of `S`. -/
  153. theorem bddOn_compact_of_attained (hP : Continuous (Function.uncurry P)) (hS : IsCompact S)
  154. {f : X → EReal} (hf : ∀ x, ∃ y₀ ∈ S, f x = ((P x y₀ : ℝ) : EReal))
  155. {K : Set X} (hK : IsCompact K) :
  156. ∃ M : ℝ, ∀ x ∈ K, (((-M : ℝ)) : EReal) ≤ f x ∧ f x ≤ (M : EReal) := by
  157. obtain ⟨m, hm⟩ := (hK.prod hS).bddBelow_image hP.continuousOn
  158. obtain ⟨M', hM'⟩ := (hK.prod hS).bddAbove_image hP.continuousOn
  159. refine ⟨max |m| |M'|, fun x hx => ?_⟩
  160. obtain ⟨y₀, hy₀, heq⟩ := hf x
  161. have h1 : m ≤ P x y₀ := hm (mem_image_of_mem _ (mk_mem_prod hx hy₀))
  162. have h2 : P x y₀ ≤ M' := hM' (mem_image_of_mem _ (mk_mem_prod hx hy₀))
  163. rw [heq, EReal.coe_le_coe_iff, EReal.coe_le_coe_iff]
  164. have := neg_abs_le m
  165. have := le_abs_self M'
  166. have := le_max_left |m| |M'|
  167. have := le_max_right |m| |M'|
  168. constructor <;> linarith
  169. /-- `berge.bdd_on_compact` (Cor 2.9, boundedness). -/
  170. theorem valueFun_bddOn_compact (hP : Continuous (Function.uncurry P))
  171. (hQ : Continuous (Function.uncurry Q)) (hS : IsCompact S) (hne : S.Nonempty)
  172. {K : Set X} (hK : IsCompact K) :
  173. ∃ M : ℝ, ∀ x ∈ K, (((-M : ℝ)) : EReal) ≤ valueFun P Q S x ∧ valueFun P Q S x ≤ (M : EReal) :=
  174. bddOn_compact_of_attained hP hS (fun x => by
  175. obtain ⟨y₀, hy₀, h⟩ := valueFun_attained hP hQ hS hne x
  176. exact ⟨y₀, hy₀.1, h⟩) hK
  177. /-- `berge.cor29` (Cor 2.9, clarified): for jointly continuous `P Q` and compact nonempty `S`,
  178. the optimistic value function is lsc, real-valued, and bounded on compacts. -/
  179. theorem cor29 (hP : Continuous (Function.uncurry P))
  180. (hQ : Continuous (Function.uncurry Q)) (hS : IsCompact S) (hne : S.Nonempty) :
  181. LowerSemicontinuous (valueFun P Q S) ∧
  182. (∀ x, valueFun P Q S x ≠ ⊤ ∧ valueFun P Q S x ≠ ⊥) ∧
  183. ∀ K : Set X, IsCompact K → ∃ M : ℝ, ∀ x ∈ K,
  184. (((-M : ℝ)) : EReal) ≤ valueFun P Q S x ∧ valueFun P Q S x ≤ (M : EReal) :=
  185. ⟨lowerSemicontinuous_valueFun hP hQ hS,
  186. fun x => ⟨valueFun_ne_top_of_isCompact hP hQ hS hne x, valueFun_ne_bot_of_isCompact hP hQ hS x⟩,
  187. fun _ hK => valueFun_bddOn_compact hP hQ hS hne hK⟩
  188. /-! ### Pessimistic version (`berge.pess`) -/
  189. theorem continuous_uncurry_neg (hP : Continuous (Function.uncurry P)) :
  190. Continuous (Function.uncurry fun x y => -P x y) :=
  191. hP.neg
  192. /-- `berge.pess`: the pessimistic value function is upper semicontinuous, unconditionally. -/
  193. theorem upperSemicontinuous_pvalueFun (hP : Continuous (Function.uncurry P))
  194. (hQ : Continuous (Function.uncurry Q)) (hS : IsCompact S) :
  195. UpperSemicontinuous (pvalueFun P Q S) := by
  196. rw [upperSemicontinuous_iff_lowerSemicontinuous_neg]
  197. have h : (fun x => -pvalueFun P Q S x) = valueFun (fun x y => -P x y) Q S := by
  198. funext x
  199. rw [pvalueFun_eq_neg_valueFun_neg, neg_neg]
  200. rw [h]
  201. exact lowerSemicontinuous_valueFun (continuous_uncurry_neg hP) hQ hS
  202. /-- `berge.pess`: the pessimistic value is attained. -/
  203. theorem pvalueFun_attained (hP : Continuous (Function.uncurry P))
  204. (hQ : Continuous (Function.uncurry Q)) (hS : IsCompact S) (hne : S.Nonempty) (x : X) :
  205. ∃ y₀ ∈ argminSet Q S x, pvalueFun P Q S x = ((P x y₀ : ℝ) : EReal) := by
  206. obtain ⟨y₀, hy₀, h⟩ := valueFun_attained (continuous_uncurry_neg hP) hQ hS hne x
  207. refine ⟨y₀, hy₀, ?_⟩
  208. rw [pvalueFun_eq_neg_valueFun_neg, h, EReal.coe_neg, neg_neg]
  209. /-- `berge.pess`: `pvalueFun ≠ ⊤` (unconditional: for `S = ∅` the value is `⊥`). -/
  210. theorem pvalueFun_ne_top_of_isCompact (hP : Continuous (Function.uncurry P))
  211. (hQ : Continuous (Function.uncurry Q)) (hS : IsCompact S) (x : X) :
  212. pvalueFun P Q S x ≠ ⊤ := by
  213. rw [pvalueFun_eq_neg_valueFun_neg]
  214. intro h
  215. exact valueFun_ne_bot_of_isCompact (continuous_uncurry_neg hP) hQ hS x
  216. (EReal.neg_eq_top_iff.1 h)
  217. /-- `berge.pess`: `pvalueFun ≠ ⊥` for compact nonempty `S`. -/
  218. theorem pvalueFun_ne_bot_of_isCompact (hP : Continuous (Function.uncurry P))
  219. (hQ : Continuous (Function.uncurry Q)) (hS : IsCompact S) (hne : S.Nonempty) (x : X) :
  220. pvalueFun P Q S x ≠ ⊥ := by
  221. obtain ⟨y₀, -, h⟩ := pvalueFun_attained hP hQ hS hne x
  222. rw [h]
  223. exact EReal.coe_ne_bot _
  224. /-- `berge.pess`: boundedness on compacts of the pessimistic value function. -/
  225. theorem pvalueFun_bddOn_compact (hP : Continuous (Function.uncurry P))
  226. (hQ : Continuous (Function.uncurry Q)) (hS : IsCompact S) (hne : S.Nonempty)
  227. {K : Set X} (hK : IsCompact K) :
  228. ∃ M : ℝ, ∀ x ∈ K, (((-M : ℝ)) : EReal) ≤ pvalueFun P Q S x ∧ pvalueFun P Q S x ≤ (M : EReal) :=
  229. bddOn_compact_of_attained hP hS (fun x => by
  230. obtain ⟨y₀, hy₀, h⟩ := pvalueFun_attained hP hQ hS hne x
  231. exact ⟨y₀, hy₀.1, h⟩) hK
  232. /-- `berge.pess` (pessimistic Cor 2.9′): usc, real-valued, bounded on compacts. -/
  233. theorem cor29_pess (hP : Continuous (Function.uncurry P))
  234. (hQ : Continuous (Function.uncurry Q)) (hS : IsCompact S) (hne : S.Nonempty) :
  235. UpperSemicontinuous (pvalueFun P Q S) ∧
  236. (∀ x, pvalueFun P Q S x ≠ ⊤ ∧ pvalueFun P Q S x ≠ ⊥) ∧
  237. ∀ K : Set X, IsCompact K → ∃ M : ℝ, ∀ x ∈ K,
  238. (((-M : ℝ)) : EReal) ≤ pvalueFun P Q S x ∧ pvalueFun P Q S x ≤ (M : EReal) :=
  239. ⟨upperSemicontinuous_pvalueFun hP hQ hS,
  240. fun x => ⟨pvalueFun_ne_top_of_isCompact hP hQ hS x,
  241. pvalueFun_ne_bot_of_isCompact hP hQ hS hne x⟩,
  242. fun _ hK => pvalueFun_bddOn_compact hP hQ hS hne hK⟩
  243. end Bilevel