File size: 2,421 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
"""Generate publication figures from results CSVs."""

from __future__ import annotations

import argparse
from pathlib import Path

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd


def fig_optimality_gap_bar(df: pd.DataFrame, out: Path) -> None:
    agg = df.groupby("method")["optimality_gap_pct"].mean().sort_values()
    fig, ax = plt.subplots(figsize=(10, 5))
    ax.barh(agg.index, agg.values)
    ax.set_xlabel("Mean optimality gap (%)")
    ax.set_title("Mean optimality gap per method (lower is better)")
    ax.grid(True, alpha=0.3, axis="x")
    plt.tight_layout()
    plt.savefig(out, dpi=150)
    plt.close()


def fig_per_family_gap(df: pd.DataFrame, out: Path) -> None:
    pivot = df.groupby(["family", "method"])["optimality_gap_pct"].mean().unstack()
    fig, ax = plt.subplots(figsize=(10, 6))
    pivot.plot(kind="bar", ax=ax)
    ax.set_ylabel("Mean optimality gap (%)")
    ax.set_title("Per-family optimality gap")
    ax.grid(True, alpha=0.3, axis="y")
    plt.tight_layout()
    plt.savefig(out, dpi=150)
    plt.close()


def fig_pareto(df: pd.DataFrame, out: Path) -> None:
    if "total_tardiness" not in df.columns:
        return
    means = df.groupby("method").agg(
        mk=("makespan", "mean"),
        td=("total_tardiness", "mean"),
    ).reset_index()
    fig, ax = plt.subplots(figsize=(8, 6))
    for _, r in means.iterrows():
        ax.scatter(r["mk"], r["td"], s=80)
        ax.annotate(r["method"], (r["mk"], r["td"]),
                    xytext=(5, 5), textcoords="offset points", fontsize=8)
    ax.set_xlabel("Mean makespan")
    ax.set_ylabel("Mean tardiness")
    ax.set_title("Pareto: makespan vs tardiness")
    ax.grid(True, alpha=0.3)
    plt.tight_layout()
    plt.savefig(out, dpi=150)
    plt.close()


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("--results", default="results/benchmark_full.csv")
    parser.add_argument("--out-dir", default="results/figures")
    args = parser.parse_args()

    df = pd.read_csv(args.results)
    out_dir = Path(args.out_dir)
    out_dir.mkdir(parents=True, exist_ok=True)

    fig_optimality_gap_bar(df, out_dir / "optimality_gap_bar.png")
    fig_per_family_gap(df, out_dir / "per_family_gap.png")
    fig_pareto(df, out_dir / "pareto.png")
    print(f"Wrote figures to {out_dir}/")


if __name__ == "__main__":
    main()