Skip to content

Commit

Permalink
Change config, add test for schedule consistency and slight changes o…
Browse files Browse the repository at this point in the history
…f station_optimization
  • Loading branch information
PaulScheerRLI committed Aug 9, 2023
1 parent 9767e93 commit 0f89841
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 4 deletions.
6 changes: 4 additions & 2 deletions data/examples/default_optimizer.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ exclusion_stations = []
# optimization will electrify these stations.
# if using inclusion stations, scenario should be rebased
inclusion_stations = []
standard_opp_station = {"type": "opps", "n_charging_stations": 200,"distance_transformer": 50}
standard_opp_station = {"type": "opps", "n_charging_stations": null}
# rotations which drop below this value are considered not electrified (default value is 0)
min_soc = 0.05

Expand All @@ -41,6 +41,7 @@ pickle_rebased_name = ""
# Should all rotations be rebased or can rotations which stay above the soc threshold be skipped?
run_only_neg = False
# Should only be opportunity vehicles be rebased, since this optimization is not meant for depot chargers
# The depot chargers will be added to the returned schedule in any case
run_only_oppb = True
# number of stations before optimal solution, where branch is checked for pruning
pruning_threshold = 3
Expand All @@ -64,7 +65,8 @@ estimation_threshold = 0.80


# Removing impossible rotations leads to a quick calculation estimating if rotations are impossible.impossible
# If they are deemed as impossible, they are not optimized but discarded
# If they are deemed as impossible, they are not optimized but discarded during optimization.
# They will be added to the returned schedule in any case.
remove_impossible_rotations = True
# Check if stations are mandatory for a fully electrified system. If they are, include them
check_for_must_stations = False
Expand Down
14 changes: 13 additions & 1 deletion simba/station_optimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""

from copy import deepcopy
import json
import sys
from pathlib import Path
Expand Down Expand Up @@ -101,6 +102,8 @@ def run_optimization(conf, sched=None, scen=None, args=None):
assert conf.args, error_message
sched, scen, args = opt_util.toolbox_from_pickle(conf.schedule, conf.scenario, conf.args)

original_schedule = deepcopy(sched)

# setup folders, paths and copy config
prepare_filesystem(args, conf)

Expand All @@ -118,8 +121,10 @@ def run_optimization(conf, sched=None, scen=None, args=None):

# filter out depot chargers if option is set
if conf.run_only_oppb:
optimizer.config.exclusion_rots = optimizer.config.exclusion_rots.union(
r for r in sched.rotations if "depb" in sched.rotations[r].charging_type)
sched.rotations = {r: sched.rotations[r] for r in sched.rotations
if "oppb" in sched.rotations[r].vehicle_id}
if "oppb" in sched.rotations[r].charging_type}
assert len(sched.rotations) > 0, "No rotations left after removing depot chargers"

# rebasing the scenario meaning simulating it again with SpiceEV and the given conditions of
Expand Down Expand Up @@ -187,6 +192,13 @@ def run_optimization(conf, sched=None, scen=None, args=None):

# Calculation with SpiceEV is more accurate and will show if the optimization is viable or not
logger.debug("Detailed calculation of optimized case as a complete scenario")

# Restore excluded rotations
for rotation_id in optimizer.config.exclusion_rots:
optimizer.schedule.rotations[rotation_id] = original_schedule.rotations[rotation_id]

# remove exclusion since internally these would not be simulated
optimizer.config.exclusion_rots = set()
_, __ = optimizer.preprocessing_scenario(
electrified_stations=ele_stations, run_only_neg=False)

Expand Down
35 changes: 34 additions & 1 deletion tests/test_station_optimization.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from copy import copy
from copy import copy, deepcopy
import json
from pathlib import Path
import pytest
Expand Down Expand Up @@ -124,6 +124,39 @@ def test_basic_optimization(self):
conf.solver = "spiceev"
opt_sched, opt_scen = run_optimization(conf, sched=sched, scen=scen, args=args)

def test_schedule_consistency(self):
""" Test if the optimization returns all rotations even when some filters are active"""
trips_file_name = "trips_for_optimizer.csv"
sched, scen, args = self.basic_run(trips_file_name)
config_path = example_root / "default_optimizer.cfg"
conf = opt_util.read_config(config_path)

sched_impossible = deepcopy(sched)
# Make a single trip impossible
next(iter(sched_impossible.rotations.values())).trips[0].distance = 99999999
sched_impossible.calculate_consumption()
scen = sched_impossible.run(args)

amount_rotations = len(sched_impossible.rotations)
conf.remove_impossible_rotations = True
conf.run_only_oppb = False
opt_sched, opt_scen = run_optimization(conf, sched=sched_impossible, scen=scen, args=args)
assert len(opt_sched.rotations) == amount_rotations

# set a single rotation to depot
next(iter(sched.rotations.values())).set_charging_type("depb")
# and run again to make everything consistent
scen = sched.run(args)

amount_rotations = len(sched.rotations)
conf.run_only_oppb = True
opt_sched, opt_scen = run_optimization(conf, sched=deepcopy(sched), scen=scen, args=args)
assert len(opt_sched.rotations) == amount_rotations

conf.run_only_oppb = False
opt_sched, opt_scen = run_optimization(conf, sched=deepcopy(sched), scen=scen, args=args)
assert len(opt_sched.rotations) == amount_rotations

def test_deep_optimization(self):
""" Check if deep analysis finds the prepared optimal solution for the test case.
Expand Down

0 comments on commit 0f89841

Please sign in to comment.