naohiro701 commited on
Commit
450b5a3
·
verified ·
1 Parent(s): 7d7cde1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +95 -261
app.py CHANGED
@@ -26,35 +26,31 @@ def get_renewable_energy_data(city_code):
26
 
27
  return result_df, None
28
 
29
- # Optimize energy system and use MGA
30
- def optimize_energy_system(data, technologies, solar_cost, onshore_wind_cost, offshore_wind_cost, river_cost, battery_cost, yearly_demand, solar_range, wind_range, river_range, offshore_wind_range, thresholds, selected_tech):
31
- for col in data.columns[1:]:
32
- data[col] = pd.to_numeric(data[col], errors='coerce')
33
- data = data.fillna(0)
34
-
35
- time_steps = range(len(data['Time']))
36
- solar_cf = data['solar hourly capacity factor']
37
- onshore_wind_cf = data['onshore_wind hourly capacity factor']
38
- offshore_wind_cf = data['offshore_wind hourly capacity factor']
39
- river_cf = data['river hourly capacity factor']
40
- demand_cf = data['demand hourly capacity factor']
41
-
42
- demand = demand_cf * yearly_demand * 1e6 / demand_cf.sum() # MW
43
-
 
 
 
44
  regions = ['region1']
45
- capacity_factor = {
46
- 'solar': solar_cf,
47
- 'onshore_wind': onshore_wind_cf,
48
- 'offshore_wind': offshore_wind_cf,
49
- 'river': river_cf
50
- }
51
-
52
  renewable_capacity_cost = {'solar': solar_cost, 'onshore_wind': onshore_wind_cost, 'offshore_wind': offshore_wind_cost, 'river': river_cost}
53
  battery_cost_per_mwh = battery_cost
54
  battery_efficiency = 0.9
55
 
56
  # Create the model
57
- model = pulp.LpProblem("EnergySystemOptimizationWithBattery", pulp.LpMinimize)
58
 
59
  # Variables
