diff --git a/jinete/__init__.py b/jinete/__init__.py index 5fbc89e4..a1a7fd20 100644 --- a/jinete/__init__.py +++ b/jinete/__init__.py @@ -18,8 +18,6 @@ PlannedTrip, Stop, - StopCause, - StopKind, Result, diff --git a/jinete/models/__init__.py b/jinete/models/__init__.py index 8cf62578..f46d7830 100644 --- a/jinete/models/__init__.py +++ b/jinete/models/__init__.py @@ -17,8 +17,6 @@ ) from .stops import ( Stop, - StopCause, - StopKind, ) from .criterions import ( PlannedTripCriterion, diff --git a/jinete/models/planned_trips.py b/jinete/models/planned_trips.py index b8ebdab0..f96383e7 100644 --- a/jinete/models/planned_trips.py +++ b/jinete/models/planned_trips.py @@ -10,8 +10,6 @@ ) from .stops import ( Stop, - StopCause, - StopKind, ) if TYPE_CHECKING: @@ -36,30 +34,33 @@ class PlannedTrip(Model): + __slots__ = [ + 'route', + 'trip', + 'down_time', + 'pickup_stop', + 'delivery_stop', + '_feasible', + ] + route: Route trip: Trip initial: Position down_time: float - def __init__(self, route: Route, trip: Trip, pickup_stop: Stop, delivery_stop: Stop, down_time: float = 0.0, - with_caching: bool = True): + def __init__(self, route: Route, trip: Trip, pickup_stop: Stop, delivery_stop: Stop, down_time: float = 0.0): self.route = route self.trip = trip self.down_time = down_time assert pickup_stop == delivery_stop.previous - pickup_stop.append_stop_cause( - StopCause(self, StopKind.PICKUP) - ) - delivery_stop.append_stop_cause( - StopCause(self, StopKind.DELIVERY) - ) - self.pickup_stop = pickup_stop + pickup_stop.append_pickup(self) + self.delivery_stop = delivery_stop + delivery_stop.append_delivery(self) - self.with_caching = with_caching self._feasible = None @staticmethod @@ -116,7 +117,7 @@ def capacity(self): @property def feasible(self) -> bool: - if not self.with_caching or self._feasible is None: + if self._feasible is None: self._feasible = self._calculate_feasible() return self._feasible diff --git a/jinete/models/positions.py b/jinete/models/positions.py index fae74f7e..ea3ea31b 100644 --- a/jinete/models/positions.py +++ b/jinete/models/positions.py @@ -56,6 +56,12 @@ def __init__(self, coordinates: Sequence[float], *args, **kwargs): def __hash__(self): return hash(self.coordinates) + def __eq__(self, other) -> bool: + return self.coordinates == other.coordinates + + def __ne__(self, other) -> bool: + return self.coordinates != other.coordinates + def __str__(self): c = ",".join(f"{x:07.3f}" for x in self) return f'({c})' diff --git a/jinete/models/routes.py b/jinete/models/routes.py index c77dbf35..a9102fad 100644 --- a/jinete/models/routes.py +++ b/jinete/models/routes.py @@ -16,7 +16,6 @@ ) from .stops import ( Stop, - StopKind, ) if TYPE_CHECKING: @@ -33,9 +32,6 @@ from .vehicles import ( Vehicle, ) - from .stops import ( - StopCause, - ) from .trips import ( Trip, ) @@ -72,16 +68,17 @@ def __iter__(self): @property def planned_trips(self) -> Iterator[PlannedTrip]: - yield from ( - stop_cause.planned_trip - for stop_cause in self.stop_causes - if stop_cause.kind == StopKind.DELIVERY - ) + yield from self.deliveries + + @property + def pickups(self) -> Iterator[PlannedTrip]: + for stop in self.stops: + yield from stop.pickups @property - def stop_causes(self) -> Iterator[StopCause]: + def deliveries(self) -> Iterator[PlannedTrip]: for stop in self.stops: - yield from stop.causes + yield from stop.deliveries @property def feasible(self) -> bool: diff --git a/jinete/models/stops.py b/jinete/models/stops.py index 2f21dd6d..99672ec3 100644 --- a/jinete/models/stops.py +++ b/jinete/models/stops.py @@ -7,7 +7,7 @@ from typing import ( TYPE_CHECKING, Optional, -) + Iterator) from .abc import ( Model, ) @@ -36,97 +36,62 @@ logger = logging.getLogger(__name__) -class StopKind(Enum): - PICKUP = 1 - DELIVERY = 2 - - def __str__(self): - return self.name - - -class StopCause(Model): - planned_trip: PlannedTrip - kind: StopKind - stop: Stop - - def __init__(self, planned_trip: PlannedTrip, kind: StopKind, stop: Stop = None): - self.planned_trip = planned_trip - self.kind = kind - self.stop = stop - - @property - def trip(self): - return self.planned_trip.trip - - @property - def trip_uuid(self): - return self.trip.uuid - - @property - def position(self): - return self.stop.position - - @property - def earliest(self) -> float: - return self.planned_trip.trip.earliest - - @property - def down_time(self) -> float: - return self.planned_trip.down_time - - @property - def load_time(self) -> float: - return self.planned_trip.trip.load_time - - def as_dict(self) -> Dict[str, Any]: - return { - 'position': self.position, - 'trip_uuid': self.trip_uuid, - 'kind': self.kind - } - - class Stop(Model): + __slots__ = [ + 'route', + 'position', + 'causes', + 'pickups', + 'deliveries', + 'previous', + '_previous_departure_time', + '_down_time', + '_load_time', + '_earliest', + '_arrival_time', + ] route: Route position: Position - def __init__(self, route: Route, position: Position, previous: Optional[Stop], with_caching: bool = True): + def __init__(self, route: Route, position: Position, previous: Optional[Stop]): self.route = route self.position = position - self.causes = set() - self.previous = previous + self.pickups = set() + self.deliveries = set() - self.with_caching = with_caching + self.previous = previous - self._previous_time = None + self._previous_departure_time = None self._down_time = None self._load_time = None self._earliest = None self._arrival_time = None - def append_stop_cause(self, stop_cause: StopCause) -> None: - stop_cause.stop = self - self.causes.add(stop_cause) + def append_pickup(self, planned_trip: PlannedTrip) -> None: + self.pickups.add(planned_trip) + + def append_delivery(self, planned_trip: PlannedTrip) -> None: + self.deliveries.add(planned_trip) @property def down_time(self) -> float: if self._down_time is None: - self._down_time = max((cause.down_time for cause in self.causes), default=0.0) + self._down_time = max((pt.down_time for pt in self.pickups), default=0.0) return self._down_time @property def earliest(self): if self._earliest is None: - self._earliest = max((cause.earliest for cause in self.causes), default=0.0) + self._earliest = max((pt.trip.earliest for pt in self.pickups), default=0.0) return self._earliest @property def load_time(self) -> float: if self._load_time is None: - self._load_time = max((cause.load_time for cause in self.causes), default=0.0) + self._load_time = max((pt.trip.load_time for pt in self.pickups), default=0.0) return self._load_time @property @@ -141,9 +106,9 @@ def vehicle_uuid(self) -> UUID: def previous_departure_time(self) -> float: if self.previous is None: return self.vehicle.earliest - if self._previous_time is None: - self._previous_time = self.previous.departure_time - return self._previous_time + if self._previous_departure_time is None: + self._previous_departure_time = self.previous.departure_time + return self._previous_departure_time @property def previous_position(self) -> Position: diff --git a/jinete/models/surfaces.py b/jinete/models/surfaces.py index 66d7d63b..7a3fa09d 100644 --- a/jinete/models/surfaces.py +++ b/jinete/models/surfaces.py @@ -80,20 +80,16 @@ class GeometricSurface(Surface): positions: Set[GeometricPosition] cached_distance: Dict[Position, Dict[Position, float]] - def __init__(self, metric: DistanceMetric, with_caching: bool = True, *args, **kwargs): + def __init__(self, metric: DistanceMetric, *args, **kwargs): super().__init__(*args, **kwargs) self.metric = metric self.cached_distance = defaultdict(dict) - self.with_caching = with_caching def _build_position(self, *args, **kwargs): return GeometricPosition(surface=self, *args, **kwargs) def distance(self, position_a: GeometricPosition, position_b: GeometricPosition) -> float: - if not self.with_caching: - return self.metric(position_a, position_b) - try: distance = self.cached_distance[position_a][position_b] except KeyError: