17#include <initializer_list>
22#include "absl/container/flat_hash_map.h"
23#include "absl/strings/str_cat.h"
24#include "absl/strings/str_format.h"
25#include "absl/types/span.h"
27#include "ortools/sat/cp_model.pb.h"
37 : builder_(builder), index_(
index) {}
40 DCHECK(builder_ !=
nullptr);
41 if (builder_ ==
nullptr)
return *
this;
49 if (builder_ ==
nullptr)
return "null";
50 const std::string&
name =
55 return absl::StrCat(
"Not(",
name,
")");
60 if (builder_ ==
nullptr)
return "null";
65 const IntegerVariableProto& var_proto = builder_->
Proto().variables(index_);
67 if (var_proto.name().empty() && var_proto.domain_size() == 2 &&
68 var_proto.domain(0) == var_proto.domain(1)) {
69 output.append(var_proto.domain(0) == 0 ?
"false" :
"true");
71 if (var_proto.name().empty()) {
72 absl::StrAppendFormat(&output,
"BoolVar%i(", index_);
74 absl::StrAppendFormat(&output,
"%s(", var_proto.name());
76 if (var_proto.domain(0) == var_proto.domain(1)) {
77 output.append(var_proto.domain(0) == 0 ?
"false)" :
"true)");
79 absl::StrAppend(&output, var_proto.domain(0),
", ", var_proto.domain(1),
97 : builder_(builder), index_(
index) {
102 if (
var.builder_ ==
nullptr) {
106 builder_ =
var.builder_;
107 index_ = builder_->GetOrCreateIntegerIndex(
var.index_);
112 if (builder_ !=
nullptr) {
113 const IntegerVariableProto&
proto = builder_->
Proto().variables(index_);
118 return BoolVar(index_, builder_);
122 DCHECK(builder_ !=
nullptr);
123 if (builder_ ==
nullptr)
return *
this;
129 if (builder_ ==
nullptr)
return "null";
130 return builder_->
Proto().variables(index_).name();
134 if (builder_ ==
nullptr)
return Domain();
139 if (builder_ ==
nullptr)
return "null";
149 const IntegerVariableProto& var_proto =
proto.variables(
index);
150 if (var_proto.name().empty() && var_proto.domain_size() == 2 &&
151 var_proto.domain(0) == var_proto.domain(1)) {
152 absl::StrAppend(&output, var_proto.domain(0));
154 if (var_proto.name().empty()) {
155 absl::StrAppend(&output,
"V",
index,
"(");
157 absl::StrAppend(&output, var_proto.name(),
"(");
161 if (var_proto.domain_size() == 2 &&
162 var_proto.domain(0) == var_proto.domain(1)) {
163 absl::StrAppend(&output, var_proto.domain(0),
")");
165 absl::StrAppend(&output, var_proto.domain(0),
", ", var_proto.domain(1),
182 variables_.push_back(
index);
183 coefficients_.push_back(1);
187 coefficients_.push_back(-1);
194 variables_.push_back(
var.index_);
195 coefficients_.push_back(1);
202 for (
int i = 0; i < expr_proto.vars_size(); ++i) {
203 result.variables_.push_back(expr_proto.vars(i));
204 result.coefficients_.push_back(expr_proto.coeffs(i));
226 absl::Span<const int64_t> coeffs) {
227 CHECK_EQ(vars.size(), coeffs.size());
229 for (
int i = 0; i < vars.size(); ++i) {
230 result += vars[i] * coeffs[i];
236 absl::Span<const int64_t> coeffs) {
237 CHECK_EQ(vars.size(), coeffs.size());
239 for (
int i = 0; i < vars.size(); ++i) {
240 result += vars[i] * coeffs[i];
258 constant_ += other.constant_;
259 variables_.insert(variables_.end(), other.variables_.begin(),
260 other.variables_.end());
261 coefficients_.insert(coefficients_.end(), other.coefficients_.begin(),
262 other.coefficients_.end());
267 constant_ -= other.constant_;
268 variables_.insert(variables_.end(), other.variables_.begin(),
269 other.variables_.end());
270 for (
const int64_t
coeff : other.coefficients_) {
271 coefficients_.push_back(-
coeff);
278 for (int64_t&
coeff : coefficients_)
coeff *= factor;
284 for (
int i = 0; i < variables_.size(); ++i) {
285 const int64_t
coeff = coefficients_[i];
286 const std::string var_string =
proto ==
nullptr
287 ? absl::StrCat(
"V", variables_[i])
291 absl::StrAppend(&result, var_string);
292 }
else if (
coeff == -1) {
293 absl::StrAppend(&result,
"-", var_string);
294 }
else if (
coeff != 0) {
295 absl::StrAppend(&result,
coeff,
" * ", var_string);
297 }
else if (
coeff == 1) {
298 absl::StrAppend(&result,
" + ", var_string);
299 }
else if (
coeff > 0) {
300 absl::StrAppend(&result,
" + ",
coeff,
" * ", var_string);
301 }
else if (
coeff == -1) {
302 absl::StrAppend(&result,
" - ", var_string);
303 }
else if (
coeff < 0) {
304 absl::StrAppend(&result,
" - ", -
coeff,
" * ", var_string);
308 if (constant_ != 0) {
309 if (variables_.empty()) {
310 return absl::StrCat(constant_);
311 }
else if (constant_ > 0) {
312 absl::StrAppend(&result,
" + ", constant_);
314 absl::StrAppend(&result,
" - ", -constant_);
350 absl::Span<const IntVar> vars, absl::Span<const double> coeffs) {
351 CHECK_EQ(vars.size(), coeffs.size());
353 for (
int i = 0; i < vars.size(); ++i) {
354 result.
AddTerm(vars[i], coeffs[i]);
360 absl::Span<const BoolVar> vars, absl::Span<const double> coeffs) {
361 CHECK_EQ(vars.size(), coeffs.size());
363 for (
int i = 0; i < vars.size(); ++i) {
364 result.
AddTerm(vars[i], coeffs[i]);
385 constant_ += expr.constant_;
386 variables_.insert(variables_.end(), expr.variables_.begin(),
387 expr.variables_.end());
388 coefficients_.insert(coefficients_.end(), expr.coefficients_.begin(),
389 expr.coefficients_.end());
394 variables_.push_back(
var.index_);
395 coefficients_.push_back(
coeff);
402 variables_.push_back(
index);
403 coefficients_.push_back(
coeff);
406 coefficients_.push_back(-
coeff);
423 constant_ -= expr.constant_;
424 variables_.insert(variables_.end(), expr.variables_.begin(),
425 expr.variables_.end());
427 coefficients_.push_back(-
coeff);
434 for (
double& c : coefficients_) {
442 for (
int i = 0; i < variables_.size(); ++i) {
443 const double coeff = coefficients_[i];
444 const std::string var_string =
proto ==
nullptr
445 ? absl::StrCat(
"V", variables_[i])
449 absl::StrAppend(&result, var_string);
450 }
else if (
coeff == -1.0) {
451 absl::StrAppend(&result,
"-", var_string);
452 }
else if (
coeff != 0.0) {
453 absl::StrAppend(&result,
coeff,
" * ", var_string);
455 }
else if (
coeff == 1.0) {
456 absl::StrAppend(&result,
" + ", var_string);
457 }
else if (
coeff > 0.0) {
458 absl::StrAppend(&result,
" + ",
coeff,
" * ", var_string);
459 }
else if (
coeff == -1.0) {
460 absl::StrAppend(&result,
" - ", var_string);
461 }
else if (
coeff < 0.0) {
462 absl::StrAppend(&result,
" - ", -
coeff,
" * ", var_string);
466 if (constant_ != 0.0) {
467 if (variables_.empty()) {
468 return absl::StrCat(constant_);
469 }
else if (constant_ > 0.0) {
470 absl::StrAppend(&result,
" + ", constant_);
472 absl::StrAppend(&result,
" - ", -constant_);
494 proto_->add_enforcement_literal(
var.index_);
518 for (
const int64_t t : tuple) {
519 proto_->mutable_table()->add_values(t);
523ReservoirConstraint::ReservoirConstraint(ConstraintProto*
proto,
528 *
proto_->mutable_reservoir()->add_time_exprs() =
529 builder_->LinearExprToProto(
time);
530 proto_->mutable_reservoir()->add_level_changes(level_change);
531 proto_->mutable_reservoir()->add_active_literals(
532 builder_->IndexFromConstant(1));
536 int64_t level_change,
538 *
proto_->mutable_reservoir()->add_time_exprs() =
539 builder_->LinearExprToProto(
time);
540 proto_->mutable_reservoir()->add_level_changes(level_change);
541 proto_->mutable_reservoir()->add_active_literals(is_active.index_);
545 int64_t transition_label) {
546 proto_->mutable_automaton()->add_transition_tail(
tail);
547 proto_->mutable_automaton()->add_transition_head(
head);
548 proto_->mutable_automaton()->add_transition_label(transition_label);
553 proto_->mutable_no_overlap_2d()->add_x_intervals(x_coordinate.index_);
554 proto_->mutable_no_overlap_2d()->add_y_intervals(y_coordinate.index_);
557CumulativeConstraint::CumulativeConstraint(ConstraintProto*
proto,
563 *
proto_->mutable_cumulative()->add_demands() =
564 builder_->LinearExprToProto(
demand);
570 : builder_(builder), index_(
index) {}
573 DCHECK(builder_ !=
nullptr);
574 if (builder_ ==
nullptr)
return *
this;
580 DCHECK(builder_ !=
nullptr);
583 builder_->
Proto().constraints(index_).interval().start());
587 DCHECK(builder_ !=
nullptr);
590 builder_->
Proto().constraints(index_).interval().size());
594 DCHECK(builder_ !=
nullptr);
597 builder_->
Proto().constraints(index_).interval().end());
601 DCHECK(builder_ !=
nullptr);
602 if (builder_ ==
nullptr)
return BoolVar();
603 return BoolVar(builder_->
Proto().constraints(index_).enforcement_literal(0),
608 if (builder_ ==
nullptr)
return "null";
609 return builder_->
Proto().constraints(index_).name();
613 if (builder_ ==
nullptr)
return "null";
616 const CpModelProto&
proto = builder_->
Proto();
617 const ConstraintProto& ct_proto =
proto.constraints(index_);
619 if (ct_proto.name().empty()) {
620 absl::StrAppend(&output,
"IntervalVar", index_,
"(");
622 absl::StrAppend(&output, ct_proto.name(),
"(");
637 cp_model_.set_name(
name);
640int CpModelBuilder::IndexFromConstant(int64_t
value) {
641 if (!constant_to_index_map_.contains(
value)) {
642 const int index = cp_model_.variables_size();
643 IntegerVariableProto*
const var_proto = cp_model_.add_variables();
644 var_proto->add_domain(
value);
645 var_proto->add_domain(
value);
648 return constant_to_index_map_[
value];
651int CpModelBuilder::GetOrCreateIntegerIndex(
int index) {
655 if (!bool_to_integer_index_map_.contains(
index)) {
657 const IntegerVariableProto& old_var = cp_model_.variables(
var);
658 const int new_index = cp_model_.variables_size();
659 IntegerVariableProto*
const new_var = cp_model_.add_variables();
660 new_var->add_domain(0);
661 new_var->add_domain(1);
662 if (!old_var.name().empty()) {
663 new_var->set_name(absl::StrCat(
"Not(", old_var.name(),
")"));
666 bool_to_integer_index_map_[
index] = new_index;
669 return bool_to_integer_index_map_[
index];
673 const int index = cp_model_.variables_size();
674 IntegerVariableProto*
const var_proto = cp_model_.add_variables();
675 for (
const auto&
interval : domain) {
676 var_proto->add_domain(
interval.start);
677 var_proto->add_domain(
interval.end);
683 const int index = cp_model_.variables_size();
684 IntegerVariableProto*
const var_proto = cp_model_.add_variables();
685 var_proto->add_domain(0);
686 var_proto->add_domain(1);
695 return BoolVar(IndexFromConstant(1),
this);
699 return BoolVar(IndexFromConstant(0),
this);
719 const int index = cp_model_.constraints_size();
720 ConstraintProto*
const ct = cp_model_.add_constraints();
721 ct->add_enforcement_literal(presence.index_);
722 IntervalConstraintProto*
const interval =
ct->mutable_interval();
724 *
interval->mutable_size() = LinearExprToProto(size);
731 const int index = cp_model_.constraints_size();
732 ConstraintProto*
const ct = cp_model_.add_constraints();
733 ct->add_enforcement_literal(presence.index_);
734 IntervalConstraintProto*
const interval =
ct->mutable_interval();
736 interval->mutable_size()->set_offset(size);
757 ConstraintProto*
const proto = cp_model_.add_constraints();
758 for (
const BoolVar& lit : literals) {
759 proto->mutable_bool_or()->add_literals(lit.index_);
769 ConstraintProto*
const proto = cp_model_.add_constraints();
770 for (
const BoolVar& lit : literals) {
771 proto->mutable_at_most_one()->add_literals(lit.index_);
777 ConstraintProto*
const proto = cp_model_.add_constraints();
778 for (
const BoolVar& lit : literals) {
779 proto->mutable_exactly_one()->add_literals(lit.index_);
785 ConstraintProto*
const proto = cp_model_.add_constraints();
786 for (
const BoolVar& lit : literals) {
787 proto->mutable_bool_and()->add_literals(lit.index_);
793 ConstraintProto*
const proto = cp_model_.add_constraints();
794 for (
const BoolVar& lit : literals) {
795 proto->mutable_bool_xor()->add_literals(lit.index_);
800void CpModelBuilder::FillLinearTerms(
const LinearExpr& left,
802 LinearConstraintProto*
proto) {
819 ConstraintProto*
const proto = cp_model_.add_constraints();
820 FillLinearTerms(left, right,
proto->mutable_linear());
822 proto->mutable_linear()->add_domain(rhs);
823 proto->mutable_linear()->add_domain(rhs);
829 ConstraintProto*
const proto = cp_model_.add_constraints();
830 FillLinearTerms(left, right,
proto->mutable_linear());
832 proto->mutable_linear()->add_domain(rhs);
839 ConstraintProto*
const proto = cp_model_.add_constraints();
840 FillLinearTerms(left, right,
proto->mutable_linear());
843 proto->mutable_linear()->add_domain(rhs);
849 ConstraintProto*
const proto = cp_model_.add_constraints();
850 FillLinearTerms(left, right,
proto->mutable_linear());
852 proto->mutable_linear()->add_domain(rhs + 1);
859 ConstraintProto*
const proto = cp_model_.add_constraints();
860 FillLinearTerms(left, right,
proto->mutable_linear());
863 proto->mutable_linear()->add_domain(rhs - 1);
869 ConstraintProto*
const proto = cp_model_.add_constraints();
871 proto->mutable_linear()->add_vars(x);
876 const int64_t cst = expr.
constant();
877 for (
const auto& i : domain) {
878 proto->mutable_linear()->add_domain(i.start - cst);
879 proto->mutable_linear()->add_domain(i.end - cst);
886 ConstraintProto*
const proto = cp_model_.add_constraints();
887 FillLinearTerms(left, right,
proto->mutable_linear());
890 proto->mutable_linear()->add_domain(rhs - 1);
891 proto->mutable_linear()->add_domain(rhs + 1);
897 ConstraintProto*
const proto = cp_model_.add_constraints();
899 auto* expr =
proto->mutable_all_diff()->add_exprs();
900 expr->add_vars(
var.index_);
907 ConstraintProto*
const proto = cp_model_.add_constraints();
909 *
proto->mutable_all_diff()->add_exprs() = LinearExprToProto(expr);
915 std::initializer_list<LinearExpr> exprs) {
916 ConstraintProto*
const proto = cp_model_.add_constraints();
918 *
proto->mutable_all_diff()->add_exprs() = LinearExprToProto(expr);
925 ConstraintProto*
const proto = cp_model_.add_constraints();
926 proto->mutable_element()->set_index(
index.index_);
927 proto->mutable_element()->set_target(target.index_);
929 proto->mutable_element()->add_vars(
var.index_);
935 absl::Span<const int64_t> values,
937 ConstraintProto*
const proto = cp_model_.add_constraints();
938 proto->mutable_element()->set_index(
index.index_);
939 proto->mutable_element()->set_target(target.index_);
940 for (int64_t
value : values) {
941 proto->mutable_element()->add_vars(IndexFromConstant(
value));
955 absl::Span<const IntVar> vars) {
956 ConstraintProto*
const proto = cp_model_.add_constraints();
958 proto->mutable_table()->add_vars(
var.index_);
964 absl::Span<const IntVar> vars) {
965 ConstraintProto*
const proto = cp_model_.add_constraints();
967 proto->mutable_table()->add_vars(
var.index_);
969 proto->mutable_table()->set_negated(
true);
974 absl::Span<const IntVar> variables,
975 absl::Span<const IntVar> inverse_variables) {
976 ConstraintProto*
const proto = cp_model_.add_constraints();
978 proto->mutable_inverse()->add_f_direct(
var.index_);
980 for (
const IntVar&
var : inverse_variables) {
981 proto->mutable_inverse()->add_f_inverse(
var.index_);
988 ConstraintProto*
const proto = cp_model_.add_constraints();
989 proto->mutable_reservoir()->set_min_level(min_level);
990 proto->mutable_reservoir()->set_max_level(max_level);
995 absl::Span<const IntVar> transition_variables,
int starting_state,
996 absl::Span<const int> final_states) {
997 ConstraintProto*
const proto = cp_model_.add_constraints();
998 for (
const IntVar&
var : transition_variables) {
999 proto->mutable_automaton()->add_vars(
var.index_);
1001 proto->mutable_automaton()->set_starting_state(starting_state);
1002 for (
const int final_state : final_states) {
1003 proto->mutable_automaton()->add_final_states(final_state);
1008LinearExpressionProto CpModelBuilder::LinearExprToProto(
const LinearExpr& expr,
1010 LinearExpressionProto expr_proto;
1012 expr_proto.add_vars(
var);
1014 const int64_t mult = negate ? -1 : 1;
1016 expr_proto.add_coeffs(
coeff * mult);
1018 expr_proto.set_offset(expr.
constant() * mult);
1023 absl::Span<const IntVar> vars) {
1024 ConstraintProto*
ct = cp_model_.add_constraints();
1025 *
ct->mutable_lin_max()->mutable_target() =
1026 LinearExprToProto(target,
true);
1028 *
ct->mutable_lin_max()->add_exprs() =
1029 LinearExprToProto(
var,
true);
1035 absl::Span<const LinearExpr> exprs) {
1036 ConstraintProto*
ct = cp_model_.add_constraints();
1037 *
ct->mutable_lin_max()->mutable_target() =
1038 LinearExprToProto(target,
true);
1040 *
ct->mutable_lin_max()->add_exprs() =
1041 LinearExprToProto(expr,
true);
1047 const LinearExpr& target, std::initializer_list<LinearExpr> exprs) {
1048 ConstraintProto*
ct = cp_model_.add_constraints();
1049 *
ct->mutable_lin_max()->mutable_target() =
1050 LinearExprToProto(target,
true);
1052 *
ct->mutable_lin_max()->add_exprs() =
1053 LinearExprToProto(expr,
true);
1059 absl::Span<const IntVar> vars) {
1060 ConstraintProto*
ct = cp_model_.add_constraints();
1061 *
ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1063 *
ct->mutable_lin_max()->add_exprs() = LinearExprToProto(
var);
1069 absl::Span<const LinearExpr> exprs) {
1070 ConstraintProto*
ct = cp_model_.add_constraints();
1071 *
ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1073 *
ct->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1079 const LinearExpr& target, std::initializer_list<LinearExpr> exprs) {
1080 ConstraintProto*
ct = cp_model_.add_constraints();
1081 *
ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1083 *
ct->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1091 ConstraintProto*
const proto = cp_model_.add_constraints();
1092 *
proto->mutable_int_div()->mutable_target() = LinearExprToProto(target);
1093 *
proto->mutable_int_div()->add_exprs() = LinearExprToProto(numerator);
1094 *
proto->mutable_int_div()->add_exprs() = LinearExprToProto(denominator);
1100 ConstraintProto*
const proto = cp_model_.add_constraints();
1101 *
proto->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1102 *
proto->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1103 *
proto->mutable_lin_max()->add_exprs() =
1104 LinearExprToProto(expr,
true);
1111 ConstraintProto*
const proto = cp_model_.add_constraints();
1112 *
proto->mutable_int_mod()->mutable_target() = LinearExprToProto(target);
1113 *
proto->mutable_int_mod()->add_exprs() = LinearExprToProto(
var);
1114 *
proto->mutable_int_mod()->add_exprs() = LinearExprToProto(mod);
1119 const LinearExpr& target, absl::Span<const IntVar> vars) {
1120 ConstraintProto*
const proto = cp_model_.add_constraints();
1121 *
proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1123 *
proto->mutable_int_prod()->add_exprs() = LinearExprToProto(
var);
1129 const LinearExpr& target, absl::Span<const LinearExpr> exprs) {
1130 ConstraintProto*
const proto = cp_model_.add_constraints();
1131 *
proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1133 *
proto->mutable_int_prod()->add_exprs() = LinearExprToProto(expr);
1139 const LinearExpr& target, std::initializer_list<LinearExpr> exprs) {
1140 ConstraintProto*
const proto = cp_model_.add_constraints();
1141 *
proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1143 *
proto->mutable_int_prod()->add_exprs() = LinearExprToProto(expr);
1150 ConstraintProto*
const proto = cp_model_.add_constraints();
1151 *
proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1152 *
proto->mutable_int_prod()->add_exprs() = LinearExprToProto(left);
1153 *
proto->mutable_int_prod()->add_exprs() = LinearExprToProto(right);
1159 ConstraintProto*
const proto = cp_model_.add_constraints();
1161 proto->mutable_no_overlap()->add_intervals(
var.index_);
1171 ConstraintProto*
const proto = cp_model_.add_constraints();
1172 *
proto->mutable_cumulative()->mutable_capacity() =
1178 cp_model_.clear_objective();
1179 cp_model_.clear_floating_point_objective();
1181 cp_model_.mutable_objective()->add_vars(x);
1184 cp_model_.mutable_objective()->add_coeffs(
coeff);
1186 cp_model_.mutable_objective()->set_offset(expr.
constant());
1190 cp_model_.clear_objective();
1191 cp_model_.clear_floating_point_objective();
1193 cp_model_.mutable_objective()->add_vars(x);
1196 cp_model_.mutable_objective()->add_coeffs(-
coeff);
1198 cp_model_.mutable_objective()->set_offset(-expr.
constant());
1199 cp_model_.mutable_objective()->set_scaling_factor(-1.0);
1203 cp_model_.clear_objective();
1204 cp_model_.clear_floating_point_objective();
1205 for (
int i = 0; i < expr.
variables().size(); ++i) {
1206 cp_model_.mutable_floating_point_objective()->add_vars(expr.
variables()[i]);
1207 cp_model_.mutable_floating_point_objective()->add_coeffs(
1210 cp_model_.mutable_floating_point_objective()->set_offset(expr.
constant());
1211 cp_model_.mutable_floating_point_objective()->set_maximize(
false);
1215 cp_model_.clear_objective();
1216 cp_model_.clear_floating_point_objective();
1217 for (
int i = 0; i < expr.
variables().size(); ++i) {
1218 cp_model_.mutable_floating_point_objective()->add_vars(expr.
variables()[i]);
1219 cp_model_.mutable_floating_point_objective()->add_coeffs(
1222 cp_model_.mutable_floating_point_objective()->set_offset(expr.
constant());
1223 cp_model_.mutable_floating_point_objective()->set_maximize(
true);
1227 absl::Span<const IntVar> variables,
1228 DecisionStrategyProto::VariableSelectionStrategy var_strategy,
1229 DecisionStrategyProto::DomainReductionStrategy domain_strategy) {
1230 DecisionStrategyProto*
const proto = cp_model_.add_search_strategy();
1234 proto->set_variable_selection_strategy(var_strategy);
1235 proto->set_domain_reduction_strategy(domain_strategy);
1239 absl::Span<const BoolVar> variables,
1240 DecisionStrategyProto::VariableSelectionStrategy var_strategy,
1241 DecisionStrategyProto::DomainReductionStrategy domain_strategy) {
1242 DecisionStrategyProto*
const proto = cp_model_.add_search_strategy();
1246 proto->set_variable_selection_strategy(var_strategy);
1247 proto->set_domain_reduction_strategy(domain_strategy);
1251 cp_model_.mutable_solution_hint()->add_vars(
var.index_);
1252 cp_model_.mutable_solution_hint()->add_values(
value);
1256 if (
var.index_ >= 0) {
1257 cp_model_.mutable_solution_hint()->add_vars(
var.index_);
1258 cp_model_.mutable_solution_hint()->add_values(
value);
1260 cp_model_.mutable_solution_hint()->add_vars(
PositiveRef(
var.index_));
1261 cp_model_.mutable_solution_hint()->add_values(!
value);
1266 cp_model_.mutable_solution_hint()->Clear();
1270 cp_model_.mutable_assumptions()->Add(lit.index_);
1274 for (
const BoolVar& lit : literals) {
1275 cp_model_.mutable_assumptions()->Add(lit.index_);
1280 cp_model_.mutable_assumptions()->Clear();
1286 constant_to_index_map_.clear();
1287 for (
int i = 0; i < cp_model_.variables_size(); ++i) {
1288 const IntegerVariableProto&
var = cp_model_.variables(i);
1289 if (
var.domain_size() == 2 &&
var.domain(0) ==
var.domain(1)) {
1290 constant_to_index_map_[
var.domain(0)] = i;
1294 bool_to_integer_index_map_.clear();
1300 const IntegerVariableProto&
proto = cp_model_.variables(
index);
1302 <<
"CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1305 <<
"CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1308 <<
"CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1322 const ConstraintProto&
ct = cp_model_.constraints(
index);
1323 CHECK_EQ(
ct.constraint_case(), ConstraintProto::kInterval)
1324 <<
"CpModelBuilder::GetIntervalVarFromProtoIndex: the referenced "
1325 "object is not an interval variable";
1332 const std::vector<int>& variables = expr.
variables();
1334 for (
int i = 0; i < variables.size(); ++i) {
1341 const int ref = x.index_;
1343 return r.solution(ref) == 1;
#define DCHECK_LE(val1, val2)
#define CHECK_LT(val1, val2)
#define CHECK_EQ(val1, val2)
#define CHECK_GE(val1, val2)
#define DCHECK_GE(val1, val2)
#define DCHECK(condition)
#define CHECK_LE(val1, val2)
#define DCHECK_EQ(val1, val2)
We call domain any subset of Int64 = [kint64min, kint64max].
Specialized automaton constraint.
void AddTransition(int tail, int head, int64_t transition_label)
Adds a transitions to the automaton.
std::string Name() const
Returns the name of the variable.
BoolVar WithName(const std::string &name)
Sets the name of the variable.
std::string DebugString() const
BoolVar()
A default constructed BoolVar can be used to mean not defined yet.
BoolVar Not() const
Returns the logical negation of the current Boolean variable.
Specialized circuit constraint.
void AddArc(int tail, int head, BoolVar literal)
Add an arc to the circuit.
Constraint OnlyEnforceIf(absl::Span< const BoolVar > literals)
The constraint will be enforced iff all literals listed here are true.
Constraint WithName(const std::string &name)
Sets the name of the constraint.
const std::string & Name() const
Returns the name of the constraint (or the empty string if not set).
Constraint(ConstraintProto *proto)
Wrapper class around the cp_model proto.
Constraint AddAtMostOne(absl::Span< const BoolVar > literals)
At most one literal is true. Sum literals <= 1.
void AddHint(IntVar var, int64_t value)
Adds hinting to a variable.
TableConstraint AddForbiddenAssignments(absl::Span< const IntVar > vars)
Adds an forbidden assignments constraint.
Constraint AddMinEquality(const LinearExpr &target, absl::Span< const IntVar > vars)
Adds target == min(vars).
Constraint AddLinearConstraint(const LinearExpr &expr, const Domain &domain)
Adds expr in domain.
void ClearAssumptions()
Remove all assumptions from the model.
Constraint AddAbsEquality(const LinearExpr &target, const LinearExpr &expr)
Adds target == abs(expr).
void AddAssumptions(absl::Span< const BoolVar > literals)
Adds multiple literals to the model as assumptions.
IntervalVar NewFixedSizeIntervalVar(const LinearExpr &start, int64_t size)
Creates an interval variable with a fixed size.
MultipleCircuitConstraint AddMultipleCircuitConstraint()
Adds a multiple circuit constraint, aka the "VRP" (Vehicle Routing Problem) constraint.
BoolVar TrueVar()
Creates an always true Boolean variable.
IntVar NewIntVar(const Domain &domain)
Creates an integer variable with the given domain.
void ClearHints()
Removes all hints.
void Maximize(const LinearExpr &expr)
Adds a linear maximization objective.
BoolVar NewBoolVar()
Creates a Boolean variable.
Constraint AddAtLeastOne(absl::Span< const BoolVar > literals)
Same as AddBoolOr. Sum literals >= 1.
Constraint AddMaxEquality(const LinearExpr &target, absl::Span< const IntVar > vars)
Adds target == max(vars).
Constraint AddMultiplicationEquality(const LinearExpr &target, absl::Span< const LinearExpr > exprs)
Adds target == prod(exprs).
void AddDecisionStrategy(absl::Span< const IntVar > variables, DecisionStrategyProto::VariableSelectionStrategy var_strategy, DecisionStrategyProto::DomainReductionStrategy domain_strategy)
Adds a decision strategy on a list of integer variables.
IntervalVar NewOptionalIntervalVar(const LinearExpr &start, const LinearExpr &size, const LinearExpr &end, BoolVar presence)
Creates an optional interval variable from 3 affine expressions and a Boolean variable.
CircuitConstraint AddCircuitConstraint()
Adds a circuit constraint.
Constraint AddVariableElement(IntVar index, absl::Span< const IntVar > variables, IntVar target)
Adds the element constraint: variables[index] == target.
Constraint AddGreaterThan(const LinearExpr &left, const LinearExpr &right)
Adds left > right.
void CopyFrom(const CpModelProto &model_proto)
Replaces the current model with the one from the given proto.
Constraint AddLessThan(const LinearExpr &left, const LinearExpr &right)
Adds left < right.
Constraint AddBoolXor(absl::Span< const BoolVar > literals)
Adds the constraint that an odd number of literals is true.
void SetName(const std::string &name)
Sets the name of the model.
Constraint AddElement(IntVar index, absl::Span< const int64_t > values, IntVar target)
Adds the element constraint: values[index] == target.
void AddAssumption(BoolVar lit)
Adds a literal to the model as assumptions.
void Minimize(const LinearExpr &expr)
Adds a linear minimization objective.
CpModelProto * MutableProto()
BoolVar FalseVar()
Creates an always false Boolean variable.
friend class CumulativeConstraint
Constraint AddBoolAnd(absl::Span< const BoolVar > literals)
Adds the constraint that all literals must be true.
IntervalVar GetIntervalVarFromProtoIndex(int index)
Returns the interval variable from its index in the proto.
CumulativeConstraint AddCumulative(LinearExpr capacity)
The cumulative constraint.
void FixVariable(IntVar var, int64_t value)
It is sometime convenient when building a model to create a bunch of variables that will later be fix...
Constraint AddLessOrEqual(const LinearExpr &left, const LinearExpr &right)
Adds left <= right.
ReservoirConstraint AddReservoirConstraint(int64_t min_level, int64_t max_level)
Adds a reservoir constraint with optional refill/emptying events.
Constraint AddEquality(const LinearExpr &left, const LinearExpr &right)
Adds left == right.
NoOverlap2DConstraint AddNoOverlap2D()
The no_overlap_2d constraint prevents a set of boxes from overlapping.
Constraint AddGreaterOrEqual(const LinearExpr &left, const LinearExpr &right)
Adds left >= right.
Constraint AddBoolOr(absl::Span< const BoolVar > literals)
Adds the constraint that at least one of the literals must be true.
IntVar GetIntVarFromProtoIndex(int index)
Returns the integer variable from its index in the proto.
AutomatonConstraint AddAutomaton(absl::Span< const IntVar > transition_variables, int starting_state, absl::Span< const int > final_states)
An automaton constraint.
IntervalVar NewOptionalFixedSizeIntervalVar(const LinearExpr &start, int64_t size, BoolVar presence)
Creates an optional interval variable with a fixed size.
Constraint AddDivisionEquality(const LinearExpr &target, const LinearExpr &numerator, const LinearExpr &denominator)
Adds target = num / denom (integer division rounded towards 0).
friend class ReservoirConstraint
BoolVar GetBoolVarFromProtoIndex(int index)
Returns the Boolean variable from its index in the proto.
Constraint AddNotEqual(const LinearExpr &left, const LinearExpr &right)
Adds left != right.
Constraint AddModuloEquality(const LinearExpr &target, const LinearExpr &var, const LinearExpr &mod)
Adds target = var % mod.
Constraint AddAllDifferent(absl::Span< const IntVar > vars)
This constraint forces all variables to have different values.
TableConstraint AddAllowedAssignments(absl::Span< const IntVar > vars)
Adds an allowed assignments constraint.
IntVar NewConstant(int64_t value)
Creates a constant variable.
IntervalVar NewIntervalVar(const LinearExpr &start, const LinearExpr &size, const LinearExpr &end)
Creates an interval variable from 3 affine expressions.
Constraint AddInverseConstraint(absl::Span< const IntVar > variables, absl::Span< const IntVar > inverse_variables)
An inverse constraint.
Constraint AddExactlyOne(absl::Span< const BoolVar > literals)
Exactly one literal is true. Sum literals == 1.
Constraint AddNoOverlap(absl::Span< const IntervalVar > vars)
Adds a no-overlap constraint that ensures that all present intervals do not overlap in time.
const CpModelProto & Proto() const
Specialized cumulative constraint.
void AddDemand(IntervalVar interval, LinearExpr demand)
Adds a pair (interval, demand) to the constraint.
A dedicated container for linear expressions with double coefficients.
double constant() const
Returns the constant term.
DoubleLinearExpr & operator+=(double value)
Adds a constant value to the linear expression.
std::string DebugString(const CpModelProto *proto=nullptr) const
Debug string. See the documentation for LinearExpr::DebugString().
static DoubleLinearExpr WeightedSum(absl::Span< const IntVar > vars, absl::Span< const double > coeffs)
Constructs the scalar product of variables and coefficients.
const std::vector< double > & coefficients() const
Returns the vector of coefficients.
const std::vector< int > & variables() const
Returns the vector of variable indices.
DoubleLinearExpr & operator-=(double value)
Adds a constant value to the linear expression.
DoubleLinearExpr & AddTerm(IntVar var, double coeff)
Adds a term (var * coeff) to the linear expression.
DoubleLinearExpr & operator*=(double coeff)
Multiply the linear expression by a constant.
static DoubleLinearExpr Sum(absl::Span< const IntVar > vars)
Constructs the sum of a list of variables.
BoolVar ToBoolVar() const
Cast IntVar -> BoolVar.
std::string Name() const
Returns the name of the variable (or the empty string if not set).
IntVar()
A default constructed IntVar can be used to mean not defined yet.
std::string DebugString() const
IntVar WithName(const std::string &name)
Sets the name of the variable.
::operations_research::Domain Domain() const
Represents a Interval variable.
LinearExpr SizeExpr() const
Returns the size linear expression.
LinearExpr StartExpr() const
Returns the start linear expression.
BoolVar PresenceBoolVar() const
Returns a BoolVar indicating the presence of this interval.
std::string Name() const
Returns the name of the interval (or the empty string if not set).
std::string DebugString() const
Returns a debug string.
IntervalVar WithName(const std::string &name)
Sets the name of the variable.
LinearExpr EndExpr() const
Returns the end linear expression.
IntervalVar()
A default constructed IntervalVar can be used to mean not defined yet.
A dedicated container for linear expressions.
LinearExpr & operator+=(const LinearExpr &other)
LinearExpr & operator-=(const LinearExpr &other)
LinearExpr & operator*=(int64_t factor)
static LinearExpr WeightedSum(absl::Span< const IntVar > vars, absl::Span< const int64_t > coeffs)
Constructs the scalar product of variables and coefficients.
static LinearExpr Sum(absl::Span< const IntVar > vars)
Constructs the sum of a list of variables.
std::string DebugString(const CpModelProto *proto=nullptr) const
Debug string.
const std::vector< int64_t > & coefficients() const
Returns the vector of coefficients.
const std::vector< int > & variables() const
Returns the vector of variable indices.
int64_t constant() const
Returns the constant term.
LinearExpr()=default
Creates an empty linear expression with value zero.
static LinearExpr FromProto(const LinearExpressionProto &proto)
Constructs a linear expr from its proto representation.
static LinearExpr Term(IntVar var, int64_t coefficient)
Constructs var * coefficient.
Specialized circuit constraint.
void AddArc(int tail, int head, BoolVar literal)
Add an arc to the circuit.
Specialized no_overlap2D constraint.
void AddRectangle(IntervalVar x_coordinate, IntervalVar y_coordinate)
Adds a rectangle (parallel to the axis) to the constraint.
Specialized reservoir constraint.
void AddOptionalEvent(LinearExpr time, int64_t level_change, BoolVar is_active)
Adds an optional event.
void AddEvent(LinearExpr time, int64_t level_change)
Adds a mandatory event.
Specialized assignment constraint.
void AddTuple(absl::Span< const int64_t > tuple)
Adds a tuple of possible values to the constraint.
This file implements a wrapper around the CP-SAT model proto.
CpModelProto const * model_proto
absl::Span< const double > coefficients
std::ostream & operator<<(std::ostream &os, const BoolVar &var)
bool RefIsPositive(int ref)
std::string VarDebugString(const CpModelProto &proto, int index)
BoolVar Not(BoolVar x)
A convenient wrapper so we can write Not(x) instead of x.Not() which is sometimes clearer.
bool SolutionBooleanValue(const CpSolverResponse &r, BoolVar x)
Evaluates the value of a Boolean literal in a solver response.
void FillDomainInProto(const Domain &domain, ProtoWithDomain *proto)
Domain ReadDomainFromProto(const ProtoWithDomain &proto)
int64_t SolutionIntegerValue(const CpSolverResponse &r, const LinearExpr &expr)
Evaluates the value of an linear expression in a solver response.
Collection of objects used to extend the Constraint Solver library.
std::optional< int64_t > end