"""Generate LaTeX tables + numeric macros from results.json.""" import json, os, numpy as np R = json.load(open("results.json")) OUT = "/app/paper"; os.makedirs(OUT, exist_ok=True) S = R["summary"] TOPOS = R["config"]["topos"]; LAMS = R["config"]["lambdas"] NR = R["config"]["n_runs"] METHODS = R["config"]["baselines"] PRETTY = {"RoundRobin": "Round Robin", "LeastConn": "Least Conn.", "ACO": "ACO", "PSO": "PSO", "WOA": "WOA", "AdaptiSwarm": "\\textbf{AdaptiSwarm}"} def g(nn, lam, m, metric): return S[str(nn)][str(lam)][m][metric] def fmt(v, d=2): return f"{v:.{d}f}" def best_mask(nn, lam, metric, lower_better=True): vals = {m: g(nn, lam, m, metric)[0] for m in METHODS} bv = min(vals.values()) if lower_better else max(vals.values()) return {m: (abs(vals[m] - bv) < 1e-9) for m in METHODS} def make_table(metric, caption, label, d=2, lower_better=True, mult=1.0): l = []; l.append("\\begin{table}[t]"); l.append("\\centering") l.append(f"\\caption{{{caption}}}"); l.append(f"\\label{{{label}}}") l.append("\\setlength{\\tabcolsep}{3pt}"); l.append("\\footnotesize") l.append("\\begin{tabular}{ll" + "c" * len(LAMS) + "}"); l.append("\\toprule") l.append("Nodes & Method & " + " & ".join([f"$\\lambda{{=}}{x}$" for x in LAMS]) + " \\\\") l.append("\\midrule") for ti, nn in enumerate(TOPOS): for mi, m in enumerate(METHODS): row = [] nc = f"\\multirow{{{len(METHODS)}}}{{*}}{{{nn}}}" if mi == 0 else "" row.append(nc); row.append(PRETTY[m]) for lam in LAMS: bm = best_mask(nn, lam, metric, lower_better) mean, std = g(nn, lam, m, metric) cell = f"{fmt(mean*mult, d)}" if bm[m]: cell = "\\underline{" + cell + "}" row.append(cell) l.append(" & ".join(row) + " \\\\") if ti != len(TOPOS) - 1: l.append("\\midrule") l.append("\\bottomrule"); l.append("\\end{tabular}"); l.append("\\end{table}") return "\n".join(l) with open(os.path.join(OUT, "table_latency.tex"), "w") as f: f.write(make_table("latency_ms", f"Avg Task Latency (ms), {NR} runs.", "tab:latency", d=2)) with open(os.path.join(OUT, "table_util.tex"), "w") as f: f.write(make_table("utilization", f"Mean Utilization (\\%), {NR} runs.", "tab:util", d=1, lower_better=False)) with open(os.path.join(OUT, "table_energy.tex"), "w") as f: f.write(make_table("energy", f"Energy (J/step), {NR} runs.", "tab:energy", d=2)) with open(os.path.join(OUT, "table_conv.tex"), "w") as f: f.write(make_table("A_deadline", f"Class A Deadline Met (\\%), {NR} runs.", "tab:conv", d=1, lower_better=False)) with open(os.path.join(OUT, "table_jain.tex"), "w") as f: f.write(make_table("jain", f"Jain Fairness Index, {NR} runs.", "tab:jain", d=3, lower_better=False)) abl = R["ablation"] abl_pretty = {"Abl_ACOonly": "V1: ACO only", "Abl_PSOrand": "V2: PSO (random)", "Abl_PSOseed": "V3: ACO-seeded PSO", "AdaptiSwarm": "\\textbf{Full}"} order = ["Abl_ACOonly", "Abl_PSOrand", "Abl_PSOseed", "AdaptiSwarm"] al = []; al.append("\\begin{table}[t]"); al.append("\\centering") al.append(f"\\caption{{Ablation, {TOPOS[-1]}-node $\\lambda=200$, {NR} runs.}}") al.append("\\label{tab:ablation}"); al.append("\\footnotesize") al.append("\\setlength{\\tabcolsep}{4pt}"); al.append("\\begin{tabular}{lccc}") al.append("\\toprule"); al.append("Variant & Latency (ms) & Util. (\\%) & Conv. iters \\\\"); al.append("\\midrule") for m in order: lat = abl["episode"][m]["latency_ms"]; util = abl["episode"][m]["utilization"]; conv = abl["convergence"][m] al.append(f"{abl_pretty[m]} & {lat[0]:.2f}$\\pm${lat[1]:.2f} & {util[0]:.1f}$\\pm${util[1]:.1f} & {conv[0]:.1f}$\\pm${conv[1]:.1f} \\\\") al.append("\\bottomrule"); al.append("\\end{tabular}"); al.append("\\end{table}") with open(os.path.join(OUT, "table_ablation.tex"), "w") as f: f.write("\n".join(al)) def avg_gain(metric, ref, lower_better=True, regimes=None): if regimes is None: regimes = [(25,100),(25,200),(50,100),(50,200)] gs = [] for nn, lam in regimes: a = g(nn, lam, "AdaptiSwarm", metric)[0]; b = g(nn, lam, ref, metric)[0] if b == 0: continue gs.append((1 - a/b)*100 if lower_better else (a/b - 1)*100) return float(np.mean(gs)) if gs else 0.0 nn_l, lam_l = TOPOS[-1], LAMS[-1] lat_gain = avg_gain("latency_ms", "PSO", True) en_gain = avg_gain("energy", "PSO", True) lat_gain_aco = (1 - g(nn_l, lam_l, "AdaptiSwarm", "latency_ms")[0] / g(nn_l, lam_l, "ACO", "latency_ms")[0]) * 100 qos_gain = g(nn_l, lam_l, "AdaptiSwarm", "A_deadline")[0] - g(nn_l, lam_l, "RoundRobin", "A_deadline")[0] conv = R["convergence"]["iters"]; conv_gain = (1 - conv["AdaptiSwarm"][0] / conv["PSO"][0]) * 100 jain_gain = (g(nn_l, lam_l, "AdaptiSwarm", "jain")[0] / g(nn_l, lam_l, "PSO", "jain")[0] - 1) * 100 macros = [] def mac(name, val): macros.append(f"\\newcommand{{\\{name}}}{{{val}}}") mac("nRuns", NR); mac("nodesList", "$"+"$, $".join(str(t) for t in TOPOS)+"$") mac("nodesSmall", TOPOS[0]); mac("nodesMedium", TOPOS[1]); mac("nodesLarge", TOPOS[2]) mac("weightAlpha", "0.5"); mac("weightBeta", "0.3"); mac("weightGamma", "0.2") mac("latGainMax", f"{lat_gain:.0f}\\%"); mac("energyGainMax", f"{en_gain:.0f}\\%") mac("convGain", f"{conv_gain:.0f}\\%"); mac("latGainACO", f"{lat_gain_aco:.0f}\\%") mac("qosGain", f"{qos_gain:.0f} pp"); mac("jainGain", f"{jain_gain:.0f}\\%") with open(os.path.join(OUT, "numbers.tex"), "w") as f: f.write("\n".join(macros) + "\n") print("Done.", flush=True)