mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-27 23:35:01 +00:00
Finds pre-2012 (S3 backup) x SAP-10.2 (new API) cert pairs per postcode, predicts each from its leave-one-out cohort with and without ADR-0054 conditioning, and reports compare_prediction hit rates side by side. Evidence for the stable-attribute whitelist, not a CI gate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
78 lines
2.4 KiB
Python
78 lines
2.4 KiB
Python
"""Pure pair-selection and aggregation logic of the ADR-0054 pairs harness."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import dataclasses
|
|
|
|
from datatypes.epc.domain.historic_epc import HistoricEpc
|
|
from domain.epc_prediction.prediction_comparison import PredictionComparison
|
|
from scripts.expired_prediction_pairs_harness import (
|
|
aggregate,
|
|
format_report,
|
|
latest_pre_2012_by_uprn,
|
|
)
|
|
|
|
|
|
def _hist(uprn: str, lodgement_date: str) -> HistoricEpc:
|
|
fields = {f.name: "" for f in dataclasses.fields(HistoricEpc)}
|
|
fields["uprn"] = uprn
|
|
fields["lodgement_date"] = lodgement_date
|
|
return HistoricEpc(**fields)
|
|
|
|
|
|
def _comparison(hits: dict[str, bool | None]) -> PredictionComparison:
|
|
return PredictionComparison(
|
|
categorical_hits=hits,
|
|
floor_area_residual=-4.0,
|
|
building_parts_residual=0,
|
|
window_count_residual=0,
|
|
total_window_area_residual=0.0,
|
|
door_count_residual=0,
|
|
)
|
|
|
|
|
|
def test_pairs_keep_only_the_latest_pre_2012_cert_per_uprn():
|
|
# Arrange — one UPRN lodged twice pre-2012, once post-2012; one UPRN-less row.
|
|
records = [
|
|
_hist("100", "2008-05-01"),
|
|
_hist("100", "2010-11-30"),
|
|
_hist("100", "2013-01-01"),
|
|
_hist("", "2009-01-01"),
|
|
]
|
|
|
|
# Act
|
|
by_uprn = latest_pre_2012_by_uprn(records)
|
|
|
|
# Assert — the 2010 cert wins; the 2013 one can never seed an expired pair.
|
|
assert set(by_uprn) == {"100"}
|
|
assert by_uprn["100"].lodgement_date == "2010-11-30"
|
|
|
|
|
|
def test_aggregate_counts_hits_and_skips_not_applicable():
|
|
# Arrange — two comparisons; wall scored twice (1 hit), roof scored once
|
|
# (None means the actual lodged no value — out of the denominator).
|
|
comparisons = [
|
|
_comparison({"wall_construction": True, "roof_construction": None}),
|
|
_comparison({"wall_construction": False, "roof_construction": True}),
|
|
]
|
|
|
|
# Act
|
|
scores = aggregate(comparisons)
|
|
|
|
# Assert
|
|
assert scores.hits["wall_construction"] == (1, 2)
|
|
assert scores.hits["roof_construction"] == (1, 1)
|
|
assert scores.floor_area_abs_residuals == [4.0, 4.0]
|
|
|
|
|
|
def test_report_prints_both_arms_side_by_side():
|
|
# Arrange
|
|
plain = aggregate([_comparison({"wall_construction": False})])
|
|
conditioned = aggregate([_comparison({"wall_construction": True})])
|
|
|
|
# Act
|
|
report = format_report(plain, conditioned, pairs=1)
|
|
|
|
# Assert
|
|
assert "| wall_construction | 0/1 | 1/1 |" in report
|
|
assert "1 pairs" in report
|