14#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_FILTERS_H_
15#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_FILTERS_H_
19#include <initializer_list>
24#include "absl/strings/string_view.h"
25#include "absl/types/span.h"
32#include "ortools/constraint_solver/routing_parameters.pb.h"
46 absl::Span<
const std::pair<int64_t, int64_t>> interbreaks);
50 const RoutingModel& routing_model);
54 const RoutingModel& routing_model);
59 const RoutingModel& routing_model);
63 const RoutingModel& routing_model,
bool filter_cost);
67 const RoutingModel& routing_model);
71 const RoutingModel& routing_model);
75 bool propagate_own_objective_value,
76 bool filter_objective_cost,
77 bool may_use_optimizers);
81 const RoutingDimension& dimension);
93 bool propagate_own_objective_value,
bool filter_objective_cost);
162 PathState(
int num_nodes, std::vector<int> path_start,
163 std::vector<int> path_end);
172 int Start(
int path)
const {
return path_start_end_[path].start; }
174 int End(
int path)
const {
return path_start_end_[path].end; }
182 int Path(
int node)
const {
return committed_paths_[node]; }
185 const std::vector<int>&
ChangedPaths()
const {
return changed_paths_; }
187 const std::vector<int>&
ChangedLoops()
const {
return changed_loops_; }
189 ChainRange
Chains(
int path)
const;
191 NodeRange
Nodes(
int path)
const;
200 void ChangePath(
int path, absl::Span<const ChainBounds> chains);
203 void ChangePath(
int path,
const std::initializer_list<ChainBounds>& chains) {
204 changed_paths_.push_back(path);
205 const int path_begin_index = chains_.size();
206 chains_.insert(chains_.end(), chains.begin(), chains.end());
207 const int path_end_index = chains_.size();
208 paths_[path] = {path_begin_index, path_end_index};
210 chains_.emplace_back(0, 0);
232 struct PathStartEnd {
233 PathStartEnd(
int start,
int end) : start(start), end(end) {}
245 void CopyNewPathAtEndOfNodes(
int path);
248 void IncrementalCommit();
254 const int num_nodes_;
255 const int num_paths_;
256 std::vector<PathStartEnd> path_start_end_;
284 std::vector<int> committed_nodes_;
286 std::vector<int> committed_paths_;
288 std::vector<int> committed_index_;
289 const int num_nodes_threshold_;
290 std::vector<ChainBounds> chains_;
291 std::vector<PathBounds> paths_;
294 std::vector<int> changed_paths_;
295 std::vector<int> changed_loops_;
298 bool is_invalid_ =
false;
312 return current_node_ != other.current_node_;
318 explicit Iterator(
const int* node) : current_node_(node) {}
319 const int* current_node_;
324 Chain(
const int* begin_node,
const int* end_node)
325 : begin_(begin_node), end_(end_node) {}
328 int First()
const {
return *begin_; }
329 int Last()
const {
return *(end_ - 1); }
336 const int*
const begin_;
337 const int*
const end_;
350 return {first_node_ + current_chain_->begin_index,
351 first_node_ + current_chain_->end_index};
354 return current_chain_ != other.current_chain_;
360 Iterator(
const ChainBounds* chain,
const int*
const first_node)
361 : current_chain_(chain), first_node_(first_node) {}
363 const int*
const first_node_;
369 const ChainBounds*
const end_chain,
const int*
const first_node)
370 : begin_(begin_chain), end_(end_chain), first_node_(first_node) {}
376 return (begin_ == end_) ? *this :
ChainRange(begin_ + 1, end_, first_node_);
380 return (begin_ == end_) ? *this :
ChainRange(begin_, end_ - 1, first_node_);
386 const int*
const first_node_;
397 if (current_node_ == end_node_) {
403 end_node_ = first_node_ + bounds.
end_index;
409 return current_chain_ != other.current_chain_;
415 Iterator(
const ChainBounds* current_chain,
const int*
const first_node)
416 : current_node_(first_node + current_chain->begin_index),
417 end_node_(first_node + current_chain->end_index),
418 current_chain_(current_chain),
419 first_node_(first_node) {}
420 const int* current_node_;
421 const int* end_node_;
423 const int*
const first_node_;
429 const int* first_node)
430 : begin_chain_(begin_chain),
431 end_chain_(end_chain),
432 first_node_(first_node) {}
441 const int*
const first_node_;
450 std::unique_ptr<PathState> path_state,
451 const std::vector<IntVar*>& nexts);
460 const RoutingModel& routing_model,
const PathState* path_state,
461 const std::vector<PickupDeliveryPair>& pairs,
462 const std::vector<RoutingModel::PickupAndDeliveryPolicy>& vehicle_policies);
489 std::vector<Interval> path_capacity,
490 std::vector<int> path_class,
491 std::vector<std::function<
Interval(int64_t, int64_t)>>
492 demand_per_path_class,
493 std::vector<Interval> node_capacity,
507 inline void UpdateCumulUsingChainRIQ(
int first_index,
int last_index,
515 void IncrementalCommit();
518 void AppendPathDemandsToSums(
int path);
524 void UpdateRIQStructure(
int begin_index,
int end_index);
527 const std::vector<ExtendedInterval> path_capacity_;
528 const std::vector<int> path_class_;
529 const std::vector<std::function<
Interval(int64_t, int64_t)>>
530 demand_per_path_class_;
531 std::vector<ExtendedInterval> cached_demand_;
532 const std::vector<ExtendedInterval> node_capacity_;
538 std::vector<int> index_;
560 std::vector<std::vector<RIQNode>> riq_;
563 const int maximum_riq_layer_size_;
565 const int min_range_size_for_riq_;
576 Solver* solver, std::unique_ptr<DimensionChecker> checker,
577 absl::string_view dimension_name);
606 std::vector<PathData> path_data);
614 std::vector<PathData> path_data_;
618 Solver* solver, std::unique_ptr<LightVehicleBreaksChecker> checker,
619 absl::string_view dimension_name);
718 int TreeSize()
const {
return tree_location_.size(); }
722 elements_.push_back({.height = height, .weight = weight});
740 int end_index)
const;
750 std::vector<Element> elements_;
754 struct TreeLocation {
759 std::vector<TreeLocation> tree_location_;
764 int64_t pivot_height;
766 bool operator<(
const Node& other)
const {
767 return pivot_height < other.pivot_height;
769 bool operator==(
const Node& other)
const {
770 return pivot_height == other.pivot_height;
773 std::vector<Node> nodes_;
786 unsigned int is_left : 1;
801 std::vector<std::vector<ElementInfo>> tree_layers_;
806 struct ElementRange {
807 int range_first_index;
808 int range_last_index;
812 bool range_first_is_node_first;
814 bool Empty()
const {
return range_first_index > range_last_index; }
816 int64_t Sum(
const ElementInfo* elements)
const {
817 return elements[range_last_index].prefix_sum -
818 (range_first_is_node_first
820 : elements[range_first_index - 1].prefix_sum);
823 ElementRange RightSubRange(
const ElementInfo* els,
int pivot_index)
const {
827 (range_first_index - els[range_first_index].left_index),
830 (range_last_index - els[range_last_index].left_index) -
831 static_cast<int>(els[range_last_index].is_left),
832 .range_first_is_node_first =
false};
833 right.range_first_is_node_first = right.range_first_index == pivot_index;
837 ElementRange LeftSubRange(
const ElementInfo* els)
const {
838 return {.range_first_index = els[range_first_index].left_index,
839 .range_last_index = els[range_last_index].left_index -
840 !els[range_last_index].is_left,
841 .range_first_is_node_first = range_first_is_node_first};
862 const PathState* path_state, std::vector<int64_t> force_start_min,
863 std::vector<int64_t> force_end_min, std::vector<int> force_class,
864 std::vector<
const std::function<int64_t(int64_t)>*> force_per_class,
865 std::vector<int> distance_class,
866 std::vector<
const std::function<int64_t(int64_t, int64_t)>*>
868 std::vector<EnergyCost> path_energy_cost,
869 std::vector<bool> path_has_cost_when_empty);
876 int64_t ComputePathCost(int64_t path)
const;
877 void CacheAndPrecomputeRangeQueriesOfPath(
int path);
878 void IncrementalCacheAndPrecompute();
879 void FullCacheAndPrecompute();
882 const std::vector<int64_t> force_start_min_;
883 const std::vector<int64_t> force_end_min_;
884 const std::vector<int> force_class_;
885 const std::vector<int> distance_class_;
886 const std::vector<
const std::function<int64_t(int64_t)>*> force_per_class_;
887 const std::vector<
const std::function<int64_t(int64_t, int64_t)>*>
889 const std::vector<EnergyCost> path_energy_cost_;
890 const std::vector<bool> path_has_cost_when_empty_;
893 const int maximum_range_query_size_;
897 std::vector<int> force_rmq_index_of_node_;
905 std::vector<int> threshold_query_index_of_node_;
907 std::vector<int64_t> cached_force_;
908 std::vector<int64_t> cached_distance_;
911 int64_t committed_total_cost_;
912 int64_t accepted_total_cost_;
913 std::vector<int64_t> committed_path_cost_;
917 Solver* solver, std::unique_ptr<PathEnergyCostChecker> checker,
918 absl::string_view dimension_name);
923 const PathState* path_state,
924 const std::vector<RoutingDimension*>& dimensions,
925 std::vector<LocalSearchFilterManager::FilterEvent>* filters);
928 const std::vector<RoutingDimension*>& dimensions,
929 const RoutingSearchParameters& parameters,
bool filter_objective_cost,
930 bool use_chain_cumul_filter,
931 std::vector<LocalSearchFilterManager::FilterEvent>* filters);
937 BasePathFilter(
const std::vector<IntVar*>& nexts,
int next_domain_size,
938 const PathsMetadata& paths_metadata);
941 int64_t objective_min, int64_t objective_max)
override;
953 for (int64_t start : paths_metadata_.Starts()) {
958 int NumPaths()
const {
return paths_metadata_.NumPaths(); }
959 int64_t
Start(
int i)
const {
return paths_metadata_.Start(i); }
960 int64_t
End(
int i)
const {
return paths_metadata_.End(i); }
961 int GetPath(int64_t node)
const {
return paths_metadata_.GetPath(node); }
962 int Rank(int64_t node)
const {
return ranks_[node]; }
964 return touched_paths_.PositionsSetAtLeastOnce();
968 return new_synchronized_unperformed_nodes_.PositionsSetAtLeastOnce();
974 virtual void OnBeforeSynchronizePaths(
bool) {}
975 virtual void OnAfterSynchronizePaths() {}
976 virtual void OnSynchronizePathFromStart(int64_t) {}
977 virtual bool InitializeAcceptPath() {
return true; }
978 virtual bool AcceptPath(int64_t path_start, int64_t chain_start,
979 int64_t chain_end) = 0;
980 virtual bool FinalizeAcceptPath(int64_t, int64_t) {
return true; }
982 void ComputePathStarts(std::vector<int64_t>* path_starts,
983 std::vector<int>* index_to_path);
984 bool HavePathsChanged();
985 void SynchronizeFullAssignment();
986 void UpdateAllRanks();
987 void UpdatePathRanksFromStart(
int start);
989 const PathsMetadata& paths_metadata_;
990 std::vector<int64_t> node_path_starts_;
991 SparseBitset<int64_t> new_synchronized_unperformed_nodes_;
992 std::vector<int64_t> new_nexts_;
993 std::vector<int> delta_touched_;
994 SparseBitset<> touched_paths_;
996 std::vector<std::pair<int64_t, int64_t> > touched_path_chain_start_ends_;
998 std::vector<int> ranks_;
~BasePathFilter() override=default
static const int64_t kUnassigned
bool lns_detected() const
bool PathStartTouched(int64_t start) const
BasePathFilter(const std::vector< IntVar * > &nexts, int next_domain_size, const PathsMetadata &paths_metadata)
int64_t GetNext(int64_t node) const
const std::vector< int64_t > & GetTouchedPathStarts() const
bool Accept(const Assignment *delta, const Assignment *deltadelta, int64_t objective_min, int64_t objective_max) override
bool HasAnySyncedPath() const
int GetPath(int64_t node) const
int Rank(int64_t node) const
const std::vector< int64_t > & GetNewSynchronizedUnperformedNodes() const
void OnSynchronize(const Assignment *delta) override
int64_t Start(int i) const
DimensionChecker(const PathState *path_state, std::vector< Interval > path_capacity, std::vector< int > path_class, std::vector< std::function< Interval(int64_t, int64_t)> > demand_per_path_class, std::vector< Interval > node_capacity, int min_range_size_for_riq=kOptimalMinRangeSizeForRIQ)
static constexpr int kOptimalMinRangeSizeForRIQ
IntVarLocalSearchFilter(const std::vector< IntVar * > &vars)
int64_t Value(int index) const
bool IsVarSynced(int index) const
LightVehicleBreaksChecker(PathState *path_state, std::vector< PathData > path_data)
PathEnergyCostChecker(const PathState *path_state, std::vector< int64_t > force_start_min, std::vector< int64_t > force_end_min, std::vector< int > force_class, std::vector< const std::function< int64_t(int64_t)> * > force_per_class, std::vector< int > distance_class, std::vector< const std::function< int64_t(int64_t, int64_t)> * > distance_per_class, std::vector< EnergyCost > path_energy_cost, std::vector< bool > path_has_cost_when_empty)
int64_t AcceptedCost() const
int64_t CommittedCost() const
bool operator!=(Iterator other) const
friend class ChainRange
Only a ChainRange can construct its Iterator.
A ChainRange is a range of Chains, committed or not.
ChainRange DropLastChain() const
ChainRange DropFirstChain() const
ChainRange(const ChainBounds *const begin_chain, const ChainBounds *const end_chain, const int *const first_node)
bool operator!=(Iterator other) const
A Chain is a range of committed nodes.
Chain(const int *begin_node, const int *end_node)
Chain WithoutFirstNode() const
bool operator!=(Iterator other) const
friend class NodeRange
Only a NodeRange can construct its Iterator.
NodeRange(const ChainBounds *begin_chain, const ChainBounds *end_chain, const int *first_node)
int NumNodes() const
Instance-constant accessors.
void ChangeLoops(absl::Span< const int > new_loops)
Describes the nodes that are newly loops in this change.
const std::vector< int > & ChangedLoops() const
Returns the set of loops that were added by the change.
void Reset()
Sets all paths to start->end, all other nodes to kUnassigned.
const std::vector< int > & ChangedPaths() const
void Commit()
Set the current state G1 as committed. See class comment for details.
ChainBounds CommittedPathRange(int path) const
ChainRange Chains(int path) const
Returns the current range of chains of path.
static constexpr int kUnassigned
State-dependent accessors.
int NumPaths() const
Returns the number of paths (empty paths included).
void Revert()
Erase incremental changes. See class comment for details.
NodeRange Nodes(int path) const
Returns the current range of nodes of path.
int End(int path) const
Returns the end of a path.
PathState(int num_nodes, std::vector< int > path_start, std::vector< int > path_end)
static constexpr int kLoop
void ChangePath(int path, const std::initializer_list< ChainBounds > &chains)
int CommittedIndex(int node) const
void ChangePath(int path, absl::Span< const ChainBounds > chains)
State modifiers.
int Start(int path) const
Returns the start of a path.
For the time being, Solver is neither MT_SAFE nor MT_HOT.
void MakeTreeFromNewElements()
WeightedWaveletTree()=default
void PushBack(int64_t height, int64_t weight)
Adds an element at index this->Size().
int64_t RangeSumWithThreshold(int64_t threshold_height, int begin_index, int end_index) const
int TreeSize() const
Returns the total number of elements in trees.
In SWIG mode, we don't want anything besides these top-level includes.
IntVarLocalSearchFilter * MakeVehicleAmortizedCostFilter(const RoutingModel &routing_model)
Returns a filter computing vehicle amortized costs.
IntVarLocalSearchFilter * MakeRouteConstraintFilter(const RoutingModel &routing_model)
Returns a filter tracking route constraints.
LocalSearchFilter * MakePickupDeliveryFilter(const RoutingModel &routing_model, const PathState *path_state, const std::vector< PickupDeliveryPair > &pairs, const std::vector< RoutingModel::PickupAndDeliveryPolicy > &vehicle_policies)
IntVarLocalSearchFilter * MakeMaxActiveVehiclesFilter(const RoutingModel &routing_model)
Returns a filter ensuring that max active vehicles constraints are enforced.
void AppendLightWeightDimensionFilters(const PathState *path_state, const std::vector< RoutingDimension * > &dimensions, std::vector< LocalSearchFilterManager::FilterEvent > *filters)
IntVarLocalSearchFilter * MakeNodeDisjunctionFilter(const RoutingModel &routing_model, bool filter_cost)
Returns a filter ensuring that node disjunction constraints are enforced.
LocalSearchFilter * MakePathEnergyCostFilter(Solver *solver, std::unique_ptr< PathEnergyCostChecker > checker, absl::string_view dimension_name)
IntVarLocalSearchFilter * MakeCumulBoundsPropagatorFilter(const RoutingDimension &dimension)
Returns a filter handling dimension cumul bounds.
LocalSearchFilter * MakePathStateFilter(Solver *solver, std::unique_ptr< PathState > path_state, const std::vector< IntVar * > &nexts)
LocalSearchFilter * MakeLightVehicleBreaksFilter(Solver *solver, std::unique_ptr< LightVehicleBreaksChecker > checker, absl::string_view dimension_name)
IntVarLocalSearchFilter * MakePathCumulFilter(const RoutingDimension &dimension, bool propagate_own_objective_value, bool filter_objective_cost, bool may_use_optimizers)
Returns a filter handling dimension costs and constraints.
IntVarLocalSearchFilter * MakeCPFeasibilityFilter(RoutingModel *routing_model)
Returns a filter checking the current solution using CP propagation.
LocalSearchFilter * MakeVehicleVarFilter(const RoutingModel &routing_model, const PathState *path_state)
Returns a filter checking that vehicle variable domains are respected.
void AppendDimensionCumulFilters(const std::vector< RoutingDimension * > &dimensions, const RoutingSearchParameters ¶meters, bool filter_objective_cost, bool use_chain_cumul_filter, std::vector< LocalSearchFilterManager::FilterEvent > *filters)
LocalSearchFilter * MakeResourceAssignmentFilter(LocalDimensionCumulOptimizer *lp_optimizer, LocalDimensionCumulOptimizer *mp_optimizer, bool propagate_own_objective_value, bool filter_objective_cost)
bool PropagateLightweightVehicleBreaks(int path, DimensionValues &dimension_values, absl::Span< const std::pair< int64_t, int64_t > > interbreaks)
IntVarLocalSearchFilter * MakeTypeRegulationsFilter(const RoutingModel &routing_model)
Returns a filter ensuring type regulation constraints are enforced.
IntVarLocalSearchFilter * MakeGlobalLPCumulFilter(GlobalDimensionCumulOptimizer *lp_optimizer, GlobalDimensionCumulOptimizer *mp_optimizer, bool filter_objective_cost)
Returns a filter checking global linear constraints and costs.
util_intops::StrongIntRange< ElementIndex > ElementRange
IntVarLocalSearchFilter * MakeActiveNodeGroupFilter(const RoutingModel &routing_model)
LocalSearchFilter * MakeDimensionFilter(Solver *solver, std::unique_ptr< DimensionChecker > checker, absl::string_view dimension_name)
int64_t num_positive_infinity
int64_t num_negative_infinity
int64_t max_interbreak_duration
int64_t min_break_duration
std::vector< VehicleBreak > vehicle_breaks
LocalSearchState::Variable start_cumul
LocalSearchState::Variable end_cumul
std::vector< InterbreakLimit > interbreak_limits
LocalSearchState::Variable total_transit
LocalSearchState::Variable span
int64_t cost_per_unit_above_threshold
int64_t cost_per_unit_below_threshold
ChainBounds(int begin_index, int end_index)
static const int64_t kint64max