Skip to content

Commit

Permalink
UI : Fastvrpy starts from existing route if it exists + fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Pierre-Graber committed Apr 6, 2023
1 parent fc8bba4 commit 76861c5
Show file tree
Hide file tree
Showing 14 changed files with 111 additions and 74 deletions.
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ RUN install -d --owner app /srv/app/archives
USER root
WORKDIR /srv/app

RUN pip3 install unconstrained-initialization/dependencies/fastvrpy-0.4.2.tar.gz --user
RUN pip3 install unconstrained-initialization/dependencies/fastvrpy-0.5.2.tar.gz --user



Expand Down
2 changes: 2 additions & 0 deletions unconstrained-initialization/blackboard/blackboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ def __init__(self):
self.free_approach = None
self.force_return = None
self.rests = None
self.vehicle_id_index = None
self.vehicle_time_window_margin = None

def add_knowledge_source(self, knowledge_source):
"""Adds a new knowlegde source to the blackboard
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def process(self):

rests = list_all_rests(problem)

num_TW = max(len(service.get('timeWindows',[])) for service in problem['services'])
num_TW = max(max(len(service.get('timeWindows',[])) for service in problem['services']),1)

# Services attributes
services_TW_starts = numpy.full((num_services, num_TW), 0, dtype=numpy.float64)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def process(self):
vehicles_capacities = [[] for i in range (self.blackboard.num_vehicle) ]
vehicles_TW_starts = []
vehicles_TW_ends = []
vehicles_TW_margin = []
vehicles_distance_max = []
vehicles_duration_max = []
vehicles_fixed_costs = []
Expand All @@ -66,7 +67,7 @@ def process(self):
if shift_preference == "force_start":
force_start.append(2)
else :
force_start.append(0)
force_start.append(1)

vehicles_fixed_costs.append(vehicle.get("costFixed", 0))
if 'capacities' in vehicle:
Expand All @@ -84,6 +85,10 @@ def process(self):
cost_time_multiplier.append(vehicle.get('costTimeMultiplier'))
vehicles_TW_starts.append(vehicle["timeWindow"].get("start",0))
vehicles_TW_ends.append(vehicle["timeWindow"].get("end",-1))
if vehicle.get("costLateMultiplier", 0) > 0:
vehicles_TW_margin.append(vehicle.get("maximumLateness", 0))
else :
vehicles_TW_margin.append(0)
distance_max = vehicle.get("distance",0)
if distance_max==0:
vehicles_distance_max.append(-1)
Expand All @@ -107,6 +112,7 @@ def process(self):
self.blackboard.vehicle_capacities = numpy.array(vehicles_capacities, dtype=numpy.float64)
self.blackboard.vehicles_TW_starts = numpy.array(vehicles_TW_starts, dtype=numpy.float64)
self.blackboard.vehicles_TW_ends = numpy.array(vehicles_TW_ends, dtype=numpy.float64)
self.blackboard.vehicle_time_window_margin = numpy.array(vehicles_TW_margin, dtype=numpy.float64)
self.blackboard.vehicles_distance_max = numpy.array(vehicles_distance_max, dtype=numpy.float64)
self.blackboard.vehicles_duration_max = numpy.array(vehicles_duration_max, dtype=numpy.float64)
self.blackboard.vehicles_fixed_costs = numpy.array(vehicles_fixed_costs, dtype=numpy.float64)
Expand All @@ -120,6 +126,8 @@ def process(self):
self.blackboard.vehicle_start_index = numpy.array(vehicle_start_index, dtype=numpy.int32)
self.blackboard.previous_vehicle = numpy.array([ -1 for _ in range(self.blackboard.num_vehicle)], dtype= numpy.int32)

self.blackboard.vehicle_id_index = vehicle_id_index

if "relations" in problem :
for relation in problem['relations']:
if relation['type'] == "vehicle_trips":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ def process(self):

solver.optimize(
solution = self.blackboard.solution,
max_execution_time=int(self.blackboard.time_limit/2),
max_execution_time=int(self.blackboard.time_limit),
problem=self.blackboard.problem,
groups_max_capacity = self.blackboard.max_capacity
groups_max_capacity = self.blackboard.max_capacity,
grouping = False
)
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ def process(self):
store_return.start_time = int(self.blackboard.solution.vehicle_ends[path_index])
store_return.type = "end"
cost_details = route.cost_details
cost_details.fixed = 0
cost_details.fixed = solution.vehicle_fixed_costs[path_index]
cost_details.distance = solution.distances[path_index] * solution.cost_distance_multiplier[path_index]
cost_details.time = solution.travel_times[path_index] * solution.cost_time_multiplier[path_index]

else:
route = result.routes.add()
start_route = route.activities.add()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,38 +40,61 @@ def process(self):
matrix_size = self.blackboard.problem["matrices"][0]["size"]
problem = self.blackboard.problem

for serviceFrom in problem["services"]:
matrix_row = []
for serviceTo in problem["services"]:
matrix_row.append(time_matrix[serviceFrom["matrixIndex"] * matrix_size + serviceTo["matrixIndex"]])
matrix.append(matrix_row)

matrix = numpy.array(matrix)

cluster = AgglomerativeClustering(n_clusters=min(num_vehicle, matrix.shape[0]), metric='precomputed', linkage='complete').fit(matrix)
log.debug("-- Compute initial solution")
num_services = numpy.zeros(num_vehicle, dtype=int)
for i in range(0, cluster.labels_.size):
vehicle = cluster.labels_[i]
num_services[vehicle] += 1

max_capacity = numpy.max(num_services) + 10 #Add margin to let algorithm the possibility to optimize something
num_services = numpy.zeros(num_vehicle, dtype=int)
self.blackboard.paths = numpy.full((num_vehicle, self.blackboard.num_services + 1), -1, dtype=numpy.int32)
for i in range(0, cluster.labels_.size):
vehicle = cluster.labels_[i]
position = num_services[vehicle]
self.blackboard.paths[vehicle][position] = i
num_services[vehicle] += 1

reverse_services_dict = {}
for index, service_id in self.blackboard.service_index_to_id.items():
reverse_services_dict[service_id] = index

for rest in self.blackboard.rests:
print(f"rest :{rest}")
vehicle = rest[1]
index = reverse_services_dict[rest[0].get("id")]
self.blackboard.paths[vehicle][num_services[vehicle]] = index
num_services[vehicle] += 1
print(f" paths au début : {numpy.array(self.blackboard.paths)}")
routes = problem.get("routes", [])

log.info(f" routes : {routes}")
log.info(f"vehicle_id_index {self.blackboard.vehicle_id_index}")

if len(routes) > 0:
service_id_to_index = {value: key for key, value in self.blackboard.service_index_to_id.items()}
self.blackboard.unassigned_services = numpy.full(self.blackboard.num_services + 1, -1, dtype=numpy.int32)
self.blackboard.paths = numpy.full((num_vehicle, self.blackboard.num_services + 1), -1, dtype=numpy.int32)
for route in routes:
vehicle_id = route.get("vehicleId")
vehicle_index = self.blackboard.vehicle_id_index[vehicle_id]
for service_index_in_route, service_id in enumerate(route.get("serviceIds")):
service_index = service_id_to_index[service_id]
self.blackboard.paths[vehicle_index, service_index_in_route] = service_index
for service_index in range (self.blackboard.num_services):
if not numpy.any(numpy.isin(self.blackboard.paths, service_index)):
self.blackboard.unassigned_services[service_index] = service_index
mask = self.blackboard.unassigned_services == -1

self.blackboard.unassigned_services = numpy.concatenate((self.blackboard.unassigned_services[~mask], self.blackboard.unassigned_services[mask]))


else :
self.blackboard.unassigned_services = numpy.full(self.blackboard.num_services + 1, -1, dtype=numpy.int32)
for serviceFrom in problem["services"]:
matrix_row = []
for serviceTo in problem["services"]:
matrix_row.append(time_matrix[serviceFrom["matrixIndex"] * matrix_size + serviceTo["matrixIndex"]])
matrix.append(matrix_row)

matrix = numpy.array(matrix)

cluster = AgglomerativeClustering(n_clusters=min(num_vehicle, matrix.shape[0]), metric='precomputed', linkage='complete').fit(matrix)
log.debug("-- Compute initial solution")
num_services = numpy.zeros(num_vehicle, dtype=int)
for i in range(0, cluster.labels_.size):
vehicle = cluster.labels_[i]
num_services[vehicle] += 1

max_capacity = numpy.max(num_services) + 10 #Add margin to let algorithm the possibility to optimize something
num_services = numpy.zeros(num_vehicle, dtype=int)
self.blackboard.paths = numpy.full((num_vehicle, self.blackboard.num_services + 1), -1, dtype=numpy.int32)
for i in range(0, cluster.labels_.size):
vehicle = cluster.labels_[i]
position = num_services[vehicle]
self.blackboard.paths[vehicle][position] = i
num_services[vehicle] += 1

reverse_services_dict = {}
for index, service_id in self.blackboard.service_index_to_id.items():
reverse_services_dict[service_id] = index

for rest in self.blackboard.rests:
vehicle = rest[1]
index = reverse_services_dict[rest[0].get("id")]
self.blackboard.paths[vehicle][num_services[vehicle]] = index
num_services[vehicle] += 1
Original file line number Diff line number Diff line change
Expand Up @@ -121,38 +121,38 @@ def verify(self):
return True

def process(self):
print(f" start tw : {numpy.array(self.blackboard.start_tw)}")
self.blackboard.solution = cvrptw.CVRPTW(
self.blackboard.paths,
self.blackboard.distance_matrices,
self.blackboard.time_matrices,
self.blackboard.num_services,
self.blackboard.start_tw,
self.blackboard.end_tw,
self.blackboard.services_max_lateness,
self.blackboard.durations,
self.blackboard.setup_durations,
self.blackboard.services_volumes,
self.blackboard.service_matrix_index,
self.blackboard.cost_distance_multiplier,
self.blackboard.cost_time_multiplier,
self.blackboard.vehicle_capacities,
self.blackboard.previous_vehicle,
self.blackboard.vehicles_distance_max,
self.blackboard.vehicles_duration_max,
self.blackboard.vehicles_fixed_costs,
self.blackboard.vehicles_overload_multiplier,
self.blackboard.vehicles_TW_starts,
self.blackboard.vehicles_TW_ends,
self.blackboard.vehicles_matrix_index,
self.blackboard.vehicle_start_index,
self.blackboard.vehicle_end_index,
self.blackboard.force_start,
self.blackboard.free_approach,
self.blackboard.free_return,
None,
None,
self.blackboard.is_break,
self.blackboard.service_sticky_vehicles,
self.blackboard.num_units
paths = self.blackboard.paths,
distance_matrix = self.blackboard.distance_matrices,
time_matrix = self.blackboard.time_matrices,
num_services = self.blackboard.num_services,
start_time_windows = self.blackboard.start_tw,
end_time_windows = self.blackboard.end_tw,
time_windows_margin = self.blackboard.services_max_lateness,
durations = self.blackboard.durations,
setup_durations = self.blackboard.setup_durations,
services_volumes = self.blackboard.services_volumes,
service_matrix_index = self.blackboard.service_matrix_index,
cost_distance_multiplier = self.blackboard.cost_distance_multiplier,
cost_time_multiplier = self.blackboard.cost_time_multiplier,
vehicle_capacities = self.blackboard.vehicle_capacities,
previous_vehicle = self.blackboard.previous_vehicle,
vehicle_max_distance = self.blackboard.vehicles_distance_max,
vehicle_max_travel_time = self.blackboard.vehicles_duration_max,
vehicle_fixed_costs = self.blackboard.vehicles_fixed_costs,
vehicle_overload_multiplier = self.blackboard.vehicles_overload_multiplier,
vehicle_start_time_window = self.blackboard.vehicles_TW_starts,
vehicle_end_time_window = self.blackboard.vehicles_TW_ends,
vehicle_time_window_margin = self.blackboard.vehicle_time_window_margin,
vehicle_matrix_index = self.blackboard.vehicles_matrix_index,
vehicle_start_index = self.blackboard.vehicle_start_index,
vehicle_end_index = self.blackboard.vehicle_end_index,
vehicle_start_mode = self.blackboard.force_start,
free_approach = self.blackboard.free_approach,
free_return = self.blackboard.free_return,
unassigned_services = self.blackboard.unassigned_services,
predecessor_successor_gap = None,
is_break = self.blackboard.is_break,
sticky_vehicles = self.blackboard.service_sticky_vehicles,
num_units = self.blackboard.num_units
)

0 comments on commit 76861c5

Please # to comment.