| """Standalone evaluator for all baseline solutions. |
| |
| Runs each solution directly (no subprocess) and applies the same |
| validation/scoring logic as the evaluate_ori.py files. |
| """ |
|
|
| import sys |
| import os |
| import time |
| import importlib.util |
| import numpy as np |
| from scipy.signal import fftconvolve |
|
|
| BASEDIR = os.path.dirname(os.path.abspath(__file__)) |
| RESULTS = os.path.join(BASEDIR, "results") |
|
|
|
|
| def load_module(path, name): |
| spec = importlib.util.spec_from_file_location(name, path) |
| mod = importlib.util.module_from_spec(spec) |
| sys.modules[name] = mod |
| spec.loader.exec_module(mod) |
| return mod |
|
|
|
|
| |
| def eval_circle_packing(path): |
| name = os.path.splitext(os.path.basename(path))[0] |
| mod = load_module(path, f"cp_{name}") |
| t0 = time.time() |
| centers, radii, reported_sum = mod.run_packing() |
| elapsed = time.time() - t0 |
|
|
| centers = np.asarray(centers) |
| radii = np.asarray(radii) |
| assert centers.shape == (26, 2), f"centers shape {centers.shape}" |
| assert radii.shape == (26,), f"radii shape {radii.shape}" |
| assert np.all(radii >= 0), "negative radii" |
|
|
| actual_sum = float(np.sum(radii)) |
| assert np.isclose(actual_sum, reported_sum, atol=1e-6), \ |
| f"sum mismatch: actual={actual_sum}, reported={reported_sum}" |
|
|
| |
| for i in range(26): |
| x, y, r = centers[i, 0], centers[i, 1], radii[i] |
| assert x - r >= -1e-6 and x + r <= 1 + 1e-6, f"circle {i} outside x" |
| assert y - r >= -1e-6 and y + r <= 1 + 1e-6, f"circle {i} outside y" |
|
|
| |
| for i in range(26): |
| for j in range(i + 1, 26): |
| dist = np.sqrt(np.sum((centers[i] - centers[j]) ** 2)) |
| assert dist >= radii[i] + radii[j] - 1e-6, \ |
| f"circles {i}&{j} overlap: dist={dist:.6f}, sum_r={radii[i]+radii[j]:.6f}" |
|
|
| return {"combined_score": actual_sum, "elapsed": elapsed} |
|
|
|
|
| |
| def eval_erdos(path): |
| name = os.path.splitext(os.path.basename(path))[0] |
| mod = load_module(path, f"erdos_{name}") |
| t0 = time.time() |
| h_values, c5_bound, n_points = mod.run(seed=42, budget_s=10.0) |
| elapsed = time.time() - t0 |
|
|
| h_values = np.asarray(h_values, dtype=np.float64) |
| n_points = int(n_points) |
| assert h_values.ndim == 1 and h_values.shape[0] == n_points |
| assert np.all(np.isfinite(h_values)) |
|
|
| |
| target = n_points / 2.0 |
| cur = float(np.sum(h_values)) |
| if abs(cur - target) > 1e-8: |
| h_values = h_values * (target / cur) |
|
|
| assert np.all(h_values >= -1e-10) and np.all(h_values <= 1 + 1e-10), \ |
| f"h out of [0,1]: [{h_values.min()}, {h_values.max()}]" |
|
|
| dx = 2.0 / n_points |
| correlation = np.correlate(h_values, 1.0 - h_values, mode="full") * dx |
| computed_c5 = float(np.max(correlation)) |
|
|
| assert np.isclose(computed_c5, float(c5_bound), atol=1e-4), \ |
| f"C5 mismatch: computed={computed_c5:.8f}, reported={float(c5_bound):.8f}" |
|
|
| return {"combined_score": -computed_c5, "c5": computed_c5, "elapsed": elapsed} |
|
|
|
|
| |
| def eval_ac1(path): |
| name = os.path.splitext(os.path.basename(path))[0] |
| mod = load_module(path, f"ac1_{name}") |
| t0 = time.time() |
| seq = mod.run(seed=42, budget_s=10.0) |
| elapsed = time.time() - t0 |
|
|
| assert isinstance(seq, list) and len(seq) > 0 |
| a = np.array([float(x) for x in seq]) |
| a = np.clip(a, 0.0, 1000.0) |
|
|
| n = len(a) |
| s = float(np.sum(a)) |
| assert s >= 0.01, f"sum too small: {s}" |
|
|
| |
| if n > 500: |
| conv = fftconvolve(a, a) |
| else: |
| conv = np.convolve(a, a) |
| max_b = float(np.max(conv)) |
| value = 2.0 * n * max_b / (s * s) |
|
|
| return {"combined_score": -value, "ac1_value": value, "n": n, "elapsed": elapsed} |
|
|
|
|
| |
| if __name__ == "__main__": |
| tasks = { |
| "circle_packing": { |
| "eval_fn": eval_circle_packing, |
| "files": ["thetaevolve.py", "autoevolve.py"], |
| }, |
| "erdos_min_overlap": { |
| "eval_fn": eval_erdos, |
| "files": ["ttt_discover.py", "autoevolve.py"], |
| }, |
| "alphaevolve_ac": { |
| "eval_fn": eval_ac1, |
| "files": ["ttt_discover.py", "alphaevolve_v2.py", "autoevolve.py"], |
| }, |
| } |
|
|
| for task_name, cfg in tasks.items(): |
| print(f"\n{'='*60}") |
| print(f" {task_name}") |
| print(f"{'='*60}") |
| for fname in cfg["files"]: |
| fpath = os.path.join(RESULTS, task_name, fname) |
| if not os.path.exists(fpath): |
| print(f" {fname}: FILE NOT FOUND") |
| continue |
| try: |
| result = cfg["eval_fn"](fpath) |
| parts = [f"{k}={v:.8f}" if isinstance(v, float) else f"{k}={v}" |
| for k, v in result.items()] |
| print(f" {fname}: {', '.join(parts)}") |
| except Exception as e: |
| print(f" {fname}: ERROR - {e}") |
|
|