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"
37 : builder_(builder), index_(index) {}
40 DCHECK(builder_ !=
nullptr);
41 if (builder_ ==
nullptr)
return *
this;
42 builder_->MutableProto()
49 if (builder_ ==
nullptr)
return "null";
50 absl::string_view name =
51 builder_->Proto().variables(
PositiveRef(index_)).name();
53 return std::string(name);
55 return absl::StrCat(
"Not(", name,
")");
60 if (builder_ ==
nullptr)
return "null";
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());
77 output.append(var_proto.
domain(0) == 0 ?
"false)" :
"true)");
79 absl::StrAppend(&output, var_proto.
domain(0),
", ", var_proto.
domain(1),
95 : builder_(builder), index_(index) {
100 if (var.builder_ ==
nullptr) {
104 builder_ = var.builder_;
105 index_ = builder_->GetOrCreateIntegerIndex(var.index_);
110 if (builder_ !=
nullptr) {
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);
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";
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(),
"(");
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);
178 const int index = var.index_;
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);
201 result.variables_.push_back(expr_proto.
vars(
i));
202 result.coefficients_.push_back(expr_proto.
coeffs(
i));
209 for (
const IntVar& var : vars) {
217 for (
const BoolVar& var : 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];
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];
245 result += var * coefficient;
251 result += var * coefficient;
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;
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;
333 for (
const IntVar& var : vars) {
341 for (
const BoolVar& var : vars) {
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);
398 const int index = var.index_;
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(
static_cast<double>(
coefficients[
i]) * coeff);
418 constant_ +=
static_cast<double>(expr.
constant()) * coeff;
434 constant_ -= expr.constant_;
435 variables_.insert(variables_.end(), expr.variables_.begin(),
436 expr.variables_.end());
438 coefficients_.push_back(-coeff);
445 for (
double& c : coefficients_) {
453 for (
int i = 0;
i < variables_.size(); ++
i) {
454 const double coeff = coefficients_[
i];
455 const std::string var_string = proto ==
nullptr
456 ? absl::StrCat(
"V", variables_[
i])
460 absl::StrAppend(&result, var_string);
461 }
else if (coeff == -1.0) {
462 absl::StrAppend(&result,
"-", var_string);
463 }
else if (coeff != 0.0) {
464 absl::StrAppend(&result, coeff,
" * ", var_string);
466 }
else if (coeff == 1.0) {
467 absl::StrAppend(&result,
" + ", var_string);
468 }
else if (coeff > 0.0) {
469 absl::StrAppend(&result,
" + ", coeff,
" * ", var_string);
470 }
else if (coeff == -1.0) {
471 absl::StrAppend(&result,
" - ", var_string);
472 }
else if (coeff < 0.0) {
473 absl::StrAppend(&result,
" - ", -coeff,
" * ", var_string);
477 if (constant_ != 0.0) {
478 if (variables_.empty()) {
479 return absl::StrCat(constant_);
480 }
else if (constant_ > 0.0) {
481 absl::StrAppend(&result,
" + ", constant_);
483 absl::StrAppend(&result,
" - ", -constant_);
504 for (
const BoolVar& var : literals) {
505 proto_->add_enforcement_literal(var.index_);
511 proto_->add_enforcement_literal(literal.index_);
516 proto_->mutable_circuit()->add_tails(tail);
517 proto_->mutable_circuit()->add_heads(head);
518 proto_->mutable_circuit()->add_literals(literal.index_);
522 proto_->mutable_routes()->add_tails(tail);
523 proto_->mutable_routes()->add_heads(head);
524 proto_->mutable_routes()->add_literals(literal.index_);
528 CHECK_EQ(tuple.size(),
proto_->table().exprs_size());
529 for (
const int64_t t : tuple) {
530 proto_->mutable_table()->add_values(t);
539 *
proto_->mutable_reservoir()->add_time_exprs() =
540 builder_->LinearExprToProto(time);
541 proto_->mutable_reservoir()->add_level_changes()->set_offset(level_change);
542 proto_->mutable_reservoir()->add_active_literals(
543 builder_->IndexFromConstant(1));
546void ReservoirConstraint::AddOptionalEvent(
LinearExpr time,
547 int64_t level_change,
550 builder_->LinearExprToProto(time);
556 int64_t transition_label) {
557 proto_->mutable_automaton()->add_transition_tail(tail);
558 proto_->mutable_automaton()->add_transition_head(head);
559 proto_->mutable_automaton()->add_transition_label(transition_label);
562void NoOverlap2DConstraint::AddRectangle(
IntervalVar x_coordinate,
568CumulativeConstraint::CumulativeConstraint(ConstraintProto* proto,
569 CpModelBuilder* builder)
572void CumulativeConstraint::AddDemand(IntervalVar interval, LinearExpr demand) {
575 builder_->LinearExprToProto(
demand);
581 : builder_(builder), index_(index) {}
584 DCHECK(builder_ !=
nullptr);
585 if (builder_ ==
nullptr)
return *
this;
586 builder_->MutableProto()->mutable_constraints(index_)->set_name(name);
591 DCHECK(builder_ !=
nullptr);
594 builder_->Proto().constraints(index_).interval().start());
598 DCHECK(builder_ !=
nullptr);
601 builder_->Proto().constraints(index_).interval().size());
605 DCHECK(builder_ !=
nullptr);
608 builder_->Proto().constraints(index_).interval().end());
612 DCHECK(builder_ !=
nullptr);
613 if (builder_ ==
nullptr)
return BoolVar();
614 if (builder_->Proto().constraints(index_).enforcement_literal_size() == 0) {
615 return builder_->TrueVar();
617 return BoolVar(builder_->Proto().constraints(index_).enforcement_literal(0),
622 if (builder_ ==
nullptr)
return "null";
623 return builder_->Proto().constraints(index_).name();
627 if (builder_ ==
nullptr)
return "null";
633 if (ct_proto.
name().empty()) {
634 absl::StrAppend(&output,
"IntervalVar", index_,
"(");
636 absl::StrAppend(&output, ct_proto.
name(),
"(");
651 cp_model_.set_name(name);
654int CpModelBuilder::IndexFromConstant(int64_t value) {
655 if (!constant_to_index_map_.contains(
value)) {
656 const int index = cp_model_.variables_size();
660 constant_to_index_map_[
value] = index;
662 return constant_to_index_map_[
value];
665int CpModelBuilder::GetOrCreateIntegerIndex(
int index) {
669 if (!bool_to_integer_index_map_.contains(index)) {
671 const IntegerVariableProto& old_var = cp_model_.variables(var);
672 const int new_index = cp_model_.variables_size();
673 IntegerVariableProto*
const new_var = cp_model_.add_variables();
674 new_var->add_domain(0);
675 new_var->add_domain(1);
676 if (!old_var.name().empty()) {
677 new_var->set_name(absl::StrCat(
"Not(", old_var.name(),
")"));
679 AddEquality(IntVar(new_index,
this), BoolVar(index,
this));
680 bool_to_integer_index_map_[index] = new_index;
683 return bool_to_integer_index_map_[index];
687 const int index = cp_model_.variables_size();
689 for (
const auto& interval : domain) {
693 return IntVar(index,
this);
697 const int index = cp_model_.variables_size();
704IntVar CpModelBuilder::NewConstant(int64_t value) {
709 return BoolVar(IndexFromConstant(1),
this);
713 return BoolVar(IndexFromConstant(0),
this);
719 const int index = cp_model_.constraints_size();
730 const int index = cp_model_.constraints_size();
735 *interval->
mutable_end() = LinearExprToProto(start);
744 const int index = cp_model_.constraints_size();
756 const int index = cp_model_.constraints_size();
762 *interval->
mutable_end() = LinearExprToProto(start);
772 const int index = var.
index();
777 cp_model_.mutable_variables(
NegatedRef(index)));
788Constraint CpModelBuilder::AddAtLeastOne(absl::Span<const BoolVar> literals) {
792Constraint CpModelBuilder::AddAtMostOne(absl::Span<const BoolVar> literals) {
793 ConstraintProto*
const proto = cp_model_.add_constraints();
794 for (
const BoolVar& lit : literals) {
795 proto->mutable_at_most_one()->add_literals(lit.index_);
800Constraint CpModelBuilder::AddExactlyOne(absl::Span<const BoolVar> literals) {
801 ConstraintProto*
const proto = cp_model_.add_constraints();
802 BoolArgumentProto*
const exactly_one = proto->mutable_exactly_one();
803 for (
const BoolVar& lit : literals) exactly_one->add_literals(lit.index_);
804 return Constraint(proto);
807Constraint CpModelBuilder::AddBoolAnd(absl::Span<const BoolVar> literals) {
808 ConstraintProto*
const proto = cp_model_.add_constraints();
809 for (
const BoolVar& lit : literals) {
810 proto->mutable_bool_and()->add_literals(lit.index_);
812 return Constraint(proto);
815Constraint CpModelBuilder::AddBoolXor(absl::Span<const BoolVar> literals) {
816 ConstraintProto*
const proto = cp_model_.add_constraints();
817 for (
const BoolVar& lit : literals) {
818 proto->mutable_bool_xor()->add_literals(lit.index_);
820 return Constraint(proto);
823void CpModelBuilder::FillLinearTerms(
const LinearExpr& left,
826 for (
const int x :
left.variables()) {
829 for (
const int64_t coeff :
left.coefficients()) {
830 proto->add_coeffs(coeff);
832 for (
const int x : right.variables()) {
835 for (
const int64_t coeff : right.coefficients()) {
836 proto->add_coeffs(-coeff);
842 ConstraintProto*
const proto = cp_model_.add_constraints();
843 FillLinearTerms(
left, right, proto->mutable_linear());
844 const int64_t
rhs = right.constant() -
left.constant();
845 proto->mutable_linear()->add_domain(
rhs);
846 proto->mutable_linear()->add_domain(
rhs);
847 return Constraint(proto);
852 ConstraintProto*
const proto = cp_model_.add_constraints();
853 FillLinearTerms(
left, right, proto->mutable_linear());
854 const int64_t
rhs = right.constant() -
left.constant();
855 proto->mutable_linear()->add_domain(
rhs);
856 proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::max());
857 return Constraint(proto);
862 ConstraintProto*
const proto = cp_model_.add_constraints();
863 FillLinearTerms(
left, right, proto->mutable_linear());
864 const int64_t
rhs = right.constant() -
left.constant();
865 proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::min());
866 proto->mutable_linear()->add_domain(
rhs);
867 return Constraint(proto);
892 ConstraintProto*
const proto = cp_model_.add_constraints();
893 for (
const int x : expr.variables()) {
894 proto->mutable_linear()->add_vars(x);
896 for (
const int64_t coeff : expr.coefficients()) {
897 proto->mutable_linear()->add_coeffs(coeff);
899 const int64_t cst = expr.constant();
900 for (
const auto&
i : domain) {
901 proto->mutable_linear()->add_domain(
i.start - cst);
902 proto->mutable_linear()->add_domain(
i.end - cst);
904 return Constraint(proto);
909 ConstraintProto*
const proto = cp_model_.add_constraints();
910 FillLinearTerms(
left, right, proto->mutable_linear());
911 const int64_t
rhs = right.constant() -
left.constant();
912 proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::min());
913 proto->mutable_linear()->add_domain(
rhs - 1);
914 proto->mutable_linear()->add_domain(
rhs + 1);
915 proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::max());
916 return Constraint(proto);
919Constraint CpModelBuilder::AddAllDifferent(absl::Span<const IntVar> vars) {
920 ConstraintProto*
const proto = cp_model_.add_constraints();
921 for (
const IntVar& var : vars) {
922 auto* expr = proto->mutable_all_diff()->add_exprs();
923 expr->add_vars(var.index_);
926 return Constraint(proto);
929Constraint CpModelBuilder::AddAllDifferent(absl::Span<const LinearExpr> exprs) {
930 ConstraintProto*
const proto = cp_model_.add_constraints();
931 for (
const LinearExpr& expr : exprs) {
932 *proto->mutable_all_diff()->add_exprs() = LinearExprToProto(expr);
934 return Constraint(proto);
938 std::initializer_list<LinearExpr> exprs) {
939 ConstraintProto*
const proto = cp_model_.add_constraints();
940 for (
const LinearExpr& expr : exprs) {
941 *proto->mutable_all_diff()->add_exprs() = LinearExprToProto(expr);
943 return Constraint(proto);
948 ConstraintProto*
const proto = cp_model_.add_constraints();
949 *proto->mutable_element()->mutable_linear_index() = LinearExprToProto(index);
950 *proto->mutable_element()->mutable_linear_target() =
951 LinearExprToProto(target);
952 for (
const IntVar& var : variables) {
953 *proto->mutable_element()->add_exprs() = LinearExprToProto(var);
955 return Constraint(proto);
959 absl::Span<const int64_t> values,
961 ConstraintProto*
const proto = cp_model_.add_constraints();
962 *proto->mutable_element()->mutable_linear_index() = LinearExprToProto(index);
963 *proto->mutable_element()->mutable_linear_target() =
964 LinearExprToProto(target);
965 for (int64_t
value : values) {
966 proto->mutable_element()->add_exprs()->set_offset(
value);
968 return Constraint(proto);
972 absl::Span<const LinearExpr> expressions,
974 ConstraintProto*
const proto = cp_model_.add_constraints();
975 *proto->mutable_element()->mutable_linear_index() = LinearExprToProto(index);
976 *proto->mutable_element()->mutable_linear_target() =
977 LinearExprToProto(target);
978 for (
const LinearExpr& expr : expressions) {
979 *proto->mutable_element()->add_exprs() = LinearExprToProto(expr);
981 return Constraint(proto);
985 LinearExpr index, std::initializer_list<LinearExpr> expressions,
987 ConstraintProto*
const proto = cp_model_.add_constraints();
988 *proto->mutable_element()->mutable_linear_index() = LinearExprToProto(index);
989 *proto->mutable_element()->mutable_linear_target() =
990 LinearExprToProto(target);
991 for (
const LinearExpr& expr : expressions) {
992 *proto->mutable_element()->add_exprs() = LinearExprToProto(expr);
994 return Constraint(proto);
998 return CircuitConstraint(cp_model_.add_constraints());
1002 return MultipleCircuitConstraint(cp_model_.add_constraints());
1006 absl::Span<const LinearExpr> expressions) {
1007 ConstraintProto*
const proto = cp_model_.add_constraints();
1008 for (
const LinearExpr& expr : expressions) {
1009 *proto->mutable_table()->add_exprs() = LinearExprToProto(expr);
1011 return TableConstraint(proto);
1015 absl::Span<const IntVar> variables) {
1016 ConstraintProto*
const proto = cp_model_.add_constraints();
1017 for (
const IntVar var : variables) {
1018 LinearExpressionProto* expr = proto->mutable_table()->add_exprs();
1019 expr->add_vars(var.index_);
1020 expr->add_coeffs(1);
1022 return TableConstraint(proto);
1026 std::initializer_list<LinearExpr> expressions) {
1027 ConstraintProto*
const proto = cp_model_.add_constraints();
1028 for (
const LinearExpr& expr : expressions) {
1029 *proto->mutable_table()->add_exprs() = LinearExprToProto(expr);
1031 return TableConstraint(proto);
1035 absl::Span<const LinearExpr> expressions) {
1036 TableConstraint ct = AddAllowedAssignments(expressions);
1037 ct.MutableProto()->mutable_table()->set_negated(
true);
1042 absl::Span<const IntVar> variables) {
1043 TableConstraint ct = AddAllowedAssignments(variables);
1044 ct.MutableProto()->mutable_table()->set_negated(
true);
1049 std::initializer_list<LinearExpr> expressions) {
1050 TableConstraint ct = AddAllowedAssignments(expressions);
1051 ct.MutableProto()->mutable_table()->set_negated(
true);
1055Constraint CpModelBuilder::AddInverseConstraint(
1056 absl::Span<const IntVar> variables,
1057 absl::Span<const IntVar> inverse_variables) {
1058 ConstraintProto*
const proto = cp_model_.add_constraints();
1059 for (
const IntVar& var : variables) {
1060 proto->mutable_inverse()->add_f_direct(var.index_);
1062 for (
const IntVar& var : inverse_variables) {
1063 proto->mutable_inverse()->add_f_inverse(var.index_);
1065 return Constraint(proto);
1069 int64_t max_level) {
1070 ConstraintProto*
const proto = cp_model_.add_constraints();
1071 proto->mutable_reservoir()->set_min_level(min_level);
1072 proto->mutable_reservoir()->set_max_level(max_level);
1073 return ReservoirConstraint(proto,
this);
1077 absl::Span<const LinearExpr> transition_expressions,
int starting_state,
1078 absl::Span<const int> final_states) {
1079 ConstraintProto*
const proto = cp_model_.add_constraints();
1080 for (
const LinearExpr& expr : transition_expressions) {
1081 *proto->mutable_automaton()->add_exprs() = LinearExprToProto(expr);
1083 proto->mutable_automaton()->set_starting_state(starting_state);
1084 for (
const int final_state : final_states) {
1085 proto->mutable_automaton()->add_final_states(final_state);
1087 return AutomatonConstraint(proto);
1091 absl::Span<const IntVar> transition_variables,
int starting_state,
1092 absl::Span<const int> final_states) {
1093 ConstraintProto*
const proto = cp_model_.add_constraints();
1094 for (
const IntVar& var : transition_variables) {
1095 LinearExpressionProto* expr = proto->mutable_automaton()->add_exprs();
1096 expr->add_vars(var.index_);
1097 expr->add_coeffs(1);
1099 proto->mutable_automaton()->set_starting_state(starting_state);
1100 for (
const int final_state : final_states) {
1101 proto->mutable_automaton()->add_final_states(final_state);
1103 return AutomatonConstraint(proto);
1107 std::initializer_list<LinearExpr> transition_expressions,
1108 int starting_state, absl::Span<const int> final_states) {
1109 ConstraintProto*
const proto = cp_model_.add_constraints();
1110 for (
const LinearExpr& expr : transition_expressions) {
1111 *proto->mutable_automaton()->add_exprs() = LinearExprToProto(expr);
1113 proto->mutable_automaton()->set_starting_state(starting_state);
1114 for (
const int final_state : final_states) {
1115 proto->mutable_automaton()->add_final_states(final_state);
1117 return AutomatonConstraint(proto);
1122 LinearExpressionProto expr_proto;
1123 for (
const int var : expr.variables()) {
1124 expr_proto.add_vars(var);
1126 const int64_t mult = negate ? -1 : 1;
1127 for (
const int64_t coeff : expr.coefficients()) {
1128 expr_proto.add_coeffs(coeff * mult);
1130 expr_proto.
set_offset(expr.constant() * mult);
1135 absl::Span<const IntVar> vars) {
1136 ConstraintProto* ct = cp_model_.add_constraints();
1137 *ct->mutable_lin_max()->mutable_target() =
1138 LinearExprToProto(target,
true);
1139 for (
const IntVar& var : vars) {
1140 *ct->mutable_lin_max()->add_exprs() =
1141 LinearExprToProto(var,
true);
1143 return Constraint(ct);
1147 absl::Span<const LinearExpr> exprs) {
1148 ConstraintProto* ct = cp_model_.add_constraints();
1149 *ct->mutable_lin_max()->mutable_target() =
1150 LinearExprToProto(target,
true);
1151 for (
const LinearExpr& expr : exprs) {
1152 *ct->mutable_lin_max()->add_exprs() =
1153 LinearExprToProto(expr,
true);
1155 return Constraint(ct);
1159 const LinearExpr& target, std::initializer_list<LinearExpr> exprs) {
1160 ConstraintProto* ct = cp_model_.add_constraints();
1161 *ct->mutable_lin_max()->mutable_target() =
1162 LinearExprToProto(target,
true);
1163 for (
const LinearExpr& expr : exprs) {
1164 *ct->mutable_lin_max()->add_exprs() =
1165 LinearExprToProto(expr,
true);
1167 return Constraint(ct);
1171 absl::Span<const IntVar> vars) {
1172 ConstraintProto* ct = cp_model_.add_constraints();
1173 *ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1174 for (
const IntVar& var : vars) {
1175 *ct->mutable_lin_max()->add_exprs() = LinearExprToProto(var);
1177 return Constraint(ct);
1181 absl::Span<const LinearExpr> exprs) {
1182 ConstraintProto* ct = cp_model_.add_constraints();
1183 *ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1184 for (
const LinearExpr& expr : exprs) {
1185 *ct->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1187 return Constraint(ct);
1191 const LinearExpr& target, std::initializer_list<LinearExpr> exprs) {
1192 ConstraintProto* ct = cp_model_.add_constraints();
1193 *ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1194 for (
const LinearExpr& expr : exprs) {
1195 *ct->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1197 return Constraint(ct);
1203 ConstraintProto*
const proto = cp_model_.add_constraints();
1204 *proto->mutable_int_div()->mutable_target() = LinearExprToProto(target);
1205 *proto->mutable_int_div()->add_exprs() = LinearExprToProto(numerator);
1206 *proto->mutable_int_div()->add_exprs() = LinearExprToProto(denominator);
1207 return Constraint(proto);
1212 ConstraintProto*
const proto = cp_model_.add_constraints();
1213 *proto->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1214 *proto->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1215 *proto->mutable_lin_max()->add_exprs() =
1216 LinearExprToProto(expr,
true);
1217 return Constraint(proto);
1223 ConstraintProto*
const proto = cp_model_.add_constraints();
1224 *proto->mutable_int_mod()->mutable_target() = LinearExprToProto(target);
1225 *proto->mutable_int_mod()->add_exprs() = LinearExprToProto(var);
1226 *proto->mutable_int_mod()->add_exprs() = LinearExprToProto(mod);
1227 return Constraint(proto);
1230Constraint CpModelBuilder::AddMultiplicationEquality(
1231 const LinearExpr& target, absl::Span<const IntVar> vars) {
1232 ConstraintProto*
const proto = cp_model_.add_constraints();
1233 *proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1234 for (
const IntVar& var : vars) {
1235 *proto->mutable_int_prod()->add_exprs() = LinearExprToProto(var);
1237 return Constraint(proto);
1240Constraint CpModelBuilder::AddMultiplicationEquality(
1241 const LinearExpr& target, absl::Span<const LinearExpr> exprs) {
1242 ConstraintProto*
const proto = cp_model_.add_constraints();
1243 *proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1244 for (
const LinearExpr& expr : exprs) {
1245 *proto->mutable_int_prod()->add_exprs() = LinearExprToProto(expr);
1247 return Constraint(proto);
1250Constraint CpModelBuilder::AddMultiplicationEquality(
1251 const LinearExpr& target, std::initializer_list<LinearExpr> exprs) {
1252 ConstraintProto*
const proto = cp_model_.add_constraints();
1253 *proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1254 for (
const LinearExpr& expr : exprs) {
1255 *proto->mutable_int_prod()->add_exprs() = LinearExprToProto(expr);
1257 return Constraint(proto);
1262 ConstraintProto*
const proto = cp_model_.add_constraints();
1263 *proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1264 *proto->mutable_int_prod()->add_exprs() = LinearExprToProto(
left);
1265 *proto->mutable_int_prod()->add_exprs() = LinearExprToProto(right);
1267 return Constraint(proto);
1270Constraint CpModelBuilder::AddNoOverlap(absl::Span<const IntervalVar> vars) {
1271 ConstraintProto*
const proto = cp_model_.add_constraints();
1272 for (
const IntervalVar& var : vars) {
1273 proto->mutable_no_overlap()->add_intervals(var.index_);
1275 return Constraint(proto);
1279 return NoOverlap2DConstraint(cp_model_.add_constraints());
1283 ConstraintProto*
const proto = cp_model_.add_constraints();
1284 *proto->mutable_cumulative()->mutable_capacity() =
1285 LinearExprToProto(capacity);
1286 return CumulativeConstraint(proto,
this);
1289void CpModelBuilder::Minimize(
const LinearExpr& expr) {
1291 for (
const int x : expr.variables()) {
1292 cp_model_.mutable_objective()->add_vars(x);
1294 for (
const int64_t coeff : expr.coefficients()) {
1295 cp_model_.mutable_objective()->add_coeffs(coeff);
1297 cp_model_.mutable_objective()->set_offset(expr.constant());
1300void CpModelBuilder::Maximize(
const LinearExpr& expr) {
1302 for (
const int x : expr.variables()) {
1303 cp_model_.mutable_objective()->add_vars(x);
1305 for (
const int64_t coeff : expr.coefficients()) {
1306 cp_model_.mutable_objective()->add_coeffs(-coeff);
1308 cp_model_.mutable_objective()->set_offset(-expr.constant());
1309 cp_model_.mutable_objective()->set_scaling_factor(-1.0);
1314 for (
int i = 0;
i < expr.variables().size(); ++
i) {
1315 cp_model_.mutable_floating_point_objective()->add_vars(expr.variables()[
i]);
1316 cp_model_.mutable_floating_point_objective()->add_coeffs(
1317 expr.coefficients()[
i]);
1319 cp_model_.mutable_floating_point_objective()->set_offset(expr.constant());
1320 cp_model_.mutable_floating_point_objective()->set_maximize(
false);
1325 for (
int i = 0;
i < expr.variables().size(); ++
i) {
1326 cp_model_.mutable_floating_point_objective()->add_vars(expr.variables()[
i]);
1327 cp_model_.mutable_floating_point_objective()->add_coeffs(
1328 expr.coefficients()[
i]);
1330 cp_model_.mutable_floating_point_objective()->set_offset(expr.constant());
1331 cp_model_.mutable_floating_point_objective()->set_maximize(
true);
1334void CpModelBuilder::ClearObjective() {
1335 cp_model_.clear_objective();
1336 cp_model_.clear_floating_point_objective();
1339bool CpModelBuilder::HasObjective()
const {
1340 return cp_model_.has_objective() || cp_model_.has_floating_point_objective();
1343void CpModelBuilder::AddDecisionStrategy(
1344 absl::Span<const IntVar> variables,
1347 DecisionStrategyProto*
const proto = cp_model_.add_search_strategy();
1348 for (
const IntVar& var : variables) {
1349 LinearExpressionProto* expr = proto->add_exprs();
1350 if (var.index_ >= 0) {
1351 expr->add_vars(var.index_);
1352 expr->add_coeffs(1);
1355 expr->add_coeffs(-1);
1356 expr->set_offset(1);
1359 proto->set_variable_selection_strategy(var_strategy);
1360 proto->set_domain_reduction_strategy(domain_strategy);
1363void CpModelBuilder::AddDecisionStrategy(
1364 absl::Span<const BoolVar> variables,
1367 DecisionStrategyProto*
const proto = cp_model_.add_search_strategy();
1368 for (
const BoolVar& var : variables) {
1369 LinearExpressionProto* expr = proto->add_exprs();
1370 if (var.index_ >= 0) {
1371 expr->add_vars(var.index_);
1372 expr->add_coeffs(1);
1375 expr->add_coeffs(-1);
1376 expr->set_offset(1);
1379 proto->set_variable_selection_strategy(var_strategy);
1380 proto->set_domain_reduction_strategy(domain_strategy);
1383void CpModelBuilder::AddDecisionStrategy(
1384 absl::Span<const LinearExpr> expressions,
1387 DecisionStrategyProto*
const proto = cp_model_.add_search_strategy();
1388 for (
const LinearExpr& expr : expressions) {
1389 *proto->add_exprs() = LinearExprToProto(expr);
1391 proto->set_variable_selection_strategy(var_strategy);
1392 proto->set_domain_reduction_strategy(domain_strategy);
1395void CpModelBuilder::AddDecisionStrategy(
1396 std::initializer_list<LinearExpr> expressions,
1399 DecisionStrategyProto*
const proto = cp_model_.add_search_strategy();
1400 for (
const LinearExpr& expr : expressions) {
1401 *proto->add_exprs() = LinearExprToProto(expr);
1403 proto->set_variable_selection_strategy(var_strategy);
1404 proto->set_domain_reduction_strategy(domain_strategy);
1407void CpModelBuilder::AddHint(
IntVar var, int64_t value) {
1408 cp_model_.mutable_solution_hint()->add_vars(var.index_);
1409 cp_model_.mutable_solution_hint()->add_values(
value);
1412void CpModelBuilder::AddHint(
BoolVar var,
bool value) {
1413 if (var.index_ >= 0) {
1414 cp_model_.mutable_solution_hint()->add_vars(var.index_);
1415 cp_model_.mutable_solution_hint()->add_values(
value);
1417 cp_model_.mutable_solution_hint()->add_vars(
PositiveRef(var.index_));
1418 cp_model_.mutable_solution_hint()->add_values(!
value);
1422void CpModelBuilder::ClearHints() {
1423 cp_model_.mutable_solution_hint()->Clear();
1426void CpModelBuilder::AddAssumption(
BoolVar lit) {
1427 cp_model_.mutable_assumptions()->Add(lit.index_);
1430void CpModelBuilder::AddAssumptions(absl::Span<const BoolVar> literals) {
1431 for (
const BoolVar& lit : literals) {
1432 cp_model_.mutable_assumptions()->Add(lit.index_);
1436void CpModelBuilder::ClearAssumptions() {
1437 cp_model_.mutable_assumptions()->Clear();
1441 CpModelBuilder clone;
1442 clone.ResetAndImport(cp_model_);
1446void CpModelBuilder::ResetAndImport(
const CpModelProto& model_proto) {
1447 cp_model_ = model_proto;
1449 constant_to_index_map_.clear();
1450 for (
int i = 0;
i < cp_model_.variables_size(); ++
i) {
1451 const IntegerVariableProto& var = cp_model_.variables(
i);
1452 if (var.domain_size() == 2 && var.domain(0) == var.domain(1)) {
1453 constant_to_index_map_[var.domain(0)] =
i;
1457 bool_to_integer_index_map_.clear();
1460BoolVar CpModelBuilder::GetBoolVarFromProtoIndex(
int index) {
1462 CHECK_LT(index, cp_model_.variables_size());
1463 const IntegerVariableProto& proto = cp_model_.variables(index);
1464 CHECK_EQ(2, proto.domain_size())
1465 <<
"CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1467 CHECK_GE(0, proto.domain(0))
1468 <<
"CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1470 CHECK_LE(1, proto.domain(1))
1471 <<
"CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1473 return BoolVar(index,
this);
1476IntVar CpModelBuilder::GetIntVarFromProtoIndex(
int index) {
1478 CHECK_LT(index, cp_model_.variables_size());
1479 return IntVar(index,
this);
1482IntervalVar CpModelBuilder::GetIntervalVarFromProtoIndex(
int index) {
1484 CHECK_LT(index, cp_model_.constraints_size());
1485 const ConstraintProto& ct = cp_model_.constraints(index);
1487 <<
"CpModelBuilder::GetIntervalVarFromProtoIndex: the referenced "
1488 "object is not an interval variable";
1489 return IntervalVar(index,
this);
1492bool CpModelBuilder::ExportToFile(absl::string_view filename)
const {
1499 const std::vector<int>& variables = expr.
variables();
1500 const std::vector<int64_t>& coefficients = expr.
coefficients();
1501 for (
int i = 0;
i < variables.size(); ++
i) {
1502 result += r.
solution(variables[
i]) * coefficients[
i];
1508 const int ref = x.index_;
virtual std::string DebugString() const
Constraint(Solver *const solver)
LinearExpr & operator+=(const LinearExpr &rhs)
LinearExpr & operator-=(const LinearExpr &rhs)
LinearExpr & operator*=(double rhs)
virtual std::string name() const
Object naming.
*Adds a transitions to the automaton void AddTransition(int tail, int head, int64_t transition_label)
void add_literals(::int32_t value)
BoolVar WithName(absl::string_view name)
std::string Name() const
Returns the name of the variable.
BoolVar Not() const
Returns the logical negation of the current Boolean variable.
std::string DebugString() const
void AddArc(int tail, int head, BoolVar literal)
::operations_research::sat::CumulativeConstraintProto *PROTOBUF_NONNULL mutable_cumulative()
::operations_research::sat::NoOverlap2DConstraintProto *PROTOBUF_NONNULL mutable_no_overlap_2d()
const ::std::string & name() const
::operations_research::sat::IntervalConstraintProto *PROTOBUF_NONNULL mutable_interval()
::operations_research::sat::ReservoirConstraintProto *PROTOBUF_NONNULL mutable_reservoir()
::operations_research::sat::BoolArgumentProto *PROTOBUF_NONNULL mutable_bool_or()
void add_enforcement_literal(::int32_t value)
::operations_research::sat::LinearConstraintProto *PROTOBUF_NONNULL mutable_linear()
Constraint WithName(absl::string_view name)
Sets the name of the constraint.
Constraint OnlyEnforceIf(absl::Span< const BoolVar > literals)
Constraint(ConstraintProto *proto)
absl::string_view Name() const
Returns the name of the constraint (or the empty string if not set).
*Creates an integer variable with the given domain IntVar NewIntVar(const Domain &domain)
*Creates an interval variable from affine expressions IntervalVar NewIntervalVar(const LinearExpr &start, const LinearExpr &size, const LinearExpr &end)
*It is sometime convenient when building a model to create a bunch of *variables that will later be fixed Instead of doing these functions modify directly the *underlying variable domain *note this ignore completely the original variable domain and just fix *the given variable to the given value
*Creates an optional interval variable from affine expressions and a *Boolean variable IntervalVar NewOptionalIntervalVar(const LinearExpr &start, const LinearExpr &size, const LinearExpr &end, BoolVar presence)
*Creates an always true Boolean variable *If this is called multiple the same variable will always be *returned BoolVar TrueVar()
*Same as AddBoolOr(). Sum literals >
*Creates a Boolean variable BoolVar NewBoolVar()
*Creates an always false Boolean variable *If this is called multiple the same variable will always be *returned BoolVar FalseVar()
*Adds left right Constraint AddGreaterThan(const LinearExpr &left, const LinearExpr &right)
*Sets the name of the model void SetName(absl::string_view name)
*It is sometime convenient when building a model to create a bunch of *variables that will later be fixed Instead of doing these functions modify directly the *underlying variable domain *note this ignore completely the original variable domain and just fix *the given variable to the given even if it was outside the given *variable domain You can still use AddEquality() if this is not what you *want. void FixVariable(IntVar var
*Adds absl::Span< const BoolVar > rhs
*Creates an interval variable with a fixed size IntervalVar NewFixedSizeIntervalVar(const LinearExpr &start, int64_t size)
*Creates an optional interval variable with a fixed size IntervalVar NewOptionalFixedSizeIntervalVar(const LinearExpr &start, int64_t size, BoolVar presence)
void FixVariable(BoolVar var, bool value)
const ::operations_research::sat::IntegerVariableProto & variables(int index) const
const ::operations_research::sat::ConstraintProto & constraints(int index) const
::int64_t solution(int index) const
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL add_demands()
void add_intervals(::int32_t value)
*Adds a LinearExpr demand
DecisionStrategyProto_DomainReductionStrategy DomainReductionStrategy
DecisionStrategyProto_VariableSelectionStrategy VariableSelectionStrategy
const std::vector< double > & coefficients() const
Returns the vector of coefficients.
static DoubleLinearExpr Sum(absl::Span< const IntVar > vars)
Constructs the sum of a list of variables.
DoubleLinearExpr & operator*=(double coeff)
Multiply the linear expression by a constant.
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.
double constant() const
Returns the constant term.
static DoubleLinearExpr WeightedSum(absl::Span< const IntVar > vars, absl::Span< const double > coeffs)
Constructs the scalar product of variables and coefficients.
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().
DoubleLinearExpr & AddExpression(const LinearExpr &exprs, double coeff=1.0)
Adds a linear expression to the double linear expression.
std::string Name() const
Returns the name of the variable (or the empty string if not set).
std::string DebugString() const
int index() const
Returns the index of the variable in the model. This will be non-negative.
IntVar WithName(absl::string_view name)
Sets the name of the variable.
BoolVar ToBoolVar() const
Cast IntVar -> BoolVar.
::operations_research::Domain Domain() const
const ::std::string & name() const
void add_domain(::int64_t value)
::int64_t domain(int index) const
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL mutable_start()
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL mutable_size()
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL mutable_end()
const ::operations_research::sat::LinearExpressionProto & end() 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.
void add_domain(::int64_t value)
static LinearExpr Sum(absl::Span< const IntVar > vars)
Constructs the sum of a list of variables.
std::string DebugString(const CpModelProto *proto=nullptr) const
static LinearExpr WeightedSum(absl::Span< const IntVar > vars, absl::Span< const int64_t > coeffs)
Constructs the scalar product of variables and coefficients.
static LinearExpr Term(IntVar var, int64_t coefficient)
Constructs var * coefficient.
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.
const std::vector< int > & variables() const
Returns the vector of variable indices.
const std::vector< int64_t > & coefficients() const
Returns the vector of coefficients.
::int64_t coeffs(int index) const
::int32_t vars(int index) const
void set_offset(::int64_t value)
void AddArc(int tail, int head, BoolVar literal)
void add_y_intervals(::int32_t value)
void add_x_intervals(::int32_t value)
*Adds a IntervalVar y_coordinate
void add_active_literals(::int32_t value)
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL add_level_changes()
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL add_time_exprs()
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.
std::string VarDebugString(const CpModelProto &proto, int index)
bool RefIsPositive(int ref)
int64_t SolutionIntegerValue(const CpSolverResponse &r, const LinearExpr &expr)
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)
Domain ReadDomainFromProto(const ProtoWithDomain &proto)
bool SolutionBooleanValue(const CpSolverResponse &r, BoolVar x)
ClosedInterval::Iterator end(ClosedInterval interval)
std::ostream & operator<<(std::ostream &out, const Assignment &assignment)