Paper
Scheduling with Two Non-Unit Job Lengths Is NP-Complete
7 pages · 32 marked passages · pdflatex · download PDF · lax-391470
-
Single Machine Scheduling with Release Times and Deadlines
An instance consists of jobs to be run on a single machine. Job has a release time , a deadline and a processing time ; the interval is its availability interval. A schedule assigns a start time to every job. It is feasible if for every job and the execution intervals are pairwise disjoint: no job starts before its release time, no job completes after its deadline, no job is interrupted, and no two jobs run at the same time. The decision problem, written in the three-field notation, asks whether a feasible schedule exists — equivalently, whether the maximum lateness can be made non-positive.
The problem is parameterized by the set of processing times its jobs may have. An instance is on the lengths if every processing time is or .
1 import Mathlib.Data.Real.Basic 2 … module docstring, 35 lines 38 39 namespace Lax391470.Scheduling 40 41 /-- An instance of single machine scheduling with release times and deadlines: `jobs` 42 jobs, each with a release time, a deadline and a processing time. -/ 43 structure Instance where 44 /-- The number `n` of jobs. -/ 45 jobs : ℕ 46 /-- The release time `r i` of job `i`. -/ 47 r : Fin jobs → ℤ 48 /-- The deadline `d i` of job `i`. -/ 49 d : Fin jobs → ℤ 50 /-- The processing time `p i` of job `i`. -/ 51 p : Fin jobs → ℕ 52 53 namespace Instance 54 55 variable (I : Instance) 56 57 /-- A schedule assigns a start time to every job. -/ 58 abbrev Schedule := Fin I.jobs → ℤ 59 60 variable {I} 61 62 /-- A schedule is *feasible* if every job runs inside its availability interval and no two 63 jobs run at the same time. -/ 64 def Feasible (t : I.Schedule) : Prop := 65 (∀ i, I.r i ≤ t i ∧ t i + I.p i ≤ I.d i) ∧ 66 (∀ i j, i ≠ j → t i + I.p i ≤ t j ∨ t j + I.p j ≤ t i) 67 68 /-- The same condition for a schedule with real start times. -/ 69 def RealFeasible (t : Fin I.jobs → ℝ) : Prop := 70 (∀ i, (I.r i : ℝ) ≤ t i ∧ t i + I.p i ≤ I.d i) ∧ 71 (∀ i j, i ≠ j → t i + I.p i ≤ t j ∨ t j + I.p j ≤ t i) 72 73 variable (I) 74 75 /-- `I` admits a feasible schedule. -/ 76 def Schedulable : Prop := ∃ t : I.Schedule, Feasible t 77 78 /-- `I` admits a feasible schedule with real start times. -/ 79 def RealSchedulable : Prop := ∃ t : Fin I.jobs → ℝ, RealFeasible t 80 81 /-- Every processing time of `I` is `p` or `q`. -/ 82 def LengthsIn (p q : ℕ) : Prop := ∀ i, I.p i = p ∨ I.p i = q 83 84 end Instance 85 86 end Lax391470.Scheduling 87 -
Binary Encodings and the Two Languages
Scheduling instances and instances of the auxiliary problem as binary words, the representation against which classical complexity measures running time, and the two decision problems of this submission as languages of such words.
A natural number is written as its binary digits preceded by their number in unary, which makes the code self-delimiting; an integer is a sign bit followed by its absolute value. A scheduling instance is the number of jobs followed by the release time, the deadline and the processing time of every job in turn. An instance of the auxiliary problem is the number of ordinary jobs, the number of connected pairs, then for every ordinary job its release time, its deadline and one bit telling whether it is long, then for every connected pair its four deadlines.
For fixed job lengths and , the language of scheduling on the lengths consists of the encodings of the instances on those lengths that have a feasible schedule, and the language consists of the encodings of the ordered instances of the auxiliary problem that have a solution at those lengths.
1 import Lax391470.AuxiliaryProblem 2 import Lax434930.PolynomialTime 3 import Mathlib.Data.List.FinRange 4 import Mathlib.Data.Nat.Bits 5 … module docstring, 36 lines 42 43 namespace Lax391470.BinaryEncoding 44 45 open Lax434930.PolynomialTime 46 47 /-- A natural number as a binary word: its digits, least significant first, preceded by 48 their number in unary. -/ 49 def encodeNat (n : ℕ) : Word := 50 List.replicate n.bits.length true ++ [false] ++ n.bits 51 52 /-- An integer as a binary word: one bit for the sign, then the absolute value. -/ 53 def encodeInt (z : ℤ) : Word := decide (z < 0) :: encodeNat z.natAbs 54 55 /-- A scheduling instance as a binary word. -/ 56 def encodeInstance (I : Scheduling.Instance) : Word := 57 encodeNat I.jobs ++ 58 (List.finRange I.jobs).flatMap fun j => 59 encodeInt (I.r j) ++ encodeInt (I.d j) ++ encodeNat (I.p j) 60 61 /-- An instance of the auxiliary problem as a binary word. -/ 62 def encodeAux (A : AuxiliaryProblem.Instance) : Word := 63 encodeNat A.ordinary ++ encodeNat A.pairs ++ 64 ((List.finRange A.ordinary).flatMap fun o => 65 encodeNat (A.r o) ++ encodeNat (A.d o) ++ [A.long o]) ++ 66 (List.finRange A.pairs).flatMap fun i => 67 encodeNat (A.longEarly i) ++ encodeNat (A.longDue i) ++ 68 encodeNat (A.shortEarly i) ++ encodeNat (A.shortDue i) 69 70 /-- **Scheduling on the lengths `{p, q}`**, as a language. -/ 71 def TwoLengths (p q : ℕ) : Language := 72 {w | ∃ I : Scheduling.Instance, encodeInstance I = w ∧ I.LengthsIn p q ∧ I.Schedulable} 73 74 /-- **The auxiliary problem `AUX(p, q)`**, as a language. -/ 75 def AUX (p q : ℕ) : Language := 76 {w | ∃ A : AuxiliaryProblem.Instance, encodeAux A = w ∧ A.Ordered ∧ A.Solvable p q} 77 78 end Lax391470.BinaryEncoding 79 -
Scheduling with Two Non-Unit Job Lengths Is NP-Complete
Let be two integer job lengths. Single machine scheduling with release times and deadlines, restricted to instances whose processing times all lie in , is NP-complete.
Hardness is obtained by composing the reduction from satisfiability to the auxiliary problem with the reduction from the auxiliary problem to scheduling on the lengths . Since and are constants, every number of the constructed instance is bounded by a polynomial in the size of the formula, so the source concludes that the problem is even strongly NP-complete. The two bounds are stated as and ; strong NP-completeness itself, which would need a unary encoding of the instance, is not stated here.
The cases left out are polynomial-time solvable: a single job length, and two job lengths of which the shorter is .
- thm✓
Lax391470.Theorem1(1st statement) - thm✓
Lax391470.Theorem1(2nd statement) - thm✓
Lax391470.Theorem1(3rd statement)
1 import Lax391470.Lemma1 2 import Lax391470.Lemma2 3 … module docstring, 27 lines 31 32 namespace Lax391470.Theorem1 33 34 open Lax391470.BinaryEncoding Lax434930.PolynomialTime 35 open Lax434930.NondeterministicPolynomialTime Lax429075.Reductions 36 37 /-- Scheduling on the lengths `{p, q}` belongs to NP. -/ 38 axiom twoLengths_mem_NP (p q : ℕ) : TwoLengths p q ∈ NP 39 40 /-- For job lengths `p > q > 1`, scheduling on the lengths `{p, q}` is NP-hard. -/ 41 axiom twoLengths_npHard (p q : ℕ) (hq : 1 < q) (hqp : q < p) : 42 ∀ A : Language, A ∈ NP → ManyOne A (TwoLengths p q) 43 44 /-- **Theorem 1.** For job lengths `p > q > 1`, scheduling on the lengths `{p, q}` is 45 NP-complete. -/ 46 axiom twoLengths_npComplete (p q : ℕ) (hq : 1 < q) (hqp : q < p) : 47 NPComplete (TwoLengths p q) 48 49 end Lax391470.Theorem1 50 - thm✓
-
A certificate is a schedule: for every job a sign and the absolute value of its start time, in the code of the instance. Since a job starts between its release time and its deadline, a feasible schedule is no longer to write down than the instance. The verifier is a word RAM program: it takes the pair of instance and certificate apart, reads both with a one-pass tokenizer — once up to the end of the instance, to see that the instance is complete, and once to the end — shifts all times to natural numbers, checks every job against its availability interval and its length against and , and compares all pairs of jobs for overlap. Polynomial time on the word RAM transfers to a Turing machine.
-
The Auxiliary Problem AUX(p, q)
The intermediate problem through which the hardness proof passes. Fix two job lengths . An instance consists of a set of ordinary jobs, each long (of length ) or short (of length ), with non-negative release times and deadlines, together with two sequences and of pending jobs each. The pending jobs of are long and those of are short. Every pending job is released at time and carries two deadlines: an early deadline and a late deadline . The deadlines satisfy
The pending jobs and are connected. The question is whether has a feasible schedule, every job meeting its late deadline, in which for every at least one of and completes by its early deadline.
A connected pair is a disjunction between two jobs that may sit anywhere on the time line, which is what lets the problem express the clauses of a formula.
1 import Lax391470.Scheduling 2 … module docstring, 41 lines 44 45 namespace Lax391470.AuxiliaryProblem 46 47 open Lax391470.Scheduling 48 49 /-- The data of an instance of `AUX(p, q)`: ordinary jobs, each long or short, and 50 `pairs` connected pairs of pending jobs with an early and a late deadline each. -/ 51 structure Instance where 52 /-- The number of ordinary jobs. -/ 53 ordinary : ℕ 54 /-- The release time of an ordinary job. -/ 55 r : Fin ordinary → ℕ 56 /-- The deadline of an ordinary job. -/ 57 d : Fin ordinary → ℕ 58 /-- Whether an ordinary job is long (of length `p`) rather than short (of length `q`). -/ 59 long : Fin ordinary → Bool 60 /-- The number `N` of connected pairs of pending jobs. -/ 61 pairs : ℕ 62 /-- The early deadline `d'_{p,i}` of the `i`-th long pending job. -/ 63 longEarly : Fin pairs → ℕ 64 /-- The late deadline `d_{p,i}` of the `i`-th long pending job. -/ 65 longDue : Fin pairs → ℕ 66 /-- The early deadline `d'_{q,i}` of the `i`-th short pending job. -/ 67 shortEarly : Fin pairs → ℕ 68 /-- The late deadline `d_{q,i}` of the `i`-th short pending job. -/ 69 shortDue : Fin pairs → ℕ 70 71 namespace Instance 72 73 variable (A : Instance) 74 75 /-- The conditions on the deadlines of the pending jobs: within each sequence the 76 intervals between early and late deadline are ordered and do not intersect, and in every 77 connected pair the long job is the more urgent. -/ 78 structure Ordered : Prop where 79 /-- `d'_{p,i} ≤ d_{p,i}`. -/ 80 longEarly_le : ∀ i, A.longEarly i ≤ A.longDue i 81 /-- `d_{p,i} ≤ d'_{p,i+1}`. -/ 82 longDue_le : ∀ i j : Fin A.pairs, (i : ℕ) + 1 = j → A.longDue i ≤ A.longEarly j 83 /-- `d'_{q,i} ≤ d_{q,i}`. -/ 84 shortEarly_le : ∀ i, A.shortEarly i ≤ A.shortDue i 85 /-- `d_{q,i} ≤ d'_{q,i+1}`. -/ 86 shortDue_le : ∀ i j : Fin A.pairs, (i : ℕ) + 1 = j → A.shortDue i ≤ A.shortEarly j 87 /-- `d_{p,i} ≤ d'_{q,i}`. -/ 88 longDue_le_shortEarly : ∀ i, A.longDue i ≤ A.shortEarly i 89 90 /-- The scheduling instance underlying `A` at the job lengths `p` and `q`: the ordinary 91 jobs, then the long pending jobs, then the short pending jobs, the pending jobs released 92 at `0` and due at their late deadlines. -/ 93 def toInstance (p q : ℕ) : Scheduling.Instance where 94 jobs := A.ordinary + A.pairs + A.pairs 95 r j := if h : (j : ℕ) < A.ordinary then A.r ⟨j, h⟩ else 0 96 d j := 97 if h : (j : ℕ) < A.ordinary then A.d ⟨j, h⟩ 98 else if h' : (j : ℕ) < A.ordinary + A.pairs then 99 A.longDue ⟨j - A.ordinary, by omega⟩ 100 else A.shortDue ⟨j - A.ordinary - A.pairs, by have := j.isLt; omega⟩ 101 p j := 102 if h : (j : ℕ) < A.ordinary then (if A.long ⟨j, h⟩ then p else q) 103 else if (j : ℕ) < A.ordinary + A.pairs then p 104 else q 105 106 /-- The `i`-th long pending job, as a job of the underlying instance. -/ 107 def longJob (p q : ℕ) (i : Fin A.pairs) : Fin (A.toInstance p q).jobs := 108 ⟨A.ordinary + i, by have := i.isLt; simp only [toInstance]; omega⟩ 109 110 /-- The `i`-th short pending job, as a job of the underlying instance. -/ 111 def shortJob (p q : ℕ) (i : Fin A.pairs) : Fin (A.toInstance p q).jobs := 112 ⟨A.ordinary + A.pairs + i, by have := i.isLt; simp only [toInstance]; omega⟩ 113 114 variable {A} 115 116 /-- A schedule *solves* `A` at the lengths `p` and `q`: it is feasible, and in every 117 connected pair the long job completes by its early deadline or the short one does. -/ 118 def Solves (p q : ℕ) (t : (A.toInstance p q).Schedule) : Prop := 119 Scheduling.Instance.Feasible t ∧ 120 ∀ i : Fin A.pairs, 121 t (A.longJob p q i) + p ≤ A.longEarly i ∨ t (A.shortJob p q i) + q ≤ A.shortEarly i 122 123 variable (A) 124 125 /-- `A` has a solution at the lengths `p` and `q`. -/ 126 def Solvable (p q : ℕ) : Prop := ∃ t, A.Solves p q t 127 128 end Instance 129 130 end Lax391470.AuxiliaryProblem 131 -
thm✓
Lax391470.Lemma2The Auxiliary Problem Is NP-Complete
For any two integer job lengths , the problem is NP-complete.
Hardness is by reduction from satisfiability of formulas in conjunctive normal form. A satisfying assignment yields a solution in which the sections of the false literals are delayed by one unit: every clause has a true literal, whose section is not delayed and whose clause block is active, and at that block the chain of connected pairs of the clause can switch from completing short jobs early to completing long jobs early. Conversely, in any solution every job runs inside its own block, one of the sections of and is delayed for every , and a chain of clause blocks can be scheduled only if it passes an active block in a section that is not delayed; setting the literals of the delayed sections to false satisfies the formula.
The assumption is needed: one unit of delay must not leave room for a short job.
- thm✓
Lax391470.Lemma2(1st statement) - thm✓
Lax391470.Lemma2(2nd statement) - thm✓
Lax391470.Lemma2(3rd statement) - thm✓
Lax391470.Lemma2(4th statement) - thm✓
Lax391470.Lemma2(5th statement)
1 import Lax391470.BinaryEncoding 2 import Lax391470.SatConstruction 3 import Lax429075.Reductions 4 import Lax429075.Satisfiability 5 … module docstring, 32 lines 38 39 namespace Lax391470.Lemma2 40 41 open Lax391470.BinaryEncoding Lax434930.PolynomialTime 42 open Lax434930.NondeterministicPolynomialTime Lax429075.Reductions 43 44 /-- An instance of the auxiliary problem without a solution, when `q ≥ 1`: one ordinary 45 short job, released and due at time `0`. -/ 46 def blocked : AuxiliaryProblem.Instance where 47 ordinary := 1 48 r _ := 0 49 d _ := 0 50 long _ := false 51 pairs := 0 52 longEarly := Fin.elim0 53 longDue := Fin.elim0 54 shortEarly := Fin.elim0 55 shortDue := Fin.elim0 56 57 /-- **The reduction**, as a map on words: the encoding of a formula is sent to the 58 encoding of the instance built from it, and every other word to the encoding of 59 `blocked`. -/ 60 def reduce (p q : ℕ) (w : Word) : Word := 61 match Lax429075.Encoding.decodeCNF w with 62 | some F => encodeAux (SatConstruction.inst p q F) 63 | none => encodeAux blocked 64 65 /-- **The reduction is correct.** -/ 66 axiom reduce_correct (p q : ℕ) (hq : 1 < q) (hqp : q < p) (w : Word) : 67 w ∈ Lax429075.Satisfiability.SAT ↔ reduce p q w ∈ AUX p q 68 69 /-- **The reduction runs in polynomial time.** -/ 70 axiom reduce_polyTime (p q : ℕ) : 71 Nonempty (Turing.TM2ComputableInPolyTime id id (reduce p q)) 72 73 /-- For job lengths `p > q > 1`, `AUX(p, q)` is NP-hard. -/ 74 axiom aux_npHard (p q : ℕ) (hq : 1 < q) (hqp : q < p) : 75 ∀ A : Language, A ∈ NP → ManyOne A (AUX p q) 76 77 /-- `AUX(p, q)` belongs to NP. -/ 78 axiom aux_mem_NP (p q : ℕ) : AUX p q ∈ NP 79 80 /-- **Lemma 2.** For job lengths `p > q > 1`, `AUX(p, q)` is NP-complete. -/ 81 axiom aux_npComplete (p q : ℕ) (hq : 1 < q) (hqp : q < p) : NPComplete (AUX p q) 82 83 end Lax391470.Lemma2 84 - thm✓
-
The Instance of AUX(p, q) Built from a Formula
The instance of built from a formula in conjunctive normal form with variables and clauses .
The time line is cut into sections of equal length , one for every literal, in the order A section consists of a literal block of total job length , then one clause block of total job length for every clause, then one unit of idle time, then a separator: an ordinary short job whose availability interval is exactly the last time units of the section.
Relative to the start of its section, the literal block of a positive literal, of type , consists of the ordinary jobs and and a long pending job with early deadline and late deadline . The block of a negative literal, of type , consists of the ordinary jobs and and a short pending job with early deadline and late deadline . In either block the pending job can complete early only at the price of one unit of idle time that no other job can fill.
Relative to the point of its section, the clause block of the clause consists of a long and a short pending job, both with late deadline and both with early deadline if the literal of the section occurs in — the block is then active — and otherwise. Both jobs of an active block can complete early if the section has not been delayed; in a delayed section, or in an inactive block, only one of them can.
Pending jobs are connected as follows. The long pending job of the literal block of is connected with the short pending job of the literal block of . For every clause, the long pending job of its clause block in a section is connected with the short pending job of its clause block in the next section. This leaves the long pending jobs of the clause blocks of the last section and the short ones of the first section unconnected; they are required to meet their early deadline, which makes them ordinary jobs released at .
A connected pair of literal blocks forces a delay of one unit in the section of or in that of ; the literal whose section is not delayed is the one set to true. The chain of clause blocks of a clause through all sections can be scheduled only if the clause block is active in some section that is not delayed, that is, if the clause contains a true literal.
- def✓
Lax391470.SatConstruction(1st statement) - def✓
Lax391470.SatConstruction(2nd statement) - def✓
Lax391470.SatConstruction(3rd statement) - def✓
Lax391470.SatConstruction(4th statement)
1 import Lax391470.AuxiliaryProblem 2 import Lax429075.CNF 3 … module docstring, 65 lines 69 70 namespace Lax391470.SatConstruction 71 72 open Lax391470.AuxiliaryProblem Lax429075.CNF 73 74 variable (p q : ℕ) (F : Formula) 75 76 /-- The number `n` of variables: one more than the largest index occurring in `F`, and 77 `1` if no literal occurs. -/ 78 def numVars : ℕ := (F.flatMap id).foldr (fun l n => max (l.index + 1) n) 1 79 80 /-- The number `m` of clauses. -/ 81 def numClauses : ℕ := F.length 82 83 /-- The length `S` of a section. -/ 84 def sectionLength : ℕ := p + 2 * q + numClauses F * (p + q) + 1 + q 85 86 /-- The start of section `s`. -/ 87 def sectionStart (s : ℕ) : ℕ := sectionLength p q F * s 88 89 /-- The literal of section `s`: the sections run `x₀, ¬x₀, x₁, ¬x₁, …`. -/ 90 def literalOf (s : ℕ) : Literal := ⟨s / 2, decide (s % 2 = 0)⟩ 91 92 /-- The clause block of clause `j` in section `s` is *active*: the literal of the section 93 occurs in the clause. -/ 94 def active (s j : ℕ) : Bool := decide (literalOf s ∈ F.getD j []) 95 96 /-- The start of the clause block of clause `j` in section `s`. -/ 97 def clauseStart (s j : ℕ) : ℕ := sectionStart p q F s + p + 2 * q + j * (p + q) 98 99 /-- The early deadline of both pending jobs of a clause block. -/ 100 def clauseEarly (s j : ℕ) : ℕ := 101 clauseStart p q F s j + (if active F s j then p + q else p + q - 1) 102 103 /-- The late deadline of both pending jobs of a clause block. -/ 104 def clauseDue (s j : ℕ) : ℕ := clauseStart p q F s j + p + q + 1 105 106 /-- The number of ordinary jobs: three for every section, and the `2m` unconnected 107 pending jobs. -/ 108 def numOrdinary : ℕ := 6 * numVars F + 2 * numClauses F 109 110 /-- The release time of the ordinary job `o`. -/ 111 def ordRelease (o : ℕ) : ℕ := 112 if o < 6 * numVars F then 113 match o % 3 with 114 | 0 => sectionStart p q F (o / 3) + (if (o / 3) % 2 = 0 then 1 else q + 1) 115 | 1 => sectionStart p q F (o / 3) 116 | _ => sectionStart p q F (o / 3) + sectionLength p q F - q 117 else 0 118 119 /-- The deadline of the ordinary job `o`. -/ 120 def ordDue (o : ℕ) : ℕ := 121 if o < 6 * numVars F then 122 match o % 3 with 123 | 0 => sectionStart p q F (o / 3) + (if (o / 3) % 2 = 0 then 2 * q else p + q) 124 | 1 => sectionStart p q F (o / 3) + p + 2 * q + 1 125 | _ => sectionStart p q F (o / 3) + sectionLength p q F 126 else if o < 6 * numVars F + numClauses F then 127 clauseEarly p q F (2 * numVars F - 1) (o - 6 * numVars F) 128 else 129 clauseEarly p q F 0 (o - 6 * numVars F - numClauses F) 130 131 /-- Whether the ordinary job `o` is long: the second ordinary job of a block of type `V⁻`, 132 and the unconnected long jobs of the last section. -/ 133 def ordLong (o : ℕ) : Bool := 134 if o < 6 * numVars F then decide (o % 3 = 1 ∧ (o / 3) % 2 = 1) 135 else decide (o < 6 * numVars F + numClauses F) 136 137 /-- The number `N = n + (2n - 1) m` of connected pairs. -/ 138 def numPairs : ℕ := numVars F + (2 * numVars F - 1) * numClauses F 139 140 /-- The variable whose group the pair `i` belongs to. -/ 141 def groupOf (i : ℕ) : ℕ := i / (1 + 2 * numClauses F) 142 143 /-- The position of the pair `i` in its group: `0` for the literal pair. -/ 144 def posOf (i : ℕ) : ℕ := i % (1 + 2 * numClauses F) 145 146 /-- The section holding the long job of the clause pair `i`. -/ 147 def pairSection (i : ℕ) : ℕ := 2 * groupOf F i + (posOf F i - 1) / numClauses F 148 149 /-- The clause of the clause pair `i`. -/ 150 def pairClause (i : ℕ) : ℕ := (posOf F i - 1) % numClauses F 151 152 /-- The early deadline of the long job of pair `i`. -/ 153 def longEarly (i : ℕ) : ℕ := 154 if posOf F i = 0 then sectionStart p q F (2 * groupOf F i) + p + q + 1 155 else clauseEarly p q F (pairSection F i) (pairClause F i) 156 157 /-- The late deadline of the long job of pair `i`. -/ 158 def longDue (i : ℕ) : ℕ := 159 if posOf F i = 0 then sectionStart p q F (2 * groupOf F i) + p + 2 * q 160 else clauseDue p q F (pairSection F i) (pairClause F i) 161 162 /-- The early deadline of the short job of pair `i`, one section after the long job. -/ 163 def shortEarly (i : ℕ) : ℕ := 164 if posOf F i = 0 then sectionStart p q F (2 * groupOf F i + 1) + q 165 else clauseEarly p q F (pairSection F i + 1) (pairClause F i) 166 167 /-- The late deadline of the short job of pair `i`. -/ 168 def shortDue (i : ℕ) : ℕ := 169 if posOf F i = 0 then sectionStart p q F (2 * groupOf F i + 1) + p + 2 * q 170 else clauseDue p q F (pairSection F i + 1) (pairClause F i) 171 172 /-- **The instance of `AUX(p, q)`** built from the formula `F`. -/ 173 def inst : AuxiliaryProblem.Instance where 174 ordinary := numOrdinary F 175 r o := ordRelease p q F o 176 d o := ordDue p q F o 177 long o := ordLong F o 178 pairs := numPairs F 179 longEarly i := longEarly p q F i 180 longDue i := longDue p q F i 181 shortEarly i := shortEarly p q F i 182 shortDue i := shortDue p q F i 183 184 /-- For job lengths `p > q > 1`, the deadlines of the constructed instance are ordered as 185 the auxiliary problem requires. -/ 186 axiom ordered (hq : 1 < q) (hqp : q < p) : (inst p q F).Ordered 187 188 /-- **From an assignment to a schedule.** If `F` is satisfiable, the constructed instance 189 has a solution. -/ 190 axiom solvable_of_satisfiable (hq : 1 < q) (hqp : q < p) : 191 Satisfiable F → (inst p q F).Solvable p q 192 193 /-- **From a schedule to an assignment.** If the constructed instance has a solution, `F` 194 is satisfiable. -/ 195 axiom satisfiable_of_solvable (hq : 1 < q) (hqp : q < p) : 196 (inst p q F).Solvable p q → Satisfiable F 197 198 /-- **The numbers of the constructed instance are small**: every release time and every 199 deadline is at most the length `2nS` of the time line, a polynomial in the size of the 200 formula. Together with `StackedConstruction.times_le`, this bounds every number of the 201 composed reduction; it is the ingredient of strong NP-hardness. -/ 202 axiom times_le : 203 (∀ o, (inst p q F).r o ≤ 2 * numVars F * sectionLength p q F ∧ 204 (inst p q F).d o ≤ 2 * numVars F * sectionLength p q F) ∧ 205 (∀ i, (inst p q F).longDue i ≤ 2 * numVars F * sectionLength p q F ∧ 206 (inst p q F).shortDue i ≤ 2 * numVars F * sectionLength p q F) 207 208 end Lax391470.SatConstruction 209 - def✓
-
no assumptions
The deadlines are those of the typed construction, whose chains are verified there.
-
no assumptions
-
no assumptions
-
no assumptions
-
A certificate is a schedule of the underlying instance: one start time for every ordinary job, every long pending job and every short pending job, in the code of the instance. All times of the auxiliary problem are natural numbers, and a job starts before its deadline, so a solution takes at most quadratically more room than the instance. The verifier is a word RAM program: it takes the pair of instance and certificate apart, reads both with a one-pass tokenizer — once up to the end of the instance, to see that the instance is complete, and once to the end — checks the conditions on the deadlines of the pending jobs, checks every job against its availability interval, checks that in every connected pair one job meets its early deadline, and compares all pairs of jobs for overlap. Polynomial time on the word RAM transfers to a Turing machine.
-
The reduction is a word RAM program on the zeros and ones of its input: a finite-state scan decodes the formula, the numbers of the constructed instance are computed into arrays, and a printer writes their binary codes. Polynomial time on the word RAM transfers to a Turing machine.
-
Compose the Cook–Levin reduction to satisfiability with the map .
-
thm✓
Lax391470.Lemma1The Auxiliary Problem Reduces to Scheduling on Two Job Lengths
For any two integer job lengths , the problem is polynomial-time reducible to single machine scheduling with release times and deadlines on the job lengths .
The reduction replaces every connected pair of pending jobs by the five jobs of the stacked construction. Its correctness is proved by an exchange argument: a feasible schedule of the stacked instance is rearranged, pair by pair in order of urgency, until every bin holds two jobs of its own pair, and the jobs left after time are then read as a solution of the auxiliary instance.
- thm✓
Lax391470.Lemma1(1st statement) - thm✓
Lax391470.Lemma1(2nd statement) - thm✓
Lax391470.Lemma1(3rd statement)
1 import Lax391470.BinaryEncoding 2 import Lax391470.StackedConstruction 3 import Lax429075.Reductions 4 … module docstring, 26 lines 31 32 namespace Lax391470.Lemma1 33 34 open Lax391470.BinaryEncoding Lax434930.PolynomialTime Lax429075.Reductions 35 36 /-- An instance on the lengths `{p, q}` without a feasible schedule, when `p ≥ 1`: one job 37 of length `p` that is due when it is released. -/ 38 def blocked (p : ℕ) : Scheduling.Instance where 39 jobs := 1 40 r _ := 0 41 d _ := 0 42 p _ := p 43 44 /-- **The reduction**, as a map on words: the encoding of an ordered instance `A` is sent 45 to the encoding of its stacked instance, and every other word to the encoding of 46 `blocked p`. -/ 47 noncomputable def reduce (p q : ℕ) (w : Word) : Word := 48 open Classical in 49 if h : ∃ A : AuxiliaryProblem.Instance, encodeAux A = w ∧ A.Ordered then 50 encodeInstance (StackedConstruction.inst p q h.choose) 51 else encodeInstance (blocked p) 52 53 /-- **The reduction is correct.** -/ 54 axiom reduce_correct (p q : ℕ) (hq : 0 < q) (hqp : q < p) (w : Word) : 55 w ∈ AUX p q ↔ reduce p q w ∈ TwoLengths p q 56 57 /-- **The reduction runs in polynomial time.** -/ 58 axiom reduce_polyTime (p q : ℕ) : 59 Nonempty (Turing.TM2ComputableInPolyTime id id (reduce p q)) 60 61 /-- **Lemma 1.** For job lengths `p > q ≥ 1`, `AUX(p, q)` is polynomial-time reducible to 62 scheduling on the lengths `{p, q}`. -/ 63 axiom aux_manyOne_twoLengths (p q : ℕ) (hq : 0 < q) (hqp : q < p) : 64 ManyOne (AUX p q) (TwoLengths p q) 65 66 end Lax391470.Lemma1 67 - thm✓
-
The Stacked Scheduling Instance
The scheduling instance built from an instance of , in which the two deadlines of a pending job are expressed by ordinary availability intervals. The construction buys the second deadline with room on the time line before time .
Let and let for . For every connected pair the instance contains five jobs:
- a separator with availability interval and length , which is thereby pinned in place;
- an inner long job and an outer long job ;
- an inner short job and an outer short job .
The ordinary jobs are kept unchanged. The separators cut the time before into bins , each with room for exactly one long and one short job. The availability intervals of the four jobs of a pair are nested, the inner ones carrying the early deadlines. A feasible schedule parks two jobs of each pair in its bin and runs the other two, one long and one short, after time . The inner long job and the inner short job of a pair do not fit into its bin together, so one of the two jobs running after is an inner job and meets an early deadline — the condition on connected pairs.
- def✓
Lax391470.StackedConstruction(1st statement) - def✓
Lax391470.StackedConstruction(2nd statement) - def✓
Lax391470.StackedConstruction(3rd statement)
1 import Lax391470.AuxiliaryProblem 2 … module docstring, 37 lines 40 41 namespace Lax391470.StackedConstruction 42 43 open Lax391470.Scheduling Lax391470.AuxiliaryProblem 44 45 variable (p q : ℕ) (A : AuxiliaryProblem.Instance) 46 47 /-- The left end `tᵢ` of the bin of pair `i`, pairs counted from `0`. -/ 48 def binStart (i : ℕ) : ℤ := -(((p + 2 * q) * (i + 1) : ℕ) : ℤ) 49 50 /-- The number of jobs: the ordinary ones and five for every connected pair. -/ 51 def numJobs : ℕ := A.ordinary + 5 * A.pairs 52 53 /-- The pair a job beyond the ordinary ones belongs to. -/ 54 def pairOf (j : ℕ) : ℕ := (j - A.ordinary) / 5 55 56 /-- Which of the five jobs of its pair a job is: `0` the separator, `1` the inner long 57 job, `2` the outer long job, `3` the inner short job, `4` the outer short job. -/ 58 def partOf (j : ℕ) : ℕ := (j - A.ordinary) % 5 59 60 /-- **The stacked instance** built from `A` at the lengths `p` and `q`. -/ 61 def inst : Scheduling.Instance where 62 jobs := numJobs A 63 r j := 64 if h : (j : ℕ) < A.ordinary then A.r ⟨j, h⟩ 65 else 66 binStart p q (pairOf A j) + 67 match partOf A j with 68 | 0 => (p + q : ℕ) 69 | 1 => (q : ℕ) 70 | 2 => 0 71 | 3 => (p : ℕ) 72 | _ => 0 73 d j := 74 if h : (j : ℕ) < A.ordinary then A.d ⟨j, h⟩ 75 else 76 have hi : pairOf A j < A.pairs := by 77 have := j.isLt 78 simp only [pairOf, numJobs] at * 79 omega 80 match partOf A j with 81 | 0 => binStart p q (pairOf A j) + (p + 2 * q : ℕ) 82 | 1 => A.longEarly ⟨pairOf A j, hi⟩ 83 | 2 => A.longDue ⟨pairOf A j, hi⟩ 84 | 3 => A.shortEarly ⟨pairOf A j, hi⟩ 85 | _ => A.shortDue ⟨pairOf A j, hi⟩ 86 p j := 87 if h : (j : ℕ) < A.ordinary then (if A.long ⟨j, h⟩ then p else q) 88 else 89 match partOf A j with 90 | 1 => p 91 | 2 => p 92 | _ => q 93 94 /-- The stacked instance is on the lengths `{p, q}`. -/ 95 axiom lengthsIn : (inst p q A).LengthsIn p q 96 97 /-- **The construction is correct.** For job lengths `p > q ≥ 1`, an ordered instance of 98 `AUX(p, q)` has a solution exactly when the stacked instance has a feasible schedule. -/ 99 axiom correct (hq : 0 < q) (hqp : q < p) (hA : A.Ordered) : 100 A.Solvable p q ↔ (inst p q A).Schedulable 101 102 /-- **The numbers of the stacked instance are small**: if every release time and every 103 deadline of an ordered instance `A` is at most `T`, every release time and deadline of the 104 stacked instance lies within `T + (p + 2q)N` of `0`, where `N` is the number of pairs. 105 Together with `SatConstruction.times_le`, this bounds every number of the composed 106 reduction by a polynomial in the size of the formula. -/ 107 axiom times_le (hA : A.Ordered) (T : ℕ) 108 (hT : (∀ o, A.r o ≤ T ∧ A.d o ≤ T) ∧ 109 (∀ i, A.longDue i ≤ T ∧ A.shortDue i ≤ T)) : 110 ∀ j, |(inst p q A).r j| ≤ ((T + (p + 2 * q) * A.pairs : ℕ) : ℤ) ∧ 111 |(inst p q A).d j| ≤ ((T + (p + 2 * q) * A.pairs : ℕ) : ℤ) 112 113 end Lax391470.StackedConstruction 114 -
no assumptions
The numbered auxiliary instance and its stacked instance are renumberings of the typed ones, for which the exchange argument of the source is carried out.
-
no assumptions
-
no assumptions
-
no assumptions
-
The reduction is a word RAM program on the zeros and ones of its input: a one-pass tokenizer decodes the instance of the auxiliary problem, a second pass checks the conditions on its deadlines, and a printer writes the binary codes of the jobs of the stacked instance, signs included. Decoded numbers may be exponential in the length of the input, which the word length of a polynomial-time word RAM accommodates. Polynomial time on the word RAM transfers to a Turing machine.
-
The reduction is the map ; its two properties are the two other statements.
-
Integral Start Times Suffice
An instance has a feasible schedule with real start times if and only if it has one with integer start times. Rounding every start time up to the next integer preserves feasibility, because release times, deadlines and processing times are integers.
1 import Lax391470.Scheduling 2 … module docstring, 16 lines 19 20 namespace Lax391470.IntegralStartTimes 21 22 open Lax391470.Scheduling 23 24 /-- Real and integer start times decide the same instances. -/ 25 axiom realSchedulable_iff (I : Instance) : I.RealSchedulable ↔ I.Schedulable 26 27 end Lax391470.IntegralStartTimes 28 -
no assumptions
Round every start time up. Rounding up is monotone and commutes with adding an integer, and all data are integers, so every inequality of feasibility survives.
-
Compose Lemma 2's hardness with the reduction of Lemma 1.
-
The Cook–Levin Theorem
-
The Word RAM
-
Computability and polynomial-time equivalence of Turing machines and word RAMs
-
Classical Complexity Classes
Loading the paper…