PO.ID.Partial.LP

The linear-programming representation of bound computations over finite outcome spaces.

Conic­Duality 9 core · 2 supporting This file develops the conic linear-programming duality backbone for partial identification bounds. ★ farkas★ strong_duality_primal_attained★ strong_duality_zero_gap

Conic Duality

This file develops the conic linear-programming duality backbone for partial identification bounds. It treats sharp bounds as optimal values of linear programs over a cone in real Hilbert spaces and proves weak duality, a Farkas feasibility alternative, primal attainment under a closedness qualification, and zero duality gap under the same qualification.

The main structure ConicProgram packages the cone K, constraint operator A, right-hand side b, and objective direction c. The predicates PrimalFeasible and DualFeasible define the primal and dual feasible sets, while primalValue and dualValue record the corresponding optimal values. The theorem weak_duality gives the pointwise inequality, and dualValue_le_primalValue lifts it to values.

The theorem farkas restates conic separation as a feasibility alternative. The set augmentedImage is the closedness constraint qualification used by strong_duality_primal_attained and strong_duality_zero_gap, which provide primal attainment and no duality gap for feasible bounded-below programs.

The Hilbert-space formulation covers infinite-dimensional function spaces used by proxy and bridge problems. Measure-cone weak-star duality is intentionally left outside this module; the module note at the end explains the missing signed-measure and cone infrastructure.

structure ConicProgram reviewed
Causalean.PartialID

Primal data of a conic linear program over real Hilbert spaces: minimize ⟪c, x⟫ subject to A x = b and x ∈ K.

Definition (Lean source)
The constraint cone (nonnegativity / shape restrictions).
K :
The linear constraint operator.
A :
E →L[ℝ] F
The right-hand side (observed-data target).
b :
F
The objective direction.
c :
E
Causalean.PartialID.ConicProgram · Causalean/PO/ID/Partial/LP/ConicDuality.lean:44
def PrimalFeasible reviewed
Causalean.PartialID.ConicProgram

A point is primal feasible when it satisfies the equality constraint and lies in the cone.

Definition (Lean source)
def PrimalFeasible (x : E) : Prop := P.A x = P.b ∧ x ∈ P.K
Causalean.PartialID.ConicProgram.PrimalFeasible · Causalean/PO/ID/Partial/LP/ConicDuality.lean:62 · uses ConicProgram
def DualFeasible reviewed
Causalean.PartialID.ConicProgram

A dual multiplier is dual feasible when the reduced cost c - Aᵀ y lies in the dual cone K⋆ = innerDual K.

Definition (Lean source)
def DualFeasible (y : F) : Prop := P.c - (adjoint P.A) y ∈ innerDual (P.K : Set E)
Causalean.PartialID.ConicProgram.DualFeasible · Causalean/PO/ID/Partial/LP/ConicDuality.lean:66 · uses ConicProgram
def primalValue reviewed
Causalean.PartialID.ConicProgram

The primal optimal value inf { ⟪c, x⟫ : x primal feasible }.

Definition (Lean source)
noncomputable def primalValue : ℝ := sInf ((fun x => ⟪P.c, x⟫) '' {x | P.PrimalFeasible x})
Causalean.PartialID.ConicProgram.primalValue · Causalean/PO/ID/Partial/LP/ConicDuality.lean:71 · uses ConicProgram
def dualValue reviewed
Causalean.PartialID.ConicProgram

The dual optimal value sup { ⟪b, y⟫ : y dual feasible }.

Definition (Lean source)
noncomputable def dualValue : ℝ := sSup ((fun y => ⟪P.b, y⟫) '' {y | P.DualFeasible y})
Causalean.PartialID.ConicProgram.dualValue · Causalean/PO/ID/Partial/LP/ConicDuality.lean:75 · uses ConicProgram
theorem farkas reviewed
Causalean.PartialID.ConicProgram

Farkas alternative / feasibility engine. For a target point b, b lies in the closed image cone A(K) if and only if every dual direction y whose pullback Aᵀ y lies in the dual cone of K pairs nonnegatively with b.

