import Optlib.Optimality.Constrained_Problem import Optlib.Convex.ConvexFunction section Duality open Constrained_OptimizationProblem InnerProductSpace Set BigOperators noncomputable section Definition namespace Constrained_OptimizationProblem variable {E : Type _} {τ σ : Finset ℕ} variable {p : Constrained_OptimizationProblem E τ σ} def dual_objective : (τ → ℝ) → (σ → ℝ) → EReal := fun (lambda1 : τ → ℝ) (lambda2 : σ → ℝ) ↦ ⨅ x ∈ p.domain, (p.Lagrange_function x lambda1 lambda2).toEReal def dual_problem : Constrained_OptimizationProblem ((τ → ℝ) × (σ → ℝ)) ∅ σ where domain := {x | p.dual_objective x.1 x.2 ≠ ⊥} equality_constraints := fun _ _ ↦ 0 inequality_constraints := fun i x ↦ if h : i ∈ σ then x.2 ⟨i, h⟩ else 0 objective := fun x ↦ (p.dual_objective x.1 x.2).toReal eq_ine_not_intersect := by simp def inf_value : EReal := sInf (Real.toEReal '' (p.objective '' (p.FeasSet))) def sup_value : EReal := sSup (Real.toEReal '' (p.objective '' (p.FeasSet))) variable [NormedAddCommGroup E] [InnerProductSpace ℝ E] [CompleteSpace E] def KKT_point (self : Constrained_OptimizationProblem E τ σ) (x : E) (lambda : τ → ℝ) (mu : σ → ℝ) : Prop := (gradient (fun m ↦ (self.Lagrange_function m lambda mu)) x = 0) ∧ (x ∈ self.FeasSet) ∧ (mu ≥ 0) ∧ (∀ i : σ, mu i * self.inequality_constraints i x = 0) end Constrained_OptimizationProblem end Definition section WeakDuality variable {E : Type _} {τ σ : Finset ℕ} variable {p : Constrained_OptimizationProblem E τ σ} {x : E} lemma empty_domain_inf_value_top {p : Constrained_OptimizationProblem E τ σ} (hp : (p.domain) = ∅) : p.inf_value = ⊤ := by unfold inf_value unfold FeasSet FeasPoint simp [hp] lemma empty_FeasSet_inf_value_top {p : Constrained_OptimizationProblem E τ σ} (hp : (p.FeasSet) = ∅) : p.inf_value = ⊤ := by unfold inf_value; simp [hp] lemma objective_le_sup {p : Constrained_OptimizationProblem E τ σ} (x : E) (hx : x ∈ p.FeasSet) : (p.objective x).toEReal ≤ p.sup_value := by unfold sup_value apply le_sSup simp; use x lemma dual_objective_le_top_nonempty {p : Constrained_OptimizationProblem E τ σ} (hp : (p.domain).Nonempty) : ∀ lambda1 lambda2, p.dual_objective lambda1 lambda2 < ⊤ := by intro lambda1 lambda2 unfold dual_objective let x := Classical.choose hp apply iInf_lt_top.mpr use x; simp; apply Classical.choose_spec hp lemma dual_objective_eq_top_empty {p : Constrained_OptimizationProblem E τ σ} (hp : (p.domain) = ∅) : ∀ lambda1 lambda2, p.dual_objective lambda1 lambda2 = ⊤ := by intro lambda1 lambda2; unfold dual_objective simp; intro x by_contra h have : x ∉ p.domain := by exact of_eq_false (congrFun hp x) exact this h lemma objective_infimum_global_minimum {p : Constrained_OptimizationProblem E τ σ} (hp : (p.objective x).toEReal = p.inf_value) (hx : x ∈ p.FeasSet) : p.Global_Minimum x := by unfold Global_Minimum constructor · exact hx intro x1 hx; simp unfold inf_value at hp have : (p.objective x).toEReal ≤ (p.objective x1).toEReal := by rw [hp] apply sInf_le simp; use x1 simpa lemma global_minimum_objective_infimum {p : Constrained_OptimizationProblem E τ σ} (hp : p.Global_Minimum x) : (p.objective x).toEReal = p.inf_value := by unfold Global_Minimum at hp unfold inf_value apply Eq.symm (sInf_eq_of_forall_ge_of_forall_gt_exists_lt _ _) · intro a ha simp at ha rcases ha with ⟨x1, hx1, hx2⟩ rw [← hx2] simp; apply hp.2 hx1 intro w hw use (p.objective x).toEReal simp; constructor · use x; simp unfold FeasSet; simp; exact hp.1 exact hw lemma objective_maximum_global_maximum {p : Constrained_OptimizationProblem E τ σ} (hp : (p.objective x).toEReal = p.sup_value) (hx : x ∈ p.FeasSet) : p.Global_Maximum x := by unfold Global_Maximum constructor · exact hx intro x1 hx; simp unfold sup_value at hp have : (p.objective x).toEReal ≥ (p.objective x1).toEReal := by rw [hp] apply le_sSup simp; use x1 simpa theorem weak_duality {p : Constrained_OptimizationProblem E τ σ} (lambda1 : τ → ℝ) {lambda2 : σ → ℝ} (mpos : lambda2 ≥ 0): p.dual_objective lambda1 lambda2 ≤ p.inf_value := by unfold inf_value dual_objective apply le_sInf; simp intro a ha let minL := ⨅ x ∈ p.domain, (p.Lagrange_function x lambda1 lambda2).toEReal have neq : ∀ x' ∈ p.FeasSet, minL ≤ p.objective x' := by intro x hx simp [minL]; unfold FeasSet FeasPoint at hx; simp at hx apply le_trans (biInf_le _ hx.1.1) simp; unfold Lagrange_function have : ∑ i : τ, lambda1 i * p.equality_constraints i x = 0:= by apply Finset.sum_eq_zero intro i _ rw [hx.1.2 _ i.2, mul_zero] have : ∑ j : σ, lambda2 j * p.inequality_constraints j x ≥ 0 := by apply Finset.sum_nonneg intro j _ apply mul_nonneg (mpos j) (hx.2.2 j j.2) linarith exact neq a ha theorem weak_duality_aux {p : Constrained_OptimizationProblem E τ σ} (hp : (p.domain).Nonempty) : (p.dual_problem).sup_value ≤ p.inf_value := by unfold sup_value dual_problem; simp intro b x lambda1 lambda2 hl hl2 hl3 rw [← hl3, ← hl2] have : ((p.dual_objective lambda1 lambda2).toReal).toEReal = p.dual_objective lambda1 lambda2 := by apply EReal.coe_toReal · obtain hlt := dual_objective_le_top_nonempty hp lambda1 lambda2 exact LT.lt.ne_top hlt unfold FeasSet FeasPoint at hl; simp at hl exact hl.1 rw [this] apply weak_duality unfold FeasSet FeasPoint at hl; simp at hl intro j obtain hlj := hl.2 j j.2 simp at hlj; simpa theorem weak_duality' {p : Constrained_OptimizationProblem E τ σ} : (p.dual_problem).sup_value ≤ p.inf_value := by by_cases hp : (p.domain).Nonempty · exact weak_duality_aux hp push_neg at hp rw [empty_domain_inf_value_top hp] simp only [le_top] end WeakDuality section Convex variable {E : Type _} {τ σ : Finset ℕ} variable [NormedAddCommGroup E] [InnerProductSpace ℝ E] [CompleteSpace E] variable {p : Constrained_OptimizationProblem E τ σ} lemma ConcaveOn.sum {α 𝕜 : Type*} [OrderedSemiring 𝕜] [AddCommMonoid α][SMul 𝕜 α] {ι : Type*} [DecidableEq ι] {s : Finset ι} {t : s → α → 𝕜} {d : Set α} (h : ∀ i : s, ConcaveOn 𝕜 d (t i)) (hd : Convex 𝕜 d): ConcaveOn 𝕜 d (fun x => ∑ i : s, t i x) := by constructor · exact hd intro x hx y hy a b ha hb hab rw [Finset.smul_sum, Finset.smul_sum, ← Finset.sum_add_distrib] simp apply Finset.sum_le_sum intro i _ obtain h1 := (h i).2 hx hy ha hb hab simpa theorem convex_problem_convex_Lagrange {p : Constrained_OptimizationProblem E τ σ} (h : ConvexOn ℝ univ p.objective) (hτ : τ = ∅) (x : E) (hi : ∀ i ∈ σ, ConcaveOn ℝ univ (inequality_constraints p i)) (lambda1 : τ → ℝ) (lambda2 : σ → ℝ) (hKKT : KKT_point p x lambda1 lambda2) : ConvexOn ℝ univ (fun m ↦ p.Lagrange_function m lambda1 lambda2) := by unfold Lagrange_function apply ConvexOn.sub · apply ConvexOn.sub h simp [hτ]; apply concaveOn_const 0 exact convex_univ apply ConcaveOn.sum _ convex_univ intro i apply ConcaveOn.smul · unfold KKT_point at hKKT exact hKKT.2.2.1 i exact hi i i.2 omit [CompleteSpace E] in theorem diff_problem_diff_Lagrange {p : Constrained_OptimizationProblem E τ σ} (hτ : τ = ∅) (x : E) (hf : DifferentiableAt ℝ p.objective x) (conti : ∀ i ∈ σ, DifferentiableAt ℝ (inequality_constraints p i) x) (lambda1 : τ → ℝ) (lambda2 : σ → ℝ) : DifferentiableAt ℝ (fun m ↦ p.Lagrange_function m lambda1 lambda2) x := by apply DifferentiableAt.sub · apply DifferentiableAt.sub · exact hf simp [hτ] apply DifferentiableAt.sum intro i _ apply DifferentiableAt.const_mul _ (lambda2 i) apply conti i i.2 theorem KKT_multipliers_objective_eq_Lagrangian {p : Constrained_OptimizationProblem E τ σ} (x : E) (lambda1 : τ → ℝ) (lambda2 : σ → ℝ) (hKKT : KKT_point p x lambda1 lambda2) : p.objective x = p.Lagrange_function x lambda1 lambda2 := by unfold Lagrange_function unfold KKT_point at hKKT have h1 : ∑ i : τ, lambda1 i * p.equality_constraints i x = 0 := by obtain hx := hKKT.2.1 unfold FeasSet FeasPoint at hx simp at hx apply Finset.sum_eq_zero intro i _ rw [hx.1.2 i i.2, mul_zero] have h2 : ∑ j : σ, lambda2 j * p.inequality_constraints j x = 0 := by apply Finset.sum_eq_zero intro j _ rw [hKKT.2.2.2] rw [h1, h2, sub_zero, sub_zero] theorem KKT_multipliers_inf_value_aux {p : Constrained_OptimizationProblem E τ σ} (h : ConvexOn ℝ univ p.objective) (hτ : τ = ∅) (x : E) (hf : DifferentiableAt ℝ p.objective x) (hi : ∀ i ∈ σ, ConcaveOn ℝ univ (inequality_constraints p i)) (conti : ∀ i ∈ σ, DifferentiableAt ℝ (inequality_constraints p i) x) (lambda1 : τ → ℝ) (lambda2 : σ → ℝ) (hg : p.Global_Minimum x) (hKKT : KKT_point p x lambda1 lambda2) : (⨅ x ∈ p.domain, (p.Lagrange_function x lambda1 lambda2).toEReal) = ((p.Lagrange_function x lambda1 lambda2).toEReal) := by obtain hg1 := hg.1 unfold FeasPoint at hg1 unfold KKT_point at hKKT have h1 : ∀ x1 ∈ p.domain, p.Lagrange_function x1 lambda1 lambda2 ≥ p.Lagrange_function x lambda1 lambda2 := by intro x1 _ have : HasGradientAt (fun m ↦ p.Lagrange_function m lambda1 lambda2) (gradient (fun m ↦ p.Lagrange_function m lambda1 lambda2) x) x := by apply DifferentiableAt.hasGradientAt exact diff_problem_diff_Lagrange hτ x hf conti lambda1 lambda2 obtain h := Convex_first_order_condition' this (convex_problem_convex_Lagrange h hτ x hi lambda1 lambda2 hKKT) (x := x) rw [hKKT.1] at h; simp at h exact h x1 refine iInf_eq_of_forall_ge_of_forall_gt_exists_lt ?_ ?_ · intro x1; simp; intro hx1 exact h1 x1 hx1 intro w hw; use x; simp [hg1.1]; exact hw theorem KKT_multipliers_inf_value {p : Constrained_OptimizationProblem E τ σ} (h : ConvexOn ℝ univ p.objective) (hτ : τ = ∅) (x : E) (hf : DifferentiableAt ℝ p.objective x) (hi : ∀ i ∈ σ, ConcaveOn ℝ univ (inequality_constraints p i)) (conti : ∀ i ∈ σ, DifferentiableAt ℝ (inequality_constraints p i) x) (lambda1 : τ → ℝ) (lambda2 : σ → ℝ) (hg : p.Global_Minimum x) (hKKT : KKT_point p x lambda1 lambda2) : (p.dual_problem).objective (lambda1, lambda2) = p.inf_value := by rw [← global_minimum_objective_infimum hg] simp; unfold dual_problem dual_objective; simp obtain hg1 := hg.1 unfold FeasPoint at hg1 unfold KKT_point at hKKT rw [KKT_multipliers_objective_eq_Lagrangian x lambda1 lambda2 hKKT] obtain hh := KKT_multipliers_inf_value_aux h hτ x hf hi conti lambda1 lambda2 hg hKKT exact congrArg EReal.toReal hh theorem KKT_multipliers_dual_feasible {p : Constrained_OptimizationProblem E τ σ} (h : ConvexOn ℝ univ p.objective) (hτ : τ = ∅) (x : E) (hf : DifferentiableAt ℝ p.objective x) (hi : ∀ i ∈ σ, ConcaveOn ℝ univ (inequality_constraints p i)) (conti : ∀ i ∈ σ, DifferentiableAt ℝ (inequality_constraints p i) x) (lambda1 : τ → ℝ) (lambda2 : σ → ℝ) (hg : p.Global_Minimum x) (hKKT : KKT_point p x lambda1 lambda2) : (lambda1, lambda2) ∈ (p.dual_problem).FeasSet := by unfold FeasSet FeasPoint unfold KKT_point at hKKT simp; constructor · unfold dual_problem; simp unfold dual_objective rw [KKT_multipliers_inf_value_aux h hτ x hf hi conti lambda1 lambda2 hg hKKT]; simp intro j hj unfold dual_problem; simp [hj] exact hKKT.2.2.1 ⟨j, hj⟩ theorem optimal_multipliers_solution_dual_problem {p : Constrained_OptimizationProblem E τ σ} (h : ConvexOn ℝ univ p.objective) (hτ : τ = ∅) (x : E) (hf : DifferentiableAt ℝ p.objective x) (hi : ∀ i ∈ σ, ConcaveOn ℝ univ (inequality_constraints p i)) (conti : ∀ i ∈ σ, DifferentiableAt ℝ (inequality_constraints p i) x) (lambda1 : τ → ℝ) (lambda2 : σ → ℝ) (hg : p.Global_Minimum x) (hKKT : KKT_point p x lambda1 lambda2) : (p.dual_problem).Global_Maximum (lambda1, lambda2) := by apply objective_maximum_global_maximum · obtain h1 := KKT_multipliers_inf_value h hτ x hf hi conti lambda1 lambda2 hg hKKT obtain h2 := weak_duality' (p := p) have : (p.dual_problem).objective (lambda1, lambda2) ≤ (p.dual_problem).sup_value := by apply objective_le_sup _ (KKT_multipliers_dual_feasible h hτ x hf hi conti lambda1 lambda2 hg hKKT) rw [← h1] at h2 symm; apply antisymm h2 this exact KKT_multipliers_dual_feasible h hτ x hf hi conti lambda1 lambda2 hg hKKT end Convex end Duality