I modified the original vrptw.py sample and want to set break for couple vehicles/routes.
from __future__ import print_function
from ortools.constraint_solver import pywrapcp
from ortools.constraint_solver import routing_enums_pb2
def create_data_model():
"""Stores the data for the problem."""
data = {}
data['time_matrix'] = [
[0, 6, 9, 8, 7, 3, 6, 2, 3, 2, 6, 6, 4, 4, 5, 9, 7],
[6, 0, 8, 3, 2, 6, 8, 4, 8, 8, 13, 7, 5, 8, 12, 10, 14],
[9, 8, 0, 11, 10, 6, 3, 9, 5, 8, 4, 15, 14, 13, 9, 18, 9],
[8, 3, 11, 0, 1, 7, 10, 6, 10, 10, 14, 6, 7, 9, 14, 6, 16],
[7, 2, 10, 1, 0, 6, 9, 4, 8, 9, 13, 4, 6, 8, 12, 8, 14],
[3, 6, 6, 7, 6, 0, 2, 3, 2, 2, 7, 9, 7, 7, 6, 12, 8],
[6, 8, 3, 10, 9, 2, 0, 6, 2, 5, 4, 12, 10, 10, 6, 15, 5],
[2, 4, 9, 6, 4, 3, 6, 0, 4, 4, 8, 5, 4, 3, 7, 8, 10],
[3, 8, 5, 10, 8, 2, 2, 4, 0, 3, 4, 9, 8, 7, 3, 13, 6],
[2, 8, 8, 10, 9, 2, 5, 4, 3, 0, 4, 6, 5, 4, 3, 9, 5],
[6, 13, 4, 14, 13, 7, 4, 8, 4, 4, 0, 10, 9, 8, 4, 13, 4],
[6, 7, 15, 6, 4, 9, 12, 5, 9, 6, 10, 0, 1, 3, 7, 3, 10],
[4, 5, 14, 7, 6, 7, 10, 4, 8, 5, 9, 1, 0, 2, 6, 4, 8],
[4, 8, 13, 9, 8, 7, 10, 3, 7, 4, 8, 3, 2, 0, 4, 5, 6],
[5, 12, 9, 14, 12, 6, 6, 7, 3, 3, 4, 7, 6, 4, 0, 9, 2],
[9, 10, 18, 6, 8, 12, 15, 8, 13, 9, 13, 3, 4, 5, 9, 0, 9],
[7, 14, 9, 16, 14, 8, 5, 10, 6, 5, 4, 10, 8, 6, 2, 9, 0],
]
import numpy as np
# data['time_matrix'] = np.full(np.array(data['time_matrixs']).shape, fill_value=1)
# data['time_matrix'] = np.array(data['time_matrixs'])[np.array(data['time_matrixs']) == 0] == 0
data['time_windows'] = [
(0, 10), # depot
(7, 12), # 1
(10, 15), # 2
(16, 18), # 3
(10, 13), # 4
(5, 30), # 5
(5, 10), # 6
(5, 30), # 7
(5, 10), # 8
(5, 10), # 9
(10, 16), # 10
(10, 20), # 11
(5, 30), # 12
(5, 11), # 13
(7, 30), # 14
(10, 19), # 15
(11, 15), # 16
]
data['num_vehicles'] = 4
data['depot'] = 0
return data
def print_solution(data, manager, routing, assignment):
"""Prints assignment on console."""
time_dimension = routing.GetDimensionOrDie('Time')
total_time = 0
print('Breaks:')
intervals = assignment.IntervalVarContainer()
for i in range(intervals.Size()):
brk = intervals.Element(i)
if brk.PerformedValue() == 1:
print('{}: Start({}) Duration({})'.format(
brk.Var().Name(),
brk.StartValue(),
brk.DurationValue()))
else:
print('{}: Unperformed'.format(brk.Var().Name()))
print()
for vehicle_id in range(data['num_vehicles']):
index = routing.Start(vehicle_id)
plan_output = 'Route for vehicle {}:\n'.format(vehicle_id)
while not routing.IsEnd(index):
time_var = time_dimension.CumulVar(index)
slack_var = time_dimension.SlackVar(index)
plan_output += '{0} Time({1},{2}) Slack({3},{4}) -> '.format(
manager.IndexToNode(index), assignment.Min(time_var),
assignment.Max(time_var), assignment.Min(slack_var), assignment.Max(slack_var))
index = assignment.Value(routing.NextVar(index))
time_var = time_dimension.CumulVar(index)
plan_output += '{0} Time({1},{2})\n'.format(manager.IndexToNode(index),
assignment.Min(time_var),
assignment.Max(time_var))
plan_output += 'Time of the route: {}min\n'.format(
assignment.Min(time_var))
print(plan_output)
total_time += assignment.Min(time_var)
print('Total time of all routes: {}min'.format(total_time))
slack_var = time_dimension.SlackVar(int(2))
print(slack_var.Bound())
if slack_var.Bound():
slack_min = assignment.Min(slack_var)
slack_max = assignment.Max(slack_var)
# print("assignment.Min(slack_var): ", assignment.Value(slack_var))
def main():
"""Solve the VRP with time windows."""
data = create_data_model()
manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']), data['num_vehicles'], data['depot'])
routing = pywrapcp.RoutingModel(manager)
def time_callback(from_index, to_index):
"""Returns the travel time between the two nodes."""
# Convert from routing variable Index to time matrix NodeIndex.
if from_index == to_index: return 0
return 1
# from_node = manager.IndexToNode(from_index)
# to_node = manager.IndexToNode(to_index)
# return data['time_matrix'][from_node][to_node]
transit_callback_index = routing.RegisterTransitCallback(time_callback)
routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)
time = 'Time'
routing.AddDimension(
transit_callback_index,
30*100, # allow waiting time
50, # maximum time per vehicle
False, # Don't force start cumul to zero.
time)
time_dimension = routing.GetDimensionOrDie(time)
# Add breaks TODO Uncomment
node_visit_transit = {}
for n in range(routing.Size()):
if n >= len(data['time_windows']):
node_visit_transit[n] = 0
else:
node_visit_transit[n] = 0 # int(data['demands'][n] * data['time_per_demand_unit'])
break_intervals = {}
# for v in xrange(data['num_vehicles']):
for v in [0,1]:
# vehicle_break = data['breaks'][v]
break_intervals[v] = [
routing.solver().FixedDurationIntervalVar(
0, 0, 1, False, 'Break for vehicle {}'.format(v))
]
time_dimension.SetBreakIntervalsOfVehicle(
break_intervals[v], v, node_visit_transit)
# Add time window constraints for each location except depot.
for location_idx, time_window in enumerate(data['time_windows']):
if location_idx == 0:
continue
index = manager.NodeToIndex(location_idx)
time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])
routing.AddToAssignment(time_dimension.SlackVar(index))
# Add time window constraints for each vehicle start node.
for vehicle_id in range(data['num_vehicles']):
index = routing.Start(vehicle_id)
time_dimension.CumulVar(index).SetRange(data['time_windows'][0][0], data['time_windows'][0][1])
routing.AddToAssignment(time_dimension.SlackVar(index))
for i in range(data['num_vehicles']):
routing.AddVariableMinimizedByFinalizer(
time_dimension.CumulVar(routing.Start(i)))
routing.AddVariableMinimizedByFinalizer(
time_dimension.CumulVar(routing.End(i)))
search_parameters = pywrapcp.DefaultRoutingSearchParameters()
search_parameters.first_solution_strategy = (
routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)
search_parameters.time_limit.seconds = 5
# search_parameters.log_search = True
assignment = routing.SolveWithParameters(search_parameters)
if assignment:
print_solution(data, manager, routing, assignment)
if __name__ == '__main__':
main()
Note:
Transit time is exactly 1
number of vehicles: 4
The break is at the beging
The problem is when I set break (node_visit_transit=1) for more than 2 vehicles, it stucks.
Could you please explain what's wrong with code and why it stuck?
P.S. When I set break for only one vehicle[ex:0 and 1], the output is as following:
Breaks:
Break for vehicle 0: Start(0) Duration(1)
Break for vehicle 1: Start(0) Duration(1)
Route for vehicle 0:
0 Time(1,1) Slack(0,0) -> 0 Time(2,2)
Time of the route: 2min
Route for vehicle 1:
0 Time(1,1) Slack(16,16) -> 0 Time(18,18)
Time of the route: 18min
Route for vehicle 2:
0 Time(0,0) Slack(4,6) -> 13 Time(5,7) Slack(0,2) -> 9 Time(6,8) Slack(0,2) -> 8 Time(7,9) Slack(0,2) -> 6 Time(8,10) Slack(0,2) -> 2 Time(10,11) Slack(0,1) -> 1 Time(11,12) Slack(0,1) -> 4 Time(12,13) Slack(2,3) -> 3 Time(16,16) Slack(0,0) -> 0 Time(17,17)
Time of the route: 17min
Route for vehicle 3:
0 Time(0,0) Slack(10,10) -> 16 Time(11,11) Slack(0,0) -> 15 Time(12,12) Slack(0,0) -> 14 Time(13,13) Slack(0,0) -> 12 Time(14,14) Slack(0,0) -> 11 Time(15,15) Slack(0,0) -> 10 Time(16,16) Slack(0,0) -> 7 Time(17,17) Slack(0,0) -> 5 Time(18,18) Slack(0,0) -> 0 Time(19,19)
Time of the route: 19min
Total time of all routes: 56min
False
Please note, The slack and time for route 2 and 3 of depot is strange
I have a 12x4 matrix in MATLAB,
A =[-1, 3, 152, 41.5 ;
3, 9, 152, 38.7 ;
9, 16, 152, 38.7 ;
16, 23, 129, 53.5 ;
23, 29, 129, 53.5 ;
29, 30, 100, 100 ;
30, 30.5, 83, 83 ;
30.5, 31, 83, 83 ;
31, 35, 83, 83 ;
35, 41, 129, 53.5 ;
41, 48, 129, 53.5 ;
48, 55, 152, 38.7 ] ;
and I need to find the changes in the rows by subtracting the 3rd column element of the 2nd row from the previous row 3rd column element if they are different else go to the 3rd row if the same.
The answer should be in the form:
B = [16, 23;
29, 29;
30, 17;
35, 46;
48, 23]
For example, the 3rd and the 4th row 3rd column elements are different, so if subtracted i got 23. Output B 1st column element will consist of the 4th row first column element.
%Given matrix
A =[-1, 3, 152, 41.5 ;
3, 9, 152, 38.7 ;
9, 16, 152, 38.7 ;
16, 23, 129, 53.5 ;
23, 29, 129, 53.5 ;
29, 30, 100, 100 ;
30, 30.5, 83, 83 ;
30.5, 31, 83, 83 ;
31, 35, 83, 83 ;
35, 41, 129, 53.5 ;
41, 48, 129, 53.5 ;
48, 55, 152, 38.7 ] ;
B=A(:,2:3); %Taking out the columns of our interest
B = B([diff(B(:,2))~=0; true],:); %Storing only those rows whose consecutive elements in the third column of A are different
B=[B(1:end-1,1) abs(diff(B(:,2)))] % First column is according to your condition and second column is the difference
I have the following problem: I need to build the scatterplot of the data. Everything nice, but there is some duplicate data there:
x = [11, 10, 3, 8, 2, 6, 2, 3, 3, 2, 3, 2, 3, 2, 2, 2, 3, 3, 2, 2];
y = [29, 14, 28, 19, 25, 21, 27, 15, 24, 23, 23, 18, 0, 26, 11, 27, 23, 30, 30, 25];
One can see that there are two elements with (2, 25); (2,27); (3,24);
So if to build this data with a regular scatter(x,y) I am loosing this information:
The way out of this I have found is to use undocumented 'jitter' parameter
scatter(x,y, 'jitter','on', 'jitterAmount', 0.06);
But I do not like the outlook:
What I was trying to achieve is this:
Where the number of duplicates is next to the point (if the number is more than 1), or may be inside the point.
Any idea how to achieve this?
You can do that pretty easily, let's cut it down in two parts:
First you're gonna need to identify the unique 2d points and count them. That's what we have the unique and accumarray function for. Read through the documentation if you don't immediately understand what they're doing and what outputs they have:
x = [11 10 3 8 2 6 2 3 3 2 3 2 3 2 2 2 3 3 2 2];
y = [29 14 28 19 25 21 27 15 24 23 23 18 0 26 11 27 23 30 30 25];
A=[x' y'];
[Auniq,~,IC] = unique(A,'rows');
cnt = accumarray(IC,1);
Now each row of Auniq contains the unique 2d points, while cnt contains the number of occurences of each of those points:
>> [cnt Auniq]
ans =
1 2 11
1 2 18
1 2 23
2 2 25
1 2 26
...etc
For displaying the number of occurences, there are a great many possibilities. As you mentioned, you could put the numbers inside/next to the scatter markers, other options are color encoding, size of the markers,... let's do all of these, you can also of course combine!
Number next to marker
scatter(Auniq(:,1), Auniq(:,2));
for ii=1:numel(cnt)
if cnt(ii)>1
text(Auniq(ii,1)+0.2,Auniq(ii,2),num2str(cnt(ii)), ...
'HorizontalAlignment','left', ...
'VerticalAlignment','middle', ...
'FontSize', 6);
end
end
xlim([1 11]);ylim([0 30]);
Number inside marker
scatter(Auniq(:,1), Auniq(:,2), (6+2*(cnt>1)).^2); % make the ones where we'll put a number inside a bit bigger
for ii=1:numel(cnt)
if cnt(ii)>1
text(Auniq(ii,1),Auniq(ii,2),num2str(cnt(ii)), ...
'HorizontalAlignment','center', ...
'VerticalAlignment','middle', ...
'FontSize', 6);
end
end
as you can see, I enlarged the size of the markers very simply with the scatter function itself.
Color encoding
scatter(Auniq(:,1), Auniq(:,2), [], cnt);
colormap(jet(max(cnt))); % just for the looks of it
after which you can add a colorbar or legend to indicate the number of occurences per color.