OR-Tools  9.6
cp_model.cc
Go to the documentation of this file.
1 // Copyright 2010-2022 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 #include "ortools/sat/cp_model.h"
15 
16 #include <cstdint>
17 #include <initializer_list>
18 #include <limits>
19 #include <ostream>
20 #include <string>
21 #include <vector>
22 
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"
27 #include "ortools/base/logging.h"
28 #include "ortools/sat/cp_model.pb.h"
31 
32 namespace operations_research {
33 namespace sat {
34 
35 BoolVar::BoolVar(int index, CpModelBuilder* builder)
36  : builder_(builder), index_(index) {}
37 
38 BoolVar BoolVar::WithName(const std::string& name) {
39  DCHECK(builder_ != nullptr);
40  if (builder_ == nullptr) return *this;
41  builder_->MutableProto()
42  ->mutable_variables(PositiveRef(index_))
43  ->set_name(name);
44  return *this;
45 }
46 
47 std::string BoolVar::Name() const {
48  if (builder_ == nullptr) return "null";
49  const std::string& name =
50  builder_->Proto().variables(PositiveRef(index_)).name();
51  if (RefIsPositive(index_)) {
52  return name;
53  } else {
54  return absl::StrCat("Not(", name, ")");
55  }
56 }
57 
58 std::string BoolVar::DebugString() const {
59  if (builder_ == nullptr) return "null";
60  if (index_ < 0) {
61  return absl::StrFormat("Not(%s)", Not().DebugString());
62  } else {
63  std::string output;
64  const IntegerVariableProto& var_proto = builder_->Proto().variables(index_);
65  // Special case for constant variables without names.
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");
69  } else {
70  if (var_proto.name().empty()) {
71  absl::StrAppendFormat(&output, "BoolVar%i(", index_);
72  } else {
73  absl::StrAppendFormat(&output, "%s(", var_proto.name());
74  }
75  if (var_proto.domain(0) == var_proto.domain(1)) {
76  output.append(var_proto.domain(0) == 0 ? "false)" : "true)");
77  } else {
78  absl::StrAppend(&output, var_proto.domain(0), ", ", var_proto.domain(1),
79  ")");
80  }
81  }
82  return output;
83  }
84 }
85 
86 BoolVar Not(BoolVar x) { return x.Not(); }
87 
88 std::ostream& operator<<(std::ostream& os, const BoolVar& var) {
89  os << var.DebugString();
90  return os;
91 }
92 
93 IntVar::IntVar(int index, CpModelBuilder* builder)
94  : builder_(builder), index_(index) {
95  DCHECK(RefIsPositive(index_));
96 }
97 
99  if (var.builder_ == nullptr) {
100  *this = IntVar();
101  return;
102  }
103  builder_ = var.builder_;
104  index_ = builder_->GetOrCreateIntegerIndex(var.index_);
105  DCHECK(RefIsPositive(index_));
106 }
107 
108 BoolVar IntVar::ToBoolVar() const {
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);
114  }
115  return BoolVar(index_, builder_);
116 }
117 
118 IntVar IntVar::WithName(const std::string& name) {
119  DCHECK(builder_ != nullptr);
120  if (builder_ == nullptr) return *this;
121  builder_->MutableProto()->mutable_variables(index_)->set_name(name);
122  return *this;
123 }
124 
125 std::string IntVar::Name() const {
126  if (builder_ == nullptr) return "null";
127  return builder_->Proto().variables(index_).name();
128 }
129 
130 ::operations_research::Domain IntVar::Domain() const {
131  if (builder_ == nullptr) return Domain();
132  return ReadDomainFromProto(builder_->Proto().variables(index_));
133 }
134 
135 std::string IntVar::DebugString() const {
136  if (builder_ == nullptr) return "null";
137  return VarDebugString(builder_->Proto(), index_);
138 }
139 
140 // TODO(user): unfortunately, we need this indirection to get a DebugString()
141 // in a const way from an index. Because building an IntVar is non-const.
142 std::string VarDebugString(const CpModelProto& proto, int index) {
143  std::string output;
144 
145  // Special case for constant variables without names.
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));
150  } else {
151  if (var_proto.name().empty()) {
152  absl::StrAppend(&output, "V", index, "(");
153  } else {
154  absl::StrAppend(&output, var_proto.name(), "(");
155  }
156 
157  // TODO(user): Use domain pretty print function.
158  if (var_proto.domain_size() == 2 &&
159  var_proto.domain(0) == var_proto.domain(1)) {
160  absl::StrAppend(&output, var_proto.domain(0), ")");
161  } else {
162  absl::StrAppend(&output, var_proto.domain(0), ", ", var_proto.domain(1),
163  ")");
164  }
165  }
166 
167  return output;
168 }
169 
170 std::ostream& operator<<(std::ostream& os, const IntVar& var) {
171  os << var.DebugString();
172  return os;
173 }
174 
176  DCHECK(var.builder_ != nullptr);
177  const int index = var.index_;
178  if (RefIsPositive(index)) {
179  variables_.push_back(index);
180  coefficients_.push_back(1);
181  } else {
182  // We add 1 - var instead.
183  variables_.push_back(PositiveRef(index));
184  coefficients_.push_back(-1);
185  constant_ += 1;
186  }
187 }
188 
190  DCHECK(var.builder_ != nullptr);
191  variables_.push_back(var.index_);
192  coefficients_.push_back(1);
193 }
194 
195 LinearExpr::LinearExpr(int64_t constant) { constant_ = constant; }
196 
197 LinearExpr LinearExpr::FromProto(const LinearExpressionProto& expr_proto) {
198  LinearExpr result(expr_proto.offset());
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));
202  }
203  return result;
204 }
205 
206 LinearExpr LinearExpr::Sum(absl::Span<const IntVar> vars) {
207  LinearExpr result;
208  for (const IntVar& var : vars) {
209  result += var;
210  }
211  return result;
212 }
213 
214 LinearExpr LinearExpr::Sum(absl::Span<const BoolVar> vars) {
215  LinearExpr result;
216  for (const BoolVar& var : vars) {
217  result += var;
218  }
219  return result;
220 }
221 
222 LinearExpr LinearExpr::WeightedSum(absl::Span<const IntVar> vars,
223  absl::Span<const int64_t> coeffs) {
224  CHECK_EQ(vars.size(), coeffs.size());
225  LinearExpr result;
226  for (int i = 0; i < vars.size(); ++i) {
227  result += vars[i] * coeffs[i];
228  }
229  return result;
230 }
231 
232 LinearExpr LinearExpr::WeightedSum(absl::Span<const BoolVar> vars,
233  absl::Span<const int64_t> coeffs) {
234  CHECK_EQ(vars.size(), coeffs.size());
235  LinearExpr result;
236  for (int i = 0; i < vars.size(); ++i) {
237  result += vars[i] * coeffs[i];
238  }
239  return result;
240 }
241 
242 LinearExpr LinearExpr::Term(IntVar var, int64_t coefficient) {
243  LinearExpr result;
244  result += var * coefficient;
245  return result;
246 }
247 
248 LinearExpr LinearExpr::Term(BoolVar var, int64_t coefficient) {
249  LinearExpr result;
250  result += var * coefficient;
251  return result;
252 }
253 
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());
260  return *this;
261 }
262 
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);
269  }
270  return *this;
271 }
272 
274  constant_ *= factor;
275  for (int64_t& coeff : coefficients_) coeff *= factor;
276  return *this;
277 }
278 
279 std::string LinearExpr::DebugString(const CpModelProto* proto) const {
280  std::string result;
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])
285  : VarDebugString(*proto, variables_[i]);
286  if (i == 0) {
287  if (coeff == 1) {
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);
293  }
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);
302  }
303  }
304 
305  if (constant_ != 0) {
306  if (variables_.empty()) {
307  return absl::StrCat(constant_);
308  } else if (constant_ > 0) {
309  absl::StrAppend(&result, " + ", constant_);
310  } else {
311  absl::StrAppend(&result, " - ", -constant_);
312  }
313  }
314  return result;
315 }
316 
317 std::ostream& operator<<(std::ostream& os, const LinearExpr& e) {
318  os << e.DebugString();
319  return os;
320 }
321 
322 DoubleLinearExpr::DoubleLinearExpr() {}
323 
324 DoubleLinearExpr::DoubleLinearExpr(BoolVar var) { AddTerm(var, 1); }
325 
326 DoubleLinearExpr::DoubleLinearExpr(IntVar var) { AddTerm(var, 1); }
327 
328 DoubleLinearExpr::DoubleLinearExpr(double constant) { constant_ = constant; }
329 
330 DoubleLinearExpr DoubleLinearExpr::Sum(absl::Span<const IntVar> vars) {
331  DoubleLinearExpr result;
332  for (const IntVar& var : vars) {
333  result.AddTerm(var, 1.0);
334  }
335  return result;
336 }
337 
338 DoubleLinearExpr DoubleLinearExpr::Sum(absl::Span<const BoolVar> vars) {
339  DoubleLinearExpr result;
340  for (const BoolVar& var : vars) {
341  result.AddTerm(var, 1.0);
342  }
343  return result;
344 }
345 
346 DoubleLinearExpr DoubleLinearExpr::WeightedSum(
347  absl::Span<const IntVar> vars, absl::Span<const double> coeffs) {
348  CHECK_EQ(vars.size(), coeffs.size());
349  DoubleLinearExpr result;
350  for (int i = 0; i < vars.size(); ++i) {
351  result.AddTerm(vars[i], coeffs[i]);
352  }
353  return result;
354 }
355 
356 DoubleLinearExpr DoubleLinearExpr::WeightedSum(
357  absl::Span<const BoolVar> vars, absl::Span<const double> coeffs) {
358  CHECK_EQ(vars.size(), coeffs.size());
359  DoubleLinearExpr result;
360  for (int i = 0; i < vars.size(); ++i) {
361  result.AddTerm(vars[i], coeffs[i]);
362  }
363  return result;
364 }
365 
366 DoubleLinearExpr& DoubleLinearExpr::operator+=(double value) {
367  constant_ += value;
368  return *this;
369 }
370 
371 DoubleLinearExpr& DoubleLinearExpr::operator+=(IntVar var) {
372  AddTerm(var, 1);
373  return *this;
374 }
375 
376 DoubleLinearExpr& DoubleLinearExpr::operator+=(BoolVar var) {
377  AddTerm(var, 1);
378  return *this;
379 }
380 
381 DoubleLinearExpr& DoubleLinearExpr::operator+=(const DoubleLinearExpr& expr) {
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());
387  return *this;
388 }
389 
390 DoubleLinearExpr& DoubleLinearExpr::AddTerm(IntVar var, double coeff) {
391  variables_.push_back(var.index_);
392  coefficients_.push_back(coeff);
393  return *this;
394 }
395 
396 DoubleLinearExpr& DoubleLinearExpr::AddTerm(BoolVar var, double coeff) {
397  const int index = var.index_;
398  if (RefIsPositive(index)) {
399  variables_.push_back(index);
400  coefficients_.push_back(coeff);
401  } else {
402  variables_.push_back(PositiveRef(index));
403  coefficients_.push_back(-coeff);
404  constant_ += coeff;
405  }
406  return *this;
407 }
408 
409 DoubleLinearExpr& DoubleLinearExpr::AddExpression(const LinearExpr& expr,
410  double coeff) {
411  const std::vector<int>& indices = expr.variables();
412  const std::vector<int64_t> coefficients = expr.coefficients();
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);
416  }
417 
418  return *this;
419 }
420 
421 DoubleLinearExpr& DoubleLinearExpr::operator-=(double value) {
422  constant_ -= value;
423  return *this;
424 }
425 
426 DoubleLinearExpr& DoubleLinearExpr::operator-=(IntVar var) {
427  AddTerm(var, -1.0);
428  return *this;
429 }
430 
431 DoubleLinearExpr& DoubleLinearExpr::operator-=(const DoubleLinearExpr& expr) {
432  constant_ -= expr.constant_;
433  variables_.insert(variables_.end(), expr.variables_.begin(),
434  expr.variables_.end());
435  for (const double coeff : expr.coefficients()) {
436  coefficients_.push_back(-coeff);
437  }
438  return *this;
439 }
440 
441 DoubleLinearExpr& DoubleLinearExpr::operator*=(double coeff) {
442  constant_ *= coeff;
443  for (double& c : coefficients_) {
444  c *= coeff;
445  }
446  return *this;
447 }
448 
449 std::string DoubleLinearExpr::DebugString(const CpModelProto* proto) const {
450  std::string result;
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])
455  : VarDebugString(*proto, variables_[i]);
456  if (i == 0) {
457  if (coeff == 1.0) {
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);
463  }
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);
472  }
473  }
474 
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_);
480  } else {
481  absl::StrAppend(&result, " - ", -constant_);
482  }
483  }
484  return result;
485 }
486 
487 std::ostream& operator<<(std::ostream& os, const DoubleLinearExpr& e) {
488  os << e.DebugString();
489  return os;
490 }
491 
492 Constraint::Constraint(ConstraintProto* proto) : proto_(proto) {}
493 
494 Constraint Constraint::WithName(const std::string& name) {
495  proto_->set_name(name);
496  return *this;
497 }
498 
499 const std::string& Constraint::Name() const { return proto_->name(); }
500 
501 Constraint Constraint::OnlyEnforceIf(absl::Span<const BoolVar> literals) {
502  for (const BoolVar& var : literals) {
503  proto_->add_enforcement_literal(var.index_);
504  }
505  return *this;
506 }
507 
509  proto_->add_enforcement_literal(literal.index_);
510  return *this;
511 }
512 
514  proto_->mutable_circuit()->add_tails(tail);
515  proto_->mutable_circuit()->add_heads(head);
516  proto_->mutable_circuit()->add_literals(literal.index_);
517 }
518 
520  proto_->mutable_routes()->add_tails(tail);
521  proto_->mutable_routes()->add_heads(head);
522  proto_->mutable_routes()->add_literals(literal.index_);
523 }
524 
525 void TableConstraint::AddTuple(absl::Span<const int64_t> tuple) {
526  CHECK_EQ(tuple.size(), proto_->table().vars_size());
527  for (const int64_t t : tuple) {
528  proto_->mutable_table()->add_values(t);
529  }
530 }
531 
532 ReservoirConstraint::ReservoirConstraint(ConstraintProto* proto,
533  CpModelBuilder* builder)
534  : Constraint(proto), builder_(builder) {}
535 
536 void ReservoirConstraint::AddEvent(LinearExpr time, int64_t level_change) {
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));
542 }
543 
545  int64_t level_change,
546  BoolVar is_active) {
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_);
551 }
552 
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);
558 }
559 
561  IntervalVar y_coordinate) {
562  proto_->mutable_no_overlap_2d()->add_x_intervals(x_coordinate.index_);
563  proto_->mutable_no_overlap_2d()->add_y_intervals(y_coordinate.index_);
564 }
565 
566 CumulativeConstraint::CumulativeConstraint(ConstraintProto* proto,
567  CpModelBuilder* builder)
568  : Constraint(proto), builder_(builder) {}
569 
571  proto_->mutable_cumulative()->add_intervals(interval.index_);
572  *proto_->mutable_cumulative()->add_demands() =
573  builder_->LinearExprToProto(demand);
574 }
575 
576 IntervalVar::IntervalVar() : builder_(nullptr), index_() {}
577 
579  : builder_(builder), index_(index) {}
580 
582  DCHECK(builder_ != nullptr);
583  if (builder_ == nullptr) return *this;
584  builder_->MutableProto()->mutable_constraints(index_)->set_name(name);
585  return *this;
586 }
587 
589  DCHECK(builder_ != nullptr);
590  if (builder_ == nullptr) return LinearExpr();
591  return LinearExpr::FromProto(
592  builder_->Proto().constraints(index_).interval().start());
593 }
594 
596  DCHECK(builder_ != nullptr);
597  if (builder_ == nullptr) return LinearExpr();
598  return LinearExpr::FromProto(
599  builder_->Proto().constraints(index_).interval().size());
600 }
601 
603  DCHECK(builder_ != nullptr);
604  if (builder_ == nullptr) return LinearExpr();
605  return LinearExpr::FromProto(
606  builder_->Proto().constraints(index_).interval().end());
607 }
608 
610  DCHECK(builder_ != nullptr);
611  if (builder_ == nullptr) return BoolVar();
612  return BoolVar(builder_->Proto().constraints(index_).enforcement_literal(0),
613  builder_);
614 }
615 
616 std::string IntervalVar::Name() const {
617  if (builder_ == nullptr) return "null";
618  return builder_->Proto().constraints(index_).name();
619 }
620 
621 std::string IntervalVar::DebugString() const {
622  if (builder_ == nullptr) return "null";
623 
624  CHECK_GE(index_, 0);
625  const CpModelProto& proto = builder_->Proto();
626  const ConstraintProto& ct_proto = proto.constraints(index_);
627  std::string output;
628  if (ct_proto.name().empty()) {
629  absl::StrAppend(&output, "IntervalVar", index_, "(");
630  } else {
631  absl::StrAppend(&output, ct_proto.name(), "(");
632  }
633  absl::StrAppend(&output, StartExpr().DebugString(&proto), ", ",
634  SizeExpr().DebugString(&proto), ", ",
635  EndExpr().DebugString(&proto), ", ",
636  PresenceBoolVar().DebugString(), ")");
637  return output;
638 }
639 
640 std::ostream& operator<<(std::ostream& os, const IntervalVar& var) {
641  os << var.DebugString();
642  return os;
643 }
644 
645 void CpModelBuilder::SetName(const std::string& name) {
646  cp_model_.set_name(name);
647 }
648 
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);
655  constant_to_index_map_[value] = index;
656  }
657  return constant_to_index_map_[value];
658 }
659 
660 int CpModelBuilder::GetOrCreateIntegerIndex(int index) {
661  if (index >= 0) {
662  return index;
663  }
664  if (!bool_to_integer_index_map_.contains(index)) {
665  const int var = PositiveRef(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(), ")"));
673  }
674  AddEquality(IntVar(new_index, this), BoolVar(index, this));
675  bool_to_integer_index_map_[index] = new_index;
676  return new_index;
677  }
678  return bool_to_integer_index_map_[index];
679 }
680 
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);
687  }
688  return IntVar(index, this);
689 }
690 
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);
696  return BoolVar(index, this);
697 }
698 
700  return IntVar(IndexFromConstant(value), this);
701 }
702 
704  return BoolVar(IndexFromConstant(1), this);
705 }
706 
708  return BoolVar(IndexFromConstant(0), this);
709 }
710 
712  const LinearExpr& size,
713  const LinearExpr& end) {
714  return NewOptionalIntervalVar(start, size, end, TrueVar());
715 }
716 
718  int64_t size) {
720 }
721 
723  const LinearExpr& size,
724  const LinearExpr& end,
725  BoolVar presence) {
726  AddEquality(LinearExpr(start) + size, end).OnlyEnforceIf(presence);
727 
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();
732  *interval->mutable_start() = LinearExprToProto(start);
733  *interval->mutable_size() = LinearExprToProto(size);
734  *interval->mutable_end() = LinearExprToProto(end);
735  return IntervalVar(index, this);
736 }
737 
739  const LinearExpr& start, int64_t size, BoolVar presence) {
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();
744  *interval->mutable_start() = LinearExprToProto(start);
745  interval->mutable_size()->set_offset(size);
746  *interval->mutable_end() = LinearExprToProto(start);
747  interval->mutable_end()->set_offset(interval->end().offset() + size);
748  return IntervalVar(index, this);
749 }
750 
752  FillDomainInProto(Domain(value), cp_model_.mutable_variables(var.index()));
753 }
754 
756  const int index = var.index();
757  if (RefIsPositive(index)) {
758  FillDomainInProto(Domain(value), cp_model_.mutable_variables(index));
759  } else {
761  cp_model_.mutable_variables(NegatedRef(index)));
762  }
763 }
764 
765 Constraint CpModelBuilder::AddBoolOr(absl::Span<const BoolVar> literals) {
766  ConstraintProto* const proto = cp_model_.add_constraints();
767  for (const BoolVar& lit : literals) {
768  proto->mutable_bool_or()->add_literals(lit.index_);
769  }
770  return Constraint(proto);
771 }
772 
773 Constraint CpModelBuilder::AddAtLeastOne(absl::Span<const BoolVar> literals) {
774  return AddBoolOr(literals);
775 }
776 
777 Constraint CpModelBuilder::AddAtMostOne(absl::Span<const BoolVar> literals) {
778  ConstraintProto* const proto = cp_model_.add_constraints();
779  for (const BoolVar& lit : literals) {
780  proto->mutable_at_most_one()->add_literals(lit.index_);
781  }
782  return Constraint(proto);
783 }
784 
785 Constraint CpModelBuilder::AddExactlyOne(absl::Span<const BoolVar> literals) {
786  ConstraintProto* const proto = cp_model_.add_constraints();
787  for (const BoolVar& lit : literals) {
788  proto->mutable_exactly_one()->add_literals(lit.index_);
789  }
790  return Constraint(proto);
791 }
792 
793 Constraint CpModelBuilder::AddBoolAnd(absl::Span<const BoolVar> literals) {
794  ConstraintProto* const proto = cp_model_.add_constraints();
795  for (const BoolVar& lit : literals) {
796  proto->mutable_bool_and()->add_literals(lit.index_);
797  }
798  return Constraint(proto);
799 }
800 
801 Constraint CpModelBuilder::AddBoolXor(absl::Span<const BoolVar> literals) {
802  ConstraintProto* const proto = cp_model_.add_constraints();
803  for (const BoolVar& lit : literals) {
804  proto->mutable_bool_xor()->add_literals(lit.index_);
805  }
806  return Constraint(proto);
807 }
808 
809 void CpModelBuilder::FillLinearTerms(const LinearExpr& left,
810  const LinearExpr& right,
811  LinearConstraintProto* proto) {
812  for (const int x : left.variables()) {
813  proto->add_vars(x);
814  }
815  for (const int64_t coeff : left.coefficients()) {
816  proto->add_coeffs(coeff);
817  }
818  for (const int x : right.variables()) {
819  proto->add_vars(x);
820  }
821  for (const int64_t coeff : right.coefficients()) {
822  proto->add_coeffs(-coeff);
823  }
824 }
825 
827  const LinearExpr& right) {
828  ConstraintProto* const proto = cp_model_.add_constraints();
829  FillLinearTerms(left, right, proto->mutable_linear());
830  const int64_t rhs = right.constant() - left.constant();
831  proto->mutable_linear()->add_domain(rhs);
832  proto->mutable_linear()->add_domain(rhs);
833  return Constraint(proto);
834 }
835 
837  const LinearExpr& right) {
838  ConstraintProto* const proto = cp_model_.add_constraints();
839  FillLinearTerms(left, right, proto->mutable_linear());
840  const int64_t rhs = right.constant() - left.constant();
841  proto->mutable_linear()->add_domain(rhs);
842  proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::max());
843  return Constraint(proto);
844 }
845 
847  const LinearExpr& right) {
848  ConstraintProto* const proto = cp_model_.add_constraints();
849  FillLinearTerms(left, right, proto->mutable_linear());
850  const int64_t rhs = right.constant() - left.constant();
851  proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::min());
852  proto->mutable_linear()->add_domain(rhs);
853  return Constraint(proto);
854 }
855 
857  const LinearExpr& right) {
858  ConstraintProto* const proto = cp_model_.add_constraints();
859  FillLinearTerms(left, right, proto->mutable_linear());
860  const int64_t rhs = right.constant() - left.constant();
861  proto->mutable_linear()->add_domain(rhs + 1);
862  proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::max());
863  return Constraint(proto);
864 }
865 
867  const LinearExpr& right) {
868  ConstraintProto* const proto = cp_model_.add_constraints();
869  FillLinearTerms(left, right, proto->mutable_linear());
870  const int64_t rhs = right.constant() - left.constant();
871  proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::min());
872  proto->mutable_linear()->add_domain(rhs - 1);
873  return Constraint(proto);
874 }
875 
877  const Domain& domain) {
878  ConstraintProto* const proto = cp_model_.add_constraints();
879  for (const int x : expr.variables()) {
880  proto->mutable_linear()->add_vars(x);
881  }
882  for (const int64_t coeff : expr.coefficients()) {
883  proto->mutable_linear()->add_coeffs(coeff);
884  }
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);
889  }
890  return Constraint(proto);
891 }
892 
894  const LinearExpr& right) {
895  ConstraintProto* const proto = cp_model_.add_constraints();
896  FillLinearTerms(left, right, proto->mutable_linear());
897  const int64_t rhs = right.constant() - left.constant();
898  proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::min());
899  proto->mutable_linear()->add_domain(rhs - 1);
900  proto->mutable_linear()->add_domain(rhs + 1);
901  proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::max());
902  return Constraint(proto);
903 }
904 
905 Constraint CpModelBuilder::AddAllDifferent(absl::Span<const IntVar> vars) {
906  ConstraintProto* const proto = cp_model_.add_constraints();
907  for (const IntVar& var : vars) {
908  auto* expr = proto->mutable_all_diff()->add_exprs();
909  expr->add_vars(var.index_);
910  expr->add_coeffs(1);
911  }
912  return Constraint(proto);
913 }
914 
915 Constraint CpModelBuilder::AddAllDifferent(absl::Span<const LinearExpr> exprs) {
916  ConstraintProto* const proto = cp_model_.add_constraints();
917  for (const LinearExpr& expr : exprs) {
918  *proto->mutable_all_diff()->add_exprs() = LinearExprToProto(expr);
919  }
920  return Constraint(proto);
921 }
922 
924  std::initializer_list<LinearExpr> exprs) {
925  ConstraintProto* const proto = cp_model_.add_constraints();
926  for (const LinearExpr& expr : exprs) {
927  *proto->mutable_all_diff()->add_exprs() = LinearExprToProto(expr);
928  }
929  return Constraint(proto);
930 }
931 
933  IntVar index, absl::Span<const IntVar> variables, IntVar target) {
934  ConstraintProto* const proto = cp_model_.add_constraints();
935  proto->mutable_element()->set_index(index.index_);
936  proto->mutable_element()->set_target(target.index_);
937  for (const IntVar& var : variables) {
938  proto->mutable_element()->add_vars(var.index_);
939  }
940  return Constraint(proto);
941 }
942 
944  absl::Span<const int64_t> values,
945  IntVar target) {
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));
951  }
952  return Constraint(proto);
953 }
954 
956  return CircuitConstraint(cp_model_.add_constraints());
957 }
958 
960  return MultipleCircuitConstraint(cp_model_.add_constraints());
961 }
962 
964  absl::Span<const IntVar> vars) {
965  ConstraintProto* const proto = cp_model_.add_constraints();
966  for (const IntVar& var : vars) {
967  proto->mutable_table()->add_vars(var.index_);
968  }
969  return TableConstraint(proto);
970 }
971 
973  absl::Span<const IntVar> vars) {
974  ConstraintProto* const proto = cp_model_.add_constraints();
975  for (const IntVar& var : vars) {
976  proto->mutable_table()->add_vars(var.index_);
977  }
978  proto->mutable_table()->set_negated(true);
979  return TableConstraint(proto);
980 }
981 
983  absl::Span<const IntVar> variables,
984  absl::Span<const IntVar> inverse_variables) {
985  ConstraintProto* const proto = cp_model_.add_constraints();
986  for (const IntVar& var : variables) {
987  proto->mutable_inverse()->add_f_direct(var.index_);
988  }
989  for (const IntVar& var : inverse_variables) {
990  proto->mutable_inverse()->add_f_inverse(var.index_);
991  }
992  return Constraint(proto);
993 }
994 
996  int64_t max_level) {
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);
1000  return ReservoirConstraint(proto, this);
1001 }
1002 
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_);
1009  }
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);
1013  }
1014  return AutomatonConstraint(proto);
1015 }
1016 
1017 LinearExpressionProto CpModelBuilder::LinearExprToProto(const LinearExpr& expr,
1018  bool negate) {
1019  LinearExpressionProto expr_proto;
1020  for (const int var : expr.variables()) {
1021  expr_proto.add_vars(var);
1022  }
1023  const int64_t mult = negate ? -1 : 1;
1024  for (const int64_t coeff : expr.coefficients()) {
1025  expr_proto.add_coeffs(coeff * mult);
1026  }
1027  expr_proto.set_offset(expr.constant() * mult);
1028  return expr_proto;
1029 }
1030 
1032  absl::Span<const IntVar> vars) {
1033  ConstraintProto* ct = cp_model_.add_constraints();
1034  *ct->mutable_lin_max()->mutable_target() =
1035  LinearExprToProto(target, /*negate=*/true);
1036  for (const IntVar& var : vars) {
1037  *ct->mutable_lin_max()->add_exprs() =
1038  LinearExprToProto(var, /*negate=*/true);
1039  }
1040  return Constraint(ct);
1041 }
1042 
1044  absl::Span<const LinearExpr> exprs) {
1045  ConstraintProto* ct = cp_model_.add_constraints();
1046  *ct->mutable_lin_max()->mutable_target() =
1047  LinearExprToProto(target, /*negate=*/true);
1048  for (const LinearExpr& expr : exprs) {
1049  *ct->mutable_lin_max()->add_exprs() =
1050  LinearExprToProto(expr, /*negate=*/true);
1051  }
1052  return Constraint(ct);
1053 }
1054 
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, /*negate=*/true);
1060  for (const LinearExpr& expr : exprs) {
1061  *ct->mutable_lin_max()->add_exprs() =
1062  LinearExprToProto(expr, /*negate=*/true);
1063  }
1064  return Constraint(ct);
1065 }
1066 
1068  absl::Span<const IntVar> vars) {
1069  ConstraintProto* ct = cp_model_.add_constraints();
1070  *ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1071  for (const IntVar& var : vars) {
1072  *ct->mutable_lin_max()->add_exprs() = LinearExprToProto(var);
1073  }
1074  return Constraint(ct);
1075 }
1076 
1078  absl::Span<const LinearExpr> exprs) {
1079  ConstraintProto* ct = cp_model_.add_constraints();
1080  *ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1081  for (const LinearExpr& expr : exprs) {
1082  *ct->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1083  }
1084  return Constraint(ct);
1085 }
1086 
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);
1091  for (const LinearExpr& expr : exprs) {
1092  *ct->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1093  }
1094  return Constraint(ct);
1095 }
1096 
1098  const LinearExpr& numerator,
1099  const LinearExpr& denominator) {
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);
1104  return Constraint(proto);
1105 }
1106 
1108  const LinearExpr& expr) {
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, /*negate=*/true);
1114  return Constraint(proto);
1115 }
1116 
1118  const LinearExpr& var,
1119  const LinearExpr& mod) {
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);
1124  return Constraint(proto);
1125 }
1126 
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);
1131  for (const IntVar& var : vars) {
1132  *proto->mutable_int_prod()->add_exprs() = LinearExprToProto(var);
1133  }
1134  return Constraint(proto);
1135 }
1136 
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);
1141  for (const LinearExpr& expr : exprs) {
1142  *proto->mutable_int_prod()->add_exprs() = LinearExprToProto(expr);
1143  }
1144  return Constraint(proto);
1145 }
1146 
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);
1151  for (const LinearExpr& expr : exprs) {
1152  *proto->mutable_int_prod()->add_exprs() = LinearExprToProto(expr);
1153  }
1154  return Constraint(proto);
1155 }
1157  const LinearExpr& left,
1158  const LinearExpr& right) {
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);
1163 
1164  return Constraint(proto);
1165 }
1166 
1167 Constraint CpModelBuilder::AddNoOverlap(absl::Span<const IntervalVar> vars) {
1168  ConstraintProto* const proto = cp_model_.add_constraints();
1169  for (const IntervalVar& var : vars) {
1170  proto->mutable_no_overlap()->add_intervals(var.index_);
1171  }
1172  return Constraint(proto);
1173 }
1174 
1176  return NoOverlap2DConstraint(cp_model_.add_constraints());
1177 }
1178 
1180  ConstraintProto* const proto = cp_model_.add_constraints();
1181  *proto->mutable_cumulative()->mutable_capacity() =
1182  LinearExprToProto(capacity);
1183  return CumulativeConstraint(proto, this);
1184 }
1185 
1187  ClearObjective();
1188  for (const int x : expr.variables()) {
1189  cp_model_.mutable_objective()->add_vars(x);
1190  }
1191  for (const int64_t coeff : expr.coefficients()) {
1192  cp_model_.mutable_objective()->add_coeffs(coeff);
1193  }
1194  cp_model_.mutable_objective()->set_offset(expr.constant());
1195 }
1196 
1198  ClearObjective();
1199  for (const int x : expr.variables()) {
1200  cp_model_.mutable_objective()->add_vars(x);
1201  }
1202  for (const int64_t coeff : expr.coefficients()) {
1203  cp_model_.mutable_objective()->add_coeffs(-coeff);
1204  }
1205  cp_model_.mutable_objective()->set_offset(-expr.constant());
1206  cp_model_.mutable_objective()->set_scaling_factor(-1.0);
1207 }
1208 
1210  ClearObjective();
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(
1214  expr.coefficients()[i]);
1215  }
1216  cp_model_.mutable_floating_point_objective()->set_offset(expr.constant());
1217  cp_model_.mutable_floating_point_objective()->set_maximize(false);
1218 }
1219 
1221  ClearObjective();
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(
1225  expr.coefficients()[i]);
1226  }
1227  cp_model_.mutable_floating_point_objective()->set_offset(expr.constant());
1228  cp_model_.mutable_floating_point_objective()->set_maximize(true);
1229 }
1230 
1232  cp_model_.clear_objective();
1233  cp_model_.clear_floating_point_objective();
1234 }
1235 
1237  return cp_model_.has_objective() || cp_model_.has_floating_point_objective();
1238 }
1239 
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();
1245  for (const IntVar& var : variables) {
1246  proto->add_variables(var.index_);
1247  }
1248  proto->set_variable_selection_strategy(var_strategy);
1249  proto->set_domain_reduction_strategy(domain_strategy);
1250 }
1251 
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();
1257  for (const BoolVar& var : variables) {
1258  proto->add_variables(var.index_);
1259  }
1260  proto->set_variable_selection_strategy(var_strategy);
1261  proto->set_domain_reduction_strategy(domain_strategy);
1262 }
1263 
1265  cp_model_.mutable_solution_hint()->add_vars(var.index_);
1266  cp_model_.mutable_solution_hint()->add_values(value);
1267 }
1268 
1270  if (var.index_ >= 0) {
1271  cp_model_.mutable_solution_hint()->add_vars(var.index_);
1272  cp_model_.mutable_solution_hint()->add_values(value);
1273  } else {
1274  cp_model_.mutable_solution_hint()->add_vars(PositiveRef(var.index_));
1275  cp_model_.mutable_solution_hint()->add_values(!value);
1276  }
1277 }
1278 
1280  cp_model_.mutable_solution_hint()->Clear();
1281 }
1282 
1284  cp_model_.mutable_assumptions()->Add(lit.index_);
1285 }
1286 
1287 void CpModelBuilder::AddAssumptions(absl::Span<const BoolVar> literals) {
1288  for (const BoolVar& lit : literals) {
1289  cp_model_.mutable_assumptions()->Add(lit.index_);
1290  }
1291 }
1292 
1294  cp_model_.mutable_assumptions()->Clear();
1295 }
1296 
1297 void CpModelBuilder::CopyFrom(const CpModelProto& model_proto) {
1298  cp_model_ = model_proto;
1299  // Rebuild constant to index map.
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;
1305  }
1306  }
1307  // This one would be more complicated to rebuild. Let's just clear it.
1308  bool_to_integer_index_map_.clear();
1309 }
1310 
1312  CHECK_GE(index, 0);
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 "
1317  "is not Boolean";
1318  CHECK_GE(0, proto.domain(0))
1319  << "CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1320  "is not Boolean";
1321  CHECK_LE(1, proto.domain(1))
1322  << "CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1323  "is not Boolean";
1324  return BoolVar(index, this);
1325 }
1326 
1328  CHECK_GE(index, 0);
1329  CHECK_LT(index, cp_model_.variables_size());
1330  return IntVar(index, this);
1331 }
1332 
1334  CHECK_GE(index, 0);
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";
1340  return IntervalVar(index, this);
1341 }
1342 
1343 bool CpModelBuilder::ExportToFile(const std::string& filename) const {
1344  return WriteModelProtoToFile(cp_model_, filename);
1345 }
1346 
1347 int64_t SolutionIntegerValue(const CpSolverResponse& r,
1348  const LinearExpr& expr) {
1349  int64_t result = expr.constant();
1350  const std::vector<int>& variables = expr.variables();
1351  const std::vector<int64_t>& coefficients = expr.coefficients();
1352  for (int i = 0; i < variables.size(); ++i) {
1353  result += r.solution(variables[i]) * coefficients[i];
1354  }
1355  return result;
1356 }
1357 
1358 bool SolutionBooleanValue(const CpSolverResponse& r, BoolVar x) {
1359  const int ref = x.index_;
1360  if (RefIsPositive(ref)) {
1361  return r.solution(ref) == 1;
1362  } else {
1363  return r.solution(PositiveRef(ref)) == 0;
1364  }
1365 }
1366 
1367 } // namespace sat
1368 } // namespace operations_research
int64_t max
Definition: alldiff_cst.cc:140
int64_t min
Definition: alldiff_cst.cc:139
We call domain any subset of Int64 = [kint64min, kint64max].
IntVar(Solver *const s)
Definition: expressions.cc:59
LinearExpr & operator*=(double rhs)
Definition: linear_expr.cc:52
LinearExpr & operator+=(const LinearExpr &rhs)
Definition: linear_expr.cc:36
LinearExpr & operator-=(const LinearExpr &rhs)
Definition: linear_expr.cc:44
virtual std::string name() const
Object naming.
Specialized automaton constraint.
Definition: cp_model.h:673
void AddTransition(int tail, int head, int64_t transition_label)
Adds a transitions to the automaton.
Definition: cp_model.cc:553
A Boolean variable.
Definition: cp_model.h:74
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.
Definition: cp_model.h:90
Specialized circuit constraint.
Definition: cp_model.h:577
void AddArc(int tail, int head, BoolVar literal)
Add an arc to the circuit.
Definition: cp_model.cc:513
Constraint OnlyEnforceIf(absl::Span< const BoolVar > literals)
The constraint will be enforced iff all literals listed here are true.
Definition: cp_model.cc:501
Constraint WithName(const std::string &name)
Sets the name of the constraint.
Definition: cp_model.cc:494
const std::string & Name() const
Returns the name of the constraint (or the empty string if not set).
Definition: cp_model.cc:499
Wrapper class around the cp_model proto.
Definition: cp_model.h:730
Constraint AddAtMostOne(absl::Span< const BoolVar > literals)
At most one literal is true. Sum literals <= 1.
Definition: cp_model.cc:777
void AddHint(IntVar var, int64_t value)
Adds hinting to a variable.
Definition: cp_model.cc:1264
TableConstraint AddForbiddenAssignments(absl::Span< const IntVar > vars)
Adds an forbidden assignments constraint.
Definition: cp_model.cc:972
Constraint AddMinEquality(const LinearExpr &target, absl::Span< const IntVar > vars)
Adds target == min(vars).
Definition: cp_model.cc:1031
Constraint AddLinearConstraint(const LinearExpr &expr, const Domain &domain)
Adds expr in domain.
Definition: cp_model.cc:876
void ClearAssumptions()
Remove all assumptions from the model.
Definition: cp_model.cc:1293
Constraint AddAbsEquality(const LinearExpr &target, const LinearExpr &expr)
Adds target == abs(expr).
Definition: cp_model.cc:1107
void AddAssumptions(absl::Span< const BoolVar > literals)
Adds multiple literals to the model as assumptions.
Definition: cp_model.cc:1287
IntervalVar NewFixedSizeIntervalVar(const LinearExpr &start, int64_t size)
Creates an interval variable with a fixed size.
Definition: cp_model.cc:717
MultipleCircuitConstraint AddMultipleCircuitConstraint()
Adds a multiple circuit constraint, aka the "VRP" (Vehicle Routing Problem) constraint.
Definition: cp_model.cc:959
BoolVar TrueVar()
Creates an always true Boolean variable.
Definition: cp_model.cc:703
IntVar NewIntVar(const Domain &domain)
Creates an integer variable with the given domain.
Definition: cp_model.cc:681
void ClearObjective()
Removes the objective from the model.
Definition: cp_model.cc:1231
void ClearHints()
Removes all hints.
Definition: cp_model.cc:1279
void Maximize(const LinearExpr &expr)
Adds a linear maximization objective.
Definition: cp_model.cc:1197
BoolVar NewBoolVar()
Creates a Boolean variable.
Definition: cp_model.cc:691
Constraint AddAtLeastOne(absl::Span< const BoolVar > literals)
Same as AddBoolOr(). Sum literals >= 1.
Definition: cp_model.cc:773
Constraint AddMaxEquality(const LinearExpr &target, absl::Span< const IntVar > vars)
Adds target == max(vars).
Definition: cp_model.cc:1067
Constraint AddMultiplicationEquality(const LinearExpr &target, absl::Span< const LinearExpr > exprs)
Adds target == prod(exprs).
Definition: cp_model.cc:1137
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.
Definition: cp_model.cc:1240
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.
Definition: cp_model.cc:722
CircuitConstraint AddCircuitConstraint()
Adds a circuit constraint.
Definition: cp_model.cc:955
Constraint AddVariableElement(IntVar index, absl::Span< const IntVar > variables, IntVar target)
Adds the element constraint: variables[index] == target.
Definition: cp_model.cc:932
const CpModelProto & Proto() const
Definition: cp_model.h:1094
Constraint AddGreaterThan(const LinearExpr &left, const LinearExpr &right)
Adds left > right.
Definition: cp_model.cc:856
bool HasObjective() const
Checks whether the model contains an objective.
Definition: cp_model.cc:1236
void CopyFrom(const CpModelProto &model_proto)
Replaces the current model with the one from the given proto.
Definition: cp_model.cc:1297
Constraint AddLessThan(const LinearExpr &left, const LinearExpr &right)
Adds left < right.
Definition: cp_model.cc:866
Constraint AddBoolXor(absl::Span< const BoolVar > literals)
Adds the constraint that an odd number of literals is true.
Definition: cp_model.cc:801
void SetName(const std::string &name)
Sets the name of the model.
Definition: cp_model.cc:645
Constraint AddElement(IntVar index, absl::Span< const int64_t > values, IntVar target)
Adds the element constraint: values[index] == target.
Definition: cp_model.cc:943
void AddAssumption(BoolVar lit)
Adds a literal to the model as assumptions.
Definition: cp_model.cc:1283
void Minimize(const LinearExpr &expr)
Adds a linear minimization objective.
Definition: cp_model.cc:1186
BoolVar FalseVar()
Creates an always false Boolean variable.
Definition: cp_model.cc:707
Constraint AddBoolAnd(absl::Span< const BoolVar > literals)
Adds the constraint that all literals must be true.
Definition: cp_model.cc:793
IntervalVar GetIntervalVarFromProtoIndex(int index)
Returns the interval variable from its index in the proto.
Definition: cp_model.cc:1333
CumulativeConstraint AddCumulative(LinearExpr capacity)
The cumulative constraint.
Definition: cp_model.cc:1179
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...
Definition: cp_model.cc:751
Constraint AddLessOrEqual(const LinearExpr &left, const LinearExpr &right)
Adds left <= right.
Definition: cp_model.cc:846
ReservoirConstraint AddReservoirConstraint(int64_t min_level, int64_t max_level)
Adds a reservoir constraint with optional refill/emptying events.
Definition: cp_model.cc:995
Constraint AddEquality(const LinearExpr &left, const LinearExpr &right)
Adds left == right.
Definition: cp_model.cc:826
NoOverlap2DConstraint AddNoOverlap2D()
The no_overlap_2d constraint prevents a set of boxes from overlapping.
Definition: cp_model.cc:1175
Constraint AddGreaterOrEqual(const LinearExpr &left, const LinearExpr &right)
Adds left >= right.
Definition: cp_model.cc:836
Constraint AddBoolOr(absl::Span< const BoolVar > literals)
Adds the constraint that at least one of the literals must be true.
Definition: cp_model.cc:765
IntVar GetIntVarFromProtoIndex(int index)
Returns the integer variable from its index in the proto.
Definition: cp_model.cc:1327
AutomatonConstraint AddAutomaton(absl::Span< const IntVar > transition_variables, int starting_state, absl::Span< const int > final_states)
An automaton constraint.
Definition: cp_model.cc:1003
bool ExportToFile(const std::string &filename) const
Export the model to file.
Definition: cp_model.cc:1343
IntervalVar NewOptionalFixedSizeIntervalVar(const LinearExpr &start, int64_t size, BoolVar presence)
Creates an optional interval variable with a fixed size.
Definition: cp_model.cc:738
Constraint AddDivisionEquality(const LinearExpr &target, const LinearExpr &numerator, const LinearExpr &denominator)
Adds target = num / denom (integer division rounded towards 0).
Definition: cp_model.cc:1097
BoolVar GetBoolVarFromProtoIndex(int index)
Returns the Boolean variable from its index in the proto.
Definition: cp_model.cc:1311
Constraint AddNotEqual(const LinearExpr &left, const LinearExpr &right)
Adds left != right.
Definition: cp_model.cc:893
Constraint AddModuloEquality(const LinearExpr &target, const LinearExpr &var, const LinearExpr &mod)
Adds target = var % mod.
Definition: cp_model.cc:1117
Constraint AddAllDifferent(absl::Span< const IntVar > vars)
This constraint forces all variables to have different values.
Definition: cp_model.cc:905
TableConstraint AddAllowedAssignments(absl::Span< const IntVar > vars)
Adds an allowed assignments constraint.
Definition: cp_model.cc:963
IntVar NewConstant(int64_t value)
Creates a constant variable.
Definition: cp_model.cc:699
IntervalVar NewIntervalVar(const LinearExpr &start, const LinearExpr &size, const LinearExpr &end)
Creates an interval variable from 3 affine expressions.
Definition: cp_model.cc:711
Constraint AddInverseConstraint(absl::Span< const IntVar > variables, absl::Span< const IntVar > inverse_variables)
An inverse constraint.
Definition: cp_model.cc:982
Constraint AddExactlyOne(absl::Span< const BoolVar > literals)
Exactly one literal is true. Sum literals == 1.
Definition: cp_model.cc:785
Constraint AddNoOverlap(absl::Span< const IntervalVar > vars)
Adds a no-overlap constraint that ensures that all present intervals do not overlap in time.
Definition: cp_model.cc:1167
Specialized cumulative constraint.
Definition: cp_model.h:710
void AddDemand(IntervalVar interval, LinearExpr demand)
Adds a pair (interval, demand) to the constraint.
Definition: cp_model.cc:570
A dedicated container for linear expressions with double coefficients.
Definition: cp_model.h:345
double constant() const
Returns the constant term.
Definition: cp_model.h:412
std::string DebugString(const CpModelProto *proto=nullptr) const
Debug string. See the documentation for LinearExpr::DebugString().
Definition: cp_model.cc:449
DoubleLinearExpr & AddTerm(IntVar var, double coeff)
Adds a term (var * coeff) to the linear expression.
Definition: cp_model.cc:390
const std::vector< double > & coefficients() const
Returns the vector of coefficients.
Definition: cp_model.h:406
const std::vector< int > & variables() const
Returns the vector of variable indices.
Definition: cp_model.h:403
An integer variable.
Definition: cp_model.h:142
std::string DebugString() const
Definition: cp_model.cc:135
Represents a Interval variable.
Definition: cp_model.h:445
LinearExpr SizeExpr() const
Returns the size linear expression.
Definition: cp_model.cc:595
LinearExpr StartExpr() const
Returns the start linear expression.
Definition: cp_model.cc:588
BoolVar PresenceBoolVar() const
Returns a BoolVar indicating the presence of this interval.
Definition: cp_model.cc:609
std::string Name() const
Returns the name of the interval (or the empty string if not set).
Definition: cp_model.cc:616
std::string DebugString() const
Returns a debug string.
Definition: cp_model.cc:621
IntervalVar WithName(const std::string &name)
Sets the name of the variable.
Definition: cp_model.cc:581
LinearExpr EndExpr() const
Returns the end linear expression.
Definition: cp_model.cc:602
IntervalVar()
A default constructed IntervalVar can be used to mean not defined yet.
Definition: cp_model.cc:576
A dedicated container for linear expressions.
Definition: cp_model.h:241
std::string DebugString(const CpModelProto *proto=nullptr) const
Debug string.
Definition: cp_model.cc:279
int64_t constant() const
Returns the constant term.
Definition: cp_model.h:298
static LinearExpr FromProto(const LinearExpressionProto &proto)
Constructs a linear expr from its proto representation.
Definition: cp_model.cc:197
const std::vector< int64_t > & coefficients() const
Returns the vector of coefficients.
Definition: cp_model.h:292
const std::vector< int > & variables() const
Returns the vector of variable indices.
Definition: cp_model.h:289
void AddArc(int tail, int head, BoolVar literal)
Add an arc to the circuit.
Definition: cp_model.cc:519
Specialized no_overlap2D constraint.
Definition: cp_model.h:690
void AddRectangle(IntervalVar x_coordinate, IntervalVar y_coordinate)
Adds a rectangle (parallel to the axis) to the constraint.
Definition: cp_model.cc:560
Specialized reservoir constraint.
Definition: cp_model.h:640
void AddOptionalEvent(LinearExpr time, int64_t level_change, BoolVar is_active)
Adds an optional event.
Definition: cp_model.cc:544
void AddEvent(LinearExpr time, int64_t level_change)
Adds a mandatory event.
Definition: cp_model.cc:536
Specialized assignment constraint.
Definition: cp_model.h:623
void AddTuple(absl::Span< const int64_t > tuple)
Adds a tuple of possible values to the constraint.
Definition: cp_model.cc:525
This file implements a wrapper around the CP-SAT model proto.
CpModelProto proto
CpModelProto const * model_proto
const std::string name
const Constraint * ct
int64_t value
IntVar * var
Definition: expr_array.cc:1874
absl::Span< const double > coefficients
int index
LinearExpression Sum(const Iterable &items)
std::ostream & operator<<(std::ostream &os, const BoolVar &var)
Definition: cp_model.cc:88
bool RefIsPositive(int ref)
std::string VarDebugString(const CpModelProto &proto, int index)
Definition: cp_model.cc:142
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.
Definition: cp_model.cc:86
bool SolutionBooleanValue(const CpSolverResponse &r, BoolVar x)
Evaluates the value of a Boolean literal in a solver response.
Definition: cp_model.cc:1358
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.
Definition: cp_model.cc:1347
Collection of objects used to extend the Constraint Solver library.
std::ostream & operator<<(std::ostream &out, const Assignment &assignment)
Literal literal
Definition: optimization.cc:88
int64_t demand
Definition: resource.cc:126
int64_t time
Definition: resource.cc:1694
IntervalVar * interval
Definition: resource.cc:101
int64_t coefficient
int64_t capacity
int64_t tail
int64_t head
std::optional< int64_t > end
int64_t start
std::ostream & operator<<(std::ostream &out, const std::pair< First, Second > &p)
Definition: stl_logging.h:99