diff --git a/dynamics/Dynamic.py b/dynamics/Dynamic.py index 3049b8c2c355d6407a241cc1e1c94d8a0360db13..3834e501cba499346c5b1586e5c3e8268d94a4cd 100644 --- a/dynamics/Dynamic.py +++ b/dynamics/Dynamic.py @@ -23,6 +23,7 @@ THE SOFTWARE. """ import pandas as pd +import pyomo.environ as pyo # The root dynamic is # for TrivialDynamic: self @@ -414,11 +415,9 @@ def resample_to_backed(values, dynamic, source_p_start, source_p_end, target_dyn target_values = values.loc[target_dynamic.indices[target_p_start:target_p_end]] for target_position in range(target_p_start, target_p_end): acc = 0 - sum = 0 for source_index in dynamic.get_indices_within(target_dynamic.indices[target_position], target_dynamic.indices[target_position + 1]): acc += values.loc[source_index] * dynamic.step_size(source_index) - sum += dynamic.step_size(source_index) - target_values.loc[target_dynamic.indices[target_position]] = acc / float(sum) + target_values.loc[target_dynamic.indices[target_position]] = acc / target_dynamic.step_size_p(target_position) return target_values def resample_into_to_backed(values, dynamic, source_p_start, source_p_end, target_dynamic, target_p_start, target_p_end, target_values): @@ -446,11 +445,9 @@ def resample_into_to_backed(values, dynamic, source_p_start, source_p_end, targe target_p_end = target_dynamic.get_position_of(source_i_end) for target_position in range(target_p_start, target_p_end): acc = 0 - sum = 0 for source_index in dynamic.get_indices_within(target_dynamic.indices[target_position], target_dynamic.indices[target_position + 1]): acc += values.loc[source_index] * dynamic.step_size(source_index) - sum += dynamic.step_size(source_index) - target_values.loc[target_dynamic.indices[target_position]] = acc / float(sum) + target_values.loc[target_dynamic.indices[target_position]] = acc / target_dynamic.step_size_p(target_position) return target_values # dynamic is BackedDynamic and has target_dynamic as an ancestor @@ -602,6 +599,96 @@ def resample_into_common_reference(values, dynamic, source_p_start, source_p_end target_position += 1 return target_values +# only works if both dynamics share the same root dynamic +def resample_variable(variable, dynamic, target_dynamic, target_set): + if dynamic.get_root_dynamic() != target_dynamic.get_root_dynamic(): + raise ValueError("Both dynamics have to have the same root dynamic!") + if target_dynamic.get_index_of(0) != dynamic.get_index_of(0) or dynamic.get_index_of(dynamic.number_of_steps()) != target_dynamic.get_index_of(target_dynamic.number_of_steps()): + raise ValueError("The source and target dynamic has to cover the same interval of time!") + non_partial_dynamic = dynamic + while isinstance(non_partial_dynamic, PartialDynamic): + non_partial_dynamic = non_partial_dynamic.reference + source_p_start = non_partial_dynamic.get_position_of(dynamic.get_index_of(0)) + source_p_end = non_partial_dynamic.get_position_of(dynamic.get_index_of(dynamic.number_of_steps())) + non_partial_target_dynamic = target_dynamic + while isinstance(non_partial_target_dynamic, PartialDynamic): + non_partial_target_dynamic = non_partial_target_dynamic.reference + target_p_start = non_partial_target_dynamic.get_position_of(target_dynamic.get_index_of(0)) + target_p_end = non_partial_target_dynamic.get_position_of(target_dynamic.get_index_of(target_dynamic.number_of_steps())) + if non_partial_dynamic == non_partial_target_dynamic: + return resample_variable_same(variable, non_partial_dynamic, source_p_start, source_p_end, non_partial_target_dynamic, target_p_start, target_p_end, target_set) + elif isinstance(non_partial_target_dynamic, BackedDynamic) and non_partial_target_dynamic.has_ancestor(non_partial_dynamic): + return resample_variable_to_backed(variable, non_partial_dynamic, source_p_start, source_p_end, non_partial_target_dynamic, target_p_start, target_p_end, target_set) + elif isinstance(non_partial_dynamic, BackedDynamic) and non_partial_dynamic.has_ancestor(non_partial_target_dynamic): + return resample_variable_from_backed(variable, non_partial_dynamic, source_p_start, source_p_end, non_partial_target_dynamic, target_p_start, target_p_end, target_set) + else: + return resample_variable_common_reference(variable, non_partial_dynamic, source_p_start, source_p_end, non_partial_target_dynamic, target_p_start, target_p_end, target_set) + +# source_dynamic and target_dynamic are the same dynamic +def resample_variable_same(variable, dynamic, source_p_start, source_p_end, target_dnymiac, target_p_start, target_p_end, target_set): + def rule(m, t): + return variable[t] + return pyo.Expression(target_set, rule=rule) + +# target_dynamic is BackedDynamic and has dynamic as an ancestor +def resample_variable_to_backed(variable, dynamic, source_p_start, source_p_end, target_dynamic, target_p_start, target_p_end, target_set): + def rule(m, t): + target_position = target_dynamic.get_position_of(t) + acc = 0 + for source_index in dynamic.get_indices_within(target_dynamic.indices[target_position], target_dynamic.indices[target_position + 1]): + acc += variable[source_index] * dynamic.step_size(source_index) + return acc / target_dynamic.step_size_p(target_position) + return pyo.Expression(target_set, rule=rule) + +# dynamic is BackedDynamic and has target_dynamic as an ancestor +def resample_variable_from_backed(variable, dynamic, source_p_start, source_p_end, target_dynamic, target_p_start, target_p_end, target_set): + assignment = dict() + source_i_start = dynamic.indices[source_p_start] + target_i_start = target_dynamic.get_index_of(target_p_start) + if source_i_start < target_i_start: + source_p_start = dynamic.get_position_of(target_i_start) + source_i_end = dynamic.indices[source_p_end] + target_i_end = target_dynamic.get_index_of(target_p_end) + if target_i_end < source_i_end: + source_p_end = dynamic.get_position_of(target_i_end) + for source_position in range(source_p_start, source_p_end): + target_indices = target_dynamic.get_indices_within(dynamic.indices[source_position], dynamic.indices[source_position + 1]) + for target_index in target_indices: + assignment[target_index] = variable[dynamic.indices[source_position]] + def rule(m, t): + return assignment[t] + return pyo.Expression(target_set, rule=rule) + +# dynamic and target_dynamic share the same root dynamic +def resample_variable_common_reference(variable, dynamic, source_p_start, source_p_end, target_dynamic, target_p_start, target_p_end, target_set): + assignment = dict() + target_i_start = target_dynamic.get_index_of(target_p_start) + source_position = dynamic.get_position_of(target_i_start) + target_position = target_p_start + remaining_length = dynamic.step_size_p(source_position) + while target_position < target_p_end: + remaining_target_length = target_dynamic.step_size_p(target_position) + acc = [] + while remaining_target_length > 0: + if remaining_length == 0: + source_position += 1 + remaining_length = dynamic.step_size_p(source_position) + if remaining_target_length <= remaining_length: + acc.append((variable[dynamic.get_index_of(source_position)], remaining_target_length)) + remaining_length -= remaining_target_length + remaining_target_length -= remaining_target_length + else: + acc.append((variable[dynamic.get_index_of(source_position)], remaining_length)) + remaining_target_length -= remaining_length + remaining_length -= remaining_length + for i, (single_variable, factor) in enumerate(acc): + acc[i] = (single_variable, factor / target_dynamic.step_size_p(target_position)) + assignment[target_dynamic.get_index_of(target_position)] = acc + target_position += 1 + def rule(m, t): + return pyo.quicksum(variable * factor for variable, factor in assignment[t]) + return pyo.Expression(target_set, rule=rule) + def test_single_resampling(dynamic, target_dynamic): index = [dynamic.get_index_of(position) for position in range(dynamic.number_of_steps())] values = pd.Series(data = [float(i) for i in range(len(index))], index = index) @@ -611,7 +698,19 @@ def test_single_resampling(dynamic, target_dynamic): print('hey') target_index = [target_dynamic.get_index_of(position) for position in range(target_dynamic.number_of_steps())] target_values = pd.Series(dtype = float, index = target_index) - print(resample_into(values, dynamic, target_dynamic, target_values)) + try: + print(resample_into(values, dynamic, target_dynamic, target_values)) + except: + print('hey') + model = pyo.ConcreteModel() + model.set = pyo.Set(initialize = list(dynamic.time_steps()), ordered=True) + model.target_set = pyo.Set(initialize = list(target_dynamic.time_steps()), ordered=True) + model.variable = pyo.Var(model.set) + try: + model.expression = resample_variable(model.variable, dynamic, target_dynamic, model.target_set) + print(model.expression.pprint()) + except: + print('hey') def test_resampling(): dynamics = {} @@ -636,9 +735,6 @@ def test_resampling(): dynamics['d_4_4'] = BackedDynamic(dynamics['d_4'], [6, 12, 18, 24, 30]) dynamics['d_4_4_1'] = PartialDynamic(dynamics['d_4_4'], 0, 4) dynamics['d_4_4_2'] = PartialDynamic(dynamics['d_4_4'], 1, 3) + dynamics['d_5'] = BackedDynamic(dynamics['d'], [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36]) - test_resampling(dynamics['d_1'], dynamics['d_2']) - test_resampling(dynamics['d_3_4'], dynamics['d_4']) - test_resampling(dynamics['d_3_4_2'], dynamics['d_4']) - test_resampling(dynamics['d_3_4'], dynamics['d_4_2']) - test_resampling(dynamics['d_3_4_2'], dynamics['d_4_2']) + test_single_resampling(dynamics['d'], dynamics['d'])