eflips-depot 4.3.19__tar.gz → 4.4.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of eflips-depot might be problematic. Click here for more details.
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/PKG-INFO +2 -1
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/api/__init__.py +19 -304
- eflips_depot-4.4.1/eflips/depot/api/private/depot.py +1036 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/api/private/results_to_database.py +2 -1
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/api/private/smart_charging.py +7 -6
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/api/private/util.py +3 -20
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/pyproject.toml +2 -1
- eflips_depot-4.3.19/eflips/depot/api/private/depot.py +0 -944
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/LICENSE.md +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/README.md +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/__init__.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/api/defaults/default_settings.json +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/api/private/__init__.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/configuration.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/depot.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/evaluation.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/filters.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/input_epex_power_price.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/layout_opt/__init__.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/layout_opt/doc/__init__.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/layout_opt/doc/direct_details.pdf +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/layout_opt/evaluation.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/layout_opt/opt_tools/__init__.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/layout_opt/opt_tools/crossover.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/layout_opt/opt_tools/fitness_c_urfd.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/layout_opt/opt_tools/fitness_util.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/layout_opt/opt_tools/init.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/layout_opt/opt_tools/mutation.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/layout_opt/optimize_c_urfd.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/layout_opt/packing.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/layout_opt/settings.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/layout_opt/template_creation.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/layout_opt/util.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/plots.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/processes.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/rating.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/resources.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/settings_config.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/simple_vehicle.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/simulation.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/smart_charging.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/standalone.py +0 -0
- {eflips_depot-4.3.19 → eflips_depot-4.4.1}/eflips/depot/validation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: eflips-depot
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.4.1
|
|
4
4
|
Summary: Depot Simulation for eFLIPS
|
|
5
5
|
Home-page: https://github.com/mpm-tu-berlin/eflips-depot
|
|
6
6
|
License: AGPL-3.0-or-later
|
|
@@ -18,6 +18,7 @@ Requires-Dist: eflips-model (>=5.0.0,<6.0.0)
|
|
|
18
18
|
Requires-Dist: pandas (>=2.1.4,<3.0.0)
|
|
19
19
|
Requires-Dist: scipy (>=1.13.1,<2.0.0)
|
|
20
20
|
Requires-Dist: simpy (>=4.0.1,<5.0.0)
|
|
21
|
+
Requires-Dist: tqdm (>=4.67.0,<5.0.0)
|
|
21
22
|
Requires-Dist: xlrd (<=1.2.0)
|
|
22
23
|
Requires-Dist: xlsxwriter (>=3.1.9,<4.0.0)
|
|
23
24
|
Project-URL: Repository, https://github.com/mpm-tu-berlin/eflips-depot
|
|
@@ -30,25 +30,23 @@ import logging
|
|
|
30
30
|
import os
|
|
31
31
|
import warnings
|
|
32
32
|
from collections import OrderedDict
|
|
33
|
-
from dataclasses import dataclass
|
|
34
33
|
from datetime import timedelta
|
|
35
34
|
from enum import Enum
|
|
36
35
|
from math import ceil
|
|
37
|
-
from typing import Any, Dict, Optional, Union
|
|
36
|
+
from typing import Any, Dict, Optional, Union
|
|
38
37
|
|
|
39
38
|
import sqlalchemy.orm
|
|
40
39
|
from eflips.model import (
|
|
41
40
|
Area,
|
|
42
|
-
AreaType,
|
|
43
41
|
Depot,
|
|
44
42
|
Event,
|
|
45
43
|
EventType,
|
|
46
44
|
Rotation,
|
|
47
45
|
Scenario,
|
|
48
|
-
Station,
|
|
49
46
|
Trip,
|
|
50
47
|
Vehicle,
|
|
51
48
|
VehicleType,
|
|
49
|
+
AreaType,
|
|
52
50
|
)
|
|
53
51
|
from sqlalchemy.orm import Session
|
|
54
52
|
|
|
@@ -58,14 +56,10 @@ from eflips.depot import (
|
|
|
58
56
|
SimulationHost,
|
|
59
57
|
)
|
|
60
58
|
from eflips.depot.api.private.depot import (
|
|
61
|
-
_generate_all_direct_depot,
|
|
62
|
-
create_simple_depot,
|
|
63
59
|
delete_depots,
|
|
64
60
|
depot_to_template,
|
|
65
61
|
group_rotations_by_start_end_stop,
|
|
66
|
-
|
|
67
|
-
real_peak_area_utilization,
|
|
68
|
-
real_peak_vehicle_count,
|
|
62
|
+
generate_depot,
|
|
69
63
|
)
|
|
70
64
|
from eflips.depot.api.private.results_to_database import (
|
|
71
65
|
get_finished_schedules_per_vehicle,
|
|
@@ -397,297 +391,9 @@ def simple_consumption_simulation(
|
|
|
397
391
|
session.add(current_event)
|
|
398
392
|
|
|
399
393
|
|
|
400
|
-
@dataclass
|
|
401
|
-
class DepotConfiguration:
|
|
402
|
-
charging_power: float
|
|
403
|
-
line_counts: Dict[VehicleType, int]
|
|
404
|
-
direct_counts: Dict[VehicleType, int]
|
|
405
|
-
clean_duration: int
|
|
406
|
-
num_clean_areas: int
|
|
407
|
-
num_shunting_areas: int
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
def generate_realistic_depot_layout(
|
|
411
|
-
scenario: Union[Scenario, int, Any],
|
|
412
|
-
charging_power: float,
|
|
413
|
-
database_url: Optional[str] = None,
|
|
414
|
-
delete_existing_depot: bool = False,
|
|
415
|
-
line_length: int = 8,
|
|
416
|
-
CLEAN_DURATION: int = 10 * 60, # 10 minutes in seconds
|
|
417
|
-
shunting_duration: timedelta = timedelta(minutes=5),
|
|
418
|
-
) -> DepotConfiguration:
|
|
419
|
-
"""
|
|
420
|
-
Creates a realistic depot layout for the scenario.
|
|
421
|
-
|
|
422
|
-
This is done by starting with an all direct depot layout,
|
|
423
|
-
looking at the vehicle count, creating an "all line" layout and then turning some of these lines into direct
|
|
424
|
-
areas until the vehicle count of the all direct depot layout (+ an allowance) is reached.
|
|
425
|
-
|
|
426
|
-
:param scenario: The scenario for which the depot layout should be generated.
|
|
427
|
-
:param charging_power: The charging power for the line areas in kW.
|
|
428
|
-
:param database_url: An optional database URL. If no database URL is passed and the `scenario` parameter is not a
|
|
429
|
-
:class:`eflips.model.Scenario` object, the environment variable `DATABASE_URL` must be set to a valid database
|
|
430
|
-
URL.
|
|
431
|
-
:param delete_existing_depot: Whether to delete an existing depot layout for this scenario. If set to False and a
|
|
432
|
-
depot layout already exists, a ValueError will be raised.
|
|
433
|
-
:param charging_power_direct: The charging power for the direct areas in kW. If not set, the charging power for the
|
|
434
|
-
line areas will be used.
|
|
435
|
-
|
|
436
|
-
:return: None. The depot layout will be added to the database.
|
|
437
|
-
"""
|
|
438
|
-
logging.basicConfig(level=logging.DEBUG) # TODO: Remove this line
|
|
439
|
-
logger = logging.getLogger(__name__)
|
|
440
|
-
|
|
441
|
-
with create_session(scenario, database_url) as (session, scenario):
|
|
442
|
-
# STEP 0: Delete existing depots if asked to, raise an Exception otherwise
|
|
443
|
-
if session.query(Depot).filter(Depot.scenario_id == scenario.id).count() != 0:
|
|
444
|
-
if delete_existing_depot is False:
|
|
445
|
-
raise ValueError("Depot already exists.")
|
|
446
|
-
delete_depots(scenario, session)
|
|
447
|
-
|
|
448
|
-
# Make sure that the consumption simulation has been run
|
|
449
|
-
if session.query(Event).filter(Event.scenario_id == scenario.id).count() == 0:
|
|
450
|
-
raise ValueError(
|
|
451
|
-
"No consumption simulation found. Please run the consumption simulation first."
|
|
452
|
-
)
|
|
453
|
-
|
|
454
|
-
# STEP 2: Identify the spots where we will put a depot
|
|
455
|
-
# Identify all the spots that serve as start *and* end of a rotation
|
|
456
|
-
depot_stations_and_vehicle_types = group_rotations_by_start_end_stop(
|
|
457
|
-
scenario.id, session
|
|
458
|
-
)
|
|
459
|
-
|
|
460
|
-
# STEP 3: Put "all direct" depots at these spots and find the vehicle counts
|
|
461
|
-
depot_stations = []
|
|
462
|
-
vehicle_type_rotation_dict_by_station: Dict[
|
|
463
|
-
Station, Dict[VehicleType, List[Rotation]]
|
|
464
|
-
] = dict()
|
|
465
|
-
for (
|
|
466
|
-
first_last_stop_tup,
|
|
467
|
-
vehicle_type_rotation_dict,
|
|
468
|
-
) in depot_stations_and_vehicle_types.items():
|
|
469
|
-
first_stop, last_stop = first_last_stop_tup
|
|
470
|
-
if first_stop != last_stop:
|
|
471
|
-
raise ValueError("First and last stop of a rotation are not the same.")
|
|
472
|
-
depot_stations.append(first_stop)
|
|
473
|
-
vehicle_type_rotation_dict_by_station[
|
|
474
|
-
first_stop
|
|
475
|
-
] = vehicle_type_rotation_dict
|
|
476
|
-
|
|
477
|
-
del first_last_stop_tup, vehicle_type_rotation_dict
|
|
478
|
-
|
|
479
|
-
all_direct_counts: Dict[
|
|
480
|
-
Station, Dict[VehicleType, int]
|
|
481
|
-
] = vehicle_counts_for_direct_layout(
|
|
482
|
-
CLEAN_DURATION=CLEAN_DURATION,
|
|
483
|
-
charging_power=charging_power,
|
|
484
|
-
stations=depot_stations,
|
|
485
|
-
scenario=scenario,
|
|
486
|
-
session=session,
|
|
487
|
-
vehicle_type_dict_by_station=vehicle_type_rotation_dict_by_station,
|
|
488
|
-
shunting_duration=shunting_duration,
|
|
489
|
-
)
|
|
490
|
-
|
|
491
|
-
# STEP 4: Run the simulation with depots that also have a lot of line areas
|
|
492
|
-
# I know I could probably skip step 3 and go directly to step 4, but that's how I got it working and
|
|
493
|
-
# I'm too lazy to change it now
|
|
494
|
-
|
|
495
|
-
for station, vehicle_type_and_counts in all_direct_counts.items():
|
|
496
|
-
line_counts: Dict[VehicleType, int] = dict()
|
|
497
|
-
direct_counts: Dict[VehicleType, int] = dict()
|
|
498
|
-
|
|
499
|
-
# Create a Depot that has a lot of line areas as well
|
|
500
|
-
for vehicle_type, count in vehicle_type_and_counts.items():
|
|
501
|
-
line_counts[vehicle_type] = ceil(count / line_length)
|
|
502
|
-
direct_counts[vehicle_type] = ceil(count) + 500
|
|
503
|
-
|
|
504
|
-
# Run the simulation with this depot
|
|
505
|
-
generate_line_depot_layout(
|
|
506
|
-
CLEAN_DURATION=CLEAN_DURATION,
|
|
507
|
-
charging_power=charging_power,
|
|
508
|
-
station=station,
|
|
509
|
-
scenario=scenario,
|
|
510
|
-
session=session,
|
|
511
|
-
direct_counts=direct_counts,
|
|
512
|
-
line_counts=line_counts,
|
|
513
|
-
line_length=line_length,
|
|
514
|
-
vehicle_type_rotation_dict=vehicle_type_rotation_dict_by_station[
|
|
515
|
-
station
|
|
516
|
-
],
|
|
517
|
-
shunting_duration=shunting_duration,
|
|
518
|
-
)
|
|
519
|
-
|
|
520
|
-
# Simulate the depot
|
|
521
|
-
# We will not be using add_evaluation_to_database instead taking the vehicle counts directly from the `ev` object
|
|
522
|
-
logger.info("Simulating the scenario")
|
|
523
|
-
logger.info("1/2: Initializing the simulation host")
|
|
524
|
-
simulation_host = init_simulation(
|
|
525
|
-
scenario=scenario,
|
|
526
|
-
session=session,
|
|
527
|
-
)
|
|
528
|
-
logger.info("2/2: Running the simulation")
|
|
529
|
-
depot_evaluations = run_simulation(simulation_host)
|
|
530
|
-
|
|
531
|
-
# We need to remember the depot-id-station mapping
|
|
532
|
-
depot_id_station_mapping: Dict[str, Station] = dict()
|
|
533
|
-
for depot_id_as_str, ev in depot_evaluations.items():
|
|
534
|
-
station = (
|
|
535
|
-
session.query(Station)
|
|
536
|
-
.join(Depot)
|
|
537
|
-
.filter(Depot.id == int(depot_id_as_str))
|
|
538
|
-
.one()
|
|
539
|
-
)
|
|
540
|
-
depot_id_station_mapping[depot_id_as_str] = station
|
|
541
|
-
|
|
542
|
-
# Delete the old depot
|
|
543
|
-
delete_depots(scenario, session)
|
|
544
|
-
|
|
545
|
-
for depot_id_as_str, ev in depot_evaluations.items():
|
|
546
|
-
assert isinstance(ev, DepotEvaluation)
|
|
547
|
-
|
|
548
|
-
if False:
|
|
549
|
-
ev.path_results = depot_id_as_str
|
|
550
|
-
os.makedirs(depot_id_as_str, exist_ok=True)
|
|
551
|
-
|
|
552
|
-
ev.vehicle_periods(
|
|
553
|
-
periods={
|
|
554
|
-
"depot general": "darkgray",
|
|
555
|
-
"park": "lightgray",
|
|
556
|
-
"Arrival Cleaning": "steelblue",
|
|
557
|
-
"Charging": "forestgreen",
|
|
558
|
-
"Standby Pre-departure": "darkblue",
|
|
559
|
-
"precondition": "black",
|
|
560
|
-
"trip": "wheat",
|
|
561
|
-
},
|
|
562
|
-
save=True,
|
|
563
|
-
show=False,
|
|
564
|
-
formats=(
|
|
565
|
-
"pdf",
|
|
566
|
-
"png",
|
|
567
|
-
),
|
|
568
|
-
show_total_power=True,
|
|
569
|
-
show_annotates=True,
|
|
570
|
-
)
|
|
571
|
-
|
|
572
|
-
# Find the actual utilization.
|
|
573
|
-
utilization: Dict[str, int] = real_peak_area_utilization(ev)
|
|
574
|
-
utilization = {
|
|
575
|
-
session.query(VehicleType).filter(VehicleType.id == int(k)).one(): v
|
|
576
|
-
for k, v in utilization.items()
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
# Turn utilization into a two dictionaries, one for line areas and one for direct areas
|
|
580
|
-
for vehicle_type, counts in utilization.items():
|
|
581
|
-
line_counts[vehicle_type] = counts[AreaType.LINE]
|
|
582
|
-
direct_counts[vehicle_type] = counts[AreaType.DIRECT_ONESIDE] + 100
|
|
583
|
-
|
|
584
|
-
station = depot_id_station_mapping[depot_id_as_str]
|
|
585
|
-
|
|
586
|
-
generate_line_depot_layout(
|
|
587
|
-
CLEAN_DURATION=CLEAN_DURATION,
|
|
588
|
-
charging_power=charging_power,
|
|
589
|
-
station=station,
|
|
590
|
-
scenario=scenario,
|
|
591
|
-
session=session,
|
|
592
|
-
direct_counts=direct_counts,
|
|
593
|
-
line_counts=line_counts,
|
|
594
|
-
line_length=line_length,
|
|
595
|
-
vehicle_type_rotation_dict=vehicle_type_rotation_dict_by_station[
|
|
596
|
-
station
|
|
597
|
-
],
|
|
598
|
-
shunting_duration=shunting_duration,
|
|
599
|
-
)
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
def vehicle_counts_for_direct_layout(
|
|
603
|
-
CLEAN_DURATION: int,
|
|
604
|
-
charging_power: float,
|
|
605
|
-
stations: List[Station],
|
|
606
|
-
scenario: Scenario,
|
|
607
|
-
session: sqlalchemy.orm.session.Session,
|
|
608
|
-
vehicle_type_dict_by_station: Dict[Station, Dict[VehicleType, List[Rotation]]],
|
|
609
|
-
shunting_duration: timedelta = timedelta(minutes=5),
|
|
610
|
-
) -> Dict[Station, Dict[VehicleType, int]]:
|
|
611
|
-
"""
|
|
612
|
-
Generate a simple depot, simulate it and return the number of vehicles for each vehicle type.
|
|
613
|
-
|
|
614
|
-
Do this for each depot station in the scenario.
|
|
615
|
-
:param CLEAN_DURATION: The duration of the cleaning process in seconds.
|
|
616
|
-
:param charging_power: The charging power of the charging area in kW.
|
|
617
|
-
:param station: The stop where the depot is located.
|
|
618
|
-
:param scenario: The scenario for which the depot layout should be generated.
|
|
619
|
-
:param session: The SQLAlchemy session object.
|
|
620
|
-
:param vehicle_type_dict: A dictionary with vehicle types as keys and rotations as values.
|
|
621
|
-
:return: A dictionary with vehicle types as keys and the number of vehicles as values.
|
|
622
|
-
"""
|
|
623
|
-
logger = logging.getLogger(__name__)
|
|
624
|
-
|
|
625
|
-
for station in stations:
|
|
626
|
-
logger.info(f"Generating all direct depot layout at {station.name}")
|
|
627
|
-
# Generate the depot
|
|
628
|
-
direct_counts = {}
|
|
629
|
-
line_counts = {}
|
|
630
|
-
for vehicle_type, rotations in vehicle_type_dict_by_station[station].items():
|
|
631
|
-
direct_counts[vehicle_type] = len(rotations)
|
|
632
|
-
line_counts[vehicle_type] = 0
|
|
633
|
-
|
|
634
|
-
generate_line_depot_layout(
|
|
635
|
-
CLEAN_DURATION=CLEAN_DURATION,
|
|
636
|
-
charging_power=charging_power,
|
|
637
|
-
station=station,
|
|
638
|
-
scenario=scenario,
|
|
639
|
-
session=session,
|
|
640
|
-
direct_counts=direct_counts,
|
|
641
|
-
line_counts=line_counts,
|
|
642
|
-
line_length=8, # We don't care about the line length here
|
|
643
|
-
vehicle_type_rotation_dict=vehicle_type_dict_by_station[station],
|
|
644
|
-
shunting_duration=shunting_duration,
|
|
645
|
-
)
|
|
646
|
-
|
|
647
|
-
# Simulate the scenario
|
|
648
|
-
# We will not be using add_evaluation_to_database instead taking the vehicle counts directly from the `ev` object
|
|
649
|
-
logger.info("Simulating the scenario")
|
|
650
|
-
logger.info("1/2: Initializing the simulation host")
|
|
651
|
-
simulation_host = init_simulation(
|
|
652
|
-
scenario=scenario,
|
|
653
|
-
session=session,
|
|
654
|
-
)
|
|
655
|
-
logger.info("2/2: Running the simulation")
|
|
656
|
-
depot_evaluations = run_simulation(simulation_host)
|
|
657
|
-
|
|
658
|
-
assert len(depot_evaluations) == len(stations)
|
|
659
|
-
depot_evaluations: Dict[str, DepotEvaluation]
|
|
660
|
-
|
|
661
|
-
ret_val: Dict[Station, Dict[VehicleType, int]] = dict()
|
|
662
|
-
|
|
663
|
-
for depot_id_as_str, ev in depot_evaluations.items():
|
|
664
|
-
assert isinstance(ev, DepotEvaluation)
|
|
665
|
-
counts: Dict[str, int] = real_peak_vehicle_count(ev)
|
|
666
|
-
# The key of the dictionary is the vehicle type ID as a string. We need to convert it to a vehicle type object
|
|
667
|
-
vehicle_type_dict = {
|
|
668
|
-
session.query(VehicleType).filter(VehicleType.id == int(k)).one(): v
|
|
669
|
-
for k, v in counts.items()
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
# Find the station object
|
|
673
|
-
station = (
|
|
674
|
-
session.query(Station)
|
|
675
|
-
.join(Depot)
|
|
676
|
-
.filter(Depot.id == int(depot_id_as_str))
|
|
677
|
-
.one()
|
|
678
|
-
)
|
|
679
|
-
|
|
680
|
-
ret_val[station] = vehicle_type_dict
|
|
681
|
-
|
|
682
|
-
# Delete the old depots
|
|
683
|
-
delete_depots(scenario, session)
|
|
684
|
-
|
|
685
|
-
return ret_val
|
|
686
|
-
|
|
687
|
-
|
|
688
394
|
def generate_depot_layout(
|
|
689
395
|
scenario: Union[Scenario, int, Any],
|
|
690
|
-
charging_power: float =
|
|
396
|
+
charging_power: float = 90,
|
|
691
397
|
database_url: Optional[str] = None,
|
|
692
398
|
delete_existing_depot: bool = False,
|
|
693
399
|
) -> None:
|
|
@@ -720,8 +426,6 @@ def generate_depot_layout(
|
|
|
720
426
|
|
|
721
427
|
:return: None. The depot layout will be added to the database.
|
|
722
428
|
"""
|
|
723
|
-
CLEAN_DURATION = 30 * 60 # 30 minutes in seconds
|
|
724
|
-
|
|
725
429
|
with create_session(scenario, database_url) as (session, scenario):
|
|
726
430
|
# Handles existing depot
|
|
727
431
|
if session.query(Depot).filter(Depot.scenario_id == scenario.id).count() != 0:
|
|
@@ -737,13 +441,24 @@ def generate_depot_layout(
|
|
|
737
441
|
first_stop, last_stop = first_last_stop_tup
|
|
738
442
|
if first_stop != last_stop:
|
|
739
443
|
raise ValueError("First and last stop of a rotation are not the same.")
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
444
|
+
|
|
445
|
+
# Create one direct slot for each rotation (it's way too much, but should work)
|
|
446
|
+
vt_capacity_dict: Dict[VehicleType, Dict[AreaType, None | int]] = {}
|
|
447
|
+
for vehicle_type, rotations in vehicle_type_dict.items():
|
|
448
|
+
rotation_count = len(rotations)
|
|
449
|
+
vt_capacity_dict[vehicle_type] = {
|
|
450
|
+
AreaType.LINE: None,
|
|
451
|
+
AreaType.DIRECT_ONESIDE: rotation_count,
|
|
452
|
+
AreaType.DIRECT_TWOSIDE: None,
|
|
453
|
+
}
|
|
454
|
+
generate_depot(
|
|
455
|
+
vt_capacity_dict,
|
|
743
456
|
first_stop,
|
|
744
457
|
scenario,
|
|
745
458
|
session,
|
|
746
|
-
|
|
459
|
+
charging_power=charging_power,
|
|
460
|
+
num_shunting_slots=max(rotation_count // 10, 1),
|
|
461
|
+
num_cleaning_slots=max(rotation_count // 10, 1),
|
|
747
462
|
)
|
|
748
463
|
|
|
749
464
|
|