بنقرة واحدة
policyengine-core
PolicyEngine Core simulation engine - the foundation powering all PolicyEngine calculations
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
PolicyEngine Core simulation engine - the foundation powering all PolicyEngine calculations
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Recharts chart patterns, formatting, and styling for PolicyEngine apps
PolicyEngine code writing style guide - formula optimization, direct returns, eliminating unnecessary variables
PolicyEngine parameter patterns - YAML structure, naming conventions, metadata requirements, federal/state separation
PolicyEngine code review patterns - validation checklist, common issues, review standards
PolicyEngine testing patterns - YAML test structure, naming conventions, period handling, and quality standards
PolicyEngine variable patterns - variable creation, no hard-coding principle, federal/state separation, metadata standards
| name | policyengine-core |
| description | PolicyEngine Core simulation engine - the foundation powering all PolicyEngine calculations |
PolicyEngine Core is the microsimulation engine that powers all PolicyEngine calculations. It's a fork of OpenFisca-Core adapted for PolicyEngine's needs.
When you use policyengine.org to calculate taxes or benefits, PolicyEngine Core is the "calculator" running behind the scenes.
Core provides:
You don't interact with Core directly - you use it through:
Core ensures:
When writing PolicyEngine code, you'll encounter Core concepts:
Variables:
Parameters:
Entities:
Periods:
from policyengine_us import Simulation
# When you create a simulation
sim = Simulation(situation=household)
# Core manages:
# - Entity relationships
# - Variable dependencies
# - Parameter lookups
# - Period conversions
# When you calculate
result = sim.calculate("income_tax", 2026)
# Core:
# 1. Checks if already calculated
# 2. Identifies dependencies (income → AGI → taxable income → tax)
# 3. Calculates dependencies first
# 4. Applies formulas
# 5. Returns result
Core (policyengine-core):
Country packages (policyengine-us, etc.):
Relationship:
policyengine-core (engine)
↓ powers
policyengine-us (US rules)
↓ used by
policyengine-api (REST API)
↓ serves
policyengine-app (web interface)
Location: PolicyEngine/policyengine-core Origin: Fork of OpenFisca-Core
Clone:
git clone https://github.com/PolicyEngine/policyengine-core
To see current structure:
tree policyengine_core/
# Key directories:
# - variables/ - Variable class and infrastructure
# - parameters/ - Parameter class and infrastructure
# - entities/ - Entity definitions
# - simulations/ - Simulation class
# - periods/ - Period handling
# - reforms/ - Reform application
To understand a specific component:
# Variable system
cat policyengine_core/variables/variable.py
# Parameter system
cat policyengine_core/parameters/parameter.py
# Simulation engine
cat policyengine_core/simulations/simulation.py
# Entity system
cat policyengine_core/entities/entity.py
Variable:
# To see Variable class implementation
cat policyengine_core/variables/variable.py
# Variables in country packages inherit from this:
from policyengine_core.variables import Variable
class income_tax(Variable):
value_type = float
entity = Person
label = "Income tax"
definition_period = YEAR
def formula(person, period, parameters):
# Vectorized formula
return calculate_tax(...)
Simulation:
# To see Simulation class implementation
cat policyengine_core/simulations/simulation.py
# Manages calculation graph and caching
sim = Simulation(situation=situation)
sim.calculate("variable", period)
Parameters:
# To see Parameter handling
cat policyengine_core/parameters/parameter_node.py
# Access in formulas:
parameters(period).gov.irs.credits.ctc.amount.base_amount
Core requires vectorized operations - no if-elif-else with arrays:
❌ Wrong (scalar logic):
if age < 18:
eligible = True
else:
eligible = False
✅ Correct (vectorized):
eligible = age < 18 # NumPy boolean array
Why: Core processes many households simultaneously for performance.
To see vectorization examples:
# Search for where() usage (vectorized if-then-else)
grep -r "np.where" policyengine_core/
# Find select() usage (vectorized case statements)
grep -r "select" policyengine_core/
Core automatically resolves variable dependencies:
class taxable_income(Variable):
def formula(person, period, parameters):
# Core automatically calculates these first:
agi = person("adjusted_gross_income", period)
deduction = person("standard_deduction", period)
return agi - deduction
class income_tax(Variable):
def formula(person, period, parameters):
# Core knows to calculate taxable_income first
taxable = person("taxable_income", period)
return apply_brackets(taxable, ...)
To see dependency resolution:
# Find trace functionality
grep -r "trace" policyengine_core/simulations/
# Enable in your code:
simulation.trace = True
simulation.calculate("income_tax", 2026)
To see period implementation:
cat policyengine_core/periods/period.py
# Period types:
# - YEAR: 2024
# - MONTH: 2024-01
# - ETERNITY: permanent values
Usage in variables:
# Annual variable
definition_period = YEAR # Called with 2024
# Monthly variable
definition_period = MONTH # Called with "2024-01"
# Convert periods
yearly_value = person("monthly_income", period.this_year) * 12
To run Core tests:
cd policyengine-core
make test
# Specific test
pytest tests/core/test_variables.py -v
To test in country package:
# Changes to Core affect all country packages
cd policyengine-us
uv pip install -e ../policyengine-core # Local development install
make test
PolicyEngine Core differs from OpenFisca-Core:
To see PolicyEngine changes:
# Compare to OpenFisca
# Core fork diverged to add:
# - Enhanced performance
# - Better error messages
# - PolicyEngine-specific features
# See commit history for PolicyEngine changes
git log --oneline
Clone repo:
git clone https://github.com/PolicyEngine/policyengine-core
Install for development:
make install
Make changes to variable.py, simulation.py, etc.
Test locally:
make test
Test in country package:
cd ../policyengine-us
uv pip install -e ../policyengine-core
make test
Format and commit:
make format
git commit -m "Description"
Changes to Core affect:
Critical: Always test in multiple country packages before merging.
Current variable types:
# See supported types
grep "value_type" policyengine_core/variables/variable.py
Types: int, float, bool, str, Enum, date
Formula signature:
def formula(entity, period, parameters):
# entity: Person, TaxUnit, Household, etc.
# period: 2024, "2024-01", etc.
# parameters: Parameter tree for period
return calculated_value
To see formula examples:
# Search country packages for formulas
grep -A 10 "def formula" ../policyengine-us/policyengine_us/variables/ | head -50
Accessing parameters in formulas:
# Navigate parameter tree
param = parameters(period).gov.irs.credits.ctc.amount.base_amount
# Parameters automatically valid for period
# No need to check dates manually
To see parameter structure:
# Example from country package
tree ../policyengine-us/policyengine_us/parameters/gov/
Core caches calculations automatically:
# First call calculates
tax1 = sim.calculate("income_tax", 2026)
# Second call returns cached value
tax2 = sim.calculate("income_tax", 2026) # Instant
When parameter lookups happen inside loops, batch them beforehand to avoid repeated function call overhead:
❌ Inefficient (repeated lookups):
# Inside uprate_parameters or similar functions
for instant in instants:
value = uprating_parameter(instant) # Repeated function calls
# ... use value
✅ Efficient (batched lookups):
# Pre-compute all values before the loop
value_cache = {
instant: uprating_parameter(instant)
for instant in instants
}
# Use cached values in loop
for instant in instants:
value = value_cache[instant] # Fast dictionary lookup
# ... use value
Why it matters:
uprate_parameters reduced from 15s to 13.8s (8% improvement) by batching lookupsWhen to batch:
parameters(period).path.to.value callsTo find optimization opportunities:
# Profile import time
python -m cProfile -o profile.stats -c "from policyengine_us.system import system"
# Search for parameter lookup hotspots
grep -r "parameters(period)" policyengine_core/parameters/
# Set variable to zero in reform
reform = {
"income_tax": {
"2026-01-01.2100-12-31": 0
}
}
Country packages add variables by inheriting from Core's Variable class.
See policyengine-us-skill for variable creation patterns.
Repository: https://github.com/PolicyEngine/policyengine-core
Documentation:
Related skills:
Variable not found:
# Error: Variable 'income_tax' not found
# Solution: Variable is defined in country package, not Core
# Use policyengine-us, not policyengine-core directly
Scalar vs array operations:
# Error: truth value of array is ambiguous
# Solution: Use np.where() instead of if-else
# See vectorization section above
Period mismatch:
# Error: Cannot compute variable_name for period 2024-01
# Solution: Check definition_period matches request
# YEAR variables need YEAR periods (2024, not "2024-01")
To debug:
# Enable tracing
sim.trace = True
sim.calculate("variable", period)
# See calculation dependency tree
Before contributing:
Development standards: