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

Added TimeFrame class.

parent bc6335c7
No related branches found
No related tags found
1 merge request!5Revised ResourcePrice class and methods. Added tests for problem...
This commit is part of merge request !5. Comments created here will be created in the context of that merge request.
# -*- coding: utf-8 -*-
"""
Created on Wed Nov 17 13:04:53 2021
@author: pmede
"""
# standard libraries # standard libraries
# local libraries, external # local libraries, external
import numpy as np import numpy as np
# local libraries, internal # local libraries, internal
from .dynsys import DynamicSystem from .dynsys import DynamicSystem
from .signal import Signal, FixedSignal from .signal import Signal, FixedSignal
# ***************************************************************************** # *****************************************************************************
# ***************************************************************************** # *****************************************************************************
# objectives:
# 1) organise information for optimisation
# 2) upload optimisation results and compute the various objectives
# 3) retrieve information
# 4)
# TODO: create constant terms using fixed signals # TODO: create constant terms using fixed signals
...@@ -35,8 +18,6 @@ class Converter: ...@@ -35,8 +18,6 @@ class Converter:
def __init__( def __init__(
self, self,
# converter name/key
key,
# system information # system information
sys: DynamicSystem, sys: DynamicSystem,
# initial conditions # initial conditions
...@@ -49,6 +30,14 @@ class Converter: ...@@ -49,6 +30,14 @@ class Converter:
outputs: list or Signal = None, outputs: list or Signal = None,
# information about states # information about states
states: list or Signal = None, states: list or Signal = None,
# final A matrix dict: a_nnk
a_nnk: dict = None,
# final B matrix dict: b_nmk
b_nmk: dict = None,
# final C matrix dict: c_rnk
c_rnk: dict = None,
# final D matrix dict: d_rmk
d_rmk: dict = None,
# input amplitude costs # input amplitude costs
input_specific_amplitude_costs: dict = None, input_specific_amplitude_costs: dict = None,
# output amplitude costs # output amplitude costs
...@@ -63,12 +52,24 @@ class Converter: ...@@ -63,12 +52,24 @@ class Converter:
): ):
# ********************************************************************* # *********************************************************************
self.key = key
self.sys = sys self.sys = sys
# ********************************************************************* # *********************************************************************
if type(a_nnk) == dict:
self.a_nnk = a_nnk # dict(a_nnk)
if type(b_nmk) == dict:
self.b_nmk = b_nmk # dict(b_nmk)
if type(c_rnk) == dict:
self.c_rnk = c_rnk # dict(c_rnk)
if type(d_rmk) == dict:
self.d_rmk = d_rmk # dict(d_rmk)
# *********************************************************************
# inputs # inputs
if type(inputs) == list: if type(inputs) == list:
...@@ -245,59 +246,59 @@ class Converter: ...@@ -245,59 +246,59 @@ class Converter:
number_intervals = self.inputs[0].number_samples number_intervals = self.inputs[0].number_samples
# a_innk # a_nnk
a_innk = { a_nnk = {
(self.key, n1, n2, k): self.sys.A_line_k[ (n1, n2, k): self.sys.A_line_k[k if self.sys.A_line_is_time_varying else 0][
k if self.sys.A_line_is_time_varying else 0 n1, n2
][n1, n2] ]
for n1 in range(self.sys.number_states) # the state being defined for n1 in range(self.sys.number_states) # the state being defined
for n2 in range(self.sys.number_states) # the influencing state for n2 in range(self.sys.number_states) # the influencing state
for k in range(number_intervals) # the time interval for k in range(number_intervals) # the time interval
} }
# b_inmk # b_nmk
b_inmk = { b_nmk = {
(self.key, n1, m, k): self.sys.B_line_k[ (n1, m, k): self.sys.B_line_k[k if self.sys.B_line_is_time_varying else 0][
k if self.sys.B_line_is_time_varying else 0 n1, m
][n1, m] ]
for n1 in range(self.sys.number_states) # the state being defined for n1 in range(self.sys.number_states) # the state being defined
for m in range(self.sys.number_inputs) # the influencing input for m in range(self.sys.number_inputs) # the influencing input
if m not in self.fixed_inputs # free inputs only if m not in self.fixed_inputs # free inputs only
for k in range(number_intervals) # the time interval for k in range(number_intervals) # the time interval
} }
# c_irnk # c_rnk
c_irnk = { c_rnk = {
(self.key, r, n, k): self.sys.C_line_k[ (r, n, k): self.sys.C_line_k[k if self.sys.C_line_is_time_varying else 0][
k if self.sys.C_line_is_time_varying else 0 r, n
][r, n] ]
for r in range(self.sys.number_outputs) # the output being defined for r in range(self.sys.number_outputs) # the output being defined
for n in range(self.sys.number_states) # the influencing state for n in range(self.sys.number_states) # the influencing state
for k in range(number_intervals) # the time interval for k in range(number_intervals) # the time interval
} }
# d_irmk # d_rmk
d_irmk = { d_rmk = {
(self.key, r, m, k): self.sys.D_line_k[ (r, m, k): self.sys.D_line_k[k if self.sys.D_line_is_time_varying else 0][
k if self.sys.D_line_is_time_varying else 0 r, m
][r, m] ]
for r in range(self.sys.number_outputs) # the output being defined for r in range(self.sys.number_outputs) # the output being defined
for m in range(self.sys.number_inputs) # the influencing input for m in range(self.sys.number_inputs) # the influencing input
if m not in self.fixed_inputs # free inputs only if m not in self.fixed_inputs # free inputs only
for k in range(number_intervals) # the time interval for k in range(number_intervals) # the time interval
} }
# note: e_x_ink does not depend on the initial conditions since the # note: e_x_nk does not depend on the initial conditions since the
# a_innk coefficients contain the information to handle them elsewhere # a_nnk coefficients contain the information to handle them elsewhere
# e_x_ink: depends on fixed signals # e_x_nk: depends on fixed signals
e_x_ink = { e_x_nk = {
(self.key, n, k): sum( (n, k): sum(
self.sys.B_line_k[k if self.sys.B_line_is_time_varying else 0][n, m] self.sys.B_line_k[k if self.sys.B_line_is_time_varying else 0][n, m]
* self.inputs[m].samples[k] * self.inputs[m].samples[k]
for m in self.fixed_inputs # b_inmk*u_imk for fixed inputs for m in self.fixed_inputs # b_inmk*u_imk for fixed inputs
...@@ -306,13 +307,13 @@ class Converter: ...@@ -306,13 +307,13 @@ class Converter:
for k in range(number_intervals) # the time interval for k in range(number_intervals) # the time interval
} }
# e_y_irk: depends on fixed signals # e_y_rk: depends on fixed signals
e_y_irk = { e_y_rk = {
(self.key, r, k): sum( (r, k): sum(
self.sys.D_line_k[k if self.sys.D_line_is_time_varying else 0][r, m] self.sys.D_line_k[k if self.sys.D_line_is_time_varying else 0][r, m]
* self.inputs[m].samples[k] * self.inputs[m].samples[k]
for m in self.fixed_inputs # d_irmk*u_imk for fixed inputs for m in self.fixed_inputs # d_rmk*u_mk for fixed inputs
) )
for r in range(self.sys.number_outputs) # the output being defined for r in range(self.sys.number_outputs) # the output being defined
for k in range(number_intervals) # the time interval for k in range(number_intervals) # the time interval
...@@ -320,136 +321,8 @@ class Converter: ...@@ -320,136 +321,8 @@ class Converter:
# return statement # return statement
return a_innk, b_inmk, c_irnk, d_irmk, e_x_ink, e_y_irk return a_nnk, b_nmk, c_rnk, d_rmk, e_x_nk, e_y_rk
# # *************************************************************************
# # *************************************************************************
# def has_dimensionable_inputs(self):
# if len(self.dimensionable_inputs) == 0:
# # the system has no dimensionable inputs
# return False
# else: # the system has dimensionable inputs
# return True
# # *************************************************************************
# # *************************************************************************
# def has_binary_inputs(self):
# if len(self.binary_inputs) == 0:
# # the system has no binary inputs
# return False
# else: # the system has binary inputs
# return True
# # *************************************************************************
# # *************************************************************************
# def has_amplitude_penalised_inputs(self):
# if len(self.amplitude_penalised_inputs) == 0:
# # the system has no amplitude-penalised inputs
# return False
# else: # the system has amplitude-penalised inputs
# return True
# # *************************************************************************
# # *************************************************************************
# def has_externality_inducing_inputs(self):
# if len(self.externality_inducing_inputs) == 0:
# # the system has no externality-inducing inputs
# return False
# else: # the system has externality-inducing inputs
# return True
# # *************************************************************************
# # *************************************************************************
# def has_externality_inducing_outputs(self):
# if len(self.externality_inducing_outputs) == 0:
# # the system has no externality-inducing outputs
# return False
# else: # the system has externality-inducing outputs
# return True
# # *************************************************************************
# # *************************************************************************
# def identify_dimensionable_inputs(self):
# self.dimensionable_inputs = [
# i
# for i, u in enumerate(self.inputs)
# if u.is_dimensionable]
# # *************************************************************************
# # *************************************************************************
# def identify_binary_inputs(self):
# self.binary_inputs = [
# i
# for i, u in enumerate(self.inputs)
# if u.is_binary]
# # *************************************************************************
# # *************************************************************************
# def identify_externality_inducing_inputs(self):
# self.externality_inducing_inputs = [
# i
# for i, c in enumerate(self.input_externalities)
# if c != 0]
# # *************************************************************************
# # *************************************************************************
# def identify_externality_inducing_outputs(self):
# self.externality_inducing_outputs = [
# i
# for i, c in enumerate(self.output_externalities)
# if c != 0]
# # *************************************************************************
# # *************************************************************************
# def identify_amplitude_penalised_inputs(self):
# self.amplitude_penalised_inputs = [
# i
# for i, c in enumerate(self.input_amplitude_costs)
# if c != 0]
# # *************************************************************************
# # *************************************************************************
# ***************************************************************************** # *****************************************************************************
# ***************************************************************************** # *****************************************************************************
...@@ -2768,80 +2768,57 @@ class InfrastructurePlanningProblem(EnergySystem): ...@@ -2768,80 +2768,57 @@ class InfrastructurePlanningProblem(EnergySystem):
# param_f_amp_y_irqk = {} # param_f_amp_y_irqk = {}
# output equations: C matrix coefficients # output equations: C matrix coefficients
param_c_eq_y_irnqk = { param_c_eq_y_irnqk = {
(converter_key, r, n, q, k): 0 # converter.dssm[k].C[r,n] (cvt_key, *rnqk): c_rnqk
for converter_key, converter in self.converters.items() for cvt_key, cvt in self.converters.items()
for r in range(converter.number_outputs) for rnqk, c_rnqk in cvt.c_rnqk.items()
for n in range(converter.number_states)
for (q, k) in set_QK
} }
# output equations: D matrix coefficients # output equations: D matrix coefficients
param_d_eq_y_irmqk = { param_d_eq_y_irmqk = {
(converter_key, r, m, q, k): 0 # converter.dssm[k].C[r,n] (cvt_key, *rmqk): d_rmqk
for converter_key, converter in self.converters.items() for cvt_key, cvt in self.converters.items()
for r in range(converter.number_outputs) for rmqk, d_rmqk in cvt.d_rmqk.items()
for m in range(converter.number_inputs)
for (q, k) in set_QK
} }
# output equations: constant term # output equations: constant term
param_e_eq_y_irqk = { param_e_eq_y_irqk = {
(converter_key, r, q, k): 0 # converter.dssm[k].C[r,n] (cvt_key, *rqk): e_rqk
for converter_key, converter in self.converters.items() for cvt_key, cvt in self.converters.items()
for r in range(converter.number_outputs) for rqk, e_rqk in cvt.e_rqk.items()
for (q, k) in set_QK
} }
# ********************************************************************* # *********************************************************************
# states # states
# state equations: A matrix coefficients # state equations: A matrix coefficients
param_a_eq_x_innqk = { param_a_eq_x_innqk = {
# (converter_key, r, n, k): (cvt_key, *nnqk): a_nnqk
# 0 #converter.dssm[k].C[r,n] for cvt_key, cvt in self.converters.items()
# for converter_key, converter in self.converters.items() for nnqk, a_nnqk in cvt.a_nnqk.items()
# for r in range(converter.number_outputs)
# for n in range(converter.number_states)
# for k in set_K
} }
# state equations: B matrix coefficients # state equations: B matrix coefficients
param_b_eq_x_inmqk = { param_b_eq_x_inmqk = {
# (converter_key, r, m, k): (cvt_key, *nmqk): b_nmqk
# 0 #converter.dssm[k].C[r,n] for cvt_key, cvt in self.converters.items()
# for converter_key, converter in self.converters.items() for nmqk, b_nmqk in cvt.b_nmqk.items()
# for r in range(converter.number_outputs)
# for m in range(converter.number_inputs)
# for k in set_K
} }
# state equations: constant term # state equations: constant term
param_e_eq_x_inqk = { param_e_eq_x_inqk = {
# (converter_key, r, k): (cvt_key, *nqk): e_nqk
# 0 #converter.dssm[k].C[r,n] for cvt_key, cvt in self.converters.items()
# for converter_key, converter in self.converters.items() for nqk, e_nqk in cvt.e_nqk.items()
# for r in range(converter.number_outputs)
# for k in set_K
} }
# initial states # initial states
param_x_inq0 = {} param_x_inq0 = {}
# upper bounds for states (default: none) # upper bounds for states (default: none)
param_x_ub_inqk = {} param_x_ub_inqk = {}
# lower bounds for states (default: none) # lower bounds for states (default: none)
param_x_lb_inqk = {} param_x_lb_inqk = {}
# maximum positive amplitude for inputs # maximum positive amplitude for inputs
......
...@@ -272,7 +272,6 @@ def method_full_converter(time_step_durations: list): ...@@ -272,7 +272,6 @@ def method_full_converter(time_step_durations: list):
# create a converter # create a converter
cvn1 = cvn.Converter( cvn1 = cvn.Converter(
"cvn1",
sys=ds, sys=ds,
initial_states=x0, initial_states=x0,
turn_key_cost=3, turn_key_cost=3,
...@@ -282,7 +281,9 @@ def method_full_converter(time_step_durations: list): ...@@ -282,7 +281,9 @@ def method_full_converter(time_step_durations: list):
) )
# get the dictionaries # get the dictionaries
(a_innk, b_inmk, c_irnk, d_irmk, e_x_ink, e_y_irk) = cvn1.matrix_dictionaries() (a_innk, b_inmk, c_irnk, d_irmk, e_x_ink, e_y_irk) = cvn1.matrix_dictionaries(
"cvn1"
)
# TODO: check the dicts # TODO: check the dicts
......
...@@ -16,6 +16,7 @@ from src.topupopt.problems.esipp.network import Arcs, Network ...@@ -16,6 +16,7 @@ from src.topupopt.problems.esipp.network import Arcs, Network
from src.topupopt.problems.esipp.resource import ResourcePrice from src.topupopt.problems.esipp.resource import ResourcePrice
from src.topupopt.problems.esipp.problem import simplify_peak_total_problem from src.topupopt.problems.esipp.problem import simplify_peak_total_problem
from src.topupopt.problems.esipp.problem import is_peak_total_problem from src.topupopt.problems.esipp.problem import is_peak_total_problem
from src.topupopt.problems.esipp.time import TimeFrame
# ***************************************************************************** # *****************************************************************************
# ***************************************************************************** # *****************************************************************************
...@@ -38,8 +39,10 @@ class TestESIPPProblem: ...@@ -38,8 +39,10 @@ class TestESIPPProblem:
perform_analysis: bool = False, perform_analysis: bool = False,
plot_results: bool = False, plot_results: bool = False,
print_solver_output: bool = False, print_solver_output: bool = False,
time_frame: TimeFrame = None,
irregular_time_intervals: bool = False, irregular_time_intervals: bool = False,
networks: dict = None, networks: dict = None,
converters: dict = None,
number_intraperiod_time_intervals: int = 4, number_intraperiod_time_intervals: int = 4,
static_losses_mode=None, static_losses_mode=None,
mandatory_arcs: list = None, mandatory_arcs: list = None,
...@@ -47,7 +50,7 @@ class TestESIPPProblem: ...@@ -47,7 +50,7 @@ class TestESIPPProblem:
arc_groups_dict: dict = None, arc_groups_dict: dict = None,
init_aux_sets: bool = False, init_aux_sets: bool = False,
discount_rates: dict = None, discount_rates: dict = None,
reporting_periods: dict = None, # reporting_periods: dict = None,
time_intervals: dict = None, time_intervals: dict = None,
assessment_weights: dict = None, assessment_weights: dict = None,
simplify_problem: bool = False, simplify_problem: bool = False,
...@@ -60,8 +63,11 @@ class TestESIPPProblem: ...@@ -60,8 +63,11 @@ class TestESIPPProblem:
if type(assessment_weights) != dict: if type(assessment_weights) != dict:
assessment_weights = {} # default assessment_weights = {} # default
if type(reporting_periods) != dict: # if type(reporting_periods) != dict:
reporting_periods = {0: (0, 1)} # reporting_periods = {0: (0, 1)}
if type(converters) != dict:
converters = {}
# time intervals # time intervals
...@@ -114,7 +120,7 @@ class TestESIPPProblem: ...@@ -114,7 +120,7 @@ class TestESIPPProblem:
ipp = InfrastructurePlanningProblem( ipp = InfrastructurePlanningProblem(
name="problem", name="problem",
discount_rates=discount_rates, discount_rates=discount_rates,
reporting_periods=reporting_periods, reporting_periods=time_frame.reporting_periods,
time_intervals=time_intervals, time_intervals=time_intervals,
time_weights=time_weights, time_weights=time_weights,
normalised_time_interval_duration=normalised_time_interval_duration, normalised_time_interval_duration=normalised_time_interval_duration,
...@@ -126,6 +132,11 @@ class TestESIPPProblem: ...@@ -126,6 +132,11 @@ class TestESIPPProblem:
for netkey, net in networks.items(): for netkey, net in networks.items():
ipp.add_network(network_key=netkey, network=net) ipp.add_network(network_key=netkey, network=net)
# add converters
for cvtkey, cvt in converters.items():
ipp.add_converter(converter_key=cvtkey, converter=cvt)
# define arcs as mandatory # define arcs as mandatory
if type(mandatory_arcs) == list: if type(mandatory_arcs) == list:
...@@ -274,8 +285,13 @@ class TestESIPPProblem: ...@@ -274,8 +285,13 @@ class TestESIPPProblem:
q = 0 q = 0
# time # time
number_intervals = 3 number_intervals = 3
# periods
number_periods = 2 tf = TimeFrame(
reporting_periods={q: [0, 1]},
reporting_period_durations={q: [365 * 24 * 3600, 365 * 24 * 3600]},
time_intervals={q: [0, 1, 2]},
time_interval_durations={q: [1, 1, 1]},
)
# 2 nodes: one import, one regular # 2 nodes: one import, one regular
mynet = Network() mynet = Network()
...@@ -285,9 +301,11 @@ class TestESIPPProblem: ...@@ -285,9 +301,11 @@ class TestESIPPProblem:
mynet.add_import_node( mynet.add_import_node(
node_key=node_IMP, node_key=node_IMP,
prices={ prices={
(q, p, k): ResourcePrice(prices=1.0, volumes=None) # (q, p, k): ResourcePrice(prices=1.0, volumes=None)
for p in range(number_periods) # for p in range(number_periods)
for k in range(number_intervals) # for k in range(number_intervals)
qpk: ResourcePrice(prices=1.0, volumes=None)
for qpk in tf.qpk()
}, },
) )
...@@ -305,8 +323,7 @@ class TestESIPPProblem: ...@@ -305,8 +323,7 @@ class TestESIPPProblem:
arc_tech_IA = Arcs( arc_tech_IA = Arcs(
name="any", name="any",
# efficiency=[0.5, 0.5, 0.5], efficiency={qk: 0.5 for qk in tf.qk()},
efficiency={(q, 0): 0.5, (q, 1): 0.5, (q, 2): 0.5},
efficiency_reverse=None, efficiency_reverse=None,
static_loss=None, static_loss=None,
capacity=[3], capacity=[3],
...@@ -338,6 +355,7 @@ class TestESIPPProblem: ...@@ -338,6 +355,7 @@ class TestESIPPProblem:
plot_results=False, # True, plot_results=False, # True,
print_solver_output=False, print_solver_output=False,
# irregular_time_intervals=irregular_time_intervals, # irregular_time_intervals=irregular_time_intervals,
time_frame=tf,
networks={"mynet": mynet}, networks={"mynet": mynet},
number_intraperiod_time_intervals=number_intervals, number_intraperiod_time_intervals=number_intervals,
static_losses_mode=True, # just to reach a line, static_losses_mode=True, # just to reach a line,
...@@ -406,8 +424,13 @@ class TestESIPPProblem: ...@@ -406,8 +424,13 @@ class TestESIPPProblem:
q = 0 q = 0
# time # time
number_intervals = 3 number_intervals = 3
# periods
number_periods = 2 tf = TimeFrame(
reporting_periods={q: [0, 1]},
reporting_period_durations={q: [365 * 24 * 3600, 365 * 24 * 3600]},
time_intervals={q: [0, 1, 2]},
time_interval_durations={q: [1, 1, 1]},
)
# 2 nodes: one import, one regular # 2 nodes: one import, one regular
mynet = Network() mynet = Network()
...@@ -418,9 +441,11 @@ class TestESIPPProblem: ...@@ -418,9 +441,11 @@ class TestESIPPProblem:
mynet.add_import_node( mynet.add_import_node(
node_key=node_IMP, node_key=node_IMP,
prices={ prices={
(q, p, k): ResourcePrice(prices=1.0, volumes=None) # (q, p, k): ResourcePrice(prices=1.0, volumes=None)
for p in range(number_periods) # for p in range(number_periods)
for k in range(number_intervals) # for k in range(number_intervals)
qpk: ResourcePrice(prices=1.0, volumes=None)
for qpk in tf.qpk()
}, },
) )
...@@ -439,8 +464,7 @@ class TestESIPPProblem: ...@@ -439,8 +464,7 @@ class TestESIPPProblem:
arc_tech_IA = Arcs( arc_tech_IA = Arcs(
name="any", name="any",
# efficiency=[0.5, 0.5, 0.5], efficiency={qk: 0.5 for qk in tf.qk()},
efficiency={(q, 0): 0.5, (q, 1): 0.5, (q, 2): 0.5},
efficiency_reverse=None, efficiency_reverse=None,
static_loss=None, static_loss=None,
capacity=[3], capacity=[3],
...@@ -472,6 +496,7 @@ class TestESIPPProblem: ...@@ -472,6 +496,7 @@ class TestESIPPProblem:
plot_results=False, # True, plot_results=False, # True,
print_solver_output=False, print_solver_output=False,
# irregular_time_intervals=irregular_time_intervals, # irregular_time_intervals=irregular_time_intervals,
time_frame=tf,
networks={"mynet": mynet}, networks={"mynet": mynet},
number_intraperiod_time_intervals=number_intervals, number_intraperiod_time_intervals=number_intervals,
static_losses_mode=True, # just to reach a line, static_losses_mode=True, # just to reach a line,
...@@ -574,6 +599,13 @@ class TestESIPPProblem: ...@@ -574,6 +599,13 @@ class TestESIPPProblem:
# periods # periods
number_periods = 1 number_periods = 1
tf = TimeFrame(
reporting_periods={q: [0]},
reporting_period_durations={q: [365 * 24 * 3600]},
time_intervals={q: [0]},
time_interval_durations={q: [1]},
)
# 2 nodes: one import, one regular # 2 nodes: one import, one regular
mynet = Network() mynet = Network()
...@@ -582,9 +614,11 @@ class TestESIPPProblem: ...@@ -582,9 +614,11 @@ class TestESIPPProblem:
mynet.add_import_node( mynet.add_import_node(
node_key=node_IMP, node_key=node_IMP,
prices={ prices={
(q, p, k): ResourcePrice(prices=[1.0, 2.0], volumes=[0.5, None]) # (q, p, k): ResourcePrice(prices=[1.0, 2.0], volumes=[0.5, None])
for p in range(number_periods) # for p in range(number_periods)
for k in range(number_intervals) # for k in range(number_intervals)
qpk: ResourcePrice(prices=[1.0, 2.0], volumes=[0.5, None])
for qpk in tf.qpk()
}, },
) )
...@@ -624,6 +658,7 @@ class TestESIPPProblem: ...@@ -624,6 +658,7 @@ class TestESIPPProblem:
plot_results=False, # True, plot_results=False, # True,
print_solver_output=False, print_solver_output=False,
# irregular_time_intervals=irregular_time_intervals, # irregular_time_intervals=irregular_time_intervals,
time_frame=tf,
networks={"mynet": mynet}, networks={"mynet": mynet},
number_intraperiod_time_intervals=number_intervals, number_intraperiod_time_intervals=number_intervals,
static_losses_mode=True, # just to reach a line, static_losses_mode=True, # just to reach a line,
...@@ -687,6 +722,13 @@ class TestESIPPProblem: ...@@ -687,6 +722,13 @@ class TestESIPPProblem:
# periods # periods
number_periods = 1 number_periods = 1
tf = TimeFrame(
reporting_periods={q: [0]},
reporting_period_durations={q: [365 * 24 * 3600]},
time_intervals={q: [0]},
time_interval_durations={q: [1]},
)
# 2 nodes: one export, one regular # 2 nodes: one export, one regular
mynet = Network() mynet = Network()
...@@ -737,6 +779,7 @@ class TestESIPPProblem: ...@@ -737,6 +779,7 @@ class TestESIPPProblem:
plot_results=False, # True, plot_results=False, # True,
print_solver_output=False, print_solver_output=False,
# irregular_time_intervals=irregular_time_intervals, # irregular_time_intervals=irregular_time_intervals,
time_frame=tf,
networks={"mynet": mynet}, networks={"mynet": mynet},
number_intraperiod_time_intervals=number_intervals, number_intraperiod_time_intervals=number_intervals,
static_losses_mode=True, # just to reach a line, static_losses_mode=True, # just to reach a line,
...@@ -800,6 +843,13 @@ class TestESIPPProblem: ...@@ -800,6 +843,13 @@ class TestESIPPProblem:
# periods # periods
number_periods = 1 number_periods = 1
tf = TimeFrame(
reporting_periods={q: [0]},
reporting_period_durations={q: [365 * 24 * 3600]},
time_intervals={q: [0]},
time_interval_durations={q: [1]},
)
# 3 nodes: one import, one export, one regular # 3 nodes: one import, one export, one regular
mynet = Network() mynet = Network()
...@@ -877,6 +927,7 @@ class TestESIPPProblem: ...@@ -877,6 +927,7 @@ class TestESIPPProblem:
plot_results=False, # True, plot_results=False, # True,
print_solver_output=False, print_solver_output=False,
# irregular_time_intervals=irregular_time_intervals, # irregular_time_intervals=irregular_time_intervals,
time_frame=tf,
networks={"mynet": mynet}, networks={"mynet": mynet},
number_intraperiod_time_intervals=number_intervals, number_intraperiod_time_intervals=number_intervals,
static_losses_mode=True, # just to reach a line, static_losses_mode=True, # just to reach a line,
...@@ -961,6 +1012,191 @@ class TestESIPPProblem: ...@@ -961,6 +1012,191 @@ class TestESIPPProblem:
# ************************************************************************* # *************************************************************************
# ************************************************************************* # *************************************************************************
def test_problem_converter_sink(self):
# scenario
q = 0
# time
number_intervals = 3
# periods
number_periods = 1
tf = TimeFrame(
reporting_periods={q: [0]},
reporting_period_durations={q: [365 * 24 * 3600]},
time_intervals={q: [0]},
time_interval_durations={q: [1]},
)
# 2 nodes: one import, one regular
mynet = Network()
# import node
node_IMP = generate_pseudo_unique_key(mynet.nodes())
mynet.add_import_node(
node_key=node_IMP,
prices={
(q, p, k): ResourcePrice(prices=1.0, volumes=None)
for p in range(number_periods)
for k in range(number_intervals)
},
)
# other nodes
node_A = generate_pseudo_unique_key(mynet.nodes())
mynet.add_source_sink_node(
node_key=node_A,
# base_flow=[0.5, 0.0, 1.0],
base_flow={(q, 0): 0.50, (q, 1): 0.00, (q, 2): 1.00},
)
# arc IA
arc_tech_IA = Arcs(
name="any",
# efficiency=[0.5, 0.5, 0.5],
efficiency={(q, 0): 0.5, (q, 1): 0.5, (q, 2): 0.5},
efficiency_reverse=None,
static_loss=None,
capacity=[3],
minimum_cost=[2],
specific_capacity_cost=1,
capacity_is_instantaneous=False,
validate=False,
)
mynet.add_directed_arc(node_key_a=node_IMP, node_key_b=node_A, arcs=arc_tech_IA)
# identify node types
mynet.identify_node_types()
# converters
# number of samples
time_step_durations = [1, 1, 1]
number_time_steps = len(time_step_durations)
# get the coefficients
import numpy as np
# a_innk
a_innk = {
("cvt1", 0, 0, 0): 0.95,
("cvt1", 0, 0, 1): 0.95,
("cvt1", 0, 0, 2): 0.95,
}
# b_inmk
b_inmk = {("cvt1", 0, 0, 0): 3, ("cvt1", 0, 0, 1): 3, ("cvt1", 0, 0, 2): 3}
# c_irnk
c_irnk = {}
# d_irmk
d_irmk = {}
# e_x_ink: depends on fixed signals
e_x_ink = {}
# e_y_irk: depends on fixed signals
e_y_irk = {}
# get the signals
inputs, states, outputs = get_two_node_model_signals(number_time_steps)
# create a dynamic system
ds = dynsys.DynamicSystem(
time_interval_durations=time_step_durations, A=a, B=b, C=c, D=d
)
# create a converter
cvn1 = cvn.Converter(
"cvn1",
sys=ds,
initial_states=x0,
turn_key_cost=3,
inputs=inputs,
states=states,
outputs=outputs,
)
# no sos, regular time intervals
ipp = self.build_solve_ipp(
# solver=solver,
solver_options={},
# use_sos_arcs=use_sos_arcs,
# arc_sos_weight_key=sos_weight_key,
# arc_use_real_variables_if_possible=use_real_variables_if_possible,
# use_sos_sense=use_sos_sense,
# sense_sos_weight_key=sense_sos_weight_key,
# sense_use_real_variables_if_possible=sense_use_real_variables_if_possible,
# sense_use_arc_interfaces=use_arc_interfaces,
perform_analysis=False,
plot_results=False, # True,
print_solver_output=False,
# irregular_time_intervals=irregular_time_intervals,
time_frame=tf,
networks={"mynet": mynet},
converters={"mycvt": cvt},
number_intraperiod_time_intervals=number_intervals,
static_losses_mode=True, # just to reach a line,
mandatory_arcs=[],
max_number_parallel_arcs={},
# init_aux_sets=init_aux_sets,
simplify_problem=False,
)
assert is_peak_total_problem(ipp)
assert ipp.results["Problem"][0]["Number of constraints"] == 24
assert ipp.results["Problem"][0]["Number of variables"] == 22
assert ipp.results["Problem"][0]["Number of nonzeros"] == 49
# *********************************************************************
# *********************************************************************
# validation
# the arc should be installed since it is required for feasibility
assert (
True
in ipp.networks["mynet"]
.edges[(node_IMP, node_A, 0)][Network.KEY_ARC_TECH]
.options_selected
)
# the flows should be 1.0, 0.0 and 2.0
assert math.isclose(
pyo.value(ipp.instance.var_v_glljqk[("mynet", node_IMP, node_A, 0, q, 0)]),
1.0,
abs_tol=1e-6,
)
assert math.isclose(
pyo.value(ipp.instance.var_v_glljqk[("mynet", node_IMP, node_A, 0, q, 1)]),
0.0,
abs_tol=1e-6,
)
assert math.isclose(
pyo.value(ipp.instance.var_v_glljqk[("mynet", node_IMP, node_A, 0, q, 2)]),
2.0,
abs_tol=1e-6,
)
# arc amplitude should be two
assert math.isclose(
pyo.value(ipp.instance.var_v_amp_gllj[("mynet", node_IMP, node_A, 0)]),
2.0,
abs_tol=0.01,
)
# capex should be four
assert math.isclose(pyo.value(ipp.instance.var_capex), 4.0, abs_tol=1e-3)
# sdncf should be -5.7
assert math.isclose(pyo.value(ipp.instance.var_sdncf_q[q]), -5.7, abs_tol=1e-3)
# the objective function should be -9.7
assert math.isclose(pyo.value(ipp.instance.obj_f), -9.7, abs_tol=1e-3)
# ***************************************************************************** # *****************************************************************************
# ***************************************************************************** # *****************************************************************************
# imports
# local, internal
from src.topupopt.problems.esipp.time import TimeFrame
# *****************************************************************************
# *****************************************************************************
class TestTimeFrame:
# *************************************************************************
# *************************************************************************
# test problem from table 2.1
def test_nonpositive_durations(self):
# negative reporting period durations
reporting_periods = {0: [0, 1, 2]}
reporting_period_durations = {0: [1, -1, 1]}
time_intervals = {0: [0, 1]}
time_interval_durations = {0: [1, 1]}
error_raised = True
try:
TimeFrame(
reporting_periods=reporting_periods,
reporting_period_durations=reporting_period_durations,
time_intervals=time_intervals,
time_interval_durations=time_interval_durations,
)
except ValueError:
error_raised = True
assert error_raised
# zero time interval durations
reporting_periods = {0: [0, 1, 2]}
reporting_period_durations = {0: [1, 1, 1]}
time_intervals = {0: [0, 1]}
time_interval_durations = {0: [1, 0]}
error_raised = True
try:
TimeFrame(
reporting_periods=reporting_periods,
reporting_period_durations=reporting_period_durations,
time_intervals=time_intervals,
time_interval_durations=time_interval_durations,
)
except ValueError:
error_raised = True
assert error_raised
# *************************************************************************
# *************************************************************************
# test problem from table 2.1
def test_table_21(self):
# summary:
# 1 assessment
# 3 reporting periods
# 2 time intervals
reporting_periods = {0: [0, 1, 2]}
reporting_period_durations = {
0: [365 * 24 * 3600, 365 * 24 * 3600, 365 * 24 * 3600]
}
time_intervals = {0: [0, 1]}
time_interval_durations = {0: [1, 1]}
tf = TimeFrame(
reporting_periods=reporting_periods,
reporting_period_durations=reporting_period_durations,
time_intervals=time_intervals,
time_interval_durations=time_interval_durations,
)
# qk: valid
assert tf.valid_qk(
{
(0, 0): 1,
(0, 1): 1,
}
)
# qk: not valid
assert not tf.valid_qk(
{
(0, 0): 1,
(0, 2): 1,
}
)
# qk: valid and complete
assert tf.complete_qk(
{
(0, 0): 1,
(0, 1): 1,
}
)
# qk: valid but not complete
assert not tf.complete_qk(
{
(0, 0): 1,
}
)
# qp: valid
assert tf.valid_qp(
{
(0, 0): 1,
}
)
# qp: not valid
assert not tf.valid_qp({(0, 0): 1, (0, 1): 1, (0, 3): 1})
# qp: valid and complete
assert tf.complete_qp({(0, 0): 1, (0, 1): 1, (0, 2): 1})
# qp: valid but not complete
assert not tf.complete_qp({(0, 0): 1, (0, 1): 1})
# qpk: valid
assert tf.valid_qpk(
{
(0, 0, 0): 1,
(0, 0, 1): 1,
}
)
# qpk: not valid
assert not tf.valid_qpk(
{
(0, 0, 0): 1,
(0, 0, 1): 1,
(0, 1, 0): 1,
(0, 1, 1): 1,
(0, 3, 0): 1,
(0, 3, 1): 1,
}
)
# qpk: valid and complete
assert tf.complete_qpk(
{
(0, 0, 0): 1,
(0, 0, 1): 1,
(0, 1, 0): 1,
(0, 1, 1): 1,
(0, 2, 0): 1,
(0, 2, 1): 1,
}
)
# qpk: valid but not complete
assert not tf.complete_qpk(
{(0, 0, 0): 1, (0, 0, 1): 1, (0, 1, 0): 1, (0, 1, 1): 1}
)
qk_dict = {qk: None for qk in tf.qk()}
qp_dict = {qp: None for qp in tf.qp()}
qpk_dict = {qpk: None for qpk in tf.qpk()}
assert tf.complete_qk(qk_dict)
assert tf.complete_qp(qp_dict)
assert tf.complete_qpk(qpk_dict)
# *************************************************************************
# *************************************************************************
# test problem from table 2.2
def test_table_22(self):
# summary:
# 1 assessment
# 3 reporting periods
# 2 time intervals
reporting_periods = {0: [0], 1: [1, 2]}
reporting_period_durations = {
0: [365 * 24 * 3600],
1: [365 * 24 * 3600, 365 * 24 * 3600],
}
time_intervals = {0: [0, 1], 1: [0, 1]}
time_interval_durations = {0: [1, 1], 1: [1, 1]}
tf = TimeFrame(
reporting_periods=reporting_periods,
reporting_period_durations=reporting_period_durations,
time_intervals=time_intervals,
time_interval_durations=time_interval_durations,
)
# qk: valid
assert tf.valid_qk(
{
(0, 0): 1,
(0, 1): 1,
(1, 0): 1,
(1, 1): 1,
}
)
# qk: not valid
assert not tf.valid_qk(
{
(0, 0): 1,
(0, 1): 1,
(1, 0): 1,
(1, 1): 1,
(1, 2): 1,
}
)
# qk: valid and complete
assert tf.complete_qk(
{
(0, 0): 1,
(0, 1): 1,
(1, 0): 1,
(1, 1): 1,
}
)
# qk: valid but not complete
assert not tf.complete_qk(
{
(0, 0): 1,
# (0,1): 1,
(1, 0): 1,
(1, 1): 1,
}
)
# qp: valid
assert tf.valid_qp(
{
(0, 0): 1,
(1, 1): 1,
(1, 2): 1,
}
)
# qp: not valid
assert not tf.valid_qp(
{
(0, 0): 1,
(1, 1): 1,
(1, 3): 1,
}
)
# qp: valid and complete
assert tf.complete_qp(
{
(0, 0): 1,
(1, 1): 1,
(1, 2): 1,
}
)
# qp: valid but not complete
assert not tf.complete_qp({(0, 0): 1, (1, 1): 1})
# qpk: valid
assert tf.valid_qpk(
{
(0, 0, 0): 1,
(1, 1, 1): 1,
}
)
# qpk: not valid
assert not tf.valid_qpk(
{
(0, 0, 0): 1,
(0, 0, 1): 1,
(1, 1, 0): 1,
(1, 1, 1): 1,
(1, 3, 0): 1,
(1, 3, 1): 1,
}
)
# qpk: valid and complete
assert tf.complete_qpk(
{
(0, 0, 0): 1,
(0, 0, 1): 1,
(1, 1, 0): 1,
(1, 1, 1): 1,
(1, 2, 0): 1,
(1, 2, 1): 1,
}
)
# qpk: valid but not complete
assert not tf.complete_qpk(
{(0, 0, 0): 1, (0, 0, 1): 1, (1, 1, 0): 1, (1, 1, 1): 1}
)
qk_dict = {qk: None for qk in tf.qk()}
qp_dict = {qp: None for qp in tf.qp()}
qpk_dict = {qpk: None for qpk in tf.qpk()}
assert tf.complete_qk(qk_dict)
assert tf.complete_qp(qp_dict)
assert tf.complete_qpk(qpk_dict)
# *************************************************************************
# *************************************************************************
# TODO: table 2.3
def test_table_23(self):
# Problem with three reporting periods relying on two assessments
# with two and three intervals: one assessment for the first two periods with two
# intervals; and another for last period with three intervals.
reporting_periods = {0: [0, 1], 1: [2]}
reporting_period_durations = {
1: [365 * 24 * 3600],
0: [365 * 24 * 3600, 365 * 24 * 3600],
}
time_intervals = {0: [0, 1], 1: [0, 1, 2]}
time_interval_durations = {0: [1, 1], 1: [1, 1, 1]}
tf = TimeFrame(
reporting_periods=reporting_periods,
reporting_period_durations=reporting_period_durations,
time_intervals=time_intervals,
time_interval_durations=time_interval_durations,
)
# qk: valid
assert tf.valid_qk(
{
(0, 0): 1,
(0, 1): 1,
(1, 0): 1,
(1, 1): 1,
(1, 2): 1,
}
)
# qk: not valid
assert not tf.valid_qk(
{
(0, 0): 1,
(0, 1): 1,
(1, 0): 1,
(1, 1): 1,
(1, 2): 1,
(1, 3): 1,
}
)
# qk: valid and complete
assert tf.complete_qk(
{
(0, 0): 1,
(0, 1): 1,
(1, 0): 1,
(1, 1): 1,
(1, 2): 1,
}
)
# qk: valid but not complete
assert not tf.complete_qk(
{
(0, 0): 1,
# (0,1): 1,
(1, 0): 1,
(1, 1): 1,
}
)
# qp: valid
assert tf.valid_qp(
{
(0, 0): 1,
(0, 1): 1,
(1, 2): 1,
}
)
# qp: not valid
assert not tf.valid_qp(
{
(0, 0): 1,
(0, 1): 1,
(1, 3): 1,
}
)
# qp: valid and complete
assert tf.complete_qp(
{
(0, 0): 1,
(0, 1): 1,
(1, 2): 1,
}
)
# qp: valid but not complete
assert not tf.complete_qp({(0, 0): 1, (1, 1): 1})
# qpk: valid
assert tf.valid_qpk(
{
(0, 0, 0): 1,
(0, 1, 1): 1,
(1, 2, 1): 1,
}
)
# qpk: not valid
assert not tf.valid_qpk(
{
(0, 0, 0): 1,
(0, 0, 1): 1,
(1, 1, 0): 1,
(1, 1, 1): 1,
(1, 3, 0): 1,
(1, 3, 1): 1,
}
)
# qpk: valid and complete
assert tf.complete_qpk(
{
(0, 0, 0): 1,
(0, 0, 1): 1,
(0, 1, 0): 1,
(0, 1, 1): 1,
(1, 2, 0): 1,
(1, 2, 1): 1,
(1, 2, 2): 1,
}
)
# qpk: valid but not complete
assert not tf.complete_qpk(
{
(0, 0, 0): 1,
(0, 0, 1): 1,
(0, 1, 0): 1,
(0, 1, 1): 1,
(1, 2, 0): 1,
(1, 2, 1): 1,
}
)
qk_dict = {qk: None for qk in tf.qk()}
qp_dict = {qp: None for qp in tf.qp()}
qpk_dict = {qpk: None for qpk in tf.qpk()}
assert tf.complete_qk(qk_dict)
assert tf.complete_qp(qp_dict)
assert tf.complete_qpk(qpk_dict)
# *************************************************************************
# *************************************************************************
# TODO: table 2.4
def test_table_24(self):
pass
# *************************************************************************
# *************************************************************************
# TODO: table 2.5
def test_table_25(self):
pass
# *************************************************************************
# *************************************************************************
# TODO: table 2.6
def test_table_26(self):
pass
# *************************************************************************
# *************************************************************************
# *****************************************************************************
# *****************************************************************************
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment