ScheduleOpt Scheduling Benchmarks

A public library of job-shop instances that records the best known bounds for each instance and compares four solvers in a fixed 10-minute run.

Each figure has two buttons. Copy DataviewJS copies an interactive block for Obsidian (Dataview plugin, JavaScript queries on). Copy HTML copies a static snapshot of the current state. Each formula has a Copy LaTeX button. It copies a $$ … $$ block that Obsidian and most Markdown editors render.

Key idea

For most hard scheduling instances, nobody knows the optimal makespan. Instead, the library keeps the best known lower bound and upper bound for each instance, from any source. Each solver result is scored against these two bounds. Thus, one archive serves as the reference for all comparisons.

The three parts of the library

Step
The library has three parts. Instances go to four engines. All bounds, from engines or from outside sources, go to the archive. The archive is then the reference for scoring.

The site defines the library as three parts:

  1. instances An instance repository. It holds benchmark instances from the literature in one shared JSON format.
  2. engine run An engine benchmark. Four reference engines run each instance for 10 minutes on the same machine.
  3. archive A best-known-solutions archive. It keeps the best lower and upper bound for each instance, with the history of who found each one.

The archive accepts bounds from any source: papers, meta-heuristics, long runs and the reference engines. If a reference engine reproduces a published bound, the archive credits the engine.

What it contains

The library has two problem collections now. RCPSP and workforce scheduling are planned, but the site gives no date.

  • JSPLib: job-shop scheduling. A job is a fixed sequence of operations, and each operation must use one given machine. A machine runs one operation at a time.
  • FJSPLib: flexible job-shop scheduling. Each operation can use one machine from a set of eligible machines. Each option has its own duration. Thus, the solver must assign machines and also order the operations.

Neither page states the objective in a formula. The bounds are makespan values and the bound methods are makespan bounds, so the objective is makespan minimization (inferred). Makespan is the end time of the last operation.

Collection

File formats

Each instance has a JSON file. The JSON lists operations (job, step, option, machine, duration) and precedences (before, after). The same schema covers job shop, reentrant job shop, flexible job shop and arbitrary precedence graphs. The legacy text formats are also kept:

  • Standard (JSPLib): the first line is #jobs #machines. Then each line is one job, as machine and duration pairs in operation order.
  • DaColTeppan (reentrant): the same, but a job can use a machine more than once, and each line ends with -1 -1.
  • fjsp (FJSPLib): the header is #jobs #machines average_flexibility. Each operation gives its number of options, then machine and duration pairs. Machines start at 1.
  • fajsp (assembly): the header is #operations #precedences #machines, then precedence lines, then one options line per operation. Machines start at 0.

The bounds are in bks.json. Each instance has a status, a lower bound and an upper bound. Each bound has a history list with value, date, solver, hardware, time and certificate. A certificate is a stored solution or proof that a person can check. Many history fields have the value "?".

Why it matters

Job-shop results in papers are often hard to compare. Authors use different subsets, time limits, hardware and reference values. This library fixes one set of reference bounds and one run protocol. Thus, a new method can report one number against a stable target.

The library also shows which instances are still open. An open instance is an instance with no proof of optimality. For an open instance, a new lower bound or a new upper bound is a real result. The archive records it with the source and the date.

For this project: the REALM-Bench JSSP notes plan to add "OR-Tools CP-SAT reference makespans" for the J1 instances (DMU, TA, ABZ, SWV, YN). All five families are in JSPLib. Thus, jobshop/solutions/bks.json can supply the reference bounds directly, and the J1 gap can use the best known bound instead of a new CP-SAT run. This link to the project is my inference from the project note knowledge/claude/realm-bench-jssp-findings.md.

How the tests work

1. Task construction

The maintainers do not generate new tasks. They collect published instance sets from 1963 to 2025 and convert them to the shared JSON format. JSPLib has 3 groups:

  • Random (322): random processing times and machine orders, for example Taillard (ta) and Demirkol (dmu).
  • Industrial (44): synthetic instances that copy the structure of real plants (dct, bel).
  • Stress test (10): 1000 jobs × 1000 machines. These test the data structures of an engine, not its search.

