Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Environment/helper/configuration/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def __init__(self):
energy_prices = np.append(energy_prices, np.array([power[i], prices[i]]))
self.energy_prices = energy_prices.reshape(len(prices), 2)
self._vehicle_configs = {}
self.dynamic_pricing = True
self.dynamic_pricing = False

if mode == "tra":
self.capacity_pricing = False
Expand Down
2 changes: 2 additions & 0 deletions Learning_agents/Learning_Pricing.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
SUMMER_END = Configuration.instance().SUMMER_END
POST_FIX = Configuration.instance().POST_FIX

Configuration.instance().dynamic_pricing = True

evaluate_after_training = Configuration.instance().evaluation_after_training
number_of_chargers = 200
PV_CAPA = Configuration.instance().PV
Expand Down
118 changes: 118 additions & 0 deletions Operations/Operator_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# utilities.py

def get_exp_free_grid_capacity_utility(
current_time,
sim_time,
planning_interval,
num_lookahead_planning_periods,
num_lookback_periods,
baseload,
non_dispatchable_generator,
electric_storage,
charging_strategy,
charging_hub,
grid_capa
):
final_time = min(
sim_time,
round(current_time + planning_interval * num_lookahead_planning_periods),
)

periods = []
t = current_time
while t < final_time:
periods.append(t)
t += planning_interval

free_capa_list_actual = []
base_load_list = []
generation_list = []
free_capa_list_predicted = []

for t in periods:
# ACTUAL
baseload_max = max(
baseload.loc[t : t + planning_interval - 1]["load_kw_rescaled"]
)
generation_min = min(
non_dispatchable_generator.generation_profile_actual.loc[
t : t + planning_interval - 1
]["pv_generation"]
)
battery_max = min(
electric_storage.kW_discharge_peak,
(
(
electric_storage.SoC
- electric_storage.min_energy_stored_kWh
)
* (60 / planning_interval)
),
)
if charging_strategy in [
"dynamic",
"integrated_storage",
"online_multi_period",
]:
battery_max = 0

battery_usage = 0
if charging_hub.dynamic_pricing:
battery_usage = (
electric_storage.discharging_power
- electric_storage.charging_power
)

free_capa_list_actual.append(
grid_capa
- baseload_max
+ generation_min
+ battery_max
+ battery_usage
)

# PREDICTED
offset_period = num_lookback_periods
baseload_max_pred = max(
baseload.loc[
(t - offset_period):(t - offset_period) + (planning_interval - 1)
]["load_kw_rescaled"]
)
generation_min_pred = min(
non_dispatchable_generator.generation_profile_forecast.loc[
t : t + planning_interval - 1
]["pv_generation"]
)
battery_max = min(
electric_storage.kW_discharge_peak,
(
(
electric_storage.SoC
- electric_storage.min_energy_stored_kWh
)
* (60 / planning_interval)
),
)

free_capa_list_predicted.append(
grid_capa
- baseload_max_pred
+ generation_min_pred
+ battery_max
+ battery_usage
)

base_load_list.append(baseload_max_pred)
generation_list.append(generation_min_pred)

free_grid_capa_without_storage = (
free_capa_list_actual[0] - battery_max - battery_usage
)

return {
"free_grid_capa_actual": free_capa_list_actual,
"base_load_list": base_load_list,
"generation_list": generation_list,
"free_grid_capa_without_storage": free_grid_capa_without_storage,
"free_grid_capa_predicted": free_capa_list_predicted,
}
135 changes: 18 additions & 117 deletions Operations/operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import pandas as pd

from Operations.NonLinearAlgorithms import nonlinear_pricing
from Operations.Operator_utils import get_exp_free_grid_capacity_utility
from Utilities.RL_environments.rl_pricing_env import convert_to_vector


