Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
vrp_time_windows.cc

Simple VRP example.

1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// [START program]
15// [START import]
16#include <cstdint>
17#include <cstdlib>
18#include <sstream>
19#include <string>
20#include <utility>
21#include <vector>
22
29// [END import]
30
31// [START program_part1]
32namespace operations_research {
33// [START data_model]
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}, // depot
56 {7, 12}, // 1
57 {10, 15}, // 2
58 {16, 18}, // 3
59 {10, 13}, // 4
60 {0, 5}, // 5
61 {5, 10}, // 6
62 {0, 4}, // 7
63 {5, 10}, // 8
64 {0, 3}, // 9
65 {10, 16}, // 10
66 {10, 15}, // 11
67 {0, 5}, // 12
68 {5, 10}, // 13
69 {7, 8}, // 14
70 {10, 15}, // 15
71 {11, 15}, // 16
72 };
73 const int num_vehicles = 4;
74 const RoutingIndexManager::NodeIndex depot{0};
75};
76// [END data_model]
77
78// [START solution_printer]
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("
98 << solution.Min(time_var) << ", " << solution.Max(time_var)
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("
104 << solution.Min(time_var) << ", " << solution.Max(time_var)
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// [END solution_printer]
115
116void VrpTimeWindows() {
117 // Instantiate the data problem.
118 // [START data]
119 DataModel data;
120 // [END data]
121
122 // Create Routing Index Manager
123 // [START index_manager]
124 RoutingIndexManager manager(data.time_matrix.size(), data.num_vehicles,
125 data.depot);
126 // [END index_manager]
127
128 // Create Routing Model.
129 // [START routing_model]
130 RoutingModel routing(manager);
131 // [END routing_model]
132
133 // Create and register a transit callback.
134 // [START transit_callback]
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 // Convert from routing variable Index to time matrix NodeIndex.
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 // [END transit_callback]
144
145 // Define cost of each arc.
146 // [START arc_cost]
147 routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index);
148 // [END arc_cost]
149
150 // Add Time constraint.
151 // [START time_constraint]
152 const std::string time = "Time";
153 routing.AddDimension(transit_callback_index, // transit callback index
154 int64_t{30}, // allow waiting time
155 int64_t{30}, // maximum time per vehicle
156 false, // Don't force start cumul to zero
157 time);
158 const RoutingDimension& time_dimension = routing.GetDimensionOrDie(time);
159 // Add time window constraints for each location except depot.
160 for (int i = 1; i < data.time_windows.size(); ++i) {
161 const int64_t index =
162 manager.NodeToIndex(RoutingIndexManager::NodeIndex(i));
163 time_dimension.CumulVar(index)->SetRange(data.time_windows[i].first,
164 data.time_windows[i].second);
165 }
166 // Add time window constraints for each vehicle start node.
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 // [END time_constraint]
173
174 // Instantiate route start and end times to produce feasible times.
175 // [START depot_start_end_times]
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 // [END depot_start_end_times]
183
184 // Setting first solution heuristic.
185 // [START parameters]
186 RoutingSearchParameters searchParameters = DefaultRoutingSearchParameters();
187 searchParameters.set_first_solution_strategy(
189 // [END parameters]
190
191 // Solve the problem.
192 // [START solve]
193 const Assignment* solution = routing.SolveWithParameters(searchParameters);
194 // [END solve]
195
196 // Print solution on console.
197 // [START print_solution]
198 PrintSolution(data, manager, routing, *solution);
199 // [END print_solution]
200}
201} // namespace operations_research
202
203int main(int /*argc*/, char* /*argv*/[]) {
204 operations_research::VrpTimeWindows();
205 return EXIT_SUCCESS;
206}
207// [END program_part1]
208// [END program]
int main(int argc, char **argv)
Definition fz.cc:218
OR-Tools root namespace.
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...