mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
optimisation bugs fixed and reviewed with kieran
This commit is contained in:
parent
7ee9476dc1
commit
3dc5405b74
6 changed files with 44 additions and 21 deletions
|
|
@ -623,7 +623,6 @@ class Property:
|
|||
floor_height=self.floor_height,
|
||||
perimeter=self.perimeter,
|
||||
built_form=self.data["built-form"],
|
||||
property_type=self.data["property-type"],
|
||||
)
|
||||
|
||||
self.insulation_floor_area = self.floor_area / self.number_of_floors
|
||||
|
|
|
|||
|
|
@ -134,7 +134,6 @@ async def trigger_plan(body: PlanTriggerRequest):
|
|||
p.get_spatial_data(uprn_filenames)
|
||||
|
||||
logger.info("Getting components and epc recommendations")
|
||||
|
||||
recommendations = {}
|
||||
recommendations_scoring_data = []
|
||||
representative_recommendations = {}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@ class HeatingRecommender:
|
|||
# This first iteration of the recommender will provide very basic recommendation
|
||||
# We recommend heating controls based on the main heating system
|
||||
if self.property.main_heating["clean_description"] == "Room heaters, electric":
|
||||
self.recommend_room_heaters_electric(phase=phase, system_change=False, heating_controls_only=True)
|
||||
self.recommend_electric_storage_heaters(phase=phase, system_change=True, heating_controls_only=False)
|
||||
# Recommend high heat retention storage heaters
|
||||
# self.recommend_room_heaters_electric(phase=phase, system_change=False, heating_controls_only=True)
|
||||
# self.recommend_electric_storage_heaters(phase=phase, system_change=True, heating_controls_only=False)
|
||||
return
|
||||
|
||||
if self.property.main_heating["clean_description"] == "Electric storage heaters, radiators":
|
||||
|
|
@ -164,7 +165,8 @@ class HeatingRecommender:
|
|||
costs={},
|
||||
description="",
|
||||
phase=phase,
|
||||
heating_controls_only=heating_controls_only
|
||||
heating_controls_only=heating_controls_only,
|
||||
system_change=system_change
|
||||
)
|
||||
)
|
||||
return
|
||||
|
|
@ -221,7 +223,8 @@ class HeatingRecommender:
|
|||
costs={},
|
||||
description="",
|
||||
phase=phase,
|
||||
heating_controls_only=heating_controls_only
|
||||
heating_controls_only=heating_controls_only,
|
||||
system_change=system_change
|
||||
)
|
||||
)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -30,7 +30,9 @@ class CostOptimiser:
|
|||
:param min_gain: Numerical value for the minimum gain
|
||||
:return:
|
||||
"""
|
||||
if min_gain <= 5:
|
||||
if min_gain == 0:
|
||||
return min_gain
|
||||
elif min_gain <= 5:
|
||||
return min_gain + 0.5
|
||||
elif min_gain <= 20:
|
||||
return min_gain + 1.5
|
||||
|
|
|
|||
|
|
@ -9,11 +9,15 @@ class GainOptimiser:
|
|||
This class is used to maximise gain, given a constrained cost
|
||||
"""
|
||||
|
||||
def __init__(self, components, max_cost, max_gain=None):
|
||||
def __init__(self, components, max_cost, max_gain):
|
||||
"""
|
||||
This function will try and maximise the gain, given a constrained cost. If we specific a max_gain, then the
|
||||
optimisation routine is constained to try not to exceed a maximum increase
|
||||
|
||||
|
||||
If the maximum gain (`max_gain`) is explicitly set to 0, the optimization routine interprets this as an
|
||||
instruction not to perform any optimization.
|
||||
|
||||
:param components: List of components, where each component is a dictionary with keys "id", "cost" and "gain"
|
||||
:param max_cost: Maximum cost constraint
|
||||
:param max_gain: Maximum gain constraint
|
||||
|
|
@ -78,6 +82,10 @@ class GainOptimiser:
|
|||
# Remove the original cost constraint
|
||||
self.m.remove(self.cost_constraint)
|
||||
|
||||
if self.max_gain is not None:
|
||||
# Remove the original max gain constraint
|
||||
self.m.remove(self.max_gain_constraint)
|
||||
|
||||
# Add slack variable
|
||||
s = self.m.add_var(lb=0)
|
||||
|
||||
|
|
@ -99,18 +107,34 @@ class GainOptimiser:
|
|||
|
||||
def solve(self):
|
||||
# Solve the problem
|
||||
|
||||
if self.max_gain == 0:
|
||||
logger.info("Max gain is set to 0, no optimisation will be performed")
|
||||
# Nothing to do
|
||||
return
|
||||
|
||||
self.m.optimize()
|
||||
|
||||
if self.m.status == OptimizationStatus.INFEASIBLE:
|
||||
logger.info("We have an infeasible model, setting up slack model")
|
||||
self.setup_slack()
|
||||
self.m.optimize()
|
||||
|
||||
self.solution = [
|
||||
solution = [
|
||||
item for group, group_vars in zip(self.components, self.variables) for item, var in zip(group, group_vars)
|
||||
if
|
||||
var.x >= 0.99
|
||||
]
|
||||
|
||||
if (self.m.status == OptimizationStatus.INFEASIBLE) or (
|
||||
(self.m.status == OptimizationStatus.OPTIMAL) and not len(solution)
|
||||
):
|
||||
logger.info("We have an infeasible model, setting up slack model")
|
||||
self.setup_slack()
|
||||
self.m.optimize()
|
||||
solution = [
|
||||
item for group, group_vars in zip(self.components, self.variables) for item, var in
|
||||
zip(group, group_vars)
|
||||
if
|
||||
var.x >= 0.99
|
||||
]
|
||||
|
||||
self.solution = solution
|
||||
|
||||
self.solution_gain = self.m.objective.x
|
||||
self.solution_cost = sum([component['cost'] for component in self.solution])
|
||||
|
|
|
|||
|
|
@ -544,7 +544,7 @@ def get_wall_type(
|
|||
return None
|
||||
|
||||
|
||||
def estimate_external_wall_area(num_floors, floor_height, perimeter, built_form, property_type):
|
||||
def estimate_external_wall_area(num_floors, floor_height, perimeter, built_form):
|
||||
"""
|
||||
This method estimates the external wall area based on fundamental assumptions about the home
|
||||
|
||||
|
|
@ -553,7 +553,6 @@ def estimate_external_wall_area(num_floors, floor_height, perimeter, built_form,
|
|||
:param floor_height: Height of one floor in meters.
|
||||
:param perimeter: Total perimeter of the building on one floor in meters.
|
||||
:param built_form: The built form of the property. This is used to determine the number of exposed walls.
|
||||
:param property_type: The type of the property. This is used to determine the number of exposed walls.
|
||||
:return:
|
||||
"""
|
||||
wall_area_one_floor = perimeter * floor_height
|
||||
|
|
@ -566,11 +565,8 @@ def estimate_external_wall_area(num_floors, floor_height, perimeter, built_form,
|
|||
'Semi-Detached': 3,
|
||||
'Detached': 4,
|
||||
}
|
||||
if built_form == "Detached" and property_type == "Flat":
|
||||
# We don't have 4 exposed walls for a flat
|
||||
exposed_wall_area = total_wall_area * (3 / 4)
|
||||
else:
|
||||
exposed_wall_area = total_wall_area * (number_exposed_walls.get(built_form, 3) / 4)
|
||||
|
||||
exposed_wall_area = total_wall_area * (number_exposed_walls.get(built_form, 3) / 4)
|
||||
|
||||
return exposed_wall_area
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue