14#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_LP_SCHEDULING_H_
15#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_LP_SCHEDULING_H_
28#include "absl/container/flat_hash_map.h"
29#include "absl/memory/memory.h"
30#include "absl/time/time.h"
64 const std::function<int64_t(int64_t)>& next_accessor,
65 int64_t cumul_offset);
68 return propagated_bounds_[PositiveNode(
index)];
72 const int64_t negated_upper_bound = propagated_bounds_[NegativeNode(
index)];
75 : -negated_upper_bound;
88 static const int kNoParent;
89 static const int kParentToBePropagated;
93 int PositiveNode(
int index)
const {
return 2 *
index; }
94 int NegativeNode(
int index)
const {
return 2 *
index + 1; }
96 void AddNodeToQueue(
int node) {
97 if (!node_in_queue_[node]) {
98 bf_queue_.push_back(node);
99 node_in_queue_[node] =
true;
106 void AddArcs(
int first_index,
int second_index, int64_t offset);
108 bool InitializeArcsAndBounds(
109 const std::function<int64_t(int64_t)>& next_accessor,
110 int64_t cumul_offset);
112 bool UpdateCurrentLowerBoundOfNode(
int node, int64_t new_lb, int64_t offset);
114 bool DisassembleSubtree(
int source,
int target);
116 bool CleanupAndReturnFalse() {
118 for (
int node_to_cleanup : bf_queue_) {
119 node_in_queue_[node_to_cleanup] =
false;
125 const RoutingDimension& dimension_;
126 const int64_t num_nodes_;
131 std::vector<std::vector<ArcInfo>> outgoing_arcs_;
133 std::deque<int> bf_queue_;
134 std::vector<bool> node_in_queue_;
135 std::vector<int> tree_parent_node_of_;
139 std::vector<int64_t> propagated_bounds_;
142 std::vector<int> tmp_dfs_stack_;
145 std::vector<std::pair<int64_t, int64_t>>
146 visited_pickup_delivery_indices_for_pair_;
167 const std::vector<int64_t>& starts,
168 const std::vector<int64_t>& ends) = 0;
198 const std::vector<std::pair<int, double>>& variable_coeffs) {
201 for (
const auto& variable_coeff : variable_coeffs) {
211 const std::vector<std::pair<int, double>>& weighted_variables) {
216 const int under_lower_bound_ct =
231 const int within_bounds_ct =
234 return within_bounds;
241 : is_relaxation_(is_relaxation) {
246 linear_program_.
Clear();
248 allowed_intervals_.clear();
259 const int64_t kMaxValue = 1e10;
261 const double lp_max =
263 if (lp_min <= lp_max) {
272 const std::vector<int64_t>& ends)
override {
277 allowed_intervals_[
index] =
278 absl::make_unique<SortedDisjointIntervalList>(starts, ends);
290 for (glop::ColIndex i(0); i < linear_program_.
num_variables(); ++i) {
314 for (
int variable = 0; variable <
NumVariables(); variable++) {
326 absl::ToDoubleSeconds(duration_limit));
338 linear_program_.
Clear();
341 if (is_relaxation_) {
344 for (
const auto& allowed_interval : allowed_intervals_) {
345 const double value_double =
GetValue(allowed_interval.first);
346 const int64_t
value =
351 allowed_interval.second.get();
353 if (it == interval_list->
end() || value < it->start) {
371 const bool is_relaxation_;
374 absl::flat_hash_map<int, std::unique_ptr<SortedDisjointIntervalList>>
394 objective_coefficients_.clear();
395 variable_offset_.clear();
396 constraint_offset_.clear();
397 first_constraint_to_offset_ = 0;
401 if (
index >= variable_offset_.size()) {
402 variable_offset_.resize(
index + 1, 0);
415 variable_offset_[
index] = 0;
416 const int64_t offset_upper_bound =
419 const int64_t offset_lower_bound =
421 if (offset_lower_bound > offset_upper_bound)
return false;
428 const std::vector<int64_t>& ends)
override {
431 for (
int i = 0; i < starts.size(); ++i) {
446 if (
index >= objective_coefficients_.size()) {
447 objective_coefficients_.resize(
index + 1, 0);
457 return (
index < objective_coefficients_.size())
458 ? objective_coefficients_[
index]
465 if (ct_index >= constraint_offset_.size()) {
466 constraint_offset_.resize(ct_index + 1, 0);
481 constraint_offset_[ct_index] =
482 CapAdd(constraint_offset_[ct_index],
487 const double scaling_factor =
495 for (
int i = 0; i < objective.
vars_size(); ++i) {
502 ct->mutable_target()->add_vars(max_var);
503 ct->mutable_target()->add_coeffs(1);
504 for (
const int var : vars) {
513 ct->set_target(product_var);
514 for (
const int var : vars) {
524 for (
int ct_index = first_constraint_to_offset_;
525 ct_index < constraint_offset_.size(); ++ct_index) {
529 ct->set_domain(0,
CapSub(
ct->domain(0), constraint_offset_[ct_index]));
530 ct->set_domain(1,
CapSub(
ct->domain(1), constraint_offset_[ct_index]));
532 first_constraint_to_offset_ = constraint_offset_.size();
537 for (int64_t coeff : objective->
coeffs()) {
541 for (
int i = 0; i < objective->
coeffs_size(); ++i) {
549 VLOG(2) << model_.DebugString();
556 VLOG(2) << response_.DebugString();
581 std::vector<double> objective_coefficients_;
582 std::vector<int64_t> variable_offset_;
583 std::vector<int64_t> constraint_offset_;
584 int first_constraint_to_offset_;
593 bool use_precedence_propagator);
600 int vehicle,
const std::function<int64_t(int64_t)>& next_accessor,
602 std::vector<int64_t>* break_values, int64_t*
cost, int64_t* transit_cost,
603 bool clear_lp =
true);
606 const std::function<int64_t(int64_t)>& next_accessor,
608 std::vector<int64_t>* break_values, int64_t*
cost, int64_t* transit_cost,
609 bool clear_lp =
true);
612 const std::function<int64_t(int64_t)>& next_accessor,
614 std::vector<int64_t>* break_values);
617 int vehicle,
const std::function<int64_t(int64_t)>& next_accessor,
619 std::vector<int64_t>* break_values);
634 bool ComputeRouteCumulBounds(
const std::vector<int64_t>& route,
635 const std::vector<int64_t>& fixed_transits,
636 int64_t cumul_offset);
642 bool SetRouteCumulConstraints(
643 int vehicle,
const std::function<int64_t(int64_t)>& next_accessor,
644 int64_t cumul_offset,
bool optimize_costs,
646 int64_t* route_cost_offset);
654 void SetGlobalConstraints(
655 const std::function<int64_t(int64_t)>& next_accessor,
656 int64_t cumul_offset,
bool optimize_costs,
659 void SetValuesFromLP(
const std::vector<int>& lp_variables, int64_t offset,
661 std::vector<int64_t>* lp_values);
672 std::unique_ptr<CumulBoundsPropagator> propagator_;
673 std::vector<int64_t> current_route_min_cumuls_;
674 std::vector<int64_t> current_route_max_cumuls_;
677 std::vector<int> current_route_cumul_variables_;
678 std::vector<int> index_to_cumul_variable_;
683 std::vector<int> current_route_break_variables_;
687 std::vector<int> all_break_variables_;
691 std::vector<int> vehicle_to_all_break_variables_offset_;
694 int min_start_cumul_;
695 std::vector<std::pair<int64_t, int64_t>>
696 visited_pickup_delivery_indices_for_pair_;
715 int vehicle,
const std::function<int64_t(int64_t)>& next_accessor,
716 int64_t* optimal_cost);
721 int vehicle,
const std::function<int64_t(int64_t)>& next_accessor,
722 int64_t* optimal_cost_without_transits);
730 int vehicle,
const std::function<int64_t(int64_t)>& next_accessor,
731 std::vector<int64_t>* optimal_cumuls,
732 std::vector<int64_t>* optimal_breaks);
738 int vehicle,
const std::function<int64_t(int64_t)>& next_accessor,
739 std::vector<int64_t>* packed_cumuls, std::vector<int64_t>* packed_breaks);
746 std::vector<std::unique_ptr<RoutingLinearSolverWrapper>> solver_;
761 const std::function<int64_t(int64_t)>& next_accessor,
762 int64_t* optimal_cost_without_transits);
769 const std::function<int64_t(int64_t)>& next_accessor,
770 std::vector<int64_t>* optimal_cumuls,
771 std::vector<int64_t>* optimal_breaks);
777 const std::function<int64_t(int64_t)>& next_accessor,
778 std::vector<int64_t>* packed_cumuls, std::vector<int64_t>* packed_breaks);
785 std::unique_ptr<RoutingLinearSolverWrapper> solver_;
#define DCHECK_GE(val1, val2)
#define DCHECK_LT(val1, val2)
#define CHECK_LE(val1, val2)
#define DCHECK_EQ(val1, val2)
#define VLOG(verboselevel)
const RoutingDimension & dimension() const
int64_t CumulMax(int index) const
bool PropagateCumulBounds(const std::function< int64_t(int64_t)> &next_accessor, int64_t cumul_offset)
int64_t CumulMin(int index) const
CumulBoundsPropagator(const RoutingDimension *dimension)
DimensionCumulOptimizerCore(const RoutingDimension *dimension, bool use_precedence_propagator)
const RoutingDimension * dimension() const
DimensionSchedulingStatus OptimizeAndPackSingleRoute(int vehicle, const std::function< int64_t(int64_t)> &next_accessor, RoutingLinearSolverWrapper *solver, std::vector< int64_t > *cumul_values, std::vector< int64_t > *break_values)
DimensionSchedulingStatus OptimizeAndPack(const std::function< int64_t(int64_t)> &next_accessor, RoutingLinearSolverWrapper *solver, std::vector< int64_t > *cumul_values, std::vector< int64_t > *break_values)
DimensionSchedulingStatus Optimize(const std::function< int64_t(int64_t)> &next_accessor, RoutingLinearSolverWrapper *solver, std::vector< int64_t > *cumul_values, std::vector< int64_t > *break_values, int64_t *cost, int64_t *transit_cost, bool clear_lp=true)
DimensionSchedulingStatus OptimizeSingleRoute(int vehicle, const std::function< int64_t(int64_t)> &next_accessor, RoutingLinearSolverWrapper *solver, std::vector< int64_t > *cumul_values, std::vector< int64_t > *break_values, int64_t *cost, int64_t *transit_cost, bool clear_lp=true)
GlobalDimensionCumulOptimizer(const RoutingDimension *dimension, RoutingSearchParameters::SchedulingSolver solver_type)
DimensionSchedulingStatus ComputeCumulCostWithoutFixedTransits(const std::function< int64_t(int64_t)> &next_accessor, int64_t *optimal_cost_without_transits)
const RoutingDimension * dimension() const
DimensionSchedulingStatus ComputeCumuls(const std::function< int64_t(int64_t)> &next_accessor, std::vector< int64_t > *optimal_cumuls, std::vector< int64_t > *optimal_breaks)
DimensionSchedulingStatus ComputePackedCumuls(const std::function< int64_t(int64_t)> &next_accessor, std::vector< int64_t > *packed_cumuls, std::vector< int64_t > *packed_breaks)
DimensionSchedulingStatus ComputeRouteCumulCost(int vehicle, const std::function< int64_t(int64_t)> &next_accessor, int64_t *optimal_cost)
DimensionSchedulingStatus ComputeRouteCumuls(int vehicle, const std::function< int64_t(int64_t)> &next_accessor, std::vector< int64_t > *optimal_cumuls, std::vector< int64_t > *optimal_breaks)
DimensionSchedulingStatus ComputeRouteCumulCostWithoutFixedTransits(int vehicle, const std::function< int64_t(int64_t)> &next_accessor, int64_t *optimal_cost_without_transits)
LocalDimensionCumulOptimizer(const RoutingDimension *dimension, RoutingSearchParameters::SchedulingSolver solver_type)
const RoutingDimension * dimension() const
DimensionSchedulingStatus ComputePackedRouteCumuls(int vehicle, const std::function< int64_t(int64_t)> &next_accessor, std::vector< int64_t > *packed_cumuls, std::vector< int64_t > *packed_breaks)
static int64_t FastInt64Round(double x)
static int64_t GCD64(int64_t x, int64_t y)
void SetCoefficient(int ct_index, int index, double coefficient) override
int NumVariables() const override
bool IsCPSATSolver() override
int CreateNewPositiveVariable() override
bool SetVariableBounds(int index, int64_t lower_bound, int64_t upper_bound) override
double GetValue(int index) const override
int64_t GetObjectiveValue() const override
DimensionSchedulingStatus Solve(absl::Duration duration_limit) override
~RoutingCPSatWrapper() override
void AddMaximumConstraint(int max_var, std::vector< int > vars) override
void AddProductConstraint(int product_var, std::vector< int > vars) override
void SetEnforcementLiteral(int ct, int condition) override
double GetObjectiveCoefficient(int index) const override
void AddObjectiveConstraint() override
void SetVariableDisjointBounds(int index, const std::vector< int64_t > &starts, const std::vector< int64_t > &ends) override
bool SolutionIsInteger() const override
int CreateNewConstraint(int64_t lower_bound, int64_t upper_bound) override
void SetObjectiveCoefficient(int index, double coefficient) override
int64_t GetVariableLowerBound(int index) const override
void ClearObjective() override
Dimensions represent quantities accumulated at nodes along the routes.
int NumVariables() const override
bool IsCPSATSolver() override
RoutingGlopWrapper(bool is_relaxation, const glop::GlopParameters ¶meters)
int CreateNewPositiveVariable() override
bool SetVariableBounds(int index, int64_t lower_bound, int64_t upper_bound) override
double GetValue(int index) const override
int64_t GetObjectiveValue() const override
DimensionSchedulingStatus Solve(absl::Duration duration_limit) override
void SetCoefficient(int ct, int index, double coefficient) override
void AddMaximumConstraint(int max_var, std::vector< int > vars) override
void AddProductConstraint(int product_var, std::vector< int > vars) override
void SetEnforcementLiteral(int ct, int condition) override
double GetObjectiveCoefficient(int index) const override
void AddObjectiveConstraint() override
void SetVariableDisjointBounds(int index, const std::vector< int64_t > &starts, const std::vector< int64_t > &ends) override
bool SolutionIsInteger() const override
int CreateNewConstraint(int64_t lower_bound, int64_t upper_bound) override
void SetObjectiveCoefficient(int index, double coefficient) override
int64_t GetVariableLowerBound(int index) const override
void ClearObjective() override
virtual void SetCoefficient(int ct, int index, double coefficient)=0
virtual int NumVariables() const =0
int AddReifiedLinearConstraint(int64_t lower_bound, int64_t upper_bound, const std::vector< std::pair< int, double > > &weighted_variables)
virtual double GetObjectiveCoefficient(int index) const =0
virtual void AddProductConstraint(int product_var, std::vector< int > vars)=0
virtual int CreateNewPositiveVariable()=0
int AddVariable(int64_t lower_bound, int64_t upper_bound)
virtual bool IsCPSATSolver()=0
virtual int64_t GetObjectiveValue() const =0
virtual void AddObjectiveConstraint()=0
virtual void ClearObjective()=0
virtual int CreateNewConstraint(int64_t lower_bound, int64_t upper_bound)=0
int AddLinearConstraint(int64_t lower_bound, int64_t upper_bound, const std::vector< std::pair< int, double > > &variable_coeffs)
virtual double GetValue(int index) const =0
virtual DimensionSchedulingStatus Solve(absl::Duration duration_limit)=0
virtual void SetVariableDisjointBounds(int index, const std::vector< int64_t > &starts, const std::vector< int64_t > &ends)=0
virtual bool SetVariableBounds(int index, int64_t lower_bound, int64_t upper_bound)=0
virtual void SetObjectiveCoefficient(int index, double coefficient)=0
virtual void SetEnforcementLiteral(int ct, int condition)=0
virtual bool SolutionIsInteger() const =0
virtual ~RoutingLinearSolverWrapper()
virtual int64_t GetVariableLowerBound(int index) const =0
virtual void AddMaximumConstraint(int max_var, std::vector< int > vars)=0
This class represents a sorted list of disjoint, closed intervals.
ConstIterator end() const
Iterator FirstIntervalGreaterOrEqual(int64_t value) const
Returns an iterator to either:
void set_max_time_in_seconds(double value)
GlopParameters * GetMutableParameters()
Fractional GetObjectiveValue() const
const DenseRow & variable_values() const
ABSL_MUST_USE_RESULT ProblemStatus Solve(const LinearProgram &lp)
void SetParameters(const GlopParameters ¶meters)
void SetVariableBounds(ColIndex col, Fractional lower_bound, Fractional upper_bound)
void SetCoefficient(RowIndex row, ColIndex col, Fractional value)
void SetConstraintBounds(RowIndex row, Fractional lower_bound, Fractional upper_bound)
ColIndex CreateNewVariable()
bool SolutionIsInteger(const DenseRow &solution, Fractional absolute_tolerance) const
const DenseRow & objective_coefficients() const
void NotifyThatColumnsAreClean()
void SetObjectiveCoefficient(ColIndex col, Fractional value)
ColIndex num_variables() const
RowIndex CreateNewConstraint()
const DenseRow & variable_lower_bounds() const
void SetMaximizationProblem(bool maximize)
::operations_research::sat::LinearArgumentProto * mutable_lin_max()
::operations_research::sat::IntegerArgumentProto * mutable_int_prod()
void add_enforcement_literal(::PROTOBUF_NAMESPACE_ID::int32 value)
::operations_research::sat::LinearConstraintProto * mutable_linear()
const ::operations_research::sat::CpObjectiveProto & objective() const
const ::operations_research::sat::IntegerVariableProto & variables(int index) const
bool has_objective() const
::operations_research::sat::PartialVariableAssignment * mutable_solution_hint()
::operations_research::sat::ConstraintProto * mutable_constraints(int index)
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final
::operations_research::sat::IntegerVariableProto * mutable_variables(int index)
int variables_size() const
::operations_research::sat::ConstraintProto * add_constraints()
::operations_research::sat::IntegerVariableProto * add_variables()
::operations_research::sat::CpObjectiveProto * mutable_objective()
int constraints_size() const
::PROTOBUF_NAMESPACE_ID::int64 coeffs(int index) const
void add_coeffs(::PROTOBUF_NAMESPACE_ID::int64 value)
double scaling_factor() const
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final
void set_coeffs(int index, ::PROTOBUF_NAMESPACE_ID::int64 value)
void set_offset(double value)
::PROTOBUF_NAMESPACE_ID::int32 vars(int index) const
void add_vars(::PROTOBUF_NAMESPACE_ID::int32 value)
void set_scaling_factor(double value)
int solution_size() const
double objective_value() const
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final
::operations_research::sat::CpSolverStatus status() const
::PROTOBUF_NAMESPACE_ID::int64 solution(int index) const
void add_domain(::PROTOBUF_NAMESPACE_ID::int64 value)
::PROTOBUF_NAMESPACE_ID::int64 domain(int index) const
void set_domain(int index, ::PROTOBUF_NAMESPACE_ID::int64 value)
void add_coeffs(::PROTOBUF_NAMESPACE_ID::int64 value)
void add_vars(::PROTOBUF_NAMESPACE_ID::int32 value)
Class that owns everything related to a particular optimization model.
void add_values(::PROTOBUF_NAMESPACE_ID::int64 value)
PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final
void add_vars(::PROTOBUF_NAMESPACE_ID::int32 value)
void set_catch_sigint_signal(bool value)
void set_search_branching(::operations_research::sat::SatParameters_SearchBranching value)
void set_cp_model_presolve(bool value)
void set_max_presolve_iterations(::PROTOBUF_NAMESPACE_ID::int32 value)
static constexpr SearchBranching LP_SEARCH
double mip_max_bound() const
void set_max_time_in_seconds(double value)
void set_mip_max_bound(double value)
void set_num_search_workers(::PROTOBUF_NAMESPACE_ID::int32 value)
std::function< SatParameters(Model *)> NewSatParameters(const std::string ¶ms)
Creates parameters for the solver, which you can add to the model with.
CpSolverResponse SolveCpModel(const CpModelProto &model_proto, Model *model)
Solves the given CpModelProto.
Collection of objects used to extend the Constraint Solver library.
int64_t CapAdd(int64_t x, int64_t y)
int64_t CapSub(int64_t x, int64_t y)
RoutingSearchParameters_SchedulingSolver
DimensionSchedulingStatus
int64_t CapProd(int64_t x, int64_t y)