2. Run protocol

  • Each engine runs each instance one time, with a time limit of 600 s.
  • Hardware: a Windows PC with an i7 at 3 GHz, 4 cores and 32 GB RAM. The site selected 4 cores as a typical laptop.
  • Engines: Cplex 22.1.1.0 (MIP), CP Optimizer 22.1.1.0 (CP scheduling), CP-SAT v9.15.6755 (lazy clause generation) and OptalCP Academic 2026.4.0 (CP scheduling).
  • The optimality gap tolerance is 0 for CPO and OptalCP. A non-zero tolerance can make an engine report a sub-optimal schedule as optimal. CP-SAT uses its default settings.

3. Failure handling

  • If an engine returns no solution in 600 s, the instance counts as "not solved" for that engine.
  • Some engines return a degenerate schedule: all operations one after the other, so the makespan is the sum of all durations. The maintainers remove these outliers by hand and count them as not solved, because they distort the averages.
  • If no engine result exists for a group, the score is NaN. The site does not inject perturbations or machine failures. All instances are static and deterministic.

4. Scoring against the archive

Each engine reports a lower bound LB and an upper bound UB for each instance. The score compares them to the best known bounds LBbest and UBbest. The site gives three geometric averages:

$$\mathrm{lb} = \exp\Big(\tfrac{1}{N}\sum_k \log\tfrac{LB_k}{LB_{best,k}}\Big)$$
$$\mathrm{ub} = \exp\Big(\tfrac{1}{N}\sum_k \log\tfrac{UB_k}{UB_{best,k}}\Big)$$
$$\mathrm{gap} = \exp\Big(\tfrac{1}{N}\sum_k \log\big(1 + \tfrac{UB_k - LB_k}{UB_k}\big)\Big) - 1$$

An lb value of 1.00 means that the engine finds the best known lower bound. An ub value of 1.00 means that the engine finds the best known schedule. A gap of 0% means that the engine proves optimality on all instances. The site prints lb and ub without the 1/N factor. As printed, they are products, not averages. I added 1/N here because the reported values (for example 0.89) only make sense as averages (inferred).

Use the figure below to see one instance. The values for ta40 come from the JSPLib page: the Carlier lower bound is 1617, and the optimum is in [1658, 1669].

Engine LB1617 Engine UB1700 Preset
Makespan axis for ta40. The optimum is somewhere between the two best known bounds. The engine interval must contain that range. The score uses the ratios of the engine bounds to the best known bounds.

5. Difficulty classes

The archive puts each instance in one class. The class depends on the time that the fastest reference engine needs to prove optimality:

  • toy: proof in 1 minute. easy: proof in 10 minutes. medium: proof in 1 hour. hard: proof in more than 1 hour.
  • closed: the optimum is known, usually because two independent methods found equal bounds. open: no proof of optimality.
Scale
JSPLib instances per family and difficulty class, from the JSPLib page. Green shades are closed classes (darker means a longer proof). Red is open. The family rows sum to 91 open instances. The engine table says 90.

FJSPLib uses the same classes, but with one difference. In FJSPLib, "closed" means that a publication claims the optimum, but no reference engine has reproduced the proof yet. When an engine reproduces it, the instance moves to toy, easy, medium or hard. JSPLib lists no instances in that state.

Scale
FJSPLib instances per family and difficulty class, from the FJSPLib page. The first five rows are the job-shop bases with machine-independent times (4 variants each). Purple is "closed (claimed)": a published optimum that no reference engine has reproduced. The page lists no "easy" instances. The 50 assembly instances (dafjs, yfjs) have unknown status. The rows sum to 59 open instances.

Results of the 10-minute run

Only JSPLib has a results table. FJSPLib gives the raw results in its solutions folder but no summary table. "Solved" means that the engine returned a valid schedule. "Optimal" means that the engine also proved optimality in 600 s.

