From 0bbd083f410ca3a2dafb85877976a8032f2b0f0b Mon Sep 17 00:00:00 2001 From: fixfon <12512757+fixfon@users.noreply.github.com> Date: Mon, 26 Oct 2026 18:58:33 +0300 Subject: [PATCH] fix(examples): reject non-finite values in first_autocorr_ineq evaluator A NaN or +inf entry in f_values made computed_c1 NaN, so the C1 consistency check (a NaN comparison, always False) never fired and the candidate's claimed c1 was scored as is. Reject non-finite values before the non-negativity check. -inf was already rejected there and now reports the finite error instead. Fixes #549 --- .../first_autocorr_ineq/evaluator.py | 3 + tests/test_first_autocorr_ineq_evaluator.py | 77 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 tests/test_first_autocorr_ineq_evaluator.py diff --git a/examples/alphaevolve_math_problems/first_autocorr_ineq/evaluator.py b/examples/alphaevolve_math_problems/first_autocorr_ineq/evaluator.py index f0e32b7838..ceec8864b3 100644 --- a/examples/alphaevolve_math_problems/first_autocorr_ineq/evaluator.py +++ b/examples/alphaevolve_math_problems/first_autocorr_ineq/evaluator.py @@ -28,6 +28,9 @@ def verify_autocorrelation_solution(f_values: np.ndarray, c1_achieved: float, n_ 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") + # Check non-negativity if np.any(f_values < 0.0): raise ValueError("Function must be non-negative.") diff --git a/tests/test_first_autocorr_ineq_evaluator.py b/tests/test_first_autocorr_ineq_evaluator.py new file mode 100644 index 0000000000..418aee9b76 --- /dev/null +++ b/tests/test_first_autocorr_ineq_evaluator.py @@ -0,0 +1,77 @@ +"""Regression tests for issue #549: first_autocorr_ineq must reject NaN/inf function values.""" + +import importlib.util +import sys +import tempfile +import unittest +from pathlib import Path + +EXAMPLES_DIR = Path(__file__).resolve().parent.parent / "examples" +EVALUATOR_PATH = EXAMPLES_DIR / "alphaevolve_math_problems" / "first_autocorr_ineq" / "evaluator.py" + +PROGRAM_TEMPLATE = """\ +import numpy as np + + +def run(): + return {f_values}, {c1}, 0.0, 10 +""" + + +def load_evaluator(): + """Load the example evaluator module directly from its file path.""" + spec = importlib.util.spec_from_file_location("first_autocorr_ineq_evaluator", EVALUATOR_PATH) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +class TestFirstAutocorrIneqEvaluator(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.evaluator = load_evaluator() + + def evaluate_candidate(self, f_values, c1): + """Evaluate a program whose run() returns the given f_values expression and claimed c1.""" + module_name = f"candidate_{self._testMethodName}" + tmpdir = tempfile.TemporaryDirectory() + self.addCleanup(tmpdir.cleanup) + # The evaluator imports the program via __import__, which caches in sys.modules. + self.addCleanup(sys.modules.pop, module_name, None) + path = Path(tmpdir.name) / f"{module_name}.py" + path.write_text(PROGRAM_TEMPLATE.format(f_values=f_values, c1=c1)) + return self.evaluator.evaluate(str(path)) + + def assert_rejected_as_non_finite(self, result): + self.assertEqual(result["combined_score"], 0.0) + self.assertIn("error", result) + self.assertIn("finite", result["error"]) + + def test_nan_values_rejected(self): + """The issue's repro: all-NaN values with a claimed c1 must not be scored.""" + result = self.evaluate_candidate("np.full(10, np.nan)", 0.5) + self.assert_rejected_as_non_finite(result) + + def test_positive_infinity_rejected(self): + result = self.evaluate_candidate("np.full(10, np.inf)", 0.5) + self.assert_rejected_as_non_finite(result) + + def test_nan_in_one_entry_rejected(self): + result = self.evaluate_candidate("np.array([1.0] * 3 + [np.nan] + [1.0] * 6)", 2.0) + self.assert_rejected_as_non_finite(result) + + def test_negative_infinity_still_rejected(self): + result = self.evaluate_candidate("np.array([1.0] * 3 + [-np.inf] + [1.0] * 6)", 2.0) + self.assertEqual(result["combined_score"], 0.0) + self.assertIn("error", result) + + def test_finite_function_still_scores(self): + """Ten ones have autoconvolution peak 0.5 and integral^2 0.25, so c1 is exactly 2.""" + result = self.evaluate_candidate("np.ones(10)", 2.0) + self.assertNotIn("error", result) + self.assertEqual(result["c1"], 2.0) + self.assertAlmostEqual(result["combined_score"], self.evaluator.BENCHMARK / 2.0) + + +if __name__ == "__main__": + unittest.main()