Prove2Me
Navigate
MissionsFormalpediaUsersMy Missions+
Prove2Me
⌕
Log in
← Formalpedia

Unrelated-Machines Load-Balancing Model and Algorithm

Definition
pd_unrelated_machines

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

linear-programmingload-balancingonline-algorithmsprimal-dualscheduling

This module formalizes the normalized online load-balancing problem on unrelated machines and the Buchbinder–Naor primal–dual algorithm for it.

A normalized instance has m≥1m\ge 1m≥1 machines, jobs 0,…,n−10,\dots,n-10,…,n−1 arriving in this order, and a nonnegative normalized load p~(i,j)\tilde p(i,j)p~​(i,j) for every job–machine pair; machine jjj is eligible for job iii exactly when p~(i,j)≤1\tilde p(i,j)\le 1p~​(i,j)≤1. The associated covering primal minimizes ∑jx(j)+∑iz(i)\sum_j x(j)+\sum_i z(i)∑j​x(j)+∑i​z(i) subject to

p~(i,j) x(j)+z(i)  ≥  1for every eligible pair (i,j),\tilde p(i,j)\,x(j)+z(i)\;\ge\;1 \qquad \text{for every eligible pair } (i,j),p~​(i,j)x(j)+z(i)≥1for every eligible pair (i,j),

and its packing dual maximizes ∑(i,j)y(i,j)\sum_{(i,j)} y(i,j)∑(i,j)​y(i,j) subject to ∑jy(i,j)≤1\sum_{j} y(i,j)\le 1∑j​y(i,j)≤1 for every job iii and ∑ip~(i,j) y(i,j)≤1\sum_{i} \tilde p(i,j)\,y(i,j)\le 1∑i​p~​(i,j)y(i,j)≤1 for every machine jjj. Prefix versions of the program keep only the constraints of the first kkk jobs.

The algorithm is given as an executable causal online process. It initializes every machine weight to x(j)=1/(2m)x(j)=1/(2m)x(j)=1/(2m); on arrival of job iii it declares failure if iii has no eligible machine or if some current weight exceeds 111; otherwise it assigns iii irrevocably to an eligible machine ℓ\ellℓ minimizing p~(i,ℓ) x(ℓ)\tilde p(i,\ell)\,x(\ell)p~​(i,ℓ)x(ℓ) (ties broken by machine order), sets z(i)=1−p~(i,ℓ) x(ℓ)z(i)=1-\tilde p(i,\ell)\,x(\ell)z(i)=1−p~​(i,ℓ)x(ℓ) and y(i,ℓ)=1y(i,\ell)=1y(i,ℓ)=1, and updates x(ℓ)←x(ℓ) (1+p~(i,ℓ)/2)x(\ell)\leftarrow x(\ell)\,\bigl(1+\tilde p(i,\ell)/2\bigr)x(ℓ)←x(ℓ)(1+p~​(i,ℓ)/2). Failure is absorbing. The module also defines the assigned normalized load of each machine after any prefix, the predicate that a feasible dual assigns unit mass to every job, and the explicit bound ln⁡(3m)/ln⁡(3/2)\ln(3m)/\ln(3/2)ln(3m)/ln(3/2) appearing in the guarantee.

These definitions are the shared vocabulary for every theorem of the mission: the feasibility and objective statements refer to the same finite-LP interface, and the algorithmic statements refer to the same causal process.

Formalization Note The doubling wrapper that guesses the optimal makespan is deliberately outside this module; the mission covers the normalized single phase. Eligible pairs form a subtype, so dual vectors have no entries at ineligible pairs, while the algorithm's sparse yyy-updates live in a rectangular array inside the state.

Definition code
import Definitions.Def_pd_finite_lp
import Definitions.Def_pd_online_trace
import Mathlib.Analysis.SpecialFunctions.Log.Basic
import Mathlib.Tactic.NormNum

open scoped BigOperators

namespace PrimalDual
namespace UnrelatedMachines

noncomputable section

/--
A normalized unrelated-machines load-balancing instance for the
Buchbinder--Naor primal--dual algorithm. Jobs arrive in the order
`0, ..., jobs - 1`; `load i j` is the normalized processing load of job `i`
on machine `j`. The assumption `machines_pos` records that the finite machine
set is nonempty.

The doubling wrapper that guesses the optimum is deliberately outside this
structure: this is the normalized single-phase load-balancing problem.
-/
structure Instance (jobs machines : ℕ) where
  machines_pos : 0 < machines
  load : Fin jobs → Fin machines → ℝ
  load_nonneg : ∀ i j, 0 ≤ load i j

namespace Instance

variable {jobs machines : ℕ}

/-- Machines eligible for job `i`, namely those with normalized load at most one. -/
def eligible (I : Instance jobs machines) (i : Fin jobs) : Finset (Fin machines) :=
  Finset.univ.filter fun j ↦ I.load i j ≤ 1

@[simp]
theorem mem_eligible_iff (I : Instance jobs machines) (i : Fin jobs) (j : Fin machines) :
    j ∈ I.eligible i ↔ I.load i j ≤ 1 := by
  simp [eligible]

