Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

A reform simulation's baseline reads the reform's default for people the situation gives no value

オープン
#612 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 2 日以内に返信

@MaxGhenis がすでに取り組んでいます。

2026年10月12日 から。

  • #613 @MaxGhenis による — オープン

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
35/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
停滞
技術スタック
python
領域
backend, databases

調査の方向性

Start with Simulation.__init__ and _bind_to_tax_benefit_system, then trace SimulationBuilder's add_variable_value, expand_axes, and finalize_variables_init paths. Read tests/core/test_reform_baseline_system.py, especially test_an_input_default_the_reform_changes_is_the_baselines_in_the_baseline; reproduce the partial-input and neutralized-input cases from the issue. Done means the baseline matches a simulation built directly from the same situation under the baseline system, including defaults and inputs ignored by the reform.

索引モデルが issue の本文から書いたものです。

説明

Problem

Simulation(situation=..., reform=...) builds the situation under the reform's tax-benefit system, then makes its baseline as a branch of that simulation and gives the branch the baseline system. When the situation gives a variable for some people and not others (or sets it along axes), SimulationBuilder fills the other entries with that variable's default from the system it was given, the reform's, and stores the whole array as an input (add_variable_value and expand_axes start from variable.default_array(...); finalize_variables_init calls holder.set_input with the full array). The baseline branch inherits those inputs, so it reads the reform's default for people the situation never gave a value.

Reproduced on master b909d5a60, from the repository root with uv run --frozen --extra dev python:

import sys; sys.path.insert(0, ".")
from policyengine_core.country_template import Simulation
from tests.core.test_reform_baseline_system import change_salary_default  # salary default 0 -> 1000

P = "2022-01"
sit = {"persons": {"a": {"salary": {P: 3000.0}}, "b": {}}, "households": {"h": {"parents": ["a", "b"]}}}
s = Simulation(situation=sit, reform=change_salary_default)
print(s.baseline.calculate("salary", P))  # [3000. 1000.]
print(Simulation(situation=sit).calculate("salary", P))  # [3000.    0.]

With axes ("axes": [[{"name": "salary", "count": 2, "min": 0, "max": 5000, "period": P}]] over two people with no salary), the baseline gives [0, 1000, 5000, 1000]; the same situation built under the baseline system gives [0, 0, 5000, 0].

The same inheritance loses an input the reform neutralizes. The reform's system ignores a situation's income_tax (it warns that the variable is neutralized), so the baseline branch has no input either and calculates it:

from tests.core.test_reform_baseline_system import neutralize_income_tax

sit = {"persons": {"a": {"salary": {P: 3000.0}, "income_tax": {P: 7.0}}}, "households": {"h": {"parents": ["a"]}}}
print(Simulation(situation=sit, reform=neutralize_income_tax).baseline.calculate("income_tax", P))  # [450.00003]
print(Simulation(situation=sit).calculate("income_tax", P))  # [7.]

Simulation._bind_to_tax_benefit_system re-points the baseline's populations and holders at the baseline system's entities and variables, but the arrays it inherited were built by the reform's.

tests/core/test_reform_baseline_system.py::test_an_input_default_the_reform_changes_is_the_baselines_in_the_baseline notes the limitation in a comment and avoids it by giving no one a salary.

Expected

A reform simulation's baseline is what the builder makes from the situation under the baseline system: people the situation gives no value take the baseline system's default, and inputs the reform's system ignores are the baseline's.

Notes

  • A stored input is all-or-nothing today: Holder.set_input, _user_input_keys, StoreHistory and to_input_dataframe record and export whole arrays, and set_input_divide_by_period/set_input_dispatch_by_period combine a larger period's array with the sub-period inputs already stored. So the default given to one person at one period also changes what other periods' inputs are divided into.
  • policyengine-us reaches this through core's Simulation.__init__. policyengine-uk builds its baseline as a separate Simulation from the situation, so it is not affected.
  • Related: #611 (the builder replaces a simulation's population) touches the same files.
主要言語
Python
スター
22
フォーク
30
平均マージ
2日 19時間
マージ済み PR(30日)
25

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

PolicyEngine/policyengine-core のほかの issue

PolicyEngine/policyengine-core の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。