eflips-depot 3.2.7__py3-none-any.whl → 4.0.0__py3-none-any.whl
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.
- eflips/depot/api/__init__.py +679 -417
- eflips/depot/api/private/depot.py +57 -20
- eflips/depot/api/private/util.py +43 -1
- {eflips_depot-3.2.7.dist-info → eflips_depot-4.0.0.dist-info}/METADATA +2 -2
- {eflips_depot-3.2.7.dist-info → eflips_depot-4.0.0.dist-info}/RECORD +7 -7
- {eflips_depot-3.2.7.dist-info → eflips_depot-4.0.0.dist-info}/LICENSE.md +0 -0
- {eflips_depot-3.2.7.dist-info → eflips_depot-4.0.0.dist-info}/WHEEL +0 -0
|
@@ -104,6 +104,8 @@ def depot_to_template(depot: Depot) -> Dict[str, str | Dict[str, str | int]]:
|
|
|
104
104
|
"vehicle_types": [str(area.vehicle_type_id)],
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
# TODO for cleaning area etc., enable non-vehicle_type areas
|
|
108
|
+
|
|
107
109
|
for process in area.processes:
|
|
108
110
|
# Add process into process list
|
|
109
111
|
list_of_processes.append(
|
|
@@ -222,7 +224,7 @@ def depot_to_template(depot: Depot) -> Dict[str, str | Dict[str, str | int]]:
|
|
|
222
224
|
}
|
|
223
225
|
# Groups
|
|
224
226
|
for process in depot.default_plan.processes:
|
|
225
|
-
group_name = str(
|
|
227
|
+
group_name = str(process.name) + "_group"
|
|
226
228
|
template["groups"][group_name] = {
|
|
227
229
|
"typename": "AreaGroup",
|
|
228
230
|
"stores": [str(area.id) for area in process.areas],
|
|
@@ -295,6 +297,7 @@ def create_simple_depot(
|
|
|
295
297
|
charging_power: float,
|
|
296
298
|
session: sqlalchemy.orm.session.Session,
|
|
297
299
|
cleaning_duration: timedelta = timedelta(minutes=30),
|
|
300
|
+
safety_margin: float = 0.0,
|
|
298
301
|
) -> None:
|
|
299
302
|
"""
|
|
300
303
|
Creates a simple depot for a given scenario.
|
|
@@ -302,6 +305,7 @@ def create_simple_depot(
|
|
|
302
305
|
It has one area for each vehicle type and a charging process for each
|
|
303
306
|
area. Also an arrival area for each vehicle type.
|
|
304
307
|
|
|
308
|
+
:param safety_margin: a safety margin for the number of charging and cleaning capacities. Default is 0.0
|
|
305
309
|
:param scenario: The scenario to be simulated
|
|
306
310
|
:param station: The station where the depot is located
|
|
307
311
|
:param charging_capacities: A dictionary of vehicle types and the number of vehicles that can be charged at the same time
|
|
@@ -328,10 +332,11 @@ def create_simple_depot(
|
|
|
328
332
|
depot.default_plan = plan
|
|
329
333
|
|
|
330
334
|
# Create processes
|
|
331
|
-
|
|
332
|
-
name="
|
|
335
|
+
shunting_1 = Process(
|
|
336
|
+
name="Shunting 1",
|
|
333
337
|
scenario=scenario,
|
|
334
338
|
dispatchable=False,
|
|
339
|
+
duration=timedelta(minutes=5),
|
|
335
340
|
)
|
|
336
341
|
clean = Process(
|
|
337
342
|
name="Arrival Cleaning",
|
|
@@ -339,6 +344,12 @@ def create_simple_depot(
|
|
|
339
344
|
dispatchable=False,
|
|
340
345
|
duration=cleaning_duration,
|
|
341
346
|
)
|
|
347
|
+
shunting_2 = Process(
|
|
348
|
+
name="Shunting 2",
|
|
349
|
+
scenario=scenario,
|
|
350
|
+
dispatchable=False,
|
|
351
|
+
duration=timedelta(minutes=5),
|
|
352
|
+
)
|
|
342
353
|
charging = Process(
|
|
343
354
|
name="Charging",
|
|
344
355
|
scenario=scenario,
|
|
@@ -350,15 +361,27 @@ def create_simple_depot(
|
|
|
350
361
|
scenario=scenario,
|
|
351
362
|
dispatchable=True,
|
|
352
363
|
)
|
|
353
|
-
|
|
364
|
+
|
|
354
365
|
session.add(clean)
|
|
366
|
+
session.add(shunting_1)
|
|
355
367
|
session.add(charging)
|
|
356
368
|
session.add(standby_departure)
|
|
369
|
+
session.add(shunting_2)
|
|
370
|
+
|
|
371
|
+
# Create shared waiting area
|
|
372
|
+
waiting_area = Area(
|
|
373
|
+
scenario=scenario,
|
|
374
|
+
name=f"Waiting Area for every type of vehicle",
|
|
375
|
+
depot=depot,
|
|
376
|
+
area_type=AreaType.DIRECT_ONESIDE,
|
|
377
|
+
capacity=100,
|
|
378
|
+
)
|
|
379
|
+
session.add(waiting_area)
|
|
357
380
|
|
|
358
381
|
for vehicle_type in charging_capacities.keys():
|
|
359
382
|
charging_count = charging_capacities[vehicle_type]
|
|
360
|
-
|
|
361
|
-
charging_count = int(ceil(charging_count *
|
|
383
|
+
|
|
384
|
+
charging_count = int(ceil(charging_count * (1 + safety_margin)))
|
|
362
385
|
|
|
363
386
|
# Create charging area
|
|
364
387
|
charging_area = Area(
|
|
@@ -366,15 +389,15 @@ def create_simple_depot(
|
|
|
366
389
|
name=f"Direct Charging Area for {vehicle_type.name_short}",
|
|
367
390
|
depot=depot,
|
|
368
391
|
area_type=AreaType.DIRECT_ONESIDE,
|
|
369
|
-
capacity=charging_count,
|
|
392
|
+
capacity=int(charging_count * 1),
|
|
370
393
|
)
|
|
371
394
|
session.add(charging_area)
|
|
372
395
|
charging_area.vehicle_type = vehicle_type
|
|
373
396
|
|
|
374
397
|
# Create cleaning area
|
|
375
398
|
cleaning_count = cleaning_capacities[vehicle_type]
|
|
376
|
-
|
|
377
|
-
cleaning_count = int(ceil(cleaning_count *
|
|
399
|
+
|
|
400
|
+
cleaning_count = int(ceil(cleaning_count * (1 + safety_margin)))
|
|
378
401
|
|
|
379
402
|
cleaning_area = Area(
|
|
380
403
|
scenario=scenario,
|
|
@@ -386,31 +409,45 @@ def create_simple_depot(
|
|
|
386
409
|
session.add(cleaning_area)
|
|
387
410
|
cleaning_area.vehicle_type = vehicle_type
|
|
388
411
|
|
|
389
|
-
|
|
390
|
-
arrival_area = Area(
|
|
412
|
+
shunting_area_1 = Area(
|
|
391
413
|
scenario=scenario,
|
|
392
|
-
name=f"
|
|
414
|
+
name=f"Shunting Area 1 for {vehicle_type.name_short}",
|
|
393
415
|
depot=depot,
|
|
394
416
|
area_type=AreaType.DIRECT_ONESIDE,
|
|
395
|
-
capacity=
|
|
396
|
-
* 2, # SHould be huge, not all of it will be used
|
|
417
|
+
capacity=10,
|
|
397
418
|
)
|
|
398
|
-
session.add(arrival_area)
|
|
399
|
-
arrival_area.vehicle_type = vehicle_type
|
|
400
419
|
|
|
401
|
-
|
|
420
|
+
session.add(shunting_area_1)
|
|
421
|
+
shunting_area_1.vehicle_type = vehicle_type
|
|
422
|
+
|
|
423
|
+
shunting_area_2 = Area(
|
|
424
|
+
scenario=scenario,
|
|
425
|
+
name=f"Shunting Area 2 for {vehicle_type.name_short}",
|
|
426
|
+
depot=depot,
|
|
427
|
+
area_type=AreaType.DIRECT_ONESIDE,
|
|
428
|
+
capacity=10,
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
session.add(shunting_area_2)
|
|
432
|
+
shunting_area_2.vehicle_type = vehicle_type
|
|
433
|
+
|
|
402
434
|
cleaning_area.processes.append(clean)
|
|
403
435
|
charging_area.processes.append(charging)
|
|
404
436
|
charging_area.processes.append(standby_departure)
|
|
437
|
+
shunting_area_1.processes.append(shunting_1)
|
|
438
|
+
shunting_area_2.processes.append(shunting_2)
|
|
405
439
|
|
|
406
440
|
assocs = [
|
|
407
441
|
AssocPlanProcess(
|
|
408
|
-
scenario=scenario, process=
|
|
442
|
+
scenario=scenario, process=shunting_1, plan=plan, ordinal=0
|
|
409
443
|
),
|
|
410
444
|
AssocPlanProcess(scenario=scenario, process=clean, plan=plan, ordinal=1),
|
|
411
|
-
AssocPlanProcess(scenario=scenario, process=charging, plan=plan, ordinal=2),
|
|
412
445
|
AssocPlanProcess(
|
|
413
|
-
scenario=scenario, process=
|
|
446
|
+
scenario=scenario, process=shunting_2, plan=plan, ordinal=2
|
|
447
|
+
),
|
|
448
|
+
AssocPlanProcess(scenario=scenario, process=charging, plan=plan, ordinal=3),
|
|
449
|
+
AssocPlanProcess(
|
|
450
|
+
scenario=scenario, process=standby_departure, plan=plan, ordinal=4
|
|
414
451
|
),
|
|
415
452
|
]
|
|
416
453
|
session.add_all(assocs)
|
eflips/depot/api/private/util.py
CHANGED
|
@@ -7,7 +7,15 @@ from datetime import timedelta, datetime
|
|
|
7
7
|
from typing import Union, Any, Optional, Tuple, Dict, List
|
|
8
8
|
|
|
9
9
|
import simpy
|
|
10
|
-
from eflips.model import
|
|
10
|
+
from eflips.model import (
|
|
11
|
+
Scenario,
|
|
12
|
+
VehicleType,
|
|
13
|
+
Rotation,
|
|
14
|
+
Event,
|
|
15
|
+
EventType,
|
|
16
|
+
Trip,
|
|
17
|
+
Depot,
|
|
18
|
+
)
|
|
11
19
|
from sqlalchemy import inspect, create_engine
|
|
12
20
|
from sqlalchemy.orm import Session
|
|
13
21
|
|
|
@@ -164,6 +172,40 @@ def start_and_end_times(vehicle_schedules) -> Tuple[datetime, int]:
|
|
|
164
172
|
return midnight_of_first_departure_day, total_duration_seconds
|
|
165
173
|
|
|
166
174
|
|
|
175
|
+
def check_depot_validity(depot: Depot) -> None:
|
|
176
|
+
"""
|
|
177
|
+
Check if the depot is valid for the eflips-depot simulation. Raise an AssertionError if it is not.
|
|
178
|
+
:param depot: a :class:`eflips.model.Depot` object.
|
|
179
|
+
:return: None
|
|
180
|
+
"""
|
|
181
|
+
# 1. There must be an area containing no vehicle types
|
|
182
|
+
has_waiting_area = False
|
|
183
|
+
areas = depot.areas
|
|
184
|
+
for area in areas:
|
|
185
|
+
if area.vehicle_type_id is None:
|
|
186
|
+
# TODO might change to len(area.vehicle_types) == 0 after a list of vehicle types is allowed
|
|
187
|
+
has_waiting_area = True
|
|
188
|
+
|
|
189
|
+
assert (
|
|
190
|
+
has_waiting_area
|
|
191
|
+
), "There must be an area containing no vehicle types as the waiting area."
|
|
192
|
+
|
|
193
|
+
# 2. There must be only one process with no duration and no electric power, and it must be the last process in the plan
|
|
194
|
+
plan = depot.default_plan
|
|
195
|
+
processes = plan.processes
|
|
196
|
+
last_process = processes[-1]
|
|
197
|
+
assert (
|
|
198
|
+
last_process.duration is None
|
|
199
|
+
and last_process.electric_power is None
|
|
200
|
+
and last_process.dispatchable is True
|
|
201
|
+
), "The last process must be dispatchable and have no duration and no electric power."
|
|
202
|
+
|
|
203
|
+
for process in processes[:-1]:
|
|
204
|
+
assert (
|
|
205
|
+
process.electric_power is not None or process.duration is not None
|
|
206
|
+
), "All processes except the last one must have electric power."
|
|
207
|
+
|
|
208
|
+
|
|
167
209
|
@dataclass
|
|
168
210
|
class VehicleSchedule:
|
|
169
211
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: eflips-depot
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.0.0
|
|
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
|
|
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
15
|
Requires-Dist: eflips (>=0.1.3,<0.2.0)
|
|
16
|
-
Requires-Dist: eflips-model (>=
|
|
16
|
+
Requires-Dist: eflips-model (>=4.0.0a2,<5.0.0)
|
|
17
17
|
Requires-Dist: pandas (>=2.1.4,<3.0.0)
|
|
18
18
|
Requires-Dist: scipy (>=1.13.1,<2.0.0)
|
|
19
19
|
Requires-Dist: simpy (>=4.0.1,<5.0.0)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
eflips/depot/__init__.py,sha256=n7jte8R6j_Ad4Mp4hkklKwil5r8u8Q_SbXrCC-nf5jM,1556
|
|
2
|
-
eflips/depot/api/__init__.py,sha256=
|
|
2
|
+
eflips/depot/api/__init__.py,sha256=ecO_I4Tdh2vcNtxoYrNXehgKscgl26sMYqhkLoPO2lU,63743
|
|
3
3
|
eflips/depot/api/defaults/default_settings.json,sha256=0eUDTw_rtLQFvthP8oJL93iRXlmAOravAg-4qqGMQAY,5375
|
|
4
4
|
eflips/depot/api/private/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
eflips/depot/api/private/depot.py,sha256=
|
|
5
|
+
eflips/depot/api/private/depot.py,sha256=z17kGwXyt3XmOze8hn0hKpDrAUOd4pFV9ojNDEQmx5A,18112
|
|
6
6
|
eflips/depot/api/private/smart_charging.py,sha256=GpNFaExjvyTCja4Uzx-cRW_Qck3Vv5A3Qt9HUJUfFLU,13510
|
|
7
|
-
eflips/depot/api/private/util.py,sha256=
|
|
7
|
+
eflips/depot/api/private/util.py,sha256=BFdhyaCSClLJo8DjlIQCV_db-Cc-qqNuGnNa50GzaLs,16741
|
|
8
8
|
eflips/depot/configuration.py,sha256=Op3hlir-dEN7yHr0kTqbYANoCBKFWK6uKOv3NJl8w_w,35678
|
|
9
9
|
eflips/depot/depot.py,sha256=afIlaiX-J-M5-K_oAGMr_soL3_QjIAwrQKDaZzTwle0,105566
|
|
10
10
|
eflips/depot/evaluation.py,sha256=qqXyP4jA1zFcKuWhliQ6n25ZlGl9mJV-vtXf0yu8WN8,140842
|
|
@@ -35,7 +35,7 @@ eflips/depot/simulation.py,sha256=ee0qTzOzG-8ybN36ie_NJallXfC7jUaS9JZvaYFziLs,10
|
|
|
35
35
|
eflips/depot/smart_charging.py,sha256=C3BYqzn2-OYY4ipXm0ETtavbAM9QXZMYULBpVoChf0E,54311
|
|
36
36
|
eflips/depot/standalone.py,sha256=VxcTzBaB67fNJUMmjPRwKXjhqTy6oQ41Coote2LvAmk,22338
|
|
37
37
|
eflips/depot/validation.py,sha256=TIuY7cQtEJI4H2VVMSuY5IIVkacEEZ67weeMuY3NSAM,7097
|
|
38
|
-
eflips_depot-
|
|
39
|
-
eflips_depot-
|
|
40
|
-
eflips_depot-
|
|
41
|
-
eflips_depot-
|
|
38
|
+
eflips_depot-4.0.0.dist-info/LICENSE.md,sha256=KB4XTk1fPHjtZCYDyPyreu6h1LVJVZXYg-5vePcWZAc,34143
|
|
39
|
+
eflips_depot-4.0.0.dist-info/METADATA,sha256=8eRcKemy5vZa_YvcOTbxD69gQ-jcv1o6mgCr_GdwWyE,5788
|
|
40
|
+
eflips_depot-4.0.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
41
|
+
eflips_depot-4.0.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|