Skip to content

Conversation

@MaxGhenis
Copy link
Contributor

Summary

  • Update numpy version constraint from ~=2.1.0 to >=2.1.0,<3 to allow NumPy 2.3+
  • NumPy 2.3+ is required for Python 3.14 due to a critical bug fix

Problem

NumPy 2.1.x has a bug on Python 3.14 where the "temporary elision" optimization incorrectly identifies arrays as temporary due to the new LOAD_FAST_BORROW bytecode instruction, causing destructive in-place modifications during arithmetic operations.

This caused dividend_income_tax to return £0 instead of £22.55bn in UK microsimulations.

Root Cause

When formulas execute operations like:

other_income = earned + savings  # Creates new array ✓
combined = other_income + dividends  # Should create new array, but NumPy modifies other_income in-place ✗

NumPy's temporary elision optimization checks refcount==1 to decide if it can do in-place ops. Python 3.14's LOAD_FAST_BORROW bytecode creates temporary references that don't increment refcount, breaking this heuristic.

Fix

Test plan

  • Verified fix: After upgrading to NumPy 2.3.5, dividend_income_tax correctly returns £22.55bn
  • CI tests pass

Closes #407

🤖 Generated with Claude Code

MaxGhenis and others added 2 commits December 2, 2025 11:03
NumPy 2.1.x has a bug on Python 3.14 where "temporary elision" optimization
incorrectly identifies arrays as temporary due to the new LOAD_FAST_BORROW
bytecode instruction, causing destructive in-place modifications.

This caused dividend_income_tax to return £0 instead of £22bn in UK
microsimulations.

Fix: numpy/numpy#28748 (released in NumPy 2.3.0)
Issue: numpy/numpy#28681

Closes PolicyEngine#407

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@codecov
Copy link

codecov bot commented Dec 2, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.75%. Comparing base (58c2fca) to head (ed8365d).
⚠️ Report is 20 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #409      +/-   ##
==========================================
+ Coverage   81.14%   81.75%   +0.61%     
==========================================
  Files         197      200       +3     
  Lines       10228    10438     +210     
  Branches     1057     1049       -8     
==========================================
+ Hits         8299     8534     +235     
- Misses       1640     1643       +3     
+ Partials      289      261      -28     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@MaxGhenis MaxGhenis requested a review from baogorek December 2, 2025 18:03
@baogorek
Copy link
Collaborator

baogorek commented Dec 2, 2025

@MaxGhenis I just want to run a few things with it

@MaxGhenis MaxGhenis mentioned this pull request Dec 2, 2025
Copy link
Collaborator

@baogorek baogorek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The things I wanted to test are running fine.

@MaxGhenis MaxGhenis merged commit bd4581a into PolicyEngine:master Dec 3, 2025
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python 3.14 compatibility: person() accessor returns unweighted values in Microsimulation

2 participants