Google OR-Tools v9.12
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
routing_ils.h
Go to the documentation of this file.
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#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_ILS_H_
15#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_ILS_H_
16
17#include <cstddef>
18#include <cstdint>
19#include <functional>
20#include <memory>
21#include <random>
22#include <utility>
23#include <vector>
24
25#include "absl/time/time.h"
28#include "ortools/constraint_solver/routing_ils.pb.h"
29#include "ortools/constraint_solver/routing_parameters.pb.h"
30#include "ortools/util/bitset.h"
31
32namespace operations_research {
33
34// Wraps a routing assignment providing extra features.
36 public:
37 explicit RoutingSolution(const RoutingModel& model);
38
39 // Initializes the routing solution for the given assignment.
40 void Reset(const Assignment* assignment);
41
42 // Initializes next and prev pointers for the route served by the given
43 // vehicle, if not already done.
44 void InitializeRouteInfoIfNeeded(int vehicle);
45
46 // Returns whether node_index belongs to a route that has been initialized.
47 bool BelongsToInitializedRoute(int64_t node_index) const;
48
49 // Returns the next node index of the given node_index.
50 int64_t GetNextNodeIndex(int64_t node_index) const;
51
52 // Returns the previous node index of the given node_index.
53 // This must be called for node_index belonging to initialized routes.
54 int64_t GetInitializedPrevNodeIndex(int64_t node_index) const;
55
56 // Returns the number of visits performed by the given vehicle.
57 // This must be called for a vehicle associated with an initialized route.
58 int GetRouteSize(int vehicle) const;
59
60 // Returns whether node_index can be removed from the solution.
61 // This must be called for node_index belonging to initialized routes.
62 bool CanBeRemoved(int64_t node_index) const;
63
64 // Removes the node with the given node_index.
65 // This must be called for node_index belonging to initialized routes.
66 void RemoveNode(int64_t node_index);
67
68 // Removes the performed sibling pickup or delivery of customer, if any.
69 void RemovePerformedPickupDeliverySibling(int64_t customer);
70
71 // Randomly returns the next or previous visit of the given performed
72 // visit. Returns -1 if there are no other available visits. When the
73 // selected adjacent vertex is a vehicle start/end, we always pick the
74 // visit in the opposite direction.
75 // This must be called for a performed visit belonging to an initialized
76 // route.
78 int64_t visit, std::mt19937& rnd,
79 std::bernoulli_distribution& boolean_dist) const;
80
81 // Returns a randomly selected sequence of contiguous visits that includes
82 // the seed visit.
83 // This must be called for a performed seed visit belonging to an
84 // initialized route.
85 std::vector<int64_t> GetRandomSequenceOfVisits(
86 int64_t seed_visit, std::mt19937& rnd,
87 std::bernoulli_distribution& boolean_dist, int size) const;
88
89 private:
90 const RoutingModel& model_;
91 std::vector<int64_t> nexts_;
92 std::vector<int64_t> prevs_;
93 std::vector<int> route_sizes_;
94
95 // Assignment that the routing solution refers to. It's changed at every
96 // Reset call.
97 const Assignment* assignment_ = nullptr;
98};
99
100// Ruin interface.
102 public:
103 virtual ~RuinProcedure() = default;
104
105 // Returns next accessors describing the ruined solution.
106 virtual std::function<int64_t(int64_t)> Ruin(
107 const Assignment* assignment) = 0;
108};
109
110// Removes a number of routes that are spatially close together.
112 public:
113 CloseRoutesRemovalRuinProcedure(RoutingModel* model, std::mt19937* rnd,
114 size_t num_routes,
115 int num_neighbors_for_route_selection);
116 // Returns next accessors where at most num_routes routes have been shortcut,
117 // i.e., next(shortcut route begin) = shortcut route end.
118 // Next accessors for customers belonging to shortcut routes are still set to
119 // their original value and should not be used.
120 std::function<int64_t(int64_t)> Ruin(const Assignment* assignment) override;
121
122 private:
123 const RoutingModel& model_;
124 const RoutingModel::NodeNeighborsByCostClass* const neighbors_manager_;
125 const size_t num_routes_;
126 std::mt19937& rnd_;
127 std::uniform_int_distribution<int64_t> customer_dist_;
128 SparseBitset<int64_t> removed_routes_;
129};
130
131// Removes a number of non start/end nodes by performing a random walk on the
132// routing solution graph described by the assignment.
133// Note that the removal of a pickup and delivery counts as the removal of a
134// single entity.
136 public:
137 RandomWalkRemovalRuinProcedure(RoutingModel* model, std::mt19937* rnd,
138 int walk_length,
139 int num_neighbors_for_route_selection);
140
141 std::function<int64_t(int64_t)> Ruin(const Assignment* assignment) override;
142
143 private:
144 // Returns the next node towards which the random walk is extended.
145 int64_t GetNextNodeToRemove(const Assignment* assignment, int node);
146
147 const RoutingModel& model_;
148 RoutingSolution routing_solution_;
149 const RoutingModel::NodeNeighborsByCostClass* const neighbors_manager_;
150 std::mt19937& rnd_;
151 const int walk_length_;
152 std::uniform_int_distribution<int64_t> customer_dist_;
153 std::bernoulli_distribution boolean_dist_;
154};
155
156// Applies one or more ruin procedures according to the selected composition
157// strategy.
159 public:
160 // Composition strategy interface.
162 public:
163 explicit CompositionStrategy(std::vector<RuinProcedure*> ruin_procedures);
164 virtual ~CompositionStrategy() = default;
165
166 // Returns the selected ruin procedures.
167 virtual const std::vector<RuinProcedure*>& Select() = 0;
168
169 protected:
170 // Contains ptrs to the available ruins.
171 std::vector<RuinProcedure*> ruins_;
172 };
173
175 RoutingModel* model,
176 std::vector<std::unique_ptr<RuinProcedure>> ruin_procedures,
177 RuinCompositionStrategy::Value composition_strategy, std::mt19937* rnd);
178
179 std::function<int64_t(int64_t)> Ruin(const Assignment* assignment) override;
180
181 private:
182 // Creates a new assignment from the given next accessor.
183 const Assignment* BuildAssignmentFromNextAccessor(
184 const std::function<int64_t(int64_t)>& next_accessor);
185
186 const RoutingModel& model_;
187 std::vector<std::unique_ptr<RuinProcedure>> ruin_procedures_;
188 std::unique_ptr<CompositionStrategy> composition_strategy_;
189
190 // Used by BuildAssignmentFromNextAccessor to rebuild a proper assignment
191 // from next accessors. Stored at the object level to minimize re-allocations.
192 Assignment* ruined_assignment_;
193 Assignment* next_assignment_;
194};
195
196// Performs a ruin based on the Slack Induction by String Removals (SISR)
197// procedure described in "Slack Induction by String Removals for Vehicle
198// Routing Problems" by Jan Christiaens and Greet Vanden Berghe, Transportation
199// Science 2020.
200// Link to paper:
201// https://kuleuven.limo.libis.be/discovery/search?query=any,contains,LIRIAS1988666&tab=LIRIAS&search_scope=lirias_profile&vid=32KUL_KUL:Lirias&offset=0
202// Note that, in this implementation, the notion of "string" is replaced by
203// "sequence".
204// In short, at every ruin application a number of routes are
205// disrupted. This number of routes is selected according to a careful
206// combination of user-defined parameters and solution and instance properties.
207// Every selected route is then disrupted by removing a contiguous sequence of
208// visits, possibly bypassing a contiguous subsequence.
209// See also SISRRuinStrategy in ils.proto.
211 public:
212 SISRRuinProcedure(RoutingModel* model, std::mt19937* rnd,
213 int max_removed_sequence_size, int avg_num_removed_visits,
214 double bypass_factor, int num_neighbors);
215
216 std::function<int64_t(int64_t)> Ruin(const Assignment* assignment) override;
217
218 private:
219 int RuinRoute(const Assignment& assignment, int64_t seed_visit,
220 double global_max_sequence_size);
221
222 // Removes a randomly selected sequence that includes the given seed visit.
223 void RuinRouteWithSequenceProcedure(int64_t seed_visit, int sequence_size);
224
225 // Randomly removes a sequence including the seed visit but bypassing and
226 // preserving a random subsequence.
227 void RuinRouteWithSplitSequenceProcedure(int64_t route, int64_t seed_visit,
228 int sequence_size);
229
230 const RoutingModel& model_;
231 std::mt19937& rnd_;
232 int max_removed_sequence_size_;
233 int avg_num_removed_visits_;
234 double bypass_factor_;
235 const RoutingModel::NodeNeighborsByCostClass* const neighbors_manager_;
236 std::uniform_int_distribution<int64_t> customer_dist_;
237 std::bernoulli_distribution boolean_dist_;
238 std::uniform_real_distribution<double> probability_dist_;
239 SparseBitset<int64_t> ruined_routes_;
240 RoutingSolution routing_solution_;
241};
242
243// Returns a DecisionBuilder implementing a perturbation step of an Iterated
244// Local Search approach.
246 const RoutingSearchParameters& parameters, RoutingModel* model,
247 std::mt19937* rnd, const Assignment* assignment,
248 std::function<bool()> stop_search,
249 LocalSearchFilterManager* filter_manager);
250
251// Neighbor acceptance criterion interface.
253 public:
254 // Representation of the search process state.
255 struct SearchState {
256 // Search duration.
257 absl::Duration duration;
258 // Explored solutions.
259 int64_t solutions;
260 };
261
262 virtual ~NeighborAcceptanceCriterion() = default;
263 // Returns whether `candidate` should replace `reference` given the provided
264 // search state.
265 virtual bool Accept(const SearchState& search_state,
266 const Assignment* candidate,
267 const Assignment* reference) = 0;
268};
269
270// Returns a neighbor acceptance criterion based on the given parameters.
271std::unique_ptr<NeighborAcceptanceCriterion> MakeNeighborAcceptanceCriterion(
272 const RoutingModel& model, const RoutingSearchParameters& parameters,
273 std::mt19937* rnd);
274
275// Returns initial and final simulated annealing temperatures according to the
276// given simulated annealing input parameters.
277std::pair<double, double> GetSimulatedAnnealingTemperatures(
278 const RoutingModel& model, const SimulatedAnnealingParameters& sa_params,
279 std::mt19937* rnd);
280
281} // namespace operations_research
282
283#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_ILS_H_
CloseRoutesRemovalRuinProcedure(RoutingModel *model, std::mt19937 *rnd, size_t num_routes, int num_neighbors_for_route_selection)
std::function< int64_t(int64_t)> Ruin(const Assignment *assignment) override
std::vector< RuinProcedure * > ruins_
Contains ptrs to the available ruins.
CompositionStrategy(std::vector< RuinProcedure * > ruin_procedures)
virtual const std::vector< RuinProcedure * > & Select()=0
Returns the selected ruin procedures.
CompositeRuinProcedure(RoutingModel *model, std::vector< std::unique_ptr< RuinProcedure > > ruin_procedures, RuinCompositionStrategy::Value composition_strategy, std::mt19937 *rnd)
std::function< int64_t(int64_t)> Ruin(const Assignment *assignment) override
Returns next accessors describing the ruined solution.
Neighbor acceptance criterion interface.
virtual bool Accept(const SearchState &search_state, const Assignment *candidate, const Assignment *reference)=0
RandomWalkRemovalRuinProcedure(RoutingModel *model, std::mt19937 *rnd, int walk_length, int num_neighbors_for_route_selection)
std::function< int64_t(int64_t)> Ruin(const Assignment *assignment) override
Returns next accessors describing the ruined solution.
Wraps a routing assignment providing extra features.
Definition routing_ils.h:35
int64_t GetInitializedPrevNodeIndex(int64_t node_index) const
bool CanBeRemoved(int64_t node_index) const
void RemoveNode(int64_t node_index)
void RemovePerformedPickupDeliverySibling(int64_t customer)
Removes the performed sibling pickup or delivery of customer, if any.
void Reset(const Assignment *assignment)
Initializes the routing solution for the given assignment.
int64_t GetRandomAdjacentVisit(int64_t visit, std::mt19937 &rnd, std::bernoulli_distribution &boolean_dist) const
void InitializeRouteInfoIfNeeded(int vehicle)
std::vector< int64_t > GetRandomSequenceOfVisits(int64_t seed_visit, std::mt19937 &rnd, std::bernoulli_distribution &boolean_dist, int size) const
RoutingSolution(const RoutingModel &model)
int64_t GetNextNodeIndex(int64_t node_index) const
Returns the next node index of the given node_index.
int GetRouteSize(int vehicle) const
bool BelongsToInitializedRoute(int64_t node_index) const
Returns whether node_index belongs to a route that has been initialized.
virtual std::function< int64_t(int64_t)> Ruin(const Assignment *assignment)=0
Returns next accessors describing the ruined solution.
SISRRuinProcedure(RoutingModel *model, std::mt19937 *rnd, int max_removed_sequence_size, int avg_num_removed_visits, double bypass_factor, int num_neighbors)
std::function< int64_t(int64_t)> Ruin(const Assignment *assignment) override
Returns next accessors describing the ruined solution.
In SWIG mode, we don't want anything besides these top-level includes.
std::pair< double, double > GetSimulatedAnnealingTemperatures(const RoutingModel &model, const SimulatedAnnealingParameters &sa_params, std::mt19937 *rnd)
DecisionBuilder * MakePerturbationDecisionBuilder(const RoutingSearchParameters &parameters, RoutingModel *model, std::mt19937 *rnd, const Assignment *assignment, std::function< bool()> stop_search, LocalSearchFilterManager *filter_manager)
std::unique_ptr< NeighborAcceptanceCriterion > MakeNeighborAcceptanceCriterion(const RoutingModel &model, const RoutingSearchParameters &parameters, std::mt19937 *rnd)
Returns a neighbor acceptance criterion based on the given parameters.
Representation of the search process state.