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_reference as ref def test_fecundity_matches_r_definition(): params = ref.Track1Parameters(K=5000, N0=50, n=1, u=5e-6, R=10.0, T=40) r = params.intrinsic_growth_rate() assert ref.female_fecundity(r, N=0, K=params.K) == pytest_approx(10.0) def test_initialize_population_shapes_and_allele_zero_fixation(): params = ref.Track1Parameters(K=5000, N0=12, n=3, u=5e-6, R=10.0, T=40) state = ref.initialize_population(params, ref.np.random.default_rng(1)) assert state.genomes.shape == (12, 2, 3) assert state.sexes.shape == (12,) assert int(state.genomes.sum()) == 0 def test_simulate_run_returns_generation_summaries(): params = ref.Track1Parameters(K=5000, N0=20, n=1, u=5e-6, R=10.0, T=20) out = ref.simulate_run(params, seed=2) assert out assert out[0].N == 20 assert out[0].t == -(params.T // 2) def test_generation_summary_reports_tracking_fields_for_initial_population(): params = ref.Track1Parameters(K=5000, N0=20, n=2, u=5e-6, R=10.0, T=20) out = ref.simulate_run(params, seed=2) first = out[0] assert first.mean_allele_value == pytest_approx(0.0) assert first.mean_genotype_value == pytest_approx(0.0) assert first.target_value == pytest_approx(-0.5) assert first.mean_tracking_gap == pytest_approx(0.5) assert first.paper_M == pytest_approx(0.05) assert first.expected_mutations_current_N == pytest_approx(0.0004) def test_generation_summary_reports_realized_mutations_for_high_u(): params = ref.Track1Parameters(K=5000, N0=20, n=1, u=0.5, R=10.0, T=20) out = ref.simulate_run(params, seed=2) first = out[0] assert first.realized_mutation_count >= 0 assert 0.0 <= first.realized_mutation_rate_per_allele <= 1.0 def pytest_approx(value: float, tol: float = 1e-9): class Approx: def __eq__(self, other): return abs(other - value) <= tol return Approx()