PolicyEngine / PolicyEngine/policyengine-us
Enums under axes-based simulations do not appear to be decoded (returned as numeric indices)
- Dominant language
- Python
- Stars
- 162
- Forks
- 212
- Avg merge
- 3d 3h
- Merged PRs (30d)
- 97
Description
While working on the household API's UK calculation path, we observed that enum variables requested in axes-based simulations appear not to be decoded properly on the US side.
## Observed
A situation with `axes` sweeping `employment_income` (3 points) and requesting `state_name` as an output returns the enum's numeric index rather than a decoded name:
```python
sim.calculate("state_name", 2024) # EnumArray
# via EnumArray.astype(float) reshaping (household API axes path):
# → [4.0, 4.0, 4.0] # index of CA, as floats
```
For comparison, policyengine-uk's wrapper `Simulation.calculate` force-decodes enums to name strings at the top level of the computation tree (`decode_enums=True` when the tracer stack is empty), so the same request there yields `["ENGLAND", "ENGLAND", "ENGLAND"]`.
## Why it matters
Consumers of axes scans (the household API among them) receive enum results whose meaning depends on knowing the enum's member ordering, which isn't part of any public contract. The household API currently preserves this behavior for backward compatibility (UK returns decoded names; US returns indices), so the two countries' responses now differ in shape for the same kind of request.
## More research needed
- Is this policyengine-us behavior or policyengine-core behavior (`EnumArray` + `SimulationBuilder` axes expansion)? It may belong upstream in core.
- Does anything depend on the numeric-index representation today?
- If decoding is the right fix, should `Simulation.calculate` decode at the top level the way the UK wrapper does, so all country packages converge on the same contract?
Observed against policyengine-us 1.771.2 / policyengine-core 3.26.6.
Contributor guide
Research direction
Start with Simulation.calculate and the axes expansion path involving EnumArray and SimulationBuilder, then compare the policyengine-uk wrapper's top-level decode_enums behavior. Determine whether the numeric indices originate in policyengine-us or policyengine-core and whether existing consumers depend on them. Done means an agreed, consistent enum representation for axes-based simulation responses, with the relevant tests updated.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend-api-design
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 38/100