OR-Tools  9.6
routing_neighborhoods.h
Go to the documentation of this file.
1 // Copyright 2010-2022 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_NEIGHBORHOODS_H_
15 #define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_NEIGHBORHOODS_H_
16 
17 #include <cstdint>
18 #include <functional>
19 #include <memory>
20 #include <string>
21 #include <utility>
22 #include <vector>
23 
24 #include "absl/strings/str_cat.h"
26 #include "ortools/base/logging.h"
32 #include "ortools/util/bitset.h"
33 
34 namespace operations_research {
35 
56 // TODO(user): Consider merging with standard Relocate in local_search.cc.
58  public:
60  const std::vector<IntVar*>& vars,
61  const std::vector<IntVar*>& secondary_vars,
62  std::function<int(int64_t)> start_empty_path_class,
63  RoutingTransitCallback2 arc_evaluator);
65 
66  bool MakeNeighbor() override;
67  std::string DebugString() const override { return "RelocateNeighbors"; }
68 
69  private:
76  bool MoveChainAndRepair(int64_t before_chain, int64_t chain_end,
77  int64_t destination);
78 
86  int64_t Reposition(int64_t before_to_move, int64_t up_to);
87 
88  RoutingTransitCallback2 arc_evaluator_;
89 };
90 
91 // Swaps active nodes from node alternatives in sequence. Considers chains of
92 // nodes with alternatives, builds a DAG from the chain, each "layer" of the DAG
93 // being composed of the set of alternatives of the node at a given rank in the
94 // chain, fully connected to the next layer. A neighbor is built from the
95 // shortest path starting from the node before the chain (source), through the
96 // DAG to the node following the chain. The path is valued with a given
97 // callback.
98 // Example:
99 // Alternative sets: {1,2} and {3,4}
100 // Current path: 0 -> 1 -> 3 -> 5
101 // DAG + source and sink: -> 1 ---> 3 --
102 // | \ / v
103 // 0 X 5
104 // | / \ ^
105 // -> 2 ---> 4 --
106 // Supposing the shortest path from 0 to 5 is 0, 2, 3, 5, the neighbor for the
107 // chain will be: 0 -> 2 -> 3 -> 5.
108 // TODO(user): Support vehicle-class-dependent arc_evaluators.
110  public:
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,
116  RoutingTransitCallback2 arc_evaluator);
117  ~SwapActiveToShortestPathOperator() override = default;
118  bool MakeNeighbor() override;
119  std::string DebugString() const override {
120  return "SwapActiveToShortestPath";
121  }
122 
123  private:
124  void UpdateShortestPath(int source, int sink,
125  const std::vector<int>& alternative_chain);
126 
127  RoutingTransitCallback2 arc_evaluator_;
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_;
132 };
133 
138 // TODO(user): Add option to prune neighbords where the order of node pairs
139 // is violated (ie precedence between pickup and delivery nodes).
140 // TODO(user): Move this to local_search.cc if it's generic enough.
141 // TODO(user): Detect pairs automatically by parsing the constraint model;
142 // we could then get rid of the pair API in the RoutingModel
143 // class.
144 
158  public:
159  MakePairActiveOperator(const std::vector<IntVar*>& vars,
160  const std::vector<IntVar*>& secondary_vars,
161  std::function<int(int64_t)> start_empty_path_class,
162  const RoutingIndexPairs& pairs);
164  bool MakeNeighbor() override;
165  std::string DebugString() const override { return "MakePairActive"; }
166 
167  protected:
168  bool MakeOneNeighbor() override;
169  bool OnSamePathAsPreviousBase(int64_t base_index) override {
172  return true;
173  }
174 
175  int64_t GetBaseNodeRestartPosition(int base_index) override;
176 
179  bool RestartAtPathStartOnSynchronize() override { return true; }
180 
181  private:
182  void OnNodeInitialization() override;
183  int FindNextInactivePair(int pair_index) const;
184  bool ContainsActiveNodes(const std::vector<int64_t>& nodes) const;
185 
186  int inactive_pair_;
187  int inactive_pair_first_index_;
188  int inactive_pair_second_index_;
189  const RoutingIndexPairs pairs_;
190 };
191 
194  public:
195  MakePairInactiveOperator(const std::vector<IntVar*>& vars,
196  const std::vector<IntVar*>& secondary_vars,
197  std::function<int(int64_t)> start_empty_path_class,
198  const RoutingIndexPairs& index_pairs);
199 
200  bool MakeNeighbor() override;
201  std::string DebugString() const override { return "MakePairInActive"; }
202 };
203 
213  public:
214  PairRelocateOperator(const std::vector<IntVar*>& vars,
215  const std::vector<IntVar*>& secondary_vars,
216  std::function<int(int64_t)> start_empty_path_class,
217  const RoutingIndexPairs& index_pairs);
218  ~PairRelocateOperator() override {}
219 
220  bool MakeNeighbor() override;
221  std::string DebugString() const override { return "PairRelocateOperator"; }
222 
223  protected:
224  bool OnSamePathAsPreviousBase(int64_t base_index) override {
226  return base_index == kPairSecondNodeDestination;
227  }
228  int64_t GetBaseNodeRestartPosition(int base_index) override;
229 
230  bool ConsiderAlternatives(int64_t base_index) const override {
231  return base_index == kPairFirstNode;
232  }
233 
234  private:
235  bool RestartAtPathStartOnSynchronize() override { return true; }
236 
237  static constexpr int kPairFirstNode = 0;
238  static constexpr int kPairFirstNodeDestination = 1;
239  static constexpr int kPairSecondNodeDestination = 2;
240 };
241 
245  public:
247  const std::vector<IntVar*>& vars,
248  const std::vector<IntVar*>& secondary_vars,
249  std::function<int(int64_t)> start_empty_path_class,
250  const RoutingIndexPairs& index_pairs);
252 
253  bool MakeNeighbor() override;
254  std::string DebugString() const override { return "GroupPairAndRelocate"; }
255 };
256 
266 // TODO(user): Add a version which inserts the first node before the other
267 // pair's first node; there are many redundant neighbors if done blindly.
269  public:
270  LightPairRelocateOperator(const std::vector<IntVar*>& vars,
271  const std::vector<IntVar*>& secondary_vars,
272  std::function<int(int64_t)> start_empty_path_class,
273  const RoutingIndexPairs& index_pairs,
274  std::function<bool(int64_t)> force_lifo = nullptr);
276 
277  bool MakeNeighbor() override;
278  std::string DebugString() const override {
279  return "LightPairRelocateOperator";
280  }
281 
282  private:
283  std::function<bool(int64_t)> force_lifo_;
284 };
285 
293  public:
294  PairExchangeOperator(const std::vector<IntVar*>& vars,
295  const std::vector<IntVar*>& secondary_vars,
296  std::function<int(int64_t)> start_empty_path_class,
297  const RoutingIndexPairs& index_pairs);
298  ~PairExchangeOperator() override {}
299 
300  bool MakeNeighbor() override;
301  std::string DebugString() const override { return "PairExchangeOperator"; }
302 
303  private:
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;
308 };
309 
324  public:
326  const std::vector<IntVar*>& vars,
327  const std::vector<IntVar*>& secondary_vars,
328  std::function<int(int64_t)> start_empty_path_class,
329  const RoutingIndexPairs& index_pairs);
331 
332  bool MakeNeighbor() override;
333  std::string DebugString() const override {
334  return "PairExchangeRelocateOperator";
335  }
336 
337  protected:
338  bool OnSamePathAsPreviousBase(int64_t base_index) override;
339  int64_t GetBaseNodeRestartPosition(int base_index) override;
340 
341  private:
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],
346  int64_t prev[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;
349 
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;
356 };
357 
369  public:
370  SwapIndexPairOperator(const std::vector<IntVar*>& vars,
371  const std::vector<IntVar*>& path_vars,
372  std::function<int(int64_t)> start_empty_path_class,
373  const RoutingIndexPairs& index_pairs);
375 
376  bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) override;
377  void OnStart() override;
378  std::string DebugString() const override { return "SwapIndexPairOperator"; }
379 
380  private:
383  bool UpdateActiveNodes();
385  void SetNext(int64_t from, int64_t to, int64_t path) {
386  DCHECK_LT(from, number_of_nexts_);
387  SetValue(from, to);
388  if (!ignore_path_vars_) {
389  DCHECK_LT(from + number_of_nexts_, Size());
390  SetValue(from + number_of_nexts_, path);
391  }
392  }
393 
394  const RoutingIndexPairs index_pairs_;
395  int pair_index_;
396  int first_index_;
397  int second_index_;
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_;
403 };
404 
408  public:
410  const std::vector<IntVar*>& vars,
411  const std::vector<IntVar*>& secondary_vars,
412  std::function<int(int64_t)> start_empty_path_class,
413  const RoutingIndexPairs& index_pairs);
415 
416  bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) override;
417  bool MakeNeighbor() override;
418  std::string DebugString() const override {
419  return "IndexPairSwapActiveOperator";
420  }
421 
422  private:
423  void OnNodeInitialization() override;
424 
425  int inactive_node_;
426 };
427 
430 // TODO(user): Put these methods in an object with helper methods instead
431 // of adding a layer to the class hierarchy.
433  public:
435  std::unique_ptr<RoutingFilteredHeuristic> heuristic,
436  bool keep_inverse_values = false);
438 
439  protected:
440  virtual bool IncrementPosition() = 0;
444  virtual std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor() = 0;
445 
446  std::string HeuristicName() const {
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);
452  // NOTE: Verify that the "FilteredHeuristic" string was at the end of the
453  // heuristic name.
454  DCHECK_EQ(heuristic_name.size(), expected_name_size);
455  }
456  return heuristic_name;
457  }
458 
459  // TODO(user): Remove the dependency from RoutingModel by storing an
460  // IntVarFilteredHeuristic here instead and storing information on path
461  // start/ends like PathOperator does (instead of relying on the model).
465 
466  private:
467  bool MakeOneNeighbor() override;
468  bool MakeChangesAndInsertNodes();
469 
470  int64_t VehicleVarIndex(int64_t node) const { return model_->Size() + node; }
471 
472  const std::unique_ptr<RoutingFilteredHeuristic> heuristic_;
473  const bool consider_vehicle_vars_;
474 };
475 
480  public:
482  std::unique_ptr<RoutingFilteredHeuristic> heuristic);
484 
485  std::string DebugString() const override {
486  return absl::StrCat("HeuristicPathLNS(", HeuristicName(), ")");
487  }
488 
489  private:
490  void OnStart() override;
491 
492  bool IncrementPosition() override;
493  bool CurrentRouteIsEmpty() const;
494  void IncrementCurrentRouteToNextNonEmpty();
495 
496  std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor() override;
497 
498  int current_route_;
499  int last_route_;
500  bool just_started_;
501 };
502 
508  public:
510  std::unique_ptr<RoutingFilteredHeuristic> heuristic);
512 
513  std::string DebugString() const override {
514  return absl::StrCat("RelocatePathAndHeuristicInsertUnperformed(",
515  HeuristicName(), ")");
516  }
517 
518  private:
519  void OnStart() override;
520 
521  bool IncrementPosition() override;
522  bool IncrementRoutes();
523 
524  std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor() override;
525 
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_;
534  bool just_started_;
535 };
536 
542  public:
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);
549 
550  std::string DebugString() const override {
551  return absl::StrCat("HeuristicExpensiveChainLNS(", HeuristicName(), ")");
552  }
553 
554  private:
555  void OnStart() override;
556 
557  bool IncrementPosition() override;
558  bool IncrementRoute();
559  bool IncrementCurrentArcIndices();
560  bool FindMostExpensiveChainsOnRemainingRoutes();
561 
562  std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor() override;
563 
564  int current_route_;
565  int last_route_;
566 
567  const int num_arcs_to_consider_;
568  std::vector<std::pair<int64_t, int>> most_expensive_arc_starts_and_ranks_;
571  std::pair</*first_arc_index*/ int, /*second_arc_index*/ int>
572  current_expensive_arc_indices_;
573  std::function<int64_t(/*before_node*/ int64_t, /*after_node*/ int64_t,
574  /*path_start*/ int64_t)>
575  arc_cost_for_route_start_;
576 
577  bool just_started_;
578 };
579 
585  public:
587  std::unique_ptr<RoutingFilteredHeuristic> heuristic, int num_close_nodes);
589 
590  std::string DebugString() const override {
591  return absl::StrCat("HeuristicCloseNodesLNS(", HeuristicName(), ")");
592  }
593 
594  private:
595  void Initialize();
596 
597  void OnStart() override;
598 
599  bool IncrementPosition() override;
600 
601  std::function<int64_t(int64_t)> SetupNextAccessorForNeighbor() override;
602 
603  void RemoveNode(int64_t node);
604  void RemoveNodeAndActiveSibling(int64_t node);
605 
606  bool IsActive(int64_t node) const {
607  DCHECK_LT(node, model_->Size());
608  return Value(node) != node && !removed_nodes_[node];
609  }
610 
611  int64_t Prev(int64_t node) const {
612  DCHECK_EQ(Value(InverseValue(node)), node);
613  DCHECK_LT(node, new_prevs_.size());
614  return changed_prevs_[node] ? new_prevs_[node] : InverseValue(node);
615  }
616  int64_t Next(int64_t node) const {
617  DCHECK(!model_->IsEnd(node));
618  return changed_nexts_[node] ? new_nexts_[node] : Value(node);
619  }
620 
621  std::vector<int64_t> GetActiveSiblings(int64_t node) const;
622 
623  const std::vector<std::pair<std::vector<int64_t>, std::vector<int64_t>>>&
624  pickup_delivery_pairs_;
625 
626  int current_node_;
627  int last_node_;
628  bool just_started_;
629  bool initialized_;
630 
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_;
638 };
639 
648  public:
649  RelocateExpensiveChain(const std::vector<IntVar*>& vars,
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);
656  bool MakeNeighbor() override;
657  bool MakeOneNeighbor() override;
658 
659  std::string DebugString() const override { return "RelocateExpensiveChain"; }
660 
661  private:
662  void OnNodeInitialization() override;
663  void IncrementCurrentPath();
664  bool IncrementCurrentArcIndices();
668  bool FindMostExpensiveChainsOnRemainingPaths();
669 
670  int num_arcs_to_consider_;
671  int current_path_;
672  std::vector<std::pair<int64_t, int>> most_expensive_arc_starts_and_ranks_;
675  std::pair</*first_arc_index*/ int, /*second_arc_index*/ int>
676  current_expensive_arc_indices_;
677  std::function<int64_t(/*before_node*/ int64_t, /*after_node*/ int64_t,
678  /*path_start*/ int64_t)>
679  arc_cost_for_path_start_;
680  int end_path_;
683  bool has_non_empty_paths_to_explore_;
684 };
685 
693 template <bool swap_first>
695  public:
696  PairNodeSwapActiveOperator(const std::vector<IntVar*>& vars,
697  const std::vector<IntVar*>& secondary_vars,
698  std::function<int(int64_t)> start_empty_path_class,
699  const RoutingIndexPairs& index_pairs);
701 
702  bool MakeNextNeighbor(Assignment* delta, Assignment* deltadelta) override;
703  bool MakeNeighbor() override;
704  std::string DebugString() const override {
705  return "PairNodeSwapActiveOperator";
706  }
707 
708  protected:
709  bool OnSamePathAsPreviousBase(int64_t base_index) override {
712  return true;
713  }
714 
715  int64_t GetBaseNodeRestartPosition(int base_index) override;
716 
719  bool RestartAtPathStartOnSynchronize() override { return true; }
720 
721  private:
722  void OnNodeInitialization() override;
723 
724  int inactive_pair_;
725  RoutingIndexPairs pairs_;
726 };
727 
728 // ==========================================================================
729 // Section: Implementations of the template classes declared above.
730 
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,
736  const RoutingIndexPairs& index_pairs)
737  : PathOperator(vars, secondary_vars, 2, false, false,
738  std::move(start_empty_path_class)),
739  inactive_pair_(0),
740  pairs_(index_pairs) {}
741 
742 template <bool swap_first>
744  int base_index) {
745  // Base node 1 must be after base node 0 if they are both on the same path.
746  if (base_index == 0 || StartNode(base_index) != StartNode(base_index - 1)) {
747  return StartNode(base_index);
748  } else {
749  return BaseNode(base_index - 1);
750  }
751 }
752 
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])) {
757  inactive_pair_ = i;
758  return;
759  }
760  }
761  inactive_pair_ = pairs_.size();
762 }
763 
764 template <bool swap_first>
766  Assignment* delta, Assignment* deltadelta) {
767  while (inactive_pair_ < pairs_.size()) {
768  if (!IsInactive(pairs_[inactive_pair_].first[0]) ||
769  !IsInactive(pairs_[inactive_pair_].second[0]) ||
770  !PathOperator::MakeNextNeighbor(delta, deltadelta)) {
771  ResetPosition();
772  ++inactive_pair_;
773  } else {
774  return true;
775  }
776  }
777  return false;
778 }
779 
780 template <bool swap_first>
782  const int64_t base = BaseNode(0);
783  if (IsPathEnd(base)) {
784  return false;
785  }
786  const int64_t pair_first = pairs_[inactive_pair_].first[0];
787  const int64_t pair_second = pairs_[inactive_pair_].second[0];
788  if (swap_first) {
789  return MakeActive(pair_second, BaseNode(1)) &&
790  MakeActive(pair_first, base) &&
791  MakeChainInactive(pair_first, Next(pair_first));
792  } else {
793  return MakeActive(pair_second, BaseNode(1)) &&
794  MakeActive(pair_first, base) &&
795  MakeChainInactive(pair_second, Next(pair_second));
796  }
797 }
798 
811  public:
812  RelocateSubtrip(const std::vector<IntVar*>& vars,
813  const std::vector<IntVar*>& secondary_vars,
814  std::function<int(int64_t)> start_empty_path_class,
815  const RoutingIndexPairs& pairs);
816 
817  std::string DebugString() const override { return "RelocateSubtrip"; }
818  bool MakeNeighbor() override;
819 
820  private:
821  // Relocates the subtrip starting at chain_first_node. It must be a pickup.
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_;
830  // Represents the set of pairs that have been opened during a call to
831  // MakeNeighbor(). This vector must be all false before and after calling
832  // RelocateSubTripFromPickup() and RelocateSubTripFromDelivery().
833  std::vector<bool> opened_pairs_bitset_;
834 
835  std::vector<int64_t> rejected_nodes_;
836  std::vector<int64_t> subtrip_nodes_;
837 };
838 
840  public:
841  ExchangeSubtrip(const std::vector<IntVar*>& vars,
842  const std::vector<IntVar*>& secondary_vars,
843  std::function<int(int64_t)> start_empty_path_class,
844  const RoutingIndexPairs& pairs);
845 
846  std::string DebugString() const override { return "ExchangeSubtrip"; }
847  bool MakeNeighbor() override;
848 
849  private:
850  // Try to extract a subtrip from base_node (see below) and check that the move
851  // will be canonical.
852  // Given a pickup/delivery pair, this operator could generate the same move
853  // twice, the first time with base_node == pickup, the second time with
854  // base_node == delivery. This happens only when no nodes in the subtrip
855  // remain in the original path, i.e. when rejects is empty after
856  // chain extraction. In that case, we keep only a canonical move out of the
857  // two possibilities, the move where base_node is a pickup.
858  bool ExtractChainsAndCheckCanonical(int64_t base_node,
859  std::vector<int64_t>* rejects,
860  std::vector<int64_t>* subtrip);
861  // Reads the path from base_node forward, collecting subtrip nodes in
862  // subtrip and non-subtrip nodes in rejects.
863  // Non-subtrip nodes will be unmatched delivery nodes.
864  // base_node must be a pickup, and remaining/extracted_nodes must be empty.
865  // Returns true if such chains could be extracted.
866  bool ExtractChainsFromPickup(int64_t base_node, std::vector<int64_t>* rejects,
867  std::vector<int64_t>* subtrip);
868  // Reads the path from base_node backward, collecting subtrip nodes in
869  // subtrip and non-subtrip nodes in rejects.
870  // Non-subtrip nodes will be unmatched pickup nodes.
871  // base_node must be a delivery, and remaining/extracted_nodes must be empty.
872  // Returns true if such chains could be extracted.
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);
877 
878  // Precompute some information about nodes.
879  std::vector<bool> is_pickup_node_;
880  std::vector<bool> is_delivery_node_;
881  std::vector<int> pair_of_node_;
882  // Represents the set of opened pairs during ExtractChainsFromXXX().
883  std::vector<bool> opened_pairs_set_;
884  // Keep internal structures under hand to avoid reallocation.
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_;
891 };
892 
893 } // namespace operations_research
894 
895 #endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_NEIGHBORHOODS_H_
An Assignment is a variable -> domains mapping, used to report solutions to the user.
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(std::unique_ptr< RoutingFilteredHeuristic > heuristic, int num_close_nodes)
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)
Class of operators using a RoutingFilteredHeuristic to insert unperformed nodes after changes have be...
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.
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)
Operator which moves a pair of nodes to another position where the first node of the pair is directly...
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)
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 MakeNextNeighbor(Assignment *delta, Assignment *deltadelta) override
OnStart() should really be protected, but then SWIG doesn't see it.
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.
Definition: local_search.cc:79
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...
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)
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...
MakePairActiveOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, const RoutingIndexPairs &pairs)
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...
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)
Relocate neighborhood which moves chains of neighbors.
MakeRelocateNeighborsOperator(const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, std::function< int(int64_t)> start_empty_path_class, RoutingTransitCallback2 arc_evaluator)
Operator which exchanges the position of two pairs; for both pairs the first node of the pair must be...
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)
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...
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)
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...
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 MakeNextNeighbor(Assignment *delta, Assignment *deltadelta) override
OnStart() should really be protected, but then SWIG doesn't see it.
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...
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 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...
Base class of the local search operators dedicated to path modifications (a path is a set of nodes li...
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.
Heuristic-based local search operator which relocates an entire route to an empty vehicle of differen...
RelocatePathAndHeuristicInsertUnperformedOperator(std::unique_ptr< RoutingFilteredHeuristic > heuristic)
Tries to move subtrips after an insertion node.
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.
Definition: routing.h:1654
bool IsEnd(int64_t index) const
Returns true if 'index' represents the last node of a route.
Definition: routing.h:1456
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)
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)
Collection of objects used to extend the Constraint Solver library.
std::function< int64_t(int64_t, int64_t)> RoutingTransitCallback2
Definition: routing_types.h:43
std::vector< RoutingIndexPair > RoutingIndexPairs
Definition: routing_types.h:46
int64_t delta
Definition: resource.cc:1695
int nodes