JustinTX's picture
Add files using upload-large-folder tool
13d6258 verified
"""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
# ── Circle Packing ──────────────────────────────────────────────────
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}"
# boundary check
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"
# overlap check
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}
# ── Erdos Min Overlap ───────────────────────────────────────────────
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))
# normalize if needed
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}
# ── AC1 ─────────────────────────────────────────────────────────────
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}"
# Use FFT for large sequences
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}
# ── Main ────────────────────────────────────────────────────────────
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}")