Repository navigation
Conversation
MaxGhenis
added a commit
that referenced
this pull request
Oct 12, 2026
…#1235 review) Round 1 of the independent review found two majors. A group with no EITC in either year made the per-row uprating fall back to the all-returns total for its bins, and the plan's per-row index check then skipped the whole rake. And plain IPF capped at 10,000 sweeps refused feasible, ill-conditioned margins. - _eitc_rake_plan decides from structure: one all-AGI total row per split, leaf bins tiling AGI, and an AGI group for the totals and every bin. An empty group takes a zero factor; a group with active EITC but no source EITC is refused. - _rake_two_margins checks exactly whether a positive scaling exists (Menon/Brualdi) and refuses with a specific message if not. It then finds the IPF solution by damped Newton steps on the convex dual, pinning each block's largest column with a Jacobi-scaled solve, and finishes with exact IPF sweeps. Rows hold to rounding, columns to 1e-12. - The bin adjustment is relative to the recorded per-row group factor, so it stays consistent beside rounded published subtotals. - The per-row AGI metadata moves into _eitc_agi_uprating_metadata, unchanged for #1227's rows. - The plan uses an _EitcRow NamedTuple and the solver annotates its nested functions; the spine-blindness check had failed on lambda row: row[1:]. - New tests: the review's counterexamples, the empty and refused groups, the rounded-subtotal adjustment, a Hypothesis property against a scipy linprog feasibility oracle, and positive seeds spanning ten orders of magnitude. - Experiments: option (b) records the factor its new total implies; results regenerated; README separates pairs from runs, qualifies the level gap (TY2018 amount) and states the bin-level tradeoff. national_state 31bd18096d33 -> 1aafec44dbfa (values move in the last bits; the adjustment metadata changed); full ac32014f3325 -> ec807d77a746. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 13, 2026
…d 2) Round 2 found the feasibility check's rounding tolerance taking strict slack below 1e-12 of the total for an exact (infeasible) fill, so it refused a feasible decomposition. It now refuses only what is certain for the margins as given: an excess beyond rounding, or an exact fill that other splits also reach. Margins within rounding of the boundary go to the solver. Also from round 2: - The Newton solve falls back to Levenberg-Marquardt damping when rounding makes the system singular (a 1e16 dynamic range), and the seed is normalized by its largest cell before summing (1e308 cells). - Feasibility is checked over subsets of the shorter side; more than 16 splits and 16 groups is refused rather than left unchecked. - A published row over an AGI group that is zero although a bin inside it is not is refused: no factor the uprating records for it would be true. New tests: the round-2 counterexamples, direct and through the compiler. national_state 1aafec44dbfa -> f96aac657fa6 and full ec807d77a746 -> cb0eaa0418f2 (values move in the last bits); results regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 14, 2026
Contributor
Author
|
A source anomaly that bears on this rake. IRS's own TY2023 Table 2.5 (
Context: microcosm#1274, which adds CI tests on the real TY2023 rows after #1227. 🤖 Generated with Claude Code |
After #1227 each Table 2.5 child split's all-AGI total row keeps the TY2023 all-AGI child mix while each AGI bin keeps its group's, so on the pinned feed a split's total row and the sum of its 28 bins differed by up to 16% (childless amount 1.157), and calibration saw both. _rake_eitc_child_splits now rakes each decomposition's child x AGI-group matrix of source bins (iterative proportional fitting) to the splits' uprated total rows and the active filing-season AGI groups. Total rows keep their values; the 224 bins move by x0.857-1.226; every split's bins sum to its total row and every AGI group's bins to its active EITC. Decompositions with nothing to reconcile (no total rows, or uprated on the all-returns total) keep their per-row factors. Evidence (experiments/eitc-child-split-rake-20261012/): no TY2024 child mix is published; on published Table 2.5 TY2013-2023 keeping the all-AGI mix predicted next year's split totals with 40-70% of the bins' error (the bins under-predicted childless EITC in every clean year pair); it sits 3-4x closer to the HT2 state EITC-by-children rows on the same surface; and SOI's full-population TY2023 state data confirm the TY2023 mix it keeps. national_state stays at 6,102 targets, version 3fad14f85468 -> 31bd18096d33; full stays at 33,250, c3aaea9c1e8c -> ac32014f3325. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#1235 review) Round 1 of the independent review found two majors. A group with no EITC in either year made the per-row uprating fall back to the all-returns total for its bins, and the plan's per-row index check then skipped the whole rake. And plain IPF capped at 10,000 sweeps refused feasible, ill-conditioned margins. - _eitc_rake_plan decides from structure: one all-AGI total row per split, leaf bins tiling AGI, and an AGI group for the totals and every bin. An empty group takes a zero factor; a group with active EITC but no source EITC is refused. - _rake_two_margins checks exactly whether a positive scaling exists (Menon/Brualdi) and refuses with a specific message if not. It then finds the IPF solution by damped Newton steps on the convex dual, pinning each block's largest column with a Jacobi-scaled solve, and finishes with exact IPF sweeps. Rows hold to rounding, columns to 1e-12. - The bin adjustment is relative to the recorded per-row group factor, so it stays consistent beside rounded published subtotals. - The per-row AGI metadata moves into _eitc_agi_uprating_metadata, unchanged for #1227's rows. - The plan uses an _EitcRow NamedTuple and the solver annotates its nested functions; the spine-blindness check had failed on lambda row: row[1:]. - New tests: the review's counterexamples, the empty and refused groups, the rounded-subtotal adjustment, a Hypothesis property against a scipy linprog feasibility oracle, and positive seeds spanning ten orders of magnitude. - Experiments: option (b) records the factor its new total implies; results regenerated; README separates pairs from runs, qualifies the level gap (TY2018 amount) and states the bin-level tradeoff. national_state 31bd18096d33 -> 1aafec44dbfa (values move in the last bits; the adjustment metadata changed); full ac32014f3325 -> ec807d77a746. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d 2) Round 2 found the feasibility check's rounding tolerance taking strict slack below 1e-12 of the total for an exact (infeasible) fill, so it refused a feasible decomposition. It now refuses only what is certain for the margins as given: an excess beyond rounding, or an exact fill that other splits also reach. Margins within rounding of the boundary go to the solver. Also from round 2: - The Newton solve falls back to Levenberg-Marquardt damping when rounding makes the system singular (a 1e16 dynamic range), and the seed is normalized by its largest cell before summing (1e308 cells). - Feasibility is checked over subsets of the shorter side; more than 16 splits and 16 groups is refused rather than left unchecked. - A published row over an AGI group that is zero although a bin inside it is not is refused: no factor the uprating records for it would be true. New tests: the round-2 counterexamples, direct and through the compiler. national_state 1aafec44dbfa -> f96aac657fa6 and full ec807d77a746 -> cb0eaa0418f2 (values move in the last bits); results regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 3 found float subset sums rounding strict slack (2**-24) to an exact fill, so the feasibility check still refused a feasible decomposition. The subset sums are now exact (fractions.Fraction), and only an exact fill that other splits also reach, or an excess beyond rounding, is refused. Also from round 3: - The Newton solver works in log shares, so no positive cell underflows in normalization (a 1e-308 cell beside 1e308), and rows are normalized directly against the seed in units of each row's largest cell, so they hold to rounding at any magnitude. - Every published zero row over positive bins is refused, also one inside a larger AGI group. Rebased onto main after #1227 merged; its final overlap test (crossing and identical rows) is carried over. New tests: the round-3 counterexamples. national_state f96aac657fa6 -> 45adaa24b243 and full cb0eaa0418f2 -> 60a52e2f204d (values move in the last bits); results regenerated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
force-pushed
the
eitc-child-split-rake
branch
from
October 21, 2026 15:21
776ea71 to
1aac3bf
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rebased onto main after #1227 merged (2026-10-14,
de90c6c7e). #1227's final version of the overlap-refusal test (crossing and identical rows) is carried into the rewritten test file.Methodology principle for Max. No published source decides between the options below. The choice is the first instance of a general rule for stale SOI decompositions: when uprated levels conflict, rake the cells to both margins instead of shipping both. So it is queued as a principle decision rather than merged on the usual gates. The recommendation, option (c), is implemented here and ready to merge. Options (b) and (d) are each a few lines if preferred.
What is inconsistent after #1227
_uprate_cross_period_eitc_decompositionsscales the TY2023 SOI Table 2.5 EITC-by-AGI-and-children rows to the TY2024 filing-season EITC by AGI:The AGI groups grew at different rates (amount ×0.85 at $5,000–$10,000 to ×1.73 at $50,000 and over; returns ×0.81 to ×1.38). So per split, the total row and the sum of its 28 bins disagree, and both levels sit on national_state and full:
The options, on the pinned feed
These are release-equivalent compiles of
consumer_facts_us_51aa40f.jsonl, fromexperiments/eitc-child-split-rake-20261012/results/.Why (c)
24in25ic.xlsreturns 404.Full write-up:
experiments/eitc-child-split-rake-20261012/README.md.The change
_rake_eitc_child_splitsruns after the per-row uprating. For each decomposition (kind, source period, target period), it builds the child-split × AGI-group matrix of source bins (_eitc_rake_plan) and scales it (_rake_two_margins) to the splits' uprated total rows and the active AGI groups._rake_two_marginsfinds the IPF solution: the unique positive scaling r_i·s_j·x_ij that meets both margins and keeps every cross-product ratio of the source._require_scalable, the Menon 1968 / Brualdi 1968 condition, over subsets of the shorter side, at most 16). The subset sums are exact (fractions.Fraction). It refuses only when the margins are certainly infeasible: an excess beyond rounding, or an exact fill that other splits also reach. Margins within rounding of the boundary go to the solver.When it rakes. A decomposition is raked when:
Otherwise it keeps its per-row factors: uprated on the all-returns total, every row already has one factor, and with no total row there is nothing to reconcile to. A group with no EITC in either year takes a zero factor.
Refusals (
ValueError):Metadata.
uprating_reconciliation: two_margin_rake.uprating_factor(its effective factor),uprating_agi_group_factor(the factor the per-row uprating recorded) anduprating_child_split_adjustment. The adjustment is relative to the recorded factor, so the group factor times the adjustment equals the bin's factor.Refactor. The per-row AGI metadata moved into
_eitc_agi_uprating_metadata, with no change for Count each EITC child split once in the Table 2.5 uprating source total #1227's rows.Invariants
These hold for every decomposition the rake applies to:
_rake_two_marginssucceeds exactly when a positive scaling exists.Tests
test_us_eitc_decomposition_uprating.py(41 tests)._rake_two_marginsrefusals;compile_us_fiscal_target_registry;scipy.optimize.linprogoracle (the largest t such that some matrix on the seed's support, every positive cell ≥ t, meets both margins). It also checks margins and cross-product ratios;_rake_two_marginsagainst the closed-form 2×2 solution (bisection on the cross-product ratio).test_us_fiscal_targets.py.test_pinned_feed_eitc_child_split_bins_sum_to_their_total_rows: per split Σ bins = total row; per active group Σ bins = the group's EITC; adjustments within 0.85–1.23.test_us_eitc_decomposition_uprating.py: 41 passed;test_us_fiscal_targets.pyandtest_us_fiscal_refresh_builder.pywith-k "eitc or pinned_feed or decomposition": 25 passed;test_us_spine_blindness.py: 498 passed. Round 1's CI failed this static check onlambda row: row[1:].Separate findings, not changed here
An IRS cell misplacement in TY2023 Table 2.5 (comment above, 2026-10-14). The three-or-more $25,000–$30,000 cell holds about 311,000 returns that belong at $30,000–$35,000. It distorts the per-row factors of those two AGI groups under the status quo and under every option here, and the rake carries it into the raked bins just as the status quo does. Its repair or guard is a separate task.
microcosm#1274 (open) adds CI tests on the real Table 2.5 rows. One of its Hypothesis properties pins the status-quo bin factors for any filing-season input. Whichever lands second must update it to the rake's invariants. Note that for arbitrary inputs, the rake can be infeasible (active EITC where the childless split has no bins), which the compile now refuses.
Mid-November totals vs complete year. The mid-November filing-season EITC totals mostly run 3–6% below complete-year Table 2.5 (TY2017–2023: returns 0.939–0.971; amount 0.957–0.973, except TY2018 at 1.012). They are the TY2024 EITC target levels and two release critical-fit gates. All four options conserve them, so this is a separate question, proposed as a follow-up.
CD file vintage. 22incd.csv is SOI TY2022 data that Chronicle stamps TY2023, already tracked as CD record sets stamp 22incd.csv as ty2023 — a tax-year vintage error; add Table 1.4 taxable-interest facts (populace#489) chronicle#117.
TY2023 state data. SOI's TY2023 state data (
23in55cmcsv.csv, with EITC by children) are not yet in the pinned feed; Add IRS SOI Historic Table 2 TY2023 national, state broad and state EITC facts chronicle#295 is adding them. Their child mix sits 0.19–0.24 pp TVD from (c), so they would widen the gap to (b) and (d).Review
subfleet run --task review --tier hard, head a2a529d): REQUEST_CHANGES.Fractionsums now.axiom: n/a: target-compilation methodology for calibration targets (no policy encoding)
🤖 Generated with Claude Code