OR-Tools  9.3
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"
33#include "ortools/base/macros.h"
39#include "ortools/util/bitset.h"
40
41namespace operations_research {
42
43class IntVarFilteredHeuristic;
44#ifndef SWIG
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
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
122AutomaticFirstSolutionStrategy(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 const std::vector<IntVar*>& secondary_vars,
166 LocalSearchFilterManager* filter_manager);
167
169
172 Assignment* const BuildSolution();
173
176 int64_t number_of_decisions() const { return number_of_decisions_; }
177 int64_t number_of_rejects() const { return number_of_rejects_; }
178
179 virtual std::string DebugString() const { return "IntVarFilteredHeuristic"; }
180
181 protected:
183 void ResetSolution();
185 virtual bool InitializeSolution() { return true; }
187 virtual bool BuildSolutionInternal() = 0;
195 std::optional<int64_t> Evaluate(bool commit);
197 virtual bool StopSearch() { return false; }
200 void SetValue(int64_t index, int64_t value) {
201 if (!is_in_delta_[index]) {
202 delta_->FastAdd(vars_[index])->SetValue(value);
203 delta_indices_.push_back(index);
204 is_in_delta_[index] = true;
205 } else {
206 delta_->SetValue(vars_[index], value);
207 }
208 }
211 int64_t Value(int64_t index) const {
213 }
215 bool Contains(int64_t index) const {
216 return assignment_->IntVarContainer().Element(index).Var() != nullptr;
217 }
220 int Size() const { return vars_.size(); }
222 IntVar* Var(int64_t index) const { return vars_[index]; }
224 int64_t SecondaryVarIndex(int64_t index) const {
226 return index + base_vars_size_;
227 }
229 bool HasSecondaryVars() const { return base_vars_size_ != vars_.size(); }
231 bool IsSecondaryVar(int64_t index) const { return index >= base_vars_size_; }
233 void SynchronizeFilters();
234
236
237 private:
240 bool FilterAccept();
241
242 Solver* solver_;
243 std::vector<IntVar*> vars_;
244 const int base_vars_size_;
245 Assignment* const delta_;
246 std::vector<int> delta_indices_;
247 std::vector<bool> is_in_delta_;
248 Assignment* const empty_;
249 LocalSearchFilterManager* filter_manager_;
250 int64_t objective_upper_bound_;
252 int64_t number_of_decisions_;
253 int64_t number_of_rejects_;
254};
255
258 public:
260 LocalSearchFilterManager* filter_manager,
261 bool omit_secondary_vars = true);
265 const std::function<int64_t(int64_t)>& next_accessor);
266 RoutingModel* model() const { return model_; }
268 int GetStartChainEnd(int vehicle) const { return start_chain_ends_[vehicle]; }
270 int GetEndChainStart(int vehicle) const { return end_chain_starts_[vehicle]; }
273 void MakeDisjunctionNodesUnperformed(int64_t node);
281
282 protected:
283 bool StopSearch() override { return model_->CheckLimit(); }
284 virtual void SetVehicleIndex(int64_t node, int vehicle) {}
285 virtual void ResetVehicleIndices() {}
286 bool VehicleIsEmpty(int vehicle) const {
287 return Value(model()->Start(vehicle)) == model()->End(vehicle);
288 }
289
290 private:
292 bool InitializeSolution() override;
293
294 RoutingModel* const model_;
295 std::vector<int64_t> start_chain_ends_;
296 std::vector<int64_t> end_chain_starts_;
297};
298
300 public:
304 std::function<int64_t(int64_t, int64_t, int64_t)> evaluator,
305 std::function<int64_t(int64_t)> penalty_evaluator,
306 LocalSearchFilterManager* filter_manager);
308
309 protected:
313 int64_t value;
314
315 bool operator<(const NodeInsertion& other) const {
316 return std::tie(value, insert_after, vehicle) <
317 std::tie(other.value, other.insert_after, other.vehicle);
318 }
319 };
322 int64_t distance;
324
325 bool operator<(const StartEndValue& other) const {
326 return std::tie(num_allowed_vehicles, distance, vehicle) <
327 std::tie(other.num_allowed_vehicles, other.distance,
328 other.vehicle);
329 }
330 };
331 typedef std::pair<StartEndValue, /*seed_node*/ int> Seed;
332
338 // clang-format off
339 std::vector<std::vector<StartEndValue> >
340 ComputeStartEndDistanceForVehicles(const std::vector<int>& vehicles);
341
346 template <class Queue>
348 std::vector<std::vector<StartEndValue> >* start_end_distances_per_node,
349 Queue* priority_queue);
350 // clang-format on
351
357 void InsertBetween(int64_t node, int64_t predecessor, int64_t successor,
358 int vehicle = -1);
364 int64_t node_to_insert, int64_t start, int64_t next_after_start,
365 int vehicle, std::vector<NodeInsertion>* node_insertions);
370 // TODO(user): Replace 'insert_before' and 'insert_after' by 'predecessor'
371 // and 'successor' in the code.
372 int64_t GetInsertionCostForNodeAtPosition(int64_t node_to_insert,
373 int64_t insert_after,
374 int64_t insert_before,
375 int vehicle) const;
378 int64_t GetUnperformedValue(int64_t node_to_insert) const;
379
380 std::function<int64_t(int64_t, int64_t, int64_t)> evaluator_;
381 std::function<int64_t(int64_t)> penalty_evaluator_;
382};
383
393 public:
416 };
417
421 std::function<int64_t(int64_t, int64_t, int64_t)> evaluator,
422 std::function<int64_t(int64_t)> penalty_evaluator,
423 LocalSearchFilterManager* filter_manager,
426 bool BuildSolutionInternal() override;
427 std::string DebugString() const override {
428 return "GlobalCheapestInsertionFilteredHeuristic";
429 }
430
431 private:
432 class NodeEntry;
433 class PairEntry;
434
435 typedef absl::flat_hash_set<PairEntry*> PairEntries;
436 typedef absl::flat_hash_set<NodeEntry*> NodeEntries;
437
444 bool InsertPairsAndNodesByRequirementTopologicalOrder();
445
452 bool InsertPairs(
453 const std::map<int64_t, std::vector<int>>& pair_indices_by_bucket);
454
458 bool UseEmptyVehicleTypeCuratorForVehicle(int vehicle,
459 bool all_vehicles = true) {
460 return vehicle >= 0 && VehicleIsEmpty(vehicle) && all_vehicles;
461 }
462
469 bool InsertPairEntryUsingEmptyVehicleTypeCurator(
470 const std::vector<int>& pair_indices, PairEntry* const pair_entry,
472 std::vector<PairEntries>* pickup_to_entries,
473 std::vector<PairEntries>* delivery_to_entries);
474
482 bool InsertNodesOnRoutes(
483 const std::map<int64_t, std::vector<int>>& nodes_by_bucket,
484 const absl::flat_hash_set<int>& vehicles);
485
493 bool InsertNodeEntryUsingEmptyVehicleTypeCurator(
494 const std::vector<int>& nodes, bool all_vehicles,
495 NodeEntry* const node_entry,
497 std::vector<NodeEntries>* position_to_node_entries);
498
504 bool SequentialInsertNodes(
505 const std::map<int64_t, std::vector<int>>& nodes_by_bucket);
506
510 void DetectUsedVehicles(std::vector<bool>* is_vehicle_used,
511 std::vector<int>* unused_vehicles,
512 absl::flat_hash_set<int>* used_vehicles);
513
517 void InsertFarthestNodesAsSeeds();
518
527 template <class Queue>
528 int InsertSeedNode(
529 std::vector<std::vector<StartEndValue>>* start_end_distances_per_node,
530 Queue* priority_queue, std::vector<bool>* is_vehicle_used);
531 // clang-format on
532
535 bool InitializePairPositions(
536 const std::vector<int>& pair_indices,
538 std::vector<PairEntries>* pickup_to_entries,
539 std::vector<PairEntries>* delivery_to_entries);
545 void InitializeInsertionEntriesPerformingPair(
546 int64_t pickup, int64_t delivery,
548 std::vector<PairEntries>* pickup_to_entries,
549 std::vector<PairEntries>* delivery_to_entries);
553 bool UpdateAfterPairInsertion(
554 const std::vector<int>& pair_indices, int vehicle, int64_t pickup,
555 int64_t pickup_position, int64_t delivery, int64_t delivery_position,
557 std::vector<PairEntries>* pickup_to_entries,
558 std::vector<PairEntries>* delivery_to_entries);
561 bool UpdatePairPositions(const std::vector<int>& pair_indices, int vehicle,
562 int64_t insert_after,
564 std::vector<PairEntries>* pickup_to_entries,
565 std::vector<PairEntries>* delivery_to_entries) {
566 return UpdatePickupPositions(pair_indices, vehicle, insert_after,
567 priority_queue, pickup_to_entries,
568 delivery_to_entries) &&
569 UpdateDeliveryPositions(pair_indices, vehicle, insert_after,
570 priority_queue, pickup_to_entries,
571 delivery_to_entries);
572 }
575 bool UpdatePickupPositions(const std::vector<int>& pair_indices, int vehicle,
576 int64_t pickup_insert_after,
578 std::vector<PairEntries>* pickup_to_entries,
579 std::vector<PairEntries>* delivery_to_entries);
582 bool UpdateDeliveryPositions(
583 const std::vector<int>& pair_indices, int vehicle,
584 int64_t delivery_insert_after,
586 std::vector<PairEntries>* pickup_to_entries,
587 std::vector<PairEntries>* delivery_to_entries);
590 void DeletePairEntry(PairEntry* entry,
592 std::vector<PairEntries>* pickup_to_entries,
593 std::vector<PairEntries>* delivery_to_entries);
598 void AddPairEntry(int64_t pickup, int64_t pickup_insert_after,
599 int64_t delivery, int64_t delivery_insert_after,
600 int vehicle,
602 std::vector<PairEntries>* pickup_entries,
603 std::vector<PairEntries>* delivery_entries) const;
606 void UpdatePairEntry(
607 PairEntry* const pair_entry,
608 AdjustablePriorityQueue<PairEntry>* priority_queue) const;
612 int64_t GetInsertionValueForPairAtPositions(int64_t pickup,
613 int64_t pickup_insert_after,
614 int64_t delivery,
615 int64_t delivery_insert_after,
616 int vehicle) const;
617
620 bool InitializePositions(const std::vector<int>& nodes,
621 const absl::flat_hash_set<int>& vehicles,
623 std::vector<NodeEntries>* position_to_node_entries);
629 void InitializeInsertionEntriesPerformingNode(
630 int64_t node, const absl::flat_hash_set<int>& vehicles,
632 std::vector<NodeEntries>* position_to_node_entries);
635 bool UpdatePositions(const std::vector<int>& nodes, int vehicle,
636 int64_t insert_after, bool all_vehicles,
638 std::vector<NodeEntries>* node_entries);
641 void DeleteNodeEntry(NodeEntry* entry,
643 std::vector<NodeEntries>* node_entries);
644
648 void AddNodeEntry(int64_t node, int64_t insert_after, int vehicle,
649 bool all_vehicles,
651 std::vector<NodeEntries>* node_entries) const;
654 void UpdateNodeEntry(
655 NodeEntry* const node_entry,
656 AdjustablePriorityQueue<NodeEntry>* priority_queue) const;
657
660 void ComputeNeighborhoods();
661
664 bool IsNeighborForCostClass(int cost_class, int64_t node_index,
665 int64_t neighbor_index) const;
666
668 const std::vector<int64_t>& GetNeighborsOfNodeForCostClass(
669 int cost_class, int64_t node_index) const {
670 return gci_params_.neighbors_ratio == 1
671 ? all_nodes_
672 : node_index_to_neighbors_by_cost_class_[node_index][cost_class]
673 ->PositionsSetAtLeastOnce();
674 }
675
676 int64_t NumNonStartEndNodes() const {
677 return model()->Size() - model()->vehicles();
678 }
679
680 int64_t NumNeighbors() const {
681 return std::max(gci_params_.min_neighbors,
683 NumNonStartEndNodes()));
684 }
685
686 void ResetVehicleIndices() override {
687 node_index_to_vehicle_.assign(node_index_to_vehicle_.size(), -1);
688 }
689
690 void SetVehicleIndex(int64_t node, int vehicle) override {
691 DCHECK_LT(node, node_index_to_vehicle_.size());
692 node_index_to_vehicle_[node] = vehicle;
693 }
694
697 bool CheckVehicleIndices() const;
698
700 int64_t GetBucketOfNode(int node) const {
701 return model()->VehicleVar(node)->Size();
702 }
703
705 int64_t GetBucketOfPair(const RoutingModel::IndexPair& index_pair) const {
706 int64_t max_pickup_bucket = 0;
707 for (int64_t pickup : index_pair.first) {
708 max_pickup_bucket = std::max(max_pickup_bucket, GetBucketOfNode(pickup));
709 }
710 int64_t max_delivery_bucket = 0;
711 for (int64_t delivery : index_pair.second) {
712 max_delivery_bucket =
713 std::max(max_delivery_bucket, GetBucketOfNode(delivery));
714 }
715 return std::min(max_pickup_bucket, max_delivery_bucket);
716 }
717
720 template <class T>
721 bool StopSearchAndCleanup(AdjustablePriorityQueue<T>* priority_queue) {
722 if (!StopSearch()) return false;
723 for (T* const entry : *priority_queue->Raw()) {
724 delete entry;
725 }
726 priority_queue->Clear();
727 return true;
728 }
729
730 GlobalCheapestInsertionParameters gci_params_;
732 std::vector<int> node_index_to_vehicle_;
733
734 // clang-format off
735 std::vector<std::vector<std::unique_ptr<SparseBitset<int64_t> > > >
736 node_index_to_neighbors_by_cost_class_;
737 // clang-format on
738
739 std::unique_ptr<VehicleTypeCurator> empty_vehicle_type_curator_;
740
744 std::vector<int64_t> all_nodes_;
745};
746
754 public:
758 std::function<int64_t(int64_t, int64_t, int64_t)> evaluator,
759 bool evaluate_pickup_delivery_costs_independently,
760 LocalSearchFilterManager* filter_manager);
762 bool BuildSolutionInternal() override;
763 std::string DebugString() const override {
764 return "LocalCheapestInsertionFilteredHeuristic";
765 }
766
767 private:
768 struct PickupDeliveryInsertion {
769 int64_t insert_pickup_after;
770 int64_t insert_delivery_after;
771 int64_t value;
772 int vehicle;
773
774 bool operator<(const PickupDeliveryInsertion& other) const {
775 return std::tie(value, insert_pickup_after, insert_delivery_after,
776 vehicle) <
777 std::tie(other.value, other.insert_pickup_after,
778 other.insert_delivery_after, other.vehicle);
779 }
780 };
781
785 std::vector<NodeInsertion> ComputeEvaluatorSortedPositions(int64_t node);
790 std::vector<NodeInsertion> ComputeEvaluatorSortedPositionsOnRouteAfter(
791 int64_t node, int64_t start, int64_t next_after_start, int vehicle);
792
796 std::vector<PickupDeliveryInsertion> ComputeEvaluatorSortedPairPositions(
797 int64_t pickup, int64_t delivery);
798
799 std::vector<std::vector<StartEndValue>> start_end_distances_per_node_;
800 const bool evaluate_pickup_delivery_costs_independently_;
801};
802
806 public:
808 LocalSearchFilterManager* filter_manager);
810 bool BuildSolutionInternal() override;
811
812 private:
813 class PartialRoutesAndLargeVehicleIndicesFirst {
814 public:
815 explicit PartialRoutesAndLargeVehicleIndicesFirst(
817 : builder_(builder) {}
818 bool operator()(int vehicle1, int vehicle2) const;
819
820 private:
821 const CheapestAdditionFilteredHeuristic& builder_;
822 };
824 template <typename Iterator>
825 std::vector<int64_t> GetPossibleNextsFromIterator(int64_t node,
826 Iterator start,
827 Iterator end) const {
828 const int size = model()->Size();
829 std::vector<int64_t> nexts;
830 for (Iterator it = start; it != end; ++it) {
831 const int64_t next = *it;
832 if (next != node && (next >= size || !Contains(next))) {
833 nexts.push_back(next);
834 }
835 }
836 return nexts;
837 }
839 virtual void SortSuccessors(int64_t node,
840 std::vector<int64_t>* successors) = 0;
841 virtual int64_t FindTopSuccessor(int64_t node,
842 const std::vector<int64_t>& successors) = 0;
843};
844
849 public:
852 RoutingModel* model, std::function<int64_t(int64_t, int64_t)> evaluator,
853 LocalSearchFilterManager* filter_manager);
855 std::string DebugString() const override {
856 return "EvaluatorCheapestAdditionFilteredHeuristic";
857 }
858
859 private:
861 void SortSuccessors(int64_t node, std::vector<int64_t>* successors) override;
862 int64_t FindTopSuccessor(int64_t node,
863 const std::vector<int64_t>& successors) override;
864
865 std::function<int64_t(int64_t, int64_t)> evaluator_;
866};
867
872 public:
876 LocalSearchFilterManager* filter_manager);
878 std::string DebugString() const override {
879 return "ComparatorCheapestAdditionFilteredHeuristic";
880 }
881
882 private:
884 void SortSuccessors(int64_t node, std::vector<int64_t>* successors) override;
885 int64_t FindTopSuccessor(int64_t node,
886 const std::vector<int64_t>& successors) override;
887
889};
890
900 public:
904 double neighbors_ratio = 1.0;
910 bool add_reverse_arcs = false;
913 double arc_coefficient = 1.0;
914 };
915
917 LocalSearchFilterManager* filter_manager);
918 ~SavingsFilteredHeuristic() override;
919 bool BuildSolutionInternal() override;
920
921 protected:
922 typedef std::pair</*saving*/ int64_t, /*saving index*/ int64_t> Saving;
923
924 template <typename S>
925 class SavingsContainer;
926
927 virtual double ExtraSavingsMemoryMultiplicativeFactor() const = 0;
928
929 virtual void BuildRoutesFromSavings() = 0;
930
932 int64_t GetVehicleTypeFromSaving(const Saving& saving) const {
933 return saving.second / size_squared_;
934 }
936 int64_t GetBeforeNodeFromSaving(const Saving& saving) const {
937 return (saving.second % size_squared_) / Size();
938 }
940 int64_t GetAfterNodeFromSaving(const Saving& saving) const {
941 return (saving.second % size_squared_) % Size();
942 }
944 int64_t GetSavingValue(const Saving& saving) const { return saving.first; }
945
955 int StartNewRouteWithBestVehicleOfType(int type, int64_t before_node,
956 int64_t after_node);
957
958 // clang-format off
959 std::unique_ptr<SavingsContainer<Saving> > savings_container_;
960 // clang-format on
961 std::unique_ptr<VehicleTypeCurator> vehicle_type_curator_;
962
963 private:
968 // clang-format off
969 void AddSymmetricArcsToAdjacencyLists(
970 std::vector<std::vector<int64_t> >* adjacency_lists);
971 // clang-format on
972
981 bool ComputeSavings();
983 Saving BuildSaving(int64_t saving, int vehicle_type, int before_node,
984 int after_node) const {
985 return std::make_pair(saving, vehicle_type * size_squared_ +
986 before_node * Size() + after_node);
987 }
988
992 int64_t MaxNumNeighborsPerNode(int num_vehicle_types) const;
993
994 const SavingsParameters savings_params_;
995 int64_t size_squared_;
996
998};
999
1001 public:
1004 LocalSearchFilterManager* filter_manager)
1005 : SavingsFilteredHeuristic(model, parameters, filter_manager) {}
1007 std::string DebugString() const override {
1008 return "SequentialSavingsFilteredHeuristic";
1009 }
1010
1011 private:
1016 void BuildRoutesFromSavings() override;
1017 double ExtraSavingsMemoryMultiplicativeFactor() const override { return 1.0; }
1018};
1019
1021 public:
1024 LocalSearchFilterManager* filter_manager)
1025 : SavingsFilteredHeuristic(model, parameters, filter_manager) {}
1027 std::string DebugString() const override {
1028 return "ParallelSavingsFilteredHeuristic";
1029 }
1030
1031 private:
1042 void BuildRoutesFromSavings() override;
1043
1044 double ExtraSavingsMemoryMultiplicativeFactor() const override { return 2.0; }
1045
1050 void MergeRoutes(int first_vehicle, int second_vehicle, int64_t before_node,
1051 int64_t after_node);
1052
1054 std::vector<int64_t> first_node_on_route_;
1055 std::vector<int64_t> last_node_on_route_;
1059 std::vector<int> vehicle_of_first_or_last_node_;
1060};
1061
1065
1067 public:
1069 LocalSearchFilterManager* filter_manager,
1070 bool use_minimum_matching);
1072 bool BuildSolutionInternal() override;
1073 std::string DebugString() const override {
1074 return "ChristofidesFilteredHeuristic";
1075 }
1076
1077 private:
1078 const bool use_minimum_matching_;
1079};
1080
1084 public:
1085 explicit SweepArranger(
1086 const std::vector<std::pair<int64_t, int64_t>>& points);
1087 virtual ~SweepArranger() {}
1088 void ArrangeIndices(std::vector<int64_t>* indices);
1089 void SetSectors(int sectors) { sectors_ = sectors; }
1090
1091 private:
1092 std::vector<int> coordinates_;
1093 int sectors_;
1094
1095 DISALLOW_COPY_AND_ASSIGN(SweepArranger);
1096};
1097#endif // SWIG
1098
1099// Returns a DecisionBuilder building a first solution based on the Sweep
1100// heuristic. Mostly suitable when cost is proportional to distance.
1101DecisionBuilder* MakeSweepDecisionBuilder(RoutingModel* model,
1102 bool check_assignment);
1103
1104// Returns a DecisionBuilder making all nodes unperformed.
1105DecisionBuilder* MakeAllUnperformed(RoutingModel* model);
1106
1107} // namespace operations_research
1108
1109#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_SEARCH_H_
int64_t max
Definition: alldiff_cst.cc:140
int64_t min
Definition: alldiff_cst.cc:139
#define DCHECK_LT(val1, val2)
Definition: base/logging.h:894
#define DCHECK(condition)
Definition: base/logging.h:890
const std::vector< T * > * Raw() const
const E & Element(const V *const var) const
An Assignment is a variable -> domains mapping, used to report solutions to the user.
void SetValue(const IntVar *const var, int64_t value)
const IntContainer & IntVarContainer() const
IntVarElement * FastAdd(IntVar *const var)
Adds without checking if variable has been previously added.
Filtered-base decision builder based on the addition heuristic, extending a path from its start node ...
bool BuildSolutionInternal() override
Virtual method to redefine how to build a solution.
CheapestAdditionFilteredHeuristic(RoutingModel *model, LocalSearchFilterManager *filter_manager)
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...
std::function< int64_t(int64_t, int64_t, int64_t)> evaluator_
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,...
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...
int64_t GetUnperformedValue(int64_t node_to_insert) const
Returns the cost of unperforming node 'node_to_insert'.
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.
void InsertBetween(int64_t node, int64_t predecessor, int64_t successor, int vehicle=-1)
Inserts 'node' just after 'predecessor', and just before 'successor' on the route of 'vehicle',...
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.
bool BuildSolutionInternal() override
Virtual method to redefine how to build a solution.
ChristofidesFilteredHeuristic(RoutingModel *model, LocalSearchFilterManager *filter_manager, bool use_minimum_matching)
A CheapestAdditionFilteredHeuristic where the notion of 'cheapest arc' comes from an arc comparator.
ComparatorCheapestAdditionFilteredHeuristic(RoutingModel *model, Solver::VariableValueComparator comparator, LocalSearchFilterManager *filter_manager)
Takes ownership of evaluator.
A DecisionBuilder is responsible for creating the search tree.
A Decision represents a choice point in the search tree.
A CheapestAdditionFilteredHeuristic where the notion of 'cheapest arc' comes from an arc evaluator.
EvaluatorCheapestAdditionFilteredHeuristic(RoutingModel *model, std::function< int64_t(int64_t, int64_t)> evaluator, LocalSearchFilterManager *filter_manager)
Takes ownership of evaluator.
Filter-based decision builder which builds a solution by inserting nodes at their cheapest position o...
bool BuildSolutionInternal() override
Virtual method to redefine how to build a solution.
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.
Decision builder building a solution using heuristics with local search filters to evaluate its feasi...
Decision * Next(Solver *solver) override
This is the main method of the decision builder class.
int64_t number_of_decisions() const
Returns statistics from its underlying heuristic.
IntVarFilteredDecisionBuilder(std::unique_ptr< IntVarFilteredHeuristic > heuristic)
Generic filter-based heuristic applied to IntVars.
void SetValue(int64_t index, int64_t value)
Modifies the current solution by setting the variable of index 'index' to value 'value'.
virtual bool BuildSolutionInternal()=0
Virtual method to redefine how to build a solution.
int64_t SecondaryVarIndex(int64_t index) const
Returns the index of a secondary var.
int Size() const
Returns the number of variables the decision builder is trying to instantiate.
bool Contains(int64_t index) const
Returns true if the variable of index 'index' is in the current solution.
virtual bool StopSearch()
Returns true if the search must be stopped.
void ResetSolution()
Resets the data members for a new solution.
void SynchronizeFilters()
Synchronizes filters with an assignment (the current solution).
bool HasSecondaryVars() const
Returns true if there are secondary variables.
virtual bool InitializeSolution()
Virtual method to initialize the solution.
int64_t number_of_decisions() const
Returns statistics on search, number of decisions sent to filters, number of decisions rejected by fi...
IntVar * Var(int64_t index) const
Returns the variable of index 'index'.
int64_t Value(int64_t index) const
Returns the value of the variable of index 'index' in the last committed solution.
bool IsSecondaryVar(int64_t index) const
Returns true if 'index' is a secondary variable index.
std::optional< int64_t > Evaluate(bool commit)
Evaluates the modifications to the current solution.
Assignment *const BuildSolution()
Builds a solution.
IntVarFilteredHeuristic(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, LocalSearchFilterManager *filter_manager)
The class IntVar is a subset of IntExpr.
virtual uint64_t Size() const =0
This method returns the number of values in the domain of the variable.
Filter-base decision builder which builds a solution by inserting nodes at their cheapest position.
LocalCheapestInsertionFilteredHeuristic(RoutingModel *model, std::function< int64_t(int64_t, int64_t, int64_t)> evaluator, bool evaluate_pickup_delivery_costs_independently, LocalSearchFilterManager *filter_manager)
Takes ownership of evaluator.
bool BuildSolutionInternal() override
Virtual method to redefine how to build a solution.
Filter manager: when a move is made, filters are executed to decide whether the solution is feasible ...
static int64_t FastInt64Round(double x)
Definition: mathutil.h:138
ParallelSavingsFilteredHeuristic(RoutingModel *model, SavingsParameters parameters, LocalSearchFilterManager *filter_manager)
Filter-based heuristic dedicated to routing.
int GetStartChainEnd(int vehicle) const
Returns the end of the start chain of vehicle,.
virtual void SetVehicleIndex(int64_t node, int vehicle)
int GetEndChainStart(int vehicle) const
Returns the start of the end chain of vehicle,.
RoutingFilteredHeuristic(RoutingModel *model, LocalSearchFilterManager *filter_manager, bool omit_secondary_vars=true)
void MakeDisjunctionNodesUnperformed(int64_t node)
Make nodes in the same disjunction as 'node' unperformed.
bool StopSearch() override
Returns true if the search must be stopped.
void MakeUnassignedNodesUnperformed()
Make all unassigned nodes unperformed.
void MakePartiallyPerformedPairsUnperformed()
Make all partially performed pickup and delivery pairs unperformed.
const Assignment * BuildSolutionFromRoutes(const std::function< int64_t(int64_t)> &next_accessor)
Builds a solution starting from the routes formed by the next accessor.
RoutingIndexPair IndexPair
Definition: routing.h:246
bool CheckLimit()
Returns true if the search limit has been crossed.
Definition: routing.h:1514
IntVar * VehicleVar(int64_t index) const
Returns the vehicle variable of the node corresponding to index.
Definition: routing.h:1382
int64_t Size() const
Returns the number of next variables in the model.
Definition: routing.h:1531
int vehicles() const
Returns the number of vehicle routes in the model.
Definition: routing.h:1529
int64_t End(int vehicle) const
Returns the variable index of the ending node of a vehicle route.
Definition: routing.h:1335
Filter-based decision builder which builds a solution by using Clarke & Wright's Savings heuristic.
SavingsFilteredHeuristic(RoutingModel *model, SavingsParameters parameters, LocalSearchFilterManager *filter_manager)
int64_t GetVehicleTypeFromSaving(const Saving &saving) const
Returns the cost class from a saving.
std::unique_ptr< VehicleTypeCurator > vehicle_type_curator_
bool BuildSolutionInternal() override
Virtual method to redefine how to build a solution.
int64_t GetAfterNodeFromSaving(const Saving &saving) const
Returns the "after node" from a saving.
int64_t GetSavingValue(const Saving &saving) const
Returns the saving value from a saving.
std::unique_ptr< SavingsContainer< Saving > > savings_container_
virtual double ExtraSavingsMemoryMultiplicativeFactor() const =0
int64_t GetBeforeNodeFromSaving(const Saving &saving) const
Returns the "before node" from a saving.
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...
SequentialSavingsFilteredHeuristic(RoutingModel *model, SavingsParameters parameters, LocalSearchFilterManager *filter_manager)
std::function< bool(int64_t, int64_t, int64_t)> VariableValueComparator
Class to arrange indices by their distance and their angle from the depot.
SweepArranger(const std::vector< std::pair< int64_t, int64_t > > &points)
void ArrangeIndices(std::vector< int64_t > *indices)
Helper class that manages vehicles.
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 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.
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.
VehicleTypeCurator(const RoutingModel::VehicleTypeContainer &vehicle_type_container)
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...
void ReinjectVehicleOfClass(int vehicle, int vehicle_class, int64_t fixed_cost)
int GetLowestFixedCostVehicleOfType(int type) const
Block * next
SatParameters parameters
int64_t value
GRBmodel * model
int index
std::function< int64_t(const Model &)> Value(IntegerVariable v)
Definition: integer.h:1683
Collection of objects used to extend the Constraint Solver library.
DecisionBuilder * MakeAllUnperformed(RoutingModel *model)
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...
DecisionBuilder * MakeSweepDecisionBuilder(RoutingModel *model, bool check_assignment)
int vehicle_class
int nodes
std::optional< int64_t > end
int64_t start
double neighbors_ratio
If neighbors_ratio < 1 then for each node only this ratio of its neighbors leading to the smallest ar...
bool is_sequential
Whether the routes are constructed sequentially or in parallel.
double farthest_seeds_ratio
The ratio of routes on which to insert farthest nodes as seeds before starting the cheapest insertion...
bool use_neighbors_ratio_for_initialization
If true, only closest neighbors (see neighbors_ratio and min_neighbors) are considered as insertion p...
bool add_unperformed_entries
If true, entries are created for making the nodes/pairs unperformed, and when the cost of making a no...
Definition: routing.h:362
Struct used to sort and store vehicles by their type.
Definition: routing.h:361
double neighbors_ratio
If neighbors_ratio < 1 then for each node only this ratio of its neighbors leading to the smallest ar...
double arc_coefficient
arc_coefficient is a strictly positive parameter indicating the coefficient of the arc being consider...
double max_memory_usage_bytes
The number of neighbors considered for each node is also adapted so that the stored Savings don't use...
bool add_reverse_arcs
If add_reverse_arcs is true, the neighborhood relationships are considered symmetrically.