Coverage for examples/OneRoom_CIA/main_cia_flex.py: 98%

96 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2026-03-26 09:43 +0000

1import matplotlib.pyplot as plt 

2from matplotlib.ticker import FormatStrFormatter 

3from agentlib.utils.multi_agent_system import LocalMASAgency 

4import numpy as np 

5import agentlib_mpc.utils.plotting.basic as mpcplot 

6from agentlib_mpc.utils.analysis import mpc_at_time_step 

7from agentlib_flexquant.generate_flex_agents import FlexAgentGenerator 

8import logging 

9from agentlib_flexquant.utils.interactive import Dashboard 

10 

11# Set the log-level 

12logging.basicConfig(level=logging.WARN) 

13until = 12000 

14 

15time_of_activation = 9000 

16 

17ENV_CONFIG = {"rt": False, "factor": 0.01, "t_sample": 10} 

18 

19 

20def run_example(until=until, with_plots=False, with_dashboard=False): 

21 """ 

22 Runs with the CIA algorithm for solving MINLPs. AgentLib-FlexQuant implements a 

23 custom optimization backend, that also enables rounding instead of CIA for solving 

24 these problems, which sometimes shows better performance. To toggle this option set 

25 use_rounding in the config. 

26 

27 mpc_config:  

28 Sets inputs, outputs, states, and parameters for the MPC agent.  

29 It points to the path of the MPC problem definition file (simple_building.py) and defines the MPC parameters. 

30 sim_config:  

31 Sets inputs, outputs, and states for the simulation agent.  

32 It points to the path of the FMU file and defines the simulation parameters. 

33 predictor_config: 

34 Sets parameters for the predictor agent and points to the path of the predictor formulation file (predictor.py). 

35 flex_config: 

36 Sets various options for the flexibility quantification framework:  

37 - characteristic times for the indicator module (e.g. market time, preparation time, flex event duration) 

38 - options for the cost calculation 

39 - whether to use a constant electricity price or to input a time series sent by the predictor agent 

40 - whether to use a constant feed-in tariff or to input a time series sent by the predictor agent 

41 - if no feed-in is required (e.g. for a house without electricity generation), use a constant feed-in tariff with value 0 

42 - option to correct the cost for stored energy at the end of the prediction horizon  

43 - option to include a market config (points to a market config file)  

44 - options for the flexibility agent generator:  

45 - power variable of the baseline agent  

46 - cost functions of PF-MPC and NF-MPC agents, including custom parameters and variables for the shadow MPCs  

47 - general options such as results paths  

48 """ 

49 results = [] 

50 mpc_config = "mpc_and_sim/simple_cia_mpc.json" 

51 sim_config = "mpc_and_sim/simple_cia_sim.json" 

52 predictor_config = "predictor/predictor_config.json" 

53 flex_config = "flex_configs/flexibility_agent_config.json" 

54 agent_configs = [sim_config, predictor_config] 

55 

56 config_list = FlexAgentGenerator( 

57 flex_config=flex_config, mpc_agent_config=mpc_config 

58 ).generate_flex_agents() 

59 agent_configs.extend(config_list) 

60 

61 mas = LocalMASAgency( 

62 agent_configs=agent_configs, env=ENV_CONFIG, variable_logging=False 

63 ) 

64 

65 mas.run(until=until) 

66 results = mas.get_results(cleanup=False) 

67 

68 if with_plots: 

69 # disturbances 

70 fig, axs = mpcplot.make_fig(style=mpcplot.Style(use_tex=False), rows=1) 

71 ax1 = axs[0] 

72 # load 

73 ax1.set_ylabel("$dot{Q}_{Room}$ in W") 

74 results["SimAgent"]["room"]["load"].dropna().plot(ax=ax1, drawstyle="steps-post") 

75 x_ticks = np.arange(0, 3600 * 6 + 1, 3600) 

76 x_tick_labels = [int(tick / 3600) for tick in x_ticks] 

77 ax1.set_xticks(x_ticks) 

78 ax1.set_xticklabels(x_tick_labels) 

79 ax1.set_xlabel("Time in hours") 

80 for ax in axs: 

81 mpcplot.make_grid(ax) 

82 ax.set_xlim(0, 3600 * 6) 

83 

84 # room temp 

85 fig, axs = mpcplot.make_fig(style=mpcplot.Style(use_tex=False), rows=1) 

86 ax1 = axs[0] 

87 # T out 

88 ax1.set_ylabel("$T_{room}$ in K") 

89 results["SimAgent"]["room"]["T_upper"].plot(ax=ax1, color="0.5") 

90 results["SimAgent"]["room"]["T_out"].plot(ax=ax1, 

91 color=mpcplot.EBCColors.dark_grey) 

92 mpc_at_time_step( 

93 data=results["Baseline"]["Baseline"], time_step=time_of_activation, 

94 variable="T" 

95 ).plot(ax=ax1, label="base", linestyle="--", color=mpcplot.EBCColors.dark_grey) 

96 mpc_at_time_step( 

97 data=results["NegFlexMPC"]["NegFlexMPC"], time_step=time_of_activation, 

98 variable="T" 

99 ).plot(ax=ax1, label="neg", linestyle="--", color=mpcplot.EBCColors.red) 

