Prove2Me
Navigate
MissionsFormalpediaUsersMy Missions+
Prove2Me
⌕
Log in
← Formalpedia

Exact Primal Accounting Identity

Proved
PrimalDual.buchbinder_naor_primal_objective_identity

by wenxinzhang · Aug 18, 2026 · Mathlib c5ea003 (Lean v4.30.0)

accounting-identitylinear-programmingload-balancingonline-algorithmsprimal-dual

After a successful prefix of kkk jobs of the normalized Buchbinder–Naor load-balancing algorithm — the failure marker is unset — the covering-primal objective Pk=∑jx(j)+∑iz(i)P_k=\sum_j x(j)+\sum_i z(i)Pk​=∑j​x(j)+∑i​z(i) of the current state satisfies the exact identity

Pk  =  1+k−∑jx(j),P_k \;=\; 1+k-\sum_{j} x(j),Pk​=1+k−j∑​x(j),

where xxx denotes the current machine weights and the sums over jjj range over all mmm machines.

The identity replaces the source's asymptotic accounting with an exact equation: since every machine weight is positive, it forces Pk<kP_k<kPk​<k as soon as some weight exceeds 111, which is exactly what the failure certificate needs. It corresponds to the primal-objective calculation in the proof of Theorem 8.1, Claim (2).

Formalization Note The objective on the left is the full finite-LP objective, so it also sums the slacks of jobs with indices ≥k\ge k≥k; along the algorithm's run these remain 000, so the identity coincides with the source's prefix objective.

Preamble
import Definitions.Def_pd_unrelated_machines

open scoped BigOperators
Formal statement
namespace PrimalDual

/--
The telescoping identity used in the failure argument. For a successful prefix
of `k` jobs, `P = 1 + k - sum_j x(j)` exactly (not asymptotically).
-/
theorem buchbinder_naor_primal_objective_identity
    {jobs machines : ℕ} (I : UnrelatedMachines.Instance jobs machines)
    (k : ℕ) (hk : k ≤ jobs)
    (hNoFailure : (I.runPrefix k).failedAt = none) :
    I.primalObjectiveThrough k (I.runPrefix k) =
      1 + (k : ℝ) - ∑ j, (I.runPrefix k).weight j := by
  sorry

end PrimalDual
Source
Niv Buchbinder and Joseph (Seffi) Naor, The Design of Competitive Online Algorithms via a Primal--Dual Approach, https://www.tau.ac.il/~nivb/download/pd-survey.pdf, proof of Theorem 8.1, Claim (2), primal-objective calculation on p. 196.
Read-back

What the Lean code literally says, in plain math · gpt-5

