From 9c494bac60061fbd8528d7a7518edcb4ae7464a0 Mon Sep 17 00:00:00 2001 From: "Jip J. Dekker" Date: Fri, 9 Jul 2021 14:07:26 +1000 Subject: [PATCH] Update analysis scripts --- analyse_chuffed.py | 162 ++++++++++++++++++++++++++++++--------------- analyse_gecode.py | 1 - 2 files changed, 107 insertions(+), 56 deletions(-) diff --git a/analyse_chuffed.py b/analyse_chuffed.py index cda80c8..551a3b2 100755 --- a/analyse_chuffed.py +++ b/analyse_chuffed.py @@ -13,6 +13,8 @@ import os import re import sys +from statistics import stdev + def compute_area(file, time): area = -1 @@ -30,74 +32,124 @@ def compute_area(file, time): if match: objectives.append(int(match.group(1))) continue - match = re.match(r"%\stime elapsed:\s(\d+)\sms", line) + match = re.match(r"%\stime elapsed:\s(\d+\.\d+)\ss", line) if match: - times.append(int(match.group(1))) + times.append(float(match.group(1))) continue - times.append(time) + # Not proven optimal + if len(times) == len(objectives): + times.append(time) assert len(objectives) > 0 assert len(objectives) + 1 == len(times) area = 0 for i in range(len(objectives)): - area += ((times[i + 1] - times[i]) / 1000) * objectives[i] + area += (times[i + 1] - times[i]) * objectives[i] return int(area) folder = sys.argv[1] -stats = {} -for root, dirs, files in os.walk(folder): - for name in files: - if name.endswith(".sol"): - seed = 1 - match = re.search(r"\.(\d+)\.sol", name) - if match: - seed = int(match.group(1)) - with open(os.path.join(root, name)) as f: - contents = f.readlines() +statistics = dict() +instances = set() +for config in ["original", "restart"]: + for root, dirs, files in os.walk(folder + "/" + config): + for name in files: + if name.endswith(".sol"): + components = name[:-(4)].split(".") + data = components[0] + instances.add(data) + seed = 1 + if len(components) > 1: + assert len(components) == 2 + seed = components[1] - statistics = {} - print(contents) - for line in contents: - # Nodes - match = re.search(r"nodes=(\d+)", line) - if match: - statistics["nodes"] = int(match.group(1)) - continue - # Solve time - match = re.search(r"solveTime=(\d+\.\d+)", line) - if match: - statistics["search_time"] = int(float(match.group(1)) * 1000) - continue - # Restarts - match = re.search(r"restart count:\s+(\d+)", line) - if match: - statistics["restarts"] = int(match.group(1)) - continue + if data not in statistics: + statistics[data] = dict() + if config not in statistics[data]: + statistics[data][config] = [] - for line in contents[::-1]: - # Best objective - match = re.match(r"objective\s=\s(\d+)", line) - if match: - statistics["objective"] = int(match.group(1)) - break - # Area - area = compute_area(contents, statistics["search_time"]) + with open(os.path.join(root, name)) as f: + contents = f.readlines() - stats[name[:-(4)].replace(".", ",")] = ( - area, - statistics["objective"], - statistics["search_time"], - statistics["restarts"], - statistics["nodes"], + nodes = None + solvetime = None + restarts = None + objective = None + for line in contents: + # Nodes + match = re.search(r"%%%mzn-stat: nodes=(\d+)", line) + if match: + nodes = int(match.group(1)) + continue + # Solve time + match = re.search(r"%%%mzn-stat: solveTime=(\d+\.\d+)", line) + if match: + solvetime = float(match.group(1)) + continue + # Restarts + match = re.search(r"%%%mzn-stat: restarts=(\d+)", line) + if match: + restarts = int(match.group(1)) + continue + + for line in contents[::-1]: + # Best objective + match = re.match(r"%%%mzn-stat: objective=(-?\d+)", line) + if match: + objective = int(match.group(1)) + break + # Area + area = compute_area(contents, solvetime) + + statistics[data][config].append( + ( + area, + objective, + solvetime, + restarts, + nodes, + ) + ) + +for data in instances: + for config in ["original", "restart"]: + stats = statistics[data][config] + cumulative = stats[0] + for i in range(1, len(stats)): + cumulative = tuple(map(sum, zip(cumulative, stats[i]))) + avg = tuple([x / len(stats) for x in cumulative]) + dev = stdev([x[1] for x in stats]) if len(stats) > 1 else 0 + # (avg area, avg objective, stdev objective) + statistics[data][config] = (avg[0], avg[1], dev) + +# Print header +print( + """ +\\begin{tabular}{l|rr|rr|rr} +\\toprule +& \multicolumn{2}{c|}{Chuffed} & \multicolumn{2}{c|}{Chuffed Restart} \\\\ +Instance & $\intobj$ & $\minobj$ & $\intobj$ & $\minobj$ \\\\ +\midrule +""" +) + +sorted_instances = sorted(instances) +for data in sorted_instances: + print(f"{data}", end="") + for config in ["original", "restart"]: + print( + f" & {int(statistics[data][config][0] / 1000) }k & {int(statistics[data][config][1])}", + end="", + ) + if statistics[data][config][2] != 0: + print("^{", end="") + print( + int(statistics[data][config][2] / statistics[data][config][1] * 100), + # int(statistics[data][config][2]), + end="", ) + print("}", end="") + print(" \\\\") -sorted_stats = sorted(stats.items()) -a = sorted_stats[0][0][: sorted_stats[0][0].find(",")] -for key, val in sorted_stats: - if key[: key.find(",")] != a: - print("\n\n") - a = key[: key.find(",")] - print("%s,%s" % (key, ",".join([v.__str__() for v in val]))) - -exit(1) +# Print footer +print("\n\\bottomrule\n\end{tabular}") diff --git a/analyse_gecode.py b/analyse_gecode.py index 90fb8ce..99c6c53 100755 --- a/analyse_gecode.py +++ b/analyse_gecode.py @@ -8,7 +8,6 @@ area which can be found by adding 'constraint trace("% init_area = \(ub(objective));\n", true);' to the model in question. """ -import csv import os import re import sys