17#include <initializer_list>
23#include "absl/container/flat_hash_map.h"
24#include "absl/log/check.h"
25#include "absl/strings/str_cat.h"
26#include "absl/strings/str_format.h"
27#include "absl/strings/string_view.h"
28#include "absl/types/span.h"
29#include "ortools/sat/cp_model.pb.h"
37 : builder_(builder), index_(
index) {}
40 DCHECK(builder_ !=
nullptr);
41 if (builder_ ==
nullptr)
return *
this;
42 builder_->MutableProto()
48std::string BoolVar::Name()
const {
49 if (builder_ ==
nullptr)
return "null";
50 const std::string&
name =
51 builder_->Proto().variables(
PositiveRef(index_)).name();
55 return absl::StrCat(
"Not(",
name,
")");
59std::string BoolVar::DebugString()
const {
60 if (builder_ ==
nullptr)
return "null";
62 return absl::StrFormat(
"Not(%s)",
Not().DebugString());
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),
90 os <<
var.DebugString();
94IntVar::IntVar(
int index, CpModelBuilder* builder)
95 : builder_(builder), index_(
index) {
100 if (
var.builder_ ==
nullptr) {
104 builder_ =
var.builder_;
105 index_ = builder_->GetOrCreateIntegerIndex(
var.index_);
110 if (builder_ !=
nullptr) {
111 const IntegerVariableProto&
proto = builder_->Proto().variables(index_);
112 DCHECK_EQ(2,
proto.domain_size());
113 DCHECK_GE(
proto.domain(0), 0);
114 DCHECK_LE(
proto.domain(1), 1);
116 return BoolVar(index_, builder_);
120 DCHECK(builder_ !=
nullptr);
121 if (builder_ ==
nullptr)
return *
this;
122 builder_->MutableProto()->mutable_variables(index_)->set_name(
name);
126std::string IntVar::Name()
const {
127 if (builder_ ==
nullptr)
return "null";
128 return builder_->Proto().variables(index_).name();
132 if (builder_ ==
nullptr)
return Domain();
137 if (builder_ ==
nullptr)
return "null";
147 const IntegerVariableProto& var_proto =
proto.variables(
index);
148 if (var_proto.name().empty() && var_proto.domain_size() == 2 &&
149 var_proto.domain(0) == var_proto.domain(1)) {
150 absl::StrAppend(&output, var_proto.domain(0));
152 if (var_proto.name().empty()) {
153 absl::StrAppend(&output,
"V",
index,
"(");
155 absl::StrAppend(&output, var_proto.name(),
"(");
159 if (var_proto.domain_size() == 2 &&
160 var_proto.domain(0) == var_proto.domain(1)) {
161 absl::StrAppend(&output, var_proto.domain(0),
")");
163 absl::StrAppend(&output, var_proto.domain(0),
", ", var_proto.domain(1),
177 DCHECK(
var.builder_ !=
nullptr);
180 variables_.push_back(
index);
181 coefficients_.push_back(1);
185 coefficients_.push_back(-1);
191 DCHECK(
var.builder_ !=
nullptr);
192 variables_.push_back(
var.index_);
193 coefficients_.push_back(1);
198LinearExpr LinearExpr::FromProto(
const LinearExpressionProto& expr_proto) {
200 for (
int i = 0;
i < expr_proto.vars_size(); ++
i) {
201 result.variables_.push_back(expr_proto.vars(
i));
202 result.coefficients_.push_back(expr_proto.coeffs(
i));
223LinearExpr LinearExpr::WeightedSum(absl::Span<const IntVar> vars,
224 absl::Span<const int64_t> coeffs) {
225 CHECK_EQ(vars.size(), coeffs.size());
227 for (
int i = 0;
i < vars.size(); ++
i) {
228 result += vars[
i] * coeffs[
i];
233LinearExpr LinearExpr::WeightedSum(absl::Span<const BoolVar> vars,
234 absl::Span<const int64_t> coeffs) {
235 CHECK_EQ(vars.size(), coeffs.size());
237 for (
int i = 0;
i < vars.size(); ++
i) {
238 result += vars[
i] * coeffs[
i];
256 constant_ += other.constant_;
257 variables_.insert(variables_.end(), other.variables_.begin(),
258 other.variables_.end());
259 coefficients_.insert(coefficients_.end(), other.coefficients_.begin(),
260 other.coefficients_.end());
265 constant_ -= other.constant_;
266 variables_.insert(variables_.end(), other.variables_.begin(),
267 other.variables_.end());
268 for (
const int64_t coeff : other.coefficients_) {
269 coefficients_.push_back(-coeff);
276 for (int64_t& coeff : coefficients_) coeff *= factor;
280std::string LinearExpr::DebugString(
const CpModelProto*
proto)
const {
282 for (
int i = 0;
i < variables_.size(); ++
i) {
283 const int64_t coeff = coefficients_[
i];
284 const std::string var_string =
proto ==
nullptr
285 ? absl::StrCat(
"V", variables_[
i])
289 absl::StrAppend(&result, var_string);
290 }
else if (coeff == -1) {
291 absl::StrAppend(&result,
"-", var_string);
292 }
else if (coeff != 0) {
293 absl::StrAppend(&result, coeff,
" * ", var_string);
295 }
else if (coeff == 1) {
296 absl::StrAppend(&result,
" + ", var_string);
297 }
else if (coeff > 0) {
298 absl::StrAppend(&result,
" + ", coeff,
" * ", var_string);
299 }
else if (coeff == -1) {
300 absl::StrAppend(&result,
" - ", var_string);
301 }
else if (coeff < 0) {
302 absl::StrAppend(&result,
" - ", -coeff,
" * ", var_string);
306 if (constant_ != 0) {
307 if (variables_.empty()) {
308 return absl::StrCat(constant_);
309 }
else if (constant_ > 0) {
310 absl::StrAppend(&result,
" + ", constant_);
312 absl::StrAppend(&result,
" - ", -constant_);
323DoubleLinearExpr::DoubleLinearExpr() =
default;
329DoubleLinearExpr::DoubleLinearExpr(
double constant) { constant_ = constant; }
348 absl::Span<const IntVar> vars, absl::Span<const double> coeffs) {
349 CHECK_EQ(vars.size(), coeffs.size());
351 for (
int i = 0;
i < vars.size(); ++
i) {
358 absl::Span<const BoolVar> vars, absl::Span<const double> coeffs) {
359 CHECK_EQ(vars.size(), coeffs.size());
361 for (
int i = 0;
i < vars.size(); ++
i) {
383 constant_ += expr.constant_;
384 variables_.insert(variables_.end(), expr.variables_.begin(),
385 expr.variables_.end());
386 coefficients_.insert(coefficients_.end(), expr.coefficients_.begin(),
387 expr.coefficients_.end());
392 variables_.push_back(
var.index_);
393 coefficients_.push_back(coeff);
400 variables_.push_back(
index);
401 coefficients_.push_back(coeff);
404 coefficients_.push_back(-coeff);
412 const std::vector<int>& indices = expr.
variables();
414 for (
int i = 0;
i < indices.size(); ++
i) {
415 variables_.push_back(indices[
i]);
416 coefficients_.push_back(1.0 *
static_cast<double>(
coefficients[
i]) * coeff);
433 constant_ -= expr.constant_;
434 variables_.insert(variables_.end(), expr.variables_.begin(),
435 expr.variables_.end());
437 coefficients_.push_back(-coeff);
444 for (
double& c : coefficients_) {
450std::string DoubleLinearExpr::DebugString(
const CpModelProto*
proto)
const {
452 for (
int i = 0;
i < variables_.size(); ++
i) {
453 const double coeff = coefficients_[
i];
454 const std::string var_string =
proto ==
nullptr
455 ? absl::StrCat(
"V", variables_[
i])
459 absl::StrAppend(&result, var_string);
460 }
else if (coeff == -1.0) {
461 absl::StrAppend(&result,
"-", var_string);
462 }
else if (coeff != 0.0) {
463 absl::StrAppend(&result, coeff,
" * ", var_string);
465 }
else if (coeff == 1.0) {
466 absl::StrAppend(&result,
" + ", var_string);
467 }
else if (coeff > 0.0) {
468 absl::StrAppend(&result,
" + ", coeff,
" * ", var_string);
469 }
else if (coeff == -1.0) {
470 absl::StrAppend(&result,
" - ", var_string);
471 }
else if (coeff < 0.0) {
472 absl::StrAppend(&result,
" - ", -coeff,
" * ", var_string);
476 if (constant_ != 0.0) {
477 if (variables_.empty()) {
478 return absl::StrCat(constant_);
479 }
else if (constant_ > 0.0) {
480 absl::StrAppend(&result,
" + ", constant_);
482 absl::StrAppend(&result,
" - ", -constant_);
504 proto_->add_enforcement_literal(
var.index_);
527 CHECK_EQ(tuple.size(),
proto_->table().vars_size());
528 for (
const int64_t t : tuple) {
529 proto_->mutable_table()->add_values(t);
533ReservoirConstraint::ReservoirConstraint(ConstraintProto*
proto,
538 *
proto_->mutable_reservoir()->add_time_exprs() =
539 builder_->LinearExprToProto(
time);
540 proto_->mutable_reservoir()->add_level_changes()->set_offset(level_change);
541 proto_->mutable_reservoir()->add_active_literals(
542 builder_->IndexFromConstant(1));
546 int64_t level_change,
548 *
proto_->mutable_reservoir()->add_time_exprs() =
549 builder_->LinearExprToProto(
time);
550 proto_->mutable_reservoir()->add_level_changes()->set_offset(level_change);
551 proto_->mutable_reservoir()->add_active_literals(is_active.index_);
555 int64_t transition_label) {
556 proto_->mutable_automaton()->add_transition_tail(
tail);
557 proto_->mutable_automaton()->add_transition_head(
head);
558 proto_->mutable_automaton()->add_transition_label(transition_label);
563 proto_->mutable_no_overlap_2d()->add_x_intervals(x_coordinate.index_);
564 proto_->mutable_no_overlap_2d()->add_y_intervals(y_coordinate.index_);
567CumulativeConstraint::CumulativeConstraint(ConstraintProto*
proto,
573 *
proto_->mutable_cumulative()->add_demands() =
574 builder_->LinearExprToProto(
demand);
580 : builder_(builder), index_(
index) {}
583 DCHECK(builder_ !=
nullptr);
584 if (builder_ ==
nullptr)
return *
this;
590 DCHECK(builder_ !=
nullptr);
593 builder_->
Proto().constraints(index_).interval().start());
597 DCHECK(builder_ !=
nullptr);
600 builder_->
Proto().constraints(index_).interval().size());
604 DCHECK(builder_ !=
nullptr);
607 builder_->
Proto().constraints(index_).interval().end());
611 DCHECK(builder_ !=
nullptr);
612 if (builder_ ==
nullptr)
return BoolVar();
613 return BoolVar(builder_->
Proto().constraints(index_).enforcement_literal(0),
618 if (builder_ ==
nullptr)
return "null";
619 return builder_->
Proto().constraints(index_).name();
623 if (builder_ ==
nullptr)
return "null";
626 const CpModelProto&
proto = builder_->
Proto();
627 const ConstraintProto& ct_proto =
proto.constraints(index_);
629 if (ct_proto.name().empty()) {
630 absl::StrAppend(&output,
"IntervalVar", index_,
"(");
632 absl::StrAppend(&output, ct_proto.name(),
"(");
647 cp_model_.set_name(
name);
650int CpModelBuilder::IndexFromConstant(int64_t
value) {
651 if (!constant_to_index_map_.contains(
value)) {
652 const int index = cp_model_.variables_size();
653 IntegerVariableProto*
const var_proto = cp_model_.add_variables();
654 var_proto->add_domain(
value);
655 var_proto->add_domain(
value);
658 return constant_to_index_map_[
value];
661int CpModelBuilder::GetOrCreateIntegerIndex(
int index) {
665 if (!bool_to_integer_index_map_.contains(
index)) {
667 const IntegerVariableProto& old_var = cp_model_.variables(
var);
668 const int new_index = cp_model_.variables_size();
669 IntegerVariableProto*
const new_var = cp_model_.add_variables();
670 new_var->add_domain(0);
671 new_var->add_domain(1);
672 if (!old_var.name().empty()) {
673 new_var->set_name(absl::StrCat(
"Not(", old_var.name(),
")"));
676 bool_to_integer_index_map_[
index] = new_index;
679 return bool_to_integer_index_map_[
index];
683 const int index = cp_model_.variables_size();
684 IntegerVariableProto*
const var_proto = cp_model_.add_variables();
685 for (
const auto&
interval : domain) {
686 var_proto->add_domain(
interval.start);
687 var_proto->add_domain(
interval.end);
693 const int index = cp_model_.variables_size();
694 IntegerVariableProto*
const var_proto = cp_model_.add_variables();
695 var_proto->add_domain(0);
696 var_proto->add_domain(1);
705 return BoolVar(IndexFromConstant(1),
this);
709 return BoolVar(IndexFromConstant(0),
this);
727 const int index = cp_model_.constraints_size();
728 ConstraintProto*
const ct = cp_model_.add_constraints();
729 ct->add_enforcement_literal(presence.index_);
730 IntervalConstraintProto*
const interval =
ct->mutable_interval();
739 const int index = cp_model_.constraints_size();
740 ConstraintProto*
const ct = cp_model_.add_constraints();
741 ct->add_enforcement_literal(presence.index_);
742 IntervalConstraintProto*
const interval =
ct->mutable_interval();
765 ConstraintProto*
const proto = cp_model_.add_constraints();
767 proto->mutable_bool_or()->add_literals(
lit.index_);
777 ConstraintProto*
const proto = cp_model_.add_constraints();
779 proto->mutable_at_most_one()->add_literals(
lit.index_);
785 ConstraintProto*
const proto = cp_model_.add_constraints();
787 proto->mutable_exactly_one()->add_literals(
lit.index_);
793 ConstraintProto*
const proto = cp_model_.add_constraints();
795 proto->mutable_bool_and()->add_literals(
lit.index_);
801 ConstraintProto*
const proto = cp_model_.add_constraints();
803 proto->mutable_bool_xor()->add_literals(
lit.index_);
808void CpModelBuilder::FillLinearTerms(
const LinearExpr& left,
810 LinearConstraintProto*
proto) {
815 proto->add_coeffs(coeff);
821 proto->add_coeffs(-coeff);
827 ConstraintProto*
const proto = cp_model_.add_constraints();
828 FillLinearTerms(left, right,
proto->mutable_linear());
830 proto->mutable_linear()->add_domain(rhs);
831 proto->mutable_linear()->add_domain(rhs);
837 ConstraintProto*
const proto = cp_model_.add_constraints();
838 FillLinearTerms(left, right,
proto->mutable_linear());
840 proto->mutable_linear()->add_domain(rhs);
841 proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::max());
847 ConstraintProto*
const proto = cp_model_.add_constraints();
848 FillLinearTerms(left, right,
proto->mutable_linear());
850 proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::min());
851 proto->mutable_linear()->add_domain(rhs);
857 ConstraintProto*
const proto = cp_model_.add_constraints();
858 FillLinearTerms(left, right,
proto->mutable_linear());
860 proto->mutable_linear()->add_domain(rhs + 1);
861 proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::max());
867 ConstraintProto*
const proto = cp_model_.add_constraints();
868 FillLinearTerms(left, right,
proto->mutable_linear());
870 proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::min());
871 proto->mutable_linear()->add_domain(rhs - 1);
877 ConstraintProto*
const proto = cp_model_.add_constraints();
879 proto->mutable_linear()->add_vars(
x);
882 proto->mutable_linear()->add_coeffs(coeff);
884 const int64_t cst = expr.
constant();
885 for (
const auto&
i : domain) {
886 proto->mutable_linear()->add_domain(
i.start - cst);
887 proto->mutable_linear()->add_domain(
i.end - cst);
894 ConstraintProto*
const proto = cp_model_.add_constraints();
895 FillLinearTerms(left, right,
proto->mutable_linear());
897 proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::min());
898 proto->mutable_linear()->add_domain(rhs - 1);
899 proto->mutable_linear()->add_domain(rhs + 1);
900 proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::max());
905 ConstraintProto*
const proto = cp_model_.add_constraints();
907 auto* expr =
proto->mutable_all_diff()->add_exprs();
908 expr->add_vars(
var.index_);
915 ConstraintProto*
const proto = cp_model_.add_constraints();
917 *
proto->mutable_all_diff()->add_exprs() = LinearExprToProto(expr);
923 std::initializer_list<LinearExpr> exprs) {
924 ConstraintProto*
const proto = cp_model_.add_constraints();
926 *
proto->mutable_all_diff()->add_exprs() = LinearExprToProto(expr);
933 ConstraintProto*
const proto = cp_model_.add_constraints();
934 proto->mutable_element()->set_index(
index.index_);
935 proto->mutable_element()->set_target(target.index_);
937 proto->mutable_element()->add_vars(
var.index_);
943 absl::Span<const int64_t> values,
945 ConstraintProto*
const proto = cp_model_.add_constraints();
946 proto->mutable_element()->set_index(
index.index_);
947 proto->mutable_element()->set_target(target.index_);
948 for (int64_t
value : values) {
949 proto->mutable_element()->add_vars(IndexFromConstant(
value));
963 absl::Span<const IntVar> vars) {
964 ConstraintProto*
const proto = cp_model_.add_constraints();
966 proto->mutable_table()->add_vars(
var.index_);
972 absl::Span<const IntVar> vars) {
973 ConstraintProto*
const proto = cp_model_.add_constraints();
975 proto->mutable_table()->add_vars(
var.index_);
977 proto->mutable_table()->set_negated(
true);
982 absl::Span<const IntVar> variables,
983 absl::Span<const IntVar> inverse_variables) {
984 ConstraintProto*
const proto = cp_model_.add_constraints();
986 proto->mutable_inverse()->add_f_direct(
var.index_);
988 for (
const IntVar&
var : inverse_variables) {
989 proto->mutable_inverse()->add_f_inverse(
var.index_);
996 ConstraintProto*
const proto = cp_model_.add_constraints();
997 proto->mutable_reservoir()->set_min_level(min_level);
998 proto->mutable_reservoir()->set_max_level(max_level);
1003 absl::Span<const IntVar> transition_variables,
int starting_state,
1004 absl::Span<const int> final_states) {
1005 ConstraintProto*
const proto = cp_model_.add_constraints();
1006 for (
const IntVar&
var : transition_variables) {
1007 proto->mutable_automaton()->add_vars(
var.index_);
1009 proto->mutable_automaton()->set_starting_state(starting_state);
1010 for (
const int final_state : final_states) {
1011 proto->mutable_automaton()->add_final_states(final_state);
1016LinearExpressionProto CpModelBuilder::LinearExprToProto(
const LinearExpr& expr,
1018 LinearExpressionProto expr_proto;
1020 expr_proto.add_vars(
var);
1022 const int64_t mult = negate ? -1 : 1;
1024 expr_proto.add_coeffs(coeff * mult);
1026 expr_proto.set_offset(expr.
constant() * mult);
1031 absl::Span<const IntVar> vars) {
1032 ConstraintProto*
ct = cp_model_.add_constraints();
1033 *
ct->mutable_lin_max()->mutable_target() =
1034 LinearExprToProto(target,
true);
1036 *
ct->mutable_lin_max()->add_exprs() =
1037 LinearExprToProto(
var,
true);
1043 absl::Span<const LinearExpr> exprs) {
1044 ConstraintProto*
ct = cp_model_.add_constraints();
1045 *
ct->mutable_lin_max()->mutable_target() =
1046 LinearExprToProto(target,
true);
1048 *
ct->mutable_lin_max()->add_exprs() =
1049 LinearExprToProto(expr,
true);
1055 const LinearExpr& target, std::initializer_list<LinearExpr> exprs) {
1056 ConstraintProto*
ct = cp_model_.add_constraints();
1057 *
ct->mutable_lin_max()->mutable_target() =
1058 LinearExprToProto(target,
true);
1060 *
ct->mutable_lin_max()->add_exprs() =
1061 LinearExprToProto(expr,
true);
1067 absl::Span<const IntVar> vars) {
1068 ConstraintProto*
ct = cp_model_.add_constraints();
1069 *
ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1071 *
ct->mutable_lin_max()->add_exprs() = LinearExprToProto(
var);
1077 absl::Span<const LinearExpr> exprs) {
1078 ConstraintProto*
ct = cp_model_.add_constraints();
1079 *
ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1081 *
ct->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1087 const LinearExpr& target, std::initializer_list<LinearExpr> exprs) {
1088 ConstraintProto*
ct = cp_model_.add_constraints();
1089 *
ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1091 *
ct->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1099 ConstraintProto*
const proto = cp_model_.add_constraints();
1100 *
proto->mutable_int_div()->mutable_target() = LinearExprToProto(target);
1101 *
proto->mutable_int_div()->add_exprs() = LinearExprToProto(numerator);
1102 *
proto->mutable_int_div()->add_exprs() = LinearExprToProto(denominator);
1108 ConstraintProto*
const proto = cp_model_.add_constraints();
1109 *
proto->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1110 *
proto->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1111 *
proto->mutable_lin_max()->add_exprs() =
1112 LinearExprToProto(expr,
true);
1119 ConstraintProto*
const proto = cp_model_.add_constraints();
1120 *
proto->mutable_int_mod()->mutable_target() = LinearExprToProto(target);
1121 *
proto->mutable_int_mod()->add_exprs() = LinearExprToProto(
var);
1122 *
proto->mutable_int_mod()->add_exprs() = LinearExprToProto(mod);
1127 const LinearExpr& target, absl::Span<const IntVar> vars) {
1128 ConstraintProto*
const proto = cp_model_.add_constraints();
1129 *
proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1131 *
proto->mutable_int_prod()->add_exprs() = LinearExprToProto(
var);
1137 const LinearExpr& target, absl::Span<const LinearExpr> exprs) {
1138 ConstraintProto*
const proto = cp_model_.add_constraints();
1139 *
proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1141 *
proto->mutable_int_prod()->add_exprs() = LinearExprToProto(expr);
1147 const LinearExpr& target, std::initializer_list<LinearExpr> exprs) {
1148 ConstraintProto*
const proto = cp_model_.add_constraints();
1149 *
proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1151 *
proto->mutable_int_prod()->add_exprs() = LinearExprToProto(expr);
1158 ConstraintProto*
const proto = cp_model_.add_constraints();
1159 *
proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1160 *
proto->mutable_int_prod()->add_exprs() = LinearExprToProto(left);
1161 *
proto->mutable_int_prod()->add_exprs() = LinearExprToProto(right);
1167 ConstraintProto*
const proto = cp_model_.add_constraints();
1169 proto->mutable_no_overlap()->add_intervals(
var.index_);
1179 ConstraintProto*
const proto = cp_model_.add_constraints();
1180 *
proto->mutable_cumulative()->mutable_capacity() =
1181 LinearExprToProto(capacity);
1188 cp_model_.mutable_objective()->add_vars(
x);
1191 cp_model_.mutable_objective()->add_coeffs(coeff);
1193 cp_model_.mutable_objective()->set_offset(expr.
constant());
1199 cp_model_.mutable_objective()->add_vars(
x);
1202 cp_model_.mutable_objective()->add_coeffs(-coeff);
1204 cp_model_.mutable_objective()->set_offset(-expr.
constant());
1205 cp_model_.mutable_objective()->set_scaling_factor(-1.0);
1211 cp_model_.mutable_floating_point_objective()->add_vars(expr.
variables()[
i]);
1212 cp_model_.mutable_floating_point_objective()->add_coeffs(
1215 cp_model_.mutable_floating_point_objective()->set_offset(expr.
constant());
1216 cp_model_.mutable_floating_point_objective()->set_maximize(
false);
1222 cp_model_.mutable_floating_point_objective()->add_vars(expr.
variables()[
i]);
1223 cp_model_.mutable_floating_point_objective()->add_coeffs(
1226 cp_model_.mutable_floating_point_objective()->set_offset(expr.
constant());
1227 cp_model_.mutable_floating_point_objective()->set_maximize(
true);
1231 cp_model_.clear_objective();
1232 cp_model_.clear_floating_point_objective();
1236 return cp_model_.has_objective() || cp_model_.has_floating_point_objective();
1240 absl::Span<const IntVar> variables,
1241 DecisionStrategyProto::VariableSelectionStrategy var_strategy,
1242 DecisionStrategyProto::DomainReductionStrategy domain_strategy) {
1243 DecisionStrategyProto*
const proto = cp_model_.add_search_strategy();
1245 LinearExpressionProto* expr =
proto->add_exprs();
1246 if (
var.index_ >= 0) {
1247 expr->add_vars(
var.index_);
1248 expr->add_coeffs(1);
1251 expr->add_coeffs(-1);
1252 expr->set_offset(1);
1255 proto->set_variable_selection_strategy(var_strategy);
1256 proto->set_domain_reduction_strategy(domain_strategy);
1260 absl::Span<const BoolVar> variables,
1261 DecisionStrategyProto::VariableSelectionStrategy var_strategy,
1262 DecisionStrategyProto::DomainReductionStrategy domain_strategy) {
1263 DecisionStrategyProto*
const proto = cp_model_.add_search_strategy();
1265 LinearExpressionProto* expr =
proto->add_exprs();
1266 if (
var.index_ >= 0) {
1267 expr->add_vars(
var.index_);
1268 expr->add_coeffs(1);
1271 expr->add_coeffs(-1);
1272 expr->set_offset(1);
1275 proto->set_variable_selection_strategy(var_strategy);
1276 proto->set_domain_reduction_strategy(domain_strategy);
1280 absl::Span<const LinearExpr> expressions,
1281 DecisionStrategyProto::VariableSelectionStrategy var_strategy,
1282 DecisionStrategyProto::DomainReductionStrategy domain_strategy) {
1283 DecisionStrategyProto*
const proto = cp_model_.add_search_strategy();
1285 *
proto->add_exprs() = LinearExprToProto(expr);
1287 proto->set_variable_selection_strategy(var_strategy);
1288 proto->set_domain_reduction_strategy(domain_strategy);
1292 std::initializer_list<LinearExpr> expressions,
1293 DecisionStrategyProto::VariableSelectionStrategy var_strategy,
1294 DecisionStrategyProto::DomainReductionStrategy domain_strategy) {
1295 DecisionStrategyProto*
const proto = cp_model_.add_search_strategy();
1297 *
proto->add_exprs() = LinearExprToProto(expr);
1299 proto->set_variable_selection_strategy(var_strategy);
1300 proto->set_domain_reduction_strategy(domain_strategy);
1304 cp_model_.mutable_solution_hint()->add_vars(
var.index_);
1305 cp_model_.mutable_solution_hint()->add_values(
value);
1309 if (
var.index_ >= 0) {
1310 cp_model_.mutable_solution_hint()->add_vars(
var.index_);
1311 cp_model_.mutable_solution_hint()->add_values(
value);
1313 cp_model_.mutable_solution_hint()->add_vars(
PositiveRef(
var.index_));
1314 cp_model_.mutable_solution_hint()->add_values(!
value);
1319 cp_model_.mutable_solution_hint()->Clear();
1323 cp_model_.mutable_assumptions()->Add(
lit.index_);
1328 cp_model_.mutable_assumptions()->Add(
lit.index_);
1333 cp_model_.mutable_assumptions()->Clear();
1338 clone.ResetAndImport(cp_model_);
1342void CpModelBuilder::ResetAndImport(
const CpModelProto& model_proto) {
1343 cp_model_ = model_proto;
1345 constant_to_index_map_.clear();
1346 for (
int i = 0;
i < cp_model_.variables_size(); ++
i) {
1347 const IntegerVariableProto&
var = cp_model_.variables(
i);
1348 if (
var.domain_size() == 2 &&
var.domain(0) ==
var.domain(1)) {
1349 constant_to_index_map_[
var.domain(0)] =
i;
1353 bool_to_integer_index_map_.clear();
1358 CHECK_LT(
index, cp_model_.variables_size());
1359 const IntegerVariableProto&
proto = cp_model_.variables(
index);
1360 CHECK_EQ(2,
proto.domain_size())
1361 <<
"CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1363 CHECK_GE(0,
proto.domain(0))
1364 <<
"CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1366 CHECK_LE(1,
proto.domain(1))
1367 <<
"CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1374 CHECK_LT(
index, cp_model_.variables_size());
1380 CHECK_LT(
index, cp_model_.constraints_size());
1381 const ConstraintProto&
ct = cp_model_.constraints(
index);
1382 CHECK_EQ(
ct.constraint_case(), ConstraintProto::kInterval)
1383 <<
"CpModelBuilder::GetIntervalVarFromProtoIndex: the referenced "
1384 "object is not an interval variable";
1395 const std::vector<int>& variables = expr.
variables();
1397 for (
int i = 0;
i < variables.size(); ++
i) {
1404 const int ref =
x.index_;
1406 return r.solution(ref) == 1;
virtual std::string DebugString() const
Constraint(Solver *const solver)
IntVar(Solver *s)
-------— IntVar -------—
LinearExpr & operator+=(const LinearExpr &rhs)
LinearExpr & operator-=(const LinearExpr &rhs)
LinearExpr & operator*=(double rhs)
virtual std::string name() const
Object naming.
std::string DebugString() const override
void AddTransition(int tail, int head, int64_t transition_label)
Adds a transitions to the automaton.
BoolVar Not() const
Returns the logical negation of the current Boolean variable.
void AddArc(int tail, int head, BoolVar literal)
Constraint WithName(absl::string_view name)
Sets the name of the constraint.
Constraint OnlyEnforceIf(absl::Span< const BoolVar > literals)
absl::string_view Name() const
Returns the name of the constraint (or the empty string if not set).
Constraint AddVariableElement(IntVar index, absl::Span< const IntVar > variables, IntVar target)
Adds the element constraint: variables[index] == target.
bool HasObjective() const
Checks whether the model contains an objective.
TableConstraint AddForbiddenAssignments(absl::Span< const IntVar > vars)
BoolVar GetBoolVarFromProtoIndex(int index)
Returns the Boolean variable from its index in the proto.
IntVar NewIntVar(const Domain &domain)
Creates an integer variable with the given domain.
Constraint AddInverseConstraint(absl::Span< const IntVar > variables, absl::Span< const IntVar > inverse_variables)
void Minimize(const LinearExpr &expr)
Adds a linear minimization objective.
NoOverlap2DConstraint AddNoOverlap2D()
Constraint AddBoolXor(absl::Span< const BoolVar > literals)
Adds the constraint that an odd number of literals is true.
IntervalVar NewIntervalVar(const LinearExpr &start, const LinearExpr &size, const LinearExpr &end)
Creates an interval variable from 3 affine expressions.
IntVar GetIntVarFromProtoIndex(int index)
Returns the integer variable from its index in the proto.
Constraint AddMultiplicationEquality(const LinearExpr &target, absl::Span< const LinearExpr > exprs)
Adds target == prod(exprs).
CpModelBuilder Clone() const
Returns a cloned version of the current model.
IntVar NewConstant(int64_t value)
Constraint AddBoolAnd(absl::Span< const BoolVar > literals)
Adds the constraint that all literals must be true.
Constraint AddMaxEquality(const LinearExpr &target, absl::Span< const IntVar > vars)
Adds target == max(vars).
void Maximize(const LinearExpr &expr)
Adds a linear maximization objective.
void FixVariable(IntVar var, int64_t value)
ReservoirConstraint AddReservoirConstraint(int64_t min_level, int64_t max_level)
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.
Constraint AddLessOrEqual(const LinearExpr &left, const LinearExpr &right)
Adds left <= right.
IntervalVar NewOptionalIntervalVar(const LinearExpr &start, const LinearExpr &size, const LinearExpr &end, BoolVar presence)
void ClearAssumptions()
Remove all assumptions from the model.
Constraint AddLinearConstraint(const LinearExpr &expr, const Domain &domain)
Adds expr in domain.
AutomatonConstraint AddAutomaton(absl::Span< const IntVar > transition_variables, int starting_state, absl::Span< const int > final_states)
void AddHint(IntVar var, int64_t value)
Adds hinting to a variable.
Constraint AddAllDifferent(absl::Span< const IntVar > vars)
This constraint forces all variables to have different values.
IntervalVar GetIntervalVarFromProtoIndex(int index)
Returns the interval variable from its index in the proto.
Constraint AddExactlyOne(absl::Span< const BoolVar > literals)
Exactly one literal is true. Sum literals == 1.
Constraint AddMinEquality(const LinearExpr &target, absl::Span< const IntVar > vars)
Adds target == min(vars).
void AddAssumption(BoolVar lit)
Adds a literal to the model as assumptions.
bool ExportToFile(absl::string_view filename) const
Export the model to file.
Constraint AddGreaterOrEqual(const LinearExpr &left, const LinearExpr &right)
Adds left >= right.
Constraint AddLessThan(const LinearExpr &left, const LinearExpr &right)
Adds left < right.
TableConstraint AddAllowedAssignments(absl::Span< const IntVar > vars)
Constraint AddElement(IntVar index, absl::Span< const int64_t > values, IntVar target)
Adds the element constraint: values[index] == target.
MultipleCircuitConstraint AddMultipleCircuitConstraint()
Constraint AddNoOverlap(absl::Span< const IntervalVar > vars)
const CpModelProto & Proto() const
BoolVar NewBoolVar()
Creates a Boolean variable.
friend class CumulativeConstraint
CpModelProto * MutableProto()
Constraint AddNotEqual(const LinearExpr &left, const LinearExpr &right)
Adds left != right.
Constraint AddAtLeastOne(absl::Span< const BoolVar > literals)
Same as AddBoolOr(). Sum literals >= 1.
void ClearObjective()
Removes the objective from the model.
Constraint AddAtMostOne(absl::Span< const BoolVar > literals)
At most one literal is true. Sum literals <= 1.
void ClearHints()
Removes all hints.
void AddAssumptions(absl::Span< const BoolVar > literals)
Adds multiple literals to the model as assumptions.
Constraint AddGreaterThan(const LinearExpr &left, const LinearExpr &right)
Adds left > right.
CircuitConstraint AddCircuitConstraint()
Constraint AddDivisionEquality(const LinearExpr &target, const LinearExpr &numerator, const LinearExpr &denominator)
Adds target = num / denom (integer division rounded towards 0).
Constraint AddEquality(const LinearExpr &left, const LinearExpr &right)
Adds left == right.
void SetName(absl::string_view name)
Sets the name of the model.
Constraint AddAbsEquality(const LinearExpr &target, const LinearExpr &expr)
Adds target == abs(expr).
friend class ReservoirConstraint
Constraint AddBoolOr(absl::Span< const BoolVar > literals)
Adds the constraint that at least one of the literals must be true.
IntervalVar NewFixedSizeIntervalVar(const LinearExpr &start, int64_t size)
Creates an interval variable with a fixed size.
CumulativeConstraint AddCumulative(LinearExpr capacity)
Constraint AddModuloEquality(const LinearExpr &target, const LinearExpr &var, const LinearExpr &mod)
Adds target = var % mod.
IntervalVar NewOptionalFixedSizeIntervalVar(const LinearExpr &start, int64_t size, BoolVar presence)
Creates an optional interval variable with a fixed size.
void AddDemand(IntervalVar interval, LinearExpr demand)
Adds a pair (interval, demand) to the constraint.
const std::vector< double > & coefficients() const
Returns the vector of coefficients.
DoubleLinearExpr & AddTerm(IntVar var, double coeff)
Adds a term (var * coeff) to the linear expression.
double constant() const
Returns the constant term.
const std::vector< int > & variables() const
Returns the vector of variable indices.
std::string DebugString(const CpModelProto *proto=nullptr) const
Debug string. See the documentation for LinearExpr::DebugString().
std::string DebugString() const
IntervalVar WithName(absl::string_view name)
Sets the name of the variable.
LinearExpr StartExpr() const
std::string Name() const
Returns the name of the interval (or the empty string if not set).
LinearExpr EndExpr() const
LinearExpr SizeExpr() const
BoolVar PresenceBoolVar() const
std::string DebugString() const
Returns a debug string.
std::string DebugString(const CpModelProto *proto=nullptr) const
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< int > & variables() const
Returns the vector of variable indices.
const std::vector< int64_t > & coefficients() const
Returns the vector of coefficients.
void AddArc(int tail, int head, BoolVar literal)
void AddRectangle(IntervalVar x_coordinate, IntervalVar y_coordinate)
Adds a rectangle (parallel to the axis) to the constraint.
void AddOptionalEvent(LinearExpr time, int64_t level_change, BoolVar is_active)
void AddEvent(LinearExpr time, int64_t level_change)
void AddTuple(absl::Span< const int64_t > tuple)
Adds a tuple of possible values to the constraint.
CpModelProto proto
The output proto.
const std::string name
A name for logging purposes.
absl::Span< const double > coefficients
std::string VarDebugString(const CpModelProto &proto, int index)
bool RefIsPositive(int ref)
bool WriteModelProtoToFile(const M &proto, absl::string_view filename)
std::ostream & operator<<(std::ostream &os, const BoolVar &var)
void FillDomainInProto(const Domain &domain, ProtoWithDomain *proto)
Serializes a Domain into the domain field of a proto.
Domain ReadDomainFromProto(const ProtoWithDomain &proto)
Reads a Domain from the domain field of a proto.
int64_t SolutionIntegerValue(const CpSolverResponse &r, const LinearExpr &expr)
Evaluates the value of an linear expression in a solver response.
int NegatedRef(int ref)
Small utility functions to deal with negative variable/literal references.
bool SolutionBooleanValue(const CpSolverResponse &r, BoolVar x)
Evaluates the value of a Boolean literal in a solver response.
In SWIG mode, we don't want anything besides these top-level includes.
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)