14#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_SEARCH_H_
15#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_SEARCH_H_
24#include <initializer_list>
37#include "absl/container/flat_hash_set.h"
38#include "absl/container/inlined_vector.h"
39#include "absl/log/check.h"
40#include "absl/types/span.h"
45#include "ortools/constraint_solver/routing_enums.pb.h"
46#include "ortools/constraint_solver/routing_parameters.pb.h"
77 RoutingModel* primary_model,
78 const std::vector<RoutingModel*>& alternative_models,
79 const RoutingSearchParameters& parameters,
80 int max_non_improving_iterations);
83 const Assignment* assignment, RoutingModel* primary_model,
84 const std::vector<RoutingModel*>& alternative_models,
85 const RoutingSearchParameters& parameters,
86 int max_non_improving_iterations);
89 const Assignment* assignment, RoutingModel* primary_model,
90 const RoutingSearchParameters& parameters,
91 const std::vector<RoutingModel*>& alternative_models,
92 const std::vector<RoutingSearchParameters>& alternative_parameters,
93 int max_non_improving_iterations);
103 const RoutingModel::VehicleTypeContainer& vehicle_type_container)
104 : vehicle_type_container_(&vehicle_type_container) {}
106 int NumTypes()
const {
return vehicle_type_container_->NumTypes(); }
108 int Type(
int vehicle)
const {
return vehicle_type_container_->Type(vehicle); }
112 void Reset(
const std::function<
bool(
int)>& store_vehicle);
116 void Update(
const std::function<
bool(
int)>& remove_vehicle);
120 const std::set<VehicleClassEntry>& vehicle_classes =
121 sorted_vehicle_classes_per_type_[type];
122 if (vehicle_classes.empty()) {
125 const int vehicle_class = (vehicle_classes.begin())->vehicle_class;
126 DCHECK(!vehicles_per_vehicle_class_[vehicle_class].empty());
127 return vehicles_per_vehicle_class_[vehicle_class][0];
131 int64_t fixed_cost) {
132 std::vector<int>& vehicles = vehicles_per_vehicle_class_[vehicle_class];
133 if (vehicles.empty()) {
136 std::set<VehicleClassEntry>& vehicle_classes =
137 sorted_vehicle_classes_per_type_[
Type(vehicle)];
138 const auto& insertion =
139 vehicle_classes.insert({vehicle_class, fixed_cost});
140 DCHECK(insertion.second);
142 vehicles.push_back(vehicle);
148 int type,
const std::function<
bool(
int)>& vehicle_is_compatible)
const;
158 int type,
const std::function<
bool(
int)>& vehicle_is_compatible,
159 const std::function<
bool(
int)>& stop_and_return_vehicle);
162 using VehicleClassEntry =
163 RoutingModel::VehicleTypeContainer::VehicleClassEntry;
164 const RoutingModel::VehicleTypeContainer*
const vehicle_type_container_;
166 std::vector<std::set<VehicleClassEntry> > sorted_vehicle_classes_per_type_;
167 std::vector<std::vector<int> > vehicles_per_vehicle_class_;
173operations_research::FirstSolutionStrategy::Value
175 bool has_node_precedences,
176 bool has_single_vehicle_node);
201 std::unique_ptr<IntVarFilteredHeuristic> heuristic);
214 const std::unique_ptr<IntVarFilteredHeuristic> heuristic_;
221 const std::vector<IntVar*>& secondary_vars,
235 virtual std::string
DebugString()
const {
return "IntVarFilteredHeuristic"; }
253 std::optional<int64_t>
Evaluate(
bool commit,
bool ignore_upper_bound =
false,
254 bool update_upper_bound =
true);
260 DCHECK_LT(index, is_in_delta_.size());
261 if (!is_in_delta_[index]) {
262 delta_->FastAdd(vars_[index])->SetValue(value);
263 delta_indices_.push_back(index);
264 is_in_delta_[index] =
true;
266 delta_->SetValue(vars_[index], value);
273 int64_t
Value(int64_t index)
const {
274 return assignment_->IntVarContainer().Element(index).Value();
278 return assignment_->IntVarContainer().Element(index).Var() !=
nullptr;
281 IntVar*
Var(int64_t index)
const {
return vars_[index]; }
285 return index + base_vars_size_;
299 bool FilterAccept(
bool ignore_upper_bound);
302 std::vector<IntVar*> vars_;
303 const int base_vars_size_;
305 std::vector<int> delta_indices_;
306 std::vector<bool> is_in_delta_;
309 int64_t objective_upper_bound_;
311 int64_t number_of_decisions_;
312 int64_t number_of_rejects_;
319 std::function<
bool()> stop_search,
324 const std::function<int64_t(int64_t)>& next_accessor);
325 RoutingModel*
model()
const {
return model_; }
350 void SetNext(int64_t node, int64_t next,
int vehicle) {
357 bool InitializeSolution()
override;
359 RoutingModel*
const model_;
360 std::function<bool()> stop_search_;
361 std::vector<int64_t> start_chain_ends_;
362 std::vector<int64_t> end_chain_starts_;
369 RoutingModel*
model, std::function<
bool()> stop_search,
370 std::function<int64_t(int64_t, int64_t, int64_t)> evaluator,
371 std::function<int64_t(int64_t)> penalty_evaluator,
406 for (
size_t i = 0; i <
properties.size(); ++i) {
421 std::priority_queue<Seed, std::vector<Seed>, std::greater<Seed> >
433 std::vector<std::vector<StartEndValue> >
440 std::vector<std::vector<StartEndValue> >* start_end_distances_per_node,
447 std::vector<StartEndValue>* start_end_distances,
455 void InsertBetween(int64_t node, int64_t predecessor, int64_t successor,
462 int64_t node_to_insert, int64_t start, int64_t next_after_start,
463 int vehicle,
bool ignore_cost,
464 std::vector<NodeInsertion>* node_insertions);
472 int64_t insert_after,
473 int64_t insert_before,
487 bool IsHint(
int node, int64_t next)
const {
491 std::function<int64_t(int64_t, int64_t, int64_t)>
evaluator_;
533 RoutingModel*
model, std::function<
bool()> stop_search,
534 std::function<int64_t(int64_t, int64_t, int64_t)> evaluator,
535 std::function<int64_t(int64_t)> penalty_evaluator,
541 return "GlobalCheapestInsertionFilteredHeuristic";
546 class NodeEntryQueue;
551 PairEntry(
int pickup_to_insert,
int pickup_insert_after,
552 int delivery_to_insert,
int delivery_insert_after,
int vehicle,
554 : value_(
std::numeric_limits<int64_t>::max()),
556 pickup_to_insert_(pickup_to_insert),
557 pickup_insert_after_(pickup_insert_after),
558 delivery_to_insert_(delivery_to_insert),
559 delivery_insert_after_(delivery_insert_after),
564 bool operator<(
const PairEntry& other)
const {
566 if (bucket_ != other.bucket_) {
567 return bucket_ > other.bucket_;
571 if (value_ != other.value_) {
572 return value_ > other.value_;
574 if ((vehicle_ == -1) ^ (other.vehicle_ == -1)) {
575 return vehicle_ == -1;
577 return std::tie(pickup_insert_after_, pickup_to_insert_,
578 delivery_insert_after_, delivery_to_insert_, vehicle_) >
579 std::tie(other.pickup_insert_after_, other.pickup_to_insert_,
580 other.delivery_insert_after_, other.delivery_to_insert_,
583 void SetHeapIndex(
int h) { heap_index_ = h; }
584 int GetHeapIndex()
const {
return heap_index_; }
585 void set_value(int64_t value) { value_ = value; }
586 int pickup_to_insert()
const {
return pickup_to_insert_; }
587 int pickup_insert_after()
const {
return pickup_insert_after_; }
588 void set_pickup_insert_after(
int pickup_insert_after) {
589 pickup_insert_after_ = pickup_insert_after;
591 int delivery_to_insert()
const {
return delivery_to_insert_; }
592 int delivery_insert_after()
const {
return delivery_insert_after_; }
593 int vehicle()
const {
return vehicle_; }
594 void set_vehicle(
int vehicle) { vehicle_ = vehicle; }
599 int pickup_to_insert_;
600 int pickup_insert_after_;
601 int delivery_to_insert_;
602 int delivery_insert_after_;
607 typedef absl::flat_hash_set<PairEntry*> PairEntries;
610 template <
typename T>
611 class EntryAllocator {
613 EntryAllocator() =
default;
616 free_entries_.clear();
618 template <
typename... Args>
619 T* NewEntry(
const Args&... args) {
620 if (!free_entries_.empty()) {
621 auto* entry = free_entries_.back();
622 free_entries_.pop_back();
626 entries_.emplace_back(args...);
627 return &entries_.back();
630 void FreeEntry(T* entry) { free_entries_.push_back(entry); }
634 std::deque<T> entries_;
635 std::vector<T*> free_entries_;
644 bool InsertPairsAndNodesByRequirementTopologicalOrder();
653 const std::map<int64_t, std::vector<int>>& pair_indices_by_bucket);
658 bool UseEmptyVehicleTypeCuratorForVehicle(
int vehicle,
659 bool all_vehicles =
true) {
669 bool InsertPairEntryUsingEmptyVehicleTypeCurator(
670 const absl::flat_hash_set<int>& pair_indices, PairEntry* pair_entry,
671 AdjustablePriorityQueue<PairEntry>* priority_queue,
672 std::vector<PairEntries>* pickup_to_entries,
673 std::vector<PairEntries>* delivery_to_entries);
682 bool InsertNodesOnRoutes(
683 const std::map<int64_t, std::vector<int>>& nodes_by_bucket,
684 const absl::flat_hash_set<int>& vehicles);
693 bool InsertNodeEntryUsingEmptyVehicleTypeCurator(
694 const SparseBitset<int>& nodes,
bool all_vehicles,
NodeEntryQueue* queue);
701 bool SequentialInsertNodes(
702 const std::map<int64_t, std::vector<int>>& nodes_by_bucket);
707 void DetectUsedVehicles(std::vector<bool>* is_vehicle_used,
708 std::vector<int>* unused_vehicles,
709 absl::flat_hash_set<int>* used_vehicles);
713 bool IsCheapestClassRepresentative(
int vehicle)
const;
718 void InsertFarthestNodesAsSeeds();
729 std::vector<std::vector<StartEndValue>>* start_end_distances_per_node,
730 SeedQueue* sq, std::vector<bool>* is_vehicle_used);
735 bool InitializePairPositions(
736 const absl::flat_hash_set<int>& pair_indices,
737 AdjustablePriorityQueue<PairEntry>* priority_queue,
738 std::vector<PairEntries>* pickup_to_entries,
739 std::vector<PairEntries>* delivery_to_entries);
745 void InitializeInsertionEntriesPerformingPair(
746 int64_t pickup, int64_t delivery,
747 AdjustablePriorityQueue<PairEntry>* priority_queue,
748 std::vector<PairEntries>* pickup_to_entries,
749 std::vector<PairEntries>* delivery_to_entries);
753 bool UpdateAfterPairInsertion(
754 const absl::flat_hash_set<int>& pair_indices,
int vehicle, int64_t pickup,
755 int64_t pickup_position, int64_t delivery, int64_t delivery_position,
756 AdjustablePriorityQueue<PairEntry>* priority_queue,
757 std::vector<PairEntries>* pickup_to_entries,
758 std::vector<PairEntries>* delivery_to_entries);
762 bool UpdateExistingPairEntriesOnChain(
763 int64_t insert_after_start, int64_t insert_after_end,
764 AdjustablePriorityQueue<PairEntry>* priority_queue,
765 std::vector<PairEntries>* pickup_to_entries,
766 std::vector<PairEntries>* delivery_to_entries);
772 bool AddPairEntriesAfter(
const absl::flat_hash_set<int>& pair_indices,
773 int vehicle, int64_t insert_after,
774 int64_t skip_entries_inserting_delivery_after,
775 AdjustablePriorityQueue<PairEntry>* priority_queue,
776 std::vector<PairEntries>* pickup_to_entries,
777 std::vector<PairEntries>* delivery_to_entries) {
778 return AddPairEntriesWithDeliveryAfter(pair_indices, vehicle, insert_after,
779 priority_queue, pickup_to_entries,
780 delivery_to_entries) &&
781 AddPairEntriesWithPickupAfter(pair_indices, vehicle, insert_after,
782 skip_entries_inserting_delivery_after,
783 priority_queue, pickup_to_entries,
784 delivery_to_entries);
792 bool AddPairEntriesWithPickupAfter(
793 const absl::flat_hash_set<int>& pair_indices,
int vehicle,
794 int64_t insert_after, int64_t skip_entries_inserting_delivery_after,
795 AdjustablePriorityQueue<PairEntry>* priority_queue,
796 std::vector<PairEntries>* pickup_to_entries,
797 std::vector<PairEntries>* delivery_to_entries);
801 bool AddPairEntriesWithDeliveryAfter(
802 const absl::flat_hash_set<int>& pair_indices,
int vehicle,
803 int64_t insert_after, AdjustablePriorityQueue<PairEntry>* priority_queue,
804 std::vector<PairEntries>* pickup_to_entries,
805 std::vector<PairEntries>* delivery_to_entries);
808 void DeletePairEntry(PairEntry* entry,
809 AdjustablePriorityQueue<PairEntry>* priority_queue,
810 std::vector<PairEntries>* pickup_to_entries,
811 std::vector<PairEntries>* delivery_to_entries);
816 void AddPairEntry(int64_t pickup, int64_t pickup_insert_after,
817 int64_t delivery, int64_t delivery_insert_after,
819 AdjustablePriorityQueue<PairEntry>* priority_queue,
820 std::vector<PairEntries>* pickup_entries,
821 std::vector<PairEntries>* delivery_entries)
const;
824 void UpdatePairEntry(
825 PairEntry* pair_entry,
826 AdjustablePriorityQueue<PairEntry>* priority_queue)
const;
830 int64_t GetInsertionValueForPairAtPositions(int64_t pickup,
831 int64_t pickup_insert_after,
833 int64_t delivery_insert_after,
838 bool InitializePositions(
const SparseBitset<int>& nodes,
839 const absl::flat_hash_set<int>& vehicles,
846 void InitializeInsertionEntriesPerformingNode(
847 int64_t node,
const absl::flat_hash_set<int>& vehicles,
851 bool UpdateAfterNodeInsertion(
const SparseBitset<int>& nodes,
int vehicle,
852 int64_t node, int64_t insert_after,
857 bool UpdateExistingNodeEntriesOnChain(
const SparseBitset<int>& nodes,
858 int vehicle, int64_t insert_after_start,
859 int64_t insert_after_end,
864 bool AddNodeEntriesAfter(
const SparseBitset<int>& nodes,
int vehicle,
865 int64_t insert_after,
bool all_vehicles,
871 void AddNodeEntry(int64_t node, int64_t insert_after,
int vehicle,
874 void ResetVehicleIndices()
override {
875 node_index_to_vehicle_.assign(node_index_to_vehicle_.size(), -1);
878 void SetVehicleIndex(int64_t node,
int vehicle)
override {
879 DCHECK_LT(node, node_index_to_vehicle_.size());
880 node_index_to_vehicle_[node] = vehicle;
885 bool CheckVehicleIndices()
const;
888 int64_t GetBucketOfNode(
int node)
const {
889 return model()->VehicleVar(node)->Size();
893 int64_t GetBucketOfPair(
const PickupDeliveryPair& pair)
const {
894 int64_t max_pickup_bucket = 0;
895 for (int64_t pickup : pair.pickup_alternatives) {
896 max_pickup_bucket = std::max(max_pickup_bucket, GetBucketOfNode(pickup));
898 int64_t max_delivery_bucket = 0;
899 for (int64_t delivery : pair.delivery_alternatives) {
900 max_delivery_bucket =
901 std::max(max_delivery_bucket, GetBucketOfNode(delivery));
903 return std::min(max_pickup_bucket, max_delivery_bucket);
908 template <
typename T>
909 bool StopSearchAndCleanup(AdjustablePriorityQueue<T>* priority_queue) {
911 if constexpr (std::is_same_v<T, PairEntry>) {
912 pair_entry_allocator_.Clear();
914 priority_queue->
Clear();
920 std::vector<int> node_index_to_vehicle_;
922 const RoutingModel::NodeNeighborsByCostClass*
923 node_index_to_neighbors_by_cost_class_;
925 std::unique_ptr<VehicleTypeCurator> empty_vehicle_type_curator_;
927 mutable EntryAllocator<PairEntry> pair_entry_allocator_;
944 struct InsertionBounds {
950 bool operator<(
const InsertionBounds& other)
const {
951 return std::tie(neg_hint_weight, cost, vehicle,
begin) <
952 std::tie(other.neg_hint_weight, other.cost, other.vehicle,
972 : data_(data), bounds_(bounds) {}
975 DCHECK_NE(data_, other.data_);
976 return bounds_ != other.bounds_;
981 size_t Size()
const {
return bounds_->Size(); }
982 int Vehicle()
const {
return bounds_->vehicle; }
983 int64_t
Cost()
const {
return bounds_->cost; }
984 int64_t&
Cost() {
return bounds_->cost; }
986 bounds_->neg_hint_weight = -hint_weight;
992 InsertionBounds*
const bounds_;
997 : data_(data), bounds_(bounds) {}
999 DCHECK_EQ(data_, other.data_);
1000 return bounds_ != other.bounds_;
1010 InsertionBounds* bounds_;
1015 return {insertions_.data(), insertion_bounds_.data()};
1018 return {insertions_.data(),
1019 insertion_bounds_.data() + insertion_bounds_.size()};
1022 size_t Size()
const {
return insertion_bounds_.size(); }
1028 int vehicle, std::initializer_list<Insertion> insertion_sequence) {
1029 insertion_bounds_.push_back(
1030 {.begin = insertions_.size(),
1031 .end = insertions_.size() + insertion_sequence.size(),
1034 insertions_.insert(insertions_.end(), insertion_sequence.begin(),
1035 insertion_sequence.end());
1040 absl::Span<const Insertion> insertion_sequence) {
1041 insertion_bounds_.push_back(
1042 {.begin = insertions_.size(),
1043 .end = insertions_.size() + insertion_sequence.size(),
1046 insertions_.insert(insertions_.end(), insertion_sequence.begin(),
1047 insertion_sequence.end());
1057 if (!p(sequence)) insertion_bounds_[
to++] = insertion_bounds_[from];
1060 insertion_bounds_.resize(
to);
1067 void Sort() { std::sort(insertion_bounds_.begin(), insertion_bounds_.end()); }
1071 insertions_.clear();
1072 insertion_bounds_.clear();
1076 std::vector<Insertion> insertions_;
1077 std::vector<InsertionBounds> insertion_bounds_;
1103 int pickup,
int delivery,
int vehicle,
const std::vector<int>& path,
1104 const std::vector<bool>& path_node_is_pickup,
1105 const std::vector<bool>& path_node_is_delivery,
1110 std::vector<int> next_decrease_;
1111 std::vector<int> next_increase_;
1112 std::vector<int> prev_decrease_;
1113 std::vector<int> prev_increase_;
1142 RoutingModel*
model, std::function<
bool()> stop_search,
1143 std::function<int64_t(int64_t, int64_t, int64_t)> evaluator,
1144 RoutingSearchParameters::PairInsertionStrategy pair_insertion_strategy,
1145 std::vector<RoutingSearchParameters::InsertionSortingProperty>
1146 insertion_sorting_properties,
1149 std::function<
bool(
const std::vector<RoutingModel::VariableValuePair>&,
1150 std::vector<RoutingModel::VariableValuePair>*)>
1151 optimize_on_insertion =
nullptr);
1155 return "LocalCheapestInsertionFilteredHeuristic";
1165 void ComputeInsertionOrder();
1169 std::vector<NodeInsertion> ComputeEvaluatorSortedPositions(int64_t node);
1174 std::vector<NodeInsertion> ComputeEvaluatorSortedPositionsOnRouteAfter(
1175 int64_t node, int64_t start, int64_t next_after_start,
int vehicle);
1180 std::vector<PickupDeliveryInsertion> ComputeEvaluatorSortedPairPositions(
1181 int pickup,
int delivery);
1194 bool InsertPair(int64_t pickup, int64_t insert_pickup_after, int64_t delivery,
1195 int64_t insert_delivery_after,
int vehicle);
1203 bool MustUpdateBinCapacities()
const {
1204 return bin_capacities_ !=
nullptr && optimize_on_insertion_ ==
nullptr;
1207 std::vector<Seed> insertion_order_;
1208 const RoutingSearchParameters::PairInsertionStrategy pair_insertion_strategy_;
1209 std::vector<RoutingSearchParameters::InsertionSortingProperty>
1210 insertion_sorting_properties_;
1211 InsertionSequenceContainer insertion_container_;
1212 InsertionSequenceGenerator insertion_generator_;
1214 const bool use_first_solution_hint_;
1216 BinCapacities*
const bin_capacities_;
1218 std::function<bool(
const std::vector<RoutingModel::VariableValuePair>&,
1219 std::vector<RoutingModel::VariableValuePair>*)>
1220 optimize_on_insertion_;
1221 bool synchronize_insertion_optimizer_ =
true;
1229 std::function<
bool()> stop_search,
1235 class PartialRoutesAndLargeVehicleIndicesFirst {
1237 explicit PartialRoutesAndLargeVehicleIndicesFirst(
1239 : builder_(builder) {}
1240 bool operator()(
int vehicle1,
int vehicle2)
const;
1246 template <
typename Iterator>
1247 std::vector<int64_t> GetPossibleNextsFromIterator(int64_t node,
1249 Iterator end)
const {
1250 const int size =
model()->Size();
1251 std::vector<int64_t> nexts;
1252 for (Iterator it = start; it != end; ++it) {
1253 const int64_t next = *it;
1254 if (next != node && (next >= size || !
Contains(next))) {
1255 nexts.push_back(next);
1261 virtual void SortSuccessors(int64_t node,
1262 std::vector<int64_t>* successors) = 0;
1263 virtual int64_t FindTopSuccessor(int64_t node,
1264 const std::vector<int64_t>& successors) = 0;
1274 RoutingModel*
model, std::function<
bool()> stop_search,
1275 std::function<int64_t(int64_t, int64_t)> evaluator,
1279 return "EvaluatorCheapestAdditionFilteredHeuristic";
1284 void SortSuccessors(int64_t node, std::vector<int64_t>* successors)
override;
1285 int64_t FindTopSuccessor(int64_t node,
1286 const std::vector<int64_t>& successors)
override;
1288 std::function<int64_t(int64_t, int64_t)> evaluator_;
1298 RoutingModel*
model, std::function<
bool()> stop_search,
1303 return "ComparatorCheapestAdditionFilteredHeuristic";
1308 void SortSuccessors(int64_t node, std::vector<int64_t>* successors)
override;
1309 int64_t FindTopSuccessor(int64_t node,
1310 const std::vector<int64_t>& successors)
override;
1341 std::function<
bool()> stop_search,
1360 template <
typename S>
1361 class SavingsContainer;
1377 int64_t after_node);
1390 void AddSymmetricArcsToAdjacencyLists(
1391 std::vector<std::vector<int64_t> >* adjacency_lists);
1402 bool ComputeSavings();
1404 Saving BuildSaving(int64_t saving,
int vehicle_type,
int before_node,
1405 int after_node)
const {
1406 return {saving,
static_cast<unsigned int>(vehicle_type),
1407 static_cast<unsigned int>(before_node),
1408 static_cast<unsigned int>(after_node)};
1414 int64_t MaxNumNeighborsPerNode(
int num_vehicle_types)
const;
1416 const SavingsParameters savings_params_;
1424 std::function<
bool()> stop_search,
1431 return "SequentialSavingsFilteredHeuristic";
1439 void BuildRoutesFromSavings()
override;
1440 double ExtraSavingsMemoryMultiplicativeFactor()
const override {
return 1.0; }
1446 std::function<
bool()> stop_search,
1453 return "ParallelSavingsFilteredHeuristic";
1467 void BuildRoutesFromSavings()
override;
1469 double ExtraSavingsMemoryMultiplicativeFactor()
const override {
return 2.0; }
1475 void MergeRoutes(
int first_vehicle,
int second_vehicle, int64_t before_node,
1476 int64_t after_node);
1479 std::vector<int64_t> first_node_on_route_;
1480 std::vector<int64_t> last_node_on_route_;
1484 std::vector<int> vehicle_of_first_or_last_node_;
1494 std::function<
bool()> stop_search,
1496 bool use_minimum_matching);
1500 return "ChristofidesFilteredHeuristic";
1504 const bool use_minimum_matching_;
1511 explicit SweepArranger(absl::Span<
const std::pair<int64_t, int64_t>> points);
1522 std::vector<int> coordinates_;
1530 bool check_assignment);
bool BuildSolutionInternal() override
Virtual method to redefine how to build a solution.
CheapestAdditionFilteredHeuristic(RoutingModel *model, std::function< bool()> stop_search, LocalSearchFilterManager *filter_manager)
CheapestAdditionFilteredHeuristic.
~CheapestAdditionFilteredHeuristic() override=default
int64_t GetInsertionCostForNodeAtPosition(int64_t node_to_insert, int64_t insert_after, int64_t insert_before, int vehicle) const
std::function< int64_t(int64_t, int64_t, int64_t)> evaluator_
std::vector< std::vector< StartEndValue > > ComputeStartEndDistanceForVehicles(absl::Span< const int > vehicles)
bool HasHintedNext(int node) const
std::vector< int > hint_prev_values_
~CheapestInsertionFilteredHeuristic() override=default
bool IsHint(int node, int64_t next) const
std::vector< int > hint_next_values_
void InitializeSeedQueue(std::vector< std::vector< StartEndValue > > *start_end_distances_per_node, SeedQueue *sq)
CheapestInsertionFilteredHeuristic(RoutingModel *model, std::function< bool()> stop_search, 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 AppendInsertionPositionsAfter(int64_t node_to_insert, int64_t start, int64_t next_after_start, int vehicle, bool ignore_cost, std::vector< NodeInsertion > *node_insertions)
int64_t GetUnperformedValue(int64_t node_to_insert) const
void InsertBetween(int64_t node, int64_t predecessor, int64_t successor, int vehicle=-1)
bool HasHintedPrev(int node) const
std::function< int64_t(int64_t)> penalty_evaluator_
void AddSeedNodeToQueue(int node, std::vector< StartEndValue > *start_end_distances, SeedQueue *sq)
clang-format on
ChristofidesFilteredHeuristic(RoutingModel *model, std::function< bool()> stop_search, LocalSearchFilterManager *filter_manager, bool use_minimum_matching)
ChristofidesFilteredHeuristic.
bool BuildSolutionInternal() override
~ChristofidesFilteredHeuristic() override=default
std::string DebugString() const override
std::string DebugString() const override
~ComparatorCheapestAdditionFilteredHeuristic() override=default
ComparatorCheapestAdditionFilteredHeuristic(RoutingModel *model, std::function< bool()> stop_search, Solver::VariableValueComparator comparator, LocalSearchFilterManager *filter_manager)
Takes ownership of evaluator.
~EvaluatorCheapestAdditionFilteredHeuristic() override=default
std::string DebugString() const override
EvaluatorCheapestAdditionFilteredHeuristic(RoutingModel *model, std::function< bool()> stop_search, std::function< int64_t(int64_t, int64_t)> evaluator, LocalSearchFilterManager *filter_manager)
Takes ownership of evaluator.
GlobalCheapestInsertionFilteredHeuristic(RoutingModel *model, std::function< bool()> stop_search, 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.
bool BuildSolutionInternal() override
Virtual method to redefine how to build a solution.
~GlobalCheapestInsertionFilteredHeuristic() override=default
std::string DebugString() const override
InsertionSequenceIterator(Insertion *data, InsertionBounds *bounds)
InsertionSequence operator*() const
bool operator!=(const InsertionSequenceIterator &other) const
InsertionSequenceIterator & operator++()
void SetHintWeight(int hint_weight)
const Insertion * end() const
const Insertion * begin() const
bool operator!=(const InsertionSequence &other) const
int NegHintWeight() const
InsertionSequence(Insertion *data, InsertionBounds *bounds)
void RemoveIf(const std::function< bool(const InsertionSequence &)> &p)
void AddInsertionSequence(int vehicle, std::initializer_list< Insertion > insertion_sequence)
InsertionSequenceIterator begin()
InsertionSequenceContainer is a range over insertion sequences.
void Clear()
Removes all sequences.
size_t Size() const
Returns the number of sequences of this container.
InsertionSequenceIterator end()
void AddInsertionSequence(int vehicle, absl::Span< const Insertion > insertion_sequence)
Adds an insertion sequence to the container.
void AppendPickupDeliveryMultitourInsertions(int pickup, int delivery, int vehicle, const std::vector< int > &path, const std::vector< bool > &path_node_is_pickup, const std::vector< bool > &path_node_is_delivery, InsertionSequenceContainer &insertions)
InsertionSequenceGenerator()=default
int64_t number_of_rejects() const
int64_t number_of_decisions() const
Returns statistics from its underlying heuristic.
std::string DebugString() const override
-------— Decision Builder -------—
IntVarFilteredDecisionBuilder(std::unique_ptr< IntVarFilteredHeuristic > heuristic)
— First solution decision builder —
~IntVarFilteredDecisionBuilder() override=default
Generic filter-based heuristic applied to IntVars.
bool HasSecondaryVars() const
Returns true if there are secondary variables.
Assignment *const assignment_
virtual std::string DebugString() const
void ResetSolution()
Resets the data members for a new solution.
IntVarFilteredHeuristic(Solver *solver, const std::vector< IntVar * > &vars, const std::vector< IntVar * > &secondary_vars, LocalSearchFilterManager *filter_manager)
— First solution heuristics —
virtual bool BuildSolutionInternal()=0
Virtual method to redefine how to build a solution.
int64_t number_of_rejects() const
virtual ~IntVarFilteredHeuristic()=default
int64_t number_of_decisions() const
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.
virtual void Initialize()
Initialize the heuristic; called before starting to build a new solution.
Assignment * BuildSolution()
int64_t SecondaryVarIndex(int64_t index) const
Returns the index of a secondary var.
int64_t Value(int64_t index) const
void SetValue(int64_t index, int64_t value)
virtual bool InitializeSolution()
Virtual method to initialize the solution.
const std::vector< int > & delta_indices() const
Returns the indices of the nodes currently in the insertion delta.
IntVar * Var(int64_t index) const
Returns the variable of index 'index'.
void SynchronizeFilters()
Synchronizes filters with an assignment (the current solution).
std::optional< int64_t > Evaluate(bool commit, bool ignore_upper_bound=false, bool update_upper_bound=true)
bool IsSecondaryVar(int64_t index) const
Returns true if 'index' is a secondary variable index.
void Initialize() override
Initialize the heuristic; called before starting to build a new solution.
~LocalCheapestInsertionFilteredHeuristic() override=default
LocalCheapestInsertionFilteredHeuristic(RoutingModel *model, std::function< bool()> stop_search, std::function< int64_t(int64_t, int64_t, int64_t)> evaluator, RoutingSearchParameters::PairInsertionStrategy pair_insertion_strategy, std::vector< RoutingSearchParameters::InsertionSortingProperty > insertion_sorting_properties, LocalSearchFilterManager *filter_manager, bool use_first_solution_hint, BinCapacities *bin_capacities=nullptr, std::function< bool(const std::vector< RoutingModel::VariableValuePair > &, std::vector< RoutingModel::VariableValuePair > *)> optimize_on_insertion=nullptr)
Takes ownership of evaluator.
std::string DebugString() const override
bool BuildSolutionInternal() override
Virtual method to redefine how to build a solution.
~ParallelSavingsFilteredHeuristic() override=default
std::string DebugString() const override
ParallelSavingsFilteredHeuristic(RoutingModel *model, std::function< bool()> stop_search, SavingsParameters parameters, LocalSearchFilterManager *filter_manager)
int GetEndChainStart(int vehicle) const
Returns the start of the end chain of vehicle,.
virtual void ResetVehicleIndices()
virtual void SetVehicleIndex(int64_t, int)
Assignment * BuildSolutionFromRoutes(const std::function< int64_t(int64_t)> &next_accessor)
Builds a solution starting from the routes formed by the next accessor.
~RoutingFilteredHeuristic() override=default
void SetNext(int64_t node, int64_t next, int vehicle)
bool VehicleIsEmpty(int vehicle) const
void MakeDisjunctionNodesUnperformed(int64_t node)
bool MakeUnassignedNodesUnperformed()
Make all unassigned nodes unperformed, always returns true.
RoutingFilteredHeuristic(RoutingModel *model, std::function< bool()> stop_search, LocalSearchFilterManager *filter_manager)
RoutingFilteredHeuristic.
int GetStartChainEnd(int vehicle) const
Returns the end of the start chain of vehicle,.
RoutingModel * model() const
bool StopSearch() override
Returns true if the search must be stopped.
void AddUnassignedNodesToEmptyVehicles()
Adds all unassigned nodes to empty vehicles.
void MakePartiallyPerformedPairsUnperformed()
virtual void BuildRoutesFromSavings()=0
bool BuildSolutionInternal() override
Virtual method to redefine how to build a solution.
SavingsFilteredHeuristic(RoutingModel *model, std::function< bool()> stop_search, SavingsParameters parameters, LocalSearchFilterManager *filter_manager)
SavingsFilteredHeuristic.
~SavingsFilteredHeuristic() override
friend class SavingsFilteredHeuristicTestPeer
virtual double ExtraSavingsMemoryMultiplicativeFactor() const =0
int StartNewRouteWithBestVehicleOfType(int type, int64_t before_node, int64_t after_node)
std::unique_ptr< SavingsContainer< Saving > > savings_container_
clang-format off
std::unique_ptr< VehicleTypeCurator > vehicle_type_curator_
clang-format on
std::string DebugString() const override
SequentialSavingsFilteredHeuristic(RoutingModel *model, std::function< bool()> stop_search, SavingsParameters parameters, LocalSearchFilterManager *filter_manager)
~SequentialSavingsFilteredHeuristic() override=default
For the time being, Solver is neither MT_SAFE nor MT_HOT.
std::function< bool(int64_t, int64_t, int64_t)> VariableValueComparator
SweepArranger(absl::Span< const std::pair< int64_t, int64_t > > points)
SweepArranger(const SweepArranger &)=delete
This type is neither copyable nor movable.
void ArrangeIndices(std::vector< int64_t > *indices)
void SetSectors(int sectors)
virtual ~SweepArranger()=default
SweepArranger & operator=(const SweepArranger &)=delete
void Update(const std::function< bool(int)> &remove_vehicle)
bool HasCompatibleVehicleOfType(int type, const std::function< bool(int)> &vehicle_is_compatible) const
VehicleTypeCurator(const RoutingModel::VehicleTypeContainer &vehicle_type_container)
void ReinjectVehicleOfClass(int vehicle, int vehicle_class, int64_t fixed_cost)
int GetLowestFixedCostVehicleOfType(int type) const
std::pair< int, int > GetCompatibleVehicleOfType(int type, const std::function< bool(int)> &vehicle_is_compatible, const std::function< bool(int)> &stop_and_return_vehicle)
void Reset(const std::function< bool(int)> &store_vehicle)
— VehicleTypeCurator —
int Type(int vehicle) const
dual_gradient T(y - `dual_solution`) class DiagonalTrustRegionProblemFromQp
In SWIG mode, we don't want anything besides these top-level includes.
const Assignment * SolveFromAssignmentWithAlternativeSolversAndParameters(const Assignment *assignment, RoutingModel *primary_model, const RoutingSearchParameters &primary_parameters, const std::vector< RoutingModel * > &alternative_models, const std::vector< RoutingSearchParameters > &alternative_parameters, int max_non_improving_iterations)
Same as above but taking alternative parameters for each alternative model.
DecisionBuilder * MakeAllUnperformed(RoutingModel *model)
Returns a DecisionBuilder making all nodes unperformed.
FirstSolutionStrategy::Value AutomaticFirstSolutionStrategy(bool has_pickup_deliveries, bool has_node_precedences, bool has_single_vehicle_node)
std::vector< int64_t > ComputeVehicleEndChainStarts(const RoutingModel &model)
const Assignment * SolveFromAssignmentWithAlternativeSolvers(const Assignment *assignment, RoutingModel *primary_model, const std::vector< RoutingModel * > &alternative_models, const RoutingSearchParameters ¶meters, int max_non_improving_iterations)
Same as above, but taking an initial solution.
DecisionBuilder * MakeSweepDecisionBuilder(RoutingModel *model, bool check_assignment)
const Assignment * SolveWithAlternativeSolvers(RoutingModel *primary_model, const std::vector< RoutingModel * > &alternative_models, const RoutingSearchParameters ¶meters, int max_non_improving_iterations)
trees with all degrees equal to
bool operator<(const NodeInsertion &other) const
const bool prioritize_farthest_nodes
std::priority_queue< Seed, std::vector< Seed >, std::greater< Seed > > priority_queue
SeedQueue(bool prioritize_farthest_nodes)
bool operator>(const Seed &other) const
absl::InlinedVector< int64_t, 8 > properties
bool operator<(const StartEndValue &other) const
bool add_unperformed_entries
bool use_neighbors_ratio_for_initialization
double farthest_seeds_ratio
bool is_sequential
Whether the routes are constructed sequentially or in parallel.
bool operator==(const Insertion &other) const
bool operator<(const PickupDeliveryInsertion &other) const
int64_t insert_pickup_after
int64_t insert_delivery_after
unsigned int vehicle_type
bool operator<(const Saving &other) const
double max_memory_usage_bytes