16 #include "absl/strings/str_format.h"
29 : cp_model_(cp_model), index_(
index) {}
32 cp_model_->mutable_variables(index_)->set_name(
name);
41 const IntegerVariableProto& var_proto = cp_model_->variables(index_);
43 if (var_proto.name().empty() && var_proto.domain_size() == 2 &&
44 var_proto.domain(0) == var_proto.domain(1)) {
45 output.append(var_proto.domain(0) == 0 ?
"false" :
"true");
47 if (var_proto.name().empty()) {
48 absl::StrAppendFormat(&output,
"BoolVar%i(", index_);
50 absl::StrAppendFormat(&output,
"%s(", var_proto.name());
52 if (var_proto.domain(0) == var_proto.domain(1)) {
53 output.append(var_proto.domain(0) == 0 ?
"false)" :
"true)");
55 absl::StrAppend(&output, var_proto.domain(0),
", ", var_proto.domain(1),
73 : cp_model_(cp_model), index_(
index) {
78 cp_model_->mutable_variables(index_)->set_name(
name);
83 cp_model_ =
var.cp_model_;
92 var.cp_model_ = cp_model_;
103 return absl::StrFormat(
"Not(%s)",
106 const IntegerVariableProto& var_proto = cp_model_->variables(index_);
108 if (var_proto.name().empty() && var_proto.domain_size() == 2 &&
109 var_proto.domain(0) == var_proto.domain(1)) {
110 return absl::StrCat(var_proto.domain(0));
113 if (var_proto.name().empty()) {
114 absl::StrAppend(&output,
"IntVar", index_,
"(");
116 absl::StrAppend(&output, var_proto.name(),
"(");
118 if (var_proto.domain_size() == 2 &&
119 var_proto.domain(0) == var_proto.domain(1)) {
120 absl::StrAppend(&output, var_proto.domain(0),
")");
123 absl::StrAppend(&output, var_proto.domain(0),
", ", var_proto.domain(1),
152 absl::Span<const int64> coeffs) {
153 CHECK_EQ(vars.size(), coeffs.size());
155 for (
int i = 0; i < vars.size(); ++i) {
156 result.
AddTerm(vars[i], coeffs[i]);
176 absl::Span<const int64> coeffs) {
177 CHECK_EQ(vars.size(), coeffs.size());
179 for (
int i = 0; i < vars.size(); ++i) {
180 result.
AddTerm(vars[i], coeffs[i]);
195 variables_.push_back(
var);
196 coefficients_.push_back(coeff);
199 coefficients_.push_back(-coeff);
215 proto_->add_enforcement_literal(
var.index_);
239 for (
const int64 t : tuple) {
240 proto_->mutable_table()->add_values(t);
244 ReservoirConstraint::ReservoirConstraint(ConstraintProto*
proto,
249 proto_->mutable_reservoir()->add_times(
250 builder_->GetOrCreateIntegerIndex(
time.index_));
252 proto_->mutable_reservoir()->add_actives(builder_->IndexFromConstant(1));
257 proto_->mutable_reservoir()->add_times(
258 builder_->GetOrCreateIntegerIndex(
time.index_));
260 proto_->mutable_reservoir()->add_actives(is_active.index_);
264 int64 transition_label) {
265 proto_->mutable_automaton()->add_transition_tail(
tail);
266 proto_->mutable_automaton()->add_transition_head(
head);
267 proto_->mutable_automaton()->add_transition_label(transition_label);
272 proto_->mutable_no_overlap_2d()->add_x_intervals(x_coordinate.index_);
273 proto_->mutable_no_overlap_2d()->add_y_intervals(y_coordinate.index_);
276 CumulativeConstraint::CumulativeConstraint(ConstraintProto*
proto,
282 proto_->mutable_cumulative()->add_demands(
283 builder_->GetOrCreateIntegerIndex(
demand.index_));
289 : cp_model_(cp_model), index_(
index) {}
292 cp_model_->mutable_constraints(index_)->set_name(
name);
307 return BoolVar(cp_model_->constraints(index_).enforcement_literal(0),
312 return cp_model_->constraints(index_).name();
317 const ConstraintProto& ct_proto = cp_model_->constraints(index_);
319 if (ct_proto.name().empty()) {
320 absl::StrAppend(&output,
"IntervalVar", index_,
"(");
322 absl::StrAppend(&output, ct_proto.name(),
"(");
335 int CpModelBuilder::IndexFromConstant(
int64 value) {
337 const int index = cp_model_.variables_size();
338 IntegerVariableProto*
const var_proto = cp_model_.add_variables();
339 var_proto->add_domain(
value);
340 var_proto->add_domain(
value);
343 return constant_to_index_map_[
value];
346 int CpModelBuilder::GetOrCreateIntegerIndex(
int index) {
352 const IntegerVariableProto& old_var = cp_model_.variables(ref);
353 const int new_index = cp_model_.variables_size();
354 IntegerVariableProto*
const new_var = cp_model_.add_variables();
355 new_var->add_domain(0);
356 new_var->add_domain(1);
357 if (!old_var.name().empty()) {
358 new_var->set_name(absl::StrCat(
"Not(", old_var.name(),
")"));
361 bool_to_integer_index_map_[
index] = new_index;
364 return bool_to_integer_index_map_[
index];
368 const int index = cp_model_.variables_size();
369 IntegerVariableProto*
const var_proto = cp_model_.add_variables();
370 for (
const auto&
interval : domain) {
371 var_proto->add_domain(
interval.start);
372 var_proto->add_domain(
interval.end);
378 const int index = cp_model_.variables_size();
379 IntegerVariableProto*
const var_proto = cp_model_.add_variables();
380 var_proto->add_domain(0);
381 var_proto->add_domain(1);
386 return IntVar(IndexFromConstant(
value), &cp_model_);
390 return BoolVar(IndexFromConstant(1), &cp_model_);
394 return BoolVar(IndexFromConstant(0), &cp_model_);
405 const int index = cp_model_.constraints_size();
406 ConstraintProto*
const ct = cp_model_.add_constraints();
407 ct->add_enforcement_literal(presence.index_);
408 IntervalConstraintProto*
const interval =
ct->mutable_interval();
409 interval->set_start(GetOrCreateIntegerIndex(start.index_));
410 interval->set_size(GetOrCreateIntegerIndex(size.index_));
411 interval->set_end(GetOrCreateIntegerIndex(end.index_));
416 ConstraintProto*
const proto = cp_model_.add_constraints();
417 for (
const BoolVar& lit : literals) {
418 proto->mutable_bool_or()->add_literals(lit.index_);
424 ConstraintProto*
const proto = cp_model_.add_constraints();
425 for (
const BoolVar& lit : literals) {
426 proto->mutable_bool_and()->add_literals(lit.index_);
432 ConstraintProto*
const proto = cp_model_.add_constraints();
433 for (
const BoolVar& lit : literals) {
434 proto->mutable_bool_xor()->add_literals(lit.index_);
439 void CpModelBuilder::FillLinearTerms(
const LinearExpr& left,
441 LinearConstraintProto*
proto) {
443 proto->add_vars(x.index_);
446 proto->add_coeffs(coeff);
448 for (
const IntVar& x : right.
variables()) {
449 proto->add_vars(x.index_);
452 proto->add_coeffs(-coeff);
458 ConstraintProto*
const proto = cp_model_.add_constraints();
459 FillLinearTerms(left, right,
proto->mutable_linear());
461 proto->mutable_linear()->add_domain(rhs);
462 proto->mutable_linear()->add_domain(rhs);
468 ConstraintProto*
const proto = cp_model_.add_constraints();
469 FillLinearTerms(left, right,
proto->mutable_linear());
471 proto->mutable_linear()->add_domain(rhs);
478 ConstraintProto*
const proto = cp_model_.add_constraints();
479 FillLinearTerms(left, right,
proto->mutable_linear());
482 proto->mutable_linear()->add_domain(rhs);
488 ConstraintProto*
const proto = cp_model_.add_constraints();
489 FillLinearTerms(left, right,
proto->mutable_linear());
491 proto->mutable_linear()->add_domain(rhs + 1);
498 ConstraintProto*
const proto = cp_model_.add_constraints();
499 FillLinearTerms(left, right,
proto->mutable_linear());
502 proto->mutable_linear()->add_domain(rhs - 1);
508 ConstraintProto*
const proto = cp_model_.add_constraints();
510 proto->mutable_linear()->add_vars(x.index_);
513 proto->mutable_linear()->add_coeffs(coeff);
516 for (
const auto& i : domain) {
517 proto->mutable_linear()->add_domain(i.start - cst);
518 proto->mutable_linear()->add_domain(i.end - cst);
525 ConstraintProto*
const proto = cp_model_.add_constraints();
526 FillLinearTerms(left, right,
proto->mutable_linear());
529 proto->mutable_linear()->add_domain(rhs - 1);
530 proto->mutable_linear()->add_domain(rhs + 1);
536 ConstraintProto*
const proto = cp_model_.add_constraints();
538 proto->mutable_all_diff()->add_vars(GetOrCreateIntegerIndex(
var.index_));
545 ConstraintProto*
const proto = cp_model_.add_constraints();
546 proto->mutable_element()->set_index(GetOrCreateIntegerIndex(
index.index_));
547 proto->mutable_element()->set_target(GetOrCreateIntegerIndex(target.index_));
549 proto->mutable_element()->add_vars(GetOrCreateIntegerIndex(
var.index_));
555 absl::Span<const int64> values,
557 ConstraintProto*
const proto = cp_model_.add_constraints();
558 proto->mutable_element()->set_index(GetOrCreateIntegerIndex(
index.index_));
559 proto->mutable_element()->set_target(GetOrCreateIntegerIndex(target.index_));
561 proto->mutable_element()->add_vars(IndexFromConstant(
value));
575 absl::Span<const IntVar> vars) {
576 ConstraintProto*
const proto = cp_model_.add_constraints();
578 proto->mutable_table()->add_vars(GetOrCreateIntegerIndex(
var.index_));
584 absl::Span<const IntVar> vars) {
585 ConstraintProto*
const proto = cp_model_.add_constraints();
587 proto->mutable_table()->add_vars(GetOrCreateIntegerIndex(
var.index_));
589 proto->mutable_table()->set_negated(
true);
594 absl::Span<const IntVar> variables,
595 absl::Span<const IntVar> inverse_variables) {
596 ConstraintProto*
const proto = cp_model_.add_constraints();
598 proto->mutable_inverse()->add_f_direct(GetOrCreateIntegerIndex(
var.index_));
600 for (
const IntVar&
var : inverse_variables) {
601 proto->mutable_inverse()->add_f_inverse(
602 GetOrCreateIntegerIndex(
var.index_));
609 ConstraintProto*
const proto = cp_model_.add_constraints();
610 proto->mutable_reservoir()->set_min_level(min_level);
611 proto->mutable_reservoir()->set_max_level(max_level);
616 absl::Span<const IntVar> transition_variables,
int starting_state,
617 absl::Span<const int> final_states) {
618 ConstraintProto*
const proto = cp_model_.add_constraints();
619 for (
const IntVar&
var : transition_variables) {
620 proto->mutable_automaton()->add_vars(GetOrCreateIntegerIndex(
var.index_));
622 proto->mutable_automaton()->set_starting_state(starting_state);
623 for (
const int final_state : final_states) {
624 proto->mutable_automaton()->add_final_states(final_state);
630 absl::Span<const IntVar> vars) {
631 ConstraintProto*
const proto = cp_model_.add_constraints();
632 proto->mutable_int_min()->set_target(GetOrCreateIntegerIndex(target.index_));
634 proto->mutable_int_min()->add_vars(GetOrCreateIntegerIndex(
var.index_));
639 void CpModelBuilder::LinearExprToProto(
const LinearExpr& expr,
640 LinearExpressionProto* expr_proto) {
642 expr_proto->add_vars(GetOrCreateIntegerIndex(
var.index_));
645 expr_proto->add_coeffs(coeff);
647 expr_proto->set_offset(expr.
constant());
651 const LinearExpr& target, absl::Span<const LinearExpr> exprs) {
652 ConstraintProto*
const proto = cp_model_.add_constraints();
653 LinearExprToProto(target,
proto->mutable_lin_min()->mutable_target());
655 LinearExpressionProto* expr_proto =
proto->mutable_lin_min()->add_exprs();
656 LinearExprToProto(expr, expr_proto);
662 absl::Span<const IntVar> vars) {
663 ConstraintProto*
const proto = cp_model_.add_constraints();
664 proto->mutable_int_max()->set_target(GetOrCreateIntegerIndex(target.index_));
666 proto->mutable_int_max()->add_vars(GetOrCreateIntegerIndex(
var.index_));
672 const LinearExpr& target, absl::Span<const LinearExpr> exprs) {
673 ConstraintProto*
const proto = cp_model_.add_constraints();
674 LinearExprToProto(target,
proto->mutable_lin_max()->mutable_target());
676 LinearExpressionProto* expr_proto =
proto->mutable_lin_max()->add_exprs();
677 LinearExprToProto(expr, expr_proto);
684 ConstraintProto*
const proto = cp_model_.add_constraints();
685 proto->mutable_int_div()->set_target(GetOrCreateIntegerIndex(target.index_));
686 proto->mutable_int_div()->add_vars(GetOrCreateIntegerIndex(numerator.index_));
687 proto->mutable_int_div()->add_vars(
688 GetOrCreateIntegerIndex(denominator.index_));
693 ConstraintProto*
const proto = cp_model_.add_constraints();
694 proto->mutable_int_max()->set_target(GetOrCreateIntegerIndex(target.index_));
695 proto->mutable_int_max()->add_vars(GetOrCreateIntegerIndex(
var.index_));
696 proto->mutable_int_max()->add_vars(
703 ConstraintProto*
const proto = cp_model_.add_constraints();
704 proto->mutable_int_mod()->set_target(GetOrCreateIntegerIndex(target.index_));
705 proto->mutable_int_mod()->add_vars(GetOrCreateIntegerIndex(
var.index_));
706 proto->mutable_int_mod()->add_vars(GetOrCreateIntegerIndex(mod.index_));
711 absl::Span<const IntVar> vars) {
712 ConstraintProto*
const proto = cp_model_.add_constraints();
713 proto->mutable_int_prod()->set_target(GetOrCreateIntegerIndex(target.index_));
715 proto->mutable_int_prod()->add_vars(GetOrCreateIntegerIndex(
var.index_));
721 ConstraintProto*
const proto = cp_model_.add_constraints();
723 proto->mutable_no_overlap()->add_intervals(
724 GetOrCreateIntegerIndex(
var.index_));
734 ConstraintProto*
const proto = cp_model_.add_constraints();
735 proto->mutable_cumulative()->set_capacity(
736 GetOrCreateIntegerIndex(
capacity.index_));
741 cp_model_.mutable_objective()->Clear();
743 cp_model_.mutable_objective()->add_vars(x.index_);
746 cp_model_.mutable_objective()->add_coeffs(coeff);
748 cp_model_.mutable_objective()->set_offset(expr.
constant());
752 cp_model_.mutable_objective()->Clear();
754 cp_model_.mutable_objective()->add_vars(x.index_);
757 cp_model_.mutable_objective()->add_coeffs(-coeff);
759 cp_model_.mutable_objective()->set_offset(-expr.
constant());
760 cp_model_.mutable_objective()->set_scaling_factor(-1.0);
764 CHECK(cp_model_.has_objective());
765 cp_model_.mutable_objective()->set_scaling_factor(
766 scaling * cp_model_.objective().scaling_factor());
770 absl::Span<const IntVar> variables,
771 DecisionStrategyProto::VariableSelectionStrategy var_strategy,
772 DecisionStrategyProto::DomainReductionStrategy domain_strategy) {
773 DecisionStrategyProto*
const proto = cp_model_.add_search_strategy();
777 proto->set_variable_selection_strategy(var_strategy);
778 proto->set_domain_reduction_strategy(domain_strategy);
782 absl::Span<const BoolVar> variables,
783 DecisionStrategyProto::VariableSelectionStrategy var_strategy,
784 DecisionStrategyProto::DomainReductionStrategy domain_strategy) {
785 DecisionStrategyProto*
const proto = cp_model_.add_search_strategy();
789 proto->set_variable_selection_strategy(var_strategy);
790 proto->set_domain_reduction_strategy(domain_strategy);
794 cp_model_.mutable_solution_hint()->add_vars(
795 GetOrCreateIntegerIndex(
var.index_));
796 cp_model_.mutable_solution_hint()->add_values(
value);
801 for (
int i = 0; i < expr.
variables().size(); ++i) {
808 if (r.solution_size() > 0) {
809 return r.solution(x.index_);
811 return r.solution_lower_bounds(x.index_);
816 if (r.solution_size() > 0) {
817 return r.solution(x.index_);
819 return r.solution_upper_bounds(x.index_);
824 const int ref = x.index_;
826 return r.solution(ref) == 1;