14#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_NEIGHBORHOODS_H_
15#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_NEIGHBORHOODS_H_
23#include "absl/log/check.h"
24#include "absl/types/span.h"
56 const std::vector<IntVar*>& vars,
57 const std::vector<IntVar*>& secondary_vars,
58 std::function<
int(int64_t)> start_empty_path_class,
59 std::function<
const std::vector<int>&(
int,
int)> get_neighbors,
62 const std::vector<IntVar*>& vars,
63 const std::vector<IntVar*>& secondary_vars,
64 std::function<
int(int64_t)> start_empty_path_class,
67 std::move(start_empty_path_class),
68 nullptr,
std::move(arc_evaluator)) {}
72 std::string
DebugString()
const override {
return "RelocateNeighbors"; }
81 bool MoveChainAndRepair(int64_t before_chain, int64_t chain_end,
91 int64_t Reposition(int64_t before_to_move, int64_t up_to);
117 const std::vector<IntVar*>& vars,
118 const std::vector<IntVar*>& secondary_vars,
119 std::function<
int(int64_t)> start_empty_path_class,
120 std::vector<std::vector<int64_t>> alternative_sets,
125 return "SwapActiveToShortestPath";
129 const std::vector<int64_t>& GetShortestPath(
130 int source,
int sink,
const std::vector<int>& alternative_chain);
133 const std::vector<std::vector<int64_t>> alternative_sets_;
134 std::vector<int> to_alternative_set_;
135 std::vector<int64_t> path_predecessor_;
136 std::vector<int64_t> path_;
166 const std::vector<IntVar*>& secondary_vars,
167 std::function<
int(int64_t)> start_empty_path_class,
168 const std::vector<PickupDeliveryPair>& pairs);
171 std::string
DebugString()
const override {
return "MakePairActive"; }
188 void OnNodeInitialization()
override;
189 int FindNextInactivePair(
int pair_index)
const;
190 bool ContainsActiveNodes(
const std::vector<int64_t>&
nodes)
const;
193 int inactive_pair_first_index_;
194 int inactive_pair_second_index_;
195 const std::vector<PickupDeliveryPair> pairs_;
202 const std::vector<IntVar*>& secondary_vars,
203 std::function<
int(int64_t)> start_empty_path_class,
204 const std::vector<PickupDeliveryPair>& pairs);
207 std::string
DebugString()
const override {
return "MakePairInActive"; }
221 const std::vector<IntVar*>& secondary_vars,
222 std::function<
int(int64_t)> start_empty_path_class,
223 const std::vector<PickupDeliveryPair>& pairs);
227 std::string
DebugString()
const override {
return "PairRelocateOperator"; }
232 return base_index == kPairSecondNodeDestination;
237 return base_index == kPairFirstNode;
241 bool RestartAtPathStartOnSynchronize()
override {
return true; }
243 static constexpr int kPairFirstNode = 0;
244 static constexpr int kPairFirstNodeDestination = 1;
245 static constexpr int kPairSecondNodeDestination = 2;
253 const std::vector<IntVar*>& vars,
254 const std::vector<IntVar*>& secondary_vars,
255 std::function<
int(int64_t)> start_empty_path_class,
256 std::function<
const std::vector<int>&(
int,
int)> get_neighbors,
257 const std::vector<PickupDeliveryPair>& pairs);
259 const std::vector<IntVar*>& vars,
260 const std::vector<IntVar*>& secondary_vars,
261 std::function<
int(int64_t)> start_empty_path_class,
262 const std::vector<PickupDeliveryPair>& pairs)
264 std::move(start_empty_path_class), nullptr,
269 std::string
DebugString()
const override {
return "GroupPairAndRelocate"; }
286 const std::vector<IntVar*>& vars,
287 const std::vector<IntVar*>& secondary_vars,
288 std::function<
int(int64_t)> start_empty_path_class,
289 std::function<
const std::vector<int>&(
int,
int)> get_neighbors,
290 const std::vector<PickupDeliveryPair>& pairs,
291 std::function<
bool(int64_t)> force_lifo =
nullptr);
293 const std::vector<IntVar*>& secondary_vars,
294 std::function<
int(int64_t)> start_empty_path_class,
295 const std::vector<PickupDeliveryPair>& pairs,
296 std::function<
bool(int64_t)> force_lifo =
nullptr);
301 return "LightPairRelocateOperator";
305 std::function<bool(int64_t)> force_lifo_;
317 const std::vector<IntVar*>& vars,
318 const std::vector<IntVar*>& secondary_vars,
319 std::function<
int(int64_t)> start_empty_path_class,
320 std::function<
const std::vector<int>&(
int,
int)> get_neighbors,
321 const std::vector<PickupDeliveryPair>& pairs);
323 const std::vector<IntVar*>& secondary_vars,
324 std::function<
int(int64_t)> start_empty_path_class,
325 const std::vector<PickupDeliveryPair>& pairs)
327 std::move(start_empty_path_class), nullptr,
332 std::string
DebugString()
const override {
return "PairExchangeOperator"; }
335 bool RestartAtPathStartOnSynchronize()
override {
return true; }
336 bool ConsiderAlternatives(int64_t )
const override {
339 bool GetPreviousAndSibling(int64_t node, int64_t* previous, int64_t* sibling,
340 int64_t* sibling_previous)
const;
359 const std::vector<IntVar*>& vars,
360 const std::vector<IntVar*>& secondary_vars,
361 std::function<
int(int64_t)> start_empty_path_class,
362 const std::vector<PickupDeliveryPair>& pairs);
367 return "PairExchangeRelocateOperator";
375 bool RestartAtPathStartOnSynchronize()
override {
return true; }
376 bool GetPreviousAndSibling(int64_t node, int64_t* previous, int64_t* sibling,
377 int64_t* sibling_previous)
const;
378 bool MoveNode(
int pair,
int node, int64_t
nodes[2][2], int64_t dest[2][2],
380 bool LoadAndCheckDest(
int pair,
int node, int64_t base_node,
381 int64_t
nodes[2][2], int64_t dest[2][2])
const;
383 static constexpr int kFirstPairFirstNode = 0;
384 static constexpr int kSecondPairFirstNode = 1;
385 static constexpr int kFirstPairFirstNodeDestination = 2;
386 static constexpr int kFirstPairSecondNodeDestination = 3;
387 static constexpr int kSecondPairFirstNodeDestination = 4;
388 static constexpr int kSecondPairSecondNodeDestination = 5;
404 const std::vector<IntVar*>& path_vars,
405 const std::vector<PickupDeliveryPair>& pairs);
410 std::string
DebugString()
const override {
return "SwapIndexPairOperator"; }
415 bool UpdateActiveNodes();
417 void SetNext(int64_t from, int64_t
to, int64_t path) {
418 DCHECK_LT(from, number_of_nexts_);
420 if (!ignore_path_vars_) {
421 DCHECK_LT(from + number_of_nexts_,
Size());
422 SetValue(from + number_of_nexts_, path);
426 const std::vector<PickupDeliveryPair> pairs_;
430 int64_t first_active_;
431 int64_t second_active_;
432 std::vector<int64_t> prevs_;
433 const int number_of_nexts_;
434 const bool ignore_path_vars_;
442 const std::vector<IntVar*>& vars,
443 const std::vector<IntVar*>& secondary_vars,
444 std::function<
int(int64_t)> start_empty_path_class,
445 const std::vector<PickupDeliveryPair>& pairs);
451 return "IndexPairSwapActiveOperator";
455 void OnNodeInitialization()
override;
467class RelocateExpensiveChain :
public PathOperator {
470 const std::vector<IntVar*>& secondary_vars,
471 std::function<
int(int64_t)> start_empty_path_class,
472 int num_arcs_to_consider,
473 std::function<int64_t(int64_t, int64_t, int64_t)>
474 arc_cost_for_path_start);
479 std::string
DebugString()
const override {
return "RelocateExpensiveChain"; }
482 void OnNodeInitialization()
override;
483 void IncrementCurrentPath();
484 bool IncrementCurrentArcIndices();
488 bool FindMostExpensiveChainsOnRemainingPaths();
490 int num_arcs_to_consider_;
492 std::vector<std::pair<int64_t, int>> most_expensive_arc_starts_and_ranks_;
496 current_expensive_arc_indices_;
497 std::function<int64_t( int64_t, int64_t,
499 arc_cost_for_path_start_;
503 bool has_non_empty_paths_to_explore_;
513template <
bool swap_first>
517 const std::vector<IntVar*>& secondary_vars,
518 std::function<
int(int64_t)> start_empty_path_class,
519 const std::vector<PickupDeliveryPair>& pairs);
525 return "PairNodeSwapActiveOperator";
542 void OnNodeInitialization()
override;
545 std::vector<PickupDeliveryPair> pairs_;
551template <
bool swap_first>
553 const std::vector<IntVar*>& vars,
554 const std::vector<IntVar*>& secondary_vars,
555 std::function<
int(int64_t)> start_empty_path_class,
556 const std::vector<PickupDeliveryPair>& pairs)
558 std::move(start_empty_path_class), nullptr),
562template <
bool swap_first>
566 if (base_index == 0 || StartNode(base_index) != StartNode(base_index - 1)) {
567 return StartNode(base_index);
569 return BaseNode(base_index - 1);
573template <
bool swap_first>
574void PairNodeSwapActiveOperator<swap_first>::OnNodeInitialization() {
575 for (
int i = 0;
i < pairs_.size(); ++
i) {
576 if (IsInactive(pairs_[i].pickup_alternatives[0]) &&
577 IsInactive(pairs_[i].delivery_alternatives[0])) {
582 inactive_pair_ = pairs_.size();
585template <
bool swap_first>
587 Assignment*
delta, Assignment* deltadelta) {
588 while (inactive_pair_ < pairs_.size()) {
589 if (!IsInactive(pairs_[inactive_pair_].pickup_alternatives[0]) ||
590 !IsInactive(pairs_[inactive_pair_].delivery_alternatives[0]) ||
601template <
bool swap_first>
603 const int64_t base = BaseNode(0);
604 if (IsPathEnd(base)) {
607 const int64_t pair_first = pairs_[inactive_pair_].pickup_alternatives[0];
608 const int64_t pair_second = pairs_[inactive_pair_].delivery_alternatives[0];
610 return MakeActive(pair_second, BaseNode(1)) &&
611 MakeActive(pair_first, base) &&
612 MakeChainInactive(pair_first,
Next(pair_first));
614 return MakeActive(pair_second, BaseNode(1)) &&
615 MakeActive(pair_first, base) &&
616 MakeChainInactive(pair_second,
Next(pair_second));
621class PickupAndDeliveryData {
624 absl::Span<const PickupDeliveryPair> pairs);
626 DCHECK_LT(node, is_pickup_node_.size());
627 return is_pickup_node_[node];
630 DCHECK_LT(node, is_delivery_node_.size());
631 return is_delivery_node_[node];
634 DCHECK_LT(node, pair_of_node_.size());
635 return pair_of_node_[node];
639 std::vector<bool> is_pickup_node_;
640 std::vector<bool> is_delivery_node_;
641 std::vector<int> pair_of_node_;
655class RelocateSubtrip :
public PathOperator {
658 const std::vector<IntVar*>& vars,
659 const std::vector<IntVar*>& secondary_vars,
660 std::function<
int(int64_t)> start_empty_path_class,
661 std::function<
const std::vector<int>&(
int,
int)> get_neighbors,
662 const std::vector<PickupDeliveryPair>& pairs);
664 const std::vector<IntVar*>& secondary_vars,
665 std::function<
int(int64_t)> start_empty_path_class,
666 const std::vector<PickupDeliveryPair>& pairs)
670 std::string
DebugString()
const override {
return "RelocateSubtrip"; }
675 bool RelocateSubTripFromPickup(int64_t chain_first_node,
676 int64_t insertion_node);
678 bool RelocateSubTripFromDelivery(int64_t chain_last_node,
679 int64_t insertion_node);
680 void SetPath(absl::Span<const int64_t> path,
int path_id);
686 std::vector<bool> opened_pairs_set_;
688 std::vector<int64_t> rejected_nodes_;
689 std::vector<int64_t> subtrip_nodes_;
695 const std::vector<IntVar*>& vars,
696 const std::vector<IntVar*>& secondary_vars,
697 std::function<
int(int64_t)> start_empty_path_class,
698 std::function<
const std::vector<int>&(
int,
int)> get_neighbors,
699 const std::vector<PickupDeliveryPair>& pairs);
701 const std::vector<IntVar*>& secondary_vars,
702 std::function<
int(int64_t)> start_empty_path_class,
703 const std::vector<PickupDeliveryPair>& pairs)
707 std::string
DebugString()
const override {
return "ExchangeSubtrip"; }
719 bool ExtractChainsAndCheckCanonical(int64_t base_node,
720 std::vector<int64_t>* rejects,
721 std::vector<int64_t>* subtrip);
727 bool ExtractChainsFromPickup(int64_t base_node, std::vector<int64_t>* rejects,
728 std::vector<int64_t>* subtrip);
734 bool ExtractChainsFromDelivery(int64_t base_node,
735 std::vector<int64_t>* rejects,
736 std::vector<int64_t>* subtrip);
737 void SetPath(
const std::vector<int64_t>& path,
int path_id);
741 std::vector<bool> opened_pairs_set_;
743 std::vector<int64_t> rejects0_;
744 std::vector<int64_t> subtrip0_;
745 std::vector<int64_t> rejects1_;
746 std::vector<int64_t> subtrip1_;
747 std::vector<int64_t> path0_;
748 std::vector<int64_t> path1_;
bool MakeNeighbor() override
std::string DebugString() const override
ExchangeSubtrip(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, std::function< const std::vector< int > &(int, int)> get_neighbors, const std::vector< PickupDeliveryPair > &pairs)
bool MakeNeighbor() override
std::string DebugString() const override
GroupPairAndRelocateOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, std::function< const std::vector< int > &(int, int)> get_neighbors, const std::vector< PickupDeliveryPair > &pairs)
GroupPairAndRelocateOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const std::vector< PickupDeliveryPair > &pairs)
~GroupPairAndRelocateOperator() override
bool MakeNextNeighbor(Assignment *delta, Assignment *deltadelta) override
~IndexPairSwapActiveOperator() override
bool MakeNeighbor() override
IndexPairSwapActiveOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const std::vector< PickupDeliveryPair > &pairs)
std::string DebugString() const override
void SetValue(int64_t index, int64_t value)
LightPairRelocateOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, std::function< const std::vector< int > &(int, int)> get_neighbors, const std::vector< PickupDeliveryPair > &pairs, std::function< bool(int64_t)> force_lifo=nullptr)
std::string DebugString() const override
bool MakeNeighbor() override
~LightPairRelocateOperator() override
virtual bool MakeNextNeighbor(Assignment *delta, Assignment *deltadelta)=0
std::string DebugString() const override
bool OnSamePathAsPreviousBase(int64_t) override
bool MakeOneNeighbor() override
bool MakeNeighbor() override
bool RestartAtPathStartOnSynchronize() override
int64_t GetBaseNodeRestartPosition(int base_index) override
MakePairActiveOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const std::vector< PickupDeliveryPair > &pairs)
~MakePairActiveOperator() override
Operator which makes pairs of active nodes inactive.
bool MakeNeighbor() override
std::string DebugString() const override
MakePairInactiveOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const std::vector< PickupDeliveryPair > &pairs)
MakeRelocateNeighborsOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, RoutingTransitCallback2 arc_evaluator)
std::string DebugString() const override
bool MakeNeighbor() override
MakeRelocateNeighborsOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, std::function< const std::vector< int > &(int, int)> get_neighbors, RoutingTransitCallback2 arc_evaluator)
~MakeRelocateNeighborsOperator() override
PairExchangeOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const std::vector< PickupDeliveryPair > &pairs)
~PairExchangeOperator() override
PairExchangeOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, std::function< const std::vector< int > &(int, int)> get_neighbors, const std::vector< PickupDeliveryPair > &pairs)
std::string DebugString() const override
bool MakeNeighbor() override
int64_t GetBaseNodeRestartPosition(int base_index) override
~PairExchangeRelocateOperator() override
bool OnSamePathAsPreviousBase(int64_t base_index) override
std::string DebugString() const override
PairExchangeRelocateOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const std::vector< PickupDeliveryPair > &pairs)
bool MakeNeighbor() override
bool RestartAtPathStartOnSynchronize() override
bool MakeNextNeighbor(Assignment *delta, Assignment *deltadelta) override
--— Base operator class for operators manipulating IntVars --—
int64_t GetBaseNodeRestartPosition(int base_index) override
bool OnSamePathAsPreviousBase(int64_t) override
~PairNodeSwapActiveOperator() override
bool MakeNeighbor() override
PairNodeSwapActiveOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const std::vector< PickupDeliveryPair > &pairs)
Section: Implementations of the template classes declared above.
std::string DebugString() const override
bool ConsiderAlternatives(int64_t base_index) const override
~PairRelocateOperator() override
bool MakeNeighbor() override
int64_t GetBaseNodeRestartPosition(int base_index) override
std::string DebugString() const override
PairRelocateOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const std::vector< PickupDeliveryPair > &pairs)
bool OnSamePathAsPreviousBase(int64_t base_index) override
A utility class to maintain pickup and delivery information of nodes.
int GetPairOfNode(int64_t node) const
PickupAndDeliveryData(int num_nodes, absl::Span< const PickupDeliveryPair > pairs)
bool IsDeliveryNode(int64_t node) const
bool IsPickupNode(int64_t node) const
~RelocateExpensiveChain() override
std::string DebugString() const override
bool MakeNeighbor() override
bool MakeOneNeighbor() override
This method should not be overridden. Override MakeNeighbor() instead.
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)
RelocateSubtrip(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, std::function< const std::vector< int > &(int, int)> get_neighbors, const std::vector< PickupDeliveryPair > &pairs)
bool MakeNeighbor() override
std::string DebugString() const override
std::string DebugString() const 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)
~SwapActiveToShortestPathOperator() override
bool MakeNeighbor() override
SwapIndexPairOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &path_vars, const std::vector< PickupDeliveryPair > &pairs)
std::string DebugString() const override
~SwapIndexPairOperator() override
bool MakeNextNeighbor(Assignment *delta, Assignment *deltadelta) override
--— Base operator class for operators manipulating IntVars --—
In SWIG mode, we don't want anything besides these top-level includes.
std::function< int64_t(int64_t, int64_t)> RoutingTransitCallback2
trees with all degrees equal to