14 #ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_NEIGHBORHOODS_H_
15 #define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_NEIGHBORHOODS_H_
24 #include "absl/strings/str_cat.h"
60 const std::vector<IntVar*>& vars,
61 const std::vector<IntVar*>& secondary_vars,
62 std::function<
int(int64_t)> start_empty_path_class,
67 std::string
DebugString()
const override {
return "RelocateNeighbors"; }
76 bool MoveChainAndRepair(int64_t before_chain, int64_t chain_end,
86 int64_t Reposition(int64_t before_to_move, int64_t up_to);
112 const std::vector<IntVar*>& vars,
113 const std::vector<IntVar*>& secondary_vars,
114 std::function<
int(int64_t)> start_empty_path_class,
115 std::vector<std::vector<int64_t>> alternative_sets,
120 return "SwapActiveToShortestPath";
124 void UpdateShortestPath(
int source,
int sink,
125 const std::vector<int>& alternative_chain);
128 const std::vector<std::vector<int64_t>> alternative_sets_;
129 std::vector<int> to_alternative_set_;
130 std::vector<int64_t> path_predecessor_;
131 std::vector<int64_t> path_;
160 const std::vector<IntVar*>& secondary_vars,
161 std::function<
int(int64_t)> start_empty_path_class,
165 std::string
DebugString()
const override {
return "MakePairActive"; }
182 void OnNodeInitialization()
override;
183 int FindNextInactivePair(
int pair_index)
const;
184 bool ContainsActiveNodes(
const std::vector<int64_t>&
nodes)
const;
187 int inactive_pair_first_index_;
188 int inactive_pair_second_index_;
196 const std::vector<IntVar*>& secondary_vars,
197 std::function<
int(int64_t)> start_empty_path_class,
201 std::string
DebugString()
const override {
return "MakePairInActive"; }
215 const std::vector<IntVar*>& secondary_vars,
216 std::function<
int(int64_t)> start_empty_path_class,
221 std::string
DebugString()
const override {
return "PairRelocateOperator"; }
226 return base_index == kPairSecondNodeDestination;
231 return base_index == kPairFirstNode;
235 bool RestartAtPathStartOnSynchronize()
override {
return true; }
237 static constexpr
int kPairFirstNode = 0;
238 static constexpr
int kPairFirstNodeDestination = 1;
239 static constexpr
int kPairSecondNodeDestination = 2;
247 const std::vector<IntVar*>& vars,
248 const std::vector<IntVar*>& secondary_vars,
249 std::function<
int(int64_t)> start_empty_path_class,
254 std::string
DebugString()
const override {
return "GroupPairAndRelocate"; }
271 const std::vector<IntVar*>& secondary_vars,
272 std::function<
int(int64_t)> start_empty_path_class,
274 std::function<
bool(int64_t)> force_lifo =
nullptr);
279 return "LightPairRelocateOperator";
283 std::function<bool(int64_t)> force_lifo_;
295 const std::vector<IntVar*>& secondary_vars,
296 std::function<
int(int64_t)> start_empty_path_class,
301 std::string
DebugString()
const override {
return "PairExchangeOperator"; }
304 bool RestartAtPathStartOnSynchronize()
override {
return true; }
305 bool ConsiderAlternatives(int64_t base_index)
const override {
return true; }
306 bool GetPreviousAndSibling(int64_t node, int64_t* previous, int64_t* sibling,
307 int64_t* sibling_previous)
const;
326 const std::vector<IntVar*>& vars,
327 const std::vector<IntVar*>& secondary_vars,
328 std::function<
int(int64_t)> start_empty_path_class,
334 return "PairExchangeRelocateOperator";
342 bool RestartAtPathStartOnSynchronize()
override {
return true; }
343 bool GetPreviousAndSibling(int64_t node, int64_t* previous, int64_t* sibling,
344 int64_t* sibling_previous)
const;
345 bool MoveNode(
int pair,
int node, int64_t
nodes[2][2], int64_t dest[2][2],
347 bool LoadAndCheckDest(
int pair,
int node, int64_t base_node,
348 int64_t
nodes[2][2], int64_t dest[2][2])
const;
350 static constexpr
int kFirstPairFirstNode = 0;
351 static constexpr
int kSecondPairFirstNode = 1;
352 static constexpr
int kFirstPairFirstNodeDestination = 2;
353 static constexpr
int kFirstPairSecondNodeDestination = 3;
354 static constexpr
int kSecondPairFirstNodeDestination = 4;
355 static constexpr
int kSecondPairSecondNodeDestination = 5;
371 const std::vector<IntVar*>& path_vars,
372 std::function<
int(int64_t)> start_empty_path_class,
378 std::string
DebugString()
const override {
return "SwapIndexPairOperator"; }
383 bool UpdateActiveNodes();
385 void SetNext(int64_t from, int64_t to, int64_t path) {
386 DCHECK_LT(from, number_of_nexts_);
388 if (!ignore_path_vars_) {
389 DCHECK_LT(from + number_of_nexts_,
Size());
390 SetValue(from + number_of_nexts_, path);
398 int64_t first_active_;
399 int64_t second_active_;
400 std::vector<int64_t> prevs_;
401 const int number_of_nexts_;
402 const bool ignore_path_vars_;
410 const std::vector<IntVar*>& vars,
411 const std::vector<IntVar*>& secondary_vars,
412 std::function<
int(int64_t)> start_empty_path_class,
419 return "IndexPairSwapActiveOperator";
423 void OnNodeInitialization()
override;
435 std::unique_ptr<RoutingFilteredHeuristic> heuristic,
436 bool keep_inverse_values =
false);
447 std::string heuristic_name = heuristic_->DebugString();
448 const int erase_pos = heuristic_name.find(
"FilteredHeuristic");
449 if (erase_pos != std::string::npos) {
450 const int expected_name_size = heuristic_name.size() - 17;
451 heuristic_name.erase(erase_pos);
454 DCHECK_EQ(heuristic_name.size(), expected_name_size);
456 return heuristic_name;
467 bool MakeOneNeighbor()
override;
468 bool MakeChangesAndInsertNodes();
470 int64_t VehicleVarIndex(int64_t node)
const {
return model_->
Size() + node; }
472 const std::unique_ptr<RoutingFilteredHeuristic> heuristic_;
473 const bool consider_vehicle_vars_;
482 std::unique_ptr<RoutingFilteredHeuristic> heuristic);
486 return absl::StrCat(
"HeuristicPathLNS(",
HeuristicName(),
")");
490 void OnStart()
override;
492 bool IncrementPosition()
override;
493 bool CurrentRouteIsEmpty()
const;
494 void IncrementCurrentRouteToNextNonEmpty();
496 std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor()
override;
510 std::unique_ptr<RoutingFilteredHeuristic> heuristic);
514 return absl::StrCat(
"RelocatePathAndHeuristicInsertUnperformed(",
519 void OnStart()
override;
521 bool IncrementPosition()
override;
522 bool IncrementRoutes();
524 std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor()
override;
526 int route_to_relocate_index_;
527 int last_route_to_relocate_index_;
528 int empty_route_index_;
529 int last_empty_route_index_;
530 std::vector<int> routes_to_relocate_;
531 std::vector<int> empty_routes_;
532 std::vector<int64_t> last_node_on_route_;
533 bool has_unperformed_nodes_;
544 std::unique_ptr<RoutingFilteredHeuristic> heuristic,
545 int num_arcs_to_consider,
546 std::function<int64_t(int64_t, int64_t, int64_t)>
547 arc_cost_for_route_start);
551 return absl::StrCat(
"HeuristicExpensiveChainLNS(",
HeuristicName(),
")");
555 void OnStart()
override;
557 bool IncrementPosition()
override;
558 bool IncrementRoute();
559 bool IncrementCurrentArcIndices();
560 bool FindMostExpensiveChainsOnRemainingRoutes();
562 std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor()
override;
567 const int num_arcs_to_consider_;
568 std::vector<std::pair<int64_t, int>> most_expensive_arc_starts_and_ranks_;
572 current_expensive_arc_indices_;
573 std::function<int64_t( int64_t, int64_t,
575 arc_cost_for_route_start_;
587 std::unique_ptr<RoutingFilteredHeuristic> heuristic,
int num_close_nodes);
591 return absl::StrCat(
"HeuristicCloseNodesLNS(",
HeuristicName(),
")");
597 void OnStart()
override;
599 bool IncrementPosition()
override;
601 std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor()
override;
603 void RemoveNode(int64_t node);
604 void RemoveNodeAndActiveSibling(int64_t node);
606 bool IsActive(int64_t node)
const {
611 int64_t Prev(int64_t node)
const {
613 DCHECK_LT(node, new_prevs_.size());
614 return changed_prevs_[node] ? new_prevs_[node] :
InverseValue(node);
616 int64_t Next(int64_t node)
const {
618 return changed_nexts_[node] ? new_nexts_[node] :
Value(node);
621 std::vector<int64_t> GetActiveSiblings(int64_t node)
const;
623 const std::vector<std::pair<std::vector<int64_t>, std::vector<int64_t>>>&
624 pickup_delivery_pairs_;
631 std::vector<std::vector<int64_t>> close_nodes_;
632 const int num_close_nodes_;
634 std::vector<int64_t> new_nexts_;
635 SparseBitset<> changed_nexts_;
636 std::vector<int64_t> new_prevs_;
637 SparseBitset<> changed_prevs_;
650 const std::vector<IntVar*>& secondary_vars,
651 std::function<
int(int64_t)> start_empty_path_class,
652 int num_arcs_to_consider,
653 std::function<int64_t(int64_t, int64_t, int64_t)>
654 arc_cost_for_path_start);
659 std::string
DebugString()
const override {
return "RelocateExpensiveChain"; }
662 void OnNodeInitialization()
override;
663 void IncrementCurrentPath();
664 bool IncrementCurrentArcIndices();
668 bool FindMostExpensiveChainsOnRemainingPaths();
670 int num_arcs_to_consider_;
672 std::vector<std::pair<int64_t, int>> most_expensive_arc_starts_and_ranks_;
676 current_expensive_arc_indices_;
677 std::function<int64_t( int64_t, int64_t,
679 arc_cost_for_path_start_;
683 bool has_non_empty_paths_to_explore_;
693 template <
bool swap_first>
697 const std::vector<IntVar*>& secondary_vars,
698 std::function<
int(int64_t)> start_empty_path_class,
705 return "PairNodeSwapActiveOperator";
722 void OnNodeInitialization()
override;
731 template <
bool swap_first>
733 const std::vector<IntVar*>& vars,
734 const std::vector<IntVar*>& secondary_vars,
735 std::function<
int(int64_t)> start_empty_path_class,
738 std::move(start_empty_path_class)),
740 pairs_(index_pairs) {}
742 template <
bool swap_first>
746 if (base_index == 0 || StartNode(base_index) != StartNode(base_index - 1)) {
747 return StartNode(base_index);
749 return BaseNode(base_index - 1);
753 template <
bool swap_first>
755 for (
int i = 0; i < pairs_.size(); ++i) {
756 if (IsInactive(pairs_[i].first[0]) && IsInactive(pairs_[i].second[0])) {
761 inactive_pair_ = pairs_.size();
764 template <
bool swap_first>
767 while (inactive_pair_ < pairs_.size()) {
768 if (!IsInactive(pairs_[inactive_pair_].first[0]) ||
769 !IsInactive(pairs_[inactive_pair_].second[0]) ||
780 template <
bool swap_first>
782 const int64_t base = BaseNode(0);
783 if (IsPathEnd(base)) {
786 const int64_t pair_first = pairs_[inactive_pair_].first[0];
787 const int64_t pair_second = pairs_[inactive_pair_].second[0];
789 return MakeActive(pair_second, BaseNode(1)) &&
790 MakeActive(pair_first, base) &&
791 MakeChainInactive(pair_first, Next(pair_first));
793 return MakeActive(pair_second, BaseNode(1)) &&
794 MakeActive(pair_first, base) &&
795 MakeChainInactive(pair_second, Next(pair_second));
813 const std::vector<IntVar*>& secondary_vars,
814 std::function<
int(int64_t)> start_empty_path_class,
817 std::string
DebugString()
const override {
return "RelocateSubtrip"; }
822 bool RelocateSubTripFromPickup(int64_t chain_first_node,
823 int64_t insertion_node);
825 bool RelocateSubTripFromDelivery(int64_t chain_last_node,
826 int64_t insertion_node);
827 std::vector<bool> is_pickup_node_;
828 std::vector<bool> is_delivery_node_;
829 std::vector<int> pair_of_node_;
833 std::vector<bool> opened_pairs_bitset_;
835 std::vector<int64_t> rejected_nodes_;
836 std::vector<int64_t> subtrip_nodes_;
842 const std::vector<IntVar*>& secondary_vars,
843 std::function<
int(int64_t)> start_empty_path_class,
846 std::string
DebugString()
const override {
return "ExchangeSubtrip"; }
858 bool ExtractChainsAndCheckCanonical(int64_t base_node,
859 std::vector<int64_t>* rejects,
860 std::vector<int64_t>* subtrip);
866 bool ExtractChainsFromPickup(int64_t base_node, std::vector<int64_t>* rejects,
867 std::vector<int64_t>* subtrip);
873 bool ExtractChainsFromDelivery(int64_t base_node,
874 std::vector<int64_t>* rejects,
875 std::vector<int64_t>* subtrip);
876 void SetPath(
const std::vector<int64_t>& path,
int path_id);
879 std::vector<bool> is_pickup_node_;
880 std::vector<bool> is_delivery_node_;
881 std::vector<int> pair_of_node_;
883 std::vector<bool> opened_pairs_set_;
885 std::vector<int64_t> rejects0_;
886 std::vector<int64_t> subtrip0_;
887 std::vector<int64_t> rejects1_;
888 std::vector<int64_t> subtrip1_;
889 std::vector<int64_t> path0_;
890 std::vector<int64_t> path1_;
An Assignment is a variable -> domains mapping, used to report solutions to the user.
bool MakeNeighbor() override
ExchangeSubtrip(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const RoutingIndexPairs &pairs)
std::string DebugString() const override
Filtered heuristic LNS operator, where the destruction phase consists of removing a node and the 'num...
~FilteredHeuristicCloseNodesLNSOperator() override
FilteredHeuristicCloseNodesLNSOperator(std::unique_ptr< RoutingFilteredHeuristic > heuristic, int num_close_nodes)
std::string DebugString() const override
Similar to the heuristic path LNS above, but instead of removing one route entirely,...
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() override
std::string DebugString() const override
Class of operators using a RoutingFilteredHeuristic to insert unperformed nodes after changes have be...
~FilteredHeuristicLocalSearchOperator() override
FilteredHeuristicLocalSearchOperator(std::unique_ptr< RoutingFilteredHeuristic > heuristic, bool keep_inverse_values=false)
virtual std::function< int64_t(int64_t)> SetupNextAccessorForNeighbor()=0
Virtual method to return the next_accessor to be passed to the heuristic to build a new solution.
RoutingModel *const model_
virtual bool IncrementPosition()=0
std::string HeuristicName() const
SparseBitset removed_nodes_
Keeps track of removed nodes when making a neighbor.
LNS-like operator based on a filtered first solution heuristic to rebuild the solution,...
FilteredHeuristicPathLNSOperator(std::unique_ptr< RoutingFilteredHeuristic > heuristic)
std::string DebugString() const override
~FilteredHeuristicPathLNSOperator() override
Operator which moves a pair of nodes to another position where the first node of the pair is directly...
bool MakeNeighbor() override
GroupPairAndRelocateOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const RoutingIndexPairs &index_pairs)
~GroupPairAndRelocateOperator() override
std::string DebugString() const override
Operator which inserts inactive nodes into a path and makes a pair of active nodes inactive.
IndexPairSwapActiveOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const RoutingIndexPairs &index_pairs)
bool MakeNeighbor() override
bool MakeNextNeighbor(Assignment *delta, Assignment *deltadelta) override
OnStart() should really be protected, but then SWIG doesn't see it.
~IndexPairSwapActiveOperator() override
std::string DebugString() const override
Specialization of LocalSearchOperator built from an array of IntVars which specifies the scope of the...
void SetValue(int64_t index, int64_t value)
bool MakeNextNeighbor(Assignment *delta, Assignment *deltadelta) override
OnStart() should really be protected, but then SWIG doesn't see it.
int64_t InverseValue(int64_t index) const
int64_t Value(int64_t index) const
Returns the value in the current assignment of the variable of given index.
Operator which moves a pair of nodes to another position where the first node of the pair must be bef...
bool MakeNeighbor() override
LightPairRelocateOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const RoutingIndexPairs &index_pairs, std::function< bool(int64_t)> force_lifo=nullptr)
~LightPairRelocateOperator() override
std::string DebugString() const override
Pair-based neighborhood operators, designed to move nodes by pairs (pairs are static and given).
int64_t GetBaseNodeRestartPosition(int base_index) override
Returns the index of the node to which the base node of index base_index must be set to when it reach...
bool MakeNeighbor() override
MakePairActiveOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const RoutingIndexPairs &pairs)
~MakePairActiveOperator() override
bool RestartAtPathStartOnSynchronize() override
Required to ensure that after synchronization the operator is in a state compatible with GetBaseNodeR...
bool MakeOneNeighbor() override
This method should not be overridden. Override MakeNeighbor() instead.
bool OnSamePathAsPreviousBase(int64_t base_index) override
Returns true if a base node has to be on the same path as the "previous" base node (base node of inde...
std::string DebugString() const override
Operator which makes pairs of active nodes inactive.
MakePairInactiveOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const RoutingIndexPairs &index_pairs)
bool MakeNeighbor() override
std::string DebugString() const override
Relocate neighborhood which moves chains of neighbors.
bool MakeNeighbor() override
MakeRelocateNeighborsOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, RoutingTransitCallback2 arc_evaluator)
~MakeRelocateNeighborsOperator() override
std::string DebugString() const override
Operator which exchanges the position of two pairs; for both pairs the first node of the pair must be...
bool MakeNeighbor() override
~PairExchangeOperator() override
PairExchangeOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const RoutingIndexPairs &index_pairs)
std::string DebugString() const override
Operator which exchanges the paths of two pairs (path have to be different).
int64_t GetBaseNodeRestartPosition(int base_index) override
Returns the index of the node to which the base node of index base_index must be set to when it reach...
bool MakeNeighbor() override
PairExchangeRelocateOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const RoutingIndexPairs &index_pairs)
~PairExchangeRelocateOperator() override
bool OnSamePathAsPreviousBase(int64_t base_index) override
Returns true if a base node has to be on the same path as the "previous" base node (base node of inde...
std::string DebugString() const override
Operator which inserts pairs of inactive nodes into a path and makes an active node inactive.
int64_t GetBaseNodeRestartPosition(int base_index) override
Returns the index of the node to which the base node of index base_index must be set to when it reach...
bool MakeNeighbor() override
bool MakeNextNeighbor(Assignment *delta, Assignment *deltadelta) override
OnStart() should really be protected, but then SWIG doesn't see it.
~PairNodeSwapActiveOperator() override
bool RestartAtPathStartOnSynchronize() override
Required to ensure that after synchronization the operator is in a state compatible with GetBaseNodeR...
PairNodeSwapActiveOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const RoutingIndexPairs &index_pairs)
bool OnSamePathAsPreviousBase(int64_t base_index) override
Returns true if a base node has to be on the same path as the "previous" base node (base node of inde...
std::string DebugString() const override
Operator which moves a pair of nodes to another position where the first node of the pair must be bef...
int64_t GetBaseNodeRestartPosition(int base_index) override
Returns the index of the node to which the base node of index base_index must be set to when it reach...
bool MakeNeighbor() override
~PairRelocateOperator() override
bool ConsiderAlternatives(int64_t base_index) const override
Indicates if alternatives should be considered when iterating over base nodes.
PairRelocateOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const RoutingIndexPairs &index_pairs)
bool OnSamePathAsPreviousBase(int64_t base_index) override
Returns true if a base node has to be on the same path as the "previous" base node (base node of inde...
std::string DebugString() const override
Base class of the local search operators dedicated to path modifications (a path is a set of nodes li...
bool MakeNeighbor() override
~RelocateExpensiveChain() override
RelocateExpensiveChain(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, int num_arcs_to_consider, std::function< int64_t(int64_t, int64_t, int64_t)> arc_cost_for_path_start)
bool MakeOneNeighbor() override
This method should not be overridden. Override MakeNeighbor() instead.
std::string DebugString() const override
Tries to move subtrips after an insertion node.
bool MakeNeighbor() override
RelocateSubtrip(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const RoutingIndexPairs &pairs)
std::string DebugString() const override
int64_t Size() const
Returns the number of next variables in the model.
bool IsEnd(int64_t index) const
Returns true if 'index' represents the last node of a route.
~SwapActiveToShortestPathOperator() override=default
bool MakeNeighbor() override
SwapActiveToShortestPathOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, std::vector< std::vector< int64_t >> alternative_sets, RoutingTransitCallback2 arc_evaluator)
std::string DebugString() const override
Operator which iterates through each alternative of a set of pairs.
void OnStart() override
Called by Start() after synchronizing the operator with the current assignment.
bool MakeNextNeighbor(Assignment *delta, Assignment *deltadelta) override
OnStart() should really be protected, but then SWIG doesn't see it.
SwapIndexPairOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &path_vars, std::function< int(int64_t)> start_empty_path_class, const RoutingIndexPairs &index_pairs)
~SwapIndexPairOperator() override
std::string DebugString() const override
Collection of objects used to extend the Constraint Solver library.
std::function< int64_t(int64_t, int64_t)> RoutingTransitCallback2
std::vector< RoutingIndexPair > RoutingIndexPairs