Group Metric
JSPLib engine benchmark, 600 s, 4 cores. Values are copied from the JSPLib aggregate table. NaN means that the engine returned no usable result in that group.

OptalCP has the best value in each group. Its lb ratio is 0.99 or 1.00 in all groups, so its lower bounds are almost always the best known bounds. CPO and CP-SAT are close on upper bounds (ub 1.03 for both on all instances). But CP-SAT proves fewer instances optimal (44% against 51%). Cplex, the MIP engine, proves 7% optimal and returns no schedule for the industrial and stress-test groups.

No engine proves an open instance optimal in 10 minutes, as expected. On the stress test, CP-SAT returns no schedule in 600 s. The JSPLib page says that CP-SAT can use the full run for preprocessing on tai_1000_1000. On the same instance, CPO and OptalCP need about one hour to find a first solution, but a hand-written greedy needs about one minute.

Limits and edge cases

Check the counts before you cite them. The site has small inconsistencies, listed below.
  • Instance count. The JSPLib page says "Currently there are 462 instances". The families sum to 376, and the benchmark ran 376.
  • Open count. The family table sums to 91 open instances. The engine table reports 90 open and 286 closed.
  • Formulas. The printed lb and ub formulas have no 1/N factor, but the gap formula has it.
  • One run, one machine. Engines are not deterministic, and each instance runs one time. Small differences in the averages are not significant. The site says this itself.
  • Hardware choice affects the ranking. CP-SAT recommends 8 to 16 cores, and CPO works best on 1 or 2 cores. The 4-core setup is a compromise, so another core count can change the order.
  • Weak provenance. Many history entries have no hardware, time or certificate. Some times are rough, for example "OptalCP in < 10h".
  • Manual outlier removal. The maintainers remove degenerate schedules by hand. The site does not list which results it removed.
  • FJSPLib. There is no summary of the 600 s run. The 50 assembly instances have unknown status.
  • Possible conflict of interest. The site hosts an OptalCP benchmark repository, and OptalCP has the best results with tuned settings ("maximum propagation", "other parameter changes"). The other engines use defaults or a zero tolerance only. This is an observation, not a claim of bias.
  • Small link error. The Cplex entry links to the CP Optimizer product page.

Glossary

Terms used on this page
Job shop (JSP)
A scheduling problem. Each job is a fixed sequence of operations, and each operation uses one given machine.
Flexible job shop (FJSP)
A job shop in which each operation can use one of several machines, each with its own duration.
Reentrant job shop
A job shop in which a job can use the same machine more than once. JSPLib treats it as a flexible job shop with one option.
Operation
One step of a job. It has a machine (or a set of machine options) and a duration.
Instance
One concrete problem: a set of jobs, machines and durations.
Makespan
The end time of the last operation in a schedule. The solvers minimize it.
Upper bound (UB)
The makespan of a valid schedule. The optimum is equal to it or smaller.
Lower bound (LB)
A value that the optimum cannot be smaller than, from a proof or a relaxation.
Optimality gap
(UB − LB) / UB. A gap of 0 is a proof of optimality.
Best known solution (BKS)
The best LB and the best UB that anyone found for an instance. The archive stores both.
Certificate
A stored schedule or proof that lets another person check a bound.
Carlier bound
A classic one-machine lower bound for job-shop makespan.
Closed / open
Closed: the optimum is known with a proof. Open: no proof of optimality exists.
Reference engine
One of the four solvers that the site runs with the fixed protocol.
CP (constraint programming)
A solver method that searches over decisions and removes impossible values with propagation.
MIP (mixed-integer programming)
A solver method that writes the problem as linear constraints with integer variables.
Lazy clause generation (LCG)
A CP method that learns new constraints (clauses) from conflicts, as SAT solvers do. CP-SAT uses it.
Gap tolerance
A solver setting. The solver stops and reports "optimal" when its gap is smaller than this value.
Geometric average
exp of the mean of the logs. It treats ratios fairly, so one large instance does not dominate.

Sources