Gap
Python Simulation exposes multiple input entry points:
build_from_situation(dict) — household-level JSON (the format the PolicyEngine web app uses)
build_from_dataframe(df) — pandas dataframe of person- + benunit- + household-level data
build_from_url(url) — fetch a saved situation by ID
build_from_ids(...) — re-hydrate from snapshotted IDs
Rust currently only ingests bulk surveys (FRS / EFRS / SPI / WAS / LCFS) via src/data/. There is no household-level entry point.
Why it matters
- The PolicyEngine web app (https://policyengine.org/uk) is a household-level tool — users build a single household and see their tax/benefit computation. To migrate that tool to Rust, Rust must accept the same situation-JSON format
- Reform authors who want to test a single household scenario against both Python and Rust currently can't — there's no input path
- The YAML test harness (separate issue) effectively requires this, since tests are specified as situation dicts
Proposal
- Define a
Situation struct mirroring the Python situation-JSON schema (people, benunits, households + per-entity variable values + period keys)
- Implement
Simulation::build_from_situation(Situation) -> Simulation that constructs the in-memory frames the engine expects
- Implement
build_from_dataframe taking polars / arrow input (Rust already uses polars)
- Expose both through the Python wrapper (
interfaces/python/policyengine_uk_compiled/engine.py) so Microsimulation and a future Simulation class share the entry points
Effort
Small. Most of the work is the schema definition; the compute path is unchanged once data is in the expected frames.
References
- Python:
policyengine_uk/simulation.py:200-360 (build_from_* methods)
- Rust wrapper:
interfaces/python/policyengine_uk_compiled/engine.py, data.py
- Rust engine:
src/engine/, src/data/
Gap
Python
Simulationexposes multiple input entry points:build_from_situation(dict)— household-level JSON (the format the PolicyEngine web app uses)build_from_dataframe(df)— pandas dataframe of person- + benunit- + household-level databuild_from_url(url)— fetch a saved situation by IDbuild_from_ids(...)— re-hydrate from snapshotted IDsRust currently only ingests bulk surveys (FRS / EFRS / SPI / WAS / LCFS) via
src/data/. There is no household-level entry point.Why it matters
Proposal
Situationstruct mirroring the Python situation-JSON schema (people, benunits, households + per-entity variable values + period keys)Simulation::build_from_situation(Situation) -> Simulationthat constructs the in-memory frames the engine expectsbuild_from_dataframetaking polars / arrow input (Rust already uses polars)interfaces/python/policyengine_uk_compiled/engine.py) soMicrosimulationand a futureSimulationclass share the entry pointsEffort
Small. Most of the work is the schema definition; the compute path is unchanged once data is in the expected frames.
References
policyengine_uk/simulation.py:200-360(build_from_* methods)interfaces/python/policyengine_uk_compiled/engine.py,data.pysrc/engine/,src/data/