OR-Tools  9.2
routing_search.h
Go to the documentation of this file.
1 // Copyright 2010-2021 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_SEARCH_H_
15 #define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_SEARCH_H_
16 
17 #include <sys/types.h>
18 
19 #include <algorithm>
20 #include <functional>
21 #include <iterator>
22 #include <memory>
23 #include <set>
24 #include <string>
25 #include <tuple>
26 #include <utility>
27 #include <vector>
28 
29 #include "absl/container/flat_hash_set.h"
32 #include "ortools/base/logging.h"
33 #include "ortools/base/macros.h"
34 #include "ortools/base/mathutil.h"
39 #include "ortools/util/bitset.h"
40 
41 namespace operations_research {
42 
43 class IntVarFilteredHeuristic;
44 #ifndef SWIG
45 class VehicleTypeCurator {
49  public:
51  const RoutingModel::VehicleTypeContainer& vehicle_type_container)
52  : vehicle_type_container_(&vehicle_type_container) {}
53 
54  int NumTypes() const { return vehicle_type_container_->NumTypes(); }
55 
56  int Type(int vehicle) const { return vehicle_type_container_->Type(vehicle); }
57 
60  void Reset(const std::function<bool(int)>& store_vehicle);
61 
64  void Update(const std::function<bool(int)>& remove_vehicle);
65 
66  int GetLowestFixedCostVehicleOfType(int type) const {
67  DCHECK_LT(type, NumTypes());
68  const std::set<VehicleClassEntry>& vehicle_classes =
69  sorted_vehicle_classes_per_type_[type];
70  if (vehicle_classes.empty()) {
71  return -1;
72  }
73  const int vehicle_class = (vehicle_classes.begin())->vehicle_class;
74  DCHECK(!vehicles_per_vehicle_class_[vehicle_class].empty());
75  return vehicles_per_vehicle_class_[vehicle_class][0];
76  }
77 
78  void ReinjectVehicleOfClass(int vehicle, int vehicle_class,
79  int64_t fixed_cost) {
80  std::vector<int>& vehicles = vehicles_per_vehicle_class_[vehicle_class];
81  if (vehicles.empty()) {
84  std::set<VehicleClassEntry>& vehicle_classes =
85  sorted_vehicle_classes_per_type_[Type(vehicle)];
86  const auto& insertion =
87  vehicle_classes.insert({vehicle_class, fixed_cost});
88  DCHECK(insertion.second);
89  }
90  vehicles.push_back(vehicle);
91  }
92 
96  int type, const std::function<bool(int)>& vehicle_is_compatible) const;
105  std::pair<int, int> GetCompatibleVehicleOfType(
106  int type, std::function<bool(int)> vehicle_is_compatible,
107  std::function<bool(int)> stop_and_return_vehicle);
108 
109  private:
110  using VehicleClassEntry =
112  const RoutingModel::VehicleTypeContainer* const vehicle_type_container_;
113  // clang-format off
114  std::vector<std::set<VehicleClassEntry> > sorted_vehicle_classes_per_type_;
115  std::vector<std::vector<int> > vehicles_per_vehicle_class_;
116  // clang-format on
117 };
118 
122 AutomaticFirstSolutionStrategy(bool has_pickup_deliveries,
123  bool has_node_precedences,
124  bool has_single_vehicle_node);
125 
138 
140 // TODO(user): Eventually move this to the core CP solver library
143  public:
145  std::unique_ptr<IntVarFilteredHeuristic> heuristic);
146 
148 
149  Decision* Next(Solver* solver) override;
150 
151  std::string DebugString() const override;
152 
154  int64_t number_of_decisions() const;
155  int64_t number_of_rejects() const;
156 
157  private:
158  const std::unique_ptr<IntVarFilteredHeuristic> heuristic_;
159 };
160 
163  public:
164  IntVarFilteredHeuristic(Solver* solver, const std::vector<IntVar*>& vars,
165  LocalSearchFilterManager* filter_manager);
166 
168 
171  Assignment* const BuildSolution();
172 
175  int64_t number_of_decisions() const { return number_of_decisions_; }
176  int64_t number_of_rejects() const { return number_of_rejects_; }
177 
178  virtual std::string DebugString() const { return "IntVarFilteredHeuristic"; }
179 
180  protected:
182  void ResetSolution();
184  virtual bool InitializeSolution() { return true; }
186  virtual bool BuildSolutionInternal() = 0;
190  bool Commit();
192  virtual bool StopSearch() { return false; }
195  void SetValue(int64_t index, int64_t value) {
196  if (!is_in_delta_[index]) {
197  delta_->FastAdd(vars_[index])->SetValue(value);
198  delta_indices_.push_back(index);
199  is_in_delta_[index] = true;
200  } else {
201  delta_->SetValue(vars_[index], value);
202  }
203  }
206  int64_t Value(int64_t index) const {
208  }
210  bool Contains(int64_t index) const {
211  return assignment_->IntVarContainer().Element(index).Var() != nullptr;
212  }
215  int Size() const { return vars_.size(); }
217  IntVar* Var(int64_t index) const { return vars_[index]; }
219  void SynchronizeFilters();
220 
222 
223  private:
226  bool FilterAccept();
227 
228  Solver* solver_;
229  const std::vector<IntVar*> vars_;
230  Assignment* const delta_;
231  std::vector<int> delta_indices_;
232  std::vector<bool> is_in_delta_;
233  Assignment* const empty_;
234  LocalSearchFilterManager* filter_manager_;
236  int64_t number_of_decisions_;
237  int64_t number_of_rejects_;
238 };
239 
242  public:
244  LocalSearchFilterManager* filter_manager);
248  const std::function<int64_t(int64_t)>& next_accessor);
249  RoutingModel* model() const { return model_; }
251  int GetStartChainEnd(int vehicle) const { return start_chain_ends_[vehicle]; }
253  int GetEndChainStart(int vehicle) const { return end_chain_starts_[vehicle]; }
256  void MakeDisjunctionNodesUnperformed(int64_t node);
264 
265  protected:
266  bool StopSearch() override { return model_->CheckLimit(); }
267  virtual void SetVehicleIndex(int64_t node, int vehicle) {}
268  virtual void ResetVehicleIndices() {}
269  bool VehicleIsEmpty(int vehicle) const {
270  return Value(model()->Start(vehicle)) == model()->End(vehicle);
271  }
272 
273  private:
275  bool InitializeSolution() override;
276 
277  RoutingModel* const model_;
278  std::vector<int64_t> start_chain_ends_;
279  std::vector<int64_t> end_chain_starts_;
280 };
281 
283  public:
287  std::function<int64_t(int64_t, int64_t, int64_t)> evaluator,
288  std::function<int64_t(int64_t)> penalty_evaluator,
289  LocalSearchFilterManager* filter_manager);
291 
292  protected:
293  struct NodeInsertion {
294  int64_t insert_after;
295  int vehicle;
296  int64_t value;
297 
298  bool operator<(const NodeInsertion& other) const {
299  return std::tie(value, insert_after, vehicle) <
300  std::tie(other.value, other.insert_after, other.vehicle);
301  }
302  };
303  struct StartEndValue {
305  int64_t distance;
306  int vehicle;
307 
308  bool operator<(const StartEndValue& other) const {
309  return std::tie(num_allowed_vehicles, distance, vehicle) <
310  std::tie(other.num_allowed_vehicles, other.distance,
311  other.vehicle);
312  }
313  };
314  typedef std::pair<StartEndValue, /*seed_node*/ int> Seed;
315 
321  // clang-format off
322  std::vector<std::vector<StartEndValue> >
323  ComputeStartEndDistanceForVehicles(const std::vector<int>& vehicles);
324 
329  template <class Queue>
331  std::vector<std::vector<StartEndValue> >* start_end_distances_per_node,
332  Queue* priority_queue);
333  // clang-format on
334 
339  void InsertBetween(int64_t node, int64_t predecessor, int64_t successor);
345  int64_t node_to_insert, int64_t start, int64_t next_after_start,
346  int vehicle, std::vector<NodeInsertion>* node_insertions);
351  // TODO(user): Replace 'insert_before' and 'insert_after' by 'predecessor'
352  // and 'successor' in the code.
353  int64_t GetInsertionCostForNodeAtPosition(int64_t node_to_insert,
354  int64_t insert_after,
355  int64_t insert_before,
356  int vehicle) const;
359  int64_t GetUnperformedValue(int64_t node_to_insert) const;
360 
361  std::function<int64_t(int64_t, int64_t, int64_t)> evaluator_;
362  std::function<int64_t(int64_t)> penalty_evaluator_;
363 };
364 
374  public:
387  int64_t min_neighbors;
397  };
398 
402  std::function<int64_t(int64_t, int64_t, int64_t)> evaluator,
403  std::function<int64_t(int64_t)> penalty_evaluator,
404  LocalSearchFilterManager* filter_manager,
407  bool BuildSolutionInternal() override;
408  std::string DebugString() const override {
409  return "GlobalCheapestInsertionFilteredHeuristic";
410  }
411 
412  private:
413  class NodeEntry;
414  class PairEntry;
415 
416  typedef absl::flat_hash_set<PairEntry*> PairEntries;
417  typedef absl::flat_hash_set<NodeEntry*> NodeEntries;
418 
425  bool InsertPairsAndNodesByRequirementTopologicalOrder();
426 
433  bool InsertPairs(
434  const std::map<int64_t, std::vector<int>>& pair_indices_by_bucket);
435 
439  bool UseEmptyVehicleTypeCuratorForVehicle(int vehicle,
440  bool all_vehicles = true) {
441  return vehicle >= 0 && VehicleIsEmpty(vehicle) && all_vehicles;
442  }
443 
450  bool InsertPairEntryUsingEmptyVehicleTypeCurator(
451  const std::vector<int>& pair_indices, PairEntry* const pair_entry,
452  AdjustablePriorityQueue<PairEntry>* priority_queue,
453  std::vector<PairEntries>* pickup_to_entries,
454  std::vector<PairEntries>* delivery_to_entries);
455 
463  bool InsertNodesOnRoutes(
464  const std::map<int64_t, std::vector<int>>& nodes_by_bucket,
465  const absl::flat_hash_set<int>& vehicles);
466 
474  bool InsertNodeEntryUsingEmptyVehicleTypeCurator(
475  const std::vector<int>& nodes, bool all_vehicles,
476  NodeEntry* const node_entry,
477  AdjustablePriorityQueue<NodeEntry>* priority_queue,
478  std::vector<NodeEntries>* position_to_node_entries);
479 
485  bool SequentialInsertNodes(
486  const std::map<int64_t, std::vector<int>>& nodes_by_bucket);
487 
491  void DetectUsedVehicles(std::vector<bool>* is_vehicle_used,
492  std::vector<int>* unused_vehicles,
493  absl::flat_hash_set<int>* used_vehicles);
494 
498  void InsertFarthestNodesAsSeeds();
499 
508  template <class Queue>
509  int InsertSeedNode(
510  std::vector<std::vector<StartEndValue>>* start_end_distances_per_node,
511  Queue* priority_queue, std::vector<bool>* is_vehicle_used);
512  // clang-format on
513 
516  bool InitializePairPositions(
517  const std::vector<int>& pair_indices,
518  AdjustablePriorityQueue<PairEntry>* priority_queue,
519  std::vector<PairEntries>* pickup_to_entries,
520  std::vector<PairEntries>* delivery_to_entries);
526  void InitializeInsertionEntriesPerformingPair(
527  int64_t pickup, int64_t delivery,
528  AdjustablePriorityQueue<PairEntry>* priority_queue,
529  std::vector<PairEntries>* pickup_to_entries,
530  std::vector<PairEntries>* delivery_to_entries);
534  bool UpdateAfterPairInsertion(
535  const std::vector<int>& pair_indices, int vehicle, int64_t pickup,
536  int64_t pickup_position, int64_t delivery, int64_t delivery_position,
537  AdjustablePriorityQueue<PairEntry>* priority_queue,
538  std::vector<PairEntries>* pickup_to_entries,
539  std::vector<PairEntries>* delivery_to_entries);
542  bool UpdatePairPositions(const std::vector<int>& pair_indices, int vehicle,
543  int64_t insert_after,
544  AdjustablePriorityQueue<PairEntry>* priority_queue,
545  std::vector<PairEntries>* pickup_to_entries,
546  std::vector<PairEntries>* delivery_to_entries) {
547  return UpdatePickupPositions(pair_indices, vehicle, insert_after,
548  priority_queue, pickup_to_entries,
549  delivery_to_entries) &&
550  UpdateDeliveryPositions(pair_indices, vehicle, insert_after,
551  priority_queue, pickup_to_entries,
552  delivery_to_entries);
553  }
556  bool UpdatePickupPositions(const std::vector<int>& pair_indices, int vehicle,
557  int64_t pickup_insert_after,
558  AdjustablePriorityQueue<PairEntry>* priority_queue,
559  std::vector<PairEntries>* pickup_to_entries,
560  std::vector<PairEntries>* delivery_to_entries);
563  bool UpdateDeliveryPositions(
564  const std::vector<int>& pair_indices, int vehicle,
565  int64_t delivery_insert_after,
566  AdjustablePriorityQueue<PairEntry>* priority_queue,
567  std::vector<PairEntries>* pickup_to_entries,
568  std::vector<PairEntries>* delivery_to_entries);
571  void DeletePairEntry(PairEntry* entry,
572  AdjustablePriorityQueue<PairEntry>* priority_queue,
573  std::vector<PairEntries>* pickup_to_entries,
574  std::vector<PairEntries>* delivery_to_entries);
579  void AddPairEntry(int64_t pickup, int64_t pickup_insert_after,
580  int64_t delivery, int64_t delivery_insert_after,
581  int vehicle,
582  AdjustablePriorityQueue<PairEntry>* priority_queue,
583  std::vector<PairEntries>* pickup_entries,
584  std::vector<PairEntries>* delivery_entries) const;
587  void UpdatePairEntry(
588  PairEntry* const pair_entry,
589  AdjustablePriorityQueue<PairEntry>* priority_queue) const;
593  int64_t GetInsertionValueForPairAtPositions(int64_t pickup,
594  int64_t pickup_insert_after,
595  int64_t delivery,
596  int64_t delivery_insert_after,
597  int vehicle) const;
598 
601  bool InitializePositions(const std::vector<int>& nodes,
602  const absl::flat_hash_set<int>& vehicles,
603  AdjustablePriorityQueue<NodeEntry>* priority_queue,
604  std::vector<NodeEntries>* position_to_node_entries);
610  void InitializeInsertionEntriesPerformingNode(
611  int64_t node, const absl::flat_hash_set<int>& vehicles,
612  AdjustablePriorityQueue<NodeEntry>* priority_queue,
613  std::vector<NodeEntries>* position_to_node_entries);
616  bool UpdatePositions(const std::vector<int>& nodes, int vehicle,
617  int64_t insert_after, bool all_vehicles,
618  AdjustablePriorityQueue<NodeEntry>* priority_queue,
619  std::vector<NodeEntries>* node_entries);
622  void DeleteNodeEntry(NodeEntry* entry,
623  AdjustablePriorityQueue<NodeEntry>* priority_queue,
624  std::vector<NodeEntries>* node_entries);
625 
629  void AddNodeEntry(int64_t node, int64_t insert_after, int vehicle,
630  bool all_vehicles,
631  AdjustablePriorityQueue<NodeEntry>* priority_queue,
632  std::vector<NodeEntries>* node_entries) const;
635  void UpdateNodeEntry(
636  NodeEntry* const node_entry,
637  AdjustablePriorityQueue<NodeEntry>* priority_queue) const;
638 
641  void ComputeNeighborhoods();
642 
645  bool IsNeighborForCostClass(int cost_class, int64_t node_index,
646  int64_t neighbor_index) const;
647 
649  const std::vector<int64_t>& GetNeighborsOfNodeForCostClass(
650  int cost_class, int64_t node_index) const {
651  return gci_params_.neighbors_ratio == 1
652  ? all_nodes_
653  : node_index_to_neighbors_by_cost_class_[node_index][cost_class]
654  ->PositionsSetAtLeastOnce();
655  }
656 
657  int64_t NumNonStartEndNodes() const {
658  return model()->Size() - model()->vehicles();
659  }
660 
661  int64_t NumNeighbors() const {
662  return std::max(gci_params_.min_neighbors,
664  NumNonStartEndNodes()));
665  }
666 
667  void ResetVehicleIndices() override {
668  node_index_to_vehicle_.assign(node_index_to_vehicle_.size(), -1);
669  }
670 
671  void SetVehicleIndex(int64_t node, int vehicle) override {
672  DCHECK_LT(node, node_index_to_vehicle_.size());
673  node_index_to_vehicle_[node] = vehicle;
674  }
675 
678  bool CheckVehicleIndices() const;
679 
681  int64_t GetBucketOfNode(int node) const {
682  return model()->VehicleVar(node)->Size();
683  }
684 
686  int64_t GetBucketOfPair(const RoutingModel::IndexPair& index_pair) const {
687  int64_t max_pickup_bucket = 0;
688  for (int64_t pickup : index_pair.first) {
689  max_pickup_bucket = std::max(max_pickup_bucket, GetBucketOfNode(pickup));
690  }
691  int64_t max_delivery_bucket = 0;
692  for (int64_t delivery : index_pair.second) {
693  max_delivery_bucket =
694  std::max(max_delivery_bucket, GetBucketOfNode(delivery));
695  }
696  return std::min(max_pickup_bucket, max_delivery_bucket);
697  }
698 
701  template <class T>
702  bool StopSearchAndCleanup(AdjustablePriorityQueue<T>* priority_queue) {
703  if (!StopSearch()) return false;
704  for (T* const entry : *priority_queue->Raw()) {
705  delete entry;
706  }
707  priority_queue->Clear();
708  return true;
709  }
710 
711  GlobalCheapestInsertionParameters gci_params_;
713  std::vector<int> node_index_to_vehicle_;
714 
715  // clang-format off
716  std::vector<std::vector<std::unique_ptr<SparseBitset<int64_t> > > >
717  node_index_to_neighbors_by_cost_class_;
718  // clang-format on
719 
720  std::unique_ptr<VehicleTypeCurator> empty_vehicle_type_curator_;
721 
725  std::vector<int64_t> all_nodes_;
726 };
727 
735  public:
739  std::function<int64_t(int64_t, int64_t, int64_t)> evaluator,
740  LocalSearchFilterManager* filter_manager);
742  bool BuildSolutionInternal() override;
743  std::string DebugString() const override {
744  return "LocalCheapestInsertionFilteredHeuristic";
745  }
746 
747  private:
752  void ComputeEvaluatorSortedPositions(
753  int64_t node, std::vector<NodeInsertion>* sorted_insertions);
758  void ComputeEvaluatorSortedPositionsOnRouteAfter(
759  int64_t node, int64_t start, int64_t next_after_start, int vehicle,
760  std::vector<NodeInsertion>* sorted_insertions);
761 
762  std::vector<std::vector<StartEndValue>> start_end_distances_per_node_;
763 };
764 
768  public:
770  LocalSearchFilterManager* filter_manager);
772  bool BuildSolutionInternal() override;
773 
774  private:
775  class PartialRoutesAndLargeVehicleIndicesFirst {
776  public:
777  explicit PartialRoutesAndLargeVehicleIndicesFirst(
778  const CheapestAdditionFilteredHeuristic& builder)
779  : builder_(builder) {}
780  bool operator()(int vehicle1, int vehicle2) const;
781 
782  private:
783  const CheapestAdditionFilteredHeuristic& builder_;
784  };
786  template <typename Iterator>
787  std::vector<int64_t> GetPossibleNextsFromIterator(int64_t node,
788  Iterator start,
789  Iterator end) const {
790  const int size = model()->Size();
791  std::vector<int64_t> nexts;
792  for (Iterator it = start; it != end; ++it) {
793  const int64_t next = *it;
794  if (next != node && (next >= size || !Contains(next))) {
795  nexts.push_back(next);
796  }
797  }
798  return nexts;
799  }
801  virtual void SortSuccessors(int64_t node,
802  std::vector<int64_t>* successors) = 0;
803  virtual int64_t FindTopSuccessor(int64_t node,
804  const std::vector<int64_t>& successors) = 0;
805 };
806 
811  public:
814  RoutingModel* model, std::function<int64_t(int64_t, int64_t)> evaluator,
815  LocalSearchFilterManager* filter_manager);
817  std::string DebugString() const override {
818  return "EvaluatorCheapestAdditionFilteredHeuristic";
819  }
820 
821  private:
823  void SortSuccessors(int64_t node, std::vector<int64_t>* successors) override;
824  int64_t FindTopSuccessor(int64_t node,
825  const std::vector<int64_t>& successors) override;
826 
827  std::function<int64_t(int64_t, int64_t)> evaluator_;
828 };
829 
834  public:
838  LocalSearchFilterManager* filter_manager);
840  std::string DebugString() const override {
841  return "ComparatorCheapestAdditionFilteredHeuristic";
842  }
843 
844  private:
846  void SortSuccessors(int64_t node, std::vector<int64_t>* successors) override;
847  int64_t FindTopSuccessor(int64_t node,
848  const std::vector<int64_t>& successors) override;
849 
851 };
852 
862  public:
866  double neighbors_ratio = 1.0;
872  bool add_reverse_arcs = false;
875  double arc_coefficient = 1.0;
876  };
877 
879  LocalSearchFilterManager* filter_manager);
880  ~SavingsFilteredHeuristic() override;
881  bool BuildSolutionInternal() override;
882 
883  protected:
884  typedef std::pair</*saving*/ int64_t, /*saving index*/ int64_t> Saving;
885 
886  template <typename S>
887  class SavingsContainer;
888 
889  virtual double ExtraSavingsMemoryMultiplicativeFactor() const = 0;
890 
891  virtual void BuildRoutesFromSavings() = 0;
892 
894  int64_t GetVehicleTypeFromSaving(const Saving& saving) const {
895  return saving.second / size_squared_;
896  }
898  int64_t GetBeforeNodeFromSaving(const Saving& saving) const {
899  return (saving.second % size_squared_) / Size();
900  }
902  int64_t GetAfterNodeFromSaving(const Saving& saving) const {
903  return (saving.second % size_squared_) % Size();
904  }
906  int64_t GetSavingValue(const Saving& saving) const { return saving.first; }
907 
917  int StartNewRouteWithBestVehicleOfType(int type, int64_t before_node,
918  int64_t after_node);
919 
920  // clang-format off
921  std::unique_ptr<SavingsContainer<Saving> > savings_container_;
922  // clang-format on
923  std::unique_ptr<VehicleTypeCurator> vehicle_type_curator_;
924 
925  private:
930  // clang-format off
931  void AddSymmetricArcsToAdjacencyLists(
932  std::vector<std::vector<int64_t> >* adjacency_lists);
933  // clang-format on
934 
943  bool ComputeSavings();
945  Saving BuildSaving(int64_t saving, int vehicle_type, int before_node,
946  int after_node) const {
947  return std::make_pair(saving, vehicle_type * size_squared_ +
948  before_node * Size() + after_node);
949  }
950 
954  int64_t MaxNumNeighborsPerNode(int num_vehicle_types) const;
955 
956  const SavingsParameters savings_params_;
957  int64_t size_squared_;
958 
960 };
961 
963  public:
966  LocalSearchFilterManager* filter_manager)
967  : SavingsFilteredHeuristic(model, parameters, filter_manager) {}
969  std::string DebugString() const override {
970  return "SequentialSavingsFilteredHeuristic";
971  }
972 
973  private:
978  void BuildRoutesFromSavings() override;
979  double ExtraSavingsMemoryMultiplicativeFactor() const override { return 1.0; }
980 };
981 
983  public:
986  LocalSearchFilterManager* filter_manager)
987  : SavingsFilteredHeuristic(model, parameters, filter_manager) {}
989  std::string DebugString() const override {
990  return "ParallelSavingsFilteredHeuristic";
991  }
992 
993  private:
1004  void BuildRoutesFromSavings() override;
1005 
1006  double ExtraSavingsMemoryMultiplicativeFactor() const override { return 2.0; }
1007 
1012  void MergeRoutes(int first_vehicle, int second_vehicle, int64_t before_node,
1013  int64_t after_node);
1014 
1016  std::vector<int64_t> first_node_on_route_;
1017  std::vector<int64_t> last_node_on_route_;
1021  std::vector<int> vehicle_of_first_or_last_node_;
1022 };
1023 
1027 
1029  public:
1031  LocalSearchFilterManager* filter_manager,
1032  bool use_minimum_matching);
1034  bool BuildSolutionInternal() override;
1035  std::string DebugString() const override {
1036  return "ChristofidesFilteredHeuristic";
1037  }
1038 
1039  private:
1040  const bool use_minimum_matching_;
1041 };
1042 
1046  public:
1047  explicit SweepArranger(
1048  const std::vector<std::pair<int64_t, int64_t>>& points);
1049  virtual ~SweepArranger() {}
1050  void ArrangeIndices(std::vector<int64_t>* indices);
1051  void SetSectors(int sectors) { sectors_ = sectors; }
1052 
1053  private:
1054  std::vector<int> coordinates_;
1055  int sectors_;
1056 
1057  DISALLOW_COPY_AND_ASSIGN(SweepArranger);
1058 };
1059 #endif // SWIG
1060 
1061 // Returns a DecisionBuilder building a first solution based on the Sweep
1062 // heuristic. Mostly suitable when cost is proportional to distance.
1063 DecisionBuilder* MakeSweepDecisionBuilder(RoutingModel* model,
1064  bool check_assignment);
1065 
1066 // Returns a DecisionBuilder making all nodes unperformed.
1067 DecisionBuilder* MakeAllUnperformed(RoutingModel* model);
1068 
1069 } // namespace operations_research
1070 
1071 #endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_SEARCH_H_
bool BuildSolutionInternal() override
Virtual method to redefine how to build a solution.
int64_t GetInsertionCostForNodeAtPosition(int64_t node_to_insert, int64_t insert_after, int64_t insert_before, int vehicle) const
Returns the cost of inserting 'node_to_insert' between 'insert_after' and 'insert_before' on the 'veh...
std::function< bool(int64_t, int64_t, int64_t)> VariableValueComparator
int64_t Value(int64_t index) const
Returns the value of the variable of index 'index' in the last committed solution.
int64_t min
Definition: alldiff_cst.cc:139
CheapestAdditionFilteredHeuristic(RoutingModel *model, LocalSearchFilterManager *filter_manager)
bool BuildSolutionInternal() override
Virtual method to redefine how to build a solution.
Definition: routing.h:360
std::unique_ptr< VehicleTypeCurator > vehicle_type_curator_
std::unique_ptr< SavingsContainer< Saving > > savings_container_
IntVarElement * FastAdd(IntVar *const var)
Adds without checking if variable has been previously added.
int64_t GetUnperformedValue(int64_t node_to_insert) const
Returns the cost of unperforming node 'node_to_insert'.
IntVar * VehicleVar(int64_t index) const
Returns the vehicle variable of the node corresponding to index.
Definition: routing.h:1369
bool Contains(int64_t index) const
Returns true if the variable of index 'index' is in the current solution.
void SetValue(const IntVar *const var, int64_t value)
int Size() const
Returns the number of variables the decision builder is trying to instantiate.
Filter-based heuristic dedicated to routing.
void ReinjectVehicleOfClass(int vehicle, int vehicle_class, int64_t fixed_cost)
double farthest_seeds_ratio
The ratio of routes on which to insert farthest nodes as seeds before starting the cheapest insertion...
bool add_reverse_arcs
If add_reverse_arcs is true, the neighborhood relationships are considered symmetrically.
int64_t GetVehicleTypeFromSaving(const Saving &saving) const
Returns the cost class from a saving.
virtual double ExtraSavingsMemoryMultiplicativeFactor() const =0
IntVarFilteredHeuristic(Solver *solver, const std::vector< IntVar * > &vars, LocalSearchFilterManager *filter_manager)
IntVar * Var(int64_t index) const
Returns the variable of index 'index'.
GRBmodel * model
double neighbors_ratio
If neighbors_ratio < 1 then for each node only this ratio of its neighbors leading to the smallest ar...
CheapestInsertionFilteredHeuristic(RoutingModel *model, std::function< int64_t(int64_t, int64_t, int64_t)> evaluator, std::function< int64_t(int64_t)> penalty_evaluator, LocalSearchFilterManager *filter_manager)
Takes ownership of evaluator.
int64_t End(int vehicle) const
Returns the variable index of the ending node of a vehicle route.
Definition: routing.h:1322
int64_t number_of_decisions() const
Returns statistics on search, number of decisions sent to filters, number of decisions rejected by fi...
int64_t GetBeforeNodeFromSaving(const Saving &saving) const
Returns the "before node" from a saving.
void Reset(const std::function< bool(int)> &store_vehicle)
Resets the vehicles stored, storing only vehicles from the vehicle_type_container_ for which store_ve...
const E & Element(const V *const var) const
static int64_t FastInt64Round(double x)
Definition: mathutil.h:138
Decision * Next(Solver *solver) override
This is the main method of the decision builder class.
A DecisionBuilder is responsible for creating the search tree.
EvaluatorCheapestAdditionFilteredHeuristic(RoutingModel *model, std::function< int64_t(int64_t, int64_t)> evaluator, LocalSearchFilterManager *filter_manager)
Takes ownership of evaluator.
const Assignment * BuildSolutionFromRoutes(const std::function< int64_t(int64_t)> &next_accessor)
Builds a solution starting from the routes formed by the next accessor.
bool StopSearch() override
Returns true if the search must be stopped.
ComparatorCheapestAdditionFilteredHeuristic(RoutingModel *model, Solver::VariableValueComparator comparator, LocalSearchFilterManager *filter_manager)
Takes ownership of evaluator.
Filter-base decision builder which builds a solution by inserting nodes at their cheapest position.
Generic filter-based heuristic applied to IntVars.
bool HasCompatibleVehicleOfType(int type, const std::function< bool(int)> &vehicle_is_compatible) const
Searches a compatible vehicle of the given type; returns false if none was found.
A CheapestAdditionFilteredHeuristic where the notion of 'cheapest arc' comes from an arc evaluator.
int64_t max
Definition: alldiff_cst.cc:140
Block * next
void ResetSolution()
Resets the data members for a new solution.
Filter manager: when a move is made, filters are executed to decide whether the solution is feasible ...
void MakeUnassignedNodesUnperformed()
Make all unassigned nodes unperformed.
RoutingFilteredHeuristic(RoutingModel *model, LocalSearchFilterManager *filter_manager)
double arc_coefficient
arc_coefficient is a strictly positive parameter indicating the coefficient of the arc being consider...
bool BuildSolutionInternal() override
Virtual method to redefine how to build a solution.
bool BuildSolutionInternal() override
Virtual method to redefine how to build a solution.
A CheapestAdditionFilteredHeuristic where the notion of 'cheapest arc' comes from an arc comparator.
virtual bool BuildSolutionInternal()=0
Virtual method to redefine how to build a solution.
double max_memory_usage_bytes
The number of neighbors considered for each node is also adapted so that the stored Savings don't use...
void InitializePriorityQueue(std::vector< std::vector< StartEndValue > > *start_end_distances_per_node, Queue *priority_queue)
Initializes the priority_queue by inserting the best entry corresponding to each node,...
virtual bool StopSearch()
Returns true if the search must be stopped.
double neighbors_ratio
If neighbors_ratio < 1 then for each node only this ratio of its neighbors leading to the smallest ar...
void InsertBetween(int64_t node, int64_t predecessor, int64_t successor)
Inserts 'node' just after 'predecessor', and just before 'successor', resulting in the following subs...
Filter-based decision builder which builds a solution by using Clarke & Wright's Savings heuristic.
void AppendInsertionPositionsAfter(int64_t node_to_insert, int64_t start, int64_t next_after_start, int vehicle, std::vector< NodeInsertion > *node_insertions)
Helper method to the ComputeEvaluatorSortedPositions* methods.
int index
Definition: pack.cc:509
void Update(const std::function< bool(int)> &remove_vehicle)
Goes through all the currently stored vehicles and removes vehicles for which remove_vehicle() return...
bool BuildSolutionInternal() override
Virtual method to redefine how to build a solution.
void MakePartiallyPerformedPairsUnperformed()
Make all partially performed pickup and delivery pairs unperformed.
An Assignment is a variable -> domains mapping, used to report solutions to the user.
virtual uint64_t Size() const =0
This method returns the number of values in the domain of the variable.
The class IntVar is a subset of IntExpr.
void SetValue(int64_t index, int64_t value)
Modifies the current solution by setting the variable of index 'index' to value 'value'.
Filter-based decision builder which builds a solution by inserting nodes at their cheapest position o...
void SynchronizeFilters()
Synchronizes filters with an assignment (the current solution).
LocalCheapestInsertionFilteredHeuristic(RoutingModel *model, std::function< int64_t(int64_t, int64_t, int64_t)> evaluator, LocalSearchFilterManager *filter_manager)
Takes ownership of evaluator.
Decision builder building a solution using heuristics with local search filters to evaluate its feasi...
#define DCHECK(condition)
Definition: base/logging.h:889
GlobalCheapestInsertionFilteredHeuristic(RoutingModel *model, std::function< int64_t(int64_t, int64_t, int64_t)> evaluator, std::function< int64_t(int64_t)> penalty_evaluator, LocalSearchFilterManager *filter_manager, GlobalCheapestInsertionParameters parameters)
Takes ownership of evaluators.
int64_t GetSavingValue(const Saving &saving) const
Returns the saving value from a saving.
ChristofidesFilteredHeuristic(RoutingModel *model, LocalSearchFilterManager *filter_manager, bool use_minimum_matching)
int vehicles() const
Returns the number of vehicle routes in the model.
Definition: routing.h:1516
RoutingIndexPair IndexPair
Definition: routing.h:244
std::vector< std::vector< StartEndValue > > ComputeStartEndDistanceForVehicles(const std::vector< int > &vehicles)
Computes and returns the distance of each uninserted node to every vehicle in "vehicles" as a std::ve...
void ArrangeIndices(std::vector< int64_t > *indices)
SavingsFilteredHeuristic(RoutingModel *model, SavingsParameters parameters, LocalSearchFilterManager *filter_manager)
Filtered-base decision builder based on the addition heuristic, extending a path from its start node ...
bool Commit()
Commits the modifications to the current solution if these modifications are "filter-feasible",...
A Decision represents a choice point in the search tree.
int StartNewRouteWithBestVehicleOfType(int type, int64_t before_node, int64_t after_node)
Finds the best available vehicle of type "type" to start a new route to serve the arc before_node-->a...
virtual void SetVehicleIndex(int64_t node, int vehicle)
bool add_unperformed_entries
If true, entries are created for making the nodes/pairs unperformed, and when the cost of making a no...
Struct used to sort and store vehicles by their type.
Definition: routing.h:359
Collection of objects used to extend the Constraint Solver library.
std::pair< int, int > GetCompatibleVehicleOfType(int type, std::function< bool(int)> vehicle_is_compatible, std::function< bool(int)> stop_and_return_vehicle)
Searches for the best compatible vehicle of the given type, i.e.
const std::vector< T * > * Raw() const
SatParameters parameters
SweepArranger(const std::vector< std::pair< int64_t, int64_t >> &points)
DecisionBuilder * MakeAllUnperformed(RoutingModel *model)
int vehicle_class
int GetLowestFixedCostVehicleOfType(int type) const
int64_t Size() const
Returns the number of next variables in the model.
Definition: routing.h:1518
bool is_sequential
Whether the routes are constructed sequentially or in parallel.
void MakeDisjunctionNodesUnperformed(int64_t node)
Make nodes in the same disjunction as 'node' unperformed.
SequentialSavingsFilteredHeuristic(RoutingModel *model, SavingsParameters parameters, LocalSearchFilterManager *filter_manager)
int GetEndChainStart(int vehicle) const
Returns the start of the end chain of vehicle,.
ParallelSavingsFilteredHeuristic(RoutingModel *model, SavingsParameters parameters, LocalSearchFilterManager *filter_manager)
virtual bool InitializeSolution()
Virtual method to initialize the solution.
std::function< int64_t(int64_t, int64_t, int64_t)> evaluator_
int nodes
bool use_neighbors_ratio_for_initialization
If true, only closest neighbors (see neighbors_ratio and min_neighbors) are considered as insertion p...
bool CheckLimit()
Returns true if the search limit has been crossed.
Definition: routing.h:1501
FirstSolutionStrategy::Value AutomaticFirstSolutionStrategy(bool has_pickup_deliveries, bool has_node_precedences, bool has_single_vehicle_node)
Returns the best value for the automatic first solution strategy, based on the given model parameters...
int GetStartChainEnd(int vehicle) const
Returns the end of the start chain of vehicle,.
IntVarFilteredDecisionBuilder(std::unique_ptr< IntVarFilteredHeuristic > heuristic)
const IntContainer & IntVarContainer() const
Assignment *const BuildSolution()
Builds a solution.
int64_t value
Class to arrange indices by by their distance and their angles from the depot.
VehicleTypeCurator(const RoutingModel::VehicleTypeContainer &vehicle_type_container)
#define DCHECK_LT(val1, val2)
Definition: base/logging.h:893
int64_t GetAfterNodeFromSaving(const Saving &saving) const
Returns the "after node" from a saving.
DecisionBuilder * MakeSweepDecisionBuilder(RoutingModel *model, bool check_assignment)
int64_t number_of_decisions() const
Returns statistics from its underlying heuristic.