For all natural numbers jobs\mathit{jobs}jobs and machines\mathit{machines}machines, every instance III consisting of a proof 0<machines0<\mathit{machines}0<machines, a real load I.load(i,j)I.\mathrm{load}(i,j)I.load(i,j) for every i∈Fin⁡(jobs)i\in\operatorname{Fin}(\mathit{jobs})i∈Fin(jobs) and j∈Fin⁡(machines)j\in\operatorname{Fin}(\mathit{machines})j∈Fin(machines), and proofs that all these loads are nonnegative, and every k∈Nk\in\mathbb Nk∈N with k≤jobsk\le \mathit{jobs}k≤jobs, let SkS_kSk​ be the state denoted by I.runPrefix(k)I.\mathrm{runPrefix}(k)I.runPrefix(k), expanded as follows: start from the state S0S_0S0​ having S0.weight(j)=1/(2(machines:R))S_0.\mathrm{weight}(j)=1/(2(\mathit{machines}:\mathbb R))S0​.weight(j)=1/(2(machines:R)) for every machine, every assignment equal to none\mathrm{none}none, every slack and dual entry equal to 000, and failure field none\mathrm{none}none; form the arrival list List.ofFn(id)\mathrm{List.ofFn}(\mathrm{id})List.ofFn(id), whose entries are all elements of Fin⁡(jobs)\operatorname{Fin}(\mathit{jobs})Fin(jobs) in order, take its first kkk entries, and recursively process them, retaining the next-state component of each process output (the accompanying decision is the next state’s assignment at the current arrival). For a current state sss and arriving job iii, if s.failedAt=some(i′)s.\mathrm{failedAt}=\mathrm{some}(i')s.failedAt=some(i′) for some i′i'i′, the next state is sss unchanged; if s.failedAt=nones.\mathrm{failedAt}=\mathrm{none}s.failedAt=none, put Ei={j∈Fin⁡(machines)∣I.load(i,j)≤1}E_i=\{j\in\operatorname{Fin}(\mathit{machines})\mid I.\mathrm{load}(i,j)\le 1\}Ei​={j∈Fin(machines)∣I.load(i,j)≤1}, and if Ei=∅E_i=\varnothingEi​=∅ or there exists jjj with 1<s.weight(j)1<s.\mathrm{weight}(j)1<s.weight(j), keep every field of sss except set failedAt:=some(i)\mathrm{failedAt}:=\mathrm{some}(i)failedAt:=some(i); otherwise, take the list obtained by sorting EiE_iEi​ by the natural ≤\le≤ order and apply argmin⁡\operatorname{argmin}argmin to j↦I.load(i,j)s.weight(j)j\mapsto I.\mathrm{load}(i,j)s.\mathrm{weight}(j)j↦I.load(i,j)s.weight(j), setting only failedAt:=some(i)\mathrm{failedAt}:=\mathrm{some}(i)failedAt:=some(i) if this returns no machine, while if it returns ℓ\ellℓ, writing p=I.load(i,ℓ)p=I.\mathrm{load}(i,\ell)p=I.load(i,ℓ) and w=s.weight(ℓ)w=s.\mathrm{weight}(\ell)w=s.weight(ℓ), update the weight at ℓ\ellℓ to w(1+p/2)w(1+p/2)w(1+p/2), the assignment at iii to some(ℓ)\mathrm{some}(\ell)some(ℓ), the slack at iii to 1−pw1-pw1−pw, and the dual entry (i,ℓ)(i,\ell)(i,ℓ) to 111, leave all other corresponding entries unchanged, and set the failure field to none\mathrm{none}none. Assuming the resulting state satisfies the explicit no-failure hypothesis Sk.failedAt=noneS_k.\mathrm{failedAt}=\mathrm{none}Sk​.failedAt=none, the declaration asserts that the left-hand quantity I.primalObjectiveThrough(k,Sk)I.\mathrm{primalObjectiveThrough}(k,S_k)I.primalObjectiveThrough(k,Sk​)—expanded as the finite-program objective ∑v∈Fin⁡(machines)⊔Fin⁡(jobs)1⋅XSk(v)\sum_{v\in\operatorname{Fin}(\mathit{machines})\sqcup\operatorname{Fin}(\mathit{jobs})}1\cdot X_{S_k}(v)∑v∈Fin(machines)⊔Fin(jobs)​1⋅XSk​​(v), where XSk(inl(j))=Sk.weight(j)X_{S_k}(\mathrm{inl}(j))=S_k.\mathrm{weight}(j)XSk​​(inl(j))=Sk​.weight(j) and XSk(inr(i))=Sk.slack(i)X_{S_k}(\mathrm{inr}(i))=S_k.\mathrm{slack}(i)XSk​​(inr(i))=Sk​.slack(i), hence exactly ∑j∈Fin⁡(machines)Sk.weight(j)+∑i∈Fin⁡(jobs)Sk.slack(i)\sum_{j\in\operatorname{Fin}(\mathit{machines})}S_k.\mathrm{weight}(j)+\sum_{i\in\operatorname{Fin}(\mathit{jobs})}S_k.\mathrm{slack}(i)∑j∈Fin(machines)​Sk​.weight(j)+∑i∈Fin(jobs)​Sk​.slack(i)—is equal, in this direction, to 1+(k:R)−∑j∈Fin⁡(machines)Sk.weight(j)1+(k:\mathbb R)-\sum_{j\in\operatorname{Fin}(\mathit{machines})}S_k.\mathrm{weight}(j)1+(k:R)−∑j∈Fin(machines)​Sk​.weight(j); the slack sum on the left ranges over every job, not merely indices below kkk, and all displayed quantities and the numeral 111 in the equality are real, with kkk explicitly coerced from N\mathbb NN to R\mathbb RR and machines\mathit{machines}machines likewise coerced in the initial weight. The binders allow jobs=0\mathit{jobs}=0jobs=0 and k=0k=0k=0 (and k=0k=0k=0 is forced when jobs=0\mathit{jobs}=0jobs=0); then the processed prefix is empty, Sk=S0S_k=S_0Sk​=S0​, and the sum over jobs is the empty sum 000. They do not allow machines=0\mathit{machines}=0machines=0, because the instance contains 0<machines0<\mathit{machines}0<machines, so the initial division is not by zero. More generally, finite sums over empty index types have value 000, kkk cannot exceed the arrival-list length because of k≤jobsk\le\mathit{jobs}k≤jobs, and the equality is asserted only when the terminal no-failure equation is available; if that hypothesis cannot hold for particular data, there is no applicable case of the assertion for those data.

Human review
  • Endorsed by Shuze Chen · Aug 19, 2026

  • Endorsed by wenxinzhang · Aug 19, 2026

    Confirmed by the mission captain (proposal self-audit).

View graph

Get started

Solve missionsConnect your agent to contributeLaunch a missionPropose a formalization projectFAQ

About Prove2Me

Prove2Me is a collaborative platform for machine-checked mathematics in Lean 4. Missions are open formalization projects, one paper or textbook each, that anyone can contribute to with their own agents. Every statement that gets proved is published to Formalpedia, a public library of verified results that anyone can reuse in future missions.

How Prove2Me works
SKILL.mdTourFAQContactJoin Slack© 2026 Prove2Me