def update_device_data(self, device_type=None, device_id=None): self._device_type = device_type if device_type is not None else self._device_type or 'not_specified' self._device_id = device_id if device_id is not None else self._device_id if self._device_type in self._device_type_id_struct: _id_set = self._device_type_id_struct[self._device_type].id_set _id_list = self._device_type_id_struct[self._device_type].id_list if self.device_id in _id_set: raise ValueError( "Agent with type:'{}' and device_id:'{}' already exists". format(self._device_type, self.device_id)) elif self.device_id is None: self._device_id = (_id_list[-1] + 1) if _id_list else 1 _id_set.add(self._device_id) bisect.insort(_id_list, self._device_id) else: if self.device_id is None: self._device_id = 1 self._device_type_id_struct[self._device_type] = StructDict( id_set=set(), id_list=[]) self._device_type_id_struct[self._device_type].id_set.add( self._device_id) self._device_type_id_struct[self._device_type].id_list.append( self._device_id)
def sim_step_k(self, k, x_k_struct=None, omega_k_struct=None, mld_numeric_k_struct=None, solver=None, step_state=True): x_k_struct = x_k_struct if x_k_struct is not None else dict.fromkeys( self.controllers, None) omega_k_struct = omega_k_struct if omega_k_struct is not None else ( self.get_omega_tilde_k_act(k=k, N_tilde_or_struct=1)) mld_numeric_k_struct = mld_numeric_k_struct if mld_numeric_k_struct is not None else ( dict.fromkeys(self.controllers, None)) sims_step_k_struct = StructDict() for cname, controller in self._controllers.items(): sims_step_k_struct[cname] = controller.sim_step_k( k=k, x_k=x_k_struct[cname], omega_k=omega_k_struct[cname], mld_numeric_k=mld_numeric_k_struct[cname], solver=solver, step_state=step_state) return sims_step_k_struct
def get_expr_shapes(*exprs, get_max_dim=False): if not exprs: return None if isinstance(exprs[0], dict): shapes = StructDict({ expr_id: get_expr_shape(expr) for expr_id, expr in exprs[0].items() }) else: shapes = [get_expr_shape(expr) for expr in exprs] if get_max_dim: shapes = list(shapes.values()) if isinstance(shapes, dict) else shapes return tuple(np.maximum.reduce(shapes)) else: return shapes
def gen_optimization_vars(self, N_p=None, N_tilde=None, mld_numeric_k: MldModel = None, mld_numeric_tilde=None, mld_info_k: MldInfo = None): slack_names = mld_info_k._slack_var_names # extract variable matrix_types from mld mld_infos if mld_numeric_tilde: var_types_N_tilde = { var_name: ( np.vstack( [mld_numeric_tilde[k].mld_info.get_var_type(var_name) for k in range(N_tilde)] ) if mld_info_k.get_var_dim(var_name) else ( np.empty((0, mld_info_k.get_var_dim(var_name) * N_tilde), dtype=np.str)) ) for var_name in self._controllable_vars } else: var_types_N_tilde = { var_name: ( np.tile(mld_info_k.get_var_type(var_name), (N_tilde, 1))) for var_name in self._controllable_vars } def to_bin_index(type_mat): return (list(map(tuple, np.argwhere(type_mat == 'b').tolist()))) # generate individual variable tilde mats opt_var_N_tilde = { var_name: ( cvx.Variable(var_type_mat.shape, boolean=to_bin_index(var_type_mat), name="".join([var_name.capitalize(), '_var_N_tilde']), nonneg=(var_name in slack_names or None)) if var_type_mat.size else np.empty((0, 1)) ) for var_name, var_type_mat in var_types_N_tilde.items() } variables = StructDict({var_name: EvoVariableStruct() for var_name in self._optimization_vars}) for var_name in self._controllable_vars: self._set_var_using_var_N_tilde(variable=variables[var_name], var_dim=mld_info_k.get_var_dim(var_name), var_N_tilde=opt_var_N_tilde[var_name], N_p=N_p, N_tilde=N_tilde) # add combined input variable tilde mat opt_var_mats_N_tilde = [variables[var_name].var_mat_N_tilde for var_name in self._controllable_vars if mld_info_k.get_var_dim(var_name)] v_var_mat_N_tilde = cvx.vstack(opt_var_mats_N_tilde) if opt_var_mats_N_tilde else np.empty((0, N_tilde)) self._set_var_using_var_mat_N_tilde(variable=variables['v'], var_dim=mld_info_k.nv, var_mat_N_tilde=v_var_mat_N_tilde, N_p=N_p, N_tilde=N_tilde) return variables
def get_actual_omega_dewh_profiles(actual_scenarios=None, N_h=1, size=1): if isinstance(actual_scenarios, pd.DataFrame): actual_scenarios = actual_scenarios.values _, num_scen = actual_scenarios.shape omega_dewh_profiles = StructDict() for i in range(1, N_h + 1): randstate = np.random.RandomState(seed=np.int32(i**2)) profile = actual_scenarios[:, randstate. choice(num_scen, size=size, replace=False)] omega_dewh_profiles[i] = profile.reshape(-1, 1, order='F') return omega_dewh_profiles
def _set_vars_k_neg1(self, variables_k_neg1_struct=None, N_p=None, N_tilde=None, mld_numeric_k: MldModel = None, mld_numeric_tilde=None, mld_info_k: MldInfo = None): variables_k_neg1_struct = variables_k_neg1_struct or self.VariablesStruct_k_neg1.fromkeys(self) variables_k_neg1_struct_update = StructDict() for var_name, variable in self.items(): var_k_neg1_update = variables_k_neg1_struct.get(var_name,None) var_update = ( self._process_parameter_update(name=var_name + "_k_neg1", parameter=variable.var_k_neg1, required_shape=(variable.var_dim, 1), new_value=var_k_neg1_update)) if var_update is not None: variables_k_neg1_struct_update[var_name] = var_update return variables_k_neg1_struct_update if variables_k_neg1_struct_update else None
def gen_state_output_vars(self, variables=None, x_k=None, omega_tilde_k=None, N_p=None, N_tilde=None, mld_numeric_k: MldModel = None, mld_numeric_tilde=None, mld_info_k: MldInfo = None): state_output_vars = StructDict({var_name: EvoVariableStruct() for var_name in self._state_output_vars}) x_k = x_k if x_k is not None else self.x_k omega_tilde_k = omega_tilde_k if omega_tilde_k is not None else self.omega_tilde_k variables = variables or self if mld_info_k.nx: state_output_vars.x.var_N_tilde = ( matmul(self.mld_evo_matrices.state_input['Phi_x_N_tilde'], x_k) + matmul(self.mld_evo_matrices.state_input['Gamma_v_N_tilde'], variables.v.var_N_tilde) + matmul(self.mld_evo_matrices.state_input['Gamma_omega_N_tilde'], omega_tilde_k) + self.mld_evo_matrices.state_input['Gamma_5_N_tilde'] ) else: state_output_vars.x.var_N_tilde = np.empty((0, 1)) if mld_info_k.ny: state_output_vars.y.var_N_tilde = ( matmul(self.mld_evo_matrices.output['L_x_N_tilde'], x_k) + matmul(self.mld_evo_matrices.output['L_v_N_tilde'], variables['v']['var_N_tilde']) + matmul(self.mld_evo_matrices.output['L_omega_N_tilde'], omega_tilde_k) + self.mld_evo_matrices.output['L_5_N_tilde'] ) else: state_output_vars.y.var_N_tilde = np.empty((0, 1)) for var_name in self._state_output_vars: var_N_tilde = state_output_vars[var_name].var_N_tilde self._set_var_using_var_N_tilde(variable=state_output_vars[var_name], var_dim=mld_info_k.get_var_dim(var_name), var_N_tilde=var_N_tilde, N_p=N_p, N_tilde=N_tilde) return state_output_vars
def sim_mpc(N_p=1, sim_steps=1, soft_top_mult=10.0, soft_bot_mult=1.0, num_scenarios=20, N_sb_reduced=8, controllers=None, save_text_postfix=""): N_tilde = N_p + 1 controllers = controllers or {} deterministic_struct = { cname: controller.is_deterministic for cname, controller in controllers.items() } for dev in itertools.chain([grid], grid.devices): dev.delete_all_controllers() for cname, controller in controllers.items(): for dev in itertools.chain([grid], grid.devices): if isinstance(dev, DewhAgentMpc): if issubclass(controller.controller_type, MpcController): dev.add_controller(cname, controller.controller_type, N_p=N_p) else: dev.add_controller(cname, controller.controller_type, N_p=0, N_tilde=1) else: if issubclass(controller.controller_type, MpcController): dev.add_controller(cname, controller.controller_type, N_p=N_p) else: dev.add_controller(cname, NoController, N_p=0, N_tilde=1) for dev in grid.devices: if isinstance(dev, DewhAgentMpc): dev.x_k = get_dewh_random_initial_state(dev.device_id) total_cost_struct = StructDict({cname: 0 for cname in controllers}) grid.build_grid(k=0, deterministic_or_struct=deterministic_struct) for k in range(0, sim_steps): st = time.time() prices_tilde = grid.get_price_tilde_k(k=k) for cname, controller in controllers.items(): if issubclass(controller.controller_type, MpcController): for dev in itertools.chain([grid], grid.devices): if isinstance(dev, DewhAgentMpc) and issubclass( controller.controller_type, MpcController): if cname.startswith('mpc'): price_vec = prices_tilde[cname] max_cost = np.sum( price_vec) * dewh_param_struct.P_h_Nom q_mu_top = max_cost * soft_top_mult q_mu_bot = max_cost * soft_bot_mult dev.set_device_objective_atoms( controller_name=cname, q_mu=np.hstack([q_mu_top, q_mu_bot]).ravel(order='c')) if cname.startswith('mpc_sb'): omega_tilde_scenarios = dev.get_omega_tilde_scenario( k, N_tilde=N_tilde, num_scenarios=num_scenarios) if cname == 'mpc_sb_reduced': dev.controllers[cname].set_constraints( other_constraints=[ dev.controllers[cname]. gen_evo_constraints( N_tilde=N_sb_reduced, omega_scenarios_k= omega_tilde_scenarios) ]) elif cname == 'mpc_sb_full': dev.controllers[cname].set_constraints( other_constraints=[ dev.controllers[cname]. gen_evo_constraints( omega_scenarios_k= omega_tilde_scenarios) ]) elif cname == 'mpc_minmax': omega_min, omega_max = get_min_max_dhw_scenario( k=k, N_tilde=N_tilde, min_dhw_day=min_dhw_day, max_dhw_day=max_dhw_day) min_cons = dev.controllers[ cname].gen_evo_constraints( N_tilde=N_tilde, omega_tilde_k=omega_min) max_cons = dev.controllers[ cname].gen_evo_constraints( N_tilde=N_tilde, omega_tilde_k=omega_max) dev.controllers[cname].set_constraints( other_constraints=[min_cons, max_cons]) elif isinstance(dev, GridAgentMpc) and issubclass( controller.controller_type, MpcController): dev.controllers[cname].set_std_obj_atoms( q_z=prices_tilde[cname]) grid.build_grid(k=k, deterministic_or_struct=deterministic_struct) grid.solve_grid_mpc(k=k, verbose=False, TimeLimit=20, MIPGap=1e-2) print(f'k={k}, N_p={N_p}') print(f"Time to solve including data transfer:{time.time() - st}") l_sim = grid.sim_step_k(k=k) print(f"Total Looptime:{time.time() - st}") solve_times_struct = StructDict() for cname in controllers: total_cost_struct[cname] += grid.sim_logs[cname].get(k).cost solve_times_struct[cname] = ( grid.sim_logs[cname].get(k).time_in_solver, grid.sim_logs[cname].get(k).time_solve_overall) print('Total_cost\n', total_cost_struct) print('Solve_times\n', solve_times_struct) print('\n') df_sim: pd.DataFrame = grid.grid_sim_dataframe df_sim.index = pd.date_range(start=time_0, periods=sim_steps, freq='15min') if save_text_postfix and not save_text_postfix.startswith('_'): save_text_postfix = '_' + save_text_postfix T_max = int(dewh_param_struct_adjusted.T_h_max) T_min = int(dewh_param_struct_adjusted.T_h_min) save_dir = fr'{BASE_FILE}/sim_out' if not os.path.exists(save_dir): os.makedirs(save_dir) save_path = os.path.realpath( fr'{BASE_FILE}/sim_out/sim_Np_{N_p}_st_{int(soft_top_mult)}_sb_{int(soft_bot_mult)}_Ns_{num_scenarios}_' fr'Nsr_{N_sb_reduced}_Nh_{N_h}_Tmax_{T_max}_Tmin_{T_min}{save_text_postfix}.sim_out' ) df_sim.to_pickle(save_path) return StructDict(df_sim=df_sim, locals_vars=locals())
resdAgent.set_omega_profile(omega_resd_profile) grid.add_device(resdAgent) ################################ print(f"Time to create dewh's':{time.time() - st}") ControllerClass = namedtuple('ControllerClass', ['controller_type', 'is_deterministic']) controllers_choices = StructDict({ 'mpc_pb': ControllerClass(MpcController, True), 'mpc_ce': ControllerClass(MpcController, False), 'mpc_sb_reduced': ControllerClass(MpcController, False), 'mpc_sb_full': ControllerClass(MpcController, False), 'mpc_minmax': ControllerClass(MpcController, False), 'thermo': ControllerClass(DewhTheromstatController, False) }) def sim_mpc(N_p=1, sim_steps=1, soft_top_mult=10.0, soft_bot_mult=1.0, num_scenarios=20, N_sb_reduced=8, controllers=None,
class Agent: _device_type_id_struct = StructDict() def __init__(self, device_type=None, device_id=None, sim_model: MldSystemModel = ParNotSet, control_model: MldSystemModel = ParNotSet): self._device_type = None self._device_id = None self._sim_model = None self._control_model = None self.update_device_data(device_type=device_type, device_id=device_id) self.update_models(sim_model=sim_model, control_model=control_model) # todo Still needs work @classmethod def delete_all_devices(cls): cls._device_type_id_struct.clear() def update_device_data(self, device_type=None, device_id=None): self._device_type = device_type if device_type is not None else self._device_type or 'not_specified' self._device_id = device_id if device_id is not None else self._device_id if self._device_type in self._device_type_id_struct: _id_set = self._device_type_id_struct[self._device_type].id_set _id_list = self._device_type_id_struct[self._device_type].id_list if self.device_id in _id_set: raise ValueError( "Agent with type:'{}' and device_id:'{}' already exists". format(self._device_type, self.device_id)) elif self.device_id is None: self._device_id = (_id_list[-1] + 1) if _id_list else 1 _id_set.add(self._device_id) bisect.insort(_id_list, self._device_id) else: if self.device_id is None: self._device_id = 1 self._device_type_id_struct[self._device_type] = StructDict( id_set=set(), id_list=[]) self._device_type_id_struct[self._device_type].id_set.add( self._device_id) self._device_type_id_struct[self._device_type].id_list.append( self._device_id) def update_models(self, sim_model: MldSystemModel = ParNotSet, control_model: MldSystemModel = ParNotSet): if is_all_None(self._sim_model, self._control_model, sim_model, control_model): self._sim_model = MldSystemModel() self._control_model = None else: self._sim_model = sim_model if sim_model is not ParNotSet else self._sim_model or MldSystemModel( ) self._control_model = control_model if control_model is not ParNotSet else self._control_model or None # todo think about cleanup def __del__(self): # print("deleting") for col in self._device_type_id_struct[self._device_type].values(): try: col.remove(self._device_id) except Exception: pass @property def device_type(self): return self._device_type @property def device_id(self): return self._device_id @property def sim_model(self) -> MldSystemModel: return self._sim_model @property def control_model(self) -> MldSystemModel: return self._control_model if self._control_model is not None else self._sim_model @property def mld_numeric(self) -> MldModel: return self._sim_model._mld_numeric @property def mld_info(self) -> MldInfo: return self.mld_numeric.mld_info @property def mld_numeric_tilde(self): return None @_recursive_repr() def __repr__(self): repr_dict = OrderedDict(device_type=self.device_type, device_id=self.device_id, sim_model=self.sim_model, control_model=self.control_model) return struct_repr(repr_dict, type_name=self.__class__.__name__)
def get_variables_k_act(self, k): return StructDict({ controller_name: controller.sim_log.get(k) for controller_name, controller in self._controllers })
def sim_logs(self) -> MutableMapping[AnyStr, MldSimLog]: return StructDict({ controller_name: controller.sim_log for controller_name, controller in self._controllers.items() })
import numpy as np __all__ = ['dewh_param_struct', 'grid_param_struct'] control_ts = TimeDelta(minutes=15) #150L dewh_param_struct = StructDict( C_w=4.1816 * 10 ** 3, # J/kg/K A_h=2.35, # m^2 U_h=0.88, # W/m^2/K m_h=150.0, # kg T_w=15.0, # C T_inf=25.0 , # C P_h_Nom=3000.0, # W (Joules/s) T_h_min=50.0, # C T_h_max=65.0, # C T_h_Nom=45.0, # C T_h_max_sub_T_h_on = 12, T_h_max_sub_T_h_off = 4, T_h = 45.0, #C D_h=0.0, # kg/s control_ts=control_ts, ts=control_ts.seconds, ) # # #250L # dewh_param_struct = StructDict( # C_w=4.1816 * 10 ** 3, # J/kg/K # A_h=3.22,#2.35, # m^2 # U_h=0.88, # W/m^2/K # m_h=250,#150.0, # kg