Skip to content

Commit a094b9a

Browse files
fix: clear caches after parameter updates in simulation modifier
The simulation modifier now clears both parameter caches and variable holder caches after updating parameter values. This ensures that subsequent calculations use the updated parameter values instead of stale cached values. Previously, when a simulation was created and then modified with parameter updates, the cached calculations would still use the old parameter values, causing reforms to have no effect.
1 parent 00794f9 commit a094b9a

2 files changed

Lines changed: 68 additions & 0 deletions

File tree

src/policyengine/utils/parametric_reforms.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ def modifier(simulation):
3434
start=start_period,
3535
stop=stop_period,
3636
)
37+
38+
# Clear caches so calculations use updated parameter values
39+
simulation.tax_benefit_system.reset_parameter_caches()
40+
for population in simulation.populations.values():
41+
for holder in population._holders.values():
42+
holder.delete_arrays()
43+
3744
return simulation
3845

3946
return modifier

tests/test_parametric_reforms.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
"""Test script for parameter cache clearing fix."""
2+
3+
from datetime import datetime
4+
from policyengine.tax_benefit_models.uk import uk_latest
5+
from policyengine.core.policy import ParameterValue as PEParameterValue
6+
from policyengine.utils.parametric_reforms import simulation_modifier_from_parameter_values
7+
from policyengine_uk import Microsimulation
8+
9+
10+
def test_modifier_clears_cache():
11+
"""Test that the modifier clears cache so parameter updates take effect."""
12+
13+
# Create BASELINE simulation (no reform)
14+
sim_baseline = Microsimulation(situation={'people': {'person': {'age': {'2026': 30}}}})
15+
uc_baseline = sim_baseline.calculate('universal_credit', '2026')[0]
16+
param_baseline = sim_baseline.tax_benefit_system.parameters('2026-01').gov.dwp.universal_credit.standard_allowance.amount.SINGLE_OLD
17+
print(f'Baseline UC: £{uc_baseline:.2f}')
18+
print(f'Baseline SINGLE_OLD: £{param_baseline:.2f}/month')
19+
20+
# Create REFORM simulation - apply modifier BEFORE any calculations
21+
sim_reform = Microsimulation(situation={'people': {'person': {'age': {'2026': 30}}}})
22+
23+
# Apply modifier immediately (before any calculate calls)
24+
param_lookup = {p.name: p for p in uk_latest.parameters}
25+
pe_param = param_lookup.get('gov.dwp.universal_credit.standard_allowance.amount.SINGLE_OLD')
26+
pv = PEParameterValue(
27+
parameter=pe_param,
28+
value=533.0,
29+
start_date=datetime(2026, 1, 1),
30+
end_date=None,
31+
)
32+
modifier = simulation_modifier_from_parameter_values([pv])
33+
modifier(sim_reform)
34+
35+
# Check param was updated
36+
param_reform = sim_reform.tax_benefit_system.parameters('2026-01').gov.dwp.universal_credit.standard_allowance.amount.SINGLE_OLD
37+
print(f'Reform SINGLE_OLD: £{param_reform:.2f}/month')
38+
assert param_reform == 533.0, f"Parameter not updated: {param_reform}"
39+
40+
# Now calculate UC on reform sim
41+
uc_reform = sim_reform.calculate('universal_credit', '2026')[0]
42+
print(f'Reform UC: £{uc_reform:.2f}')
43+
44+
# Expected values
45+
expected_reform_uc = 533.0 * 12 # £6396
46+
print(f'\nExpected reform UC: £{expected_reform_uc:.2f}')
47+
print(f'Actual reform UC: £{uc_reform:.2f}')
48+
49+
# Check the increase is correct
50+
expected_increase = (533.0 - param_baseline) * 12
51+
actual_increase = uc_reform - uc_baseline
52+
print(f'\nExpected increase: £{expected_increase:.2f}')
53+
print(f'Actual increase: £{actual_increase:.2f}')
54+
55+
# Assert UC changed correctly
56+
assert abs(uc_reform - expected_reform_uc) < 1, f"Reform UC should be ~{expected_reform_uc}, got {uc_reform}"
57+
print('\nTest PASSED!')
58+
59+
60+
if __name__ == '__main__':
61+
test_modifier_clears_cache()

0 commit comments

Comments
 (0)