Preprocessing an interval scheduling instance down to a bounded number of live jobs
Lax470956.Preprocessing · concepts/Lax470956/Preprocessing.lean · lax-470956
No public endorsements yet.
Loading review…
Sign in with ORCIDNatural Language Statement
Definition
The step that makes the dynamic program fixed-parameter tractable. Two jobs with the same processing time and the same deadline occupy the same interval, so on any one machine they are interchangeable; of the jobs sharing an interval and eligible on a given machine, only the heaviest can ever be useful, because a schedule places at most of them at once and a lighter one can always be exchanged for a heavier unused one. Keeping, for each machine, the best jobs of each interval eligible there, and discarding the rest, leaves the optimum unchanged.
What the step buys is a bound independent of the number of jobs. A job alive at time has a deadline in and a processing time in , so there are at most intervals it could occupy; each interval keeps at most jobs per machine and there are machines. So at most surviving jobs are alive at any one instant — a bound in the parameter alone. Fed into the state-space bound of the dynamic program, this makes the table's size a function of and .
Concept map
Evidence
Lean source view on GitHub
| 1 | import Lax470956.DynamicProgram |
| 2 | |
| 3 | /-! |
| 4 | --- |
| 5 | title: Preprocessing an interval scheduling instance down to a bounded number of live jobs |
| 6 | type: definition |
| 7 | --- |
| 8 | The step that makes the dynamic program fixed-parameter tractable. Two jobs with the |
| 9 | same processing time and the same deadline occupy the same interval, so on any one |
| 10 | machine they are interchangeable; of the jobs sharing an interval and eligible on a |
| 11 | given machine, only the heaviest can ever be useful, because a schedule places at |
| 12 | most of them at once and a lighter one can always be exchanged for a heavier unused |
| 13 | one. Keeping, for each machine, the best jobs of each interval eligible there, and |
| 14 | discarding the rest, leaves the optimum unchanged. |
| 15 | |
| 16 | What the step buys is a bound independent of the number of jobs. A job alive at time |
| 17 | has a deadline in and a processing time in , so there |
| 18 | are at most intervals it could occupy; each interval keeps at most jobs |
| 19 | per machine and there are machines. So at most surviving jobs are |
| 20 | alive at any one instant — a bound in the parameter alone. Fed into the state-space |
| 21 | bound of the dynamic program, this makes the table's size a function of and . |
| 22 | |
| 23 | # Formalization notes |
| 24 | |
| 25 | Discarding is modelled as a set of kept jobs together with the best weight achievable |
| 26 | using only those, rather than as a second instance on a smaller job set. The two say the |
| 27 | same thing, and the first states it without transporting an instance along a change of |
| 28 | index type — which would make the statement about the transport as much as about the |
| 29 | preprocessing. |
| 30 | |
| 31 | Ties in weight are broken by the job's index. "The best" has to be well defined, and |
| 32 | some tie-break is needed to define it; the index is the tie-break a program would use, |
| 33 | since it is the order the jobs arrive in. `Better` is the resulting strict linear order: |
| 34 | heavier, or equally heavy and earlier. |
| 35 | |
| 36 | A job is kept when it is among the best *for some machine it is eligible on*, not |
| 37 | for all of them. The exchange argument needs this: a job is discarded only when every machine that could run |
| 38 | it already keeps better alternatives for its interval. It is also why the bound counts |
| 39 | machines twice. |
| 40 | -/ |
| 41 | |
| 42 | namespace Lax470956.Preprocessing |
| 43 | |
| 44 | open Lax470956.Scheduling Lax470956.Scheduling.Instance Lax470956.DynamicProgram |
| 45 | |
| 46 | variable (I : Instance) |
| 47 | |
| 48 | /-- `j` is strictly better than `j'`: heavier, or equally heavy and earlier in index |
| 49 | order. -/ |
| 50 | def Better (j j' : Fin I.jobs) : Prop := |
| 51 | I.w j' < I.w j ∨ (I.w j' = I.w j ∧ (j : ℕ) < (j' : ℕ)) |
| 52 | |
| 53 | instance (j j' : Fin I.jobs) : Decidable (Better I j j') := |
| 54 | inferInstanceAs (Decidable (_ ∨ _)) |
| 55 | |
| 56 | /-- The jobs occupying the interval `[dd - pp, dd)` that are eligible on machine `i`. -/ |
| 57 | def slotOf (i : Fin I.machines) (dd pp : ℕ) : Finset (Fin I.jobs) := |
| 58 | Finset.univ.filter fun j => I.d j = dd ∧ I.p j = pp ∧ i ∈ I.eligible j |
| 59 | |
| 60 | /-- The jobs occupying the same interval as `j` that are eligible on machine `i`. -/ |
| 61 | def sameSlot (i : Fin I.machines) (j : Fin I.jobs) : Finset (Fin I.jobs) := |
| 62 | slotOf I i (I.d j) (I.p j) |
| 63 | |
| 64 | /-- How many jobs of `j`'s slot on machine `i` beat `j`. -/ |
| 65 | def rank (i : Fin I.machines) (j : Fin I.jobs) : ℕ := |
| 66 | ((sameSlot I i j).filter fun j' => Better I j' j).card |
| 67 | |
| 68 | /-- **The preprocessing step.** Keep a job when, for some machine it is eligible on, it |
| 69 | is among the `m` best jobs of its interval there. -/ |
| 70 | def keep : Finset (Fin I.jobs) := |
| 71 | Finset.univ.filter fun j => ∃ i ∈ I.eligible j, rank I i j < I.machines |
| 72 | |
| 73 | /-- The best weight achievable by a feasible schedule that uses only jobs from `K`. -/ |
| 74 | def optimumOn (K : Finset (Fin I.jobs)) : ℕ := |
| 75 | (Finset.univ.filter fun σ : I.Schedule => Feasible σ ∧ ∀ j, σ j ≠ none → j ∈ K).sup |
| 76 | weight |
| 77 | |
| 78 | /-- **Lemma 5.** Preprocessing does not change the optimum: the best weight achievable |
| 79 | using only the kept jobs is the optimum of the whole instance. -/ |
| 80 | axiom optimumOn_keep (I : Instance) : optimumOn I (keep I) = optimum I |
| 81 | |
| 82 | /-- **Observation 5.** At most `p_max ^ 2 * m ^ 2` kept jobs are alive at any one |
| 83 | instant — a bound in the parameter alone, with no dependence on the number of jobs. -/ |
| 84 | axiom card_keep_alive_le (I : Instance) (t : ℕ) : |
| 85 | ((keep I).filter fun j => Active t j).card ≤ I.pmax * I.pmax * (I.machines * I.machines) |
| 86 | |
| 87 | end Lax470956.Preprocessing |
| 88 |
Formalization notes
Discarding is modelled as a set of kept jobs together with the best weight achievable using only those, rather than as a second instance on a smaller job set. The two say the same thing, and the first states it without transporting an instance along a change of index type — which would make the statement about the transport as much as about the preprocessing.
Ties in weight are broken by the job's index. "The best" has to be well defined, and some tie-break is needed to define it; the index is the tie-break a program would use, since it is the order the jobs arrive in. is the resulting strict linear order: heavier, or equally heavy and earlier.
A job is kept when it is among the best for some machine it is eligible on, not for all of them. The exchange argument needs this: a job is discarded only when every machine that could run it already keeps better alternatives for its interval. It is also why the bound counts machines twice.
Discussion
Ask a question or add context. Endorsements and structured flags are kept in the review panel above.
0 comments