14#ifndef ORTOOLS_CONSTRAINT_SOLVER_ROUTING_SEARCH_H_
15#define ORTOOLS_CONSTRAINT_SOLVER_ROUTING_SEARCH_H_
22#include <initializer_list>
36#include "absl/container/flat_hash_set.h"
37#include "absl/container/inlined_vector.h"
38#include "absl/log/check.h"
39#include "absl/types/span.h"
78 const std::vector<RoutingModel*>& alternative_models,
80 int max_non_improving_iterations);
84 const std::vector<RoutingModel*>& alternative_models,
86 int max_non_improving_iterations);
91 const std::vector<RoutingModel*>& alternative_models,
92 const std::vector<RoutingSearchParameters>& alternative_parameters,
93 int max_non_improving_iterations);
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 =
166 std::vector<std::set<VehicleClassEntry> > sorted_vehicle_classes_per_type_;
167 std::vector<std::vector<int> > vehicles_per_vehicle_class_;
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);
350 void SetNext(int64_t node, int64_t next,
int vehicle) {
360 std::function<bool()> stop_search_;
361 std::vector<int64_t> start_chain_ends_;
362 std::vector<int64_t> end_chain_starts_;
370 std::function<int64_t(int64_t, int64_t, int64_t)> evaluator,
371 std::function<int64_t(int64_t)> penalty_evaluator,
399 for (
size_t i = 0; i <
properties.size(); ++i) {
414 std::priority_queue<Seed, std::vector<Seed>, std::greater<Seed> >
426 std::vector<std::vector<StartEndValue> >
433 std::vector<std::vector<StartEndValue> >* start_end_distances_per_node,
440 std::vector<StartEndValue>* start_end_distances,
448 void InsertBetween(int64_t node, int64_t predecessor, int64_t successor,
457 int64_t insert_after,
458 int64_t insert_before,
464 int64_t node_to_insert, int64_t insert_after, int64_t insert_before,
465 int vehicle,
int hint_weight = 0);
469 int64_t pickup_to_insert, int64_t pickup_insert_after,
470 int64_t delivery_to_insert, int64_t delivery_insert_after,
int vehicle,
471 int hint_weight = 0);
484 bool IsHint(
int node, int64_t next)
const {
488 std::function<int64_t(int64_t, int64_t, int64_t)>
evaluator_;
509 std::function<int64_t(int64_t, int64_t, int64_t)> evaluator,
510 std::function<int64_t(int64_t)> penalty_evaluator,
516 return "GlobalCheapestInsertionFilteredHeuristic";
521 class NodeEntryQueue;
526 PairEntry(
int pickup_to_insert,
int pickup_insert_after,
527 int delivery_to_insert,
int delivery_insert_after,
int vehicle,
529 : value_(
std::numeric_limits<int64_t>::max()),
531 pickup_to_insert_(pickup_to_insert),
532 pickup_insert_after_(pickup_insert_after),
533 delivery_to_insert_(delivery_to_insert),
534 delivery_insert_after_(delivery_insert_after),
539 bool operator<(
const PairEntry& other)
const {
541 if (bucket_ != other.bucket_) {
542 return bucket_ > other.bucket_;
546 if (value_ != other.value_) {
547 return value_ > other.value_;
549 if ((vehicle_ == -1) ^ (other.vehicle_ == -1)) {
550 return vehicle_ == -1;
552 return std::tie(pickup_insert_after_, pickup_to_insert_,
553 delivery_insert_after_, delivery_to_insert_, vehicle_) >
554 std::tie(other.pickup_insert_after_, other.pickup_to_insert_,
555 other.delivery_insert_after_, other.delivery_to_insert_,
558 void SetHeapIndex(
int h) { heap_index_ = h; }
559 int GetHeapIndex()
const {
return heap_index_; }
560 void set_value(int64_t value) { value_ = value; }
561 int pickup_to_insert()
const {
return pickup_to_insert_; }
562 int pickup_insert_after()
const {
return pickup_insert_after_; }
563 void set_pickup_insert_after(
int pickup_insert_after) {
564 pickup_insert_after_ = pickup_insert_after;
566 int delivery_to_insert()
const {
return delivery_to_insert_; }
567 int delivery_insert_after()
const {
return delivery_insert_after_; }
568 int vehicle()
const {
return vehicle_; }
569 void set_vehicle(
int vehicle) { vehicle_ = vehicle; }
574 int pickup_to_insert_;
575 int pickup_insert_after_;
576 int delivery_to_insert_;
577 int delivery_insert_after_;
582 typedef absl::flat_hash_set<PairEntry*> PairEntries;
585 template <
typename T>
586 class EntryAllocator {
588 EntryAllocator() =
default;
591 free_entries_.clear();
593 template <
typename... Args>
594 T* NewEntry(
const Args&... args) {
595 if (!free_entries_.empty()) {
596 auto* entry = free_entries_.back();
597 free_entries_.pop_back();
601 entries_.emplace_back(args...);
602 return &entries_.back();
605 void FreeEntry(T* entry) { free_entries_.push_back(entry); }
609 std::deque<T> entries_;
610 std::vector<T*> free_entries_;
619 bool InsertPairsAndNodesByRequirementTopologicalOrder();
626 bool InsertPairsAndNodesByPrecedenceTopologicalOrder();
635 const std::map<int64_t, std::vector<int>>& pair_indices_by_bucket);
640 bool UseEmptyVehicleTypeCuratorForVehicle(
int vehicle,
641 bool all_vehicles =
true)
const {
655 bool InsertPairEntryUsingEmptyVehicleTypeCurator(
656 const absl::flat_hash_set<int>& pair_indices, PairEntry* pair_entry,
657 AdjustablePriorityQueue<PairEntry>* priority_queue,
658 std::vector<PairEntries>* pickup_to_entries,
659 std::vector<PairEntries>* delivery_to_entries);
668 bool InsertNodesOnRoutes(
669 const std::map<int64_t, std::vector<int>>& nodes_by_bucket,
670 const absl::flat_hash_set<int>& vehicles);
679 bool InsertNodeEntryUsingEmptyVehicleTypeCurator(
680 const SparseBitset<int>& nodes,
bool all_vehicles,
NodeEntryQueue* queue);
687 bool SequentialInsertNodes(
688 const std::map<int64_t, std::vector<int>>& nodes_by_bucket);
693 void DetectUsedVehicles(std::vector<bool>* is_vehicle_used,
694 std::vector<int>* unused_vehicles,
695 absl::flat_hash_set<int>* used_vehicles);
699 bool IsCheapestClassRepresentative(
int vehicle)
const;
704 void InsertFarthestNodesAsSeeds();
715 std::vector<std::vector<StartEndValue>>* start_end_distances_per_node,
716 SeedQueue* sq, std::vector<bool>* is_vehicle_used);
721 bool InitializePairPositions(
722 const absl::flat_hash_set<int>& pair_indices,
723 AdjustablePriorityQueue<PairEntry>* priority_queue,
724 std::vector<PairEntries>* pickup_to_entries,
725 std::vector<PairEntries>* delivery_to_entries);
731 void InitializeInsertionEntriesPerformingPair(
732 int64_t pickup, int64_t delivery,
733 AdjustablePriorityQueue<PairEntry>* priority_queue,
734 std::vector<PairEntries>* pickup_to_entries,
735 std::vector<PairEntries>* delivery_to_entries);
739 bool UpdateAfterPairInsertion(
740 const absl::flat_hash_set<int>& pair_indices,
int vehicle, int64_t pickup,
741 int64_t pickup_position, int64_t delivery, int64_t delivery_position,
742 AdjustablePriorityQueue<PairEntry>* priority_queue,
743 std::vector<PairEntries>* pickup_to_entries,
744 std::vector<PairEntries>* delivery_to_entries);
747 bool UpdateExistingPairEntriesAfter(
748 int64_t insert_after, AdjustablePriorityQueue<PairEntry>* priority_queue,
749 std::vector<PairEntries>* pickup_to_entries,
750 std::vector<PairEntries>* delivery_to_entries);
756 bool AddPairEntriesAfter(
const absl::flat_hash_set<int>& pair_indices,
757 int vehicle, int64_t insert_after,
758 int64_t skip_entries_inserting_delivery_after,
759 AdjustablePriorityQueue<PairEntry>* priority_queue,
760 std::vector<PairEntries>* pickup_to_entries,
761 std::vector<PairEntries>* delivery_to_entries) {
762 return AddPairEntriesWithDeliveryAfter(pair_indices, vehicle, insert_after,
763 priority_queue, pickup_to_entries,
764 delivery_to_entries) &&
765 AddPairEntriesWithPickupAfter(pair_indices, vehicle, insert_after,
766 skip_entries_inserting_delivery_after,
767 priority_queue, pickup_to_entries,
768 delivery_to_entries);
776 bool AddPairEntriesWithPickupAfter(
777 const absl::flat_hash_set<int>& pair_indices,
int vehicle,
778 int64_t insert_after, int64_t skip_entries_inserting_delivery_after,
779 AdjustablePriorityQueue<PairEntry>* priority_queue,
780 std::vector<PairEntries>* pickup_to_entries,
781 std::vector<PairEntries>* delivery_to_entries);
785 bool AddPairEntriesWithDeliveryAfter(
786 const absl::flat_hash_set<int>& pair_indices,
int vehicle,
787 int64_t insert_after, AdjustablePriorityQueue<PairEntry>* priority_queue,
788 std::vector<PairEntries>* pickup_to_entries,
789 std::vector<PairEntries>* delivery_to_entries);
792 void DeletePairEntry(PairEntry* entry,
793 AdjustablePriorityQueue<PairEntry>* priority_queue,
794 std::vector<PairEntries>* pickup_to_entries,
795 std::vector<PairEntries>* delivery_to_entries);
800 void AddPairEntry(int64_t pickup, int64_t pickup_insert_after,
801 int64_t delivery, int64_t delivery_insert_after,
803 AdjustablePriorityQueue<PairEntry>* priority_queue,
804 std::vector<PairEntries>* pickup_entries,
805 std::vector<PairEntries>* delivery_entries);
811 bool UpdatePairEntry(PairEntry* pair_entry,
812 AdjustablePriorityQueue<PairEntry>* priority_queue);
816 bool InitializePositions(
const SparseBitset<int>& nodes,
817 const absl::flat_hash_set<int>& vehicles,
824 void InitializeInsertionEntriesPerformingNode(
825 int64_t node,
const absl::flat_hash_set<int>& vehicles,
829 bool UpdateAfterNodeInsertion(
const SparseBitset<int>& nodes,
int vehicle,
830 int64_t node, int64_t insert_after,
834 bool AddNodeEntriesAfter(
const SparseBitset<int>& nodes,
int vehicle,
835 int64_t insert_after,
bool all_vehicles,
841 void AddNodeEntry(int64_t node, int64_t insert_after,
int vehicle,
845 node_index_to_vehicle_.assign(node_index_to_vehicle_.size(), -1);
848 void SetVehicleIndex(int64_t node,
int vehicle)
override {
849 DCHECK_LT(node, node_index_to_vehicle_.size());
850 node_index_to_vehicle_[node] = vehicle;
855 bool CheckVehicleIndices()
const;
858 int64_t GetBucketOfNode(
int node)
const {
863 int64_t GetBucketOfPair(
const PickupDeliveryPair& pair)
const {
864 int64_t max_pickup_bucket = 0;
865 for (int64_t pickup : pair.pickup_alternatives) {
866 max_pickup_bucket = std::max(max_pickup_bucket, GetBucketOfNode(pickup));
868 int64_t max_delivery_bucket = 0;
869 for (int64_t delivery : pair.delivery_alternatives) {
870 max_delivery_bucket =
871 std::max(max_delivery_bucket, GetBucketOfNode(delivery));
873 return std::min(max_pickup_bucket, max_delivery_bucket);
878 template <
typename T>
879 bool StopSearchAndCleanup(AdjustablePriorityQueue<T>* priority_queue) {
881 if constexpr (std::is_same_v<T, PairEntry>) {
882 pair_entry_allocator_.Clear();
884 priority_queue->
Clear();
888 GlobalCheapestInsertionParameters gci_params_;
892 std::vector<int> node_index_to_vehicle_;
894 const RoutingModel::NodeNeighborsByCostClass*
895 node_index_to_neighbors_by_cost_class_;
897 std::unique_ptr<VehicleTypeCurator> empty_vehicle_type_curator_;
900 SparseBitset<int> temp_inserted_nodes_;
902 mutable EntryAllocator<PairEntry> pair_entry_allocator_;
919 struct InsertionBounds {
925 bool operator<(
const InsertionBounds& other)
const {
926 return std::tie(neg_hint_weight, cost, vehicle,
begin) <
927 std::tie(other.neg_hint_weight, other.cost, other.vehicle,
947 : data_(data), bounds_(bounds) {}
950 DCHECK_NE(data_, other.data_);
951 return bounds_ != other.bounds_;
956 size_t Size()
const {
return bounds_->Size(); }
957 int Vehicle()
const {
return bounds_->vehicle; }
958 int64_t
Cost()
const {
return bounds_->cost; }
959 int64_t&
Cost() {
return bounds_->cost; }
961 bounds_->neg_hint_weight = -hint_weight;
967 InsertionBounds*
const bounds_;
972 : data_(data), bounds_(bounds) {}
974 DCHECK_EQ(data_, other.data_);
975 return bounds_ != other.bounds_;
985 InsertionBounds* bounds_;
990 return {insertions_.data(), insertion_bounds_.data()};
993 return {insertions_.data(),
994 insertion_bounds_.data() + insertion_bounds_.size()};
997 size_t Size()
const {
return insertion_bounds_.size(); }
1003 int vehicle, std::initializer_list<Insertion> insertion_sequence) {
1004 insertion_bounds_.push_back(
1005 {.begin = insertions_.size(),
1006 .end = insertions_.size() + insertion_sequence.size(),
1009 insertions_.insert(insertions_.end(), insertion_sequence.begin(),
1010 insertion_sequence.end());
1015 absl::Span<const Insertion> insertion_sequence) {
1016 insertion_bounds_.push_back(
1017 {.begin = insertions_.size(),
1018 .end = insertions_.size() + insertion_sequence.size(),
1021 insertions_.insert(insertions_.end(), insertion_sequence.begin(),
1022 insertion_sequence.end());
1032 if (!p(sequence)) insertion_bounds_[
to++] = insertion_bounds_[from];
1035 insertion_bounds_.resize(
to);
1042 void Sort() { std::sort(insertion_bounds_.begin(), insertion_bounds_.end()); }
1046 insertions_.clear();
1047 insertion_bounds_.clear();
1051 std::vector<Insertion> insertions_;
1052 std::vector<InsertionBounds> insertion_bounds_;
1078 int pickup,
int delivery,
int vehicle, absl::Span<const int> path,
1079 const std::vector<bool>& path_node_is_pickup,
1080 const std::vector<bool>& path_node_is_delivery,
1085 std::vector<int> next_decrease_;
1086 std::vector<int> next_increase_;
1087 std::vector<int> prev_decrease_;
1088 std::vector<int> prev_increase_;
1118 std::function<int64_t(int64_t, int64_t, int64_t)> evaluator,
1122 std::function<
bool(
const std::vector<RoutingModel::VariableValuePair>&,
1123 std::vector<RoutingModel::VariableValuePair>*)>
1124 optimize_on_insertion =
nullptr);
1128 return "LocalCheapestInsertionFilteredHeuristic";
1135 struct NodeInsertion {
1136 int64_t insert_after;
1138 int neg_hint_weight;
1141 bool operator<(
const NodeInsertion& other)
const {
1142 return std::tie(neg_hint_weight, value, insert_after, vehicle) <
1143 std::tie(other.neg_hint_weight, other.value, other.insert_after,
1150 void ComputeInsertionOrder();
1155 void AppendInsertionPositionsAfter(
1156 int64_t node_to_insert, int64_t start, int64_t next_after_start,
1157 int vehicle, std::vector<NodeInsertion>* node_insertions);
1161 std::vector<NodeInsertion> ComputeEvaluatorSortedPositions(int64_t node);
1166 std::vector<NodeInsertion> ComputeEvaluatorSortedPositionsOnRouteAfter(
1167 int64_t node, int64_t start, int64_t next_after_start,
int vehicle);
1172 std::vector<PickupDeliveryInsertion> ComputeEvaluatorSortedPairPositions(
1173 int pickup,
int delivery);
1177 void InsertBestPickupThenDelivery(
const PickupDeliveryPair& pair);
1180 void InsertBestPair(
const PickupDeliveryPair& pair);
1184 void InsertBestPairMultitour(
const PickupDeliveryPair& pair);
1186 bool InsertPair(int64_t pickup, int64_t insert_pickup_after, int64_t delivery,
1187 int64_t insert_delivery_after,
int vehicle);
1195 bool MustUpdateBinCapacities()
const {
1196 return bin_capacities_ !=
nullptr && optimize_on_insertion_ ==
nullptr;
1199 std::vector<Seed> insertion_order_;
1201 pair_insertion_strategy_;
1202 std::vector<LocalCheapestInsertionParameters::InsertionSortingProperty>
1203 insertion_sorting_properties_;
1204 InsertionSequenceContainer insertion_container_;
1205 InsertionSequenceGenerator insertion_generator_;
1207 const bool use_first_solution_hint_;
1209 BinCapacities*
const bin_capacities_;
1211 std::function<bool(
const std::vector<RoutingModel::VariableValuePair>&,
1212 std::vector<RoutingModel::VariableValuePair>*)>
1213 optimize_on_insertion_;
1214 bool synchronize_insertion_optimizer_ =
true;
1216 const bool use_random_insertion_order_;
1225 std::function<
bool()> stop_search,
1231 class PartialRoutesAndLargeVehicleIndicesFirst {
1233 explicit PartialRoutesAndLargeVehicleIndicesFirst(
1235 : builder_(builder) {}
1236 bool operator()(
int vehicle1,
int vehicle2)
const;
1242 template <
typename Iterator>
1243 std::vector<int64_t> GetPossibleNextsFromIterator(int64_t node,
1245 Iterator
end)
const {
1247 std::vector<int64_t> nexts;
1248 for (Iterator it = start; it !=
end; ++it) {
1249 const int64_t next = *it;
1250 if (next != node && (next >= size || !
Contains(next))) {
1251 nexts.push_back(next);
1257 virtual void SortSuccessors(int64_t node,
1258 std::vector<int64_t>* successors) = 0;
1259 virtual int64_t FindTopSuccessor(int64_t node,
1260 const std::vector<int64_t>& successors) = 0;
1271 std::function<int64_t(int64_t, int64_t)> evaluator,
1275 return "EvaluatorCheapestAdditionFilteredHeuristic";
1280 void SortSuccessors(int64_t node, std::vector<int64_t>* successors)
override;
1281 int64_t FindTopSuccessor(int64_t node,
1282 const std::vector<int64_t>& successors)
override;
1284 std::function<int64_t(int64_t, int64_t)> evaluator_;
1299 return "ComparatorCheapestAdditionFilteredHeuristic";
1304 void SortSuccessors(int64_t node, std::vector<int64_t>* successors)
override;
1305 int64_t FindTopSuccessor(int64_t node,
1306 const std::vector<int64_t>& successors)
override;
1322 std::function<
bool()> stop_search,
1341 template <
typename S>
1342 class SavingsContainer;
1358 int64_t after_node);
1371 void AddSymmetricArcsToAdjacencyLists(
1372 std::vector<std::vector<int64_t> >* adjacency_lists);
1383 bool ComputeSavings();
1385 Saving BuildSaving(int64_t saving,
int vehicle_type,
int before_node,
1386 int after_node)
const {
1387 return {saving,
static_cast<unsigned int>(vehicle_type),
1388 static_cast<unsigned int>(before_node),
1389 static_cast<unsigned int>(after_node)};
1395 int64_t MaxNumNeighborsPerNode(
int num_vehicle_types)
const;
1397 const SavingsParameters savings_params_;
1405 std::function<
bool()> stop_search,
1412 return "SequentialSavingsFilteredHeuristic";
1427 std::function<
bool()> stop_search,
1434 return "ParallelSavingsFilteredHeuristic";
1456 void MergeRoutes(
int first_vehicle,
int second_vehicle, int64_t before_node,
1457 int64_t after_node);
1460 std::vector<int64_t> first_node_on_route_;
1461 std::vector<int64_t> last_node_on_route_;
1465 std::vector<int> vehicle_of_first_or_last_node_;
1475 std::function<
bool()> stop_search,
1477 bool use_minimum_matching);
1481 return "ChristofidesFilteredHeuristic";
1485 const bool use_minimum_matching_;
1492 explicit SweepArranger(absl::Span<
const std::pair<int64_t, int64_t>> points);
1503 std::vector<int> coordinates_;
1511 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() override=default
std::function< int64_t(int64_t, int64_t, int64_t)> evaluator_
std::vector< std::vector< StartEndValue > > ComputeStartEndDistanceForVehicles(absl::Span< const int > vehicles)
int64_t GetEvaluatorInsertionCostForNodeAtPosition(int64_t node_to_insert, int64_t insert_after, int64_t insert_before, int vehicle) const
bool HasHintedNext(int node) const
std::optional< int64_t > GetInsertionCostForPairAtPositions(int64_t pickup_to_insert, int64_t pickup_insert_after, int64_t delivery_to_insert, int64_t delivery_insert_after, int vehicle, int hint_weight=0)
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)
std::vector< EvaluatorCache > evaluator_cache_
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.
int64_t GetUnperformedValue(int64_t node_to_insert) const
std::optional< int64_t > GetInsertionCostForNodeAtPosition(int64_t node_to_insert, int64_t insert_after, int64_t insert_before, int vehicle, int hint_weight=0)
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)
ChristofidesFilteredHeuristic(RoutingModel *model, std::function< bool()> stop_search, LocalSearchFilterManager *filter_manager, bool use_minimum_matching)
bool BuildSolutionInternal() override
Virtual method to redefine how to build a solution.
~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.
FirstSolutionStrategy_Value Value
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, bool is_sequential)
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()
InsertionSequenceIterator end()
void AddInsertionSequence(int vehicle, absl::Span< const Insertion > insertion_sequence)
void AppendPickupDeliveryMultitourInsertions(int pickup, int delivery, int vehicle, absl::Span< const 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
IntVarFilteredDecisionBuilder(std::unique_ptr< IntVarFilteredHeuristic > heuristic)
~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)
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.
virtual uint64_t Size() const =0
This method returns the number of values in the domain of the variable.
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, LocalCheapestInsertionParameters lci_params, 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.
LocalCheapestInsertionParameters_PairInsertionStrategy PairInsertionStrategy
~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)
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()
int64_t Size() const
Returns the number of next variables in the model.
int64_t End(int vehicle) const
Returns the variable index of the ending node of a vehicle route.
operations_research::IntVar * VehicleVar(int64_t index) const
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() 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_
std::unique_ptr< VehicleTypeCurator > vehicle_type_curator_
std::string DebugString() const override
SequentialSavingsFilteredHeuristic(RoutingModel *model, std::function< bool()> stop_search, SavingsParameters parameters, LocalSearchFilterManager *filter_manager)
~SequentialSavingsFilteredHeuristic() override=default
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
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)
int Type(int vehicle) const
dual_gradient T(y - `dual_solution`) class DiagonalTrustRegionProblemFromQp
DecisionBuilder * MakeAllUnperformed(RoutingModel *model)
FirstSolutionStrategy::Value AutomaticFirstSolutionStrategy(bool has_pickup_deliveries, bool has_node_precedences, bool has_single_vehicle_node)
std::vector< int64_t > ComputeVehicleEndChainStarts(const RoutingModel &model)
ClosedInterval::Iterator end(ClosedInterval interval)
const Assignment * SolveFromAssignmentWithAlternativeSolvers(const Assignment *assignment, RoutingModel *primary_model, const std::vector< RoutingModel * > &alternative_models, const RoutingSearchParameters ¶meters, int max_non_improving_iterations)
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)
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
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
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 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