File size: 3,546 Bytes
52c82e4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
"""Tabulate DASH-JSP results against published metaheuristic and RL baselines.

Published numbers are quoted, not re-run.

References
----------
- Goncalves, J. F., Mendes, J. J., Resende, M. G. C. (2005). A hybrid genetic
  algorithm for the job shop scheduling problem. EJOR 167(1), 77-95.
- Nowicki, E., Smutnicki, C. (2005). An advanced tabu search algorithm for the
  job shop problem. Journal of Scheduling 8(2), 145-159.
- Zhang, C. et al. (2020). Learning to dispatch for job shop scheduling via
  deep reinforcement learning. NeurIPS.
- Park, J. et al. (2021). Learning to schedule job-shop problems: representation
  and policy learning using graph neural network and reinforcement learning.
  IJPR 59(11), 3360-3377.

Outputs
-------
results/comparisons.md and results/comparisons.csv
"""

from __future__ import annotations

import argparse
from pathlib import Path

import pandas as pd


# Published average optimality gap (%) on Taillard, by method.
# Numbers compiled from the references above. Where multiple variants exist
# in the same paper, we quote the best-reported aggregate. These values are
# QUOTED, not re-computed.
PUBLISHED_TAILLARD_GAPS = {
    "Goncalves 2005 (Hybrid GA)":         5.30,
    "Nowicki & Smutnicki 2005 (TS)":      5.46,
    "Zhang et al. 2020 (Deep RL, L2D)":  17.24,  # average across all sizes
    "Park et al. 2021 (GNN + RL)":       15.38,
    "FIFO":                               43.0,
    "EDD":                                40.0,
    "WSPT":                               18.5,
    "ATC":                                14.0,
    "MWKR (most work remaining)":         13.0,
}


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--results", default="results/benchmark_full.csv",
        help="DASH-JSP benchmark CSV produced by scripts/run_evaluation.py",
    )
    parser.add_argument("--out-dir", default="results")
    args = parser.parse_args()

    out_dir = Path(args.out_dir)
    out_dir.mkdir(parents=True, exist_ok=True)

    rows = []
    for k, v in PUBLISHED_TAILLARD_GAPS.items():
        rows.append({"method": k, "source": "published", "mean_gap_pct": v})

    # Add DASH-JSP rows from local results, if available.
    p = Path(args.results)
    if p.exists():
        df = pd.read_csv(p)
        df = df[df["family"] == "taillard"]
        agg = df.groupby("method")["optimality_gap_pct"].mean()
        for m, v in agg.items():
            rows.append({"method": f"DASH-JSP ({m})", "source": "this work", "mean_gap_pct": float(v)})
    else:
        rows.append({
            "method": "DASH-JSP (LinUCB)",
            "source": "this work",
            "mean_gap_pct": "TBD (run scripts/run_evaluation.py)",
        })

    df_out = pd.DataFrame(rows)
    df_out.to_csv(out_dir / "comparisons.csv", index=False)

    md = ["# DASH-JSP vs. published methods on Taillard (mean optimality gap, %)", ""]
    md.append("| Method | Source | Mean gap (%) |")
    md.append("|---|---|---:|")
    for r in rows:
        v = r["mean_gap_pct"]
        v_s = f"{v:.2f}" if isinstance(v, (int, float)) else str(v)
        md.append(f"| {r['method']} | {r['source']} | {v_s} |")

    md.append("")
    md.append(
        "*Smaller is better. Published numbers are quoted from the cited papers; "
        "DASH-JSP numbers are computed in this work.*",
    )
    (out_dir / "comparisons.md").write_text("\n".join(md), encoding="utf-8")
    print((out_dir / "comparisons.md").read_text(encoding="utf-8"))


if __name__ == "__main__":
    main()