Update app.py
Browse files
app.py
CHANGED
|
@@ -5,10 +5,154 @@ import pulp
|
|
| 5 |
import plotly.graph_objs as go
|
| 6 |
import plotly.express as px
|
| 7 |
import numpy as np
|
| 8 |
-
import matplotlib.pyplot as plt #
|
| 9 |
|
| 10 |
-
#
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
|
| 13 |
# Streamlit UI setup
|
| 14 |
st.set_page_config(page_title='Renewable Energy System Optimization with MGA', layout='wide')
|
|
|
|
| 5 |
import plotly.graph_objs as go
|
| 6 |
import plotly.express as px
|
| 7 |
import numpy as np
|
| 8 |
+
import matplotlib.pyplot as plt # 修正:matplotlibのインポートを追加
|
| 9 |
|
| 10 |
+
# Renewable energy data fetch function
|
| 11 |
+
def get_renewable_energy_data(city_code):
|
| 12 |
+
url = f"https://energy-sustainability.jp/_ajax/renewable_energy/get/?code={city_code}"
|
| 13 |
+
response = requests.get(url)
|
| 14 |
+
if response.status_code != 200:
|
| 15 |
+
return None, "Failed to retrieve data."
|
| 16 |
+
|
| 17 |
+
data = response.json()
|
| 18 |
+
if not data:
|
| 19 |
+
return None, "No data found."
|
| 20 |
+
|
| 21 |
+
base_times = data[next(iter(data))]['x']
|
| 22 |
+
result_df = pd.DataFrame({"Time": base_times})
|
| 23 |
+
|
| 24 |
+
for energy_type, energy_data in data.items():
|
| 25 |
+
if 'x' in energy_data and 'y' in energy_data:
|
| 26 |
+
values = energy_data['y']
|
| 27 |
+
result_df[f"{energy_type} hourly capacity factor"] = values
|
| 28 |
+
|
| 29 |
+
return result_df, None
|
| 30 |
+
|
| 31 |
+
# Optimize energy system and use MGA
|
| 32 |
+
def 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, thresholds):
|
| 33 |
+
data, error = get_renewable_energy_data(city_code)
|
| 34 |
+
if error:
|
| 35 |
+
st.error(error)
|
| 36 |
+
return None, None, None, None, None, None, None
|
| 37 |
+
|
| 38 |
+
for col in data.columns[1:]:
|
| 39 |
+
data[col] = pd.to_numeric(data[col], errors='coerce')
|
| 40 |
+
data = data.fillna(0)
|
| 41 |
+
|
| 42 |
+
time_steps = range(len(data['Time']))
|
| 43 |
+
solar_cf = data['solar hourly capacity factor']
|
| 44 |
+
onshore_wind_cf = data['onshore_wind hourly capacity factor']
|
| 45 |
+
offshore_wind_cf = data['offshore_wind hourly capacity factor']
|
| 46 |
+
river_cf = data['river hourly capacity factor']
|
| 47 |
+
demand_cf = data['demand hourly capacity factor']
|
| 48 |
+
|
| 49 |
+
regions = ['region1']
|
| 50 |
+
technologies = ['solar', 'onshore_wind', 'offshore_wind', 'river']
|
| 51 |
+
capacity_factor = {
|
| 52 |
+
'solar': solar_cf,
|
| 53 |
+
'onshore_wind': onshore_wind_cf,
|
| 54 |
+
'offshore_wind': offshore_wind_cf,
|
| 55 |
+
'river': river_cf
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
renewable_capacity_cost = {'solar': solar_cost, 'onshore_wind': onshore_wind_cost, 'offshore_wind': offshore_wind_cost, 'river': river_cost}
|
| 59 |
+
battery_cost_per_mwh = battery_cost
|
| 60 |
+
battery_efficiency = 0.9
|
| 61 |
+
|
| 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')
|
| 70 |
+
battery_capacity = pulp.LpVariable("battery_capacity", lowBound=0, cat='Continuous')
|
| 71 |
+
battery_charge = pulp.LpVariable.dicts("battery_charge", time_steps, lowBound=0, cat='Continuous')
|
| 72 |
+
battery_discharge = pulp.LpVariable.dicts("battery_discharge", time_steps, lowBound=0, cat='Continuous')
|
| 73 |
+
SOC = pulp.LpVariable.dicts("SOC", time_steps, lowBound=0, cat='Continuous')
|
| 74 |
+
|
| 75 |
+
model = pulp.LpProblem("EnergySystemOptimizationWithBattery", pulp.LpMinimize)
|
| 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:
|
| 90 |
+
model += SOC[t] == SOC[t - 1] + battery_charge[t] * battery_efficiency - battery_discharge[t] * (1 / battery_efficiency), f"SOCUpdate_{t}"
|
| 91 |
+
model += SOC[t] <= battery_capacity, f"SOCUpperBound_{t}"
|
| 92 |
+
|
| 93 |
+
# Capacity range constraints
|
| 94 |
+
model += renewable_capacity[('region1', 'solar')] >= solar_range[0]
|
| 95 |
+
model += renewable_capacity[('region1', 'solar')] <= solar_range[1]
|
| 96 |
+
model += renewable_capacity[('region1', 'onshore_wind')] >= wind_range[0]
|
| 97 |
+
model += renewable_capacity[('region1', 'onshore_wind')] <= wind_range[1]
|
| 98 |
+
model += renewable_capacity[('region1', 'offshore_wind')] >= offshore_wind_range[0]
|
| 99 |
+
model += renewable_capacity[('region1', 'offshore_wind')] <= offshore_wind_range[1]
|
| 100 |
+
model += renewable_capacity[('region1', 'river')] >= river_range[0]
|
| 101 |
+
model += renewable_capacity[('region1', 'river')] <= river_range[1]
|
| 102 |
+
|
| 103 |
+
# Solve the initial model to find the optimal solution
|
| 104 |
+
model.solve()
|
| 105 |
+
optimal_cost = pulp.value(model.objective)
|
| 106 |
+
|
| 107 |
+
# MGA: Generate alternative solutions
|
| 108 |
+
mga_models = []
|
| 109 |
+
alternative_solutions = []
|
| 110 |
+
for threshold in thresholds:
|
| 111 |
+
relaxed_cost = optimal_cost * (1 + threshold)
|
| 112 |
+
for tech in technologies:
|
| 113 |
+
# Minimize capacity of each technology
|
| 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()
|
| 125 |
+
if pulp.LpStatus[alt_model_min.status] == 'Optimal':
|
| 126 |
+
alternative_solutions.append({
|
| 127 |
+
'threshold': threshold,
|
| 128 |
+
'type': 'min',
|
| 129 |
+
'technology': tech,
|
| 130 |
+
'solution': {g: renewable_capacity[('region1', g)].varValue for g in technologies},
|
| 131 |
+
'battery_capacity': battery_capacity.varValue
|
| 132 |
+
})
|
| 133 |
+
|
| 134 |
+
# Maximize capacity of each technology
|
| 135 |
+
alt_model_max = pulp.LpProblem(f"AlternativeModel_Max_{tech}_{threshold}", pulp.LpMinimize)
|
| 136 |
+
alt_model_max += pulp.lpSum([renewable_capacity[(r, g)] * renewable_capacity_cost[g]
|
| 137 |
+
for r in regions for g in technologies]) + battery_capacity * battery_cost_per_mwh <= relaxed_cost
|
| 138 |
+
|
| 139 |
+
# Copy original constraints with unique names
|
| 140 |
+
for name, constraint in model.constraints.items():
|
| 141 |
+
alt_model_max += constraint.copy(), f"{name}_max_{tech}_{threshold}"
|
| 142 |
+
|
| 143 |
+
# Maximize the capacity of the selected technology
|
| 144 |
+
alt_model_max += -renewable_capacity[('region1', tech)], f"Maximize_{tech}_Capacity"
|
| 145 |
+
alt_model_max.solve()
|
| 146 |
+
if pulp.LpStatus[alt_model_max.status] == 'Optimal':
|
| 147 |
+
alternative_solutions.append({
|
| 148 |
+
'threshold': threshold,
|
| 149 |
+
'type': 'max',
|
| 150 |
+
'technology': tech,
|
| 151 |
+
'solution': {g: renewable_capacity[('region1', g)].varValue for g in technologies},
|
| 152 |
+
'battery_capacity': battery_capacity.varValue
|
| 153 |
+
})
|
| 154 |
+
|
| 155 |
+
return alternative_solutions
|
| 156 |
|
| 157 |
# Streamlit UI setup
|
| 158 |
st.set_page_config(page_title='Renewable Energy System Optimization with MGA', layout='wide')
|