Skip to content

Commit edfa540

Browse files
hmgaudeckerclaude
andcommitted
tests: positive regression guard — assets=-$1M passes benchmark validation
Asserts that `validate_initial_conditions` admits a subject placed at `assets = -1_000_000` in `retiree_nomc_inelig_canwork` under the benchmark model. Encodes the economic story: with the consumption floor / transfer system, any past assets level is representable — `c = c_floor` is always feasible because `transfers` tops up cash-on-hand to the floor. The test passes today on benchmark params; it doesn't reproduce the gpu-01 failure (production-side, separate setup loaded by `aca-estimation`'s `assemble_fixed_params`). Kept as a permanent regression guard so a future change that re-introduces a constraint shape that rejects extreme negatives is caught immediately at benchmark scale. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 00ee7d2 commit edfa540

1 file changed

Lines changed: 50 additions & 0 deletions

File tree

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""Subjects at extreme negative assets must clear `validate_initial_conditions`.
2+
3+
The transfer system (`agent.assets_and_income.transfers`) tops cash-on-hand
4+
to `consumption_floor * equivalence_scale` at any starting state, so the
5+
lowest consumption-grid point is always a feasible action regardless of
6+
how negative starting assets are. The model's constraints — and pylcm's
7+
`validate_initial_conditions` pass — must reflect this.
8+
"""
9+
10+
import jax.numpy as jnp
11+
from lcm.simulation.initial_conditions import validate_initial_conditions
12+
13+
from aca_model.benchmark import (
14+
create_benchmark_model,
15+
get_benchmark_initial_conditions,
16+
get_benchmark_params,
17+
)
18+
19+
20+
def test_extreme_negative_assets_subject_passes_validation() -> None:
21+
"""A subject placed at `assets = -1_000_000` clears initial-conditions validation.
22+
23+
HRS bottom-codes very-large-negative net wealth at exactly $-1{,}000{,}000$.
24+
Such subjects should remain in the simulated population: the consumption
25+
floor / transfer system absorbs them, with `c = c_floor` always feasible.
26+
"""
27+
n_subjects = 1
28+
model = create_benchmark_model(n_subjects=n_subjects)
29+
_, params = get_benchmark_params(model=model)
30+
31+
initial_conditions = get_benchmark_initial_conditions(
32+
model=model, n_subjects=n_subjects, seed=0
33+
)
34+
initial_conditions = {
35+
**initial_conditions,
36+
"assets": jnp.asarray([-1_000_000.0]),
37+
"regime": jnp.asarray(
38+
[model.regime_names_to_ids["retiree_nomc_inelig_canwork"]],
39+
dtype=jnp.int32,
40+
),
41+
}
42+
43+
internal_params = model._process_params(params) # noqa: SLF001
44+
validate_initial_conditions(
45+
initial_conditions=initial_conditions,
46+
internal_regimes=model.internal_regimes,
47+
regime_names_to_ids=model.regime_names_to_ids,
48+
internal_params=internal_params,
49+
ages=model.ages,
50+
)

0 commit comments

Comments
 (0)