Reform engine: structural reforms beyond YAML parameter overlay#80
Open
vahid-ahmadi wants to merge 1 commit into
Open
Reform engine: structural reforms beyond YAML parameter overlay#80vahid-ahmadi wants to merge 1 commit into
vahid-ahmadi wants to merge 1 commit into
Conversation
…pose) Address #41 by adding `src/reforms/structural.rs`: a `StructuralReform` enum that supports neutralising a named benefit variable, overriding its computed output with a custom closure, composing reforms in sequence, and wrapping the existing parameter-overlay `Reform`. Applied as a post-compute transform on the finalised reform-side results, reconciling aggregates by delta. Includes an example registry and unit tests. The existing parameter override and YAML neutralise paths are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses #41
Scope
Adds a Rust reform abstraction (
src/reforms/structural.rs) that goes beyond the existing YAML parameter overlay, mirroring the structural half of PolicyEngine's PythonReformsystem.The new
StructuralReformenum supports:Reform, so structural and parametric changes compose (re-applies the reform'sneutralise:list).fn(old_value, &BenUnit) -> new_value(the output-level analogue of swapping acompute_*formula)..then(...)(flattens nested composes).Integration
Structural reforms are applied as a post-compute transform on the finalised reform-side
SimulationResults— the least-invasive hook, identical to the one the existingReform::apply_to_resultsneutralisation already uses. Each variant computes a per-benunit delta against the named field, applies it, and reconciles benunittotal_benefitsplus the household income aggregates (net_income,net_income_ahc,extended_net_income,equivalised_*) by the same delta. The baseline run is never touched.A small example registry (
registry::disable_simulated_benefits,neutralise_benefit,halve_child_benefit,by_name) is provided, analogous to the Pythonpolicyengine_uk/reforms/examples.The existing parameter-override path and YAML
neutralise:path are unchanged; all prior reform tests still pass.Tests
11 new unit tests in
src/reforms/structural.rscovering: neutralise zeroes a variable and reconciles aggregates; output-override applies a closure (decrease and increase); compose applies both reforms in sequence and flattens;disable_simulated_benefitszeroes means-tested benefits; validation rejects unsupported targets and recurses into composes; the parametric variant re-applies its neutralise list; registry lookup.cargo buildandcargo testboth pass (200 passed, 0 failed).Remaining
compute_*function before downstream variables read it (so the change propagates through tapers/caps) is out of scope here; this slice covers leaf-output override where the delta is reconciled afterwards.Reformsubclass into this Rust abstraction is not wired up; no CLI flag routes intoStructuralReformyet (the API is exercised by unit tests).NEUTRALISABLE_BENEFITS(state pension, benefit cap, person-level tax) are excluded because of cross-variable feedback.🤖 Generated with Claude Code