Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/ridepy/util/dispatchers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from ridepy.util.dispatchers.taxicab import TaxicabDispatcherDriveFirst
from ridepy.util.dispatchers.ridepooling import (
BruteForceTotalTravelTimeMinimizingDispatcher,
MinimalPassengerTravelTimeDispatcher,
)

"""
Expand Down
222 changes: 221 additions & 1 deletion src/ridepy/util/dispatchers/ridepooling.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from copy import deepcopy

from itertools import tee
import numpy as np

from ridepy.data_structures import (
Expand Down Expand Up @@ -209,6 +209,27 @@ def is_timewindow_violated_or_violation_worsened_due_to_insertion(
return False


def pairwise(iterable):
# A pairwise iterator.
a, b = tee(iterable)
next(b, None)
return zip(a, b)


def is_between(network, a, u, v):
"""
checks if a is on a shortest path between u and v
"""
dist_to = network.t(u, a)
dist_from = network.t(a, v)
dist_direct = network.t(u, v)
is_inbetween = dist_to + dist_from == dist_direct
if is_inbetween:
return True, dist_to, dist_from, dist_direct
else:
return False, dist_to, dist_from, dist_direct


@dispatcherclass
def BruteForceTotalTravelTimeMinimizingDispatcher(
request: TransportationRequest,
Expand Down Expand Up @@ -386,3 +407,202 @@ def BruteForceTotalTravelTimeMinimizingDispatcher(
return min_cost, new_stoplist, (EAST_pu, LAST_pu, EAST_do, LAST_do)
else:
return min_cost, None, (np.nan, np.nan, np.nan, np.nan)


@dispatcherclass
def MinimalPassengerTravelTimeDispatcher(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name is possibly not optimal. As far as I understand, the dispatcher only accepts requests for which both pick-up and delivery locations lie on existing vehicle routes, except if the request can be appended? Or did I confuse it? I didn't fully read the code, yet.

request: TransportationRequest,
stoplist: Stoplist,
space: TransportSpace,
seat_capacity: int,
) -> DispatcherSolution:
"""
#FIXME Add description
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be important :)

