-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdatatypes.py
More file actions
111 lines (90 loc) · 3.6 KB
/
Copy pathdatatypes.py
File metadata and controls
111 lines (90 loc) · 3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# datatypes.py
from copy import deepcopy
from dataclasses import dataclass
from typing import List, Optional, Dict, Set, Tuple
@dataclass(frozen=True)
class Location:
x: float
y: float
@dataclass
class Node:
id: int # Unique identifier
location: Location # Physical location
@dataclass
class Order:
id: int # pickup, delivery & reposition
request_time: float
pickup_node_id: Node # Restaurant node ID
delivery_node_id: Node # Customer node ID (dynamically created) -> when order is created!!!
deadline: float
ready_time: Optional[float]
service_time: float
status: str = "pending"
pickup_time: Optional[float] = None
delivery_time: Optional[float] = None
first_postpone_time: Optional[float] = None
postpone_count: int = 0
expected_prep_time: float = None # Expected preparation time when order created
actual_prep_time: float = None # Actual preparation time based on when order was ready
driver_wait_time: float = 0.0 # How long driver waited for the order
current_estimated_delay: float = 0.0 # Estimated delay based on current route plan
@dataclass
class Vehicle:
id: int
initial_location: Location
current_location: Location
current_destination: Optional[Location] = None
movement_progress: float = 0.0
total_travel_time: float = 0.0
current_phase: Optional[dict] = None
def __str__(self):
return f"Vehicle {self.id} at ({self.current_location.x}, {self.current_location.y})"
@dataclass
class Route:
vehicle_id: int
sequence: List[Tuple[int, Set[int], Set[int]]] # (node_id, pickups, deliveries)
# Bundled Route Example:
# {0: Route(vehicle_id=0, sequence=[(0, {0, 1, 2}, set()), (1000000, set(), {0}), (1000001, set(), {1}), (1000002, set(), {2})],
# total_distance=0.0, total_time=0.0)}
# Sequential Route example:
# Route(vehicle_id=0, sequence=[(0, {0}, set()), (1000000, set(), {0}), (0, {1}, set()), (1000001, set(), {1}), (0, {2}, set()), (1000002, set(), {2})])
total_distance: float = 0.0
total_time: float = 0.0
def __iter__(self):
"""Make Route iterable by returning iterator over sequence"""
return iter(self.sequence)
def get_all_orders(self) -> Set[int]:
"""Get all order IDs in this route"""
orders = set()
for _, pickups, deliveries in self.sequence:
orders.update(pickups)
orders.update(deliveries)
return orders
def copy(self):
"""Create a deep copy of the Route"""
return Route(
vehicle_id=self.vehicle_id,
sequence=deepcopy(self.sequence),
total_distance=self.total_distance,
total_time=self.total_time,
)
@dataclass
class State:
"""Represents the current state of the system."""
time: float
orders: List[Order] # All active orders
route_plan: Dict[int, Route] # Current routes (key: vehicle_id)
unassigned_orders: Set[int] # Order IDs not yet assigned
vehicles: Dict[int, Vehicle] # All vehicles
nodes: Dict[int, Node] # Static nodes (restaurants)
# -> den State den dann die Algorithmen bekommen. (wissen nicht alles)
# Nur wenn sich dieser geändert hat muss eine neue entscheidung getroffen werdne
# tk, Dk,Θk,
# tk = point of time
# Dk = order = tD, RD, VD, LD
# tD, time of request
# RD, restaurant associated with the request, Node ggf. -> man könnte darüber nachdenken, ob man hier
# VD, vehicle assigned to the Order/request
# LD, loading status of the request
# maybe better to take directly from the state, since then
# there are less likely to be any discrepancies.