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"
59 const std::vector<IntVar*>& vars,
60 const std::vector<IntVar*>& secondary_vars,
61 std::function<
int(int64_t)> start_empty_path_class,
66 std::string
DebugString()
const override {
return "RelocateNeighbors"; }
75 bool MoveChainAndRepair(int64_t before_chain, int64_t chain_end,
85 int64_t Reposition(int64_t before_to_move, int64_t up_to);
116 const std::vector<IntVar*>& secondary_vars,
117 std::function<
int(int64_t)> start_empty_path_class,
121 std::string
DebugString()
const override {
return "MakePairActive"; }
138 void OnNodeInitialization()
override;
139 int FindNextInactivePair(
int pair_index)
const;
140 bool ContainsActiveNodes(
const std::vector<int64_t>&
nodes)
const;
143 int inactive_pair_first_index_;
144 int inactive_pair_second_index_;
152 const std::vector<IntVar*>& secondary_vars,
153 std::function<
int(int64_t)> start_empty_path_class,
157 std::string
DebugString()
const override {
return "MakePairInActive"; }
171 const std::vector<IntVar*>& secondary_vars,
172 std::function<
int(int64_t)> start_empty_path_class,
177 std::string
DebugString()
const override {
return "PairRelocateOperator"; }
182 return base_index == kPairSecondNodeDestination;
187 return base_index == kPairFirstNode;
191 bool RestartAtPathStartOnSynchronize()
override {
return true; }
193 static constexpr int kPairFirstNode = 0;
194 static constexpr int kPairFirstNodeDestination = 1;
195 static constexpr int kPairSecondNodeDestination = 2;
201 const std::vector<IntVar*>& secondary_vars,
202 std::function<
int(int64_t)> start_empty_path_class,
208 return "LightPairRelocateOperator";
221 const std::vector<IntVar*>& secondary_vars,
222 std::function<
int(int64_t)> start_empty_path_class,
227 std::string
DebugString()
const override {
return "PairExchangeOperator"; }
230 bool RestartAtPathStartOnSynchronize()
override {
return true; }
231 bool ConsiderAlternatives(int64_t base_index)
const override {
return true; }
232 bool GetPreviousAndSibling(int64_t node, int64_t* previous, int64_t* sibling,
233 int64_t* sibling_previous)
const;
252 const std::vector<IntVar*>& vars,
253 const std::vector<IntVar*>& secondary_vars,
254 std::function<
int(int64_t)> start_empty_path_class,
260 return "PairExchangeRelocateOperator";
268 bool RestartAtPathStartOnSynchronize()
override {
return true; }
269 bool GetPreviousAndSibling(int64_t node, int64_t* previous, int64_t* sibling,
270 int64_t* sibling_previous)
const;
271 bool MoveNode(
int pair,
int node, int64_t
nodes[2][2], int64_t dest[2][2],
273 bool LoadAndCheckDest(
int pair,
int node, int64_t base_node,
274 int64_t
nodes[2][2], int64_t dest[2][2])
const;
276 static constexpr int kFirstPairFirstNode = 0;
277 static constexpr int kSecondPairFirstNode = 1;
278 static constexpr int kFirstPairFirstNodeDestination = 2;
279 static constexpr int kFirstPairSecondNodeDestination = 3;
280 static constexpr int kSecondPairFirstNodeDestination = 4;
281 static constexpr int kSecondPairSecondNodeDestination = 5;
297 const std::vector<IntVar*>& path_vars,
298 std::function<
int(int64_t)> start_empty_path_class,
304 std::string
DebugString()
const override {
return "SwapIndexPairOperator"; }
309 bool UpdateActiveNodes();
311 void SetNext(int64_t from, int64_t to, int64_t path) {
314 if (!ignore_path_vars_) {
316 SetValue(from + number_of_nexts_, path);
324 int64_t first_active_;
325 int64_t second_active_;
326 std::vector<int64_t> prevs_;
327 const int number_of_nexts_;
328 const bool ignore_path_vars_;
336 const std::vector<IntVar*>& vars,
337 const std::vector<IntVar*>& secondary_vars,
338 std::function<
int(int64_t)> start_empty_path_class,
345 return "IndexPairSwapActiveOperator";
349 void OnNodeInitialization()
override;
361 std::unique_ptr<RoutingFilteredHeuristic> heuristic,
362 bool keep_inverse_values =
false);
373 std::string heuristic_name = heuristic_->DebugString();
374 const int erase_pos = heuristic_name.find(
"FilteredHeuristic");
375 if (erase_pos != std::string::npos) {
376 const int expected_name_size = heuristic_name.size() - 17;
377 heuristic_name.erase(erase_pos);
380 DCHECK_EQ(heuristic_name.size(), expected_name_size);
382 return heuristic_name;
393 bool MakeOneNeighbor()
override;
394 bool MakeChangesAndInsertNodes();
396 int64_t VehicleVarIndex(int64_t node)
const {
return model_->
Size() + node; }
398 const std::unique_ptr<RoutingFilteredHeuristic> heuristic_;
399 const bool consider_vehicle_vars_;
408 std::unique_ptr<RoutingFilteredHeuristic> heuristic);
412 return absl::StrCat(
"HeuristicPathLNS(",
HeuristicName(),
")");
416 void OnStart()
override;
418 bool IncrementPosition()
override;
419 bool CurrentRouteIsEmpty()
const;
420 void IncrementCurrentRouteToNextNonEmpty();
422 std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor()
override;
436 std::unique_ptr<RoutingFilteredHeuristic> heuristic);
440 return absl::StrCat(
"RelocatePathAndHeuristicInsertUnperformed(",
445 void OnStart()
override;
447 bool IncrementPosition()
override;
448 bool IncrementRoutes();
450 std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor()
override;
452 int route_to_relocate_index_;
453 int last_route_to_relocate_index_;
454 int empty_route_index_;
455 int last_empty_route_index_;
456 std::vector<int> routes_to_relocate_;
457 std::vector<int> empty_routes_;
458 std::vector<int64_t> last_node_on_route_;
459 bool has_unperformed_nodes_;
470 std::unique_ptr<RoutingFilteredHeuristic> heuristic,
471 int num_arcs_to_consider,
472 std::function<int64_t(int64_t, int64_t, int64_t)>
473 arc_cost_for_route_start);
477 return absl::StrCat(
"HeuristicExpensiveChainLNS(",
HeuristicName(),
")");
481 void OnStart()
override;
483 bool IncrementPosition()
override;
484 bool IncrementRoute();
485 bool IncrementCurrentArcIndices();
486 bool FindMostExpensiveChainsOnRemainingRoutes();
488 std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor()
override;
493 const int num_arcs_to_consider_;
494 std::vector<std::pair<int64_t, int>> most_expensive_arc_starts_and_ranks_;
498 current_expensive_arc_indices_;
499 std::function<int64_t( int64_t, int64_t,
501 arc_cost_for_route_start_;
513 std::unique_ptr<RoutingFilteredHeuristic> heuristic,
int num_close_nodes);
517 return absl::StrCat(
"HeuristicCloseNodesLNS(",
HeuristicName(),
")");
521 void OnStart()
override;
523 bool IncrementPosition()
override;
525 std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor()
override;
527 void RemoveNode(int64_t node);
528 void RemoveNodeAndActiveSibling(int64_t node);
530 bool IsActive(int64_t node)
const {
535 int64_t Prev(int64_t node)
const {
538 return changed_prevs_[node] ? new_prevs_[node] :
InverseValue(node);
540 int64_t Next(int64_t node)
const {
542 return changed_nexts_[node] ? new_nexts_[node] :
Value(node);
545 std::vector<int64_t> GetActiveSiblings(int64_t node)
const;
547 const std::vector<std::pair<std::vector<int64_t>, std::vector<int64_t>>>&
548 pickup_delivery_pairs_;
554 std::vector<std::vector<int64_t>> close_nodes_;
556 std::vector<int64_t> new_nexts_;
557 SparseBitset<> changed_nexts_;
558 std::vector<int64_t> new_prevs_;
559 SparseBitset<> changed_prevs_;
572 const std::vector<IntVar*>& secondary_vars,
573 std::function<
int(int64_t)> start_empty_path_class,
574 int num_arcs_to_consider,
575 std::function<int64_t(int64_t, int64_t, int64_t)>
576 arc_cost_for_path_start);
581 std::string
DebugString()
const override {
return "RelocateExpensiveChain"; }
584 void OnNodeInitialization()
override;
585 void IncrementCurrentPath();
586 bool IncrementCurrentArcIndices();
590 bool FindMostExpensiveChainsOnRemainingPaths();
592 int num_arcs_to_consider_;
594 std::vector<std::pair<int64_t, int>> most_expensive_arc_starts_and_ranks_;
598 current_expensive_arc_indices_;
599 std::function<int64_t( int64_t, int64_t,
601 arc_cost_for_path_start_;
605 bool has_non_empty_paths_to_explore_;
615template <
bool swap_first>
619 const std::vector<IntVar*>& secondary_vars,
620 std::function<
int(int64_t)> start_empty_path_class,
627 return "PairNodeSwapActiveOperator";
644 void OnNodeInitialization()
override;
653template <
bool swap_first>
655 const std::vector<IntVar*>& vars,
656 const std::vector<IntVar*>& secondary_vars,
657 std::function<
int(int64_t)> start_empty_path_class,
660 std::move(start_empty_path_class)),
662 pairs_(index_pairs) {}
664template <
bool swap_first>
668 if (base_index == 0 || StartNode(base_index) != StartNode(base_index - 1)) {
669 return StartNode(base_index);
671 return BaseNode(base_index - 1);
675template <
bool swap_first>
677 for (
int i = 0; i < pairs_.size(); ++i) {
678 if (IsInactive(pairs_[i].first[0]) && IsInactive(pairs_[i].second[0])) {
683 inactive_pair_ = pairs_.size();
686template <
bool swap_first>
689 while (inactive_pair_ < pairs_.size()) {
690 if (!IsInactive(pairs_[inactive_pair_].first[0]) ||
691 !IsInactive(pairs_[inactive_pair_].second[0]) ||
702template <
bool swap_first>
704 const int64_t base = BaseNode(0);
705 if (IsPathEnd(base)) {
708 const int64_t pair_first = pairs_[inactive_pair_].first[0];
709 const int64_t pair_second = pairs_[inactive_pair_].second[0];
711 return MakeActive(pair_second, BaseNode(1)) &&
712 MakeActive(pair_first, base) &&
713 MakeChainInactive(pair_first, Next(pair_first));
715 return MakeActive(pair_second, BaseNode(1)) &&
716 MakeActive(pair_first, base) &&
717 MakeChainInactive(pair_second, Next(pair_second));
735 const std::vector<IntVar*>& secondary_vars,
736 std::function<
int(int64_t)> start_empty_path_class,
739 std::string
DebugString()
const override {
return "RelocateSubtrip"; }
744 bool RelocateSubTripFromPickup(int64_t chain_first_node,
745 int64_t insertion_node);
747 bool RelocateSubTripFromDelivery(int64_t chain_last_node,
748 int64_t insertion_node);
749 std::vector<bool> is_pickup_node_;
750 std::vector<bool> is_delivery_node_;
751 std::vector<int> pair_of_node_;
755 std::vector<bool> opened_pairs_bitset_;
757 std::vector<int64_t> rejected_nodes_;
758 std::vector<int64_t> subtrip_nodes_;
764 const std::vector<IntVar*>& secondary_vars,
765 std::function<
int(int64_t)> start_empty_path_class,
768 std::string
DebugString()
const override {
return "ExchangeSubtrip"; }
780 bool ExtractChainsAndCheckCanonical(int64_t base_node,
781 std::vector<int64_t>* rejects,
782 std::vector<int64_t>* subtrip);
788 bool ExtractChainsFromPickup(int64_t base_node, std::vector<int64_t>* rejects,
789 std::vector<int64_t>* subtrip);
795 bool ExtractChainsFromDelivery(int64_t base_node,
796 std::vector<int64_t>* rejects,
797 std::vector<int64_t>* subtrip);
798 void SetPath(
const std::vector<int64_t>& path,
int path_id);
801 std::vector<bool> is_pickup_node_;
802 std::vector<bool> is_delivery_node_;
803 std::vector<int> pair_of_node_;
805 std::vector<bool> opened_pairs_set_;
807 std::vector<int64_t> rejects0_;
808 std::vector<int64_t> subtrip0_;
809 std::vector<int64_t> rejects1_;
810 std::vector<int64_t> subtrip1_;
811 std::vector<int64_t> path0_;
812 std::vector<int64_t> path1_;
#define DCHECK_LT(val1, val2)
#define DCHECK(condition)
#define DCHECK_EQ(val1, val2)
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)
RoutingModel *const model_
virtual bool IncrementPosition()=0
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.
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 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
Redefines MakeNextNeighbor to export a simpler interface.
~IndexPairSwapActiveOperator() override
std::string DebugString() const override
Specialization of LocalSearchOperator built from an array of IntVars which specifies the scope of the...
bool MakeNextNeighbor(Assignment *delta, Assignment *deltadelta) override
Redefines MakeNextNeighbor to export a simpler interface.
int64_t InverseValue(int64_t index) const
bool MakeNeighbor() override
~LightPairRelocateOperator() 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::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
Redefines MakeNextNeighbor to export a simpler interface.
~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.
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
Redefines MakeNextNeighbor to export a simpler interface.
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
void SetValue(int64_t index, const int64_t &value)
const int64_t & Value(int64_t index) const
Returns the value in the current assignment of the variable of given index.
Collection of objects used to extend the Constraint Solver library.
std::function< int64_t(int64_t, int64_t)> RoutingTransitCallback2
std::vector< RoutingIndexPair > RoutingIndexPairs