implementing gain

This commit is contained in:
Khalim Conn-Kowlessar 2025-08-19 17:58:02 +01:00
parent 01722a94e2
commit ce362f5262
3 changed files with 54 additions and 2 deletions

View file

@ -320,6 +320,17 @@ class Funding:
return data["Cost Savings"].values[0]
def _calculate_full_project_abs(self, floor_area_band: str, starting_sap_band: str, ending_sap_band: str):
data = self.project_scores_matrix[
(self.project_scores_matrix["Floor Area Segment"] == floor_area_band) &
(self.project_scores_matrix["Starting Band"] == starting_sap_band) &
(self.project_scores_matrix["Finishing Band"] == ending_sap_band)
]
if data.empty:
raise ValueError("Missing ABS rate, check the project scores matrix")
return data["Cost Savings"].values[0]
@staticmethod
def get_starting_ending_uvalues(current_uvalue: float) -> tuple[str, str]:
"""
@ -1058,3 +1069,13 @@ class Funding:
)
raise ValueError("Invalid tenure type for innovation uplift calculation: {}".format(self.tenure))
def get_abs_rate(self, is_cavity: bool) -> float:
if self.tenure == "Social":
return self.eco4_social_cavity_abs_rate if is_cavity else self.eco4_social_solid_abs_rate
if self.tenure == "Private":
return self.eco4_private_cavity_abs_rate if is_cavity else self.eco4_private_solid_abs_rate
raise NotImplementedError(
"Only 'Private' and 'Social' tenures are supported for ABS rate calculation."
)

View file

@ -903,6 +903,16 @@ async def model_engine(body: PlanTriggerRequest):
)
# Given the solutions we select the optimal one
solutions["cost_less_full_project_funding"] = solutions["total_cost"] - solutions[
"eco4_full_project_funding"]
solutions = solutions.sort_values("cost_less_full_project_funding", ascending=True)
if solutions["meets_upgrade_target"].any():
# If we have a solution that meets the upgrade target, we select that one
optimal_solution = solutions[solutions["meets_upgrade_target"]].iloc[0]
else:
optimal_solution = optimal_solution.iloc[0]
# optimal_solution =
if not body.optimise:

View file

@ -290,7 +290,7 @@ def optimise_with_funding_paths(p, input_measures, housing_type, funding: Fundin
if scheme == "eco4":
# Need to strip out any measure types that are not eligible for ECO4 funding (e.g. secondary heating)
raise ValueError()
sub_measures = _filter_fundable_subgroups(sub_measures, scheme)
# 4) run your existing optimiser for the remaining groups
# If we have a budget, we need to ensure the subproblem respects it so we remove the fixed cost (which
@ -338,6 +338,26 @@ def optimise_with_funding_paths(p, input_measures, housing_type, funding: Fundin
if not solutions[solutions["is_eligible"] & ~solutions["meets_upgrade_target"]].empty:
raise NotImplementedError("Implement me")
# We now can calculate the project ABS, which subtracts from the cost, but this is only relevant for ECO4
solutions["starting_sap"] = p.data["current-energy-efficiency"]
solutions["floor_area"] = p.floor_area
solutions["ending_sap"] = solutions["starting_sap"] + solutions["total_gain"]
solutions["starting_band"] = solutions["starting_sap"].apply(funding.get_sap_band)
solutions["ending_band"] = solutions["ending_sap"].apply(funding.get_sap_band)
solutions["floor_area_band"] = solutions["floor_area"].apply(funding.get_floor_area_band)
solutions["project_score"] = solutions.apply(
lambda x: funding._calculate_full_project_abs(
floor_area_band=x["floor_area_band"],
starting_sap_band=x["starting_band"],
ending_sap_band=x["ending_band"],
),
axis=1
)
rate = funding.get_abs_rate(is_cavity=p.walls["is_cavity_wall"])
solutions["eco4_full_project_funding"] = solutions["project_score"] * rate
# if the scheme is not ECO4, we set the funding to 0 with iloc
solutions.loc[solutions["scheme"] != "eco4", "eco4_full_project_funding"] = 0.0
return solutions
@ -759,7 +779,8 @@ def make_funding_paths(p, input_measures, housing_type, funding: Funding):
input_gbis_measures = []
for measures in input_measures:
for measure in measures:
if measure["type"] in remaining_insulation_type + other_gbis_insulation_measures:
type_to_check = measure["type"].split("+")[0] if "+" in measure["type"] else measure["type"]
if type_to_check in remaining_insulation_type + other_gbis_insulation_measures:
input_gbis_measures.append([measure])
funding_paths = _make_generic_gbis_funding_paths(input_gbis_measures, funding_paths)