Update app.py
Browse files
app.py
CHANGED
|
@@ -62,8 +62,8 @@ def optimize_energy_system(city_code, solar_cost, onshore_wind_cost, offshore_wi
|
|
| 62 |
demand = demand_cf * yearly_demand / 100 * 1000 * 1000
|
| 63 |
|
| 64 |
renewable_capacity = pulp.LpVariable.dicts("renewable_capacity",
|
| 65 |
-
|
| 66 |
-
|
| 67 |
curtailment = pulp.LpVariable.dicts("curtailment",
|
| 68 |
[(r, t) for r in regions for t in time_steps],
|
| 69 |
lowBound=0, cat='Continuous')
|
|
@@ -76,14 +76,14 @@ def optimize_energy_system(city_code, solar_cost, onshore_wind_cost, offshore_wi
|
|
| 76 |
|
| 77 |
# Objective: minimize total cost (renewable capacities and battery)
|
| 78 |
model += pulp.lpSum([renewable_capacity[(r, g)] * renewable_capacity_cost[g]
|
| 79 |
-
|
| 80 |
battery_capacity * battery_cost_per_mwh, "TotalCost"
|
| 81 |
|
| 82 |
# Constraints: meet demand, manage battery SOC
|
| 83 |
for r in regions:
|
| 84 |
for t in time_steps:
|
| 85 |
model += pulp.lpSum([renewable_capacity[(r, g)] * capacity_factor[g][t]
|
| 86 |
-
|
| 87 |
if t == 0:
|
| 88 |
model += SOC[t] == battery_charge[t] * battery_efficiency - battery_discharge[t] * (1 / battery_efficiency), f"SOCUpdate_{t}"
|
| 89 |
else:
|
|
@@ -114,11 +114,11 @@ def optimize_energy_system(city_code, solar_cost, onshore_wind_cost, offshore_wi
|
|
| 114 |
alt_model_min = pulp.LpProblem(f"AlternativeModel_Min_{tech}_{threshold}", pulp.LpMinimize)
|
| 115 |
alt_model_min += pulp.lpSum([renewable_capacity[(r, g)] * renewable_capacity_cost[g]
|
| 116 |
for r in regions for g in technologies]) + battery_capacity * battery_cost_per_mwh <= relaxed_cost
|
| 117 |
-
|
| 118 |
# Copy original constraints with unique names
|
| 119 |
for name, constraint in model.constraints.items():
|
| 120 |
alt_model_min += constraint.copy(), f"{name}_min_{tech}_{threshold}"
|
| 121 |
-
|
| 122 |
# Minimize the capacity of the selected technology
|
| 123 |
alt_model_min += renewable_capacity[('region1', tech)], f"Minimize_{tech}_Capacity"
|
| 124 |
alt_model_min.solve()
|
|
@@ -131,16 +131,16 @@ def optimize_energy_system(city_code, solar_cost, onshore_wind_cost, offshore_wi
|
|
| 131 |
'battery_capacity': battery_capacity.varValue,
|
| 132 |
'total_cost': pulp.value(alt_model_min.objective)
|
| 133 |
})
|
| 134 |
-
|
| 135 |
# Maximize capacity of each technology
|
| 136 |
alt_model_max = pulp.LpProblem(f"AlternativeModel_Max_{tech}_{threshold}", pulp.LpMinimize)
|
| 137 |
alt_model_max += pulp.lpSum([renewable_capacity[(r, g)] * renewable_capacity_cost[g]
|
| 138 |
for r in regions for g in technologies]) + battery_capacity * battery_cost_per_mwh <= relaxed_cost
|
| 139 |
-
|
| 140 |
# Copy original constraints with unique names
|
| 141 |
for name, constraint in model.constraints.items():
|
| 142 |
alt_model_max += constraint.copy(), f"{name}_max_{tech}_{threshold}"
|
| 143 |
-
|
| 144 |
# Maximize the capacity of the selected technology
|
| 145 |
alt_model_max += -renewable_capacity[('region1', tech)], f"Maximize_{tech}_Capacity"
|
| 146 |
alt_model_max.solve()
|
|
@@ -176,7 +176,7 @@ with st.sidebar:
|
|
| 176 |
river_range = st.slider("River Capacity Range (MW)", 0, 10000, (0, 10000))
|
| 177 |
# 0.1の刻みで0から1までの値を生成し、小数点以下3桁に丸める
|
| 178 |
thresholds = st.multiselect(
|
| 179 |
-
"Select MGA Cost Deviation Thresholds (%)",
|
| 180 |
list(np.arange(0, 11, 0.5)),
|
| 181 |
default=[0, 5, 10]
|
| 182 |
)
|
|
@@ -186,7 +186,7 @@ with st.sidebar:
|
|
| 186 |
if st.button("Run MGA Optimization"):
|
| 187 |
# 実行して alternative_solutions を取得
|
| 188 |
alternative_solutions = optimize_energy_system(city_code, solar_cost, onshore_wind_cost, offshore_wind_cost, river_cost, battery_cost, yearly_demand, solar_range, wind_range, river_range, offshore_wind_range, [t / 100 for t in thresholds], selected_technologies)
|
| 189 |
-
|
| 190 |
if alternative_solutions:
|
| 191 |
# コスト積み上げ用データの収集
|
| 192 |
cost_data = []
|
|
@@ -216,7 +216,7 @@ if st.button("Run MGA Optimization"):
|
|
| 216 |
|
| 217 |
# 各技術の容量範囲を個別のグラフで表示
|
| 218 |
epsilon_values = sorted(list(set(sol['threshold'] * 100 for sol in alternative_solutions)))
|
| 219 |
-
|
| 220 |
for tech in selected_technologies:
|
| 221 |
storage_min = []
|
| 222 |
storage_max = []
|
|
@@ -243,25 +243,25 @@ if st.button("Run MGA Optimization"):
|
|
| 243 |
|
| 244 |
|
| 245 |
st.markdown("""
|
| 246 |
-
This application uses **Modeling to Generate Alternatives (MGA)** to explore near-optimal solutions in a renewable energy system model. MGA helps to identify alternative configurations that are close to the optimal solution but vary in their specific technological composition, providing flexibility for policy makers and stakeholders who might prioritize factors beyond cost minimization, such as social acceptance or regional preferences.
|
| 247 |
-
""")
|
| 248 |
|
| 249 |
st.write("## Objective Function and Cost Minimization")
|
| 250 |
st.markdown("""
|
| 251 |
-
In our renewable energy model, the **objective function** is to minimize the total annual cost of the system, which includes the costs of installing renewable generation capacities (such as solar, wind, and hydroelectric) and storage (batteries). The objective function is defined as:
|
| 252 |
-
""")
|
| 253 |
st.latex(r"""
|
| 254 |
-
\text{Minimize } \quad \sum_{r, g} \text{Cost}_{g} \times \text{Capacity}_{r, g} + \text{Battery Cost} \times \text{Battery Capacity}
|
| 255 |
-
""")
|
| 256 |
st.markdown("""
|
| 257 |
-
where:
|
| 258 |
-
- $r$ represents the region (in this case, a single region),
|
| 259 |
-
- $g$ represents the generation technology (solar, onshore wind, offshore wind, river),
|
| 260 |
-
-
|
| 261 |
-
-
|
| 262 |
-
-
|
| 263 |
-
-
|
| 264 |
-
""")
|
| 265 |
|
| 266 |
st.markdown("""
|
| 267 |
## What is MGA and Why is it Important?
|
|
@@ -282,7 +282,7 @@ st.latex(r"""
|
|
| 282 |
st.markdown("""
|
| 283 |
where:
|
| 284 |
- $\epsilon$ is the cost deviation percentage (e.g., if $\epsilon = 0.05$, then the solution can be up to 5% more expensive than the optimal cost),
|
| 285 |
-
-
|
| 286 |
|
| 287 |
This constraint allows for flexibility in cost, enabling the exploration of solutions that are **near-optimal** but differ in terms of installed capacities for each technology.
|
| 288 |
""")
|
|
@@ -298,24 +298,24 @@ st.markdown("""
|
|
| 298 |
These steps generate a set of **alternative solutions** that are close in cost but vary significantly in their reliance on each technology, revealing **flexibility** and **trade-offs** in the renewable energy system configuration.
|
| 299 |
""")
|
| 300 |
|
| 301 |
-
st.write("## Interpreting the Cost Threshold (
|
| 302 |
st.markdown("""
|
| 303 |
-
The cost threshold parameter
|
| 304 |
-
-
|
| 305 |
-
-
|
| 306 |
-
-
|
| 307 |
|
| 308 |
-
By exploring a range of
|
| 309 |
""")
|
| 310 |
|
| 311 |
st.markdown("""
|
| 312 |
## Visualization of Results
|
| 313 |
- **Cost Breakdown**: The total cost of each solution, broken down by technology, helps us see the contribution of each technology to the total cost.
|
| 314 |
-
- **Capacity Ranges**: For each technology, we plot the minimum and maximum capacities across different
|
| 315 |
|
| 316 |
This visualization provides insights into:
|
| 317 |
-
- Which technologies are essential (appear consistently in solutions across all
|
| 318 |
-
- Which technologies offer flexibility (capacities vary widely as
|
| 319 |
- The cost impact of relying more or less on specific technologies.
|
| 320 |
|
| 321 |
Through MGA, we can make more **informed decisions** about the renewable energy mix and identify robust, flexible strategies that align with broader goals beyond cost minimization.
|
|
|
|
| 62 |
demand = demand_cf * yearly_demand / 100 * 1000 * 1000
|
| 63 |
|
| 64 |
renewable_capacity = pulp.LpVariable.dicts("renewable_capacity",
|
| 65 |
+
[(r, g) for r in regions for g in technologies],
|
| 66 |
+
lowBound=0, cat='Continuous')
|
| 67 |
curtailment = pulp.LpVariable.dicts("curtailment",
|
| 68 |
[(r, t) for r in regions for t in time_steps],
|
| 69 |
lowBound=0, cat='Continuous')
|
|
|
|
| 76 |
|
| 77 |
# Objective: minimize total cost (renewable capacities and battery)
|
| 78 |
model += pulp.lpSum([renewable_capacity[(r, g)] * renewable_capacity_cost[g]
|
| 79 |
+
for r in regions for g in technologies]) + \
|
| 80 |
battery_capacity * battery_cost_per_mwh, "TotalCost"
|
| 81 |
|
| 82 |
# Constraints: meet demand, manage battery SOC
|
| 83 |
for r in regions:
|
| 84 |
for t in time_steps:
|
| 85 |
model += pulp.lpSum([renewable_capacity[(r, g)] * capacity_factor[g][t]
|
| 86 |
+
for g in technologies]) + battery_discharge[t] == demand[t] + battery_charge[t] + curtailment[(r, t)], f"DemandConstraint_{r}_{t}"
|
| 87 |
if t == 0:
|
| 88 |
model += SOC[t] == battery_charge[t] * battery_efficiency - battery_discharge[t] * (1 / battery_efficiency), f"SOCUpdate_{t}"
|
| 89 |
else:
|
|
|
|
| 114 |
alt_model_min = pulp.LpProblem(f"AlternativeModel_Min_{tech}_{threshold}", pulp.LpMinimize)
|
| 115 |
alt_model_min += pulp.lpSum([renewable_capacity[(r, g)] * renewable_capacity_cost[g]
|
| 116 |
for r in regions for g in technologies]) + battery_capacity * battery_cost_per_mwh <= relaxed_cost
|
| 117 |
+
|
| 118 |
# Copy original constraints with unique names
|
| 119 |
for name, constraint in model.constraints.items():
|
| 120 |
alt_model_min += constraint.copy(), f"{name}_min_{tech}_{threshold}"
|
| 121 |
+
|
| 122 |
# Minimize the capacity of the selected technology
|
| 123 |
alt_model_min += renewable_capacity[('region1', tech)], f"Minimize_{tech}_Capacity"
|
| 124 |
alt_model_min.solve()
|
|
|
|
| 131 |
'battery_capacity': battery_capacity.varValue,
|
| 132 |
'total_cost': pulp.value(alt_model_min.objective)
|
| 133 |
})
|
| 134 |
+
|
| 135 |
# Maximize capacity of each technology
|
| 136 |
alt_model_max = pulp.LpProblem(f"AlternativeModel_Max_{tech}_{threshold}", pulp.LpMinimize)
|
| 137 |
alt_model_max += pulp.lpSum([renewable_capacity[(r, g)] * renewable_capacity_cost[g]
|
| 138 |
for r in regions for g in technologies]) + battery_capacity * battery_cost_per_mwh <= relaxed_cost
|
| 139 |
+
|
| 140 |
# Copy original constraints with unique names
|
| 141 |
for name, constraint in model.constraints.items():
|
| 142 |
alt_model_max += constraint.copy(), f"{name}_max_{tech}_{threshold}"
|
| 143 |
+
|
| 144 |
# Maximize the capacity of the selected technology
|
| 145 |
alt_model_max += -renewable_capacity[('region1', tech)], f"Maximize_{tech}_Capacity"
|
| 146 |
alt_model_max.solve()
|
|
|
|
| 176 |
river_range = st.slider("River Capacity Range (MW)", 0, 10000, (0, 10000))
|
| 177 |
# 0.1の刻みで0から1までの値を生成し、小数点以下3桁に丸める
|
| 178 |
thresholds = st.multiselect(
|
| 179 |
+
"Select MGA Cost Deviation Thresholds (%)",
|
| 180 |
list(np.arange(0, 11, 0.5)),
|
| 181 |
default=[0, 5, 10]
|
| 182 |
)
|
|
|
|
| 186 |
if st.button("Run MGA Optimization"):
|
| 187 |
# 実行して alternative_solutions を取得
|
| 188 |
alternative_solutions = optimize_energy_system(city_code, solar_cost, onshore_wind_cost, offshore_wind_cost, river_cost, battery_cost, yearly_demand, solar_range, wind_range, river_range, offshore_wind_range, [t / 100 for t in thresholds], selected_technologies)
|
| 189 |
+
|
| 190 |
if alternative_solutions:
|
| 191 |
# コスト積み上げ用データの収集
|
| 192 |
cost_data = []
|
|
|
|
| 216 |
|
| 217 |
# 各技術の容量範囲を個別のグラフで表示
|
| 218 |
epsilon_values = sorted(list(set(sol['threshold'] * 100 for sol in alternative_solutions)))
|
| 219 |
+
|
| 220 |
for tech in selected_technologies:
|
| 221 |
storage_min = []
|
| 222 |
storage_max = []
|
|
|
|
| 243 |
|
| 244 |
|
| 245 |
st.markdown("""
|
| 246 |
+
This application uses **Modeling to Generate Alternatives (MGA)** to explore near-optimal solutions in a renewable energy system model. MGA helps to identify alternative configurations that are close to the optimal solution but vary in their specific technological composition, providing flexibility for policy makers and stakeholders who might prioritize factors beyond cost minimization, such as social acceptance or regional preferences.
|
| 247 |
+
""")
|
| 248 |
|
| 249 |
st.write("## Objective Function and Cost Minimization")
|
| 250 |
st.markdown("""
|
| 251 |
+
In our renewable energy model, the **objective function** is to minimize the total annual cost of the system, which includes the costs of installing renewable generation capacities (such as solar, wind, and hydroelectric) and storage (batteries). The objective function is defined as:
|
| 252 |
+
""")
|
| 253 |
st.latex(r"""
|
| 254 |
+
\text{Minimize } \quad \sum_{r, g} \text{Cost}_{g} \times \text{Capacity}_{r, g} + \text{Battery Cost} \times \text{Battery Capacity}
|
| 255 |
+
""")
|
| 256 |
st.markdown("""
|
| 257 |
+
where:
|
| 258 |
+
- $r$ represents the region (in this case, a single region),
|
| 259 |
+
- $g$ represents the generation technology (solar, onshore wind, offshore wind, river),
|
| 260 |
+
- ${Cost}_{g}$ is the per-MW cost of technology $g$,
|
| 261 |
+
- $Capacity_{r, g}$ is the installed capacity of technology $g$ in region $r$,
|
| 262 |
+
- ${Battery/, Cost}$ represents the cost per MWh of battery storage,
|
| 263 |
+
- ${Battery/, Capacity}$ is the total installed battery capacity.
|
| 264 |
+
""")
|
| 265 |
|
| 266 |
st.markdown("""
|
| 267 |
## What is MGA and Why is it Important?
|
|
|
|
| 282 |
st.markdown("""
|
| 283 |
where:
|
| 284 |
- $\epsilon$ is the cost deviation percentage (e.g., if $\epsilon = 0.05$, then the solution can be up to 5% more expensive than the optimal cost),
|
| 285 |
+
- ${Optimal\, Cost}$ is the minimum cost obtained from the initial optimization.
|
| 286 |
|
| 287 |
This constraint allows for flexibility in cost, enabling the exploration of solutions that are **near-optimal** but differ in terms of installed capacities for each technology.
|
| 288 |
""")
|
|
|
|
| 298 |
These steps generate a set of **alternative solutions** that are close in cost but vary significantly in their reliance on each technology, revealing **flexibility** and **trade-offs** in the renewable energy system configuration.
|
| 299 |
""")
|
| 300 |
|
| 301 |
+
st.write("## Interpreting the Cost Threshold ($psilon$ )")
|
| 302 |
st.markdown("""
|
| 303 |
+
The cost threshold parameter ($epsilon$ ) is crucial in MGA, as it determines the range within which we consider solutions to be "near-optimal." For example:
|
| 304 |
+
- **$epsilon = 0% $**: Only the exact optimal solution is considered.
|
| 305 |
+
- **$epsilon = 5% $**: Solutions within 5% of the optimal cost are considered acceptable, allowing for slightly more flexibility in technology choice.
|
| 306 |
+
- **$epsilon = 10% $**: Solutions within 10% of the optimal cost are allowed, providing even greater flexibility.
|
| 307 |
|
| 308 |
+
By exploring a range of $epsilon$ values, we can see how the system configuration changes as we relax the cost constraint, offering a broader view of feasible solutions.
|
| 309 |
""")
|
| 310 |
|
| 311 |
st.markdown("""
|
| 312 |
## Visualization of Results
|
| 313 |
- **Cost Breakdown**: The total cost of each solution, broken down by technology, helps us see the contribution of each technology to the total cost.
|
| 314 |
+
- **Capacity Ranges**: For each technology, we plot the minimum and maximum capacities across different $epsilon$ values, showing the flexibility in system design as cost thresholds change.
|
| 315 |
|
| 316 |
This visualization provides insights into:
|
| 317 |
+
- Which technologies are essential (appear consistently in solutions across all $epsilon$ values),
|
| 318 |
+
- Which technologies offer flexibility (capacities vary widely as $epsilon$ increases),
|
| 319 |
- The cost impact of relying more or less on specific technologies.
|
| 320 |
|
| 321 |
Through MGA, we can make more **informed decisions** about the renewable energy mix and identify robust, flexible strategies that align with broader goals beyond cost minimization.
|