From 28eebb69c26e1a6b69a2778da30a246068053137 Mon Sep 17 00:00:00 2001 From: Hugh Runyan Date: Tue, 20 Oct 2026 11:30:26 -0700 Subject: [PATCH] A listed landfill's share a rounding error below zero sends no negative waste Co-Authored-By: Claude Opus 5.5 --- SWEET_python/advanced_dst_city.py | 5 ++++- changelog/2026-10.md | 5 +++++ tests/test_adst_city_other_landfills.py | 12 ++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/SWEET_python/advanced_dst_city.py b/SWEET_python/advanced_dst_city.py index 2a9948d..da88e15 100644 --- a/SWEET_python/advanced_dst_city.py +++ b/SWEET_python/advanced_dst_city.py @@ -737,7 +737,10 @@ def _with_other_landfills(request: AdvancedDSTCityRequest) -> AdvancedDSTCityReq rows: Dict[str, Dict[int, List[float]]] = {} for variant in variants: _validate_share_range(splits[variant], variant) - listed = splits[variant].where(accepting[variant], 0.0) + # The range check tolerates a share a rounding error outside [0, 1]. Used + # as given, -0.01 would bury negative waste at that site and hand other + # landfills 101% of the rest. + listed = splits[variant].where(accepting[variant], 0.0).clip(lower=0.0, upper=1.0) claimed = listed.sum(axis=1) over = claimed > 1.0 listed.loc[over] = listed.loc[over].div(claimed[over], axis=0) diff --git a/changelog/2026-10.md b/changelog/2026-10.md index d844bb7..83e6adc 100644 --- a/changelog/2026-10.md +++ b/changelog/2026-10.md @@ -195,6 +195,11 @@ take to other landfills, so a caller no longer has to make the shares add up to ## Fixed +- **A listed landfill's share a rounding error below zero sends no negative waste.** + With `other_landfills`, a share the range check tolerates (down to -0.02) was used + as given: -0.01 buried negative waste at that site and gave other landfills 101% + of the rest. Tolerated shares are now clipped to [0, 1] first. + - **Indonesia has a per-capita waste rate of its own** (model-output change). `defaults_2019.msw_per_capita_country` copies IPCC 2019 Refinement, Vol. 5 Ch. 2, Table 2A.1 (Updated), 2010 column, in tonnes per person per year. All diff --git a/tests/test_adst_city_other_landfills.py b/tests/test_adst_city_other_landfills.py index 6352554..fa9b776 100644 --- a/tests/test_adst_city_other_landfills.py +++ b/tests/test_adst_city_other_landfills.py @@ -214,6 +214,18 @@ def test_shares_over_one_are_scaled_down_and_other_landfills_take_nothing(): assert shares[2].to_numpy() == pytest.approx(0.0) +def test_a_tolerated_negative_share_sends_no_negative_waste_anywhere(): + """-0.01 passes the range check as a rounding error. Used as given, it buried + negative waste at the listed site and gave other landfills 101% of the rest.""" + result = _run(_request([_site()], [-0.01], other=_other())) + + for variant in ("baseline", "scenario"): + shares = _site_shares(result, variant) + assert shares[0].to_numpy() == pytest.approx(0.0) + assert shares[1].to_numpy() == pytest.approx(1.0) + assert (pd.concat(result["mass_flow"][variant]["sites"], axis=1) >= 0).all().all() + + def test_other_landfills_open_with_a_listed_site_that_opens_before_the_model(): early = MODEL_START_YEAR - 10 shares = _site_shares(