"""
min_cost = np.inf
boolInsertEnd = True
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use snake_case for all Python variables instead of camelCase, as per convention.

best_pickup_idx = len(stoplist) - 1
best_dropoff_idx = len(stoplist) - 1

for counter in range(0, len(stoplist) - 1):
stop_before_pickup = stoplist[counter]
stop_after_pickup = stoplist[counter + 1]
listResultInBetweenTest = is_between(
space,
request.origin,
stop_before_pickup.location,
stop_after_pickup.location,
)
if listResultInBetweenTest[0] == True and listResultInBetweenTest[2] != 0:
if stop_before_pickup.occupancy_after_servicing == seat_capacity:
continue
time_to_pickup = space.t(stop_before_pickup.location, request.origin)
CPAT_pu = cpat_of_inserted_stop(stop_before_pickup, time_to_pickup)
EAST_pu = request.pickup_timewindow_min
if CPAT_pu > request.pickup_timewindow_max:
continue
CPAT_do = max(EAST_pu, CPAT_pu) + space.t(
request.origin, request.destination
)
if CPAT_do > request.delivery_timewindow_max:
continue

best_pickup_idx = counter
boolDropOffEnroute = False
boolContinuePickUpLoop = False
boolBreakPickUpLoop = False

# Check if drop-off is between pick-up and next stop

listResultInBetweenTestFollowingPickUp = is_between(
space, request.destination, request.origin, stop_after_pickup.location
)
if (
listResultInBetweenTestFollowingPickUp[0] == True
and listResultInBetweenTestFollowingPickUp[2] != 0
):
# Time violation and seat capacity error not possilbe
# As long as now drop-off time restriction is used
# Ganz grosse Skepsis hier ...
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

best_dropoff_idx = counter
min_cost = CPAT_pu
boolDropOffEnroute = True
boolInsertEnd = False
break

for counter_drop_off, (
stop_before_dropoff,
stop_after_dropoff,
) in enumerate(pairwise(stoplist[best_pickup_idx:])):
if counter_drop_off == 0:
continue
listResultInBetweenTestDropOff = is_between(
space,
request.destination,
stop_before_dropoff.location,
stop_after_dropoff.location,
)
if (
listResultInBetweenTestDropOff[0] == True
and listResultInBetweenTestDropOff[1] != 0
):
best_dropoff_idx = counter + counter_drop_off
time_to_dropoff = space.t(
stop_before_dropoff.location, request.destination
)
CPAT_do = cpat_of_inserted_stop(
stop_before_dropoff, time_to_dropoff, delta_cpat=0
)
stoplist_request_in_vehicle = stoplist[
best_pickup_idx : best_dropoff_idx + 1
]

# occupancies_ausschnitt = list(map(lambda x: x.occupancy_after_servicing, stoplist_request_in_vehicle))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?


occupancies_ausschnitt = []
for x in stoplist_request_in_vehicle:
occupancies_ausschnitt.append(x.occupancy_after_servicing)

if seat_capacity in occupancies_ausschnitt:
boolContinuePickUpLoop = True
break
if CPAT_do > request.delivery_timewindow_max:
# Pick-Up kann direkt fortgesetzt werden, da in diesem Fall auch der Drop-Off am Ende sicher scheitern wird
boolContinuePickUpLoop = True
break
boolInsertEnd = False
min_cost = CPAT_do
boolDropOffEnroute = True
boolBreakPickUpLoop = True
break

if boolBreakPickUpLoop:
break

if boolContinuePickUpLoop:
best_pickup_idx = len(stoplist) - 1
best_dropoff_idx = len(stoplist) - 1
continue

if not boolDropOffEnroute:
best_dropoff_idx = len(stoplist) - 1
stop_before_dropoff = stoplist[-1]
time_to_dropoff = space.t(
stop_before_dropoff.location, request.destination
)
CPAT_do = cpat_of_inserted_stop(
stop_before_dropoff, time_to_dropoff, delta_cpat=0
)
# Check time violations?
# Hier muss ueberprueft werden, ob druch das einfügen irgendwo die seat capacity verletzt wird
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wird es?

stoplist_request_in_vehicle = stoplist[
best_pickup_idx : best_dropoff_idx + 1
]
# occupancies_ausschnitt = list(map(lambda x: x.occupancy_after_servicing, stoplist_request_in_vehicle))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?


occupancies_ausschnitt = []
for x in stoplist_request_in_vehicle:
occupancies_ausschnitt.append(x.occupancy_after_servicing)

if seat_capacity in occupancies_ausschnitt:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

occupancies_ausschnitt should be changed into some English word.

best_pickup_idx = len(stoplist) - 1
best_dropoff_idx = len(stoplist) - 1
continue
if CPAT_do > request.delivery_timewindow_max:
best_pickup_idx = len(stoplist) - 1
best_dropoff_idx = len(stoplist) - 1
continue
boolInsertEnd = False
min_cost = CPAT_do
break
else:
continue

if boolInsertEnd:
best_pickup_idx = len(stoplist) - 1
best_dropoff_idx = len(stoplist) - 1
time_to_pickup = space.t(stoplist[best_pickup_idx].location, request.origin)
CPAT_pu = cpat_of_inserted_stop(stoplist[best_pickup_idx], time_to_pickup)
EAST_pu = request.pickup_timewindow_min
CPAT_do = max(EAST_pu, CPAT_pu) + space.t(request.origin, request.destination)
if CPAT_pu > request.pickup_timewindow_max:
min_cost = np.inf
elif CPAT_do > request.delivery_timewindow_max:
min_cost = np.inf
else:
min_cost = CPAT_do

if min_cost < np.inf:
new_stoplist = insert_request_to_stoplist_drive_first(
stoplist=stoplist,
request=request,
pickup_idx=best_pickup_idx,
dropoff_idx=best_dropoff_idx,
space=space,
)
EAST_pu, LAST_pu = (
new_stoplist[best_pickup_idx + 1].time_window_min,
new_stoplist[best_pickup_idx + 1].time_window_max,
)
EAST_do, LAST_do = (
new_stoplist[best_dropoff_idx + 2].time_window_min,
new_stoplist[best_dropoff_idx + 2].time_window_max,
)

listOccupanciesNewStopList = list(
map(lambda x: x.occupancy_after_servicing, new_stoplist)
)
for item in listOccupanciesNewStopList:
if item > seat_capacity:
print("Seat capacity error!!")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this print statement. Normally, the dispatcher should not print anything. If indeed an unexpected error happens, this should be raised.


for item in new_stoplist[1:]:
request_item = item.request
if item.action.name == "pickup":
if item.estimated_arrival_time > request_item.pickup_timewindow_max:
print("Time violation!!")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above: I don't understand this print statement. Normally, the dispatcher should not print anything. If indeed an unexpected error happens, this should be raised.

continue

return min_cost, new_stoplist, (EAST_pu, LAST_pu, EAST_do, LAST_do)
else:
return min_cost, None, (np.nan, np.nan, np.nan, np.nan)
1 change: 1 addition & 0 deletions src/ridepy/util/dispatchers_cython/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .dispatchers import (
BruteForceTotalTravelTimeMinimizingDispatcher,
MinimalPassengerTravelTimeDispatcher,
SimpleEllipseDispatcher,
)
Loading