forked from ANRGUSC/saga
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathanalyze.py
More file actions
194 lines (161 loc) · 6.11 KB
/
Copy pathanalyze.py
File metadata and controls
194 lines (161 loc) · 6.11 KB
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
import logging
import pathlib
from functools import lru_cache
from typing import Dict
import dill as pickle
import matplotlib.pyplot as plt
import pandas as pd
from saga.utils.draw import gradient_heatmap
from simulated_annealing import SimulatedAnnealing
thisdir = pathlib.Path(__file__).parent.absolute()
SCHEDULER_RENAMES = {
"Cpop": "CPoP",
"Heft": "HEFT",
}
@lru_cache(maxsize=1)
def load_results(resultspath: pathlib.Path) -> Dict[str, Dict[str, SimulatedAnnealing]]:
"""Load results from resultspath.
Args:
resultspath: path to results directory
Returns:
results: dict of dicts of SimulatedAnnealing objects
"""
results = {}
for base_path in resultspath.glob("*"):
results[base_path.name] = {}
for path in base_path.glob("*.pkl"):
results[base_path.name][path.stem] = pickle.loads(path.read_bytes())
return results
def to_df(results: Dict[str, Dict[str, SimulatedAnnealing]]) -> pd.DataFrame:
"""Convert results to dataframe.
Args:
results: dict of dicts of SimulatedAnnealing objects
Returns:
df_results: dataframe of results
"""
rows = []
for base_scheduler_name, base_scheduler_results in results.items():
for scheduler_name, scheduler_results in base_scheduler_results.items():
makespan_ratio = scheduler_results.iterations[-1].best_energy
rows.append([base_scheduler_name, scheduler_name, makespan_ratio])
df_results = pd.DataFrame(rows, columns=["Base Scheduler", "Scheduler", "Makespan Ratio"])
return df_results
def load_results_csv(outputpath: pathlib.Path) -> pd.DataFrame:
"""Load results from outputpath.
Args:
outputpath: path to output directory
Returns:
df_results: dataframe of results
"""
df_results = pd.read_csv(outputpath.joinpath("results.csv"), index_col=0)
return df_results
def results_to_csv(resultspath: pathlib.Path,
outputpath: pathlib.Path):
"""Convert results to csv.
Args:
resultspath: path to results directory
outputpath: path to output directory
Returns:
df_results: dataframe of results
"""
df_results = to_df(load_results(resultspath))
df_results.to_csv(outputpath.joinpath("results.csv"))
def tab_results(resultsdir: pathlib.Path,
savedir: pathlib.Path,
upper_threshold: float = 5.0,
include_hybrid = False,
add_worst_row = True,
title: str = None,
savename: str = "results",
mode: str = None) -> None:
"""Generate table of results.
Args:
resultsdir: path to results directory
savedir: path to save directory
upper_threshold: upper threshold for heatmap
include_hybrid: whether to include hybrid results
add_worst_row: whether to add a row for the worst result
title: title for plot
savename: name for plot
mode: "pdf", "png", or None. None saves both.
"""
savedir.mkdir(parents=True, exist_ok=True)
df_all_results = load_results_csv(resultsdir)
# rename some schedulers via dict
rename_dict = {
"CPOP": "CPoP",
"Fastest Node": "FastestNode",
**SCHEDULER_RENAMES
}
rename_dict = {
**rename_dict,
**{f"Not{key}": f"Not{value}" for key, value in rename_dict.items()}
}
df_all_results["Scheduler"] = df_all_results["Scheduler"].replace(rename_dict)
df_all_results["Base Scheduler"] = df_all_results["Base Scheduler"].replace(rename_dict)
df_results = df_all_results[
(~df_all_results["Scheduler"].str.startswith("Not")) &
(~df_all_results["Base Scheduler"].str.startswith("Not"))]
if include_hybrid:
hybrid_values = []
for scheduler in df_results["Scheduler"].unique():
# get NotScheduler Base Scheduler result
res = df_all_results[
(df_all_results["Scheduler"] == scheduler) &
(df_all_results["Base Scheduler"] == f"Not{scheduler}")
]
try:
hybrid_values.append([scheduler, "Hybrid", res["Makespan Ratio"].values[0]])
except IndexError:
pass
# append hybrid values to df_results
df_hybrid = pd.DataFrame(hybrid_values, columns=["Scheduler", "Base Scheduler", "Makespan Ratio"])
df_results = pd.concat([df_results, df_hybrid], ignore_index=True)
if add_worst_row:
worst_results = df_results.groupby("Scheduler")["Makespan Ratio"].max()
df_worst = pd.DataFrame(
[[scheduler, "Worst", worst_results[scheduler]]
for scheduler in worst_results.index],
columns=["Scheduler", "Base Scheduler", "Makespan Ratio"]
)
df_results = pd.concat([df_results, df_worst], ignore_index=True)
def default_order(x):
return x.replace("Hybrid", "ZHybrid").replace("Worst", "ZWorst").replace(r"\textit", "AA")
axis = gradient_heatmap(
df_results,
x="Scheduler",
y="Base Scheduler",
color="Makespan Ratio",
upper_threshold=upper_threshold,
x_label="Scheduler",
y_label="Base Scheduler",
color_label="Makespan Ratio",
# custom order so that "Hybrid" and "Worst" are at the bottom
xorder=default_order,
yorder=default_order,
# include_cell_labels=True,
title=title,
cell_font_size=12.0
)
plt.tight_layout()
if mode is None or mode == "pdf":
axis.get_figure().savefig(
savedir / f"{savename}.pdf",
dpi=300,
bbox_inches='tight'
)
if mode is None or mode == "png":
axis.get_figure().savefig(
savedir / f"{savename}.png",
dpi=300,
bbox_inches='tight'
)
def main():
logging.basicConfig(level=logging.INFO)
resultsdir = thisdir.joinpath("results")
outputdir = thisdir.joinpath("output")
outputdir.mkdir(parents=True, exist_ok=True)
results_to_csv(resultsdir, outputdir)
tab_results(outputdir, outputdir, mode="pdf")
if __name__ == "__main__":
main()