eflips-depot 4.9.1__tar.gz → 4.10.0__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.

Files changed (42) hide show
  1. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/PKG-INFO +1 -1
  2. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/api/__init__.py +147 -10
  3. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/api/private/depot.py +2 -1
  4. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/pyproject.toml +1 -1
  5. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/LICENSE.md +0 -0
  6. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/README.md +0 -0
  7. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/__init__.py +0 -0
  8. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/api/defaults/default_settings.json +0 -0
  9. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/api/private/__init__.py +0 -0
  10. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/api/private/consumption.py +0 -0
  11. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/api/private/results_to_database.py +0 -0
  12. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/api/private/util.py +0 -0
  13. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/configuration.py +0 -0
  14. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/depot.py +0 -0
  15. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/evaluation.py +0 -0
  16. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/filters.py +0 -0
  17. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/input_epex_power_price.py +0 -0
  18. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/layout_opt/__init__.py +0 -0
  19. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/layout_opt/doc/__init__.py +0 -0
  20. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/layout_opt/doc/direct_details.pdf +0 -0
  21. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/layout_opt/evaluation.py +0 -0
  22. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/layout_opt/opt_tools/__init__.py +0 -0
  23. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/layout_opt/opt_tools/crossover.py +0 -0
  24. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/layout_opt/opt_tools/fitness_c_urfd.py +0 -0
  25. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/layout_opt/opt_tools/fitness_util.py +0 -0
  26. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/layout_opt/opt_tools/init.py +0 -0
  27. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/layout_opt/opt_tools/mutation.py +0 -0
  28. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/layout_opt/optimize_c_urfd.py +0 -0
  29. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/layout_opt/packing.py +0 -0
  30. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/layout_opt/settings.py +0 -0
  31. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/layout_opt/template_creation.py +0 -0
  32. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/layout_opt/util.py +0 -0
  33. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/plots.py +0 -0
  34. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/processes.py +0 -0
  35. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/rating.py +0 -0
  36. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/resources.py +0 -0
  37. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/settings_config.py +0 -0
  38. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/simple_vehicle.py +0 -0
  39. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/simulation.py +0 -0
  40. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/smart_charging.py +0 -0
  41. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/standalone.py +0 -0
  42. {eflips_depot-4.9.1 → eflips_depot-4.10.0}/eflips/depot/validation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: eflips-depot
3
- Version: 4.9.1
3
+ Version: 4.10.0
4
4
  Summary: Depot Simulation for eFLIPS
5
5
  License: AGPL-3.0-or-later
6
6
  Author: Enrico Lauth
@@ -49,6 +49,8 @@ from eflips.model import (
49
49
  AreaType,
50
50
  ChargeType,
51
51
  Route,
52
+ ConsistencyWarning,
53
+ Station,
52
54
  )
53
55
  from sqlalchemy.orm import Session
54
56
 
@@ -67,6 +69,7 @@ from eflips.depot.api.private.depot import (
67
69
  depot_to_template,
68
70
  group_rotations_by_start_end_stop,
69
71
  generate_depot,
72
+ depot_smallest_possible_size,
70
73
  )
