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"
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 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:
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 };
305 int64_t distance;
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:
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,
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,
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,
519 std::vector<PairEntries>* pickup_to_entries,
520 std::vector<PairEntries>* delivery_to_entries);
526 void InitializeInsertionEntriesPerformingPair(
527 int64_t pickup, int64_t delivery,
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,
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,
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,
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,
567 std::vector<PairEntries>* pickup_to_entries,
568 std::vector<PairEntries>* delivery_to_entries);
571 void DeletePairEntry(PairEntry* entry,
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,
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,
604 std::vector<NodeEntries>* position_to_node_entries);
610 void InitializeInsertionEntriesPerformingNode(
611 int64_t node, const absl::flat_hash_set<int>& vehicles,
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,
619 std::vector<NodeEntries>* node_entries);
622 void DeleteNodeEntry(NodeEntry* entry,
624 std::vector<NodeEntries>* node_entries);
625
629 void AddNodeEntry(int64_t node, int64_t insert_after, int vehicle,
630 bool all_vehicles,
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(
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.
1063DecisionBuilder* MakeSweepDecisionBuilder(RoutingModel* model,
1064 bool check_assignment);
1065
1066// Returns a DecisionBuilder making all nodes unperformed.
1067DecisionBuilder* MakeAllUnperformed(RoutingModel* model);
1068
1069} // namespace operations_research
1070
1071#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:893
#define DCHECK(condition)
Definition: base/logging.h:889
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)
Inserts 'node' just after 'predecessor', and just before 'successor', resulting in the following subs...
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.
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.
bool Commit()
Commits the modifications to the current solution if these modifications are "filter-feasible",...
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).
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.
IntVarFilteredHeuristic(Solver *solver, const std::vector< IntVar * > &vars, LocalSearchFilterManager *filter_manager)
Assignment *const BuildSolution()
Builds a solution.
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.
bool BuildSolutionInternal() override
Virtual method to redefine how to build a solution.
LocalCheapestInsertionFilteredHeuristic(RoutingModel *model, std::function< int64_t(int64_t, int64_t, int64_t)> evaluator, LocalSearchFilterManager *filter_manager)
Takes ownership of evaluator.
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,.
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.
RoutingFilteredHeuristic(RoutingModel *model, LocalSearchFilterManager *filter_manager)
RoutingIndexPair IndexPair
Definition: routing.h:244
bool CheckLimit()
Returns true if the search limit has been crossed.
Definition: routing.h:1501
IntVar * VehicleVar(int64_t index) const
Returns the vehicle variable of the node corresponding to index.
Definition: routing.h:1369
int64_t Size() const
Returns the number of next variables in the model.
Definition: routing.h:1518
int vehicles() const
Returns the number of vehicle routes in the model.
Definition: routing.h:1516
int64_t End(int vehicle) const
Returns the variable index of the ending node of a vehicle route.
Definition: routing.h:1322
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 by their distance and their angles 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
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 index
Definition: pack.cc:509
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:360
Struct used to sort and store vehicles by their type.
Definition: routing.h:359
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.