Google OR-Tools v9.12
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
routing_insertion_lns.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_INSERTION_LNS_H_
15#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_INSERTION_LNS_H_
16
17#include <cstdint>
18#include <functional>
19#include <memory>
20#include <string>
21#include <utility>
22#include <vector>
23
24#include "absl/log/check.h"
25#include "absl/strings/str_cat.h"
31#include "ortools/util/bitset.h"
32
33namespace operations_research {
34
37// TODO(user): Put these methods in an object with helper methods instead
38// of adding a layer to the class hierarchy.
40 public:
42 std::unique_ptr<RoutingFilteredHeuristic> heuristic,
43 bool keep_inverse_values = false);
45
46 protected:
47 virtual bool IncrementPosition() = 0;
51 virtual std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor() = 0;
52
53 std::string HeuristicName() const {
54 std::string heuristic_name = heuristic_->DebugString();
55 const int erase_pos = heuristic_name.find("FilteredHeuristic");
56 if (erase_pos != std::string::npos) {
57 const int expected_name_size = heuristic_name.size() - 17;
58 heuristic_name.erase(erase_pos);
59 // NOTE: Verify that the "FilteredHeuristic" string was at the end of the
60 // heuristic name.
61 DCHECK_EQ(heuristic_name.size(), expected_name_size);
62 }
63 return heuristic_name;
64 }
65
66 // TODO(user): Remove the dependency from RoutingModel by storing an
67 // IntVarFilteredHeuristic here instead and storing information on path
68 // start/ends like PathOperator does (instead of relying on the model).
69 RoutingModel* const model_;
72
73 private:
74 bool MakeOneNeighbor() override;
75 bool MakeChangesAndInsertNodes();
76
77 int64_t VehicleVarIndex(int64_t node) const { return model_->Size() + node; }
78
79 const std::unique_ptr<RoutingFilteredHeuristic> heuristic_;
80 const bool consider_vehicle_vars_;
81};
82
87 public:
89 std::unique_ptr<RoutingFilteredHeuristic> heuristic);
91
92 std::string DebugString() const override {
93 return absl::StrCat("HeuristicPathLNS(", HeuristicName(), ")");
94 }
95
96 private:
97 void OnStart() override;
98
99 bool IncrementPosition() override;
100 bool RouteIsEmpty(int route) const;
101 int GetNextRoute(int route) const {
102 return route + 1 < num_routes_ ? route + 1 : 0;
103 }
104 int GetFirstNonEmptyRouteAfterCurrentRoute() const;
105
106 std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor() override;
107
108 const int num_routes_;
109 int current_route_;
110 int last_route_;
111 bool just_started_;
112};
113
119 public:
121 std::unique_ptr<RoutingFilteredHeuristic> heuristic);
123
124 std::string DebugString() const override {
125 return absl::StrCat("RelocatePathAndHeuristicInsertUnperformed(",
126 HeuristicName(), ")");
127 }
128
129 private:
130 void OnStart() override;
131
132 bool IncrementPosition() override;
133 bool IncrementRoutes();
134
135 std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor() override;
136
137 int route_to_relocate_index_;
138 int last_route_to_relocate_index_;
139 int empty_route_index_;
140 int last_empty_route_index_;
141 std::vector<int> routes_to_relocate_;
142 std::vector<int> empty_routes_;
143 std::vector<int64_t> last_node_on_route_;
144 bool has_unperformed_nodes_;
145 bool just_started_;
146};
147
153 public:
155 std::unique_ptr<RoutingFilteredHeuristic> heuristic,
156 int num_arcs_to_consider,
157 std::function<int64_t(int64_t, int64_t, int64_t)>
158 arc_cost_for_route_start);
160
161 std::string DebugString() const override {
162 return absl::StrCat("HeuristicExpensiveChainLNS(", HeuristicName(), ")");
163 }
164
165 private:
166 void OnStart() override;
167
168 bool IncrementPosition() override;
169 bool IncrementRoute();
170 bool IncrementCurrentArcIndices();
171 bool FindMostExpensiveChainsOnRemainingRoutes();
172
173 std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor() override;
174
175 int current_route_;
176 int last_route_;
177
178 const int num_arcs_to_consider_;
179 std::vector<std::pair<int64_t, int>> most_expensive_arc_starts_and_ranks_;
182 std::pair</*first_arc_index*/ int, /*second_arc_index*/ int>
183 current_expensive_arc_indices_;
184 std::function<int64_t(/*before_node*/ int64_t, /*after_node*/ int64_t,
185 /*path_start*/ int64_t)>
186 arc_cost_for_route_start_;
187
188 bool just_started_;
189};
190
196 public:
198 std::unique_ptr<RoutingFilteredHeuristic> heuristic, int num_close_nodes);
200
201 std::string DebugString() const override {
202 return absl::StrCat("HeuristicCloseNodesLNS(", HeuristicName(), ")");
203 }
204
205 private:
206 void Initialize();
207
208 void OnStart() override;
209
210 bool IncrementPosition() override;
211
212 std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor() override;
213
214 void RemoveNode(int64_t node);
215 void RemoveNodeAndActiveSibling(int64_t node);
216
217 bool IsActive(int64_t node) const {
218 DCHECK_LT(node, model_->Size());
219 return Value(node) != node && !removed_nodes_[node];
220 }
221
222 int64_t Prev(int64_t node) const {
223 DCHECK_EQ(Value(InverseValue(node)), node);
224 DCHECK_LT(node, new_prevs_.size());
225 return changed_prevs_[node] ? new_prevs_[node] : InverseValue(node);
226 }
227 int64_t Next(int64_t node) const {
228 DCHECK(!model_->IsEnd(node));
229 return changed_nexts_[node] ? new_nexts_[node] : Value(node);
230 }
231
232 std::vector<int64_t> GetActiveSiblings(int64_t node) const;
233
234 const std::vector<PickupDeliveryPair>& pickup_delivery_pairs_;
235
236 int current_node_;
237 int last_node_;
238 bool just_started_;
239 bool initialized_;
240
241 std::vector<std::vector<int64_t>> close_nodes_;
242 const int num_close_nodes_;
244 std::vector<int64_t> new_nexts_;
245 SparseBitset<> changed_nexts_;
246 std::vector<int64_t> new_prevs_;
247 SparseBitset<> changed_prevs_;
248};
249
250} // namespace operations_research
251
252#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_INSERTION_LNS_H_
FilteredHeuristicCloseNodesLNSOperator(std::unique_ptr< RoutingFilteredHeuristic > heuristic, int num_close_nodes)
FilteredHeuristicCloseNodesLNSOperator.
FilteredHeuristicExpensiveChainLNSOperator(std::unique_ptr< RoutingFilteredHeuristic > heuristic, int num_arcs_to_consider, std::function< int64_t(int64_t, int64_t, int64_t)> arc_cost_for_route_start)
FilteredHeuristicExpensiveChainLNSOperator.
SparseBitset removed_nodes_
Keeps track of removed nodes when making a neighbor.
virtual std::function< int64_t(int64_t)> SetupNextAccessorForNeighbor()=0
FilteredHeuristicLocalSearchOperator(std::unique_ptr< RoutingFilteredHeuristic > heuristic, bool keep_inverse_values=false)
FilteredHeuristicLocalSearchOperator.
FilteredHeuristicPathLNSOperator(std::unique_ptr< RoutingFilteredHeuristic > heuristic)
FilteredHeuristicPathLNSOperator.
IntVarLocalSearchOperator(const std::vector< IntVar * > &vars, bool keep_inverse_values=false)
RelocatePathAndHeuristicInsertUnperformedOperator(std::unique_ptr< RoutingFilteredHeuristic > heuristic)
RelocatePathAndHeuristicInsertUnperformedOperator.
In SWIG mode, we don't want anything besides these top-level includes.
bool Next()