71
74
  from eflips.depot.api.private.results_to_database import (
72
75
  get_finished_schedules_per_vehicle,
@@ -492,19 +495,14 @@ def generate_depot_layout(
492
495
 
493
496
  # Create one direct slot for each rotation (it's way too much, but should work)
494
497
  vt_capacity_dict: Dict[VehicleType, Dict[AreaType, None | int]] = {}
498
+ rotation_count_depot = 0
495
499
  for vehicle_type, rotations in vehicle_type_dict.items():
496
- rotation_count = len(rotations)
497
500
  vt_capacity_dict[vehicle_type] = {
498
501
  AreaType.LINE: None,
499
- AreaType.DIRECT_ONESIDE: rotation_count,
502
+ AreaType.DIRECT_ONESIDE: len(rotations),
500
503
  AreaType.DIRECT_TWOSIDE: None,
501
504
  }
502
-
503
- total_rotation_count = (
504
- session.query(Rotation)
505
- .filter(Rotation.scenario_id == scenario.id)
506
- .count()
507
- )
505
+ rotation_count_depot += len(rotations)
508
506
 
509
507
  generate_depot(
510
508
  vt_capacity_dict,
@@ -512,8 +510,8 @@ def generate_depot_layout(
512
510
  scenario,
513
511
  session,
514
512
  charging_power=charging_power,
515
- num_shunting_slots=max(total_rotation_count // 10, 1),
516
- num_cleaning_slots=max(total_rotation_count // 10, 1),
513
+ num_shunting_slots=max(rotation_count_depot // 10, 1),
514
+ num_cleaning_slots=max(rotation_count_depot // 10, 1),
517
515
  )
518
516
 
519
517
 
@@ -1097,3 +1095,142 @@ def add_evaluation_to_database(
1097
1095
  # Postprocessing of events
1098
1096
  update_vehicle_in_rotation(session, scenario, list_of_assigned_schedules)
1099
1097
  update_waiting_events(session, scenario, waiting_area_id)
1098
+
1099
+
1100
+ def generate_depot_optimal_size(
1101
+ scenario: Scenario,
1102
+ standard_block_length: int = 6,
1103
+ charging_power: float = 90,
1104
+ database_url: Optional[str] = None,
1105
+ delete_existing_depot: bool = False,
1106
+ ) -> None:
1107
+ """
1108
+ Generates an optimal depot layout with the smallest possible size for each depot in the scenario. Line charging areas
1109
+ with given block length area preferred. The existing depot will be deleted if `delete_existing_depot` is set to True.
1110
+
1111
+ :param scenario: A :class:`eflips.model.Scenario` object containing the input data for the simulation.
1112
+ :param standard_block_length: The standard block length for the depot layout in meters. Default is 6.
1113
+ :param charging_power: The charging power of the charging area in kW. Default is 90.
1114
+ :param database_url: An optional database URL. Used if no database url is given by the environment variable.
1115
+ :param delete_existing_depot: If there is already a depot existing in this scenario, set True to delete this
1116
+ existing depot. Set to False and a ValueError will be raised if there is a depot in this scenario.
1117
+
1118
+ :return: None. The depot layout will be added to the database.
1119
+
1120
+ """
1121
+
1122
+ logger = logging.getLogger(__name__)
1123
+
1124
+ with create_session(scenario, database_url) as (session, scenario):
1125
+ # Delete all vehicles and events, also disconnect the vehicles from the rotations
1126
+ rotation_q = session.query(Rotation).filter(Rotation.scenario_id == scenario.id)
1127
+ rotation_q.update({"vehicle_id": None})
1128
+ session.query(Event).filter(Event.scenario_id == scenario.id).delete()
1129
+ session.query(Vehicle).filter(Vehicle.scenario_id == scenario.id).delete()
1130
+
1131
+ # Handles existing depot
1132
+ if session.query(Depot).filter(Depot.scenario_id == scenario.id).count() != 0:
1133
+ if delete_existing_depot is False:
1134
+ raise ValueError("Depot already exists.")
1135
+
1136
+ delete_depots(scenario, session)
1137
+
1138
+ # Temporary workaround to set vehicle energy consumption manually
1139
+ # TODO: Replace by "use DS consumption if LUT"
1140
+ for vehicle_type in (
1141
+ session.query(VehicleType)
1142
+ .filter(VehicleType.scenario_id == scenario.id)
1143
+ .all()
1144
+ ):
1145
+ vehicle_type.consumption = 2.0
1146
+ vehicle_type.vehicle_classes = []
1147
+
1148
+ ##### Step 0: Consumption Simulation #####
1149
+ # Run the consumption simulation for all depots
1150
+ simple_consumption_simulation(scenario, initialize_vehicles=True)
1151
+
1152
+ ##### Step 1: Find all potential depots #####
1153
+ # These are all the spots where a rotation starts and end
1154
+ warnings.simplefilter("ignore", category=ConsistencyWarning)
1155
+ warnings.simplefilter("ignore", category=UserWarning)
1156
+
1157
+ depot_capacities_for_scenario: Dict[
1158
+ Station, Dict[VehicleType, Dict[AreaType, int]]
1159
+ ] = {}
1160
+
1161
+ num_rotations_for_scenario: Dict[Station, int] = {}
1162
+
1163
+ for (
1164
+ first_last_stop_tup,
1165
+ vehicle_type_dict,
1166
+ ) in group_rotations_by_start_end_stop(scenario.id, session).items():
1167
+ first_stop, last_stop = first_last_stop_tup
1168
+ if first_stop != last_stop:
1169
+ raise ValueError("First and last stop of a rotation are not the same.")
1170
+
1171
+ station = first_stop
1172
+ rotation_count_depot = sum(
1173
+ len(rotations) for vehicle_type, rotations in vehicle_type_dict.items()
1174
+ )
1175
+
1176
+ savepoint = session.begin_nested()
1177
+ try:
1178
+ # (Temporarily) Delete all rotations not starting or ending at the station
1179
+ logger.debug(
1180
+ f"Deleting all rotations not starting or ending at {station.name}"
1181
+ )
1182
+ all_rot_for_scenario = (
1183
+ session.query(Rotation)
1184
+ .filter(Rotation.scenario_id == scenario.id)
1185
+ .all()
1186
+ )
1187
+ to_delete = []
1188
+ for rot in all_rot_for_scenario:
1189
+ first_stop = rot.trips[0].route.departure_station
1190
+ if first_stop != station:
1191
+ for trip in rot.trips:
1192
+ for stop_time in trip.stop_times:
1193
+ to_delete.append(stop_time)
1194
+ for event in trip.events:
1195
+ to_delete.append(event)
1196
+ to_delete.append(trip)
1197
+ to_delete.append(rot)
1198
+ for obj in to_delete:
1199
+ session.flush()
1200
+ session.delete(obj)
1201
+ session.flush()
1202
+
1203
+ logger.info(f"Generating depot layout for station {station.name}")
1204
+ vt_capacities_for_station = depot_smallest_possible_size(
1205
+ station,
1206
+ scenario,
1207
+ session,
1208
+ standard_block_length,
1209
+ charging_power,
1210
+ )
1211
+
1212
+ depot_capacities_for_scenario[station] = vt_capacities_for_station
1213
+ num_rotations_for_scenario[station] = rotation_count_depot
1214
+ finally:
1215
+ savepoint.rollback()
1216
+
1217
+ # create depot with the calculated area sizes
1218
+
1219
+ for depot_station, capacities in depot_capacities_for_scenario.items():
1220
+ generate_depot(
1221
+ capacities,
1222
+ depot_station,
1223
+ scenario,
1224
+ session,
1225
+ standard_block_length=standard_block_length,
1226
+ charging_power=charging_power,
1227
+ num_shunting_slots=num_rotations_for_scenario[depot_station] // 10,
1228
+ num_cleaning_slots=num_rotations_for_scenario[depot_station] // 10,
1229
+ )
1230
+
1231
+ # Delete all vehicles and events again. Only depot layout is kept
1232
+
1233
+ rotation_q = session.query(Rotation).filter(Rotation.scenario_id == scenario.id)
1234
+ rotation_q.update({"vehicle_id": None})
1235
+ session.query(Event).filter(Event.scenario_id == scenario.id).delete()
1236
+ session.query(Vehicle).filter(Vehicle.scenario_id == scenario.id).delete()
@@ -1070,7 +1070,8 @@ def depot_smallest_possible_size(
1070
1070
  logger.debug(
1071
1071
  f"Vehicle count for {vt.name} in {amount_of_line_areas} line areas configuration: {vehicle_count_q}. This is > than the all-direct configuration ({vehicle_counts_all_direct[vt]})."
1072
1072
  )
1073
- except ValueError as e:
1073
+ except Exception as e:
1074
+ # This change is made after Unstable exception and delay exceptions are introduced
1074
1075
  if (
1075
1076
  "which suggests the fleet or the infrastructure might not be enough for the full electrification. Please add charging interfaces or increase charging power ."
1076
1077
  in repr(e)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "eflips-depot"
3
- version = "4.9.1"
3
+ version = "4.10.0"
4
4
  description = "Depot Simulation for eFLIPS"
5
5
  authors = ["Enrico Lauth <enrico.lauth@tu-berlin.de>",
6
6
  "Ludger Heide <ludger.heide@tu-berlin.de",
File without changes
File without changes