Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
cp_model.cc
Go to the documentation of this file.
1// Copyright 2010-2025 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
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/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"
32
33namespace operations_research {
34namespace sat {
35
36BoolVar::BoolVar(int index, CpModelBuilder* builder)
37 : builder_(builder), index_(index) {}
38
39BoolVar BoolVar::WithName(absl::string_view name) {
40 DCHECK(builder_ != nullptr);
41 if (builder_ == nullptr) return *this;
42 builder_->MutableProto()
43 ->mutable_variables(PositiveRef(index_))
44 ->set_name(name);
45 return *this;
46}
47
48std::string BoolVar::Name() const {
49 if (builder_ == nullptr) return "null";
50 absl::string_view name =
51 builder_->Proto().variables(PositiveRef(index_)).name();
52 if (RefIsPositive(index_)) {
53 return std::string(name);
54 } else {
55 return absl::StrCat("Not(", name, ")");
56 }
57}
58
59std::string BoolVar::DebugString() const {
60 if (builder_ == nullptr) return "null";
61 if (index_ < 0) {
62 return absl::StrFormat("Not(%s)", Not().DebugString());
63 } else {
64 std::string output;
65 const IntegerVariableProto& var_proto = builder_->Proto().variables(index_);
66 // Special case for constant variables without names.
67 if (var_proto.name().empty() && var_proto.domain_size() == 2 &&
68 var_proto.domain(0) == var_proto.domain(1)) {
69 output.append(var_proto.domain(0) == 0 ? "false" : "true");
70 } else {
71 if (var_proto.name().empty()) {
72 absl::StrAppendFormat(&output, "BoolVar%i(", index_);
73 } else {
74 absl::StrAppendFormat(&output, "%s(", var_proto.name());
75 }
76 if (var_proto.domain(0) == var_proto.domain(1)) {
77 output.append(var_proto.domain(0) == 0 ? "false)" : "true)");
78 } else {
79 absl::StrAppend(&output, var_proto.domain(0), ", ", var_proto.domain(1),
80 ")");
81 }
82 }
83 return output;
84 }
85}
86
87BoolVar Not(BoolVar x) { return x.Not(); }
88
89std::ostream& operator<<(std::ostream& os, const BoolVar& var) {
90 os << var.DebugString();
91 return os;
92}
93
94IntVar::IntVar(int index, CpModelBuilder* builder)
95 : builder_(builder), index_(index) {
96 DCHECK(RefIsPositive(index_));
97}
98
100 if (var.builder_ == nullptr) {
101 *this = IntVar();
102 return;
103 }
104 builder_ = var.builder_;
105 index_ = builder_->GetOrCreateIntegerIndex(var.index_);
106 DCHECK(RefIsPositive(index_));
107}
108
110 if (builder_ != nullptr) {
111 const IntegerVariableProto& proto = builder_->Proto().variables(index_);
112 DCHECK_EQ(2, proto.domain_size());
113 DCHECK_GE(proto.domain(0), 0);
114 DCHECK_LE(proto.domain(1), 1);
115 }
116 return BoolVar(index_, builder_);
117}
118
119IntVar IntVar::WithName(absl::string_view name) {
120 DCHECK(builder_ != nullptr);
121 if (builder_ == nullptr) return *this;
122 builder_->MutableProto()->mutable_variables(index_)->set_name(name);
123 return *this;
124}
125
126std::string IntVar::Name() const {
127 if (builder_ == nullptr) return "null";
128 return builder_->Proto().variables(index_).name();
129}
130
132 if (builder_ == nullptr) return Domain();
133 return ReadDomainFromProto(builder_->Proto().variables(index_));
134}
135
136std::string IntVar::DebugString() const {
137 if (builder_ == nullptr) return "null";
138 return VarDebugString(builder_->Proto(), index_);
139}
140
141// TODO(user): unfortunately, we need this indirection to get a DebugString()
142// in a const way from an index. Because building an IntVar is non-const.
143std::string VarDebugString(const CpModelProto& proto, int index) {
144 std::string output;
145
146 // Special case for constant variables without names.
147 const IntegerVariableProto& var_proto = proto.variables(index);
148 if (var_proto.name().empty() && var_proto.domain_size() == 2 &&
149 var_proto.domain(0) == var_proto.domain(1)) {
150 absl::StrAppend(&output, var_proto.domain(0));
151 } else {
152 if (var_proto.name().empty()) {
153 absl::StrAppend(&output, "V", index, "(");
154 } else {
155 absl::StrAppend(&output, var_proto.name(), "(");
156 }
157
158 // TODO(user): Use domain pretty print function.
159 if (var_proto.domain_size() == 2 &&
160 var_proto.domain(0) == var_proto.domain(1)) {
161 absl::StrAppend(&output, var_proto.domain(0), ")");
162 } else {
163 absl::StrAppend(&output, var_proto.domain(0), ", ", var_proto.domain(1),
164 ")");
165 }
166 }
167
168 return output;
169}
170
171std::ostream& operator<<(std::ostream& os, const IntVar& var) {
172 os << var.DebugString();
173 return os;
174}
175
177 DCHECK(var.builder_ != nullptr);
178 const int index = var.index_;
179 if (RefIsPositive(index)) {
180 variables_.push_back(index);
181 coefficients_.push_back(1);
182 } else {
183 // We add 1 - var instead.
184 variables_.push_back(PositiveRef(index));
185 coefficients_.push_back(-1);
186 constant_ += 1;
187 }
188}
189
191 DCHECK(var.builder_ != nullptr);
192 variables_.push_back(var.index_);
193 coefficients_.push_back(1);
194}
195
196LinearExpr::LinearExpr(int64_t constant) { constant_ = constant; }
197
199 LinearExpr result(expr_proto.offset());
200 for (int i = 0; i < expr_proto.vars_size(); ++i) {
201 result.variables_.push_back(expr_proto.vars(i));
202 result.coefficients_.push_back(expr_proto.coeffs(i));
203 }
204 return result;
205}
206
207LinearExpr LinearExpr::Sum(absl::Span<const IntVar> vars) {
208 LinearExpr result;
209 for (const IntVar& var : vars) {
210 result += var;
211 }
212 return result;
213}
214
215LinearExpr LinearExpr::Sum(absl::Span<const BoolVar> vars) {
216 LinearExpr result;
217 for (const BoolVar& var : vars) {
218 result += var;
219 }
220 return result;
221}
222
223LinearExpr LinearExpr::WeightedSum(absl::Span<const IntVar> vars,
224 absl::Span<const int64_t> coeffs) {
225 CHECK_EQ(vars.size(), coeffs.size());
226 LinearExpr result;
227 for (int i = 0; i < vars.size(); ++i) {
228 result += vars[i] * coeffs[i];
229 }
230 return result;
231}
232
233LinearExpr LinearExpr::WeightedSum(absl::Span<const BoolVar> vars,
234 absl::Span<const int64_t> coeffs) {
235 CHECK_EQ(vars.size(), coeffs.size());
236 LinearExpr result;
237 for (int i = 0; i < vars.size(); ++i) {
238 result += vars[i] * coeffs[i];
239 }
240 return result;
241}
242
243LinearExpr LinearExpr::Term(IntVar var, int64_t coefficient) {
244 LinearExpr result;
245 result += var * coefficient;
246 return result;
247}
248
249LinearExpr LinearExpr::Term(BoolVar var, int64_t coefficient) {
250 LinearExpr result;
251 result += var * coefficient;
252 return result;
253}
254
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());
261 return *this;
262}
263
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);
270 }
271 return *this;
272}
273
275 constant_ *= factor;
276 for (int64_t& coeff : coefficients_) coeff *= factor;
277 return *this;
278}
279
280std::string LinearExpr::DebugString(const CpModelProto* proto) const {
281 std::string result;
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])
286 : VarDebugString(*proto, variables_[i]);
287 if (i == 0) {
288 if (coeff == 1) {
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);
294 }
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);
303 }
304 }
305
306 if (constant_ != 0) {
307 if (variables_.empty()) {
308 return absl::StrCat(constant_);
309 } else if (constant_ > 0) {
310 absl::StrAppend(&result, " + ", constant_);
311 } else {
312 absl::StrAppend(&result, " - ", -constant_);
313 }
314 }
315 return result;
316}
317
318std::ostream& operator<<(std::ostream& os, const LinearExpr& e) {
319 os << e.DebugString();
320 return os;
321}
322
323DoubleLinearExpr::DoubleLinearExpr() = default;
324
326
328
330
331DoubleLinearExpr DoubleLinearExpr::Sum(absl::Span<const IntVar> vars) {
332 DoubleLinearExpr result;
333 for (const IntVar& var : vars) {
334 result.AddTerm(var, 1.0);
335 }
336 return result;
337}
338
339DoubleLinearExpr DoubleLinearExpr::Sum(absl::Span<const BoolVar> vars) {
340 DoubleLinearExpr result;
341 for (const BoolVar& var : vars) {
342 result.AddTerm(var, 1.0);
343 }
344 return result;
345}
346
348 absl::Span<const IntVar> vars, absl::Span<const double> coeffs) {
349 CHECK_EQ(vars.size(), coeffs.size());
350 DoubleLinearExpr result;
351 for (int i = 0; i < vars.size(); ++i) {
352 result.AddTerm(vars[i], coeffs[i]);
353 }
354 return result;
355}
356
358 absl::Span<const BoolVar> vars, absl::Span<const double> coeffs) {
359 CHECK_EQ(vars.size(), coeffs.size());
360 DoubleLinearExpr result;
361 for (int i = 0; i < vars.size(); ++i) {
362 result.AddTerm(vars[i], coeffs[i]);
363 }
364 return result;
365}
366
368 constant_ += value;
369 return *this;
370}
371
373 AddTerm(var, 1);
374 return *this;
375}
376
378 AddTerm(var, 1);
379 return *this;
380}
381
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());
388 return *this;
389}
390
392 variables_.push_back(var.index_);
393 coefficients_.push_back(coeff);
394 return *this;
395}
396
398 const int index = var.index_;
399 if (RefIsPositive(index)) {
400 variables_.push_back(index);
401 coefficients_.push_back(coeff);
402 } else {
403 variables_.push_back(PositiveRef(index));
404 coefficients_.push_back(-coeff);
405 constant_ += coeff;
406 }
407 return *this;
408}
409
411 double coeff) {
412 const std::vector<int>& indices = expr.variables();
413 const std::vector<int64_t> coefficients = expr.coefficients();
414 for (int i = 0; i < indices.size(); ++i) {
415 variables_.push_back(indices[i]);
416 coefficients_.push_back(1.0 * static_cast<double>(coefficients[i]) * coeff);
417 }
418
419 return *this;
420}
421
423 constant_ -= value;
424 return *this;
425}
426
428 AddTerm(var, -1.0);
429 return *this;
430}
431
433 constant_ -= expr.constant_;
434 variables_.insert(variables_.end(), expr.variables_.begin(),
435 expr.variables_.end());
436 for (const double coeff : expr.coefficients()) {
437 coefficients_.push_back(-coeff);
438 }
439 return *this;
440}
441
443 constant_ *= coeff;
444 for (double& c : coefficients_) {
445 c *= coeff;
446 }
447 return *this;
448}
449
450std::string DoubleLinearExpr::DebugString(const CpModelProto* proto) const {
451 std::string result;
452 for (int i = 0; i < variables_.size(); ++i) {
453 const double coeff = coefficients_[i];
454 const std::string var_string = proto == nullptr
455 ? absl::StrCat("V", variables_[i])
456 : VarDebugString(*proto, variables_[i]);
457 if (i == 0) {
458 if (coeff == 1.0) {
459 absl::StrAppend(&result, var_string);
460 } else if (coeff == -1.0) {
461 absl::StrAppend(&result, "-", var_string);
462 } else if (coeff != 0.0) {
463 absl::StrAppend(&result, coeff, " * ", var_string);
464 }
465 } else if (coeff == 1.0) {
466 absl::StrAppend(&result, " + ", var_string);
467 } else if (coeff > 0.0) {
468 absl::StrAppend(&result, " + ", coeff, " * ", var_string);
469 } else if (coeff == -1.0) {
470 absl::StrAppend(&result, " - ", var_string);
471 } else if (coeff < 0.0) {
472 absl::StrAppend(&result, " - ", -coeff, " * ", var_string);
473 }
474 }
475
476 if (constant_ != 0.0) {
477 if (variables_.empty()) {
478 return absl::StrCat(constant_);
479 } else if (constant_ > 0.0) {
480 absl::StrAppend(&result, " + ", constant_);
481 } else {
482 absl::StrAppend(&result, " - ", -constant_);
483 }
484 }
485 return result;
486}
487
488std::ostream& operator<<(std::ostream& os, const DoubleLinearExpr& e) {
489 os << e.DebugString();
490 return os;
491}
492
494
495Constraint Constraint::WithName(absl::string_view name) {
496 proto_->set_name(name);
497 return *this;
498}
499
500absl::string_view Constraint::Name() const { return proto_->name(); }
501
502Constraint Constraint::OnlyEnforceIf(absl::Span<const BoolVar> literals) {
503 for (const BoolVar& var : literals) {
504 proto_->add_enforcement_literal(var.index_);
505 }
506 return *this;
507}
508
510 proto_->add_enforcement_literal(literal.index_);
511 return *this;
512}
513
514void CircuitConstraint::AddArc(int tail, int head, BoolVar literal) {
515 proto_->mutable_circuit()->add_tails(tail);
516 proto_->mutable_circuit()->add_heads(head);
517 proto_->mutable_circuit()->add_literals(literal.index_);
518}
519
520void MultipleCircuitConstraint::AddArc(int tail, int head, BoolVar literal) {
521 proto_->mutable_routes()->add_tails(tail);
522 proto_->mutable_routes()->add_heads(head);
523 proto_->mutable_routes()->add_literals(literal.index_);
524}
525
526void TableConstraint::AddTuple(absl::Span<const int64_t> tuple) {
527 CHECK_EQ(tuple.size(), proto_->table().exprs_size());
528 for (const int64_t t : tuple) {
529 proto_->mutable_table()->add_values(t);
530 }
531}
532
533ReservoirConstraint::ReservoirConstraint(ConstraintProto* proto,
534 CpModelBuilder* builder)
535 : Constraint(proto), builder_(builder) {}
536
537void ReservoirConstraint::AddEvent(LinearExpr time, int64_t level_change) {
538 *proto_->mutable_reservoir()->add_time_exprs() =
539 builder_->LinearExprToProto(time);
540 proto_->mutable_reservoir()->add_level_changes()->set_offset(level_change);
541 proto_->mutable_reservoir()->add_active_literals(
542 builder_->IndexFromConstant(1));
543}
544
546 int64_t level_change,
547 BoolVar is_active) {
548 *proto_->mutable_reservoir()->add_time_exprs() =
549 builder_->LinearExprToProto(time);
550 proto_->mutable_reservoir()->add_level_changes()->set_offset(level_change);
551 proto_->mutable_reservoir()->add_active_literals(is_active.index_);
552}
553
555 int64_t transition_label) {
556 proto_->mutable_automaton()->add_transition_tail(tail);
557 proto_->mutable_automaton()->add_transition_head(head);
558 proto_->mutable_automaton()->add_transition_label(transition_label);
559}
560
562 IntervalVar y_coordinate) {
563 proto_->mutable_no_overlap_2d()->add_x_intervals(x_coordinate.index_);
564 proto_->mutable_no_overlap_2d()->add_y_intervals(y_coordinate.index_);
565}
566
567CumulativeConstraint::CumulativeConstraint(ConstraintProto* proto,
568 CpModelBuilder* builder)
569 : Constraint(proto), builder_(builder) {}
570
572 proto_->mutable_cumulative()->add_intervals(interval.index_);
573 *proto_->mutable_cumulative()->add_demands() =
574 builder_->LinearExprToProto(demand);
575}
576
577IntervalVar::IntervalVar() : builder_(nullptr), index_() {}
578
579IntervalVar::IntervalVar(int index, CpModelBuilder* builder)
580 : builder_(builder), index_(index) {}
581
582IntervalVar IntervalVar::WithName(absl::string_view name) {
583 DCHECK(builder_ != nullptr);
584 if (builder_ == nullptr) return *this;
585 builder_->MutableProto()->mutable_constraints(index_)->set_name(name);
586 return *this;
587}
588
590 DCHECK(builder_ != nullptr);
591 if (builder_ == nullptr) return LinearExpr();
593 builder_->Proto().constraints(index_).interval().start());
594}
595
597 DCHECK(builder_ != nullptr);
598 if (builder_ == nullptr) return LinearExpr();
600 builder_->Proto().constraints(index_).interval().size());
601}
602
604 DCHECK(builder_ != nullptr);
605 if (builder_ == nullptr) return LinearExpr();
607 builder_->Proto().constraints(index_).interval().end());
608}
609
611 DCHECK(builder_ != nullptr);
612 if (builder_ == nullptr) return BoolVar();
613 if (builder_->Proto().constraints(index_).enforcement_literal_size() == 0) {
614 return builder_->TrueVar();
615 }
616 return BoolVar(builder_->Proto().constraints(index_).enforcement_literal(0),
617 builder_);
618}
619
620std::string IntervalVar::Name() const {
621 if (builder_ == nullptr) return "null";
622 return builder_->Proto().constraints(index_).name();
623}
624
625std::string IntervalVar::DebugString() const {
626 if (builder_ == nullptr) return "null";
627
628 CHECK_GE(index_, 0);
629 const CpModelProto& proto = builder_->Proto();
630 const ConstraintProto& ct_proto = proto.constraints(index_);
631 std::string output;
632 if (ct_proto.name().empty()) {
633 absl::StrAppend(&output, "IntervalVar", index_, "(");
634 } else {
635 absl::StrAppend(&output, ct_proto.name(), "(");
636 }
637 absl::StrAppend(&output, StartExpr().DebugString(&proto), ", ",
638 SizeExpr().DebugString(&proto), ", ",
639 EndExpr().DebugString(&proto), ", ",
641 return output;
642}
643
644std::ostream& operator<<(std::ostream& os, const IntervalVar& var) {
645 os << var.DebugString();
646 return os;
647}
648
649void CpModelBuilder::SetName(absl::string_view name) {
650 cp_model_.set_name(name);
651}
652
653int CpModelBuilder::IndexFromConstant(int64_t value) {
654 if (!constant_to_index_map_.contains(value)) {
655 const int index = cp_model_.variables_size();
656 IntegerVariableProto* const var_proto = cp_model_.add_variables();
657 var_proto->add_domain(value);
658 var_proto->add_domain(value);
659 constant_to_index_map_[value] = index;
660 }
661 return constant_to_index_map_[value];
662}
663
664int CpModelBuilder::GetOrCreateIntegerIndex(int index) {
665 if (index >= 0) {
666 return index;
667 }
668 if (!bool_to_integer_index_map_.contains(index)) {
669 const int var = PositiveRef(index);
670 const IntegerVariableProto& old_var = cp_model_.variables(var);
671 const int new_index = cp_model_.variables_size();
672 IntegerVariableProto* const new_var = cp_model_.add_variables();
673 new_var->add_domain(0);
674 new_var->add_domain(1);
675 if (!old_var.name().empty()) {
676 new_var->set_name(absl::StrCat("Not(", old_var.name(), ")"));
677 }
678 AddEquality(IntVar(new_index, this), BoolVar(index, this));
679 bool_to_integer_index_map_[index] = new_index;
680 return new_index;
681 }
682 return bool_to_integer_index_map_[index];
683}
684
686 const int index = cp_model_.variables_size();
687 IntegerVariableProto* const var_proto = cp_model_.add_variables();
688 for (const auto& interval : domain) {
689 var_proto->add_domain(interval.start);
690 var_proto->add_domain(interval.end);
691 }
692 return IntVar(index, this);
693}
694
696 const int index = cp_model_.variables_size();
697 IntegerVariableProto* const var_proto = cp_model_.add_variables();
698 var_proto->add_domain(0);
699 var_proto->add_domain(1);
700 return BoolVar(index, this);
701}
702
704 return IntVar(IndexFromConstant(value), this);
705}
706
708 return BoolVar(IndexFromConstant(1), this);
709}
710
712 return BoolVar(IndexFromConstant(0), this);
713}
714
716 const LinearExpr& size,
717 const LinearExpr& end) {
718 const int index = cp_model_.constraints_size();
719 ConstraintProto* const ct = cp_model_.add_constraints();
720 IntervalConstraintProto* const interval = ct->mutable_interval();
721 *interval->mutable_start() = LinearExprToProto(start);
722 *interval->mutable_size() = LinearExprToProto(size);
723 *interval->mutable_end() = LinearExprToProto(end);
724 return IntervalVar(index, this);
725}
726
728 int64_t size) {
729 const int index = cp_model_.constraints_size();
730 ConstraintProto* const ct = cp_model_.add_constraints();
731 IntervalConstraintProto* const interval = ct->mutable_interval();
732 *interval->mutable_start() = LinearExprToProto(start);
733 interval->mutable_size()->set_offset(size);
734 *interval->mutable_end() = LinearExprToProto(start);
735 interval->mutable_end()->set_offset(interval->end().offset() + size);
736 return IntervalVar(index, this);
737}
738
740 const LinearExpr& size,
741 const LinearExpr& end,
742 BoolVar presence) {
743 const int index = cp_model_.constraints_size();
744 ConstraintProto* const ct = cp_model_.add_constraints();
745 ct->add_enforcement_literal(presence.index_);
746 IntervalConstraintProto* const interval = ct->mutable_interval();
747 *interval->mutable_start() = LinearExprToProto(start);
748 *interval->mutable_size() = LinearExprToProto(size);
749 *interval->mutable_end() = LinearExprToProto(end);
750 return IntervalVar(index, this);
751}
752
754 const LinearExpr& start, int64_t size, BoolVar presence) {
755 const int index = cp_model_.constraints_size();
756 ConstraintProto* const ct = cp_model_.add_constraints();
757 ct->add_enforcement_literal(presence.index_);
758 IntervalConstraintProto* const interval = ct->mutable_interval();
759 *interval->mutable_start() = LinearExprToProto(start);
760 interval->mutable_size()->set_offset(size);
761 *interval->mutable_end() = LinearExprToProto(start);
762 interval->mutable_end()->set_offset(interval->end().offset() + size);
763 return IntervalVar(index, this);
764}
765
766void CpModelBuilder::FixVariable(IntVar var, int64_t value) {
767 FillDomainInProto(Domain(value), cp_model_.mutable_variables(var.index()));
768}
769
771 const int index = var.index();
772 if (RefIsPositive(index)) {
773 FillDomainInProto(Domain(value), cp_model_.mutable_variables(index));
774 } else {
776 cp_model_.mutable_variables(NegatedRef(index)));
777 }
778}
779
780Constraint CpModelBuilder::AddBoolOr(absl::Span<const BoolVar> literals) {
781 ConstraintProto* const proto = cp_model_.add_constraints();
782 BoolArgumentProto* const bool_or = proto->mutable_bool_or();
783 for (const BoolVar& lit : literals) bool_or->add_literals(lit.index_);
784 return Constraint(proto);
785}
786
787Constraint CpModelBuilder::AddAtLeastOne(absl::Span<const BoolVar> literals) {
788 return AddBoolOr(literals);
789}
790
791Constraint CpModelBuilder::AddAtMostOne(absl::Span<const BoolVar> literals) {
792 ConstraintProto* const proto = cp_model_.add_constraints();
793 for (const BoolVar& lit : literals) {
794 proto->mutable_at_most_one()->add_literals(lit.index_);
795 }
796 return Constraint(proto);
797}
798
799Constraint CpModelBuilder::AddExactlyOne(absl::Span<const BoolVar> literals) {
800 ConstraintProto* const proto = cp_model_.add_constraints();
801 BoolArgumentProto* const exactly_one = proto->mutable_exactly_one();
802 for (const BoolVar& lit : literals) exactly_one->add_literals(lit.index_);
803 return Constraint(proto);
804}
805
806Constraint CpModelBuilder::AddBoolAnd(absl::Span<const BoolVar> literals) {
807 ConstraintProto* const proto = cp_model_.add_constraints();
808 for (const BoolVar& lit : literals) {
809 proto->mutable_bool_and()->add_literals(lit.index_);
810 }
811 return Constraint(proto);
812}
813
814Constraint CpModelBuilder::AddBoolXor(absl::Span<const BoolVar> literals) {
815 ConstraintProto* const proto = cp_model_.add_constraints();
816 for (const BoolVar& lit : literals) {
817 proto->mutable_bool_xor()->add_literals(lit.index_);
818 }
819 return Constraint(proto);
820}
821
822void CpModelBuilder::FillLinearTerms(const LinearExpr& left,
823 const LinearExpr& right,
824 LinearConstraintProto* proto) {
825 for (const int x : left.variables()) {
826 proto->add_vars(x);
827 }
828 for (const int64_t coeff : left.coefficients()) {
829 proto->add_coeffs(coeff);
830 }
831 for (const int x : right.variables()) {
832 proto->add_vars(x);
833 }
834 for (const int64_t coeff : right.coefficients()) {
835 proto->add_coeffs(-coeff);
836 }
837}
838
840 const LinearExpr& right) {
841 ConstraintProto* const proto = cp_model_.add_constraints();
842 FillLinearTerms(left, right, proto->mutable_linear());
843 const int64_t rhs = right.constant() - left.constant();
844 proto->mutable_linear()->add_domain(rhs);
845 proto->mutable_linear()->add_domain(rhs);
846 return Constraint(proto);
847}
848
850 const LinearExpr& right) {
851 ConstraintProto* const proto = cp_model_.add_constraints();
852 FillLinearTerms(left, right, proto->mutable_linear());
853 const int64_t rhs = right.constant() - left.constant();
854 proto->mutable_linear()->add_domain(rhs);
855 proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::max());
856 return Constraint(proto);
857}
858
860 const LinearExpr& right) {
861 ConstraintProto* const proto = cp_model_.add_constraints();
862 FillLinearTerms(left, right, proto->mutable_linear());
863 const int64_t rhs = right.constant() - left.constant();
864 proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::min());
865 proto->mutable_linear()->add_domain(rhs);
866 return Constraint(proto);
867}
868
870 const LinearExpr& right) {
871 ConstraintProto* const proto = cp_model_.add_constraints();
872 FillLinearTerms(left, right, proto->mutable_linear());
873 const int64_t rhs = right.constant() - left.constant();
874 proto->mutable_linear()->add_domain(rhs + 1);
875 proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::max());
876 return Constraint(proto);
877}
878
880 const LinearExpr& right) {
881 ConstraintProto* const proto = cp_model_.add_constraints();
882 FillLinearTerms(left, right, proto->mutable_linear());
883 const int64_t rhs = right.constant() - left.constant();
884 proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::min());
885 proto->mutable_linear()->add_domain(rhs - 1);
886 return Constraint(proto);
887}
888
890 const Domain& domain) {
891 ConstraintProto* const proto = cp_model_.add_constraints();
892 for (const int x : expr.variables()) {
893 proto->mutable_linear()->add_vars(x);
894 }
895 for (const int64_t coeff : expr.coefficients()) {
896 proto->mutable_linear()->add_coeffs(coeff);
897 }
898 const int64_t cst = expr.constant();
899 for (const auto& i : domain) {
900 proto->mutable_linear()->add_domain(i.start - cst);
901 proto->mutable_linear()->add_domain(i.end - cst);
902 }
903 return Constraint(proto);
904}
905
907 const LinearExpr& right) {
908 ConstraintProto* const proto = cp_model_.add_constraints();
909 FillLinearTerms(left, right, proto->mutable_linear());
910 const int64_t rhs = right.constant() - left.constant();
911 proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::min());
912 proto->mutable_linear()->add_domain(rhs - 1);
913 proto->mutable_linear()->add_domain(rhs + 1);
914 proto->mutable_linear()->add_domain(std::numeric_limits<int64_t>::max());
915 return Constraint(proto);
916}
917
918Constraint CpModelBuilder::AddAllDifferent(absl::Span<const IntVar> vars) {
919 ConstraintProto* const proto = cp_model_.add_constraints();
920 for (const IntVar& var : vars) {
921 auto* expr = proto->mutable_all_diff()->add_exprs();
922 expr->add_vars(var.index_);
923 expr->add_coeffs(1);
924 }
925 return Constraint(proto);
926}
927
928Constraint CpModelBuilder::AddAllDifferent(absl::Span<const LinearExpr> exprs) {
929 ConstraintProto* const proto = cp_model_.add_constraints();
930 for (const LinearExpr& expr : exprs) {
931 *proto->mutable_all_diff()->add_exprs() = LinearExprToProto(expr);
932 }
933 return Constraint(proto);
934}
935
937 std::initializer_list<LinearExpr> exprs) {
938 ConstraintProto* const proto = cp_model_.add_constraints();
939 for (const LinearExpr& expr : exprs) {
940 *proto->mutable_all_diff()->add_exprs() = LinearExprToProto(expr);
941 }
942 return Constraint(proto);
943}
944
946 LinearExpr index, absl::Span<const IntVar> variables, LinearExpr target) {
947 ConstraintProto* const proto = cp_model_.add_constraints();
948 *proto->mutable_element()->mutable_linear_index() = LinearExprToProto(index);
950 LinearExprToProto(target);
951 for (const IntVar& var : variables) {
952 *proto->mutable_element()->add_exprs() = LinearExprToProto(var);
953 }
954 return Constraint(proto);
955}
956
958 absl::Span<const int64_t> values,
959 LinearExpr target) {
960 ConstraintProto* const proto = cp_model_.add_constraints();
961 *proto->mutable_element()->mutable_linear_index() = LinearExprToProto(index);
963 LinearExprToProto(target);
964 for (int64_t value : values) {
965 proto->mutable_element()->add_exprs()->set_offset(value);
966 }
967 return Constraint(proto);
968}
969
971 absl::Span<const LinearExpr> expressions,
972 LinearExpr target) {
973 ConstraintProto* const proto = cp_model_.add_constraints();
974 *proto->mutable_element()->mutable_linear_index() = LinearExprToProto(index);
976 LinearExprToProto(target);
977 for (const LinearExpr& expr : expressions) {
978 *proto->mutable_element()->add_exprs() = LinearExprToProto(expr);
979 }
980 return Constraint(proto);
981}
982
984 LinearExpr index, std::initializer_list<LinearExpr> expressions,
985 LinearExpr target) {
986 ConstraintProto* const proto = cp_model_.add_constraints();
987 *proto->mutable_element()->mutable_linear_index() = LinearExprToProto(index);
989 LinearExprToProto(target);
990 for (const LinearExpr& expr : expressions) {
991 *proto->mutable_element()->add_exprs() = LinearExprToProto(expr);
992 }
993 return Constraint(proto);
994}
995
997 return CircuitConstraint(cp_model_.add_constraints());
998}
999
1003
1005 absl::Span<const LinearExpr> expressions) {
1006 ConstraintProto* const proto = cp_model_.add_constraints();
1007 for (const LinearExpr& expr : expressions) {
1008 *proto->mutable_table()->add_exprs() = LinearExprToProto(expr);
1009 }
1010 return TableConstraint(proto);
1011}
1012
1014 absl::Span<const IntVar> variables) {
1015 ConstraintProto* const proto = cp_model_.add_constraints();
1016 for (const IntVar var : variables) {
1017 LinearExpressionProto* expr = proto->mutable_table()->add_exprs();
1018 expr->add_vars(var.index_);
1019 expr->add_coeffs(1);
1020 }
1021 return TableConstraint(proto);
1022}
1023
1025 std::initializer_list<LinearExpr> expressions) {
1026 ConstraintProto* const proto = cp_model_.add_constraints();
1027 for (const LinearExpr& expr : expressions) {
1028 *proto->mutable_table()->add_exprs() = LinearExprToProto(expr);
1029 }
1030 return TableConstraint(proto);
1031}
1032
1034 absl::Span<const LinearExpr> expressions) {
1035 TableConstraint ct = AddAllowedAssignments(expressions);
1036 ct.MutableProto()->mutable_table()->set_negated(true);
1037 return ct;
1038}
1039
1041 absl::Span<const IntVar> variables) {
1042 TableConstraint ct = AddAllowedAssignments(variables);
1043 ct.MutableProto()->mutable_table()->set_negated(true);
1044 return ct;
1045}
1046
1048 std::initializer_list<LinearExpr> expressions) {
1049 TableConstraint ct = AddAllowedAssignments(expressions);
1050 ct.MutableProto()->mutable_table()->set_negated(true);
1051 return ct;
1052}
1053
1055 absl::Span<const IntVar> variables,
1056 absl::Span<const IntVar> inverse_variables) {
1057 ConstraintProto* const proto = cp_model_.add_constraints();
1058 for (const IntVar& var : variables) {
1059 proto->mutable_inverse()->add_f_direct(var.index_);
1060 }
1061 for (const IntVar& var : inverse_variables) {
1062 proto->mutable_inverse()->add_f_inverse(var.index_);
1063 }
1064 return Constraint(proto);
1065}
1066
1068 int64_t max_level) {
1069 ConstraintProto* const proto = cp_model_.add_constraints();
1070 proto->mutable_reservoir()->set_min_level(min_level);
1071 proto->mutable_reservoir()->set_max_level(max_level);
1072 return ReservoirConstraint(proto, this);
1073}
1074
1076 absl::Span<const LinearExpr> transition_expressions, int starting_state,
1077 absl::Span<const int> final_states) {
1078 ConstraintProto* const proto = cp_model_.add_constraints();
1079 for (const LinearExpr& expr : transition_expressions) {
1080 *proto->mutable_automaton()->add_exprs() = LinearExprToProto(expr);
1081 }
1082 proto->mutable_automaton()->set_starting_state(starting_state);
1083 for (const int final_state : final_states) {
1084 proto->mutable_automaton()->add_final_states(final_state);
1085 }
1086 return AutomatonConstraint(proto);
1087}
1088
1090 absl::Span<const IntVar> transition_variables, int starting_state,
1091 absl::Span<const int> final_states) {
1092 ConstraintProto* const proto = cp_model_.add_constraints();
1093 for (const IntVar& var : transition_variables) {
1095 expr->add_vars(var.index_);
1096 expr->add_coeffs(1);
1097 }
1098 proto->mutable_automaton()->set_starting_state(starting_state);
1099 for (const int final_state : final_states) {
1100 proto->mutable_automaton()->add_final_states(final_state);
1101 }
1102 return AutomatonConstraint(proto);
1103}
1104
1106 std::initializer_list<LinearExpr> transition_expressions,
1107 int starting_state, absl::Span<const int> final_states) {
1108 ConstraintProto* const proto = cp_model_.add_constraints();
1109 for (const LinearExpr& expr : transition_expressions) {
1110 *proto->mutable_automaton()->add_exprs() = LinearExprToProto(expr);
1111 }
1112 proto->mutable_automaton()->set_starting_state(starting_state);
1113 for (const int final_state : final_states) {
1114 proto->mutable_automaton()->add_final_states(final_state);
1115 }
1116 return AutomatonConstraint(proto);
1117}
1118
1119LinearExpressionProto CpModelBuilder::LinearExprToProto(const LinearExpr& expr,
1120 bool negate) {
1121 LinearExpressionProto expr_proto;
1122 for (const int var : expr.variables()) {
1123 expr_proto.add_vars(var);
1124 }
1125 const int64_t mult = negate ? -1 : 1;
1126 for (const int64_t coeff : expr.coefficients()) {
1127 expr_proto.add_coeffs(coeff * mult);
1128 }
1129 expr_proto.set_offset(expr.constant() * mult);
1130 return expr_proto;
1131}
1132
1134 absl::Span<const IntVar> vars) {
1135 ConstraintProto* ct = cp_model_.add_constraints();
1137 LinearExprToProto(target, /*negate=*/true);
1138 for (const IntVar& var : vars) {
1139 *ct->mutable_lin_max()->add_exprs() =
1140 LinearExprToProto(var, /*negate=*/true);
1141 }
1142 return Constraint(ct);
1143}
1144
1146 absl::Span<const LinearExpr> exprs) {
1147 ConstraintProto* ct = cp_model_.add_constraints();
1149 LinearExprToProto(target, /*negate=*/true);
1150 for (const LinearExpr& expr : exprs) {
1151 *ct->mutable_lin_max()->add_exprs() =
1152 LinearExprToProto(expr, /*negate=*/true);
1153 }
1154 return Constraint(ct);
1155}
1156
1158 const LinearExpr& target, std::initializer_list<LinearExpr> exprs) {
1159 ConstraintProto* ct = cp_model_.add_constraints();
1161 LinearExprToProto(target, /*negate=*/true);
1162 for (const LinearExpr& expr : exprs) {
1163 *ct->mutable_lin_max()->add_exprs() =
1164 LinearExprToProto(expr, /*negate=*/true);
1165 }
1166 return Constraint(ct);
1167}
1168
1170 absl::Span<const IntVar> vars) {
1171 ConstraintProto* ct = cp_model_.add_constraints();
1172 *ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1173 for (const IntVar& var : vars) {
1174 *ct->mutable_lin_max()->add_exprs() = LinearExprToProto(var);
1175 }
1176 return Constraint(ct);
1177}
1178
1180 absl::Span<const LinearExpr> exprs) {
1181 ConstraintProto* ct = cp_model_.add_constraints();
1182 *ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1183 for (const LinearExpr& expr : exprs) {
1184 *ct->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1185 }
1186 return Constraint(ct);
1187}
1188
1190 const LinearExpr& target, std::initializer_list<LinearExpr> exprs) {
1191 ConstraintProto* ct = cp_model_.add_constraints();
1192 *ct->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1193 for (const LinearExpr& expr : exprs) {
1194 *ct->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1195 }
1196 return Constraint(ct);
1197}
1198
1200 const LinearExpr& numerator,
1201 const LinearExpr& denominator) {
1202 ConstraintProto* const proto = cp_model_.add_constraints();
1203 *proto->mutable_int_div()->mutable_target() = LinearExprToProto(target);
1204 *proto->mutable_int_div()->add_exprs() = LinearExprToProto(numerator);
1205 *proto->mutable_int_div()->add_exprs() = LinearExprToProto(denominator);
1206 return Constraint(proto);
1207}
1208
1210 const LinearExpr& expr) {
1211 ConstraintProto* const proto = cp_model_.add_constraints();
1212 *proto->mutable_lin_max()->mutable_target() = LinearExprToProto(target);
1213 *proto->mutable_lin_max()->add_exprs() = LinearExprToProto(expr);
1214 *proto->mutable_lin_max()->add_exprs() =
1215 LinearExprToProto(expr, /*negate=*/true);
1216 return Constraint(proto);
1217}
1218
1220 const LinearExpr& var,
1221 const LinearExpr& mod) {
1222 ConstraintProto* const proto = cp_model_.add_constraints();
1223 *proto->mutable_int_mod()->mutable_target() = LinearExprToProto(target);
1224 *proto->mutable_int_mod()->add_exprs() = LinearExprToProto(var);
1225 *proto->mutable_int_mod()->add_exprs() = LinearExprToProto(mod);
1226 return Constraint(proto);
1227}
1228
1230 const LinearExpr& target, absl::Span<const IntVar> vars) {
1231 ConstraintProto* const proto = cp_model_.add_constraints();
1232 *proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1233 for (const IntVar& var : vars) {
1234 *proto->mutable_int_prod()->add_exprs() = LinearExprToProto(var);
1235 }
1236 return Constraint(proto);
1237}
1238
1240 const LinearExpr& target, absl::Span<const LinearExpr> exprs) {
1241 ConstraintProto* const proto = cp_model_.add_constraints();
1242 *proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1243 for (const LinearExpr& expr : exprs) {
1244 *proto->mutable_int_prod()->add_exprs() = LinearExprToProto(expr);
1245 }
1246 return Constraint(proto);
1247}
1248
1250 const LinearExpr& target, std::initializer_list<LinearExpr> exprs) {
1251 ConstraintProto* const proto = cp_model_.add_constraints();
1252 *proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1253 for (const LinearExpr& expr : exprs) {
1254 *proto->mutable_int_prod()->add_exprs() = LinearExprToProto(expr);
1255 }
1256 return Constraint(proto);
1257}
1259 const LinearExpr& left,
1260 const LinearExpr& right) {
1261 ConstraintProto* const proto = cp_model_.add_constraints();
1262 *proto->mutable_int_prod()->mutable_target() = LinearExprToProto(target);
1263 *proto->mutable_int_prod()->add_exprs() = LinearExprToProto(left);
1264 *proto->mutable_int_prod()->add_exprs() = LinearExprToProto(right);
1265
1266 return Constraint(proto);
1267}
1268
1269Constraint CpModelBuilder::AddNoOverlap(absl::Span<const IntervalVar> vars) {
1270 ConstraintProto* const proto = cp_model_.add_constraints();
1271 for (const IntervalVar& var : vars) {
1272 proto->mutable_no_overlap()->add_intervals(var.index_);
1273 }
1274 return Constraint(proto);
1275}
1276
1278 return NoOverlap2DConstraint(cp_model_.add_constraints());
1279}
1280
1282 ConstraintProto* const proto = cp_model_.add_constraints();
1284 LinearExprToProto(capacity);
1285 return CumulativeConstraint(proto, this);
1286}
1287
1290 for (const int x : expr.variables()) {
1291 cp_model_.mutable_objective()->add_vars(x);
1292 }
1293 for (const int64_t coeff : expr.coefficients()) {
1294 cp_model_.mutable_objective()->add_coeffs(coeff);
1295 }
1296 cp_model_.mutable_objective()->set_offset(expr.constant());
1297}
1298
1301 for (const int x : expr.variables()) {
1302 cp_model_.mutable_objective()->add_vars(x);
1303 }
1304 for (const int64_t coeff : expr.coefficients()) {
1305 cp_model_.mutable_objective()->add_coeffs(-coeff);
1306 }
1307 cp_model_.mutable_objective()->set_offset(-expr.constant());
1308 cp_model_.mutable_objective()->set_scaling_factor(-1.0);
1309}
1310
1313 for (int i = 0; i < expr.variables().size(); ++i) {
1314 cp_model_.mutable_floating_point_objective()->add_vars(expr.variables()[i]);
1315 cp_model_.mutable_floating_point_objective()->add_coeffs(
1316 expr.coefficients()[i]);
1317 }
1318 cp_model_.mutable_floating_point_objective()->set_offset(expr.constant());
1319 cp_model_.mutable_floating_point_objective()->set_maximize(false);
1320}
1321
1324 for (int i = 0; i < expr.variables().size(); ++i) {
1325 cp_model_.mutable_floating_point_objective()->add_vars(expr.variables()[i]);
1326 cp_model_.mutable_floating_point_objective()->add_coeffs(
1327 expr.coefficients()[i]);
1328 }
1329 cp_model_.mutable_floating_point_objective()->set_offset(expr.constant());
1330 cp_model_.mutable_floating_point_objective()->set_maximize(true);
1331}
1332
1334 cp_model_.clear_objective();
1335 cp_model_.clear_floating_point_objective();
1336}
1337
1339 return cp_model_.has_objective() || cp_model_.has_floating_point_objective();
1340}
1341
1343 absl::Span<const IntVar> variables,
1346 DecisionStrategyProto* const proto = cp_model_.add_search_strategy();
1347 for (const IntVar& var : variables) {
1348 LinearExpressionProto* expr = proto->add_exprs();
1349 if (var.index_ >= 0) {
1350 expr->add_vars(var.index_);
1351 expr->add_coeffs(1);
1352 } else {
1353 expr->add_vars(PositiveRef(var.index_));
1354 expr->add_coeffs(-1);
1355 expr->set_offset(1);
1356 }
1357 }
1358 proto->set_variable_selection_strategy(var_strategy);
1359 proto->set_domain_reduction_strategy(domain_strategy);
1360}
1361
1363 absl::Span<const BoolVar> variables,
1366 DecisionStrategyProto* const proto = cp_model_.add_search_strategy();
1367 for (const BoolVar& var : variables) {
1368 LinearExpressionProto* expr = proto->add_exprs();
1369 if (var.index_ >= 0) {
1370 expr->add_vars(var.index_);
1371 expr->add_coeffs(1);
1372 } else {
1373 expr->add_vars(PositiveRef(var.index_));
1374 expr->add_coeffs(-1);
1375 expr->set_offset(1);
1376 }
1377 }
1378 proto->set_variable_selection_strategy(var_strategy);
1379 proto->set_domain_reduction_strategy(domain_strategy);
1380}
1381
1383 absl::Span<const LinearExpr> expressions,
1386 DecisionStrategyProto* const proto = cp_model_.add_search_strategy();
1387 for (const LinearExpr& expr : expressions) {
1388 *proto->add_exprs() = LinearExprToProto(expr);
1389 }
1390 proto->set_variable_selection_strategy(var_strategy);
1391 proto->set_domain_reduction_strategy(domain_strategy);
1392}
1393
1395 std::initializer_list<LinearExpr> expressions,
1398 DecisionStrategyProto* const proto = cp_model_.add_search_strategy();
1399 for (const LinearExpr& expr : expressions) {
1400 *proto->add_exprs() = LinearExprToProto(expr);
1401 }
1402 proto->set_variable_selection_strategy(var_strategy);
1403 proto->set_domain_reduction_strategy(domain_strategy);
1404}
1405
1406void CpModelBuilder::AddHint(IntVar var, int64_t value) {
1407 cp_model_.mutable_solution_hint()->add_vars(var.index_);
1408 cp_model_.mutable_solution_hint()->add_values(value);
1409}
1410
1411void CpModelBuilder::AddHint(BoolVar var, bool value) {
1412 if (var.index_ >= 0) {
1413 cp_model_.mutable_solution_hint()->add_vars(var.index_);
1414 cp_model_.mutable_solution_hint()->add_values(value);
1415 } else {
1416 cp_model_.mutable_solution_hint()->add_vars(PositiveRef(var.index_));
1417 cp_model_.mutable_solution_hint()->add_values(!value);
1418 }
1419}
1420
1422 cp_model_.mutable_solution_hint()->Clear();
1423}
1424
1426 cp_model_.mutable_assumptions()->Add(lit.index_);
1427}
1428
1429void CpModelBuilder::AddAssumptions(absl::Span<const BoolVar> literals) {
1430 for (const BoolVar& lit : literals) {
1431 cp_model_.mutable_assumptions()->Add(lit.index_);
1432 }
1433}
1434
1436 cp_model_.mutable_assumptions()->Clear();
1437}
1438
1440 CpModelBuilder clone;
1441 clone.ResetAndImport(cp_model_);
1442 return clone;
1443}
1444
1445void CpModelBuilder::ResetAndImport(const CpModelProto& model_proto) {
1446 cp_model_ = model_proto;
1447 // Rebuild constant to index map.
1448 constant_to_index_map_.clear();
1449 for (int i = 0; i < cp_model_.variables_size(); ++i) {
1450 const IntegerVariableProto& var = cp_model_.variables(i);
1451 if (var.domain_size() == 2 && var.domain(0) == var.domain(1)) {
1452 constant_to_index_map_[var.domain(0)] = i;
1453 }
1454 }
1455 // This one would be more complicated to rebuild. Let's just clear it.
1456 bool_to_integer_index_map_.clear();
1457}
1458
1460 CHECK_GE(index, 0);
1461 CHECK_LT(index, cp_model_.variables_size());
1462 const IntegerVariableProto& proto = cp_model_.variables(index);
1463 CHECK_EQ(2, proto.domain_size())
1464 << "CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1465 "is not Boolean";
1466 CHECK_GE(0, proto.domain(0))
1467 << "CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1468 "is not Boolean";
1469 CHECK_LE(1, proto.domain(1))
1470 << "CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable "
1471 "is not Boolean";
1472 return BoolVar(index, this);
1473}
1474
1476 CHECK_GE(index, 0);
1477 CHECK_LT(index, cp_model_.variables_size());
1478 return IntVar(index, this);
1479}
1480
1482 CHECK_GE(index, 0);
1483 CHECK_LT(index, cp_model_.constraints_size());
1484 const ConstraintProto& ct = cp_model_.constraints(index);
1486 << "CpModelBuilder::GetIntervalVarFromProtoIndex: the referenced "
1487 "object is not an interval variable";
1488 return IntervalVar(index, this);
1489}
1490
1491bool CpModelBuilder::ExportToFile(absl::string_view filename) const {
1492 return WriteModelProtoToFile(cp_model_, filename);
1493}
1494
1496 const LinearExpr& expr) {
1497 int64_t result = expr.constant();
1498 const std::vector<int>& variables = expr.variables();
1499 const std::vector<int64_t>& coefficients = expr.coefficients();
1500 for (int i = 0; i < variables.size(); ++i) {
1501 result += r.solution(variables[i]) * coefficients[i];
1502 }
1503 return result;
1504}
1505
1507 const int ref = x.index_;
1508 if (RefIsPositive(ref)) {
1509 return r.solution(ref) == 1;
1510 } else {
1511 return r.solution(PositiveRef(ref)) == 0;
1512 }
1513}
1514
1515} // namespace sat
1516} // namespace operations_research
virtual std::string DebugString() const
IntVar(Solver *s)
-------— IntVar -------—
LinearExpr & operator+=(const LinearExpr &rhs)
LinearExpr & operator-=(const LinearExpr &rhs)
LinearExpr & operator*=(double rhs)
virtual std::string name() const
Object naming.
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL add_exprs()
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL add_exprs()
void AddTransition(int tail, int head, int64_t transition_label)
Adds a transitions to the automaton.
Definition cp_model.cc:554
BoolVar WithName(absl::string_view name)
Definition cp_model.cc:39
std::string Name() const
Returns the name of the variable.
Definition cp_model.cc:48
BoolVar Not() const
Returns the logical negation of the current Boolean variable.
Definition cp_model.h:91
std::string DebugString() const
Definition cp_model.cc:59
void AddArc(int tail, int head, BoolVar literal)
Definition cp_model.cc:514
::operations_research::sat::BoolArgumentProto *PROTOBUF_NONNULL mutable_bool_and()
::operations_research::sat::CumulativeConstraintProto *PROTOBUF_NONNULL mutable_cumulative()
::operations_research::sat::NoOverlapConstraintProto *PROTOBUF_NONNULL mutable_no_overlap()
::operations_research::sat::AllDifferentConstraintProto *PROTOBUF_NONNULL mutable_all_diff()
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_xor()
::operations_research::sat::LinearArgumentProto *PROTOBUF_NONNULL mutable_int_div()
::operations_research::sat::LinearArgumentProto *PROTOBUF_NONNULL mutable_int_prod()
::operations_research::sat::BoolArgumentProto *PROTOBUF_NONNULL mutable_exactly_one()
::operations_research::sat::BoolArgumentProto *PROTOBUF_NONNULL mutable_bool_or()
::operations_research::sat::LinearArgumentProto *PROTOBUF_NONNULL mutable_lin_max()
::operations_research::sat::LinearConstraintProto *PROTOBUF_NONNULL mutable_linear()
::operations_research::sat::ElementConstraintProto *PROTOBUF_NONNULL mutable_element()
::operations_research::sat::TableConstraintProto *PROTOBUF_NONNULL mutable_table()
::operations_research::sat::InverseConstraintProto *PROTOBUF_NONNULL mutable_inverse()
::operations_research::sat::LinearArgumentProto *PROTOBUF_NONNULL mutable_int_mod()
::operations_research::sat::BoolArgumentProto *PROTOBUF_NONNULL mutable_at_most_one()
::operations_research::sat::AutomatonConstraintProto *PROTOBUF_NONNULL mutable_automaton()
Constraint WithName(absl::string_view name)
Sets the name of the constraint.
Definition cp_model.cc:495
Constraint OnlyEnforceIf(absl::Span< const BoolVar > literals)
Definition cp_model.cc:502
Constraint(ConstraintProto *proto)
Definition cp_model.cc:493
ConstraintProto * MutableProto() const
Returns the mutable underlying protobuf object (useful for model edition).
Definition cp_model.h:567
absl::string_view Name() const
Returns the name of the constraint (or the empty string if not set).
Definition cp_model.cc:500
bool HasObjective() const
Checks whether the model contains an objective.
Definition cp_model.cc:1338
BoolVar GetBoolVarFromProtoIndex(int index)
Returns the Boolean variable from its index in the proto.
Definition cp_model.cc:1459
IntVar NewIntVar(const Domain &domain)
Creates an integer variable with the given domain.
Definition cp_model.cc:685
Constraint AddInverseConstraint(absl::Span< const IntVar > variables, absl::Span< const IntVar > inverse_variables)
Definition cp_model.cc:1054
void Minimize(const LinearExpr &expr)
Adds a linear minimization objective.
Definition cp_model.cc:1288
NoOverlap2DConstraint AddNoOverlap2D()
Definition cp_model.cc:1277
Constraint AddBoolXor(absl::Span< const BoolVar > literals)
Adds the constraint that an odd number of literals is true.
Definition cp_model.cc:814
IntervalVar NewIntervalVar(const LinearExpr &start, const LinearExpr &size, const LinearExpr &end)
Creates an interval variable from 3 affine expressions.
Definition cp_model.cc:715
IntVar GetIntVarFromProtoIndex(int index)
Returns the integer variable from its index in the proto.
Definition cp_model.cc:1475
Constraint AddMultiplicationEquality(const LinearExpr &target, absl::Span< const LinearExpr > exprs)
Adds target == prod(exprs).
Definition cp_model.cc:1239
CpModelBuilder Clone() const
Returns a cloned version of the current model.
Definition cp_model.cc:1439
Constraint AddBoolAnd(absl::Span< const BoolVar > literals)
Adds the constraint that all literals must be true.
Definition cp_model.cc:806
Constraint AddMaxEquality(const LinearExpr &target, absl::Span< const IntVar > vars)
Adds target == max(vars).
Definition cp_model.cc:1169
void Maximize(const LinearExpr &expr)
Adds a linear maximization objective.
Definition cp_model.cc:1299
TableConstraint AddAllowedAssignments(absl::Span< const LinearExpr > expressions)
Definition cp_model.cc:1004
void FixVariable(IntVar var, int64_t value)
Definition cp_model.cc:766
ReservoirConstraint AddReservoirConstraint(int64_t min_level, int64_t max_level)
Definition cp_model.cc:1067
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:1342
Constraint AddLessOrEqual(const LinearExpr &left, const LinearExpr &right)
Adds left <= right.
Definition cp_model.cc:859
IntervalVar NewOptionalIntervalVar(const LinearExpr &start, const LinearExpr &size, const LinearExpr &end, BoolVar presence)
Definition cp_model.cc:739
void ClearAssumptions()
Remove all assumptions from the model.
Definition cp_model.cc:1435
Constraint AddLinearConstraint(const LinearExpr &expr, const Domain &domain)
Adds expr in domain.
Definition cp_model.cc:889
void AddHint(IntVar var, int64_t value)
Adds hinting to a variable.
Definition cp_model.cc:1406
Constraint AddAllDifferent(absl::Span< const IntVar > vars)
This constraint forces all variables to have different values.
Definition cp_model.cc:918
IntervalVar GetIntervalVarFromProtoIndex(int index)
Returns the interval variable from its index in the proto.
Definition cp_model.cc:1481
AutomatonConstraint AddAutomaton(absl::Span< const LinearExpr > transition_expressions, int starting_state, absl::Span< const int > final_states)
Definition cp_model.cc:1075
Constraint AddExactlyOne(absl::Span< const BoolVar > literals)
Exactly one literal is true. Sum literals == 1.
Definition cp_model.cc:799
Constraint AddMinEquality(const LinearExpr &target, absl::Span< const IntVar > vars)
Adds target == min(vars).
Definition cp_model.cc:1133
void AddAssumption(BoolVar lit)
Adds a literal to the model as assumptions.
Definition cp_model.cc:1425
bool ExportToFile(absl::string_view filename) const
Export the model to file.
Definition cp_model.cc:1491
Constraint AddGreaterOrEqual(const LinearExpr &left, const LinearExpr &right)
Adds left >= right.
Definition cp_model.cc:849
Constraint AddLessThan(const LinearExpr &left, const LinearExpr &right)
Adds left < right.
Definition cp_model.cc:879
MultipleCircuitConstraint AddMultipleCircuitConstraint()
Definition cp_model.cc:1000
Constraint AddNoOverlap(absl::Span< const IntervalVar > vars)
Definition cp_model.cc:1269
BoolVar NewBoolVar()
Creates a Boolean variable.
Definition cp_model.cc:695
Constraint AddNotEqual(const LinearExpr &left, const LinearExpr &right)
Adds left != right.
Definition cp_model.cc:906
Constraint AddAtLeastOne(absl::Span< const BoolVar > literals)
Same as AddBoolOr(). Sum literals >= 1.
Definition cp_model.cc:787
void ClearObjective()
Removes the objective from the model.
Definition cp_model.cc:1333
Constraint AddAtMostOne(absl::Span< const BoolVar > literals)
At most one literal is true. Sum literals <= 1.
Definition cp_model.cc:791
void ClearHints()
Removes all hints.
Definition cp_model.cc:1421
void AddAssumptions(absl::Span< const BoolVar > literals)
Adds multiple literals to the model as assumptions.
Definition cp_model.cc:1429
Constraint AddGreaterThan(const LinearExpr &left, const LinearExpr &right)
Adds left > right.
Definition cp_model.cc:869
Constraint AddDivisionEquality(const LinearExpr &target, const LinearExpr &numerator, const LinearExpr &denominator)
Adds target = num / denom (integer division rounded towards 0).
Definition cp_model.cc:1199
Constraint AddEquality(const LinearExpr &left, const LinearExpr &right)
Adds left == right.
Definition cp_model.cc:839
TableConstraint AddForbiddenAssignments(absl::Span< const LinearExpr > expression)
Definition cp_model.cc:1033
void SetName(absl::string_view name)
Sets the name of the model.
Definition cp_model.cc:649
Constraint AddAbsEquality(const LinearExpr &target, const LinearExpr &expr)
Adds target == abs(expr).
Definition cp_model.cc:1209
Constraint AddBoolOr(absl::Span< const BoolVar > literals)
Adds the constraint that at least one of the literals must be true.
Definition cp_model.cc:780
IntervalVar NewFixedSizeIntervalVar(const LinearExpr &start, int64_t size)
Creates an interval variable with a fixed size.
Definition cp_model.cc:727
CumulativeConstraint AddCumulative(LinearExpr capacity)
Definition cp_model.cc:1281
Constraint AddModuloEquality(const LinearExpr &target, const LinearExpr &var, const LinearExpr &mod)
Adds target = var % mod.
Definition cp_model.cc:1219
Constraint AddVariableElement(LinearExpr index, absl::Span< const IntVar > variables, LinearExpr target)
Adds the element constraint: variables[index] == target.
Definition cp_model.cc:945
IntervalVar NewOptionalFixedSizeIntervalVar(const LinearExpr &start, int64_t size, BoolVar presence)
Creates an optional interval variable with a fixed size.
Definition cp_model.cc:753
Constraint AddElement(LinearExpr index, absl::Span< const LinearExpr > expressions, LinearExpr target)
Adds the element constraint: expressions[index] == target.
Definition cp_model.cc:970
const ::operations_research::sat::IntegerVariableProto & variables(int index) const
const ::operations_research::sat::ConstraintProto & constraints(int index) const
::operations_research::sat::IntegerVariableProto *PROTOBUF_NONNULL add_variables()
int variables_size() const
repeated .operations_research.sat.IntegerVariableProto variables = 2;
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL mutable_capacity()
void AddDemand(IntervalVar interval, LinearExpr demand)
Adds a pair (interval, demand) to the constraint.
Definition cp_model.cc:571
DecisionStrategyProto_DomainReductionStrategy DomainReductionStrategy
void set_variable_selection_strategy(::operations_research::sat::DecisionStrategyProto_VariableSelectionStrategy value)
void set_domain_reduction_strategy(::operations_research::sat::DecisionStrategyProto_DomainReductionStrategy value)
DecisionStrategyProto_VariableSelectionStrategy VariableSelectionStrategy
nested types -------------------------------------------------—
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL add_exprs()
const std::vector< double > & coefficients() const
Returns the vector of coefficients.
Definition cp_model.h:411
static DoubleLinearExpr Sum(absl::Span< const IntVar > vars)
Constructs the sum of a list of variables.
Definition cp_model.cc:331
DoubleLinearExpr & operator*=(double coeff)
Multiply the linear expression by a constant.
Definition cp_model.cc:442
DoubleLinearExpr & operator+=(double value)
Adds a constant value to the linear expression.
Definition cp_model.cc:367
DoubleLinearExpr & AddTerm(IntVar var, double coeff)
Adds a term (var * coeff) to the linear expression.
Definition cp_model.cc:391
double constant() const
Returns the constant term.
Definition cp_model.h:417
static DoubleLinearExpr WeightedSum(absl::Span< const IntVar > vars, absl::Span< const double > coeffs)
Constructs the scalar product of variables and coefficients.
Definition cp_model.cc:347
DoubleLinearExpr & operator-=(double value)
Adds a constant value to the linear expression.
Definition cp_model.cc:422
const std::vector< int > & variables() const
Returns the vector of variable indices.
Definition cp_model.h:408
std::string DebugString(const CpModelProto *proto=nullptr) const
Debug string. See the documentation for LinearExpr::DebugString().
Definition cp_model.cc:450
DoubleLinearExpr & AddExpression(const LinearExpr &exprs, double coeff=1.0)
Adds a linear expression to the double linear expression.
Definition cp_model.cc:410
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL add_exprs()
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL mutable_linear_index()
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL mutable_linear_target()
std::string Name() const
Returns the name of the variable (or the empty string if not set).
Definition cp_model.cc:126
std::string DebugString() const
Definition cp_model.cc:136
int index() const
Returns the index of the variable in the model. This will be non-negative.
Definition cp_model.h:192
IntVar WithName(absl::string_view name)
Sets the name of the variable.
Definition cp_model.cc:119
::operations_research::Domain Domain() const
Definition cp_model.cc:131
int domain_size() const
repeated int64 domain = 2;
::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.
Definition cp_model.cc:582
std::string Name() const
Returns the name of the interval (or the empty string if not set).
Definition cp_model.cc:620
std::string DebugString() const
Returns a debug string.
Definition cp_model.cc:625
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL mutable_target()
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL add_exprs()
static LinearExpr Sum(absl::Span< const IntVar > vars)
NOLINTEND(google-explicit-constructor)
Definition cp_model.cc:207
std::string DebugString(const CpModelProto *proto=nullptr) const
Definition cp_model.cc:280
static LinearExpr WeightedSum(absl::Span< const IntVar > vars, absl::Span< const int64_t > coeffs)
Constructs the scalar product of variables and coefficients.
Definition cp_model.cc:223
static LinearExpr Term(IntVar var, int64_t coefficient)
Constructs var * coefficient.
Definition cp_model.cc:243
int64_t constant() const
Returns the constant term.
Definition cp_model.h:303
LinearExpr()=default
Creates an empty linear expression with value zero.
static LinearExpr FromProto(const LinearExpressionProto &proto)
Constructs a linear expr from its proto representation.
Definition cp_model.cc:198
const std::vector< int > & variables() const
Returns the vector of variable indices.
Definition cp_model.h:294
const std::vector< int64_t > & coefficients() const
Returns the vector of coefficients.
Definition cp_model.h:297
int vars_size() const
repeated int32 vars = 1;
void AddArc(int tail, int head, BoolVar literal)
Definition cp_model.cc:520
void AddRectangle(IntervalVar x_coordinate, IntervalVar y_coordinate)
Adds a rectangle (parallel to the axis) to the constraint.
Definition cp_model.cc:561
void AddOptionalEvent(LinearExpr time, int64_t level_change, BoolVar is_active)
Definition cp_model.cc:545
void AddEvent(LinearExpr time, int64_t level_change)
Definition cp_model.cc:537
::operations_research::sat::LinearExpressionProto *PROTOBUF_NONNULL add_exprs()
void AddTuple(absl::Span< const int64_t > tuple)
Adds a tuple of possible values to the constraint.
Definition cp_model.cc:526
std::string VarDebugString(const CpModelProto &proto, int index)
Definition cp_model.cc:143
bool WriteModelProtoToFile(const M &proto, absl::string_view filename)
BoolVar Not(BoolVar x)
Definition cp_model.cc:87
std::ostream & operator<<(std::ostream &os, const BoolVar &var)
Definition cp_model.cc:89
void FillDomainInProto(const Domain &domain, ProtoWithDomain *proto)
Serializes a Domain into the domain field of a proto.
Domain ReadDomainFromProto(const ProtoWithDomain &proto)
Reads a Domain from the domain field of a proto.
int64_t SolutionIntegerValue(const CpSolverResponse &r, const LinearExpr &expr)
Evaluates the value of an linear expression in a solver response.
Definition cp_model.cc:1495
int NegatedRef(int ref)
Small utility functions to deal with negative variable/literal references.
bool SolutionBooleanValue(const CpSolverResponse &r, BoolVar x)
Evaluates the value of a Boolean literal in a solver response.
Definition cp_model.cc:1506
In SWIG mode, we don't want anything besides these top-level includes.
ClosedInterval::Iterator end(ClosedInterval interval)
std::ostream & operator<<(std::ostream &out, const Assignment &assignment)
std::ostream & operator<<(std::ostream &out, const std::pair< First, Second > &p)
Definition stl_logging.h:99