Fabric-first phase 2 re-scores candidates in the goal objective's currency 🟩

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Khalim Conn-Kowlessar 2026-07-09 13:13:23 +00:00
parent ffaf89935b
commit e329c50fa3

View file

@ -276,7 +276,7 @@ def optimise_package_fabric_first(
)
if (
target_sap is not None
and fabric_package.score.sap_continuous >= target_sap
and objective(fabric_package.score) >= target_sap
):
return fabric_package
if not fabric_package.selected:
@ -326,13 +326,15 @@ def optimise_package_fabric_first(
remaining_groups,
post_fabric_scorer,
baseline_epc,
start_sap=fabric_package.score.sap_continuous,
objective=objective,
start_value=objective(fabric_package.score),
),
scorer=post_fabric_scorer,
baseline_epc=baseline_epc,
budget=leftover_budget,
target_sap=target_sap,
dependencies=outstanding_dependencies,
objective=objective,
)
return OptimisedPackage(
selected=[*fabric_package.selected, *top_up.selected],
@ -353,23 +355,25 @@ def _rescored_groups(
scorer: Scorer,
baseline_epc: EpcPropertyData,
*,
start_sap: float,
objective: Callable[[Score], float],
start_value: float,
) -> list[list[ScoredOption]]:
"""The groups with every Option's role-1 warm-start signal re-scored
through ``scorer`` for phase 2, its independent gain on the post-fabric
dwelling rather than the raw baseline, so options whose worth changes once
the envelope is treated (a boiler on an insulated home) are re-ranked.
``start_sap`` is the score of ``baseline_epc`` through ``scorer`` with no
candidate applied the caller already has it (the phase-1 package score),
so it is threaded in rather than re-computed."""
through ``scorer`` in the ``objective``'s currency — for phase 2, its
independent gain on the post-fabric dwelling rather than the raw baseline,
so options whose worth changes once the envelope is treated (a boiler on
an insulated home) are re-ranked. ``start_value`` is the objective value of
``baseline_epc`` through ``scorer`` with no candidate applied the caller
already has it (the phase-1 package score in the objective's currency), so
it is threaded in rather than re-computed."""
return [
[
ScoredOption(
option=scored.option,
sap_gain=scorer.score(
baseline_epc, [scored.option.overlay]
).sap_continuous
- start_sap,
sap_gain=objective(
scorer.score(baseline_epc, [scored.option.overlay])
)
- start_value,
)
for scored in group
]