83 lines
3.6 KiB
Python
83 lines
3.6 KiB
Python
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
SRC_DIR = ROOT / "src"
|
|
if str(SRC_DIR) not in sys.path:
|
|
sys.path.insert(0, str(SRC_DIR))
|
|
|
|
import renunney.track1_threshold as thr
|
|
|
|
from track1_reference import Track1Parameters
|
|
|
|
|
|
def test_published_threshold_accepts_when_all_checks_survive():
|
|
result = thr.ThresholdSearchResult(
|
|
threshold_T=100.0,
|
|
baseline_check=thr.ThresholdCheck(T=100.0, runs=20, extinctions=0),
|
|
check_1_02=thr.ThresholdCheck(T=102.0, runs=20, extinctions=0),
|
|
check_1_05=thr.ThresholdCheck(T=105.0, runs=20, extinctions=0),
|
|
check_1_10=thr.ThresholdCheck(T=110.0, runs=20, extinctions=0),
|
|
retest_check=None,
|
|
)
|
|
assert thr.published_threshold_accepts(result) is True
|
|
|
|
|
|
def test_published_threshold_accepts_single_failure_if_retest_survives():
|
|
result = thr.ThresholdSearchResult(
|
|
threshold_T=100.0,
|
|
baseline_check=thr.ThresholdCheck(T=100.0, runs=20, extinctions=0),
|
|
check_1_02=thr.ThresholdCheck(T=102.0, runs=20, extinctions=1),
|
|
check_1_05=thr.ThresholdCheck(T=105.0, runs=20, extinctions=0),
|
|
check_1_10=thr.ThresholdCheck(T=110.0, runs=20, extinctions=0),
|
|
retest_check=thr.ThresholdCheck(T=102.0, runs=20, extinctions=0),
|
|
)
|
|
assert thr.published_threshold_accepts(result) is True
|
|
|
|
|
|
def test_published_threshold_rejects_multiple_failures():
|
|
result = thr.ThresholdSearchResult(
|
|
threshold_T=100.0,
|
|
baseline_check=thr.ThresholdCheck(T=100.0, runs=20, extinctions=0),
|
|
check_1_02=thr.ThresholdCheck(T=102.0, runs=20, extinctions=1),
|
|
check_1_05=thr.ThresholdCheck(T=105.0, runs=20, extinctions=1),
|
|
check_1_10=thr.ThresholdCheck(T=110.0, runs=20, extinctions=0),
|
|
retest_check=None,
|
|
)
|
|
assert thr.published_threshold_accepts(result) is False
|
|
|
|
|
|
def test_search_threshold_over_candidates_uses_first_accepted(monkeypatch):
|
|
params = Track1Parameters(K=5000, N0=20, n=1, u=5e-6, R=10.0, T=20)
|
|
|
|
def fake_eval(params, T_value, runs=20, seed_start=0, cache_path=None, jobs=1):
|
|
if T_value == 60:
|
|
return thr.ThresholdSearchResult(
|
|
threshold_T=60.0,
|
|
baseline_check=thr.ThresholdCheck(T=60.0, runs=runs, extinctions=1),
|
|
check_1_02=thr.ThresholdCheck(T=61.2, runs=runs, extinctions=0),
|
|
check_1_05=thr.ThresholdCheck(T=63.0, runs=runs, extinctions=0),
|
|
check_1_10=thr.ThresholdCheck(T=66.0, runs=runs, extinctions=0),
|
|
retest_check=None,
|
|
)
|
|
return thr.ThresholdSearchResult(
|
|
threshold_T=float(T_value),
|
|
baseline_check=thr.ThresholdCheck(T=float(T_value), runs=runs, extinctions=0),
|
|
check_1_02=thr.ThresholdCheck(T=1.02 * T_value, runs=runs, extinctions=0),
|
|
check_1_05=thr.ThresholdCheck(T=1.05 * T_value, runs=runs, extinctions=0),
|
|
check_1_10=thr.ThresholdCheck(T=1.10 * T_value, runs=runs, extinctions=0),
|
|
retest_check=None,
|
|
)
|
|
|
|
monkeypatch.setattr(thr, "evaluate_threshold_candidate", fake_eval)
|
|
result = thr.search_threshold_over_candidates(params, [60, 80, 100], runs=3, seed_start=10)
|
|
assert result is not None
|
|
assert result.threshold_T == 80.0
|
|
|
|
|
|
def test_run_extinction_check_parallel_matches_serial():
|
|
params = Track1Parameters(K=5000, N0=20, n=1, u=5e-6, R=10.0, T=20)
|
|
serial = thr.run_extinction_check(params, T_value=20.0, runs=2, seed_start=5, jobs=1)
|
|
parallel = thr.run_extinction_check(params, T_value=20.0, runs=2, seed_start=5, jobs=2)
|
|
assert parallel == serial
|