Formal statement
b :
F
b ∈ map P.A P.K
↔ ∀ y : F, (adjoint P.A) y ∈ innerDual (P.K : Set E) → 0 ≤ ⟪b, y⟫
Proof (Lean source)
theorem farkas {b : F} : b ∈ ProperCone.map P.A P.K ↔ ∀ y : F, (adjoint P.A) y ∈ innerDual (P.K : Set E) → 0 ≤ ⟪b, y⟫ := ProperCone.relative_hyperplane_separation
Causalean.PartialID.ConicProgram.farkas · Causalean/PO/ID/Partial/LP/ConicDuality.lean:107 · uses ConicProgram
def augmentedImage reviewed
Causalean.PartialID.ConicProgram

The augmented image cone { (A x, ⟪c, x⟫) : x ∈ K } in F × ℝ. Its closedness is the constraint qualification for primal attainment, and the geometry (a boundary point (b, primalValue)) is where the dual certificate is read off.

Definition (Lean source)
def augmentedImage : Set (F × ℝ) := (fun x => (P.A x, ⟪P.c, x⟫)) '' (P.K : Set E)
Causalean.PartialID.ConicProgram.augmentedImage · Causalean/PO/ID/Partial/LP/ConicDuality.lean:122 · uses ConicProgram
theorem strong_duality_primal_attained reviewed
Causalean.PartialID.ConicProgram

Strong duality I — primal attainment (closedness CQ). For a conic program that is primal feasible and whose feasible objective values are bounded below, if the augmented image cone {(Ax, ⟪c,x⟫) : x ∈ K} is closed — the constraint qualification separating attained optima from mere infima — then the primal optimum is attained: some primal-feasible point x achieves the objective value ⟪c,x⟫ = primalValue exactly. This is the "there is an extremal data-generating distribution" half of sharpness.

Formal statement
hP :
{x | P.PrimalFeasible x}.Nonempty
hbdd :
BddBelow ((fun x => ⟪P.c, x⟫) '' {x | P.PrimalFeasible x})
hCQ :
IsClosed P.augmentedImage
∃ x, P.PrimalFeasible x ∧ ⟪P.c, x⟫ = P.primalValue
Proof (Lean source)
theorem strong_duality_primal_attained (hP : {x | P.PrimalFeasible x}.Nonempty) (hbdd : BddBelow ((fun x => ⟪P.c, x⟫) '' {x | P.PrimalFeasible x})) (hCQ : IsClosed P.augmentedImage) : ∃ x, P.PrimalFeasible x ∧ ⟪P.c, x⟫ = P.primalValue := by have hSeq : (fun x => ⟪P.c, x⟫) '' {x | P.PrimalFeasible x} = (fun r : ℝ => (P.b, r)) ⁻¹' P.augmentedImage := by ext r constructor · rintro ⟨x, hx, rfl⟩ exact ⟨x, hx.2, by simp only [hx.1]⟩ · rintro ⟨x, hxK, hxeq⟩ exact ⟨x, ⟨(Prod.ext_iff.mp hxeq).1, hxK⟩, (Prod.ext_iff.mp hxeq).2⟩ have hScl : IsClosed ((fun x => ⟪P.c, x⟫) '' {x | P.PrimalFeasible x}) := by rw [hSeq]; exact hCQ.preimage (by fun_prop) have hmem := hScl.csInf_mem (hP.image _) hbdd obtain ⟨x, hx, hxval⟩ := hmem exact ⟨x, hx, hxval⟩
Causalean.PartialID.ConicProgram.strong_duality_primal_attained · Causalean/PO/ID/Partial/LP/ConicDuality.lean:128 · uses ConicProgram , PrimalFeasible , augmentedImage , primalValue
theorem strong_duality_zero_gap reviewed
Causalean.PartialID.ConicProgram

Strong duality II — zero gap (closedness CQ). For a conic program that is primal feasible and whose feasible objective values are bounded below, if the augmented image cone is closed — the same constraint qualification as primal attainment — then there is no duality gap: the primal optimal value equals the dual optimal value, primalValue = dualValue.

