Skip to content
Snippets Groups Projects
Commit f020357d authored by Pedro L. Magalhães's avatar Pedro L. Magalhães
Browse files

Created new methods for problem statistics.

parent 5497c30d
Branches
No related tags found
1 merge request!6Stats
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
import numpy as np import numpy as np
from geopandas import GeoDataFrame from geopandas import GeoDataFrame
from ...misc.utils import discrete_sinusoid_matching_integral from ...misc.utils import discrete_sinusoid_matching_integral
from ...misc.utils import create_profile_using_time_weighted_state # from ...misc.utils import create_profile_using_time_weighted_state
from ...misc.utils import generate_manual_state_correlated_profile
from ...misc.utils import generate_state_correlated_profile
from .bbr import label_bbr_entrance_id, label_bbr_housing_area from .bbr import label_bbr_entrance_id, label_bbr_housing_area
# ***************************************************************************** # *****************************************************************************
...@@ -66,6 +68,8 @@ def heat_demand_dict_by_building_entrance( ...@@ -66,6 +68,8 @@ def heat_demand_dict_by_building_entrance(
key_bbr_entr_id: str = label_bbr_entrance_id, key_bbr_entr_id: str = label_bbr_entrance_id,
avg_state: list = None, avg_state: list = None,
state_correlates_with_output: bool = False, state_correlates_with_output: bool = False,
deviation_gain: float = 1.0,
solver: str = 'glpk'
) -> dict: ) -> dict:
# initialise dict for each building entrance # initialise dict for each building entrance
...@@ -84,11 +88,8 @@ def heat_demand_dict_by_building_entrance( ...@@ -84,11 +88,8 @@ def heat_demand_dict_by_building_entrance(
# for each building # for each building
for building_index in building_indexes: for building_index in building_indexes:
# get relevant data # get relevant data
# base_load_avg_ratio = 0.3
# specific_demand = 107 # kWh/m2/year
area = gdf_buildings.loc[building_index][label_bbr_housing_area] area = gdf_buildings.loc[building_index][label_bbr_housing_area]
# generate the profile
# estimate its demand
if type(avg_state) == type(None): if type(avg_state) == type(None):
# ignore states # ignore states
heat_demand_profiles.append( heat_demand_profiles.append(
...@@ -104,18 +105,46 @@ def heat_demand_dict_by_building_entrance( ...@@ -104,18 +105,46 @@ def heat_demand_dict_by_building_entrance(
) )
) )
elif type(deviation_gain) == type(None):
# states matter but the gain must be determined
# heat_demand_profiles.append(
# np.array(
# create_profile_using_time_weighted_state(
# integration_result=(
# bdg_specific_demand[building_index] * area
# ),
# avg_state=avg_state,
# time_interval_durations=time_interval_durations,
# min_to_max_ratio=bdg_ratio_min_max[building_index],
# state_correlates_with_output=state_correlates_with_output,
# )
# )
# )
heat_demand_profiles.append(
np.array(
generate_state_correlated_profile(
integration_result=(
bdg_specific_demand[building_index] * area
),
states=avg_state,
time_interval_durations=time_interval_durations,
states_correlate_profile=state_correlates_with_output,
min_max_ratio=bdg_ratio_min_max[building_index],
solver=solver
)
)
)
else: else:
# states matter # states matter and the gain is predefined
heat_demand_profiles.append( heat_demand_profiles.append(
np.array( np.array(
create_profile_using_time_weighted_state( generate_manual_state_correlated_profile(
integration_result=( integration_result=(
bdg_specific_demand[building_index] * area bdg_specific_demand[building_index] * area
), ),
avg_state=avg_state, states=avg_state,
time_interval_durations=time_interval_durations, time_interval_durations=time_interval_durations,
min_to_max_ratio=bdg_ratio_min_max[building_index], deviation_gain=deviation_gain
state_correlates_with_output=state_correlates_with_output,
) )
) )
) )
......
...@@ -368,7 +368,7 @@ def generate_state_correlated_profile( ...@@ -368,7 +368,7 @@ def generate_state_correlated_profile(
states_correlate_profile: bool, states_correlate_profile: bool,
min_max_ratio: float, min_max_ratio: float,
solver: str solver: str
) -> list: ) -> tuple:
""" """
Returns a profile observing a number of conditions. Returns a profile observing a number of conditions.
...@@ -379,6 +379,23 @@ def generate_state_correlated_profile( ...@@ -379,6 +379,23 @@ def generate_state_correlated_profile(
This method relies on linear programming. An LP solver must be used. This method relies on linear programming. An LP solver must be used.
The profile for interval i is defined as follows:
P[i] = (dt[i]/dt_mean)*( (x[i]-x_mean)*gain + offset)
where:
dt[i] is the time interval duration for interval i
dt_mean is the mean time interval duration
x[i] is the state for interval i
x_mean is the mean state for the entire profile
The offset is defined as the integration result divided by the number
time intervals, whereas the gain is determined via optimisation.
Parameters Parameters
---------- ----------
integration_result : float integration_result : float
...@@ -402,14 +419,16 @@ def generate_state_correlated_profile( ...@@ -402,14 +419,16 @@ def generate_state_correlated_profile(
Returns Returns
------- -------
list tuple
A profile matching the aforementioned characteristics. A tuple containing the profile, the gain and the offset.
""" """
# ************************************************************************* # *************************************************************************
# ************************************************************************* # *************************************************************************
# TODO: find alternative solution, as this is most likely overkill
# internal model # internal model
def model(states_correlate_profile: bool) -> pyo.AbstractModel: def model(states_correlate_profile: bool) -> pyo.AbstractModel:
...@@ -477,10 +496,8 @@ def generate_state_correlated_profile( ...@@ -477,10 +496,8 @@ def generate_state_correlated_profile(
# ************************************************************************* # *************************************************************************
# ************************************************************************* # *************************************************************************
dt_total = sum(time_interval_durations) dt_total = sum(time_interval_durations)
dt_mean = mean(time_interval_durations) dt_mean = mean(time_interval_durations)
# x_mean = mean(states)
x_mean = sum( x_mean = sum(
deltat_k*x_k deltat_k*x_k
for deltat_k, x_k in zip(time_interval_durations, states) for deltat_k, x_k in zip(time_interval_durations, states)
...@@ -510,7 +527,11 @@ def generate_state_correlated_profile( ...@@ -510,7 +527,11 @@ def generate_state_correlated_profile(
problem = fit_model.create_instance(data=data_dict) problem = fit_model.create_instance(data=data_dict)
opt.solve(problem, tee=False) opt.solve(problem, tee=False)
# return profile # return profile
return [pyo.value(problem.P_i[i]) for i in problem.I] return (
[pyo.value(problem.P_i[i]) for i in problem.I],
pyo.value(problem.alpha),
beta
)
# ***************************************************************************** # *****************************************************************************
# ***************************************************************************** # *****************************************************************************
......
This diff is collapsed.
# imports # imports
# standard # standard
import random import random
import math import math
from statistics import mean from statistics import mean
# local, internal # local, internal
from src.topupopt.data.misc import utils from src.topupopt.data.misc import utils
# ******************************************************************************
# ******************************************************************************
class TestDataUtils: class TestDataUtils:
# *************************************************************************
# *************************************************************************
def test_profile_synching2(self): def test_profile_synching2(self):
integration_result = 10446 integration_result = 10446
...@@ -390,7 +380,7 @@ class TestDataUtils: ...@@ -390,7 +380,7 @@ class TestDataUtils:
states_correlate_profile = True states_correlate_profile = True
min_max_ratio = 0.2 min_max_ratio = 0.2
profile = utils.generate_state_correlated_profile( profile, a, b = utils.generate_state_correlated_profile(
integration_result=integration_result, integration_result=integration_result,
states=states, states=states,
time_interval_durations=time_interval_durations, time_interval_durations=time_interval_durations,
...@@ -400,6 +390,7 @@ class TestDataUtils: ...@@ -400,6 +390,7 @@ class TestDataUtils:
) )
# test profile # test profile
assert a > 0 and b > 0
assert len(profile) == number_time_intervals assert len(profile) == number_time_intervals
assert math.isclose(sum(profile), integration_result, abs_tol=1e-3) assert math.isclose(sum(profile), integration_result, abs_tol=1e-3)
assert math.isclose(min(profile), max(profile)*min_max_ratio, abs_tol=1e-3) assert math.isclose(min(profile), max(profile)*min_max_ratio, abs_tol=1e-3)
...@@ -413,7 +404,7 @@ class TestDataUtils: ...@@ -413,7 +404,7 @@ class TestDataUtils:
states_correlate_profile = False states_correlate_profile = False
min_max_ratio = 0.2 min_max_ratio = 0.2
profile = utils.generate_state_correlated_profile( profile, a, b = utils.generate_state_correlated_profile(
integration_result=integration_result, integration_result=integration_result,
states=states, states=states,
time_interval_durations=time_interval_durations, time_interval_durations=time_interval_durations,
...@@ -423,6 +414,7 @@ class TestDataUtils: ...@@ -423,6 +414,7 @@ class TestDataUtils:
) )
# test profile # test profile
assert a < 0 and b > 0
assert len(profile) == number_time_intervals assert len(profile) == number_time_intervals
assert math.isclose(sum(profile), integration_result, abs_tol=1e-3) assert math.isclose(sum(profile), integration_result, abs_tol=1e-3)
assert math.isclose(min(profile), max(profile)*min_max_ratio, abs_tol=1e-3) assert math.isclose(min(profile), max(profile)*min_max_ratio, abs_tol=1e-3)
...@@ -464,7 +456,6 @@ class TestDataUtils: ...@@ -464,7 +456,6 @@ class TestDataUtils:
# correlation: direct, inverse # correlation: direct, inverse
# states: positive, negative # states: positive, negative
# time intervals: regular irregular # time intervals: regular irregular
#
# profile with positive correlation, positive states, regular intervals # profile with positive correlation, positive states, regular intervals
number_time_intervals = 10 number_time_intervals = 10
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment