eflips-depot 3.0.3__tar.gz → 3.0.5__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.
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/PKG-INFO +6 -4
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/README.md +1 -1
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/api/__init__.py +277 -249
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/api/private/util.py +12 -12
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/pyproject.toml +4 -2
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/LICENSE.md +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/__init__.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/api/defaults/default_settings.json +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/api/private/__init__.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/api/private/depot.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/configuration.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/depot.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/evaluation.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/filters.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/input_epex_power_price.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/layout_opt/__init__.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/layout_opt/doc/__init__.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/layout_opt/doc/direct_details.pdf +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/layout_opt/evaluation.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/layout_opt/opt_tools/__init__.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/layout_opt/opt_tools/crossover.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/layout_opt/opt_tools/fitness_c_urfd.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/layout_opt/opt_tools/fitness_util.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/layout_opt/opt_tools/init.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/layout_opt/opt_tools/mutation.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/layout_opt/optimize_c_urfd.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/layout_opt/packing.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/layout_opt/settings.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/layout_opt/template_creation.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/layout_opt/util.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/plots.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/processes.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/rating.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/resources.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/settings_config.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/simple_vehicle.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/simulation.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/smart_charging.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/standalone.py +0 -0
- {eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/validation.py +0 -0
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: eflips-depot
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.5
|
|
4
4
|
Summary: Depot Simulation for eFLIPS
|
|
5
|
-
|
|
5
|
+
Home-page: https://github.com/mpm-tu-berlin/eflips-depot
|
|
6
|
+
License: AGPL-3.0-or-later
|
|
6
7
|
Author: Enrico Lauth
|
|
7
8
|
Author-email: enrico.lauth@tu-berlin.de
|
|
8
9
|
Requires-Python: >=3.10,<4.0
|
|
9
|
-
Classifier: License ::
|
|
10
|
+
Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
|
|
10
11
|
Classifier: Programming Language :: Python :: 3
|
|
11
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -17,9 +18,10 @@ Requires-Dist: pandas (>=2.1.4,<3.0.0)
|
|
|
17
18
|
Requires-Dist: simpy (>=4.0.1,<5.0.0)
|
|
18
19
|
Requires-Dist: xlrd (<=1.2.0)
|
|
19
20
|
Requires-Dist: xlsxwriter (>=3.1.9,<4.0.0)
|
|
21
|
+
Project-URL: Repository, https://github.com/mpm-tu-berlin/eflips-depot
|
|
20
22
|
Description-Content-Type: text/markdown
|
|
21
23
|
|
|
22
|
-
[](https://github.com/mpm-tu-berlin/eflips-depot/actions/workflows/unittests.yml)
|
|
23
25
|
[](https://github.com/psf/black)
|
|
24
26
|
|
|
25
27
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[](https://github.com/mpm-tu-berlin/eflips-depot/actions/workflows/unittests.yml)
|
|
2
2
|
[](https://github.com/psf/black)
|
|
3
3
|
|
|
4
4
|
|
|
@@ -306,7 +306,7 @@ def generate_depot_layout(
|
|
|
306
306
|
max_occupancies: Dict[eflips.model.VehicleType, int] = {}
|
|
307
307
|
max_clean_occupancies: Dict[eflips.model.VehicleType, int] = {}
|
|
308
308
|
for vehicle_type, rotations in vehicle_type_dict.items():
|
|
309
|
-
# Slightly
|
|
309
|
+
# Slightly convoluted vehicle summation
|
|
310
310
|
start_time = min(
|
|
311
311
|
[rotation.trips[0].departure_time for rotation in rotations]
|
|
312
312
|
).timestamp()
|
|
@@ -663,16 +663,10 @@ def add_evaluation_to_database(
|
|
|
663
663
|
|
|
664
664
|
# Initialization of empty lists
|
|
665
665
|
|
|
666
|
-
list_of_vehicles = []
|
|
667
|
-
|
|
668
|
-
list_of_events = []
|
|
669
|
-
|
|
670
666
|
list_of_assigned_schedules = []
|
|
671
667
|
|
|
672
668
|
# Read results from depot_evaluation categorized by vehicle
|
|
673
669
|
for current_vehicle in depot_evaluation.vehicle_generator.items:
|
|
674
|
-
list_of_events_per_vehicle = []
|
|
675
|
-
|
|
676
670
|
vehicle_type_id = int(current_vehicle.vehicle_type.ID)
|
|
677
671
|
|
|
678
672
|
# Create a Vehicle object for database
|
|
@@ -685,26 +679,56 @@ def add_evaluation_to_database(
|
|
|
685
679
|
# Flush the vehicle object to get the vehicle id
|
|
686
680
|
session.add(current_vehicle_db)
|
|
687
681
|
session.flush()
|
|
688
|
-
list_of_vehicles.append(current_vehicle_db)
|
|
689
682
|
|
|
690
683
|
dict_of_events = {}
|
|
691
684
|
|
|
692
|
-
# Generate process log for each
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
685
|
+
# Generate process log for each
|
|
686
|
+
list_of_finished_trips = current_vehicle.finished_trips
|
|
687
|
+
list_of_finished_trips.sort(key=lambda x: x.atd)
|
|
688
|
+
|
|
689
|
+
for i in range(len(list_of_finished_trips)):
|
|
690
|
+
if list_of_finished_trips[i].is_copy is False:
|
|
691
|
+
current_trip = list_of_finished_trips[i]
|
|
699
692
|
|
|
700
|
-
|
|
701
|
-
|
|
693
|
+
# Add all non-copy trips to the dictionary
|
|
694
|
+
dict_of_events[current_trip.atd] = {
|
|
695
|
+
"type": "Trip",
|
|
696
|
+
"end": current_trip.ata,
|
|
697
|
+
"is_copy": current_trip.is_copy,
|
|
698
|
+
"id": current_trip.ID,
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
# Match current trip to its serving vehicle
|
|
702
|
+
assigned_schedule_id = int(current_trip.ID)
|
|
702
703
|
list_of_assigned_schedules.append(
|
|
703
704
|
(assigned_schedule_id, current_vehicle_db.id)
|
|
704
705
|
)
|
|
706
|
+
# Also add two copy trips before and after the non-copy trip as "time boarders" for the depot process
|
|
707
|
+
try:
|
|
708
|
+
if list_of_finished_trips[i + 1].is_copy is True:
|
|
709
|
+
dict_of_events[list_of_finished_trips[i + 1].atd] = {
|
|
710
|
+
"type": "Trip",
|
|
711
|
+
"end": list_of_finished_trips[i + 1].ata,
|
|
712
|
+
"is_copy": list_of_finished_trips[i + 1].is_copy,
|
|
713
|
+
"id": list_of_finished_trips[i + 1].ID,
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
if list_of_finished_trips[i - 1].is_copy is True:
|
|
717
|
+
dict_of_events[list_of_finished_trips[i - 1].atd] = {
|
|
718
|
+
"type": "Trip",
|
|
719
|
+
"end": list_of_finished_trips[i - 1].ata,
|
|
720
|
+
"is_copy": list_of_finished_trips[i - 1].is_copy,
|
|
721
|
+
"id": list_of_finished_trips[i - 1].ID,
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
except IndexError:
|
|
725
|
+
# In case there are no copy trips before or after the non-copy trip
|
|
726
|
+
continue
|
|
705
727
|
|
|
706
|
-
#
|
|
707
|
-
#
|
|
728
|
+
# The range of time of events to be generated. It is between the copy trip before the first non-copy trip and the
|
|
729
|
+
# copy trip after the last non-copy trip
|
|
730
|
+
earliest_time = sorted(dict_of_events.keys())[0]
|
|
731
|
+
latest_time = sorted(dict_of_events.keys())[-1]
|
|
708
732
|
|
|
709
733
|
last_standby_departure_start = 0
|
|
710
734
|
|
|
@@ -712,7 +736,6 @@ def add_evaluation_to_database(
|
|
|
712
736
|
area_log = current_vehicle.logger.loggedData["dwd.current_area"]
|
|
713
737
|
slot_log = current_vehicle.logger.loggedData["dwd.current_slot"]
|
|
714
738
|
|
|
715
|
-
# For future uses
|
|
716
739
|
waiting_log = current_vehicle.logger.loggedData["area_waiting_time"]
|
|
717
740
|
battery_log = current_vehicle.battery_logs
|
|
718
741
|
|
|
@@ -721,46 +744,52 @@ def add_evaluation_to_database(
|
|
|
721
744
|
|
|
722
745
|
for idx in range(len(waiting_log_timekeys)):
|
|
723
746
|
end_time = waiting_log_timekeys[idx]
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
Process.
|
|
741
|
-
|
|
742
|
-
|
|
747
|
+
|
|
748
|
+
# Only extract events if the time is within the upper mentioned range
|
|
749
|
+
|
|
750
|
+
if earliest_time < end_time < latest_time:
|
|
751
|
+
waiting_info = waiting_log[end_time]
|
|
752
|
+
|
|
753
|
+
if waiting_info["waiting_time"] == 0:
|
|
754
|
+
continue
|
|
755
|
+
|
|
756
|
+
# Vehicle is waiting in the last area in waiting_log and expecting to enter the current area
|
|
757
|
+
expected_area = waiting_info["area"]
|
|
758
|
+
# Find the area for standby arrival event
|
|
759
|
+
|
|
760
|
+
waiting_area_id = (
|
|
761
|
+
session.query(Area.id)
|
|
762
|
+
.join(AssocAreaProcess, AssocAreaProcess.area_id == Area.id)
|
|
763
|
+
.join(Process, Process.id == AssocAreaProcess.process_id)
|
|
764
|
+
.filter(
|
|
765
|
+
Process.dispatchable == False,
|
|
766
|
+
# Must use "==" instead of "is". Or it would be recongnize as a python statement rather than a SQL statement
|
|
767
|
+
Process.duration.is_(None),
|
|
768
|
+
Process.electric_power.is_(None),
|
|
769
|
+
Area.vehicle_type_id
|
|
770
|
+
== int(current_vehicle.vehicle_type.ID),
|
|
771
|
+
Area.scenario_id == scenario.id,
|
|
772
|
+
)
|
|
773
|
+
.one()[0]
|
|
743
774
|
)
|
|
744
|
-
.one()[0]
|
|
745
|
-
)
|
|
746
775
|
|
|
747
|
-
|
|
776
|
+
# Make sure the vehicle is waiting at an area with enough capacity
|
|
748
777
|
|
|
749
|
-
|
|
778
|
+
current_slot = slot_log[waiting_log_timekeys[idx - 1]]
|
|
750
779
|
|
|
751
|
-
|
|
780
|
+
start_time = end_time - waiting_info["waiting_time"]
|
|
752
781
|
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
782
|
+
warnings.warn(
|
|
783
|
+
f"Vehicle {current_vehicle.ID} is waiting at {waiting_area_id} because area {expected_area} is full."
|
|
784
|
+
)
|
|
756
785
|
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
786
|
+
dict_of_events[start_time] = {
|
|
787
|
+
"type": "Standby",
|
|
788
|
+
"end": end_time,
|
|
789
|
+
"area": waiting_area_id,
|
|
790
|
+
"slot": current_slot,
|
|
791
|
+
"is_area_sink": False,
|
|
792
|
+
}
|
|
764
793
|
|
|
765
794
|
# Create a list of battery log in order of time asc. Convenient for looking up corresponding soc
|
|
766
795
|
battery_log_list = []
|
|
@@ -770,230 +799,230 @@ def add_evaluation_to_database(
|
|
|
770
799
|
for start_time, process_log in current_vehicle.logger.loggedData[
|
|
771
800
|
"dwd.active_processes_copy"
|
|
772
801
|
].items():
|
|
773
|
-
if
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
802
|
+
if earliest_time < start_time < latest_time:
|
|
803
|
+
if len(process_log) == 0:
|
|
804
|
+
# A departure happens
|
|
805
|
+
if last_standby_departure_start != 0:
|
|
806
|
+
# Update the last standby-departure end time
|
|
807
|
+
dict_of_events[last_standby_departure_start][
|
|
808
|
+
"end"
|
|
809
|
+
] = start_time
|
|
810
|
+
else:
|
|
811
|
+
continue
|
|
780
812
|
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
current_area = area_log[start_time]
|
|
792
|
-
current_slot = slot_log[start_time]
|
|
793
|
-
|
|
794
|
-
if current_area is None or current_slot is None:
|
|
795
|
-
raise ValueError(
|
|
796
|
-
f"For process {process.ID} Area and slot should not be None."
|
|
813
|
+
else:
|
|
814
|
+
for process in process_log:
|
|
815
|
+
match process.status:
|
|
816
|
+
case ProcessStatus.COMPLETED | ProcessStatus.CANCELLED:
|
|
817
|
+
assert (
|
|
818
|
+
len(process.starts) == 1
|
|
819
|
+
and len(process.ends) == 1
|
|
820
|
+
), (
|
|
821
|
+
f"Current process {process.ID} is completed and should only contain one start and "
|
|
822
|
+
f"one end time."
|
|
797
823
|
)
|
|
824
|
+
current_area = area_log[start_time]
|
|
825
|
+
current_slot = slot_log[start_time]
|
|
798
826
|
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
}
|
|
808
|
-
else:
|
|
809
|
-
# Duration is 0
|
|
810
|
-
if current_area.issink is True:
|
|
811
|
-
# Standby departure
|
|
812
|
-
if start_time in dict_of_events:
|
|
813
|
-
# Actual start time should be the end time of the other positive duration
|
|
814
|
-
# process starting at the same time
|
|
815
|
-
actual_start_time = dict_of_events[
|
|
816
|
-
start_time
|
|
817
|
-
]["end"]
|
|
818
|
-
else:
|
|
819
|
-
for other_process in process_log:
|
|
820
|
-
if (
|
|
821
|
-
other_process.dur > 0
|
|
822
|
-
and len(other_process.ends) != 0
|
|
823
|
-
):
|
|
824
|
-
actual_start_time = (
|
|
825
|
-
other_process.ends[0]
|
|
826
|
-
)
|
|
827
|
-
else:
|
|
828
|
-
# Invalid standby before a process in progress will be ignored
|
|
829
|
-
continue
|
|
830
|
-
|
|
831
|
-
last_standby_departure_start = actual_start_time
|
|
832
|
-
|
|
833
|
-
# If this standby event lasts actually 0 seconds, it is not a real event
|
|
834
|
-
if (
|
|
835
|
-
actual_start_time in dict_of_events.keys()
|
|
836
|
-
and dict_of_events[actual_start_time][
|
|
837
|
-
"type"
|
|
838
|
-
]
|
|
839
|
-
== "trip"
|
|
840
|
-
):
|
|
841
|
-
continue
|
|
842
|
-
dict_of_events[actual_start_time] = {
|
|
827
|
+
if current_area is None or current_slot is None:
|
|
828
|
+
raise ValueError(
|
|
829
|
+
f"For process {process.ID} Area and slot should not be None."
|
|
830
|
+
)
|
|
831
|
+
|
|
832
|
+
if process.dur > 0:
|
|
833
|
+
# Valid duration
|
|
834
|
+
dict_of_events[start_time] = {
|
|
843
835
|
"type": type(process).__name__,
|
|
836
|
+
"end": process.ends[0],
|
|
844
837
|
"area": current_area.ID,
|
|
845
|
-
"is_area_sink": current_area.issink,
|
|
846
838
|
"slot": current_slot,
|
|
847
839
|
"id": process.ID,
|
|
848
840
|
}
|
|
849
|
-
|
|
850
841
|
else:
|
|
851
|
-
#
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
842
|
+
# Duration is 0
|
|
843
|
+
if current_area.issink is True:
|
|
844
|
+
# Standby departure
|
|
845
|
+
if start_time in dict_of_events:
|
|
846
|
+
# Actual start time should be the end time of the other positive
|
|
847
|
+
# duration process starting at the same time
|
|
848
|
+
actual_start_time = dict_of_events[
|
|
849
|
+
start_time
|
|
850
|
+
]["end"]
|
|
851
|
+
else:
|
|
852
|
+
for other_process in process_log:
|
|
853
|
+
if (
|
|
854
|
+
other_process.dur > 0
|
|
855
|
+
and len(other_process.ends) != 0
|
|
856
|
+
):
|
|
857
|
+
actual_start_time = (
|
|
858
|
+
other_process.ends[0]
|
|
859
|
+
)
|
|
860
|
+
else:
|
|
861
|
+
# Invalid standby before a process in progress will be ignored
|
|
862
|
+
continue
|
|
863
|
+
|
|
864
|
+
last_standby_departure_start = (
|
|
865
|
+
actual_start_time
|
|
866
|
+
)
|
|
867
|
+
|
|
868
|
+
# If this standby event lasts actually 0 seconds, it is not a real event
|
|
869
|
+
if (
|
|
870
|
+
actual_start_time
|
|
871
|
+
in dict_of_events.keys()
|
|
872
|
+
and dict_of_events[actual_start_time][
|
|
873
|
+
"type"
|
|
874
|
+
]
|
|
875
|
+
== "Trip"
|
|
876
|
+
):
|
|
877
|
+
continue
|
|
878
|
+
dict_of_events[actual_start_time] = {
|
|
879
|
+
"type": type(process).__name__,
|
|
880
|
+
"area": current_area.ID,
|
|
881
|
+
"is_area_sink": current_area.issink,
|
|
882
|
+
"slot": current_slot,
|
|
883
|
+
"id": process.ID,
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
else:
|
|
887
|
+
# Standby arrival
|
|
888
|
+
assert current_area.issink is False, (
|
|
889
|
+
f"A bus cannot go from Area {current_area.ID} to other areas. A Parking Area"
|
|
890
|
+
f" for standby arrival should be added."
|
|
891
|
+
)
|
|
892
|
+
dict_of_events[start_time] = {
|
|
893
|
+
"type": type(process).__name__,
|
|
894
|
+
"area": current_area.ID,
|
|
895
|
+
"is_area_sink": current_area.issink,
|
|
896
|
+
"slot": current_slot,
|
|
897
|
+
"id": process.ID,
|
|
898
|
+
}
|
|
899
|
+
case ProcessStatus.IN_PROGRESS:
|
|
900
|
+
assert (
|
|
901
|
+
len(process.starts) == 1
|
|
902
|
+
and len(process.ends) == 0
|
|
903
|
+
), f"Current process {process.ID} is marked IN_PROGRESS, but has an end."
|
|
904
|
+
current_area = area_log[start_time]
|
|
905
|
+
current_slot = slot_log[start_time]
|
|
906
|
+
|
|
907
|
+
if current_area is None or current_slot is None:
|
|
908
|
+
raise ValueError(
|
|
909
|
+
f"For process {process.ID} Area and slot should not be None."
|
|
855
910
|
)
|
|
911
|
+
|
|
912
|
+
if process.dur > 0:
|
|
913
|
+
# Valid duration
|
|
856
914
|
dict_of_events[start_time] = {
|
|
857
915
|
"type": type(process).__name__,
|
|
916
|
+
"end": process.etc,
|
|
858
917
|
"area": current_area.ID,
|
|
859
|
-
"is_area_sink": current_area.issink,
|
|
860
918
|
"slot": current_slot,
|
|
861
919
|
"id": process.ID,
|
|
862
920
|
}
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
if current_area is None or current_slot is None:
|
|
871
|
-
raise ValueError(
|
|
872
|
-
f"For process {process.ID} Area and slot should not be None."
|
|
921
|
+
else:
|
|
922
|
+
raise NotImplementedError(
|
|
923
|
+
"We believe this should never happen. If it happens, handle it here."
|
|
924
|
+
)
|
|
925
|
+
case ProcessStatus.WAITING:
|
|
926
|
+
raise NotImplementedError(
|
|
927
|
+
f"Current process {process.ID} is waiting. Not implemented yet."
|
|
873
928
|
)
|
|
874
929
|
|
|
875
|
-
|
|
876
|
-
# Valid duration
|
|
877
|
-
dict_of_events[start_time] = {
|
|
878
|
-
"type": type(process).__name__,
|
|
879
|
-
"end": process.etc,
|
|
880
|
-
"area": current_area.ID,
|
|
881
|
-
"slot": current_slot,
|
|
882
|
-
"id": process.ID,
|
|
883
|
-
}
|
|
884
|
-
else:
|
|
930
|
+
case ProcessStatus.NOT_STARTED:
|
|
885
931
|
raise NotImplementedError(
|
|
886
|
-
"
|
|
932
|
+
f"Current process {process.ID} is not started. Not implemented yet."
|
|
887
933
|
)
|
|
888
|
-
|
|
889
|
-
raise NotImplementedError(
|
|
890
|
-
f"Current process {process.ID} is waiting. Not implemented yet."
|
|
891
|
-
)
|
|
892
|
-
|
|
893
|
-
case ProcessStatus.NOT_STARTED:
|
|
894
|
-
raise NotImplementedError(
|
|
895
|
-
f"Current process {process.ID} is not started. Not implemented yet."
|
|
896
|
-
)
|
|
897
|
-
|
|
898
|
-
case _:
|
|
899
|
-
raise ValueError(
|
|
900
|
-
f"Invalid process status {process.status} for process {process.ID}."
|
|
901
|
-
)
|
|
902
|
-
|
|
903
|
-
reversed_time_keys = sorted(dict_of_events.keys(), reverse=True)
|
|
904
|
-
if len(reversed_time_keys) != 0:
|
|
905
|
-
# Generating valid event-list
|
|
906
|
-
is_copy = True
|
|
907
|
-
for start_time in reversed_time_keys:
|
|
908
|
-
process_dict = dict_of_events[start_time]
|
|
909
|
-
if process_dict["type"] == "trip":
|
|
910
|
-
is_copy = process_dict["is_copy"]
|
|
911
|
-
else:
|
|
912
|
-
if is_copy is False:
|
|
913
|
-
# Generate EventType
|
|
914
|
-
match process_dict["type"]:
|
|
915
|
-
case "Serve":
|
|
916
|
-
event_type = EventType.SERVICE
|
|
917
|
-
case "Charge":
|
|
918
|
-
event_type = EventType.CHARGING_DEPOT
|
|
919
|
-
case "Standby":
|
|
920
|
-
if process_dict["is_area_sink"] is True:
|
|
921
|
-
event_type = EventType.STANDBY_DEPARTURE
|
|
922
|
-
else:
|
|
923
|
-
event_type = EventType.STANDBY
|
|
924
|
-
case "Precondition":
|
|
925
|
-
event_type = EventType.PRECONDITIONING
|
|
934
|
+
|
|
926
935
|
case _:
|
|
927
936
|
raise ValueError(
|
|
928
|
-
|
|
929
|
-
'"Standby", "Precondition"'
|
|
937
|
+
f"Invalid process status {process.status} for process {process.ID}."
|
|
930
938
|
)
|
|
931
939
|
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
soc_end = log[1]
|
|
960
|
-
|
|
961
|
-
current_event = Event(
|
|
962
|
-
scenario=scenario,
|
|
963
|
-
vehicle_type_id=vehicle_type_id,
|
|
964
|
-
vehicle=current_vehicle_db,
|
|
965
|
-
station_id=None,
|
|
966
|
-
area_id=int(process_dict["area"]),
|
|
967
|
-
subloc_no=int(process_dict["slot"]),
|
|
968
|
-
trip_id=None,
|
|
969
|
-
time_start=timedelta(seconds=start_time)
|
|
970
|
-
+ simulation_start_time,
|
|
971
|
-
time_end=timedelta(seconds=process_dict["end"])
|
|
972
|
-
+ simulation_start_time,
|
|
973
|
-
soc_start=soc_start
|
|
974
|
-
if soc_start is not None
|
|
975
|
-
else soc_end,
|
|
976
|
-
soc_end=soc_end
|
|
977
|
-
if soc_end is not None
|
|
978
|
-
else soc_start, # if only one battery log is found,
|
|
979
|
-
# then this is not an event with soc change
|
|
980
|
-
event_type=event_type,
|
|
981
|
-
description=None,
|
|
982
|
-
timeseries=None,
|
|
940
|
+
# Reverse the time keys to make generation of events before the trip easier
|
|
941
|
+
time_keys = sorted(dict_of_events.keys())
|
|
942
|
+
if len(time_keys) != 0:
|
|
943
|
+
# Generating valid event-list
|
|
944
|
+
|
|
945
|
+
for start_time in time_keys:
|
|
946
|
+
process_dict = dict_of_events[start_time]
|
|
947
|
+
|
|
948
|
+
# Generate EventType
|
|
949
|
+
match process_dict["type"]:
|
|
950
|
+
case "Serve":
|
|
951
|
+
event_type = EventType.SERVICE
|
|
952
|
+
case "Charge":
|
|
953
|
+
event_type = EventType.CHARGING_DEPOT
|
|
954
|
+
case "Standby":
|
|
955
|
+
if process_dict["is_area_sink"] is True:
|
|
956
|
+
event_type = EventType.STANDBY_DEPARTURE
|
|
957
|
+
else:
|
|
958
|
+
event_type = EventType.STANDBY
|
|
959
|
+
case "Precondition":
|
|
960
|
+
event_type = EventType.PRECONDITIONING
|
|
961
|
+
case "Trip":
|
|
962
|
+
continue
|
|
963
|
+
case _:
|
|
964
|
+
raise ValueError(
|
|
965
|
+
'Invalid process type %s. Valid process types are "Serve", "Charge", '
|
|
966
|
+
'"Standby", "Precondition"'
|
|
983
967
|
)
|
|
984
|
-
session.add(current_event)
|
|
985
|
-
list_of_events_per_vehicle.append(current_event)
|
|
986
968
|
|
|
987
|
-
|
|
969
|
+
# End time of 0-duration processes are start time of the next process
|
|
970
|
+
|
|
971
|
+
if "end" not in process_dict:
|
|
972
|
+
# End time will be the one time key "later"
|
|
973
|
+
end_time = time_keys[time_keys.index(start_time) + 1]
|
|
974
|
+
|
|
975
|
+
process_dict["end"] = end_time
|
|
976
|
+
|
|
977
|
+
# Get soc
|
|
978
|
+
soc_start = None
|
|
979
|
+
soc_end = None
|
|
980
|
+
|
|
981
|
+
for i in range(len(battery_log_list)):
|
|
982
|
+
# Access the correct battery log according to time since there is only one battery log for each time
|
|
983
|
+
log = battery_log_list[i]
|
|
984
|
+
|
|
985
|
+
if log[0] == start_time:
|
|
986
|
+
soc_start = log[1]
|
|
987
|
+
if log[0] == process_dict["end"]:
|
|
988
|
+
soc_end = log[1]
|
|
989
|
+
if log[0] < start_time < battery_log_list[i + 1][0]:
|
|
990
|
+
soc_start = log[1]
|
|
991
|
+
if log[0] < process_dict["end"] < battery_log_list[i + 1][0]:
|
|
992
|
+
soc_end = log[1]
|
|
993
|
+
|
|
994
|
+
current_event = Event(
|
|
995
|
+
scenario=scenario,
|
|
996
|
+
vehicle_type_id=vehicle_type_id,
|
|
997
|
+
vehicle=current_vehicle_db,
|
|
998
|
+
station_id=None,
|
|
999
|
+
area_id=int(process_dict["area"]),
|
|
1000
|
+
subloc_no=int(process_dict["slot"]),
|
|
1001
|
+
trip_id=None,
|
|
1002
|
+
time_start=timedelta(seconds=start_time)
|
|
1003
|
+
+ simulation_start_time,
|
|
1004
|
+
time_end=timedelta(seconds=process_dict["end"])
|
|
1005
|
+
+ simulation_start_time,
|
|
1006
|
+
soc_start=soc_start if soc_start is not None else soc_end,
|
|
1007
|
+
soc_end=soc_end
|
|
1008
|
+
if soc_end is not None
|
|
1009
|
+
else soc_start, # if only one battery log is found,
|
|
1010
|
+
# then this is not an event with soc change
|
|
1011
|
+
event_type=event_type,
|
|
1012
|
+
description=None,
|
|
1013
|
+
timeseries=None,
|
|
1014
|
+
)
|
|
1015
|
+
|
|
1016
|
+
session.add(current_event)
|
|
988
1017
|
|
|
989
1018
|
# For non-copy schedules with no predecessor events, adding a dummy standby-departure
|
|
990
1019
|
if (
|
|
991
|
-
dict_of_events[
|
|
992
|
-
and dict_of_events[
|
|
1020
|
+
dict_of_events[time_keys[0]]["type"] == "Trip"
|
|
1021
|
+
and dict_of_events[time_keys[0]]["is_copy"] is False
|
|
993
1022
|
):
|
|
994
|
-
standby_start =
|
|
995
|
-
standby_end =
|
|
996
|
-
rotation_id =
|
|
1023
|
+
standby_start = time_keys[0] - 1
|
|
1024
|
+
standby_end = time_keys[0]
|
|
1025
|
+
rotation_id = int(dict_of_events[time_keys[0]]["id"])
|
|
997
1026
|
area = (
|
|
998
1027
|
session.query(Area)
|
|
999
1028
|
.filter(Area.vehicle_type_id == vehicle_type_id)
|
|
@@ -1033,7 +1062,6 @@ def add_evaluation_to_database(
|
|
|
1033
1062
|
)
|
|
1034
1063
|
|
|
1035
1064
|
session.add(standby_event)
|
|
1036
|
-
list_of_events.append(standby_event)
|
|
1037
1065
|
|
|
1038
1066
|
# New rotation assignment
|
|
1039
1067
|
for schedule_id, vehicle_id in list_of_assigned_schedules:
|
|
@@ -340,18 +340,18 @@ class VehicleSchedule:
|
|
|
340
340
|
departure = int((self.departure - simulation_start_time).total_seconds())
|
|
341
341
|
arrival = int((self.arrival - simulation_start_time).total_seconds())
|
|
342
342
|
simple_trip = SimpleTrip(
|
|
343
|
-
env,
|
|
344
|
-
self.id,
|
|
345
|
-
None,
|
|
346
|
-
self.start_depot_id,
|
|
347
|
-
self.end_depot_id,
|
|
348
|
-
vehicle_types,
|
|
349
|
-
departure,
|
|
350
|
-
arrival,
|
|
351
|
-
None,
|
|
352
|
-
self.departure_soc,
|
|
353
|
-
self.arrival_soc,
|
|
354
|
-
self.opportunity_charging,
|
|
343
|
+
env=env,
|
|
344
|
+
ID=self.id,
|
|
345
|
+
line_name=None,
|
|
346
|
+
origin=self.start_depot_id,
|
|
347
|
+
destination=self.end_depot_id,
|
|
348
|
+
vehicle_types=vehicle_types,
|
|
349
|
+
std=departure,
|
|
350
|
+
sta=arrival,
|
|
351
|
+
distance=None,
|
|
352
|
+
start_soc=self.departure_soc,
|
|
353
|
+
end_soc=self.arrival_soc,
|
|
354
|
+
charge_on_track=self.opportunity_charging,
|
|
355
355
|
is_copy=self._is_copy,
|
|
356
356
|
)
|
|
357
357
|
return simple_trip
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "eflips-depot"
|
|
3
|
-
version = "3.0.
|
|
3
|
+
version = "3.0.5"
|
|
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",
|
|
7
7
|
"Shuyao Guo <shuyao.guo@tu-berlin.de"]
|
|
8
|
-
license = "
|
|
8
|
+
license = "AGPL-3.0-or-later"
|
|
9
9
|
readme = "README.md"
|
|
10
|
+
homepage = "https://github.com/mpm-tu-berlin/eflips-depot"
|
|
11
|
+
repository = "https://github.com/mpm-tu-berlin/eflips-depot"
|
|
10
12
|
packages = [{ include = "eflips/depot" }]
|
|
11
13
|
|
|
12
14
|
[tool.poetry.dependencies]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{eflips_depot-3.0.3 → eflips_depot-3.0.5}/eflips/depot/layout_opt/opt_tools/fitness_c_urfd.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|