Formal statement
hP :
{x | P.PrimalFeasible x}.Nonempty
hbdd :
BddBelow ((fun x => ⟪P.c, x⟫) '' {x | P.PrimalFeasible x})
hCQ :
IsClosed P.augmentedImage
P.primalValue = P.dualValue
Proof (Lean source)
theorem strong_duality_zero_gap (hP : {x | P.PrimalFeasible x}.Nonempty) (hbdd : BddBelow ((fun x => ⟪P.c, x⟫) '' {x | P.PrimalFeasible x})) (hCQ : IsClosed P.augmentedImage) : P.primalValue = P.dualValue := by -- The augmented operator `à x = (A x, ⟪c, x⟫)`. set à : E →L[ℝ] (F × ℝ) := (P.A).prod (innerSL ℝ P.c) with hÃdef have hÃapp : ∀ x : E, à x = (P.A x, ⟪P.c, x⟫) := fun x => rfl -- The underlying `PointedCone.map` image set is exactly the augmented image. have hpcimg : ((PointedCone.map (à : E →ₗ[ℝ] (F × ℝ)) (P.K : PointedCone ℝ E)) : Set (F × ℝ)) = P.augmentedImage := by rw [PointedCone.coe_map] ext z simp only [augmentedImage, Set.mem_image] constructor · rintro ⟨x, hx, rfl⟩; exact ⟨x, hx, (hÃapp x).symm⟩ · rintro ⟨x, hx, rfl⟩; exact ⟨x, hx, hÃapp x⟩ -- `p* := primalValue` is a finite lower bound for the feasible objective values. set S : Set ℝ := (fun x => ⟪P.c, x⟫) '' {x | P.PrimalFeasible x} with hSdef have hSne : S.Nonempty := hP.image _ have hlb : ∀ x : E, P.PrimalFeasible x → P.primalValue ≤ ⟪P.c, x⟫ := by intro x hx exact csInf_le hbdd ⟨x, hx, rfl⟩ -- (A) dualValue ≤ primalValue: every dual-feasible value is ≤ every feasible objective, -- hence ≤ the infimum p*. have hA : ∀ y : F, P.DualFeasible y → ⟪P.b, y⟫ ≤ P.primalValue := by intro y hy refine le_csInf hSne ?_ rintro _ ⟨x, hx, rfl⟩ exact P.weak_duality hx hy -- (B) primalValue ≤ dualValue, via separation. -- First: for every ε > 0 there is a dual-feasible ȳ with ⟪b, ȳ⟫ > p* - ε. have hB : ∀ ε : ℝ, 0 < ε → ∃ y : F, P.DualFeasible y ∧ P.primalValue - ε < ⟪P.b, y⟫ := by intro ε hε -- The point (b, p* - ε) is not in the map cone. have hnotmem : (P.b, P.primalValue - ε) ∉ map à P.K := by intro hmem have hcl : (P.b, P.primalValue - ε) ∈ (PointedCone.map (à : E →ₗ[ℝ] (F × ℝ)) (P.K : PointedCone ℝ E)).closure := ProperCone.mem_map.mp hmem rw [PointedCone.mem_closure] at hcl -- closure of the augmented image is itself, since it is closed. have : (P.b, P.primalValue - ε) ∈ P.augmentedImage := by have hset : closure ((PointedCone.map (à : E →ₗ[ℝ] (F × ℝ)) (P.K : PointedCone ℝ E)) : Set (F × ℝ)) = P.augmentedImage := by rw [hpcimg]; exact hCQ.closure_eq rwa [hset] at hcl obtain ⟨x, hxK, hxeq⟩ := this have h1 : P.A x = P.b := (Prod.ext_iff.mp hxeq).1 have h2 : ⟪P.c, x⟫ = P.primalValue - ε := (Prod.ext_iff.mp hxeq).2 have hfeas : P.PrimalFeasible x := ⟨h1, hxK⟩ have := hlb x hfeas rw [h2] at this linarith -- Separate. obtain ⟨g, hgpos, hgneg⟩ := ProperCone.hyperplane_separation_point (map à P.K) hnotmem -- Decompose g into the F-part (Riesz) and the ℝ-part s := g(0,1). set s : ℝ := g (0, 1) with hsdef set φ : F →L[ℝ] ℝ := g.comp ((ContinuousLinearMap.inl ℝ F ℝ)) with hφdef -- φ v = g (v, 0); Riesz representative y₀. set y₀ : F := (InnerProductSpace.toDual ℝ F).symm φ with hy₀def have hφapp : ∀ v : F, φ v = ⟪y₀, v⟫ := by intro v rw [hy₀def] rw [InnerProductSpace.toDual_symm_apply] -- g decomposes: g (v, t) = ⟪y₀, v⟫ + t * s. have hgdecomp : ∀ (v : F) (t : ℝ), g (v, t) = ⟪y₀, v⟫ + s * t := by intro v t have hvt : ((v, t) : F × ℝ) = (v, 0) + t • (0, 1) := by simp rw [hvt, map_add, map_smul] have hv : g (v, 0) = ⟪y₀, v⟫ := by rw [← hφapp v]; rfl rw [hv] simp only [hsdef, smul_eq_mul] ring -- (i): ∀ x ∈ K, 0 ≤ ⟪y₀, A x⟫ + s * ⟪c, x⟫. have hi : ∀ x : E, x ∈ P.K → 0 ≤ ⟪y₀, P.A x⟫ + s * ⟪P.c, x⟫ := by intro x hx have hxmem : à x ∈ map à P.K := by apply ProperCone.mem_map.mpr rw [PointedCone.mem_closure] apply subset_closure -- à x ∈ (PointedCone.map ↑à ↑P.K : Set _) = augmentedImage rw [hpcimg] exact ⟨x, hx, rfl⟩ have := hgpos (à x) hxmem rw [hÃapp x, hgdecomp] at this exact this -- (ii): ⟪y₀, b⟫ + (p* - ε) * s < 0. have hii : ⟪y₀, P.b⟫ + s * (P.primalValue - ε) < 0 := by have := hgneg rw [hgdecomp] at this exact this -- Get a feasible point x₀. obtain ⟨x₀, hx₀⟩ := hP have hx₀K : x₀ ∈ P.K := hx₀.2 have hx₀A : P.A x₀ = P.b := hx₀.1 have hx₀val : P.primalValue ≤ ⟪P.c, x₀⟫ := hlb x₀ hx₀ -- Case on s. rcases lt_trichotomy s 0 with hs | hs | hs · -- s < 0 impossible. exfalso have h1 := hi x₀ hx₀K rw [hx₀A] at h1 -- 0 ≤ ⟪y₀, b⟫ + s * ⟪c, x₀⟫ -- since s < 0 and ⟪c,x₀⟫ ≥ p*: s * ⟪c,x₀⟫ ≤ s * p* have hmul : s * ⟪P.c, x₀⟫ ≤ s * P.primalValue := by apply mul_le_mul_of_nonpos_left hx₀val (le_of_lt hs) -- (ii): ⟪y₀,b⟫ + (p*-ε)*s < 0, i.e. ⟪y₀,b⟫ + s*p* - s*ε < 0 nlinarith [hii, h1, hmul, hε, hs] · -- s = 0 impossible. exfalso have h1 := hi x₀ hx₀K rw [hx₀A, hs] at h1 simp only [zero_mul, add_zero] at h1 -- h1 : 0 ≤ ⟪y₀, b⟫ have h2 := hii rw [hs] at h2 simp only [zero_mul, add_zero] at h2 -- h2 : ⟪y₀, b⟫ < 0 linarith · -- s > 0: ȳ := -(1/s) • y₀ is dual feasible with ⟪b, ȳ⟫ > p* - ε. refine ⟨-(1/s) • y₀, ?_, ?_⟩ · -- dual feasibility rw [DualFeasible, ProperCone.mem_innerDual] intro x hx have hred : ⟪x, P.c - (adjoint P.A) (-(1/s) • y₀)⟫ = (1/s) * (⟪y₀, P.A x⟫ + s * ⟪P.c, x⟫) := by rw [inner_sub_right] rw [map_smul, inner_smul_right] rw [ContinuousLinearMap.adjoint_inner_right] rw [real_inner_comm x P.c, real_inner_comm (P.A x) y₀] field_simp ring rw [hred] have hpos : (0 : ℝ) ≤ 1/s := le_of_lt (by positivity) exact mul_nonneg hpos (hi x hx) · -- value bound have hval : ⟪P.b, -(1/s) • y₀⟫ = -(1/s) * ⟪y₀, P.b⟫ := by rw [inner_smul_right, real_inner_comm P.b y₀] rw [hval] -- from (ii): ⟪y₀, b⟫ + s*(p*-ε) < 0; multiply by 1/s > 0. have hsinv : (0:ℝ) < 1 / s := by positivity have key : (1/s) * (⟪y₀, P.b⟫ + s * (P.primalValue - ε)) < (1/s) * 0 := mul_lt_mul_of_pos_left hii hsinv have hexp : (1/s) * (⟪y₀, P.b⟫ + s * (P.primalValue - ε)) = (1/s) * ⟪y₀, P.b⟫ + (P.primalValue - ε) := by field_simp rw [hexp, mul_zero] at key linarith [key] -- Assemble: dualValue ≥ p* and dualValue ≤ p*. have hDne : {y | P.DualFeasible y}.Nonempty := by obtain ⟨y, hy, _⟩ := hB 1 (by norm_num) exact ⟨y, hy⟩ -- dualValue ≤ primalValue have hle : P.dualValue ≤ P.primalValue := by rw [dualValue] refine csSup_le (hDne.image _) ?_ rintro _ ⟨y, hy, rfl⟩ exact hA y hy -- primalValue ≤ dualValue have hge : P.primalValue ≤ P.dualValue := by refine le_of_forall_pos_lt_add ?_ intro ε hε obtain ⟨y, hy, hyval⟩ := hB ε hε have hbdd' : BddAbove ((fun y => ⟪P.b, y⟫) '' {y | P.DualFeasible y}) := by refine ⟨P.primalValue, ?_⟩ rintro _ ⟨z, hz, rfl⟩ exact hA z hz have : ⟪P.b, y⟫ ≤ P.dualValue := le_csSup hbdd' ⟨y, hy, rfl⟩ linarith linarith
2 supporting declarations (lemmas, instances)
  • weak_duality theorem — Weak duality (pointwise). Any dual-feasible objective value lower-bounds any primal-feasible objective value.
    x :
    E
    y :
    F
    hx :
    P.PrimalFeasible x
    hy :
    P.DualFeasible y
    ⟪P.b, y⟫ ≤ ⟪P.c, x⟫
    Proof (Lean source)
    theorem weak_duality {x : E} {y : F} (hx : P.PrimalFeasible x) (hy : P.DualFeasible y) : ⟪P.b, y⟫ ≤ ⟪P.c, x⟫ := by -- Dual feasibility says `0 ≤ ⟪x, c - Aᵀ y⟫` for `x ∈ K`. have h0 : 0 ≤ ⟪x, P.c - (adjoint P.A) y⟫ := ProperCone.mem_innerDual.mp hy hx.2 have e1 : ⟪x, P.c - (adjoint P.A) y⟫ = ⟪x, P.c⟫ - ⟪P.A x, y⟫ := by rw [inner_sub_right, ContinuousLinearMap.adjoint_inner_right] rw [e1, hx.1] at h0 -- h0 : 0 ≤ ⟪x, P.c⟫ - ⟪P.b, y⟫ have ec := real_inner_comm x P.c linarith
    Causalean.PartialID.ConicProgram.weak_duality · Causalean/PO/ID/Partial/LP/ConicDuality.lean:79
  • dualValue_le_primalValue theorem — Weak duality (value form). When both programs are feasible, dualValue ≤ primalValue. (Boundedness is not needed: the pointwise bound exhibits primalValue as an explicit upper bound for the dual values.)
    hP :
    {x | P.PrimalFeasible x}.Nonempty
    hD :
    {y | P.DualFeasible y}.Nonempty
    P.dualValue ≤ P.primalValue
    Proof (Lean source)
    theorem dualValue_le_primalValue (hP : {x | P.PrimalFeasible x}.Nonempty) (hD : {y | P.DualFeasible y}.Nonempty) : P.dualValue ≤ P.primalValue := by rw [dualValue, primalValue] refine csSup_le (hD.image _) ?_ rintro _ ⟨y, hy, rfl⟩ refine le_csInf (hP.image _) ?_ rintro _ ⟨x, hx, rfl⟩ exact P.weak_duality hx hy
    Causalean.PartialID.ConicProgram.dualValue_le_primalValue · Causalean/PO/ID/Partial/LP/ConicDuality.lean:94