Simple VRP example.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <cstdint>
17#include <cstdlib>
18#include <sstream>
19#include <string>
20#include <utility>
21#include <vector>
22
29
30
31
33
34struct DataModel {
35 const std::vector<std::vector<int64_t>> time_matrix{
36 {0, 6, 9, 8, 7, 3, 6, 2, 3, 2, 6, 6, 4, 4, 5, 9, 7},
37 {6, 0, 8, 3, 2, 6, 8, 4, 8, 8, 13, 7, 5, 8, 12, 10, 14},
38 {9, 8, 0, 11, 10, 6, 3, 9, 5, 8, 4, 15, 14, 13, 9, 18, 9},
39 {8, 3, 11, 0, 1, 7, 10, 6, 10, 10, 14, 6, 7, 9, 14, 6, 16},
40 {7, 2, 10, 1, 0, 6, 9, 4, 8, 9, 13, 4, 6, 8, 12, 8, 14},
41 {3, 6, 6, 7, 6, 0, 2, 3, 2, 2, 7, 9, 7, 7, 6, 12, 8},
42 {6, 8, 3, 10, 9, 2, 0, 6, 2, 5, 4, 12, 10, 10, 6, 15, 5},
43 {2, 4, 9, 6, 4, 3, 6, 0, 4, 4, 8, 5, 4, 3, 7, 8, 10},
44 {3, 8, 5, 10, 8, 2, 2, 4, 0, 3, 4, 9, 8, 7, 3, 13, 6},
45 {2, 8, 8, 10, 9, 2, 5, 4, 3, 0, 4, 6, 5, 4, 3, 9, 5},
46 {6, 13, 4, 14, 13, 7, 4, 8, 4, 4, 0, 10, 9, 8, 4, 13, 4},
47 {6, 7, 15, 6, 4, 9, 12, 5, 9, 6, 10, 0, 1, 3, 7, 3, 10},
48 {4, 5, 14, 7, 6, 7, 10, 4, 8, 5, 9, 1, 0, 2, 6, 4, 8},
49 {4, 8, 13, 9, 8, 7, 10, 3, 7, 4, 8, 3, 2, 0, 4, 5, 6},
50 {5, 12, 9, 14, 12, 6, 6, 7, 3, 3, 4, 7, 6, 4, 0, 9, 2},
51 {9, 10, 18, 6, 8, 12, 15, 8, 13, 9, 13, 3, 4, 5, 9, 0, 9},
52 {7, 14, 9, 16, 14, 8, 5, 10, 6, 5, 4, 10, 8, 6, 2, 9, 0},
53 };
54 const std::vector<std::pair<int64_t, int64_t>> time_windows{
55 {0, 5},
56 {7, 12},
57 {10, 15},
58 {16, 18},
59 {10, 13},
60 {0, 5},
61 {5, 10},
62 {0, 4},
63 {5, 10},
64 {0, 3},
65 {10, 16},
66 {10, 15},
67 {0, 5},
68 {5, 10},
69 {7, 8},
70 {10, 15},
71 {11, 15},
72 };
73 const int num_vehicles = 4;
74 const RoutingIndexManager::NodeIndex depot{0};
75};
76
77
78
84void PrintSolution(const DataModel& data, const RoutingIndexManager& manager,
85 const RoutingModel& routing,
const Assignment&
solution) {
86 const RoutingDimension& time_dimension = routing.GetDimensionOrDie("Time");
87 int64_t total_time{0};
88 for (int vehicle_id = 0; vehicle_id < data.num_vehicles; ++vehicle_id) {
89 if (!routing.IsVehicleUsed(
solution, vehicle_id)) {
90 continue;
91 }
92 int64_t index = routing.Start(vehicle_id);
93 LOG(INFO) << "Route for vehicle " << vehicle_id << ":";
94 std::ostringstream route;
95 while (!routing.IsEnd(index)) {
96 auto time_var = time_dimension.CumulVar(index);
97 route << manager.IndexToNode(index).value() << " Time("
99 << ") -> ";
100 index =
solution.Value(routing.NextVar(index));
101 }
102 auto time_var = time_dimension.CumulVar(index);
103 LOG(INFO) << route.str() << manager.IndexToNode(index).value() << " Time("
105 << ")";
106 LOG(INFO) <<
"Time of the route: " <<
solution.Min(time_var) <<
"min";
107 total_time +=
solution.Min(time_var);
108 }
109 LOG(INFO) << "Total time of all routes: " << total_time << "min";
110 LOG(INFO) << "";
111 LOG(INFO) << "Advanced usage:";
112 LOG(INFO) << "Problem solved in " << routing.solver()->wall_time() << "ms";
113}
114
115
116void VrpTimeWindows() {
117
118
119 DataModel data;
120
121
122
123
124 RoutingIndexManager manager(data.time_matrix.size(), data.num_vehicles,
125 data.depot);
126
127
128
129
130 RoutingModel routing(manager);
131
132
133
134
135 const int transit_callback_index = routing.RegisterTransitCallback(
136 [&data, &manager](const int64_t from_index,
137 const int64_t to_index) -> int64_t {
138
139 const int from_node = manager.IndexToNode(from_index).value();
140 const int to_node = manager.IndexToNode(to_index).value();
141 return data.time_matrix[from_node][to_node];
142 });
143
144
145
146
147 routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index);
148
149
150
151
152 const std::string time = "Time";
153 routing.AddDimension(transit_callback_index,
154 int64_t{30},
155 int64_t{30},
156 false,
157 time);
158 const RoutingDimension& time_dimension = routing.GetDimensionOrDie(time);
159
160 for (int i = 1; i < data.time_windows.size(); ++i) {
161 const int64_t index =
163 time_dimension.CumulVar(index)->SetRange(data.time_windows[i].first,
164 data.time_windows[i].second);
165 }
166
167 for (int i = 0; i < data.num_vehicles; ++i) {
168 const int64_t index = routing.Start(i);
169 time_dimension.CumulVar(index)->SetRange(data.time_windows[0].first,
170 data.time_windows[0].second);
171 }
172
173
174
175
176 for (int i = 0; i < data.num_vehicles; ++i) {
177 routing.AddVariableMinimizedByFinalizer(
178 time_dimension.CumulVar(routing.Start(i)));
179 routing.AddVariableMinimizedByFinalizer(
180 time_dimension.CumulVar(routing.End(i)));
181 }
182
183
184
185
187 searchParameters.set_first_solution_strategy(
189
190
191
192
193 const Assignment*
solution = routing.SolveWithParameters(searchParameters);
194
195
196
197
198 PrintSolution(data, manager, routing, *
solution);
199
200}
201}
202
203int main(
int ,
char* []) {
204 operations_research::VrpTimeWindows();
205 return EXIT_SUCCESS;
206}
207
208
static constexpr Value PATH_CHEAPEST_ARC
RoutingNodeIndex NodeIndex
int main(int argc, char **argv)
Select next search node to expand Select next item_i to add this new search node to the search Generate a new search node where item_i is not in the knapsack Check validity of this new partial solution(using propagators) - If valid
RoutingSearchParameters DefaultRoutingSearchParameters()
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...