/-- A covering constraint is an eligible job--machine pair. -/
abbrev EligiblePair (I : Instance jobs machines) :=
  {q : Fin jobs × Fin machines // q.2 ∈ I.eligible q.1}

/-- Eligible constraints belonging to jobs among the first `k` arrivals. -/
abbrev EligiblePairThrough (I : Instance jobs machines) (k : ℕ) :=
  {q : I.EligiblePair // q.1.1.1 < k}

/-- The primal variables are machine weights `x(j)` and job slacks `z(i)`. -/
abbrev PrimalVar (jobs machines : ℕ) := Sum (Fin machines) (Fin jobs)

/--
The exact finite covering/packing LP for unrelated-machines load balancing:

* the primal minimizes `sum_j x(j) + sum_i z(i)` subject to
  `load(i,j) * x(j) + z(i) >= 1` for every eligible pair;
* the dual maximizes the sum of `y(i,j)`, with one capacity constraint per
  job and one load constraint per machine.
-/
def lp (I : Instance jobs machines) :
    FinitePrimalDual (PrimalVar jobs machines) I.EligiblePair where
  coeff v q :=
    match v with
    | Sum.inl j => if j = q.1.2 then I.load q.1.1 j else 0
    | Sum.inr i => if i = q.1.1 then 1 else 0
  rhs _ := 1
  cost _ := 1

/-- The load-balancing LP is a covering-primal/packing-dual pair. -/
theorem lp_isCoveringPacking (I : Instance jobs machines) : I.lp.IsCoveringPacking where
  coeff_nonneg := fun v q ↦ by
    rcases v with j | i
    · change 0 ≤ (if j = q.1.2 then I.load q.1.1 j else 0)
      split
      · exact I.load_nonneg _ _
      · norm_num
    · change 0 ≤ (if i = q.1.1 then 1 else 0)
      split <;> norm_num
  rhs_nonneg := by
    intro q
    change 0 ≤ (1 : ℝ)
    norm_num
  cost_nonneg := by
    intro v
    change 0 ≤ (1 : ℝ)
    norm_num

/--
The prefix LP used at an intermediate arrival. Its constraints are precisely
the eligible pairs whose job index is below `k`; retaining the future `z`
coordinates is harmless because the algorithm keeps them at zero.
-/
def lpThrough (I : Instance jobs machines) (k : ℕ) :
    FinitePrimalDual (PrimalVar jobs machines) (I.EligiblePairThrough k) where
  coeff v q :=
    match v with
    | Sum.inl j => if j = q.1.1.2 then I.load q.1.1.1 j else 0
    | Sum.inr i => if i = q.1.1.1 then 1 else 0
  rhs _ := 1
  cost _ := 1

/-- Every prefix LP inherits the covering/packing nonnegativity data. -/
theorem lpThrough_isCoveringPacking (I : Instance jobs machines) (k : ℕ) :
    (I.lpThrough k).IsCoveringPacking where
  coeff_nonneg := fun v q ↦ by
    rcases v with j | i
    · change 0 ≤ (if j = q.1.1.2 then I.load q.1.1.1 j else 0)
      split
      · exact I.load_nonneg _ _
      · norm_num
    · change 0 ≤ (if i = q.1.1.1 then 1 else 0)
      split <;> norm_num
  rhs_nonneg := by
    intro q
    change 0 ≤ (1 : ℝ)
    norm_num
  cost_nonneg := by
    intro v
    change 0 ≤ (1 : ℝ)
    norm_num

/--
The complete mutable state of the load-balancing algorithm. `weight` is `x`,
`slack` is `z`, and `dual` is the sparse 0/1 vector `y` produced by assigning
a job. `failedAt` stores the first job at which a phase fails.
-/
structure State (jobs machines : ℕ) where
  weight : Fin machines → ℝ
  assignment : Fin jobs → Option (Fin machines)
  slack : Fin jobs → ℝ
  dual : Fin jobs → Fin machines → ℝ
  failedAt : Option (Fin jobs)

/-- The tutorial initialization `x(j) = 1 / (2m)`, with all other variables zero. -/
def initialState (_I : Instance jobs machines) : State jobs machines where
  weight _ := 1 / (2 * (machines : ℝ))
  assignment _ := none
  slack _ := 0
  dual _ _ := 0
  failedAt := none

/-- The first explicit failure condition: the arriving job has no eligible machine. -/
def noEligibleMachine (I : Instance jobs machines) (i : Fin jobs) : Prop :=
  I.eligible i = ∅

/-- The second explicit failure condition: some current machine weight exceeds one. -/
def hasOverweightMachine (_I : Instance jobs machines) (s : State jobs machines) : Prop :=
  ∃ j, 1 < s.weight j

/-- Exactly the disjunction tested in Step (1) of the source algorithm. -/
def failureCondition (I : Instance jobs machines) (s : State jobs machines)
    (i : Fin jobs) : Prop :=
  I.noEligibleMachine i ∨ I.hasOverweightMachine s

/--
The eligible machine minimizing `load(i,j) * x(j)`. Machines are sorted by
their natural `Fin` order before `argmin`, so ties are broken deterministically.
-/
def chooseMachine (I : Instance jobs machines) (s : State jobs machines)
    (i : Fin jobs) : Option (Fin machines) :=
  ((I.eligible i).sort (· ≤ ·)).argmin fun j ↦ I.load i j * s.weight j

/-- The source predicate characterizing a valid choice, independent of tie-breaking. -/
def IsMinimumChoice (I : Instance jobs machines) (s : State jobs machines)
    (i : Fin jobs) (j : Fin machines) : Prop :=
  j ∈ I.eligible i ∧
    ∀ k ∈ I.eligible i, I.load i j * s.weight j ≤ I.load i k * s.weight k

theorem chooseMachine_spec (I : Instance jobs machines)
    {s : State jobs machines} {i : Fin jobs} {j : Fin machines}
    (h : I.chooseMachine s i = some j) : I.IsMinimumChoice s i j := by
  have hjarg : j ∈ ((I.eligible i).sort (· ≤ ·)).argmin
      (fun k ↦ I.load i k * s.weight k) := h
  constructor
  · have hjlist := List.argmin_mem hjarg
    exact ((I.eligible i).mem_sort (· ≤ ·)).1 hjlist
  · intro k hk
    apply List.le_of_mem_argmin (m := j)
    · exact ((I.eligible i).mem_sort (· ≤ ·)).2 hk
    · exact hjarg

/--
One deterministic transition of the normalized algorithm. A prior failure is
absorbing. Otherwise Step (1) is checked, then the selected machine `ell`
receives the job and the source updates are applied:

`z(i) = 1 - load(i,ell) * x(ell)`, `y(i,ell) = 1`, and
`x(ell) := x(ell) * (1 + load(i,ell) / 2)`.
-/
def step (I : Instance jobs machines) (s : State jobs machines)
    (i : Fin jobs) : State jobs machines := by
  classical
  exact
    match s.failedAt with
    | some _ => s
    | none =>
        if I.failureCondition s i then
          { s with failedAt := some i }
        else
          match I.chooseMachine s i with
          | none => { s with failedAt := some i }
          | some ell =>
              let p := I.load i ell
              let oldWeight := s.weight ell
              { weight := Function.update s.weight ell (oldWeight * (1 + p / 2))
                assignment := Function.update s.assignment i (some ell)
                slack := Function.update s.slack i (1 - p * oldWeight)
                dual := Function.update s.dual i (Function.update (s.dual i) ell 1)
                failedAt := none }

/--
The load-balancing transition as a reusable causal online process. The decision is
the assigned machine when the arrival succeeds and `none` when the phase has
failed; the detailed first-failure witness remains in the state.
-/
def process (I : Instance jobs machines) :
    Online.Process (Fin jobs) (State jobs machines) (Option (Fin machines)) where
  initial := I.initialState
  step s i :=
    let next := I.step s i
    (next, next.assignment i)

/-- The arrival list `0, ..., jobs - 1`. -/
def arrivals (_I : Instance jobs machines) : List (Fin jobs) :=
  List.ofFn id

/-- State after processing the first `k` arrivals (or after the first earlier failure). -/
def runPrefix (I : Instance jobs machines) (k : ℕ) : State jobs machines :=
  I.process.stateAfter (I.arrivals.take k)

/-- Final state after the finite arrival sequence. -/
def finalState (I : Instance jobs machines) : State jobs machines :=
  I.runPrefix jobs

/-- The algorithm's phase did not encounter either failure condition. -/
def Succeeded (I : Instance jobs machines) : Prop :=
  I.finalState.failedAt = none

/-- Every arriving job received an irrevocable machine assignment. -/
def AssignsAll (I : Instance jobs machines) : Prop :=
  ∀ i, ∃ j, I.finalState.assignment i = some j

/-- Total normalized load recorded by a state on machine `j`. -/
def stateAssignedLoad (I : Instance jobs machines) (s : State jobs machines)
    (j : Fin machines) : ℝ :=
  ∑ i, if s.assignment i = some j then I.load i j else 0

/-- Normalized load assigned to machine `j` after the first `k` arrivals. -/
def assignedLoadThrough (I : Instance jobs machines) (k : ℕ) (j : Fin machines) : ℝ :=
  I.stateAssignedLoad (I.runPrefix k) j

/-- Total normalized load assigned by the final phase state to machine `j`. -/
def assignedLoad (I : Instance jobs machines) (j : Fin machines) : ℝ :=
  I.stateAssignedLoad I.finalState j

/-- Turn a state `(x,z)` into the primal vector of `I.lp`. -/
def primalVector (_I : Instance jobs machines) (s : State jobs machines) :
    PrimalVar jobs machines → ℝ
  | Sum.inl j => s.weight j
  | Sum.inr i => s.slack i

/-- Turn the algorithm's rectangular `y` array into the dual vector on eligible pairs. -/
def algorithmDualVector (I : Instance jobs machines) (s : State jobs machines) :
    I.EligiblePair → ℝ :=
  fun q ↦ s.dual q.1.1 q.1.2

/-- Restrict a full dual vector to the constraints present in prefix `k`. -/
def restrictDual (I : Instance jobs machines) (y : I.EligiblePair → ℝ) (k : ℕ) :
    I.EligiblePairThrough k → ℝ :=
  fun q ↦ y q.1

/-- The total dual mass placed on eligible machines for one job. -/
def jobDualMass (I : Instance jobs machines) (y : I.EligiblePair → ℝ)
    (i : Fin jobs) : ℝ :=
  ∑ q, if q.1.1 = i then y q else 0

/--
The premise “a feasible dual solution assigning all jobs” used by the
load-balancing guarantee.
The first conjunct uses the shared finite-LP interface; the second says every
job constraint is tight at value one, equivalently giving dual objective
`jobs` in this unit-right-hand-side LP.
-/
def DualAssignsAll (I : Instance jobs machines) (y : I.EligiblePair → ℝ) : Prop :=
  I.lp.DualFeasible y ∧ ∀ i, I.jobDualMass y i = 1

/-- Primal feasibility for the shared finite covering LP of the first `k` arrivals. -/
def PrimalFeasibleThrough (I : Instance jobs machines) (k : ℕ)
    (s : State jobs machines) : Prop :=
  (I.lpThrough k).PrimalFeasible (I.primalVector s)

/--
The shared finite-LP primal objective for prefix `k`. Along `runPrefix k`, all
future slack coordinates remain zero, so this is exactly the source objective
containing the machine weights and the first `k` job slacks.
-/
def primalObjectiveThrough (I : Instance jobs machines) (k : ℕ)
    (s : State jobs machines) : ℝ :=
  (I.lpThrough k).primalObjective (I.primalVector s)

/-- Exact logarithmic bound proved in the source, replacing its asymptotic notation. -/
def logarithmicLoadBound (_I : Instance jobs machines) : ℝ :=
  Real.log (3 * (machines : ℝ)) / Real.log ((3 : ℝ) / 2)

end Instance
end
end UnrelatedMachines
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, Chapter 8, pp. 193--196; normalized loads and eligibility on p. 194, Figure 8.1 on p. 194, and the load-balancing algorithm on p. 195.
Read-back

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

  1. Instance. For explicit natural numbers jobs=n\mathit{jobs}=njobs=n and machines=m\mathit{machines}=mmachines=m, an Instance n m consists of a proof that 0<m0<m0<m, a total function p:Fin⁡(n)→Fin⁡(m)→Rp:\operatorname{Fin}(n)\to\operatorname{Fin}(m)\to\mathbb Rp:Fin(n)→Fin(m)→R, and a proof that 0≤pij0\le p_{ij}0≤pij​ for every job iii and machine jjj. Thus nnn may be zero, in which case the load function and its nonnegativity condition have empty job domain; an inhabitant cannot exist when m=0m=0m=0 because it would contain a proof of 0<00<00<0. No upper bound on a load is included.

  2. eligible. For implicit natural numbers n,mn,mn,m, an instance III with 0<m0<m0<m and nonnegative total load function pijp_{ij}pij​, and a job i∈Fin⁡(n)i\in\operatorname{Fin}(n)i∈Fin(n), eligible I i is the finite set Ei={j∈Fin⁡(m)∣pij≤1}E_i=\{j\in\operatorname{Fin}(m)\mid p_{ij}\le1\}Ei​={j∈Fin(m)∣pij​≤1}. Because the instance separately guarantees pij≥0p_{ij}\ge0pij​≥0, these are exactly the machines with 0≤pij≤10\le p_{ij}\le10≤pij​≤1; the set may be empty despite m>0m>0m>0. If n=0n=0n=0, there is no value of iii at which to evaluate this function.

  3. mem_eligible_iff. For implicit natural numbers n,mn,mn,m, every instance III with 0<m0<m0<m and nonnegative loads, every i∈Fin⁡(n)i\in\operatorname{Fin}(n)i∈Fin(n), and every j∈Fin⁡(m)j\in\operatorname{Fin}(m)j∈Fin(m), the theorem asserts the exact equivalence j∈I.eligible(i)  ⟺  pij≤1j\in I.\mathrm{eligible}(i)\iff p_{ij}\le1j∈I.eligible(i)⟺pij​≤1, with no additional hypothesis. An instantiation has no possible job argument when n=0n=0n=0, and no instance exists when m=0m=0m=0.

  4. EligiblePair. For implicit natural numbers n,mn,mn,m and an instance III, I.EligiblePair is the subtype of pairs (i,j)∈Fin⁡(n)×Fin⁡(m)(i,j)\in\operatorname{Fin}(n)\times\operatorname{Fin}(m)(i,j)∈Fin(n)×Fin(m) equipped with a proof that j∈I.eligible(i)j\in I.\mathrm{eligible}(i)j∈I.eligible(i), equivalently a proof that pij≤1p_{ij}\le1pij​≤1. The type is empty when n=0n=0n=0 and may also be empty when every job-machine load exceeds 111; the instance itself forces m>0m>0m>0.

  5. EligiblePairThrough. For implicit natural numbers n,mn,mn,m, an instance III, and any natural number kkk, I.EligiblePairThrough k is the subtype of eligible pairs (i,j)(i,j)(i,j) additionally equipped with the condition that the natural value of iii is less than kkk. It is empty for k=0k=0k=0 or n=0n=0n=0; if k≥nk\ge nk≥n, it contains every eligible pair, and values of kkk beyond nnn introduce no extra jobs because job indices remain in Fin⁡(n)\operatorname{Fin}(n)Fin(n).

  6. PrimalVar. For explicit natural numbers n,mn,mn,m, PrimalVar n m is the disjoint sum Fin⁡(m)⊔Fin⁡(n)\operatorname{Fin}(m)\sqcup\operatorname{Fin}(n)Fin(m)⊔Fin(n): every value is either a machine-tagged index or a job-tagged index. This declaration has no positivity assumption; if m=0m=0m=0 the machine side is empty, if n=0n=0n=0 the job side is empty, and if both are zero the whole type is empty.

  7. lp. For implicit natural numbers n,mn,mn,m and an instance III with loads pij≥0p_{ij}\ge0pij​≥0 and m>0m>0m>0, I.lp is finite primal-dual data whose primal-coordinate type is Fin⁡(m)⊔Fin⁡(n)\operatorname{Fin}(m)\sqcup\operatorname{Fin}(n)Fin(m)⊔Fin(n) and whose constraint/dual-coordinate type is the eligible pairs E={(i,j)∣pij≤1}E=\{(i,j)\mid p_{ij}\le1\}E={(i,j)∣pij​≤1}. For a constraint q=(i,j)∈Eq=(i,j)\in Eq=(i,j)∈E, the coefficient of a machine coordinate j′j'j′ is pij′p_{ij'}pij′​ when j′=jj'=jj′=j and 000 otherwise, while the coefficient of a job coordinate i′i'i′ is 111 when i′=ii'=ii′=i and 000 otherwise; every right-hand side and every cost is 111. Under the imported finite-LP operations, this yields primal objective ∑jxj+∑izi\sum_jx_j+\sum_i z_i∑j​xj​+∑i​zi​, primal constraint pijxj+zi≥1p_{ij}x_j+z_i\ge1pij​xj​+zi​≥1 for each (i,j)∈E(i,j)\in E(i,j)∈E, dual objective ∑(i,j)∈Eyij\sum_{(i,j)\in E}y_{ij}∑(i,j)∈E​yij​, machine constraint ∑i:(i,j)∈Epijyij≤1\sum_{i:(i,j)\in E}p_{ij}y_{ij}\le1∑i:(i,j)∈E​pij​yij​≤1, and job constraint ∑j:(i,j)∈Eyij≤1\sum_{j:(i,j)\in E}y_{ij}\le1∑j:(i,j)∈E​yij​≤1 when the corresponding feasibility predicates are invoked; the declaration itself supplies the coefficients, right sides, and costs rather than asserting feasibility. If n=0n=0n=0, or if there are no eligible pairs, the constraint and dual-variable type is empty, while the mmm machine coordinates and their unit costs remain.

  8. lp_isCoveringPacking. For implicit natural numbers n,mn,mn,m and every instance III, the theorem supplies the imported IsCoveringPacking proposition for I.lp: for every primal coordinate vvv and eligible constraint qqq, its coefficient is nonnegative; every eligible constraint has nonnegative right-hand side; and every primal coordinate has nonnegative cost. Concretely, the coefficients are either a nonnegative load pijp_{ij}pij​, 111, or 000, and all right sides and costs are 111. If the eligible-pair type is empty, the coefficient and right-side assertions are vacuous; if n=0n=0n=0, the remaining machine-coordinate cost assertions still say 0≤10\le10≤1. It asserts no feasibility, optimality, or duality conclusion.

  9. lpThrough. For implicit natural numbers n,mn,mn,m, an instance III, and any k∈Nk\in\mathbb Nk∈N, I.lpThrough k has all machine and all job primal coordinates Fin⁡(m)⊔Fin⁡(n)\operatorname{Fin}(m)\sqcup\operatorname{Fin}(n)Fin(m)⊔Fin(n) but only constraints (i,j)(i,j)(i,j) satisfying both pij≤1p_{ij}\le1pij​≤1 and i<ki<ki<k. At such a constraint, a machine coordinate j′j'j′ has coefficient pij′p_{ij'}pij′​ if j′=jj'=jj′=j and 000 otherwise, a job coordinate i′i'i′ has coefficient 111 if i′=ii'=ii′=i and 000 otherwise, and every right-hand side and every cost is 111. Hence its primal constraints are pijxj+zi≥1p_{ij}x_j+z_i\ge1pij​xj​+zi​≥1 only for eligible pairs with i<ki<ki<k, while its objective still includes every machine coordinate and every job coordinate. For k=0k=0k=0 there are no constraints; for k≥nk\ge nk≥n this has all eligible constraints; k>nk>nk>n is silently truncated by the finite job type, and n=0n=0n=0 gives no constraints.

  10. lpThrough_isCoveringPacking. For implicit natural numbers n,mn,mn,m, every instance III, and every unrestricted k∈Nk\in\mathbb Nk∈N, the theorem asserts that every coefficient, right-hand side, and cost in I.lpThrough k is nonnegative. The coefficients are precisely nonnegative loads, 111, or 000, and every right side and cost is 111. When k=0k=0k=0, n=0n=0n=0, or the relevant jobs have no eligible pairs, the coefficient and right-side portions may be vacuous, while nonnegativity of the costs of all machine and job coordinates remains; no feasibility or optimization assertion is included.

  11. State. For explicit natural numbers n,mn,mn,m, a State n m contains total functions weight:Fin⁡(m)→R\mathrm{weight}:\operatorname{Fin}(m)\to\mathbb Rweight:Fin(m)→R, assignment:Fin⁡(n)→Option⁡(Fin⁡(m))\mathrm{assignment}:\operatorname{Fin}(n)\to\operatorname{Option}(\operatorname{Fin}(m))assignment:Fin(n)→Option(Fin(m)), slack:Fin⁡(n)→R\mathrm{slack}:\operatorname{Fin}(n)\to\mathbb Rslack:Fin(n)→R, and dual:Fin⁡(n)→Fin⁡(m)→R\mathrm{dual}:\operatorname{Fin}(n)\to\operatorname{Fin}(m)\to\mathbb Rdual:Fin(n)→Fin(m)→R, together with failedAt∈Option⁡(Fin⁡(n))\mathrm{failedAt}\in\operatorname{Option}(\operatorname{Fin}(n))failedAt∈Option(Fin(n)). No invariant requires weights, slacks, or dual values to be nonnegative, assignments to be eligible, or failedAt to be the first failure. The functions also have values for every unprocessed index whenever their domains are nonempty. If n=0n=0n=0, all job-indexed functions have empty domain and failedAt can only be none; if m=0m=0m=0, weights and each dual row have empty domain and every assignment must be none.

  12. initialState. For implicit natural numbers n,mn,mn,m and an explicit instance argument III—whose load data are unused but whose field proves m>0m>0m>0—I.initialState assigns every machine weight the value 1/(2m)1/(2m)1/(2m), every job assignment none, every job slack 000, every job-machine dual entry 000, and failedAt = none. Real division is a total operation, and here the denominator is nonzero because m>0m>0m>0. If n=0n=0n=0, the assignment, slack, and dual clauses are functions on an empty job domain.

  13. noEligibleMachine. For implicit natural numbers n,mn,mn,m, an instance III, and a job i∈Fin⁡(n)i\in\operatorname{Fin}(n)i∈Fin(n), I.noEligibleMachine i is the proposition that {j∣pij≤1}=∅\{j\mid p_{ij}\le1\}=\varnothing{j∣pij​≤1}=∅, equivalently that no machine has load at most 111 for job iii. The instance guarantees m>0m>0m>0, so this can hold even though machines exist. If n=0n=0n=0, there is no job argument at which the predicate can be formed.

  14. hasOverweightMachine. For implicit natural numbers n,mn,mn,m, an instance argument III and an arbitrary state sss, I.hasOverweightMachine s is the proposition ∃j∈Fin⁡(m), 1<s.weight(j)\exists j\in\operatorname{Fin}(m),\ 1<s.\mathrm{weight}(j)∃j∈Fin(m), 1<s.weight(j). The load, assignments, slack, dual array, and failure marker are ignored; the instance argument contributes only its indexing and the fact m>0m>0m>0. No reachability or nonnegativity assumption is imposed on sss.

  15. failureCondition. For implicit natural numbers n,mn,mn,m, an instance III, arbitrary state sss, and job i∈Fin⁡(n)i\in\operatorname{Fin}(n)i∈Fin(n), I.failureCondition s i is exactly the inclusive disjunction that either no jjj satisfies pij≤1p_{ij}\le1pij​≤1, or there exists a machine jjj with s.weight(j)>1s.\mathrm{weight}(j)>1s.weight(j)>1. It does not inspect s.failedAt, assignments, slacks, or dual values and adds no other failure case.

  16. chooseMachine. For implicit natural numbers n,mn,mn,m, an instance III, arbitrary state sss, and job iii, I.chooseMachine s i sorts the finite eligible set {j∣pij≤1}\{j\mid p_{ij}\le1\}{j∣pij​≤1} by the natural order on Fin⁡(m)\operatorname{Fin}(m)Fin(m) and applies list argmin to the real-valued score j↦pijs.weight(j)j\mapsto p_{ij}s.\mathrm{weight}(j)j↦pij​s.weight(j). It returns none when the eligible list is empty and otherwise returns the deterministic element selected as a minimum from that ordered list; ties require no uniqueness and are resolved by the library operation on the sorted list. The definition does not inspect failedAt and assumes no sign condition on the arbitrary state's weights.

  17. IsMinimumChoice. For implicit natural numbers n,mn,mn,m, an instance III, arbitrary state sss, job iii, and machine jjj, I.IsMinimumChoice s i j is the conjunction pij≤1p_{ij}\le1pij​≤1 and, for every machine kkk, the implication pik≤1⇒pijs.weight(j)≤piks.weight(k)p_{ik}\le1\Rightarrow p_{ij}s.\mathrm{weight}(j)\le p_{ik}s.\mathrm{weight}(k)pik​≤1⇒pij​s.weight(j)≤pik​s.weight(k). It asserts eligibility and weak minimality only; it does not assert uniqueness, a particular tie-breaking outcome, absence of failure, or that jjj was actually returned by chooseMachine.

  18. chooseMachine_spec. For implicit natural numbers n,mn,mn,m, every instance III, every implicit arbitrary state sss, job iii, and machine jjj, and the hypothesis I.chooseMachine s i = some j, the theorem concludes that pij≤1p_{ij}\le1pij​≤1 and that pijs.weight(j)≤piks.weight(k)p_{ij}s.\mathrm{weight}(j)\le p_{ik}s.\mathrm{weight}(k)pij​s.weight(j)≤pik​s.weight(k) for every kkk with pik≤1p_{ik}\le1pik​≤1. If the eligible set is empty, the hypothesis cannot hold. The theorem has no assumption about s.failedAt, reachability, weight signs, uniqueness, or tie order, and it asserts only this one implication.

  19. step. For implicit natural numbers n,mn,mn,m, an instance III, any state sss, and any job iii, I.step s i is a total deterministic state transition with these exact branches. If s.failedAt = some f for any job fff, it returns sss unchanged without testing iii. If s.failedAt = none and either iii has no machine with pij≤1p_{ij}\le1pij​≤1 or some current weight exceeds 111, it changes only failedAt to some i. Otherwise it invokes chooseMachine; if that unexpectedly returns none, it again changes only failedAt to some i. If it returns some ell, writing p=piℓp=p_{i\ell}p=piℓ​ and w=s.weight(ℓ)w=s.\mathrm{weight}(\ell)w=s.weight(ℓ), the result changes only machine ℓ\ellℓ's weight to w(1+p/2)w(1+p/2)w(1+p/2), job iii's assignment to some ell, job iii's slack to 1−pw1-pw1−pw, and dual entry (i,ℓ)(i,\ell)(i,ℓ) to 111, preserves every other weight, assignment, slack, and dual entry—including all other entries in row iii—and sets failedAt to none. Because the input state and arrival are arbitrary, repeated or out-of-order calls can overwrite the named assignment and slack, and no invariant on prior state values is assumed; when n=0n=0n=0 there is no job value with which to call the transition.

  20. process. For implicit natural numbers n,mn,mn,m and an instance III, I.process is an online-process record with request type Fin⁡(n)\operatorname{Fin}(n)Fin(n), state type State n m, and decision type Option⁡(Fin⁡(m))\operatorname{Option}(\operatorname{Fin}(m))Option(Fin(m)). Its designated initial state is I.initialState; on any current state sss and request iii, it computes s′=I.step(s,i)s'=I.\mathrm{step}(s,i)s′=I.step(s,i) and returns the pair (s′,s′.assignment(i))(s',s'.\mathrm{assignment}(i))(s′,s′.assignment(i)). Thus the emitted decision is the post-transition assignment entry, even on a failure or already-failed arbitrary state, so it is not definitionally forced to be none if that state already stored some j. The step is total for every state and valid request and can be fed repeated or out-of-order request lists; if n=0n=0n=0, the request type has no values.

  21. arrivals. For implicit natural numbers n,mn,mn,m and an explicit instance argument III that is otherwise unused, I.arrivals is List.ofFn id, namely the length-nnn list of all elements of Fin⁡(n)\operatorname{Fin}(n)Fin(n) in order 0,1,…,n−10,1,\ldots,n-10,1,…,n−1. It is empty when n=0n=0n=0; the instance guarantees m>0m>0m>0 but neither its loads nor its machines affect the list.

  22. runPrefix. For implicit natural numbers n,mn,mn,m, an instance III, and any k∈Nk\in\mathbb Nk∈N, I.runPrefix k starts at I.initialState and processes, from left to right, the first kkk entries of the list 0,1,…,n−10,1,\ldots,n-10,1,…,n−1, retaining the state component of each I.process transition. Because list take truncates, exactly the first min⁡(k,n)\min(k,n)min(k,n) arrivals are used: k=0k=0k=0 returns the initial state, and every k≥nk\ge nk≥n processes the whole list. If a transition records a failure, every subsequent transition returns that state unchanged because failure is absorbing. When n=0n=0n=0, every prefix is the initial state.

  23. finalState. For implicit natural numbers n,mn,mn,m and an instance III, I.finalState is I.runPrefix n, hence the state obtained from the designated initial state after processing the entire list 0,1,…,n−10,1,\ldots,n-10,1,…,n−1. If a job records a failure, this is the unchanged absorbing state from that first failure onward; if n=0n=0n=0, it is exactly the initial state.

  24. Succeeded. For implicit natural numbers n,mn,mn,m and an instance III, I.Succeeded is solely the proposition I.finalState.failedAt = none. It adds no explicit claim about assignments, eligibility, primal or dual feasibility, weights, or loads. When n=0n=0n=0, the final state is initial and this equality holds.

  25. AssignsAll. For implicit natural numbers n,mn,mn,m and an instance III, I.AssignsAll is the proposition that for every i∈Fin⁡(n)i\in\operatorname{Fin}(n)i∈Fin(n) there exists a j∈Fin⁡(m)j\in\operatorname{Fin}(m)j∈Fin(m) such that I.finalState.assignment i = some j. It does not separately require Succeeded, eligibility of the stored machine, or any load bound. The assertion is vacuously true when n=0n=0n=0; an instance always has m>0m>0m>0.

  26. stateAssignedLoad. For implicit natural numbers n,mn,mn,m, an instance III, an arbitrary state sss, and a machine jjj, I.stateAssignedLoad s j is the finite sum ∑i∈Fin⁡(n)(if s.assignment(i)=some(j) then pij else 0)\sum_{i\in\operatorname{Fin}(n)}\bigl(\text{if }s.\mathrm{assignment}(i)=\mathrm{some}(j)\text{ then }p_{ij}\text{ else }0\bigr)∑i∈Fin(n)​(if s.assignment(i)=some(j) then pij​ else 0). It ignores weights, slacks, dual values, and failedAt, and it neither requires sss to be reachable nor checks that stored assignments are eligible. The empty-job sum is 000.

  27. assignedLoadThrough. For implicit natural numbers n,mn,mn,m, an instance III, any k∈Nk\in\mathbb Nk∈N, and a machine jjj, I.assignedLoadThrough k j is ∑i(if (I.runPrefix(k)).assignment(i)=some(j) then pij else 0)\sum_i\bigl(\text{if }(I.\mathrm{runPrefix}(k)).\mathrm{assignment}(i)=\mathrm{some}(j)\text{ then }p_{ij}\text{ else }0\bigr)∑i​(if (I.runPrefix(k)).assignment(i)=some(j) then pij​ else 0), where runPrefix k processes only the first min⁡(k,n)\min(k,n)min(k,n) canonical arrivals and freezes at any earlier failure. The sum itself ranges over all jobs, including indices not below kkk, and relies on the stored state values to select terms. It is 000 for k=0k=0k=0 and for n=0n=0n=0, and for every k≥nk\ge nk≥n it uses the final state.

  28. assignedLoad. For implicit natural numbers n,mn,mn,m, an instance III, and a machine jjj, I.assignedLoad j is ∑i(if I.finalState.assignment(i)=some(j) then pij else 0)\sum_i\bigl(\text{if }I.\mathrm{finalState}.\mathrm{assignment}(i)=\mathrm{some}(j)\text{ then }p_{ij}\text{ else }0\bigr)∑i​(if I.finalState.assignment(i)=some(j) then pij​ else 0). If the canonical run fails, assignments stored before the absorbing failure still contribute and unassigned jobs do not; no success or eligibility premise is imposed. The value is 000 when n=0n=0n=0.

  29. primalVector. For implicit natural numbers n,mn,mn,m, an explicit instance argument III whose data are otherwise unused, and any state sss, I.primalVector s is the total real vector on Fin⁡(m)⊔Fin⁡(n)\operatorname{Fin}(m)\sqcup\operatorname{Fin}(n)Fin(m)⊔Fin(n) that sends a machine-tagged coordinate jjj to s.weight(j)s.\mathrm{weight}(j)s.weight(j) and a job-tagged coordinate iii to s.slack(i)s.\mathrm{slack}(i)s.slack(i). Assignments, dual entries, and failedAt are discarded, and no nonnegativity or reachability property is asserted. If n=0n=0n=0, there are no job-tagged coordinates.

  30. algorithmDualVector. For implicit natural numbers n,mn,mn,m, an instance III, and any state sss, I.algorithmDualVector s is the total real function on eligible pairs: at an eligible pair q=(i,j)q=(i,j)q=(i,j), including its proof that pij≤1p_{ij}\le1pij​≤1, it returns the rectangular-array entry s.dual(i,j)s.\mathrm{dual}(i,j)s.dual(i,j). The eligibility proof does not affect the value, ineligible array entries are absent from the output domain rather than set to zero, and no sign, feasibility, assignment, or reachability condition is imposed. The domain is empty when n=0n=0n=0 or when no pair is eligible.

  31. restrictDual. For implicit natural numbers n,mn,mn,m, an instance III, any full function yyy from eligible pairs to R\mathbb RR, and any k∈Nk\in\mathbb Nk∈N, I.restrictDual y k is the function on eligible pairs (i,j)(i,j)(i,j) with i<ki<ki<k that returns exactly y(i,j)y(i,j)y(i,j) after forgetting the additional prefix proof. It changes no values and imposes no feasibility condition. Its domain is empty for k=0k=0k=0; for k≥nk\ge nk≥n it contains every eligible pair, and n=0n=0n=0 makes both domains empty.

  32. jobDualMass. For implicit natural numbers n,mn,mn,m, an instance III, any real function yyy on eligible pairs, and a job iii, I.jobDualMass y i is the sum over every eligible pair q=(i′,j)q=(i',j)q=(i′,j) of y(q)y(q)y(q) when i′=ii'=ii′=i and 000 otherwise, equivalently ∑j:pij≤1yij\sum_{j:p_{ij}\le1}y_{ij}∑j:pij​≤1​yij​. No nonnegativity or feasibility assumption is made. If job iii has no eligible machine, the value is the empty sum 000; if n=0n=0n=0, there is no job argument.

  33. DualAssignsAll. For implicit natural numbers n,mn,mn,m, an instance III, and a real function yyy on eligible pairs E={(i,j)∣pij≤1}E=\{(i,j)\mid p_{ij}\le1\}E={(i,j)∣pij​≤1}, I.DualAssignsAll y is the conjunction of the fully expanded conditions: yij≥0y_{ij}\ge0yij​≥0 for every (i,j)∈E(i,j)\in E(i,j)∈E; ∑i:(i,j)∈Epijyij≤1\sum_{i:(i,j)\in E}p_{ij}y_{ij}\le1∑i:(i,j)∈E​pij​yij​≤1 for every machine jjj; ∑j:(i,j)∈Eyij≤1\sum_{j:(i,j)\in E}y_{ij}\le1∑j:(i,j)∈E​yij​≤1 for every job iii; and, additionally, ∑j:(i,j)∈Eyij=1\sum_{j:(i,j)\in E}y_{ij}=1∑j:(i,j)∈E​yij​=1 for every job iii. There are no values for ineligible pairs. If any existing job has no eligible machine, its required equality is the impossible equation 0=10=10=1; if n=0n=0n=0, the eligible domain and all job conditions are empty, while every machine condition is 0≤10\le10≤1, so the predicate holds for the unique empty-domain function.

  34. PrimalFeasibleThrough. For implicit natural numbers n,mn,mn,m, an instance III, any k∈Nk\in\mathbb Nk∈N, and any state sss, I.PrimalFeasibleThrough k s is exactly the conjunction that s.weight(j)≥0s.\mathrm{weight}(j)\ge0s.weight(j)≥0 for every machine jjj, s.slack(i)≥0s.\mathrm{slack}(i)\ge0s.slack(i)≥0 for every job iii, and 1≤pijs.weight(j)+s.slack(i)1\le p_{ij}s.\mathrm{weight}(j)+s.\mathrm{slack}(i)1≤pij​s.weight(j)+s.slack(i) for every pair with pij≤1p_{ij}\le1pij​≤1 and i<ki<ki<k. All job slacks, including those whose indices are not below kkk, are subject to nonnegativity, while only prefix eligible pairs generate covering constraints; assignments, dual entries, and failure status are ignored. For k=0k=0k=0 the covering constraints are vacuous but coordinate nonnegativity remains; for k≥nk\ge nk≥n all eligible constraints are included, and when n=0n=0n=0 only machine-weight nonnegativity remains.

  35. primalObjectiveThrough. For implicit natural numbers n,mn,mn,m, an instance III, any k∈Nk\in\mathbb Nk∈N, and any state sss, I.primalObjectiveThrough k s is the imported finite-LP objective ∑js.weight(j)+∑is.slack(i)\sum_j s.\mathrm{weight}(j)+\sum_i s.\mathrm{slack}(i)∑j​s.weight(j)+∑i​s.slack(i) because every machine and job coordinate has unit cost. Despite the parameter kkk, the value includes every job slack and is definitionally independent of which prefix constraints exist; no feasibility, nonnegativity, reachability, or success assumption is imposed. For n=0n=0n=0 the job sum is 000, and the same objective is used even at k=0k=0k=0 or k>nk>nk>n.

  36. logarithmicLoadBound. For implicit natural numbers n,mn,mn,m and an explicit instance argument III whose loads and job count are unused, I.logarithmicLoadBound is the exact real number log⁡(3m)/log⁡(3/2)\log(3m)/\log(3/2)log(3m)/log(3/2), with mmm coerced from N\mathbb NN to R\mathbb RR. The instance guarantees m>0m>0m>0, so 3m>03m>03m>0, and log⁡(3/2)>0\log(3/2)>0log(3/2)>0 is nonzero; real logarithm and division are total operations in any case. The value has no rounding, ceiling, asymptotic qualification, or dependence on nnn, so n=0n=0n=0 leaves it unchanged.

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