14 #ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_LP_SCHEDULING_H_
15 #define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_LP_SCHEDULING_H_
17 #include "absl/container/flat_hash_map.h"
18 #include "absl/memory/memory.h"
48 return propagated_bounds_[PositiveNode(
index)];
52 const int64 negated_upper_bound = propagated_bounds_[NegativeNode(
index)];
66 static const int kNoParent;
67 static const int kParentToBePropagated;
71 int PositiveNode(
int index)
const {
return 2 *
index; }
72 int NegativeNode(
int index)
const {
return 2 *
index + 1; }
74 void AddNodeToQueue(
int node) {
75 if (!node_in_queue_[node]) {
76 bf_queue_.push_back(node);
77 node_in_queue_[node] =
true;
84 void AddArcs(
int first_index,
int second_index,
int64 offset);
86 bool InitializeArcsAndBounds(
const std::function<
int64(
int64)>& next_accessor,
89 bool UpdateCurrentLowerBoundOfNode(
int node,
int64 new_lb,
int64 offset);
91 bool DisassembleSubtree(
int source,
int target);
93 bool CleanupAndReturnFalse() {
95 for (
int node_to_cleanup : bf_queue_) {
96 node_in_queue_[node_to_cleanup] =
false;
102 const RoutingDimension& dimension_;
103 const int64 num_nodes_;
108 std::vector<std::vector<ArcInfo>> outgoing_arcs_;
110 std::deque<int> bf_queue_;
111 std::vector<bool> node_in_queue_;
112 std::vector<int> tree_parent_node_of_;
116 std::vector<int64> propagated_bounds_;
119 std::vector<int> tmp_dfs_stack_;
122 std::vector<std::pair<int64, int64>>
123 visited_pickup_delivery_indices_for_pair_;
142 int64 upper_bound) = 0;
144 const std::vector<int64>& starts,
145 const std::vector<int64>& ends) = 0;
164 CHECK_LE(lower_bound, upper_bound);
174 const std::vector<std::pair<int, double>>& variable_coeffs) {
175 CHECK_LE(lower_bound, upper_bound);
177 for (
const auto& variable_coeff : variable_coeffs) {
187 const std::vector<std::pair<int, double>>& weighted_variables) {
192 const int under_lower_bound_ct =
199 const int above_upper_bound_ct =
205 const int within_bounds_ct =
208 return within_bounds;
219 linear_program_.
Clear();
221 allowed_intervals_.clear();
227 int64 upper_bound)
override {
228 DCHECK_GE(lower_bound, 0);
232 const int64 kMaxValue = 1e10;
233 const double lp_min = lower_bound;
234 const double lp_max =
236 if (lp_min <= lp_max) {
245 const std::vector<int64>& ends)
override {
250 allowed_intervals_[
index] =
251 absl::make_unique<SortedDisjointIntervalList>(starts, ends);
263 for (glop::ColIndex i(0); i < linear_program_.
num_variables(); ++i) {
287 absl::ToDoubleSeconds(duration_limit));
295 VLOG(2) << linear_program_.
Dump();
299 linear_program_.
Clear();
302 for (
const auto& allowed_interval : allowed_intervals_) {
303 const double value_double =
GetValue(allowed_interval.first);
308 allowed_interval.second.get();
310 if (it == interval_list->
end() ||
value < it->start) {
330 absl::flat_hash_map<int, std::unique_ptr<SortedDisjointIntervalList>>
337 parameters_.set_num_search_workers(1);
340 parameters_.set_cp_model_presolve(
true);
341 parameters_.set_max_presolve_iterations(0);
342 parameters_.set_catch_sigint_signal(
false);
343 parameters_.set_mip_max_bound(1e8);
349 objective_coefficients_.clear();
350 objective_offset_ = 0;
351 variable_offset_.clear();
352 constraint_offset_.clear();
353 first_constraint_to_offset_ = 0;
356 const int index = model_.variables_size();
357 if (
index >= variable_offset_.size()) {
358 variable_offset_.resize(
index + 1, 0);
360 sat::IntegerVariableProto*
const variable = model_.add_variables();
361 variable->add_domain(0);
362 variable->add_domain(
static_cast<int64>(parameters_.mip_max_bound()));
366 int64 upper_bound)
override {
367 DCHECK_GE(lower_bound, 0);
371 variable_offset_[
index] = 0;
372 const int64 offset_upper_bound =
373 std::min<int64>(
CapSub(upper_bound, variable_offset_[
index]),
374 parameters_.mip_max_bound());
375 const int64 offset_lower_bound =
377 if (offset_lower_bound > offset_upper_bound)
return false;
378 sat::IntegerVariableProto*
const variable = model_.mutable_variables(
index);
379 variable->set_domain(0, offset_lower_bound);
380 variable->set_domain(1, offset_upper_bound);
384 const std::vector<int64>& ends)
override {
385 DCHECK_EQ(starts.size(), ends.size());
387 for (
int i = 0; i < starts.size(); ++i) {
393 model_.mutable_constraints(window_ct)->add_enforcement_literal(variable);
402 if (
index >= objective_coefficients_.size()) {
403 objective_coefficients_.resize(
index + 1, 0);
406 sat::CpObjectiveProto*
const objective = model_.mutable_objective();
407 objective->add_vars(
index);
412 return (
index < objective_coefficients_.size())
413 ? objective_coefficients_[
index]
417 model_.mutable_objective()->Clear();
418 objective_offset_ = 0;
422 const int ct_index = model_.constraints_size();
423 if (ct_index >= constraint_offset_.size()) {
424 constraint_offset_.resize(ct_index + 1, 0);
426 sat::LinearConstraintProto*
const ct =
427 model_.add_constraints()->mutable_linear();
428 ct->add_domain(lower_bound);
429 ct->add_domain(upper_bound);
435 sat::LinearConstraintProto*
const ct =
436 model_.mutable_constraints(ct_index)->mutable_linear();
439 constraint_offset_[ct_index] =
440 CapAdd(constraint_offset_[ct_index],
445 sat::LinearArgumentProto*
const ct =
446 model_.add_constraints()->mutable_lin_max();
447 ct->mutable_target()->add_vars(max_var);
448 ct->mutable_target()->add_coeffs(1);
449 for (
const int var : vars) {
450 sat::LinearExpressionProto*
const expr =
ct->add_exprs();
456 sat::IntegerArgumentProto*
const ct =
457 model_.add_constraints()->mutable_int_prod();
458 ct->set_target(product_var);
459 for (
const int var : vars) {
464 DCHECK_LT(
ct, constraint_offset_.size());
465 model_.mutable_constraints(
ct)->add_enforcement_literal(condition);
469 for (
int ct_index = first_constraint_to_offset_;
470 ct_index < constraint_offset_.size(); ++ct_index) {
471 if (!model_.mutable_constraints(ct_index)->has_linear())
continue;
472 sat::LinearConstraintProto*
const ct =
473 model_.mutable_constraints(ct_index)->mutable_linear();
474 ct->set_domain(0,
CapSub(
ct->domain(0), constraint_offset_[ct_index]));
475 ct->set_domain(1,
CapSub(
ct->domain(1), constraint_offset_[ct_index]));
477 first_constraint_to_offset_ = constraint_offset_.size();
478 parameters_.set_max_time_in_seconds(absl::ToDoubleSeconds(duration_limit));
479 VLOG(2) << model_.DebugString();
480 if (hint_.vars_size() == model_.variables_size()) {
481 *model_.mutable_solution_hint() = hint_;
486 VLOG(2) << response_.DebugString();
489 !model_.has_objective())) {
491 for (
int i = 0; i < response_.solution_size(); ++i) {
493 hint_.add_values(response_.solution(i));
504 return response_.solution(
index) + variable_offset_[
index];
509 sat::CpModelProto model_;
510 sat::CpSolverResponse response_;
511 sat::SatParameters parameters_;
512 std::vector<double> objective_coefficients_;
513 double objective_offset_;
514 std::vector<int64> variable_offset_;
515 std::vector<int64> constraint_offset_;
516 int first_constraint_to_offset_;
517 sat::PartialVariableAssignment hint_;
525 bool use_precedence_propagator);
532 int vehicle,
const std::function<
int64(
int64)>& next_accessor,
534 std::vector<int64>* break_values,
int64*
cost,
int64* transit_cost,
535 bool clear_lp =
true);
539 std::vector<int64>* cumul_values,
540 std::vector<int64>* break_values,
int64*
cost,
541 int64* transit_cost,
bool clear_lp =
true);
545 std::vector<int64>* cumul_values,
546 std::vector<int64>* break_values);
549 int vehicle,
const std::function<
int64(
int64)>& next_accessor,
551 std::vector<int64>* break_values);
566 bool ComputeRouteCumulBounds(
const std::vector<int64>& route,
567 const std::vector<int64>& fixed_transits,
574 bool SetRouteCumulConstraints(
575 int vehicle,
const std::function<
int64(
int64)>& next_accessor,
576 int64 cumul_offset,
bool optimize_costs,
578 int64* route_cost_offset);
586 void SetGlobalConstraints(
bool optimize_costs,
589 void SetValuesFromLP(
const std::vector<int>& lp_variables,
int64 offset,
591 std::vector<int64>* lp_values);
602 std::unique_ptr<CumulBoundsPropagator> propagator_;
603 std::vector<int64> current_route_min_cumuls_;
604 std::vector<int64> current_route_max_cumuls_;
607 std::vector<int> current_route_cumul_variables_;
608 std::vector<int> index_to_cumul_variable_;
613 std::vector<int> current_route_break_variables_;
617 std::vector<int> all_break_variables_;
621 std::vector<int> vehicle_to_all_break_variables_offset_;
624 int min_start_cumul_;
625 std::vector<std::pair<int64, int64>>
626 visited_pickup_delivery_indices_for_pair_;
638 RoutingSearchParameters::SchedulingSolver solver_type);
645 int vehicle,
const std::function<
int64(
int64)>& next_accessor,
646 int64* optimal_cost);
651 int vehicle,
const std::function<
int64(
int64)>& next_accessor,
652 int64* optimal_cost_without_transits);
660 int vehicle,
const std::function<
int64(
int64)>& next_accessor,
661 std::vector<int64>* optimal_cumuls, std::vector<int64>* optimal_breaks);
667 int vehicle,
const std::function<
int64(
int64)>& next_accessor,
668 std::vector<int64>* packed_cumuls, std::vector<int64>* packed_breaks);
675 std::vector<std::unique_ptr<RoutingLinearSolverWrapper>> solver_;
688 const std::function<
int64(
int64)>& next_accessor,
689 int64* optimal_cost_without_transits);
696 std::vector<int64>* optimal_cumuls,
697 std::vector<int64>* optimal_breaks);
707 std::vector<int64>* packed_cumuls,
708 std::vector<int64>* packed_breaks);
715 std::unique_ptr<RoutingLinearSolverWrapper> solver_;
721 #endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_LP_SCHEDULING_H_