diff --git a/examples/alphaevolve_math_problems/second_autocorr_ineq/evaluator.py b/examples/alphaevolve_math_problems/second_autocorr_ineq/evaluator.py index ce51b43d69..84b80c125a 100644 --- a/examples/alphaevolve_math_problems/second_autocorr_ineq/evaluator.py +++ b/examples/alphaevolve_math_problems/second_autocorr_ineq/evaluator.py @@ -27,6 +27,9 @@ def verify_c2_solution(f_values: np.ndarray, c2_achieved_from_opt: float, n_poin if f_values.shape != (n_points,): raise ValueError(f"Expected function values shape {(n_points,)}. Got {f_values.shape}.") + if not np.isfinite(f_values).all(): + raise ValueError("Function values must be finite.") + if np.any(f_values < -1e-6): # Allow for small floating point errors raise ValueError("Function must be non-negative.") diff --git a/examples/alphaevolve_math_problems/third_autocorr_ineq/evaluator.py b/examples/alphaevolve_math_problems/third_autocorr_ineq/evaluator.py index b33c77d62b..ba915ed5b7 100644 --- a/examples/alphaevolve_math_problems/third_autocorr_ineq/evaluator.py +++ b/examples/alphaevolve_math_problems/third_autocorr_ineq/evaluator.py @@ -27,6 +27,9 @@ def verify_c3_solution(f_values: np.ndarray, c3_achieved: float, n_points: int): if f_values.shape != (n_points,): raise ValueError(f"Expected function values shape {(n_points,)}. Got {f_values.shape}.") + if not np.isfinite(f_values).all() or not np.isfinite(c3_achieved): + raise ValueError("Function values and the reported C3 must be finite.") + # Recompute C3 using NumPy to verify dx = 0.5 / n_points diff --git a/tests/test_autocorr_evaluators_finite.py b/tests/test_autocorr_evaluators_finite.py new file mode 100644 index 0000000000..33a05a0964 --- /dev/null +++ b/tests/test_autocorr_evaluators_finite.py @@ -0,0 +1,80 @@ +"""The second/third autocorrelation example evaluators must reject non-finite inputs and still score valid ones.""" + +import importlib.util +import os +import tempfile +import unittest + +import numpy as np + +BASE = os.path.join(os.path.dirname(__file__), "..", "examples", "alphaevolve_math_problems") + + +def _load(name): + spec = importlib.util.spec_from_file_location("ev_" + name, os.path.join(BASE, name, "evaluator.py")) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def _write_program(directory, name, f_values, claimed, n_points): + path = os.path.join(directory, name + ".py") + with open(path, "w") as handle: + handle.write( + "import numpy as np\n" + "def run():\n" + f" return np.array({[float(x) for x in f_values]!r}), {float(claimed)!r}, 0.0, {int(n_points)}\n" + ) + return path + + +def _c3(f_values): + dx = 0.5 / len(f_values) + return np.max(np.abs(np.convolve(f_values, f_values))) * dx / (np.sum(f_values) * dx) ** 2 + + +class TestAutocorrEvaluatorsFinite(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.second = _load("second_autocorr_ineq") + cls.third = _load("third_autocorr_ineq") + + def setUp(self): + self._tmp = tempfile.TemporaryDirectory() + self.addCleanup(self._tmp.cleanup) + self.dir = self._tmp.name + + def test_second_rejects_nan_and_inf(self): + for i, bad in enumerate((np.nan, np.inf, -np.inf)): + f = np.ones(10) + f[3] = bad + result = self.second.evaluate(_write_program(self.dir, f"s_bad{i}", f, 0.9, 10)) + self.assertIn("error", result) + self.assertEqual(result["combined_score"], 0.0) + + def test_second_accepts_valid(self): + result = self.second.evaluate(_write_program(self.dir, "s_ok", np.ones(10), 0.9, 10)) + self.assertNotIn("error", result) + self.assertGreater(result["combined_score"], 0.0) + self.assertTrue(np.isfinite(result["c2"])) + + def test_third_rejects_nan_inf_and_nonfinite_claim(self): + for i, bad in enumerate((np.nan, np.inf, -np.inf)): + f = np.ones(10) + f[3] = bad + result = self.third.evaluate(_write_program(self.dir, f"t_bad{i}", f, 1.5, 10)) + self.assertIn("error", result) + self.assertEqual(result["combined_score"], 0.0) + result = self.third.evaluate(_write_program(self.dir, "t_nanclaim", np.ones(10), np.nan, 10)) + self.assertIn("error", result) + self.assertEqual(result["combined_score"], 0.0) + + def test_third_accepts_valid(self): + f = np.ones(10) + result = self.third.evaluate(_write_program(self.dir, "t_ok", f, _c3(f), 10)) + self.assertNotIn("error", result) + self.assertGreater(result["combined_score"], 0.0) + + +if __name__ == "__main__": + unittest.main()