60
  renewable_capacity = pulp.LpVariable.dicts("renewable_capacity",
@@ -62,40 +58,51 @@ def optimize_energy_system(data, technologies, solar_cost, onshore_wind_cost, of
62
  lowBound=0, cat='Continuous')
63
  battery_capacity = pulp.LpVariable("battery_capacity", lowBound=0, cat='Continuous')
64
 
65
- renewable_generation = pulp.LpVariable.dicts("renewable_generation",
66
- [(t, g) for t in time_steps for g in technologies],
67
- lowBound=0, cat='Continuous')
68
- battery_charge = pulp.LpVariable.dicts("battery_charge",
69
- time_steps, lowBound=0, cat='Continuous')
70
- battery_discharge = pulp.LpVariable.dicts("battery_discharge",
71
- time_steps, lowBound=0, cat='Continuous')
72
- battery_storage = pulp.LpVariable.dicts("battery_storage",
73
- time_steps, lowBound=0, cat='Continuous')
74
-
75
  # Objective: minimize total cost
76
  model += pulp.lpSum([renewable_capacity[('region1', g)] * renewable_capacity_cost[g] for g in technologies]) + \
77
  battery_capacity * battery_cost_per_mwh, "TotalCost"
78
 
79
- # Constraints
80
-
81
- # Renewable generation constraints
82
- for t in time_steps:
83
- for g in technologies:
84
- model += renewable_generation[(t, g)] <= renewable_capacity[('region1', g)] * capacity_factor[g].iloc[t], f"GenCap_{t}_{g}"
85
-
86
- # Energy balance constraints
87
- for t in time_steps:
88
- total_generation = pulp.lpSum([renewable_generation[(t, g)] for g in technologies])
89
- model += total_generation + battery_discharge[t] == demand.iloc[t] + battery_charge[t], f"EnergyBalance_{t}"
90
-
91
- # Battery storage constraints
92
- for t in time_steps:
93
- if t == 0:
94
- model += battery_storage[t] == battery_capacity * 0.5 + battery_charge[t] * battery_efficiency - battery_discharge[t] * (1 / battery_efficiency), f"StorageBalance_{t}"
95
- else:
96
- model += battery_storage[t] == battery_storage[t - 1] + battery_charge[t] * battery_efficiency - battery_discharge[t] * (1 / battery_efficiency), f"StorageBalance_{t}"
97
- model += battery_storage[t] <= battery_capacity, f"StorageCapacity_{t}"
98
- model += battery_storage[t] >= 0, f"StorageNonNegative_{t}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
  # Renewable capacity constraints (within specified ranges)
101
  model += renewable_capacity[('region1', 'solar')] >= solar_range[0], "SolarCapMin"
@@ -110,175 +117,23 @@ def optimize_energy_system(data, technologies, solar_cost, onshore_wind_cost, of
110
  model += renewable_capacity[('region1', 'river')] >= river_range[0], "RiverCapMin"
111
  model += renewable_capacity[('region1', 'river')] <= river_range[1], "RiverCapMax"
112
 
113
- # Solve the initial model to find the optimal solution
114
  model.solve()
115
- optimal_cost = pulp.value(model.objective)
116
-
117
- # Collect the initial solution
118
- initial_solution = {
119
- 'threshold': 0,
120
- 'type': 'optimal',
121
- 'technology': 'all',
122
- 'solution': {g: renewable_capacity[('region1', g)].varValue for g in technologies},
123
- 'battery_capacity': battery_capacity.varValue,
124
- 'total_cost': optimal_cost
125
- }
126
-
127
- # MGA: Generate alternative solutions for selected technologies only
128
- alternative_solutions = [initial_solution]
129
-
130
- for threshold in thresholds:
131
- if threshold == 0:
132
- continue # Already have the optimal solution
133
- relaxed_cost = optimal_cost * (1 + threshold)
134
- for tech in selected_tech:
135
- # Create a copy of the model
136
- alt_model = pulp.LpProblem(f"AlternativeModel_{tech}_{threshold}", pulp.LpMinimize)
137
-
138
- # Variables (need to create new variables for the new model)
139
- alt_renewable_capacity = pulp.LpVariable.dicts("alt_renewable_capacity",
140
- [(r, g) for r in regions for g in technologies],
141
- lowBound=0, cat='Continuous')
142
- alt_battery_capacity = pulp.LpVariable("alt_battery_capacity", lowBound=0, cat='Continuous')
143
-
144
- alt_renewable_generation = pulp.LpVariable.dicts("alt_renewable_generation",
145
- [(t, g) for t in time_steps for g in technologies],
146
- lowBound=0, cat='Continuous')
147
- alt_battery_charge = pulp.LpVariable.dicts("alt_battery_charge",
148
- time_steps, lowBound=0, cat='Continuous')
149
- alt_battery_discharge = pulp.LpVariable.dicts("alt_battery_discharge",
150
- time_steps, lowBound=0, cat='Continuous')
151
- alt_battery_storage = pulp.LpVariable.dicts("alt_battery_storage",
152
- time_steps, lowBound=0, cat='Continuous')
153
-
154
- # Objective: maximize the capacity of the selected technology
155
- alt_model += -alt_renewable_capacity[('region1', tech)], f"Maximize_{tech}_Capacity"
156
-
157
- # Add the cost constraint
158
- alt_model += pulp.lpSum([alt_renewable_capacity[('region1', g)] * renewable_capacity_cost[g] for g in technologies]) + \
159
- alt_battery_capacity * battery_cost_per_mwh <= relaxed_cost, "CostConstraint"
160
-
161
- # Constraints
162
-
163
- # Renewable generation constraints
164
- for t in time_steps:
165
- for g in technologies:
166
- alt_model += alt_renewable_generation[(t, g)] <= alt_renewable_capacity[('region1', g)] * capacity_factor[g].iloc[t], f"GenCap_{t}_{g}"
167
-
168
- # Energy balance constraints
169
- for t in time_steps:
170
- total_generation = pulp.lpSum([alt_renewable_generation[(t, g)] for g in technologies])
171
- alt_model += total_generation + alt_battery_discharge[t] == demand.iloc[t] + alt_battery_charge[t], f"EnergyBalance_{t}"
172
-
173
- # Battery storage constraints
174
- for t in time_steps:
175
- if t == 0:
176
- alt_model += alt_battery_storage[t] == alt_battery_capacity * 0.5 + alt_battery_charge[t] * battery_efficiency - alt_battery_discharge[t] * (1 / battery_efficiency), f"StorageBalance_{t}"
177
- else:
178
- alt_model += alt_battery_storage[t] == alt_battery_storage[t - 1] + alt_battery_charge[t] * battery_efficiency - alt_battery_discharge[t] * (1 / battery_efficiency), f"StorageBalance_{t}"
179
- alt_model += alt_battery_storage[t] <= alt_battery_capacity, f"StorageCapacity_{t}"
180
- alt_model += alt_battery_storage[t] >= 0, f"StorageNonNegative_{t}"
181
 
182
- # Renewable capacity constraints (within specified ranges)
183
- alt_model += alt_renewable_capacity[('region1', 'solar')] >= solar_range[0], "SolarCapMin"
184
- alt_model += alt_renewable_capacity[('region1', 'solar')] <= solar_range[1], "SolarCapMax"
185
-
186
- alt_model += alt_renewable_capacity[('region1', 'onshore_wind')] >= wind_range[0], "WindCapMin"
187
- alt_model += alt_renewable_capacity[('region1', 'onshore_wind')] <= wind_range[1], "WindCapMax"
188
-
189
- alt_model += alt_renewable_capacity[('region1', 'offshore_wind')] >= offshore_wind_range[0], "OffshoreWindCapMin"
190
- alt_model += alt_renewable_capacity[('region1', 'offshore_wind')] <= offshore_wind_range[1], "OffshoreWindCapMax"
191
-
192
- alt_model += alt_renewable_capacity[('region1', 'river')] >= river_range[0], "RiverCapMin"
193
- alt_model += alt_renewable_capacity[('region1', 'river')] <= river_range[1], "RiverCapMax"
194
-
195
- # Solve the alternative model
196
- alt_model.solve()
197
- if pulp.LpStatus[alt_model.status] == 'Optimal':
198
- alt_solution = {
199
- 'threshold': threshold,
200
- 'type': 'max',
201
- 'technology': tech,
202
- 'solution': {g: alt_renewable_capacity[('region1', g)].varValue for g in technologies},
203
- 'battery_capacity': alt_battery_capacity.varValue,
204
- 'total_cost': pulp.value(alt_model.objective)
205
- }
206
- alternative_solutions.append(alt_solution)
207
-
208
- return alternative_solutions
209
-
210
- # Violin plot for each technology’s capacity distribution across alternative solutions
211
- def plot_capacity_distribution(alternative_solutions, selected_technologies):
212
- # Collect capacity data for each technology at each threshold level
213
- capacity_data = []
214
- for sol in alternative_solutions:
215
- for tech in selected_technologies:
216
- capacity_data.append({
217
- 'Threshold (%)': sol['threshold'] * 100,
218
- 'Technology': tech,
219
- 'Capacity (MW)': sol['solution'][tech],
220
- 'Type': sol['type'],
221
- 'Varied Technology': sol['technology']
222
- })
223
-
224
- capacity_df = pd.DataFrame(capacity_data)
225
-
226
- # Create line plot to show capacity changes over thresholds
227
- fig_line = px.line(capacity_df, x="Threshold (%)", y="Capacity (MW)", color="Technology",
228
- line_dash="Varied Technology", markers=True,
229
- title="Technology Capacity Changes Over Thresholds")
230
- st.plotly_chart(fig_line, use_container_width=True)
231
-
232
- # Function to create cost breakdown stacked bar plot for each threshold and technology type
233
- def plot_cost_breakdown(alternative_solutions, selected_technologies, renewable_capacity_cost, battery_cost_per_mwh):
234
- for idx, sol in enumerate(alternative_solutions):
235
- cost_data = {
236
- 'Technology': selected_technologies + ['Battery'],
237
- 'Cost': [sol['solution'][tech] * renewable_capacity_cost[tech] for tech in selected_technologies] + [sol['battery_capacity'] * battery_cost_per_mwh]
238
  }
239
- cost_df = pd.DataFrame(cost_data)
240
-
241
- # Create stacked bar chart with unique key to avoid StreamlitDuplicateElementId error
242
- fig_bar = px.bar(cost_df, x='Technology', y='Cost', title=f"Cost Breakdown (Threshold: {sol['threshold'] * 100}%, Technology Varied: {sol['technology']})",
243
- labels={'Cost': 'Cost (¥)'})
244
- st.plotly_chart(fig_bar, use_container_width=True, key=f"cost_plot_{idx}")
245
-
246
- # Function to plot generation and demand over time
247
- def plot_generation_demand(data, alternative_solution, time_steps, technologies):
248
- total_generation = np.zeros(len(time_steps))
249
- for g in technologies:
250
- gen = np.array(data[f'{g} hourly capacity factor']) * alternative_solution['solution'][g]
251
- total_generation += gen
252
- demand = data['demand hourly capacity factor'] * data['demand hourly capacity factor'].sum()
253
- fig = px.line(x=time_steps, y=[total_generation, demand],
254
- labels={'x': 'Time', 'value': 'Power (MW)', 'variable': 'Legend'},
255
- title='Total Generation and Demand Over Time')
256
- fig.update_traces(mode='lines')
257
- st.plotly_chart(fig, use_container_width=True)
258
-
259
- # Function to plot battery storage levels over time
260
- def plot_battery_storage(data, alternative_solution, time_steps):
261
- # For simplicity, re-calculate battery storage levels
262
- battery_storage = np.zeros(len(time_steps))
263
- battery_capacity = alternative_solution['battery_capacity']
264
- battery_charge = data['battery_charge'] if 'battery_charge' in data else np.zeros(len(time_steps))
265
- battery_discharge = data['battery_discharge'] if 'battery_discharge' in data else np.zeros(len(time_steps))
266
- battery_efficiency = 0.9
267
-
268
- for t in range(len(time_steps)):
269
- if t == 0:
270
- battery_storage[t] = battery_capacity * 0.5 + battery_charge[t] * battery_efficiency - battery_discharge[t] * (1 / battery_efficiency)
271
- else:
272
- battery_storage[t] = battery_storage[t - 1] + battery_charge[t] * battery_efficiency - battery_discharge[t] * (1 / battery_efficiency)
273
-
274
- fig = px.line(x=time_steps, y=battery_storage,
275
- labels={'x': 'Time', 'y': 'Battery Storage Level (MWh)'},
276
- title='Battery Storage Level Over Time')
277
- st.plotly_chart(fig, use_container_width=True)
278
 
279
  # Streamlit UI setup
280
- st.set_page_config(page_title='Renewable Energy System Optimization with MGA', layout='wide')
281
- st.title('Modeling to Generate Alternatives (MGA) in Renewable Energy System Optimization')
282
 
283
  # Sidebar Inputs
284
  with st.sidebar:
@@ -294,57 +149,36 @@ with st.sidebar:
294
  wind_range = st.slider("Onshore Wind Capacity Range (MW)", 0, 10000, (0, 10000))
295
  offshore_wind_range = st.slider("Offshore Wind Capacity Range (MW)", 0, 10000, (0, 10000))
296
  river_range = st.slider("River Capacity Range (MW)", 0, 10000, (0, 10000))
297
- threshold_options = list(np.arange(0, 11, 0.5))
298
- threshold_default = [0, 5, 10]
299
- thresholds = st.multiselect(
300
- "Select MGA Cost Deviation Thresholds (%)",
301
- threshold_options,
302
- default=threshold_default
303
- )
304
- selected_technologies = st.multiselect("Select Technologies to Optimize", ['solar', 'onshore_wind', 'offshore_wind', 'river'], default=['solar'])
305
-
306
- if st.button("Run MGA Optimization"):
307
- thresholds = [t / 100 for t in thresholds] # Convert percentages to decimals
308
 
 
309
  # Fetch data
310
  data, error = get_renewable_energy_data(city_code)
311
  if error:
312
  st.error(error)
313
  st.stop()
314
 
 
 
 
315
  # Define technologies
316
  technologies = ['solar', 'onshore_wind', 'offshore_wind', 'river']
317
 
318
- # Run optimization
319
- alternative_solutions = optimize_energy_system(data, technologies, solar_cost, onshore_wind_cost, offshore_wind_cost, river_cost, battery_cost, yearly_demand, solar_range, wind_range, river_range, offshore_wind_range, thresholds, selected_technologies)
320
-
321
- if alternative_solutions:
322
- # Display capacity distribution using line plots
323
- plot_capacity_distribution(alternative_solutions, technologies)
324
-
325
- # Display cost breakdown stacked bar plots for each case
326
- plot_cost_breakdown(alternative_solutions, technologies, {
327
- 'solar': solar_cost,
328
- 'onshore_wind': onshore_wind_cost,
329
- 'offshore_wind': offshore_wind_cost,
330
- 'river': river_cost
331
- }, battery_cost)
332
-
333
- # Plot generation and demand over time for the first alternative solution
334
- st.header("Generation and Demand Over Time")
335
- plot_generation_demand(data, alternative_solutions[0], data['Time'], technologies)
336
-
337
- # Plot battery storage levels over time
338
- st.header("Battery Storage Level Over Time")
339
- plot_battery_storage(data, alternative_solutions[0], data['Time'])
340
-
341
- # Display alternative solutions in a table
342
- st.header("Alternative Solutions Summary")
343
- summary_data = []
344
- for sol in alternative_solutions:
345
- row = {'Threshold (%)': sol['threshold'] * 100, 'Type': sol['type'], 'Varied Technology': sol['technology'], 'Battery Capacity (MWh)': sol['battery_capacity'], 'Total Cost (¥)': sol['total_cost']}
346
- for tech in technologies:
347
- row[f"{tech.capitalize()} Capacity (MW)"] = sol['solution'][tech]
348
- summary_data.append(row)
349
- summary_df = pd.DataFrame(summary_data)
350
- st.dataframe(summary_df)
 
26
 
27
  return result_df, None
28
 
29
+ # Generate scenarios for robust optimization
30
+ def generate_scenarios(data, num_scenarios, demand_variation, supply_variation):
31
+ scenarios = []
32
+ for i in range(num_scenarios):
33
+ scenario = data.copy()
34
+ # Vary demand
35
+ demand_factor = 1 + np.random.uniform(-demand_variation, demand_variation)
36
+ scenario['demand hourly capacity factor'] *= demand_factor
37
+ # Vary supply capacity factors
38
+ for tech in ['solar', 'onshore_wind', 'offshore_wind', 'river']:
39
+ supply_factor = 1 + np.random.uniform(-supply_variation, supply_variation)
40
+ scenario[f'{tech} hourly capacity factor'] *= supply_factor
41
+ scenario[f'{tech} hourly capacity factor'] = scenario[f'{tech} hourly capacity factor'].clip(upper=1.0)
42
+ scenarios.append(scenario)
43
+ return scenarios
44
+
45
+ # Optimize energy system for multiple scenarios
46
+ def optimize_energy_system_robust(scenarios, technologies, solar_cost, onshore_wind_cost, offshore_wind_cost, river_cost, battery_cost, yearly_demand, solar_range, wind_range, river_range, offshore_wind_range):
47
  regions = ['region1']
 
 
 
 
 
 
 
48
  renewable_capacity_cost = {'solar': solar_cost, 'onshore_wind': onshore_wind_cost, 'offshore_wind': offshore_wind_cost, 'river': river_cost}
49
  battery_cost_per_mwh = battery_cost
50
  battery_efficiency = 0.9
51
 
52
  # Create the model
53
+ model = pulp.LpProblem("RobustEnergySystemOptimization", pulp.LpMinimize)
54
 
55
  # Variables
56
  renewable_capacity = pulp.LpVariable.dicts("renewable_capacity",
 
58
  lowBound=0, cat='Continuous')
59
  battery_capacity = pulp.LpVariable("battery_capacity", lowBound=0, cat='Continuous')
60
 
 
 
 
 
 
 
 
 
 
 
61
  # Objective: minimize total cost
62
  model += pulp.lpSum([renewable_capacity[('region1', g)] * renewable_capacity_cost[g] for g in technologies]) + \
63
  battery_capacity * battery_cost_per_mwh, "TotalCost"
64
 
65
+ # Constraints for each scenario
66
+ for idx, data in enumerate(scenarios):
67
+ time_steps = range(len(data['Time']))
68
+ capacity_factor = {
69
+ 'solar': data['solar hourly capacity factor'],
70
+ 'onshore_wind': data['onshore_wind hourly capacity factor'],
71
+ 'offshore_wind': data['offshore_wind hourly capacity factor'],
72
+ 'river': data['river hourly capacity factor']
73
+ }
74
+ demand_cf = data['demand hourly capacity factor']
75
+ demand = demand_cf * yearly_demand * 1e6 / demand_cf.sum() # MW
76
+
77
+ # Scenario-specific variables
78
+ renewable_generation = pulp.LpVariable.dicts(f"renewable_generation_s{idx}",
79
+ [(t, g) for t in time_steps for g in technologies],
80
+ lowBound=0, cat='Continuous')
81
+ battery_charge = pulp.LpVariable.dicts(f"battery_charge_s{idx}",
82
+ time_steps, lowBound=0, cat='Continuous')
83
+ battery_discharge = pulp.LpVariable.dicts(f"battery_discharge_s{idx}",
84
+ time_steps, lowBound=0, cat='Continuous')
85
+ battery_storage = pulp.LpVariable.dicts(f"battery_storage_s{idx}",
86
+ time_steps, lowBound=0, cat='Continuous')
87
+
88
+ # Renewable generation constraints
89
+ for t in time_steps:
90
+ for g in technologies:
91
+ model += renewable_generation[(t, g)] <= renewable_capacity[('region1', g)] * capacity_factor[g].iloc[t], f"GenCap_s{idx}_{t}_{g}"
92
+
93
+ # Energy balance constraints
94
+ for t in time_steps:
95
+ total_generation = pulp.lpSum([renewable_generation[(t, g)] for g in technologies])
96
+ model += total_generation + battery_discharge[t] == demand.iloc[t] + battery_charge[t], f"EnergyBalance_s{idx}_{t}"
97
+
98
+ # Battery storage constraints
99
+ for t in time_steps:
100
+ if t == 0:
101
+ model += battery_storage[t] == battery_capacity * 0.5 + battery_charge[t] * battery_efficiency - battery_discharge[t] * (1 / battery_efficiency), f"StorageBalance_s{idx}_{t}"
102
+ else:
103
+ model += battery_storage[t] == battery_storage[t - 1] + battery_charge[t] * battery_efficiency - battery_discharge[t] * (1 / battery_efficiency), f"StorageBalance_s{idx}_{t}"
104
+ model += battery_storage[t] <= battery_capacity, f"StorageCapacity_s{idx}_{t}"
105
+ model += battery_storage[t] >= 0, f"StorageNonNegative_s{idx}_{t}"
106
 
107
  # Renewable capacity constraints (within specified ranges)
108
  model += renewable_capacity[('region1', 'solar')] >= solar_range[0], "SolarCapMin"
 
117
  model += renewable_capacity[('region1', 'river')] >= river_range[0], "RiverCapMin"
118
  model += renewable_capacity[('region1', 'river')] <= river_range[1], "RiverCapMax"
119
 
120
+ # Solve the model
121
  model.solve()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
+ if pulp.LpStatus[model.status] == 'Optimal':
124
+ solution = {
125
+ 'renewable_capacity': {g: renewable_capacity[('region1', g)].varValue for g in technologies},
126
+ 'battery_capacity': battery_capacity.varValue,
127
+ 'total_cost': pulp.value(model.objective)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  }
129
+ return solution
130
+ else:
131
+ st.error("Optimization did not find an optimal solution.")
132
+ return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
  # Streamlit UI setup
135
+ st.set_page_config(page_title='Robust Energy System Optimization', layout='wide')
136
+ st.title('Robust Energy System Optimization Analysis')
137
 
138
  # Sidebar Inputs
139
  with st.sidebar:
 
149
  wind_range = st.slider("Onshore Wind Capacity Range (MW)", 0, 10000, (0, 10000))
150
  offshore_wind_range = st.slider("Offshore Wind Capacity Range (MW)", 0, 10000, (0, 10000))
151
  river_range = st.slider("River Capacity Range (MW)", 0, 10000, (0, 10000))
152
+ num_scenarios = st.number_input("Number of Scenarios", min_value=1, max_value=10, value=3)
153
+ demand_variation = st.number_input("Demand Variation (%)", min_value=0.0, max_value=100.0, value=10.0) / 100
154
+ supply_variation = st.number_input("Supply Variation (%)", min_value=0.0, max_value=100.0, value=10.0) / 100
 
 
 
 
 
 
 
 
155
 
156
+ if st.button("Run Robust Optimization"):
157
  # Fetch data
158
  data, error = get_renewable_energy_data(city_code)
159
  if error:
160
  st.error(error)
161
  st.stop()
162
 
163
+ # Generate scenarios
164
+ scenarios = generate_scenarios(data, num_scenarios, demand_variation, supply_variation)
165
+
166
  # Define technologies
167
  technologies = ['solar', 'onshore_wind', 'offshore_wind', 'river']
168
 
169
+ # Run robust optimization
170
+ solution = optimize_energy_system_robust(scenarios, technologies, solar_cost, onshore_wind_cost, offshore_wind_cost, river_cost, battery_cost, yearly_demand, solar_range, wind_range, river_range, offshore_wind_range)
171
+
172
+ if solution:
173
+ st.header("Optimization Results")
174
+ st.write(f"Total Cost: {solution['total_cost']}")
175
+ st.write(f"Battery Capacity (MWh): {solution['battery_capacity']}")
176
+ capacity_data = pd.DataFrame({
177
+ 'Technology': list(solution['renewable_capacity'].keys()),
178
+ 'Capacity (MW)': list(solution['renewable_capacity'].values())
179
+ })
180
+ st.write(capacity_data)
181
+
182
+ # Visualization
183
+ fig = px.bar(capacity_data, x='Technology', y='Capacity (MW)', title='Optimal Renewable Capacities')
184
+ st.plotly_chart(fig, use_container_width=True)