Skip to content

Conserve impact for background production-edge TDs in traverse_background - #199

Open
TimoDiepers wants to merge 8 commits into
feat/premise-temporalfrom
feat/background-production-td
Open

Conserve impact for background production-edge TDs in traverse_background#199
TimoDiepers wants to merge 8 commits into
feat/premise-temporalfrom
feat/background-production-td

Conversation

@TimoDiepers

Copy link
Copy Markdown
Member

Stacked on top of #197 (base: `feat/premise-temporal`) so it can be reviewed in isolation.

Problem

With `traverse_background=True`, when the variant-aware descent reaches a background node that carries a production-edge temporal distribution, the production TD was applied only to the node's child expansion, never to the edge that produces the node. Two symptoms follow:

  • KeyError in get_time_mapping_key — the node is consumed at cohort-years it was never registered as a producer at (producer/consumer year bands diverge).
  • N× over-count_join_datetime_and_timedelta_distributions tiles the producer TD's amounts and drops the consumer-side cohort weights, so each spread cohort emits the full exchange coefficient instead of its weighted share. A 3-cohort production TD inflates the score ~3×.

Fix

Fold the producer's own production-edge TD into the effective producer TD of the edge at both background descent sites (_emit_variant_split_for_consumer_date and _descend_variant_subtree), via a new _fold_production_td helper that takes the outer product of amounts and outer sum of dates (dates sum, weights multiply). The node is then registered at exactly the production-TD-weighted cohorts it is consumed at:

  • producer band == consumer band by construction → no more KeyError;
  • each cohort carries exchange_weight × production_weight → impact conserves.

This mirrors the existing FU-seed cohort-split pattern in build_edge_timeline. The change is confined to VariantBackgroundMixin (background proxy-descent) — the foreground/explicit product-process path, the matrix traversal, and _join_datetime_and_timedelta_distributions are untouched.

As defense-in-depth for a separate, not-yet-minimally-reproduced premise dual-path case, get_time_mapping_key also snaps a background consumer lookup to the nearest registered year of the same node (and now logs a warning when it does) instead of raising.

Tests

New `tests/test_background_production_td.py` (both `priority` and `bfs` engines), each asserting time-explicit `static_score == base_lca.score`:

  • first-level descended production-TD node conserves;
  • deeper descended production-TD node conserves;
  • convergent production-TD node (reached via two parents) conserves — verified non-vacuous (fails on pre-fix code).

Full suite green.

Defense-in-depth for the traverse_background producer/consumer year-band
mismatch: when a descended background node is consumed at a grouped year with
no time-mapped column for its own (variant, code), snap to the nearest
registered year instead of raising KeyError.
bg_S previously only had a biosphere output, so it was never actually
consumed downstream at its production-TD-shifted cohorts and the
test passed regardless of whether the descent-site fix was present.
Route bg_S through a new technosphere child (bg_T) before the
biosphere flow so both parent paths genuinely re-consume it.

Also log a warning when a background consumer lookup falls back to
the nearest registered year, so a real year mismatch is observable
instead of resolving silently.
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.

1 participant