mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
Merge pull request #667 from Hestia-Homes/main
Added change to pass an already installed sap value from rebaselining to optimisation routine to prevent optimising for rebaselining
This commit is contained in:
commit
cdd058765a
4 changed files with 88 additions and 17 deletions
|
|
@ -1065,21 +1065,8 @@ async def model_engine(body: PlanTriggerRequest):
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
fixed_gain = optimiser_functions.calculate_fixed_gain(
|
|
||||||
property_required_measures, recommendations, p, needs_ventilation
|
|
||||||
)
|
|
||||||
gain = optimiser_functions.calculate_gain(body=body, p=p, fixed_gain=fixed_gain, eco_packages=eco_packages)
|
|
||||||
|
|
||||||
# We insert the innovation uplift
|
|
||||||
measures_to_optimise_with_uplift = deepcopy(measures_to_optimise)
|
|
||||||
|
|
||||||
for group in measures_to_optimise_with_uplift:
|
|
||||||
for r in group:
|
|
||||||
(r["partial_project_score"], r["partial_project_funding"], r["innovation_uplift"],
|
|
||||||
r["uplift_project_score"]) = (0, 0, 0, 0)
|
|
||||||
|
|
||||||
already_installed_measures = []
|
already_installed_measures = []
|
||||||
for measures in measures_to_optimise_with_uplift:
|
for measures in measures_to_optimise:
|
||||||
for m in measures:
|
for m in measures:
|
||||||
# A) We're going to make the already installed measures default
|
# A) We're going to make the already installed measures default
|
||||||
# B) We need to SAP points for all already installed measures to avoid double counting
|
# B) We need to SAP points for all already installed measures to avoid double counting
|
||||||
|
|
@ -1096,6 +1083,22 @@ async def model_engine(body: PlanTriggerRequest):
|
||||||
default_already_installed = keep_max_sap_per_measure_type(already_installed_measures)
|
default_already_installed = keep_max_sap_per_measure_type(already_installed_measures)
|
||||||
already_installed_sap = float(sum(d["sap_points"] for d in default_already_installed))
|
already_installed_sap = float(sum(d["sap_points"] for d in default_already_installed))
|
||||||
|
|
||||||
|
fixed_gain = optimiser_functions.calculate_fixed_gain(
|
||||||
|
property_required_measures, recommendations, p, needs_ventilation
|
||||||
|
)
|
||||||
|
gain = optimiser_functions.calculate_gain(
|
||||||
|
body=body, p=p, fixed_gain=fixed_gain, eco_packages=eco_packages,
|
||||||
|
already_installed_gain=already_installed_sap
|
||||||
|
)
|
||||||
|
|
||||||
|
# We insert the innovation uplift
|
||||||
|
measures_to_optimise_with_uplift = deepcopy(measures_to_optimise)
|
||||||
|
|
||||||
|
for group in measures_to_optimise_with_uplift:
|
||||||
|
for r in group:
|
||||||
|
(r["partial_project_score"], r["partial_project_funding"], r["innovation_uplift"],
|
||||||
|
r["uplift_project_score"]) = (0, 0, 0, 0)
|
||||||
|
|
||||||
# Remove them from the optimisation pool
|
# Remove them from the optimisation pool
|
||||||
finalised_measures_to_optimise = []
|
finalised_measures_to_optimise = []
|
||||||
for m in measures_to_optimise_with_uplift:
|
for m in measures_to_optimise_with_uplift:
|
||||||
|
|
|
||||||
|
|
@ -231,6 +231,49 @@ properties_data, plans_data, recommendations_data = get_data(
|
||||||
)
|
)
|
||||||
|
|
||||||
recommendations_df = pd.DataFrame(recommendations_data)
|
recommendations_df = pd.DataFrame(recommendations_data)
|
||||||
|
properties_df = pd.DataFrame(properties_data)
|
||||||
|
|
||||||
solar_pv_recommendations = recommendations_df[recommendations_df["measure_type"] == "solar_pv"]
|
solar_pv_recommendations = recommendations_df[recommendations_df["measure_type"] == "solar_pv"]
|
||||||
average_savings = solar_pv_recommendations.groupby("scenario_id")["energy_cost_savings"].mean().reset_index()
|
average_savings = solar_pv_recommendations.groupby("scenario_id")["energy_cost_savings"].mean().reset_index()
|
||||||
|
|
||||||
|
# Check tenures
|
||||||
|
initial_asset_data = pd.read_excel(
|
||||||
|
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/2025_11_11 - Peabody "
|
||||||
|
"- Data Extracts for Domna.xlsx",
|
||||||
|
sheet_name="Properties"
|
||||||
|
)
|
||||||
|
sustainability_data = pd.read_excel(
|
||||||
|
"/Users/khalimconn-kowlessar/Documents/hestia/Customers/Peabody/Nov 2025 Consulting Project/2025_11_11 - Peabody "
|
||||||
|
"- Data Extracts for Domna.xlsx",
|
||||||
|
sheet_name="Sustainability"
|
||||||
|
)
|
||||||
|
|
||||||
|
sustainability_sample = sustainability_data[
|
||||||
|
sustainability_data["UPRN"].isin(properties_df["uprn"].astype(int).astype(str).values)
|
||||||
|
]
|
||||||
|
|
||||||
|
sustainability_sample = sustainability_sample.merge(
|
||||||
|
initial_asset_data, left_on="Org Ref", right_on="UPRN", suffixes=("_sustainability", "_initial_asset")
|
||||||
|
)
|
||||||
|
|
||||||
|
block_sizes = initial_asset_data["BlockCode"].value_counts().reset_index().sort_values("count", ascending=False)
|
||||||
|
block_sizes.to_excel("/Users/khalimconn-kowlessar/Downloads/peabody_block_sizes.xlsx", index=False)
|
||||||
|
|
||||||
|
initial_asset_data.columns
|
||||||
|
initial_asset_data["LeaseType"].value_counts()
|
||||||
|
|
||||||
|
# sustainability_sample["Tenure Group"].value_counts()
|
||||||
|
# Tenure Group
|
||||||
|
# General Needs 57787
|
||||||
|
# Home Ownership 25471
|
||||||
|
# Care & Supported Housing 4239
|
||||||
|
# Rental 2677
|
||||||
|
# Other 188
|
||||||
|
|
||||||
|
df = sustainability_sample["Ownership Type"].value_counts().to_frame().reset_index()
|
||||||
|
df.to_excel("/Users/khalimconn-kowlessar/Downloads/sustainability_tenures.xlsx", index=False)
|
||||||
|
|
||||||
|
tenure_groups = sustainability_sample["Tenure Group"].value_counts().to_frame().reset_index()
|
||||||
|
tenure_groups.to_excel("/Users/khalimconn-kowlessar/Downloads/sustainability_tenure_groups.xlsx", index=False)
|
||||||
|
|
||||||
|
initial_asset_data[~pd.isnull(initial_asset_data["BlockCode"])]["Tenure Group"].value_counts()
|
||||||
|
|
|
||||||
|
|
@ -202,8 +202,13 @@ def calculate_fixed_gain(property_required_measures, recommendations, p, needs_v
|
||||||
return fixed_gain
|
return fixed_gain
|
||||||
|
|
||||||
|
|
||||||
def calculate_gain(body: PlanTriggerRequest, p: Property, fixed_gain: float,
|
def calculate_gain(
|
||||||
eco_packages: None | dict = None) -> float | None:
|
body: PlanTriggerRequest,
|
||||||
|
p: Property,
|
||||||
|
fixed_gain: float,
|
||||||
|
eco_packages: None | dict = None,
|
||||||
|
already_installed_gain: float = 0,
|
||||||
|
) -> float | None:
|
||||||
"""
|
"""
|
||||||
Calculates the target gain value for optimisation based on the goal.
|
Calculates the target gain value for optimisation based on the goal.
|
||||||
|
|
||||||
|
|
@ -221,6 +226,7 @@ def calculate_gain(body: PlanTriggerRequest, p: Property, fixed_gain: float,
|
||||||
fixed_gain : float
|
fixed_gain : float
|
||||||
Total fixed gain from required measures (returned by calculate_fixed_gain).
|
Total fixed gain from required measures (returned by calculate_fixed_gain).
|
||||||
eco_packages : dict, optional
|
eco_packages : dict, optional
|
||||||
|
already_installed_gain: float, optional
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
|
|
@ -228,13 +234,16 @@ def calculate_gain(body: PlanTriggerRequest, p: Property, fixed_gain: float,
|
||||||
Required SAP gain for EPC, or None for non-EPC goals.
|
Required SAP gain for EPC, or None for non-EPC goals.
|
||||||
"""
|
"""
|
||||||
if body.goal == "Increasing EPC":
|
if body.goal == "Increasing EPC":
|
||||||
current_sap = int(p.data["current-energy-efficiency"])
|
current_sap = int(p.data["current-energy-efficiency"]) + already_installed_gain
|
||||||
|
|
||||||
target_sap = (
|
target_sap = (
|
||||||
eco_packages.get(p.id)[1] if eco_packages.get(p.id)[1] is not None
|
eco_packages.get(p.id)[1] if eco_packages.get(p.id)[1] is not None
|
||||||
else epc_to_sap_lower_bound(body.goal_value)
|
else epc_to_sap_lower_bound(body.goal_value)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if target_sap == current_sap:
|
||||||
|
return 0
|
||||||
|
|
||||||
gain = CostOptimiser.calculate_sap_gain_with_slack(
|
gain = CostOptimiser.calculate_sap_gain_with_slack(
|
||||||
target_sap - current_sap
|
target_sap - current_sap
|
||||||
) - fixed_gain
|
) - fixed_gain
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,22 @@ class TestCalculateGain:
|
||||||
gain = optimiser_functions.calculate_gain(body, prop, fixed_gain=0)
|
gain = optimiser_functions.calculate_gain(body, prop, fixed_gain=0)
|
||||||
assert gain is None
|
assert gain is None
|
||||||
|
|
||||||
|
def test_returns_zero_for_already_installed_getting_to_target(self):
|
||||||
|
body = SimpleNamespace(goal="Increasing EPC", goal_value="C")
|
||||||
|
p = SimpleNamespace(data={"current-energy-efficiency": "67"}, id=1)
|
||||||
|
fixed_gain = 0
|
||||||
|
eco_packages = {1: (None, None, None, [])}
|
||||||
|
already_installed_sap = 2
|
||||||
|
gain = optimiser_functions.calculate_gain(
|
||||||
|
body=body,
|
||||||
|
p=p,
|
||||||
|
fixed_gain=fixed_gain,
|
||||||
|
eco_packages=eco_packages,
|
||||||
|
already_installed_gain=already_installed_sap
|
||||||
|
)
|
||||||
|
|
||||||
|
assert gain == 0
|
||||||
|
|
||||||
def test_calculates_gain_for_epc(self, monkeypatch):
|
def test_calculates_gain_for_epc(self, monkeypatch):
|
||||||
# patch cost optimiser calculation
|
# patch cost optimiser calculation
|
||||||
monkeypatch.setattr(optimiser_functions, "epc_to_sap_lower_bound", lambda goal_value: 69)
|
monkeypatch.setattr(optimiser_functions, "epc_to_sap_lower_bound", lambda goal_value: 69)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue