17 #include <initializer_list>
23 #include "absl/container/flat_hash_map.h"
24 #include "absl/strings/str_cat.h"
25 #include "absl/strings/str_format.h"
26 #include "absl/types/span.h"
28 #include "ortools/sat/cp_model.pb.h"
36 : builder_(builder), index_(
index) {}
39 DCHECK(builder_ !=
nullptr);
40 if (builder_ ==
nullptr)
return *
this;
41 builder_->MutableProto()
47 std::string BoolVar::Name()
const {
48 if (builder_ ==
nullptr)
return "null";
49 const std::string&
name =
50 builder_->Proto().variables(
PositiveRef(index_)).name();
54 return absl::StrCat(
"Not(",
name,
")");
58 std::string BoolVar::DebugString()
const {
59 if (builder_ ==
nullptr)
return "null";
61 return absl::StrFormat(
"Not(%s)",
Not().DebugString());
64 const IntegerVariableProto& var_proto = builder_->Proto().variables(index_);
66 if (var_proto.name().empty() && var_proto.domain_size() == 2 &&
67 var_proto.domain(0) == var_proto.domain(1)) {
68 output.append(var_proto.domain(0) == 0 ?
"false" :
"true");
70 if (var_proto.name().empty()) {
71 absl::StrAppendFormat(&output,
"BoolVar%i(", index_);
73 absl::StrAppendFormat(&output,
"%s(", var_proto.name());
75 if (var_proto.domain(0) == var_proto.domain(1)) {
76 output.append(var_proto.domain(0) == 0 ?
"false)" :
"true)");
78 absl::StrAppend(&output, var_proto.domain(0),
", ", var_proto.domain(1),
89 os <<
var.DebugString();
93 IntVar::IntVar(
int index, CpModelBuilder* builder)
94 : builder_(builder), index_(
index) {
99 if (
var.builder_ ==
nullptr) {
103 builder_ =
var.builder_;
104 index_ = builder_->GetOrCreateIntegerIndex(
var.index_);
109 if (builder_ !=
nullptr) {
110 const IntegerVariableProto&
proto = builder_->Proto().variables(index_);
111 DCHECK_EQ(2,
proto.domain_size());
112 DCHECK_GE(
proto.domain(0), 0);
113 DCHECK_LE(
proto.domain(1), 1);
115 return BoolVar(index_, builder_);
119 DCHECK(builder_ !=
nullptr);
120 if (builder_ ==
nullptr)
return *
this;
121 builder_->MutableProto()->mutable_variables(index_)->set_name(
name);
125 std::string IntVar::Name()
const {
126 if (builder_ ==
nullptr)
return "null";
127 return builder_->Proto().variables(index_).name();
131 if (builder_ ==
nullptr)
return Domain();
136 if (builder_ ==
nullptr)
return "null";
146 const IntegerVariableProto& var_proto =
proto.variables(
index);
147 if (var_proto.name().empty() && var_proto.domain_size() == 2 &&
148 var_proto.domain(0) == var_proto.domain(1)) {
149 absl::StrAppend(&output, var_proto.domain(0));
151 if (var_proto.name().empty()) {
152 absl::StrAppend(&output,
"V",
index,
"(");
154 absl::StrAppend(&output, var_proto.name(),
"(");
158 if (var_proto.domain_size() == 2 &&
159 var_proto.domain(0) == var_proto.domain(1)) {
160 absl::StrAppend(&output, var_proto.domain(0),
")");
162 absl::StrAppend(&output, var_proto.domain(0),
", ", var_proto.domain(1),
176 DCHECK(
var.builder_ !=
nullptr);
179 variables_.push_back(
index);
180 coefficients_.push_back(1);
184 coefficients_.push_back(-1);
190 DCHECK(
var.builder_ !=
nullptr);
191 variables_.push_back(
var.index_);
192 coefficients_.push_back(1);
197 LinearExpr LinearExpr::FromProto(
const LinearExpressionProto& expr_proto) {
199 for (
int i = 0; i < expr_proto.vars_size(); ++i) {
200 result.variables_.push_back(expr_proto.vars(i));
201 result.coefficients_.push_back(expr_proto.coeffs(i));
222 LinearExpr LinearExpr::WeightedSum(absl::Span<const IntVar> vars,
223 absl::Span<const int64_t> coeffs) {
224 CHECK_EQ(vars.size(), coeffs.size());
226 for (
int i = 0; i < vars.size(); ++i) {
227 result += vars[i] * coeffs[i];
232 LinearExpr LinearExpr::WeightedSum(absl::Span<const BoolVar> vars,
233 absl::Span<const int64_t> coeffs) {
234 CHECK_EQ(vars.size(), coeffs.size());
236 for (
int i = 0; i < vars.size(); ++i) {
237 result += vars[i] * coeffs[i];
255 constant_ += other.constant_;
256 variables_.insert(variables_.end(), other.variables_.begin(),
257 other.variables_.end());
258 coefficients_.insert(coefficients_.end(), other.coefficients_.begin(),
259 other.coefficients_.end());
264 constant_ -= other.constant_;
265 variables_.insert(variables_.end(), other.variables_.begin(),
266 other.variables_.end());
267 for (
const int64_t coeff : other.coefficients_) {
268 coefficients_.push_back(-coeff);
275 for (int64_t& coeff : coefficients_) coeff *= factor;
279 std::string LinearExpr::DebugString(
const CpModelProto*
proto)
const {
281 for (
int i = 0; i < variables_.size(); ++i) {
282 const int64_t coeff = coefficients_[i];
283 const std::string var_string =
proto ==
nullptr
284 ? absl::StrCat(
"V", variables_[i])
288 absl::StrAppend(&result, var_string);
289 }
else if (coeff == -1) {
290 absl::StrAppend(&result,
"-", var_string);
291 }
else if (coeff != 0) {
292 absl::StrAppend(&result, coeff,
" * ", var_string);
294 }
else if (coeff == 1) {
295 absl::StrAppend(&result,
" + ", var_string);
296 }
else if (coeff > 0) {
297 absl::StrAppend(&result,
" + ", coeff,
" * ", var_string);
298 }
else if (coeff == -1) {
299 absl::StrAppend(&result,
" - ", var_string);
300 }
else if (coeff < 0) {
301 absl::StrAppend(&result,
" - ", -coeff,
" * ", var_string);
305 if (constant_ != 0) {
306 if (variables_.empty()) {
307 return absl::StrCat(constant_);
308 }
else if (constant_ > 0) {
309 absl::StrAppend(&result,
" + ", constant_);
311 absl::StrAppend(&result,
" - ", -constant_);
322 DoubleLinearExpr::DoubleLinearExpr() {}
328 DoubleLinearExpr::DoubleLinearExpr(
double constant) { constant_ = constant; }
347 absl::Span<const IntVar> vars, absl::Span<const double> coeffs) {
348 CHECK_EQ(vars.size(), coeffs.size());
350 for (
int i = 0; i < vars.size(); ++i) {
351 result.
AddTerm(vars[i], coeffs[i]);
357 absl::Span<const BoolVar> vars, absl::Span<const double> coeffs) {
358 CHECK_EQ(vars.size(), coeffs.size());
360 for (
int i = 0; i < vars.size(); ++i) {
361 result.
AddTerm(vars[i], coeffs[i]);
382 constant_ += expr.constant_;
383 variables_.insert(variables_.end(), expr.variables_.begin(),
384 expr.variables_.end());
385 coefficients_.insert(coefficients_.end(), expr.coefficients_.begin(),
386 expr.coefficients_.end());
391 variables_.push_back(
var.index_);
392 coefficients_.push_back(coeff);
399 variables_.push_back(
index);
400 coefficients_.push_back(coeff);
403 coefficients_.push_back(-coeff);
411 const std::vector<int>& indices = expr.
variables();
413 for (
int i = 0; i < indices.size(); ++i) {
414 variables_.push_back(indices[i]);
415 coefficients_.push_back(1.0 *
static_cast<double>(
coefficients[i]) * coeff);
432 constant_ -= expr.constant_;
433 variables_.insert(variables_.end(), expr.variables_.begin(),
434 expr.variables_.end());
436 coefficients_.push_back(-coeff);
443 for (
double& c : coefficients_) {
449 std::string DoubleLinearExpr::DebugString(
const CpModelProto*
proto)
const {
451 for (
int i = 0; i < variables_.size(); ++i) {
452 const double coeff = coefficients_[i];
453 const std::string var_string =
proto ==
nullptr
454 ? absl::StrCat(
"V", variables_[i])
458 absl::StrAppend(&result, 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);
464 }
else if (coeff == 1.0) {
465 absl::StrAppend(&result,
" + ", var_string);
466 }
else if (coeff > 0.0) {
467 absl::StrAppend(&result,
" + ", coeff,
" * ", var_string);
468 }
else if (coeff == -1.0) {
469 absl::StrAppend(&result,
" - ", var_string);
470 }
else if (coeff < 0.0) {
471 absl::StrAppend(&result,
" - ", -coeff,
" * ", var_string);
475 if (constant_ != 0.0) {
476 if (variables_.empty()) {
477 return absl::StrCat(constant_);
478 }
else if (constant_ > 0.0) {
479 absl::StrAppend(&result,
" + ", constant_);
481 absl::StrAppend(&result,
" - ", -constant_);
503 proto_->add_enforcement_literal(
var.index_);
526 CHECK_EQ(tuple.size(),
proto_->table().vars_size());
527 for (
const int64_t t : tuple) {
528 proto_->mutable_table()->add_values(t);
532 ReservoirConstraint::ReservoirConstraint(ConstraintProto*
proto,
537 *
proto_->mutable_reservoir()->add_time_exprs() =
538 builder_->LinearExprToProto(
time);
539 proto_->mutable_reservoir()->add_level_changes()->set_offset(level_change);
540 proto_->mutable_reservoir()->add_active_literals(
541 builder_->IndexFromConstant(1));
545 int64_t level_change,
547 *
proto_->mutable_reservoir()->add_time_exprs() =
548 builder_->LinearExprToProto(
time);
549 proto_->mutable_reservoir()->add_level_changes()->set_offset(level_change);
550 proto_->mutable_reservoir()->add_active_literals(is_active.index_);
554 int64_t transition_label) {
555 proto_->mutable_automaton()->add_transition_tail(
tail);
556 proto_->mutable_automaton()->add_transition_head(
head);
557 proto_->mutable_automaton()->add_transition_label(transition_label);
562 proto_->mutable_no_overlap_2d()->add_x_intervals(x_coordinate.index_);
563 proto_->mutable_no_overlap_2d()->add_y_intervals(y_coordinate.index_);
566 CumulativeConstraint::CumulativeConstraint(ConstraintProto*
proto,
572 *
proto_->mutable_cumulative()->add_demands() =
573 builder_->LinearExprToProto(
demand);
579 : builder_(builder), index_(
index) {}
582 DCHECK(builder_ !=
nullptr);
583 if (builder_ ==
nullptr)
return *
this;
589 DCHECK(builder_ !=
nullptr);
592 builder_->
Proto().constraints(index_).interval().start());
596 DCHECK(builder_ !=
nullptr);
599 builder_->
Proto().constraints(index_).interval().size());
603 DCHECK(builder_ !=
nullptr);
606 builder_->
Proto().constraints(index_).interval().end());
610 DCHECK(builder_ !=
nullptr);
611 if (builder_ ==
nullptr)
return BoolVar();
612 return BoolVar(builder_->
Proto().constraints(index_).enforcement_literal(0),
617 if (builder_ ==
nullptr)
return "null";
618 return builder_->
Proto().constraints(index_).name();
622 if (builder_ ==
nullptr)
return "null";
625 const CpModelProto&
proto = builder_->
Proto();
626 const ConstraintProto& ct_proto =
proto.constraints(index_);
628 if (ct_proto.name().empty()) {
629 absl::StrAppend(&output,
"IntervalVar", index_,
"(");
631 absl::StrAppend(&output, ct_proto.name(),
"(");
646 cp_model_.set_name(
name);
649 int CpModelBuilder::IndexFromConstant(int64_t
value) {
650 if (!constant_to_index_map_.contains(
value)) {
651 const int index = cp_model_.variables_size();
652 IntegerVariableProto*
const var_proto = cp_model_.add_variables();
653 var_proto->add_domain(
value);
654 var_proto->add_domain(
value);
657 return constant_to_index_map_[
value];
660 int CpModelBuilder::GetOrCreateIntegerIndex(
int index) {
664 if (!bool_to_integer_index_map_.contains(
index)) {
666 const IntegerVariableProto& old_var = cp_model_.variables(
var);
667 const int new_index = cp_model_.variables_size();
668 IntegerVariableProto*
const new_var = cp_model_.add_variables();
669 new_var->add_domain(0);
670 new_var->add_domain(1);
671 if (!old_var.name().empty()) {
672 new_var->set_name(absl::StrCat(
"Not(", old_var.name(),
")"));
675 bool_to_integer_index_map_[
index] = new_index;
678 return bool_to_integer_index_map_[
index];
682 const int index = cp_model_.variables_size();
683 IntegerVariableProto*
const var_proto = cp_model_.add_variables();
684 for (
const auto&
interval : domain) {
685 var_proto->add_domain(
interval.start);
686 var_proto->add_domain(
interval.end);
692 const int index = cp_model_.variables_size();
693 IntegerVariableProto*
const var_proto = cp_model_.add_variables();
694 var_proto->add_domain(0);
695 var_proto->add_domain(1);
704 return BoolVar(IndexFromConstant(1),
this);
708 return BoolVar(IndexFromConstant(0),
this);
728 const int index = cp_model_.constraints_size();
729 ConstraintProto*
const ct = cp_model_.add_constraints();
730 ct->add_enforcement_literal(presence.index_);
731 IntervalConstraintProto*
const interval =
ct->mutable_interval();
733 *
interval->mutable_size() = LinearExprToProto(size);
740 const int index = cp_model_.constraints_size();
741 ConstraintProto*
const ct = cp_model_.add_constraints();
742 ct->add_enforcement_literal(presence.index_);
743 IntervalConstraintProto*
const interval =
ct->mutable_interval();
745 interval->mutable_size()->set_offset(size);
766 ConstraintProto*
const proto = cp_model_.add_constraints();
767 for (
const BoolVar& lit : literals) {
768 proto->mutable_bool_or()->add_literals(lit.index_);
778 ConstraintProto*
const proto = cp_model_.add_constraints();
779 for (
const BoolVar& lit : literals) {
780 proto->mutable_at_most_one()->add_literals(lit.index_);
786 ConstraintProto*
const proto = cp_model_.add_constraints();
787 for (
const BoolVar& lit : literals) {
788 proto->mutable_exactly_one()->add_literals(lit.index_);
794 ConstraintProto*
const proto = cp_model_.add_constraints();
795 for (
const BoolVar& lit : literals) {
796 proto->mutable_bool_and()->add_literals(lit.index_);
802 ConstraintProto*
const proto = cp_model_.add_constraints();
803 for (
const BoolVar& lit : literals) {
804 proto->mutable_bool_xor()->add_literals(lit.index_);
809 void CpModelBuilder::FillLinearTerms(
const LinearExpr& left,
811 LinearConstraintProto*
proto) {
816 proto->add_coeffs(coeff);
822 proto->add_coeffs(-coeff);
828 ConstraintProto*
const proto = cp_model_.add_constraints();
829 FillLinearTerms(left, right,
proto->mutable_linear());
831 proto->mutable_linear()->add_domain(rhs);
832 proto->mutable_linear()->add_domain(rhs);
838 ConstraintProto*
const proto = cp_model_.add_constraints();
839 FillLinearTerms(left, right,
proto->mutable_linear());
841 proto->mutable_linear()->add_domain(rhs);
848 ConstraintProto*
const proto = cp_model_.add_constraints();
849 FillLinearTerms(left, right,
proto->mutable_linear());
852 proto->mutable_linear()->add_domain(rhs);
858 ConstraintProto*
const proto = cp_model_.add_constraints();
859 FillLinearTerms(left, right,
proto->mutable_linear());
861 proto->mutable_linear()->add_domain(rhs + 1);
868 ConstraintProto*
const proto = cp_model_.add_constraints();
869 FillLinearTerms(left, right,
proto->mutable_linear());
872 proto->mutable_linear()->add_domain(rhs - 1);
878 ConstraintProto*
const proto = cp_model_.add_constraints();
880 proto->mutable_linear()->add_vars(x);
883 proto->mutable_linear()->add_coeffs(coeff);
885 const int64_t cst = expr.
constant();
886 for (
const auto& i : domain) {
887 proto->mutable_linear()->add_domain(i.start - cst);
888 proto->mutable_linear()->add_domain(i.end - cst);
895 ConstraintProto*
const proto = cp_model_.add_constraints();
896 FillLinearTerms(left, right,
proto->mutable_linear());
899 proto->mutable_linear()->add_domain(rhs - 1);
900 proto->mutable_linear()->add_domain(rhs + 1);
906 ConstraintProto*
const proto = cp_model_.add_constraints();
908 auto* expr =
proto->mutable_all_diff()->add_exprs();
909 expr->add_vars(
var.index_);
916 ConstraintProto*
const proto = cp_model_.add_constraints();
918 *
proto->mutable_all_diff()->add_exprs() = LinearExprToProto(expr);
924 std::initializer_list<LinearExpr> exprs) {
925 ConstraintProto*
const proto = cp_model_.add_constraints();
927 *
proto->mutable_all_diff()->add_exprs() = LinearExprToProto(expr);
934 ConstraintProto*
const proto = cp_model_.add_constraints();
935 proto->mutable_element()->set_index(
index.index_);
936 proto->mutable_element()->set_target(target.index_);
938 proto->mutable_element()->add_vars(
var.index_);
944 absl::Span<const int64_t> values,
946 ConstraintProto*
const proto = cp_model_.add_constraints();
947 proto->mutable_element()->set_index(
index.index_);
948 proto->mutable_element()->set_target(target.index_);
949 for (int64_t
value : values) {
950 proto->mutable_element()->add_vars(IndexFromConstant(
value));
964 absl::Span<const IntVar> vars) {
965 ConstraintProto*
const proto = cp_model_.add_constraints();
967 proto->mutable_table()->add_vars(
var.index_);
973 absl::Span<const IntVar> vars) {
974 ConstraintProto*
const proto = cp_model_.add_constraints();
976 proto->mutable_table()->add_vars(
var.index_);
978 proto->mutable_table()->set_negated(
true);
983 absl::Span<const IntVar> variables,
984 absl::Span<const IntVar> inverse_variables) {
985 ConstraintProto*
const proto = cp_model_.add_constraints();
987 proto->mutable_inverse()->add_f_direct(
var.index_);
989 for (
const IntVar&
var : inverse_variables) {
990 proto->mutable_inverse()->add_f_inverse(
var.index_);
997 ConstraintProto*
const proto = cp_model_.add_constraints();
998 proto->mutable_reservoir()->set_min_level(min_level);
999 proto->mutable_reservoir()->set_max_level(max_level);
1004 absl::Span<const IntVar> transition_variables,
int starting_state,
1005 absl::Span<const int> final_states) {
1006 ConstraintProto*
const proto = cp_model_.add_constraints();
1007 for (
const IntVar&
var : transition_variables) {
1008 proto->mutable_automaton()->add_vars(
var.index_);
1010 proto->mutable_automaton()->set_starting_state(starting_state);
1011 for (
const int final_state : final_states) {
1012 proto->mutable_automaton()->add_final_states(final_state);
1017 LinearExpressionProto CpModelBuilder::LinearExprToProto(
const LinearExpr& expr,
1019 LinearExpressionProto expr_proto;
1021 expr_proto.add_vars(
var);
1023 const int64_t mult = negate ? -1 : 1;
1025 expr_proto.add_coeffs(coeff * mult);
1027 expr_proto.set_offset(expr.
constant() * mult);
1032 absl::Span<const IntVar> vars) {
1033 ConstraintProto*
ct = cp_model_.add_constraints();
1034 *
ct->mutable_lin_max()->mutable_target() =
1035 LinearExprToProto(target,
true);
1037 *
ct->mutable_lin_max()->add_exprs() =
1038 LinearExprToProto(
var,
true);
1044 absl::Span<const LinearExpr> exprs) {
1045 ConstraintProto*
ct = cp_model_.add_constraints();
1046 *
ct->mutable_lin_max()->mutable_target() =
1047 LinearExprToProto(target,
true);
1049 *
ct->mutable_lin_max()->add_exprs() =
1050 LinearExprToProto(expr,
true);
1056 const LinearExpr& target, std::initializer_list<LinearExpr> exprs) {
1057 ConstraintProto*
ct = cp_model_.add_constraints();
1058 *
ct->mutable_lin_max()->mutable_target() =
1059 LinearExprToProto(target,
true);
1061 *
ct->mutable_lin_max()->add_exprs() =
1062 LinearExprToProto(expr,
true);
1068 absl::Span<const IntVar> vars) {
1069 ConstraintProto*
ct = cp_model_.add_constraints();
1070 *
ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1072 *
ct->mutable_lin_max()->add_exprs() = LinearExprToProto(
var);
1078 absl::Span<const LinearExpr> exprs) {
1079 ConstraintProto*
ct = cp_model_.add_constraints();
1080 *
ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1082 *
ct->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1088 const LinearExpr& target, std::initializer_list<LinearExpr> exprs) {
1089 ConstraintProto*
ct = cp_model_.add_constraints();
1090 *
ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1092 *
ct->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1100 ConstraintProto*
const proto = cp_model_.add_constraints();
1101 *
proto->mutable_int_div()->mutable_target() = LinearExprToProto(target);
1102 *
proto->mutable_int_div()->add_exprs() = LinearExprToProto(numerator);
1103 *
proto->mutable_int_div()->add_exprs() = LinearExprToProto(denominator);
1109 ConstraintProto*
const proto = cp_model_.add_constraints();
1110 *
proto->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1111 *
proto->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1112 *
proto->mutable_lin_max()->add_exprs() =
1113 LinearExprToProto(expr,
true);
1120 ConstraintProto*
const proto = cp_model_.add_constraints();
1121 *
proto->mutable_int_mod()->mutable_target() = LinearExprToProto(target);
1122 *
proto->mutable_int_mod()->add_exprs() = LinearExprToProto(
var);
1123 *
proto->mutable_int_mod()->add_exprs() = LinearExprToProto(mod);
1128 const LinearExpr& target, absl::Span<const IntVar> vars) {
1129 ConstraintProto*
const proto = cp_model_.add_constraints();
1130 *
proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1132 *
proto->mutable_int_prod()->add_exprs() = LinearExprToProto(
var);
1138 const LinearExpr& target, absl::Span<const LinearExpr> exprs) {
1139 ConstraintProto*
const proto = cp_model_.add_constraints();
1140 *
proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1142 *
proto->mutable_int_prod()->add_exprs() = LinearExprToProto(expr);
1148 const LinearExpr& target, std::initializer_list<LinearExpr> exprs) {
1149 ConstraintProto*
const proto = cp_model_.add_constraints();
1150 *
proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1152 *
proto->mutable_int_prod()->add_exprs() = LinearExprToProto(expr);
1159 ConstraintProto*
const proto = cp_model_.add_constraints();
1160 *
proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1161 *
proto->mutable_int_prod()->add_exprs() = LinearExprToProto(left);
1162 *
proto->mutable_int_prod()->add_exprs() = LinearExprToProto(right);
1168 ConstraintProto*
const proto = cp_model_.add_constraints();
1170 proto->mutable_no_overlap()->add_intervals(
var.index_);
1180 ConstraintProto*
const proto = cp_model_.add_constraints();
1181 *
proto->mutable_cumulative()->mutable_capacity() =
1189 cp_model_.mutable_objective()->add_vars(x);
1192 cp_model_.mutable_objective()->add_coeffs(coeff);
1194 cp_model_.mutable_objective()->set_offset(expr.
constant());
1200 cp_model_.mutable_objective()->add_vars(x);
1203 cp_model_.mutable_objective()->add_coeffs(-coeff);
1205 cp_model_.mutable_objective()->set_offset(-expr.
constant());
1206 cp_model_.mutable_objective()->set_scaling_factor(-1.0);
1211 for (
int i = 0; i < expr.
variables().size(); ++i) {
1212 cp_model_.mutable_floating_point_objective()->add_vars(expr.
variables()[i]);
1213 cp_model_.mutable_floating_point_objective()->add_coeffs(
1216 cp_model_.mutable_floating_point_objective()->set_offset(expr.
constant());
1217 cp_model_.mutable_floating_point_objective()->set_maximize(
false);
1222 for (
int i = 0; i < expr.
variables().size(); ++i) {
1223 cp_model_.mutable_floating_point_objective()->add_vars(expr.
variables()[i]);
1224 cp_model_.mutable_floating_point_objective()->add_coeffs(
1227 cp_model_.mutable_floating_point_objective()->set_offset(expr.
constant());
1228 cp_model_.mutable_floating_point_objective()->set_maximize(
true);
1232 cp_model_.clear_objective();
1233 cp_model_.clear_floating_point_objective();
1237 return cp_model_.has_objective() || cp_model_.has_floating_point_objective();
1241 absl::Span<const IntVar> variables,
1242 DecisionStrategyProto::VariableSelectionStrategy var_strategy,
1243 DecisionStrategyProto::DomainReductionStrategy domain_strategy) {
1244 DecisionStrategyProto*
const proto = cp_model_.add_search_strategy();
1248 proto->set_variable_selection_strategy(var_strategy);
1249 proto->set_domain_reduction_strategy(domain_strategy);
1253 absl::Span<const BoolVar> variables,
1254 DecisionStrategyProto::VariableSelectionStrategy var_strategy,
1255 DecisionStrategyProto::DomainReductionStrategy domain_strategy) {
1256 DecisionStrategyProto*
const proto = cp_model_.add_search_strategy();
1260 proto->set_variable_selection_strategy(var_strategy);
1261 proto->set_domain_reduction_strategy(domain_strategy);
1265 cp_model_.mutable_solution_hint()->add_vars(
var.index_);
1266 cp_model_.mutable_solution_hint()->add_values(
value);
1270 if (
var.index_ >= 0) {
1271 cp_model_.mutable_solution_hint()->add_vars(
var.index_);
1272 cp_model_.mutable_solution_hint()->add_values(
value);
1274 cp_model_.mutable_solution_hint()->add_vars(
PositiveRef(
var.index_));
1275 cp_model_.mutable_solution_hint()->add_values(!
value);
1280 cp_model_.mutable_solution_hint()->Clear();
1284 cp_model_.mutable_assumptions()->Add(lit.index_);
1288 for (
const BoolVar& lit : literals) {
1289 cp_model_.mutable_assumptions()->Add(lit.index_);
1294 cp_model_.mutable_assumptions()->Clear();
1300 constant_to_index_map_.clear();
1301 for (
int i = 0; i < cp_model_.variables_size(); ++i) {
1302 const IntegerVariableProto&
var = cp_model_.variables(i);
1303 if (
var.domain_size() == 2 &&
var.domain(0) ==
var.domain(1)) {
1304 constant_to_index_map_[
var.domain(0)] = i;
1308 bool_to_integer_index_map_.clear();
1313 CHECK_LT(
index, cp_model_.variables_size());
1314 const IntegerVariableProto&
proto = cp_model_.variables(
index);
1315 CHECK_EQ(2,
proto.domain_size())
1316 <<
"CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1318 CHECK_GE(0,
proto.domain(0))
1319 <<
"CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1321 CHECK_LE(1,
proto.domain(1))
1322 <<
"CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1329 CHECK_LT(
index, cp_model_.variables_size());
1335 CHECK_LT(
index, cp_model_.constraints_size());
1336 const ConstraintProto&
ct = cp_model_.constraints(
index);
1337 CHECK_EQ(
ct.constraint_case(), ConstraintProto::kInterval)
1338 <<
"CpModelBuilder::GetIntervalVarFromProtoIndex: the referenced "
1339 "object is not an interval variable";
1350 const std::vector<int>& variables = expr.
variables();
1352 for (
int i = 0; i < variables.size(); ++i) {
1359 const int ref = x.index_;
1361 return r.solution(ref) == 1;
Constraint(Solver *const solver)
We call domain any subset of Int64 = [kint64min, kint64max].
LinearExpr & operator*=(double rhs)
LinearExpr & operator+=(const LinearExpr &rhs)
LinearExpr & operator-=(const LinearExpr &rhs)
virtual std::string name() const
Object naming.
std::string DebugString() const override
Specialized automaton constraint.
void AddTransition(int tail, int head, int64_t transition_label)
Adds a transitions to the automaton.
BoolVar()=default
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).
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 ClearObjective()
Removes the objective from the model.
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.
const CpModelProto & Proto() const
Constraint AddGreaterThan(const LinearExpr &left, const LinearExpr &right)
Adds left > right.
bool HasObjective() const
Checks whether the model contains an objective.
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.
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.
bool ExportToFile(const std::string &filename) const
Export the model to file.
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.
CpModelProto * MutableProto()
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.
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.
std::string DebugString(const CpModelProto *proto=nullptr) const
Debug string. See the documentation for LinearExpr::DebugString().
DoubleLinearExpr & AddTerm(IntVar var, double coeff)
Adds a term (var * coeff) to the linear expression.
const std::vector< double > & coefficients() const
Returns the vector of coefficients.
const std::vector< int > & variables() const
Returns the vector of variable indices.
std::string DebugString() 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.
std::string DebugString(const CpModelProto *proto=nullptr) const
Debug string.
int64_t constant() const
Returns the constant term.
static LinearExpr FromProto(const LinearExpressionProto &proto)
Constructs a linear expr from its proto representation.
const std::vector< int64_t > & coefficients() const
Returns the vector of coefficients.
const std::vector< int > & variables() const
Returns the vector of variable indices.
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
LinearExpression Sum(const Iterable &items)
std::ostream & operator<<(std::ostream &os, const BoolVar &var)
bool RefIsPositive(int ref)
std::string VarDebugString(const CpModelProto &proto, int index)
bool WriteModelProtoToFile(const M &proto, absl::string_view filename)
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::ostream & operator<<(std::ostream &out, const Assignment &assignment)
std::optional< int64_t > end
std::ostream & operator<<(std::ostream &out, const std::pair< First, Second > &p)