Expand Down Expand Up @@ -126,125 +127,25 @@ def get_exp_free_grid_capacity(self):
:param num_lookahead_periods: number of planning periods for which plan is created
:return:
"""
# while True:
current_time = self.env.now
sim_time = self.sim_time
final_time = min(
sim_time,
round(
current_time
+ self.planning_interval * self.num_lookahead_planning_periods
),
results = get_exp_free_grid_capacity_utility(
current_time=self.env.now,
sim_time=self.sim_time,
planning_interval=self.planning_interval,
num_lookahead_planning_periods=self.num_lookahead_planning_periods,
num_lookback_periods=self.num_lookback_periods,
baseload=self.baseload,
non_dispatchable_generator=self.non_dispatchable_generator,
electric_storage=self.electric_storage,
charging_strategy=self.charging_strategy,
charging_hub=self.charging_hub,
grid_capa=self.grid_capa,
)

# get periods in lookahead_window
periods = []
t = current_time
while t < final_time:
periods.append(t)
t += self.planning_interval

# get list of free grid capa
free_capa_list_actual = []
base_load_list = []
generation_list = []
free_capa_list_predicted = []

for t in periods:
# ACTUAL
baseload_max = max(
self.baseload.loc[t : t + self.planning_interval - 1][
"load_kw_rescaled"
]
)
self.baseload_min = min(
self.baseload.loc[t : t + self.planning_interval - 1][
"load_kw_rescaled"
]
)
self.baseload_max = baseload_max
generation_min = min(
self.non_dispatchable_generator.generation_profile_actual.loc[
t : t + self.planning_interval - 1
]["pv_generation"]
)
self.generation_min = generation_min
battery_max = min(
self.electric_storage.kW_discharge_peak,
(
(
self.electric_storage.SoC
- self.electric_storage.min_energy_stored_kWh
)
* (60 / self.planning_interval)
),
)

if self.charging_strategy in [
"dynamic",
"integrated_storage",
"online_multi_period",
]:
battery_max = 0
battery_usage = 0
if self.charging_hub.dynamic_pricing:

battery_usage = (
self.electric_storage.discharging_power
- self.electric_storage.charging_power
)
free_capa_list_actual.append(
self.grid_capa
- baseload_max
+ generation_min
+ battery_max
+ battery_usage
)
# PREDICTED
offset_period = (
self.num_lookback_periods
) # how many periods to go back for prediction, here we fix to 1 day
baseload_max_pred = max(
self.baseload.loc[
(t - offset_period) : (t - offset_period)
+ (self.planning_interval - 1)
]["load_kw_rescaled"]
)
generation_min_pred = min(
self.non_dispatchable_generator.generation_profile_forecast.loc[
t : t + self.planning_interval - 1
]["pv_generation"]
)
battery_max = min(
self.electric_storage.kW_discharge_peak,
(
(
self.electric_storage.SoC
- self.electric_storage.min_energy_stored_kWh
)
* (60 / self.planning_interval)
),
)
free_capa_list_predicted.append(
self.grid_capa
- baseload_max_pred
+ generation_min_pred
+ battery_max
+ battery_usage
)
base_load_list.append(baseload_max_pred)
generation_list.append(generation_min_pred)

# update free_grid_capa
self.free_grid_capa_actual = free_capa_list_actual
self.base_load_list = base_load_list
self.generation_list = generation_list
self.free_grid_capa_without_storage = (
free_capa_list_actual[0] - battery_max - battery_usage
)
self.free_grid_capa_predicted = free_capa_list_predicted
# return free_capa_list
# yield self.env.timeout(self.planning_period_length)
self.free_grid_capa_actual = results["free_grid_capa_actual"]
self.base_load_list = results["base_load_list"]
self.generation_list = results["generation_list"]
self.free_grid_capa_without_storage = results["free_grid_capa_without_storage"]
self.free_grid_capa_predicted = results["free_grid_capa_predicted"]

def get_available_battery_load(self):
"""
Expand Down
27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,29 @@ The following modules are included:
- **`Preferences` Module:** Initializes vehicle objects with respective charging and parking preferences (i.e., requests) based on empirical data
- **`Infrastructure` Module:** Initializes infrastructure objects (EV supply equipment (EVSE), connectors per each EVSE, grid connection capacity, on-site storage and on-site generation (PV))
- **`Operations` Module:** Conatain algorithms for assigning physical space (vehicle routing) and electrical capacity (vehicle charging) to individual vehicle objects based on a pre-defined charging policy
- **`Results` Module:** Monitors EVCC activity in pre-defined intervals and accounts costs. Includes plotting routines.
- **`Results` Module:** Monitors EVCC activity in pre-defined intervals and accounts costs. Includes plotting routines.

## 📦 Installation

This project uses [`uv`](https://github.com/astral-sh/uv), a modern and ultra-fast Python package manager compatible with pip.

### 1. Install `uv`

If you don’t have `uv` installed, run:

### Installation Steps

```bash
# Step 1: Install uv
pip install uv

# Step 2: Create a virtual environment
python -m venv .venv

# Step 3: Activate the environment
source .venv/bin/activate # On macOS/Linux
# or
.venv\Scripts\activate # On Windows

# Step 4: Install dependencies
uv pip install -r requirements.uv.txt
57 changes: 0 additions & 57 deletions requirements.txt

This file was deleted.