100 mpc_at_time_step( 

101 data=results["PosFlexMPC"]["PosFlexMPC"], time_step=time_of_activation, 

102 variable="T" 

103 ).plot(ax=ax1, label="pos", linestyle="--", color=mpcplot.EBCColors.blue) 

104 

105 ax1.legend() 

106 ax1.vlines(time_of_activation, ymin=0, ymax=500, colors="black") 

107 ax1.vlines(time_of_activation + 300, ymin=0, ymax=500, colors="black") 

108 ax1.vlines(time_of_activation + 600, ymin=0, ymax=500, colors="black") 

109 ax1.vlines(time_of_activation + 3000, ymin=0, ymax=500, colors="black") 

110 

111 ax1.set_ylim(289, 299) 

112 x_ticks = np.arange(0, 3600 * 6 + 1, 3600) 

113 x_tick_labels = [int(tick / 3600) for tick in x_ticks] 

114 ax1.set_xticks(x_ticks) 

115 ax1.set_xticklabels(x_tick_labels) 

116 ax1.set_xlabel("Time in hours") 

117 for ax in axs: 

118 mpcplot.make_grid(ax) 

119 ax.set_xlim(0, 3600 * 6) 

120 

121 # predictions 

122 fig, axs = mpcplot.make_fig(style=mpcplot.Style(use_tex=False), rows=1) 

123 ax1 = axs[0] 

124 # P_el 

125 ax1.set_ylabel("$P_{el}$ in W") 

126 results["SimAgent"]["room"]["P_el"].plot(ax=ax1, 

127 color=mpcplot.EBCColors.dark_grey) 

128 mpc_at_time_step( 

129 data=results["NegFlexMPC"]["NegFlexMPC"], time_step=time_of_activation, 

130 variable="P_el" 

131 ).ffill().plot( 

132 ax=ax1, 

133 drawstyle="steps-post", 

134 label="neg", 

135 linestyle="--", 

136 color=mpcplot.EBCColors.red, 

137 ) 

138 mpc_at_time_step( 

139 data=results["PosFlexMPC"]["PosFlexMPC"], time_step=time_of_activation, 

140 variable="P_el" 

141 ).ffill().plot( 

142 ax=ax1, 

143 drawstyle="steps-post", 

144 label="pos", 

145 linestyle="--", 

146 color=mpcplot.EBCColors.blue, 

147 ) 

148 mpc_at_time_step( 

149 data=results["Baseline"]["Baseline"], time_step=time_of_activation, 

150 variable="P_el" 

151 ).ffill().plot( 

152 ax=ax1, 

153 drawstyle="steps-post", 

154 label="base", 

155 linestyle="--", 

156 color=mpcplot.EBCColors.dark_grey, 

157 ) 

158 ax1.legend() 

159 ax1.vlines(time_of_activation, ymin=0, ymax=500, colors="black") 

160 ax1.vlines(time_of_activation + 300, ymin=0, ymax=500, colors="black") 

161 ax1.vlines(time_of_activation + 600, ymin=0, ymax=500, colors="black") 

162 ax1.vlines(time_of_activation + 3000, ymin=0, ymax=500, colors="black") 

163 

164 # flexibility 

165 # get only the first prediction time of each time step 

166 ind_res = results["FlexibilityIndicator"]["FlexibilityIndicator"] 

167 energy_flex_neg = ind_res.xs("negative_energy_flex", axis=1).droplevel( 

168 1).dropna() 

169 energy_flex_pos = ind_res.xs("positive_energy_flex", axis=1).droplevel( 

170 1).dropna() 

171 fig, axs = mpcplot.make_fig(style=mpcplot.Style(use_tex=False), rows=1) 

172 ax1 = axs[0] 

173 ax1.set_ylabel("$epsilon$ in kWh") 

174 energy_flex_neg.plot(ax=ax1, label="neg", color=mpcplot.EBCColors.red) 

175 energy_flex_pos.plot(ax=ax1, label="pos", color=mpcplot.EBCColors.blue) 

176 ax1.yaxis.set_major_formatter(FormatStrFormatter("%.4f")) 

177 

178 ax1.legend() 

179 

180 x_ticks = np.arange(0, 3600 * 6 + 1, 3600) 

181 x_tick_labels = [int(tick / 3600) for tick in x_ticks] 

182 ax1.set_xticks(x_ticks) 

183 ax1.set_xticklabels(x_tick_labels) 

184 ax1.set_xlabel("Time in hours") 

185 for ax in axs: 

186 mpcplot.make_grid(ax) 

187 ax.set_xlim(0, 3600 * 6) 

188 plt.show() 

189 

190 if with_dashboard: 

191 Dashboard( 

192 flex_config="flex_configs/flexibility_agent_config.json", 

193 simulator_agent_config="mpc_and_sim/simple_cia_sim.json", 

194 results=results 

195 ).show() 

196 

197 return results 

198 

199 

200if __name__ == "__main__": 

201 run_example(until, with_plots=True, with_dashboard=False)