From a7a4d84f42a475bba73213c61b97166c6450142d Mon Sep 17 00:00:00 2001 From: Laurent Perron Date: Sat, 11 Dec 2021 12:24:04 +0100 Subject: [PATCH] [CP-SAT] improve cp_model.h; improve examples with arithmetic operators --- examples/cpp/jobshop_sat.cc | 8 +- examples/cpp/network_routing_sat.cc | 2 +- examples/cpp/variable_intervals_sat.cc | 2 +- examples/cpp/weighted_tardiness_sat.cc | 37 +-- ortools/sat/cp_model.cc | 323 ++++++++++--------- ortools/sat/cp_model.h | 153 +++++---- ortools/sat/doc/scheduling.md | 20 +- ortools/sat/samples/no_overlap_sample_sat.cc | 18 +- ortools/sat/samples/ranking_sample_sat.cc | 2 +- 9 files changed, 291 insertions(+), 274 deletions(-) diff --git a/examples/cpp/jobshop_sat.cc b/examples/cpp/jobshop_sat.cc index e14986a9a6..567e0aaf4f 100644 --- a/examples/cpp/jobshop_sat.cc +++ b/examples/cpp/jobshop_sat.cc @@ -597,14 +597,12 @@ void AddCumulativeRelaxation( // Ignore trivial case with all intervals. if (intervals.size() == 1 || intervals.size() == num_tasks) continue; - const IntVar capacity = cp_model.NewConstant(component.size()); - const IntVar one = cp_model.NewConstant(1); - CumulativeConstraint cumul = cp_model.AddCumulative(capacity); + CumulativeConstraint cumul = cp_model.AddCumulative(component.size()); for (int i = 0; i < intervals.size(); ++i) { - cumul.AddDemand(intervals[i], one); + cumul.AddDemand(intervals[i], 1); } if (absl::GetFlag(FLAGS_use_interval_makespan)) { - cumul.AddDemand(makespan_interval, capacity); + cumul.AddDemand(makespan_interval, component.size()); } } } diff --git a/examples/cpp/network_routing_sat.cc b/examples/cpp/network_routing_sat.cc index 3f8ca09ed9..5180b26f95 100644 --- a/examples/cpp/network_routing_sat.cc +++ b/examples/cpp/network_routing_sat.cc @@ -616,7 +616,7 @@ class NetworkRoutingSolver { max_normalized_traffic = std::max(max_normalized_traffic, sum_of_traffic * 1000 / capacity); cp_model.AddDivisionEquality(normalized_traffic, scaled_traffic, - cp_model.NewConstant(capacity)); + capacity); normalized_traffic_vars[arc_index] = normalized_traffic; const BoolVar comfort = cp_model.NewBoolVar(); const int64_t safe_capacity = diff --git a/examples/cpp/variable_intervals_sat.cc b/examples/cpp/variable_intervals_sat.cc index c58af91376..dc442f80ff 100644 --- a/examples/cpp/variable_intervals_sat.cc +++ b/examples/cpp/variable_intervals_sat.cc @@ -24,7 +24,7 @@ void Solve() { const IntVar end_p2 = cp_model.NewIntVar(Domain(500, 1000)); const IntervalVar p2 = cp_model.NewIntervalVar(start_p2, duration_p2, end_p2); - cp_model.AddEquality(LinearExpr::Sum({duration_p1, duration_p2}), 360); + cp_model.AddEquality(duration_p1 + duration_p2, 360); cp_model.AddLessOrEqual(end_p1, start_p2); cp_model.AddNoOverlap({ins, p1, p2}); diff --git a/examples/cpp/weighted_tardiness_sat.cc b/examples/cpp/weighted_tardiness_sat.cc index 56f2c64e3b..ac383f1800 100644 --- a/examples/cpp/weighted_tardiness_sat.cc +++ b/examples/cpp/weighted_tardiness_sat.cc @@ -15,6 +15,7 @@ #include #include +#include #include #include "absl/flags/flag.h" @@ -89,26 +90,25 @@ void Solve(const std::vector& durations, std::vector task_intervals(num_tasks); std::vector task_starts(num_tasks); - std::vector task_durations(num_tasks); - std::vector task_ends(num_tasks); - std::vector tardiness_vars(num_tasks); + std::vector tardiness_expressions(num_tasks); + LinearExpr objective; for (int i = 0; i < num_tasks; ++i) { task_starts[i] = cp_model.NewIntVar(Domain(0, horizon - durations[i])); - task_durations[i] = cp_model.NewConstant(durations[i]); - task_ends[i] = cp_model.NewIntVar(Domain(durations[i], horizon)); - task_intervals[i] = cp_model.NewIntervalVar( - task_starts[i], task_durations[i], task_ends[i]); + task_intervals[i] = + cp_model.NewFixedSizeIntervalVar(task_starts[i], durations[i]); + if (due_dates[i] == 0) { - tardiness_vars[i] = task_ends[i]; + tardiness_expressions[i] = task_starts[i] + durations[i]; } else { - tardiness_vars[i] = cp_model.NewIntVar( + tardiness_expressions[i] = cp_model.NewIntVar( Domain(0, std::max(0, horizon - due_dates[i]))); // tardiness_vars >= end - due_date - cp_model.AddGreaterOrEqual(tardiness_vars[i], - task_ends[i] - due_dates[i]); + cp_model.AddGreaterOrEqual(tardiness_expressions[i], + task_starts[i] + durations[i] - due_dates[i]); } + objective += weights[i] * tardiness_expressions[i]; } // Decision heuristic. Note that we don't instantiate all the variables. As a @@ -134,7 +134,7 @@ void Solve(const std::vector& durations, // // Note however than for big problem, this will drastically augment the time // to get a first feasible solution (but then the heuristic gave one to us). - cp_model.Minimize(LinearExpr::ScalProd(tardiness_vars, weights)); + cp_model.Minimize(objective); // Optional preprocessing: add precedences that don't change the optimal // solution value. @@ -157,7 +157,7 @@ void Solve(const std::vector& durations, } ++num_added_precedences; - cp_model.AddLessOrEqual(task_ends[i], task_starts[j]); + cp_model.AddLessOrEqual(task_starts[i] + durations[i], task_starts[j]); } } } @@ -179,9 +179,9 @@ void Solve(const std::vector& durations, int64_t objective = 0; for (int i = 0; i < num_tasks; ++i) { - const int64_t end = SolutionIntegerValue(r, task_ends[i]); - objective += - weights[i] * std::max(int64_t{0}, end - due_dates[i]); + const int64_t end = + SolutionIntegerValue(r, task_starts[i]) + durations[i]; + objective += weights[i] * std::max(0, end - due_dates[i]); } LOG(INFO) << "Cost " << objective; @@ -196,13 +196,14 @@ void Solve(const std::vector& durations, int end = 0; for (const int i : sorted_tasks) { const int64_t cost = - weights[i] * SolutionIntegerValue(r, tardiness_vars[i]); + weights[i] * SolutionIntegerValue(r, tardiness_expressions[i]); absl::StrAppend(&solution, "| #", i, " "); if (cost > 0) { // Display the cost in red. absl::StrAppend(&solution, "\033[1;31m(+", cost, ") \033[0m"); } - absl::StrAppend(&solution, "|", SolutionIntegerValue(r, task_ends[i])); + absl::StrAppend(&solution, "|", + SolutionIntegerValue(r, task_starts[i]) + durations[i]); end += durations[i]; } LOG(INFO) << "solution: " << solution; diff --git a/ortools/sat/cp_model.cc b/ortools/sat/cp_model.cc index 94fc0b27a1..321afab3a6 100644 --- a/ortools/sat/cp_model.cc +++ b/ortools/sat/cp_model.cc @@ -27,22 +27,34 @@ namespace operations_research { namespace sat { -BoolVar::BoolVar() : cp_model_(nullptr), index_(0) {} +BoolVar::BoolVar() : builder_(nullptr), index_(0) {} -BoolVar::BoolVar(int index, CpModelProto* cp_model) - : cp_model_(cp_model), index_(index) {} +BoolVar::BoolVar(int index, CpModelBuilder* builder) + : builder_(builder), index_(index) {} BoolVar BoolVar::WithName(const std::string& name) { - cp_model_->mutable_variables(index_)->set_name(name); + builder_->MutableProto() + ->mutable_variables(PositiveRef(index_)) + ->set_name(name); return *this; } +std::string BoolVar::Name() const { + const std::string& name = + builder_->Proto().variables(PositiveRef(index_)).name(); + if (RefIsPositive(index_)) { + return name; + } else { + return absl::StrCat("Not(", name, ")"); + } +} + std::string BoolVar::DebugString() const { if (index_ < 0) { return absl::StrFormat("Not(%s)", Not().DebugString()); } else { std::string output; - const IntegerVariableProto& var_proto = cp_model_->variables(index_); + const IntegerVariableProto& var_proto = builder_->Proto().variables(index_); // Special case for constant variables without names. if (var_proto.name().empty() && var_proto.domain_size() == 2 && var_proto.domain(0) == var_proto.domain(1)) { @@ -71,31 +83,29 @@ std::ostream& operator<<(std::ostream& os, const BoolVar& var) { return os; } -IntVar::IntVar() : cp_model_(nullptr), index_(0) {} +IntVar::IntVar() : builder_(nullptr), index_(0) {} -IntVar::IntVar(int index, CpModelProto* cp_model) - : cp_model_(cp_model), index_(index) { - CHECK(RefIsPositive(index)); -} - -IntVar IntVar::WithName(const std::string& name) { - cp_model_->mutable_variables(index_)->set_name(name); - return *this; +IntVar::IntVar(int index, CpModelBuilder* builder) + : builder_(builder), index_(index) { + DCHECK(RefIsPositive(index_)); } IntVar::IntVar(const BoolVar& var) { - cp_model_ = var.cp_model_; - index_ = var.index_; + builder_ = var.builder_; + index_ = builder_->GetOrCreateIntegerIndex(var.index_); + DCHECK(RefIsPositive(index_)); } BoolVar IntVar::ToBoolVar() const { CHECK_EQ(2, Proto().domain_size()); CHECK_GE(Proto().domain(0), 0); CHECK_LE(Proto().domain(1), 1); - BoolVar var; - var.cp_model_ = cp_model_; - var.index_ = index(); - return var; + return BoolVar(index_, builder_); +} + +IntVar IntVar::WithName(const std::string& name) { + builder_->MutableProto()->mutable_variables(index_)->set_name(name); + return *this; } LinearExpr IntVar::AddConstant(int64_t value) const { @@ -103,19 +113,22 @@ LinearExpr IntVar::AddConstant(int64_t value) const { } std::string IntVar::DebugString() const { - if (index_ < 0) { - return absl::StrFormat("Not(%s)", - IntVar(NegatedRef(index_), cp_model_).DebugString()); - } - const IntegerVariableProto& var_proto = cp_model_->variables(index_); + return VarDebugString(builder_->Proto(), index_); +} + +// TODO(user): unfortunately, we need this indirection to get a DebugString() +// in a const way from an index. Because building an IntVar is non-const. +std::string VarDebugString(const CpModelProto& proto, int index) { + std::string output; + // Special case for constant variables without names. + const IntegerVariableProto& var_proto = proto.variables(index); if (var_proto.name().empty() && var_proto.domain_size() == 2 && var_proto.domain(0) == var_proto.domain(1)) { - return absl::StrCat(var_proto.domain(0)); + absl::StrAppend(&output, var_proto.domain(0)); } else { - std::string output; if (var_proto.name().empty()) { - absl::StrAppend(&output, "V", index_, "("); + absl::StrAppend(&output, "V", index, "("); } else { absl::StrAppend(&output, var_proto.name(), "("); } @@ -128,8 +141,17 @@ std::string IntVar::DebugString() const { absl::StrAppend(&output, var_proto.domain(0), ", ", var_proto.domain(1), ")"); } - return output; } + + return output; +} + +const IntegerVariableProto& IntVar::Proto() const { + return builder_->Proto().variables(index_); +} + +IntegerVariableProto* IntVar::MutableProto() const { + return builder_->MutableProto()->mutable_variables(index_); } std::ostream& operator<<(std::ostream& os, const IntVar& var) { @@ -143,6 +165,15 @@ LinearExpr::LinearExpr(IntVar var) { AddVar(var); } LinearExpr::LinearExpr(int64_t constant) { constant_ = constant; } +LinearExpr LinearExpr::FromProto(const LinearExpressionProto& expr_proto) { + LinearExpr result(expr_proto.offset()); + for (int i = 0; i < expr_proto.vars_size(); ++i) { + result.variables_.push_back(expr_proto.vars(i)); + result.coefficients_.push_back(expr_proto.coeffs(i)); + } + return result; +} + LinearExpr LinearExpr::Sum(absl::Span vars) { LinearExpr result; for (const IntVar& var : vars) { @@ -204,6 +235,12 @@ LinearExpr LinearExpr::Term(IntVar var, int64_t coefficient) { return result; } +LinearExpr LinearExpr::Term(BoolVar var, int64_t coefficient) { + LinearExpr result; + result.AddTerm(var, coefficient); + return result; +} + LinearExpr LinearExpr::BooleanSum(absl::Span vars) { LinearExpr result; for (const BoolVar& var : vars) { @@ -227,18 +264,24 @@ LinearExpr& LinearExpr::AddConstant(int64_t value) { return *this; } -LinearExpr& LinearExpr::AddVar(IntVar var) { - AddTerm(var, 1); +LinearExpr& LinearExpr::AddVar(IntVar var) { return AddTerm(var, 1); } + +LinearExpr& LinearExpr::AddVar(BoolVar var) { return AddTerm(var, 1); } + +LinearExpr& LinearExpr::AddTerm(IntVar var, int64_t coeff) { + variables_.push_back(var.index_); + coefficients_.push_back(coeff); return *this; } -LinearExpr& LinearExpr::AddTerm(IntVar var, int64_t coeff) { +LinearExpr& LinearExpr::AddTerm(BoolVar var, int64_t coeff) { const int index = var.index_; if (RefIsPositive(index)) { - variables_.push_back(var); + variables_.push_back(index); coefficients_.push_back(coeff); } else { - variables_.push_back(IntVar(PositiveRef(var.index_), var.cp_model_)); + // We add 1 - var instead. + variables_.push_back(PositiveRef(index)); coefficients_.push_back(-coeff); constant_ += coeff; } @@ -270,40 +313,29 @@ LinearExpr& LinearExpr::operator*=(int64_t factor) { return *this; } -IntVar LinearExpr::Var() const { - CHECK_EQ(constant_, 0); - CHECK_EQ(1, variables_.size()); - CHECK_EQ(1, coefficients_[0]); - return variables_.front(); -} - -int64_t LinearExpr::Value() const { - CHECK(variables_.empty()); - return constant_; -} - -std::string LinearExpr::DebugString() const { +std::string LinearExpr::DebugString(const CpModelProto* proto) const { std::string result; for (int i = 0; i < variables_.size(); ++i) { const int64_t coeff = coefficients_[i]; + const std::string var_string = proto == nullptr + ? absl::StrCat("V", variables_[i]) + : VarDebugString(*proto, variables_[i]); if (i == 0) { if (coeff == 1) { - absl::StrAppend(&result, variables_[i].DebugString()); + absl::StrAppend(&result, var_string); } else if (coeff == -1) { - absl::StrAppend(&result, "-", variables_[i].DebugString()); + absl::StrAppend(&result, "-", var_string); } else if (coeff != 0) { - absl::StrAppend(&result, coeff, " * ", variables_[i].DebugString()); + absl::StrAppend(&result, coeff, " * ", var_string); } } else if (coeff == 1) { - absl::StrAppend(&result, " + ", variables_[i].DebugString()); + absl::StrAppend(&result, " + ", var_string); } else if (coeff > 0) { - absl::StrAppend(&result, " + ", coeff, " * ", - variables_[i].DebugString()); + absl::StrAppend(&result, " + ", coeff, " * ", var_string); } else if (coeff == -1) { - absl::StrAppend(&result, " - ", variables_[i].DebugString()); + absl::StrAppend(&result, " - ", var_string); } else if (coeff < 0) { - absl::StrAppend(&result, " - ", -coeff, " * ", - variables_[i].DebugString()); + absl::StrAppend(&result, " - ", -coeff, " * ", var_string); } } @@ -326,7 +358,7 @@ std::ostream& operator<<(std::ostream& os, const LinearExpr& e) { DoubleLinearExpr::DoubleLinearExpr() {} -DoubleLinearExpr::DoubleLinearExpr(BoolVar var) { AddTerm(var, 1.0); } +DoubleLinearExpr::DoubleLinearExpr(BoolVar var) { AddTerm(var, 1); } DoubleLinearExpr::DoubleLinearExpr(IntVar var) { AddTerm(var, 1); } @@ -387,12 +419,6 @@ DoubleLinearExpr DoubleLinearExpr::ScalProd(std::initializer_list vars, return result; } -DoubleLinearExpr DoubleLinearExpr::Term(IntVar var, double coefficient) { - DoubleLinearExpr result; - result.AddTerm(var, coefficient); - return result; -} - DoubleLinearExpr& DoubleLinearExpr::operator+=(double value) { constant_ += value; return *this; @@ -408,6 +434,11 @@ DoubleLinearExpr& DoubleLinearExpr::operator+=(IntVar var) { return *this; } +DoubleLinearExpr& DoubleLinearExpr::operator+=(BoolVar var) { + AddTerm(var, 1); + return *this; +} + DoubleLinearExpr& DoubleLinearExpr::operator+=(const DoubleLinearExpr& expr) { constant_ += expr.constant_; variables_.insert(variables_.end(), expr.variables_.begin(), @@ -418,12 +449,18 @@ DoubleLinearExpr& DoubleLinearExpr::operator+=(const DoubleLinearExpr& expr) { } DoubleLinearExpr& DoubleLinearExpr::AddTerm(IntVar var, double coeff) { + variables_.push_back(var.index_); + coefficients_.push_back(coeff); + return *this; +} + +DoubleLinearExpr& DoubleLinearExpr::AddTerm(BoolVar var, double coeff) { const int index = var.index_; if (RefIsPositive(index)) { - variables_.push_back(var); + variables_.push_back(index); coefficients_.push_back(coeff); } else { - variables_.push_back(IntVar(PositiveRef(var.index_), var.cp_model_)); + variables_.push_back(PositiveRef(index)); coefficients_.push_back(-coeff); constant_ += coeff; } @@ -458,28 +495,29 @@ DoubleLinearExpr& DoubleLinearExpr::operator*=(double coeff) { return *this; } -std::string DoubleLinearExpr::DebugString() const { +std::string DoubleLinearExpr::DebugString(const CpModelProto* proto) const { std::string result; for (int i = 0; i < variables_.size(); ++i) { const double coeff = coefficients_[i]; + const std::string var_string = proto == nullptr + ? absl::StrCat("V", variables_[i]) + : VarDebugString(*proto, variables_[i]); if (i == 0) { if (coeff == 1.0) { - absl::StrAppend(&result, variables_[i].DebugString()); + absl::StrAppend(&result, var_string); } else if (coeff == -1.0) { - absl::StrAppend(&result, "-", variables_[i].DebugString()); + absl::StrAppend(&result, "-", var_string); } else if (coeff != 0.0) { - absl::StrAppend(&result, coeff, " * ", variables_[i].DebugString()); + absl::StrAppend(&result, coeff, " * ", var_string); } } else if (coeff == 1.0) { - absl::StrAppend(&result, " + ", variables_[i].DebugString()); + absl::StrAppend(&result, " + ", var_string); } else if (coeff > 0.0) { - absl::StrAppend(&result, " + ", coeff, " * ", - variables_[i].DebugString()); + absl::StrAppend(&result, " + ", coeff, " * ", var_string); } else if (coeff == -1.0) { - absl::StrAppend(&result, " - ", variables_[i].DebugString()); + absl::StrAppend(&result, " - ", var_string); } else if (coeff < 0.0) { - absl::StrAppend(&result, " - ", -coeff, " * ", - variables_[i].DebugString()); + absl::StrAppend(&result, " - ", -coeff, " * ", var_string); } } @@ -584,52 +622,64 @@ void CumulativeConstraint::AddDemand(IntervalVar interval, LinearExpr demand) { builder_->LinearExprToProto(demand); } -IntervalVar::IntervalVar() : cp_model_(nullptr), index_() {} +IntervalVar::IntervalVar() : builder_(nullptr), index_() {} -IntervalVar::IntervalVar(int index, CpModelProto* cp_model) - : cp_model_(cp_model), index_(index) {} +IntervalVar::IntervalVar(int index, CpModelBuilder* builder) + : builder_(builder), index_(index) {} IntervalVar IntervalVar::WithName(const std::string& name) { - cp_model_->mutable_constraints(index_)->set_name(name); + builder_->MutableProto()->mutable_constraints(index_)->set_name(name); return *this; } LinearExpr IntervalVar::StartExpr() const { - return CpModelBuilder::LinearExprFromProto(Proto().start(), cp_model_); + return LinearExpr::FromProto(Proto().start()); } LinearExpr IntervalVar::SizeExpr() const { - return CpModelBuilder::LinearExprFromProto(Proto().size(), cp_model_); + return LinearExpr::FromProto(Proto().size()); } LinearExpr IntervalVar::EndExpr() const { - return CpModelBuilder::LinearExprFromProto(Proto().end(), cp_model_); + return LinearExpr::FromProto(Proto().end()); } BoolVar IntervalVar::PresenceBoolVar() const { - return BoolVar(cp_model_->constraints(index_).enforcement_literal(0), - cp_model_); + return BoolVar(builder_->Proto().constraints(index_).enforcement_literal(0), + builder_); } const std::string& IntervalVar::Name() const { - return cp_model_->constraints(index_).name(); + return builder_->Proto().constraints(index_).name(); } std::string IntervalVar::DebugString() const { CHECK_GE(index_, 0); - const ConstraintProto& ct_proto = cp_model_->constraints(index_); + const CpModelProto& proto = builder_->Proto(); + const ConstraintProto& ct_proto = proto.constraints(index_); std::string output; if (ct_proto.name().empty()) { absl::StrAppend(&output, "IntervalVar", index_, "("); } else { absl::StrAppend(&output, ct_proto.name(), "("); } - absl::StrAppend(&output, StartExpr().DebugString(), ", ", - SizeExpr().DebugString(), ", ", EndExpr().DebugString(), ", ", + absl::StrAppend(&output, StartExpr().DebugString(&proto), ", ", + SizeExpr().DebugString(&proto), ", ", + EndExpr().DebugString(&proto), ", ", PresenceBoolVar().DebugString(), ")"); return output; } +const IntervalConstraintProto& IntervalVar::Proto() const { + return builder_->Proto().constraints(index_).interval(); +} + +IntervalConstraintProto* IntervalVar::MutableProto() const { + return builder_->MutableProto() + ->mutable_constraints(index_) + ->mutable_interval(); +} + std::ostream& operator<<(std::ostream& os, const IntervalVar& var) { os << var.DebugString(); return os; @@ -664,7 +714,7 @@ int CpModelBuilder::GetOrCreateIntegerIndex(int index) { if (!old_var.name().empty()) { new_var->set_name(absl::StrCat("Not(", old_var.name(), ")")); } - AddEquality(IntVar(new_index, &cp_model_), BoolVar(index, &cp_model_)); + AddEquality(IntVar(new_index, this), BoolVar(index, this)); bool_to_integer_index_map_[index] = new_index; return new_index; } @@ -678,7 +728,7 @@ IntVar CpModelBuilder::NewIntVar(const Domain& domain) { var_proto->add_domain(interval.start); var_proto->add_domain(interval.end); } - return IntVar(index, &cp_model_); + return IntVar(index, this); } BoolVar CpModelBuilder::NewBoolVar() { @@ -686,19 +736,19 @@ BoolVar CpModelBuilder::NewBoolVar() { IntegerVariableProto* const var_proto = cp_model_.add_variables(); var_proto->add_domain(0); var_proto->add_domain(1); - return BoolVar(index, &cp_model_); + return BoolVar(index, this); } IntVar CpModelBuilder::NewConstant(int64_t value) { - return IntVar(IndexFromConstant(value), &cp_model_); + return IntVar(IndexFromConstant(value), this); } BoolVar CpModelBuilder::TrueVar() { - return BoolVar(IndexFromConstant(1), &cp_model_); + return BoolVar(IndexFromConstant(1), this); } BoolVar CpModelBuilder::FalseVar() { - return BoolVar(IndexFromConstant(0), &cp_model_); + return BoolVar(IndexFromConstant(0), this); } IntervalVar CpModelBuilder::NewIntervalVar(const LinearExpr& start, @@ -726,7 +776,7 @@ IntervalVar CpModelBuilder::NewOptionalIntervalVar(const LinearExpr& start, *interval->mutable_start() = LinearExprToProto(start); *interval->mutable_size() = LinearExprToProto(size); *interval->mutable_end() = LinearExprToProto(end); - return IntervalVar(index, &cp_model_); + return IntervalVar(index, this); } IntervalVar CpModelBuilder::NewOptionalFixedSizeIntervalVar( @@ -739,7 +789,7 @@ IntervalVar CpModelBuilder::NewOptionalFixedSizeIntervalVar( interval->mutable_size()->set_offset(size); *interval->mutable_end() = LinearExprToProto(start); interval->mutable_end()->set_offset(interval->end().offset() + size); - return IntervalVar(index, &cp_model_); + return IntervalVar(index, this); } Constraint CpModelBuilder::AddBoolOr(absl::Span literals) { @@ -769,14 +819,14 @@ Constraint CpModelBuilder::AddBoolXor(absl::Span literals) { void CpModelBuilder::FillLinearTerms(const LinearExpr& left, const LinearExpr& right, LinearConstraintProto* proto) { - for (const IntVar& x : left.variables()) { - proto->add_vars(x.index_); + for (const int x : left.variables()) { + proto->add_vars(x); } for (const int64_t coeff : left.coefficients()) { proto->add_coeffs(coeff); } - for (const IntVar& x : right.variables()) { - proto->add_vars(x.index_); + for (const int x : right.variables()) { + proto->add_vars(x); } for (const int64_t coeff : right.coefficients()) { proto->add_coeffs(-coeff); @@ -836,8 +886,8 @@ Constraint CpModelBuilder::AddLessThan(const LinearExpr& left, Constraint CpModelBuilder::AddLinearConstraint(const LinearExpr& expr, const Domain& domain) { ConstraintProto* const proto = cp_model_.add_constraints(); - for (const IntVar& x : expr.variables()) { - proto->mutable_linear()->add_vars(x.index_); + for (const int x : expr.variables()) { + proto->mutable_linear()->add_vars(x); } for (const int64_t coeff : expr.coefficients()) { proto->mutable_linear()->add_coeffs(coeff); @@ -866,7 +916,7 @@ Constraint CpModelBuilder::AddAllDifferent(absl::Span vars) { ConstraintProto* const proto = cp_model_.add_constraints(); for (const IntVar& var : vars) { auto* expr = proto->mutable_all_diff()->add_exprs(); - expr->add_vars(GetOrCreateIntegerIndex(var.index_)); + expr->add_vars(var.index_); expr->add_coeffs(1); } return Constraint(proto); @@ -884,10 +934,10 @@ Constraint CpModelBuilder::AddAllDifferentExpr( Constraint CpModelBuilder::AddVariableElement( IntVar index, absl::Span variables, IntVar target) { ConstraintProto* const proto = cp_model_.add_constraints(); - proto->mutable_element()->set_index(GetOrCreateIntegerIndex(index.index_)); - proto->mutable_element()->set_target(GetOrCreateIntegerIndex(target.index_)); + proto->mutable_element()->set_index(index.index_); + proto->mutable_element()->set_target(target.index_); for (const IntVar& var : variables) { - proto->mutable_element()->add_vars(GetOrCreateIntegerIndex(var.index_)); + proto->mutable_element()->add_vars(var.index_); } return Constraint(proto); } @@ -896,8 +946,8 @@ Constraint CpModelBuilder::AddElement(IntVar index, absl::Span values, IntVar target) { ConstraintProto* const proto = cp_model_.add_constraints(); - proto->mutable_element()->set_index(GetOrCreateIntegerIndex(index.index_)); - proto->mutable_element()->set_target(GetOrCreateIntegerIndex(target.index_)); + proto->mutable_element()->set_index(index.index_); + proto->mutable_element()->set_target(target.index_); for (int64_t value : values) { proto->mutable_element()->add_vars(IndexFromConstant(value)); } @@ -916,7 +966,7 @@ TableConstraint CpModelBuilder::AddAllowedAssignments( absl::Span vars) { ConstraintProto* const proto = cp_model_.add_constraints(); for (const IntVar& var : vars) { - proto->mutable_table()->add_vars(GetOrCreateIntegerIndex(var.index_)); + proto->mutable_table()->add_vars(var.index_); } return TableConstraint(proto); } @@ -925,7 +975,7 @@ TableConstraint CpModelBuilder::AddForbiddenAssignments( absl::Span vars) { ConstraintProto* const proto = cp_model_.add_constraints(); for (const IntVar& var : vars) { - proto->mutable_table()->add_vars(GetOrCreateIntegerIndex(var.index_)); + proto->mutable_table()->add_vars(var.index_); } proto->mutable_table()->set_negated(true); return TableConstraint(proto); @@ -936,11 +986,10 @@ Constraint CpModelBuilder::AddInverseConstraint( absl::Span inverse_variables) { ConstraintProto* const proto = cp_model_.add_constraints(); for (const IntVar& var : variables) { - proto->mutable_inverse()->add_f_direct(GetOrCreateIntegerIndex(var.index_)); + proto->mutable_inverse()->add_f_direct(var.index_); } for (const IntVar& var : inverse_variables) { - proto->mutable_inverse()->add_f_inverse( - GetOrCreateIntegerIndex(var.index_)); + proto->mutable_inverse()->add_f_inverse(var.index_); } return Constraint(proto); } @@ -958,7 +1007,7 @@ AutomatonConstraint CpModelBuilder::AddAutomaton( absl::Span final_states) { ConstraintProto* const proto = cp_model_.add_constraints(); for (const IntVar& var : transition_variables) { - proto->mutable_automaton()->add_vars(GetOrCreateIntegerIndex(var.index_)); + proto->mutable_automaton()->add_vars(var.index_); } proto->mutable_automaton()->set_starting_state(starting_state); for (const int final_state : final_states) { @@ -970,10 +1019,10 @@ AutomatonConstraint CpModelBuilder::AddAutomaton( LinearExpressionProto CpModelBuilder::LinearExprToProto(const LinearExpr& expr, bool negate) { LinearExpressionProto expr_proto; - const int64_t mult = negate ? -1 : 1; - for (const IntVar var : expr.variables()) { - expr_proto.add_vars(GetOrCreateIntegerIndex(var.index_)); + for (const int var : expr.variables()) { + expr_proto.add_vars(var); } + const int64_t mult = negate ? -1 : 1; for (const int64_t coeff : expr.coefficients()) { expr_proto.add_coeffs(coeff * mult); } @@ -981,16 +1030,6 @@ LinearExpressionProto CpModelBuilder::LinearExprToProto(const LinearExpr& expr, return expr_proto; } -LinearExpr CpModelBuilder::LinearExprFromProto( - const LinearExpressionProto& expr_proto, CpModelProto* model_proto) { - LinearExpr result(expr_proto.offset()); - for (int i = 0; i < expr_proto.vars_size(); ++i) { - result.AddTerm(IntVar(expr_proto.vars(i), model_proto), - expr_proto.coeffs(i)); - } - return result; -} - Constraint CpModelBuilder::AddMinEquality(const LinearExpr& target, absl::Span vars) { ConstraintProto* ct = cp_model_.add_constraints(); @@ -1120,8 +1159,7 @@ Constraint CpModelBuilder::AddMultiplicationEquality( Constraint CpModelBuilder::AddNoOverlap(absl::Span vars) { ConstraintProto* const proto = cp_model_.add_constraints(); for (const IntervalVar& var : vars) { - proto->mutable_no_overlap()->add_intervals( - GetOrCreateIntegerIndex(var.index_)); + proto->mutable_no_overlap()->add_intervals(var.index_); } return Constraint(proto); } @@ -1140,8 +1178,8 @@ CumulativeConstraint CpModelBuilder::AddCumulative(LinearExpr capacity) { void CpModelBuilder::Minimize(const LinearExpr& expr) { cp_model_.clear_objective(); cp_model_.clear_floating_point_objective(); - for (const IntVar& x : expr.variables()) { - cp_model_.mutable_objective()->add_vars(x.index_); + for (const int x : expr.variables()) { + cp_model_.mutable_objective()->add_vars(x); } for (const int64_t coeff : expr.coefficients()) { cp_model_.mutable_objective()->add_coeffs(coeff); @@ -1152,8 +1190,8 @@ void CpModelBuilder::Minimize(const LinearExpr& expr) { void CpModelBuilder::Maximize(const LinearExpr& expr) { cp_model_.clear_objective(); cp_model_.clear_floating_point_objective(); - for (const IntVar& x : expr.variables()) { - cp_model_.mutable_objective()->add_vars(x.index_); + for (const int x : expr.variables()) { + cp_model_.mutable_objective()->add_vars(x); } for (const int64_t coeff : expr.coefficients()) { cp_model_.mutable_objective()->add_coeffs(-coeff); @@ -1166,8 +1204,7 @@ void CpModelBuilder::Minimize(const DoubleLinearExpr& expr) { cp_model_.clear_objective(); cp_model_.clear_floating_point_objective(); for (int i = 0; i < expr.variables().size(); ++i) { - cp_model_.mutable_floating_point_objective()->add_vars( - expr.variables()[i].index()); + cp_model_.mutable_floating_point_objective()->add_vars(expr.variables()[i]); cp_model_.mutable_floating_point_objective()->add_coeffs( expr.coefficients()[i]); } @@ -1179,8 +1216,7 @@ void CpModelBuilder::Maximize(const DoubleLinearExpr& expr) { cp_model_.clear_objective(); cp_model_.clear_floating_point_objective(); for (int i = 0; i < expr.variables().size(); ++i) { - cp_model_.mutable_floating_point_objective()->add_vars( - expr.variables()[i].index()); + cp_model_.mutable_floating_point_objective()->add_vars(expr.variables()[i]); cp_model_.mutable_floating_point_objective()->add_coeffs( expr.coefficients()[i]); } @@ -1213,8 +1249,7 @@ void CpModelBuilder::AddDecisionStrategy( } void CpModelBuilder::AddHint(IntVar var, int64_t value) { - cp_model_.mutable_solution_hint()->add_vars( - GetOrCreateIntegerIndex(var.index_)); + cp_model_.mutable_solution_hint()->add_vars(var.index_); cp_model_.mutable_solution_hint()->add_values(value); } @@ -1263,13 +1298,13 @@ BoolVar CpModelBuilder::GetBoolVarFromProtoIndex(int index) { CHECK_LE(1, proto.domain(1)) << "CpModelBuilder::GetBoolVarFromProtoIndex: The domain of the variable " "is not Boolean"; - return BoolVar(index, &cp_model_); + return BoolVar(index, this); } IntVar CpModelBuilder::GetIntVarFromProtoIndex(int index) { CHECK_GE(index, 0); CHECK_LT(index, cp_model_.variables_size()); - return IntVar(index, &cp_model_); + return IntVar(index, this); } IntervalVar CpModelBuilder::GetIntervalVarFromProtoIndex(int index) { @@ -1279,16 +1314,16 @@ IntervalVar CpModelBuilder::GetIntervalVarFromProtoIndex(int index) { CHECK_EQ(ct.constraint_case(), ConstraintProto::kInterval) << "CpModelBuilder::GetIntervalVarFromProtoIndex: the referenced " "object is not an interval variable"; - return IntervalVar(index, &cp_model_); + return IntervalVar(index, this); } int64_t SolutionIntegerValue(const CpSolverResponse& r, const LinearExpr& expr) { int64_t result = expr.constant(); - const std::vector& variables = expr.variables(); + const std::vector& variables = expr.variables(); const std::vector& coefficients = expr.coefficients(); for (int i = 0; i < variables.size(); ++i) { - result += r.solution(variables[i].index_) * coefficients[i]; + result += r.solution(variables[i]) * coefficients[i]; } return result; } diff --git a/ortools/sat/cp_model.h b/ortools/sat/cp_model.h index 4fa7800ff6..23e2133cf4 100644 --- a/ortools/sat/cp_model.h +++ b/ortools/sat/cp_model.h @@ -72,42 +72,33 @@ class BoolVar { BoolVar(); /// Sets the name of the variable. + /// Note that this will always set the "positive" version of this Boolean. BoolVar WithName(const std::string& name); /// Returns the name of the variable. - const std::string& Name() const { return Proto().name(); } + std::string Name() const; /// Returns the logical negation of the current Boolean variable. - BoolVar Not() const { return BoolVar(NegatedRef(index_), cp_model_); } + BoolVar Not() const { return BoolVar(NegatedRef(index_), builder_); } /// Equality test with another boolvar. bool operator==(const BoolVar& other) const { - return other.cp_model_ == cp_model_ && other.index_ == index_; + return other.builder_ == builder_ && other.index_ == index_; } /// Dis-Equality test. bool operator!=(const BoolVar& other) const { - return other.cp_model_ != cp_model_ || other.index_ != index_; + return other.builder_ != builder_ || other.index_ != index_; } /// Debug string. std::string DebugString() const; - /// Returns the underlying protobuf object (useful for testing). - const IntegerVariableProto& Proto() const { - return cp_model_->variables(index_); - } - - /// Returns the mutable underlying protobuf object (useful for model edition). - IntegerVariableProto* MutableProto() const { - return cp_model_->mutable_variables(index_); - } - /** * Returns the index of the variable in the model. * - * If the variable is the negation of another variable v, its index is - * -v.index() - 1. + * Warning: If the variable is the negation of another variable v, its index + * is -v.index() - 1. So this can be negative. */ int index() const { return index_; } @@ -123,9 +114,9 @@ class BoolVar { friend class ReservoirConstraint; friend bool SolutionBooleanValue(const CpSolverResponse& r, BoolVar x); - BoolVar(int index, CpModelProto* cp_model); + BoolVar(int index, CpModelBuilder* builder); - CpModelProto* cp_model_ = nullptr; + CpModelBuilder* builder_ = nullptr; int index_ = std::numeric_limits::min(); }; @@ -152,10 +143,15 @@ class IntVar { IntVar(); /// Implicit cast BoolVar -> IntVar. + /// + /// Warning: If you construct an IntVar from a negated BoolVar, this might + /// create a new variable in the model. IntVar(const BoolVar& var); // NOLINT(runtime/explicit) - /// Cast IntVar -> BoolVar. - /// Checks that the domain of the var is within {0,1}. + /// Cast IntVar -> BoolVar. + /// + /// Warning: This checks that the domain of the var is within {0,1} and + /// crash if it is not the case. Use at your own risk. BoolVar ToBoolVar() const; /// Sets the name of the variable. @@ -170,28 +166,24 @@ class IntVar { /// Equality test with another IntVar. bool operator==(const IntVar& other) const { - return other.cp_model_ == cp_model_ && other.index_ == index_; + return other.builder_ == builder_ && other.index_ == index_; } - /// Difference test with anpther IntVar. + /// Difference test with another IntVar. bool operator!=(const IntVar& other) const { - return other.cp_model_ != cp_model_ || other.index_ != index_; + return other.builder_ != builder_ || other.index_ != index_; } /// Returns a debug string. std::string DebugString() const; /// Returns the underlying protobuf object (useful for testing). - const IntegerVariableProto& Proto() const { - return cp_model_->variables(index_); - } + const IntegerVariableProto& Proto() const; /// Returns the mutable underlying protobuf object (useful for model edition). - IntegerVariableProto* MutableProto() const { - return cp_model_->mutable_variables(index_); - } + IntegerVariableProto* MutableProto() const; - /// Returns the index of the variable in the model. + /// Returns the index of the variable in the model. This will be non-negative. int index() const { return index_; } private: @@ -205,9 +197,9 @@ class IntVar { friend int64_t SolutionIntegerValue(const CpSolverResponse& r, const LinearExpr& expr); - IntVar(int index, CpModelProto* cp_model); + IntVar(int index, CpModelBuilder* builder); - CpModelProto* cp_model_ = nullptr; + CpModelBuilder* builder_ = nullptr; int index_ = std::numeric_limits::min(); }; @@ -286,6 +278,12 @@ class LinearExpr { static LinearExpr ScalProd(std::initializer_list vars, absl::Span coeffs); + /// Constructs var * coefficient. + static LinearExpr Term(IntVar var, int64_t coefficient); + + /// Constructs bool * coefficient. + static LinearExpr Term(BoolVar var, int64_t coefficient); + /// Deprecated. Use Sum() instead. static LinearExpr BooleanSum(absl::Span vars); @@ -293,8 +291,8 @@ class LinearExpr { static LinearExpr BooleanScalProd(absl::Span vars, absl::Span coeffs); - /// Constructs var * coefficient. - static LinearExpr Term(IntVar var, int64_t coefficient); + /// Constructs a linear expr from its proto representation. + static LinearExpr FromProto(const LinearExpressionProto& proto); // Operators. LinearExpr& operator+=(const LinearExpr& other); @@ -304,11 +302,13 @@ class LinearExpr { // Deprecated. Use operators instead. LinearExpr& AddConstant(int64_t value); LinearExpr& AddVar(IntVar var); + LinearExpr& AddVar(BoolVar var); + LinearExpr& AddTerm(BoolVar var, int64_t coeff); LinearExpr& AddTerm(IntVar var, int64_t coeff); LinearExpr& AddExpression(const LinearExpr& expr) { return *this += expr; } - /// Returns the vector of variables. - const std::vector& variables() const { return variables_; } + /// Returns the vector of variable indices. + const std::vector& variables() const { return variables_; } /// Returns the vector of coefficients. const std::vector& coefficients() const { return coefficients_; } @@ -316,17 +316,15 @@ class LinearExpr { /// Returns the constant term. int64_t constant() const { return constant_; } - /// Checks that the expression is 1 * var + 0, and returns var. - IntVar Var() const; - - /// Checks that the expression is constant and returns its value. - int64_t Value() const; - - /// Debug string. - std::string DebugString() const; + /** + * Debug string. If the CpModelBuilder is passed, the string will include + * variable names and domains. Otherwise, you will get a shorter string with + * only variable indices. + */ + std::string DebugString(const CpModelProto* proto = nullptr) const; private: - std::vector variables_; + std::vector variables_; std::vector coefficients_; int64_t constant_ = 0; }; @@ -376,7 +374,7 @@ class DoubleLinearExpr { /** * Constructs a linear expression from a Boolean variable. * - * It deals with logical negation correctly. + * It deals with logical negation correctly. */ explicit DoubleLinearExpr(BoolVar var); @@ -391,12 +389,14 @@ class DoubleLinearExpr { /// Adds a single integer variable to the linear expression. DoubleLinearExpr& operator+=(IntVar var); + DoubleLinearExpr& operator+=(BoolVar var); /// Adds another linear expression to the linear expression. DoubleLinearExpr& operator+=(const DoubleLinearExpr& expr); /// Adds a term (var * coeff) to the linear expression. DoubleLinearExpr& AddTerm(IntVar var, double coeff); + DoubleLinearExpr& AddTerm(BoolVar var, double coeff); /// Deprecated. Use +=. DoubleLinearExpr& AddConstant(double constant); @@ -434,11 +434,8 @@ class DoubleLinearExpr { static DoubleLinearExpr ScalProd(std::initializer_list vars, absl::Span coeffs); - /// Constructs var * coefficient. - static DoubleLinearExpr Term(IntVar var, double coefficient); - - /// Returns the vector of variables. - const std::vector& variables() const { return variables_; } + /// Returns the vector of variable indices. + const std::vector& variables() const { return variables_; } /// Returns the vector of coefficients. const std::vector& coefficients() const { return coefficients_; } @@ -446,11 +443,11 @@ class DoubleLinearExpr { /// Returns the constant term. double constant() const { return constant_; } - /// Debug string. - std::string DebugString() const; + /// Debug string. See the documentation for LinearExpr::DebugString(). + std::string DebugString(const CpModelProto* proto = nullptr) const; private: - std::vector variables_; + std::vector variables_; std::vector coefficients_; double constant_ = 0; }; @@ -509,26 +506,22 @@ class IntervalVar { /// Equality test with another interval variable. bool operator==(const IntervalVar& other) const { - return other.cp_model_ == cp_model_ && other.index_ == index_; + return other.builder_ == builder_ && other.index_ == index_; } /// Difference test with another interval variable. bool operator!=(const IntervalVar& other) const { - return other.cp_model_ != cp_model_ || other.index_ != index_; + return other.builder_ != builder_ || other.index_ != index_; } /// Returns a debug string. std::string DebugString() const; /// Returns the underlying protobuf object (useful for testing). - const IntervalConstraintProto& Proto() const { - return cp_model_->constraints(index_).interval(); - } + const IntervalConstraintProto& Proto() const; /// Returns the mutable underlying protobuf object (useful for model edition). - IntervalConstraintProto* MutableProto() const { - return cp_model_->mutable_constraints(index_)->mutable_interval(); - } + IntervalConstraintProto* MutableProto() const; /// Returns the index of the interval constraint in the model. int index() const { return index_; } @@ -539,9 +532,9 @@ class IntervalVar { friend class NoOverlap2DConstraint; friend std::ostream& operator<<(std::ostream& os, const IntervalVar& var); - IntervalVar(int index, CpModelProto* cp_model); + IntervalVar(int index, CpModelBuilder* builder); - CpModelProto* cp_model_ = nullptr; + CpModelBuilder* builder_ = nullptr; int index_ = std::numeric_limits::min(); }; @@ -768,7 +761,9 @@ class CpModelBuilder { /// Creates a Boolean variable. BoolVar NewBoolVar(); - /// Creates a constant variable. + /// Creates a constant variable. This is a shortcut for + /// NewVariable(Domain(value)).but it will return the same variable if used + /// twice with the same constant. IntVar NewConstant(int64_t value); /// Creates an always true Boolean variable. @@ -1107,17 +1102,12 @@ class CpModelBuilder { friend class CumulativeConstraint; friend class ReservoirConstraint; friend class IntervalVar; + friend class IntVar; // Fills the 'expr_proto' with the linear expression represented by 'expr'. LinearExpressionProto LinearExprToProto(const LinearExpr& expr, bool negate = false); - // Rebuilds a LinearExpr from a LinearExpressionProto. - // This method is a member of CpModelBuilder because it needs to be friend - // with IntVar. - static LinearExpr LinearExprFromProto(const LinearExpressionProto& expr_proto, - CpModelProto* model_proto_); - // Returns a (cached) integer variable index with a constant value. int IndexFromConstant(int64_t value); @@ -1142,6 +1132,11 @@ int64_t SolutionIntegerValue(const CpSolverResponse& r, const LinearExpr& expr); /// Evaluates the value of a Boolean literal in a solver response. bool SolutionBooleanValue(const CpSolverResponse& r, BoolVar x); +// Returns a more readable and compact DebugString() than +// proto.variables(index).DebugString(). This is used by IntVar::DebugString() +// but also allow to get the same string from a const proto. +std::string VarDebugString(const CpModelProto& proto, int index); + // ============================================================================ // Minimal support for "natural" API to create LinearExpr. // @@ -1169,10 +1164,10 @@ inline LinearExpr operator+(const LinearExpr& lhs, LinearExpr&& rhs) { } inline LinearExpr operator+(LinearExpr&& lhs, LinearExpr&& rhs) { if (lhs.variables().size() < rhs.variables().size()) { - rhs += lhs; + rhs += std::move(lhs); return std::move(rhs); } else { - lhs += rhs; + lhs += std::move(rhs); return std::move(lhs); } } @@ -1192,10 +1187,10 @@ inline LinearExpr operator-(const LinearExpr& lhs, LinearExpr&& rhs) { } inline LinearExpr operator-(LinearExpr&& lhs, LinearExpr&& rhs) { if (lhs.variables().size() < rhs.variables().size()) { - rhs -= lhs; + rhs -= std::move(lhs); return std::move(rhs); } else { - lhs -= rhs; + lhs -= std::move(rhs); return std::move(lhs); } } @@ -1232,10 +1227,10 @@ inline DoubleLinearExpr operator+(const DoubleLinearExpr& lhs, inline DoubleLinearExpr operator+(DoubleLinearExpr&& lhs, DoubleLinearExpr&& rhs) { if (lhs.variables().size() < rhs.variables().size()) { - rhs += lhs; + rhs += std::move(lhs); return std::move(rhs); } else { - lhs += rhs; + lhs += std::move(rhs); return std::move(lhs); } } @@ -1278,10 +1273,10 @@ inline DoubleLinearExpr operator-(const DoubleLinearExpr& lhs, inline DoubleLinearExpr operator-(DoubleLinearExpr&& lhs, DoubleLinearExpr&& rhs) { if (lhs.variables().size() < rhs.variables().size()) { - rhs -= lhs; + rhs -= std::move(lhs); return std::move(rhs); } else { - lhs -= rhs; + lhs -= std::move(rhs); return std::move(lhs); } } diff --git a/ortools/sat/doc/scheduling.md b/ortools/sat/doc/scheduling.md index ee307065aa..619737e157 100644 --- a/ortools/sat/doc/scheduling.md +++ b/ortools/sat/doc/scheduling.md @@ -482,35 +482,29 @@ void NoOverlapSampleSat() { const Domain horizon(0, kHorizon); // Task 0, duration 2. const IntVar start_0 = cp_model.NewIntVar(horizon); - const IntVar duration_0 = cp_model.NewConstant(2); + const int64_t duration_0 = 2; const IntVar end_0 = cp_model.NewIntVar(horizon); const IntervalVar task_0 = cp_model.NewIntervalVar(start_0, duration_0, end_0); // Task 1, duration 4. const IntVar start_1 = cp_model.NewIntVar(horizon); - const IntVar duration_1 = cp_model.NewConstant(4); + const int64_t duration_1 = 4; const IntVar end_1 = cp_model.NewIntVar(horizon); const IntervalVar task_1 = cp_model.NewIntervalVar(start_1, duration_1, end_1); // Task 2, duration 3. const IntVar start_2 = cp_model.NewIntVar(horizon); - const IntVar duration_2 = cp_model.NewConstant(3); + const int64_t duration_2 = 3; const IntVar end_2 = cp_model.NewIntVar(horizon); const IntervalVar task_2 = cp_model.NewIntervalVar(start_2, duration_2, end_2); // Week ends. - const IntervalVar weekend_0 = - cp_model.NewIntervalVar(cp_model.NewConstant(5), cp_model.NewConstant(2), - cp_model.NewConstant(7)); - const IntervalVar weekend_1 = - cp_model.NewIntervalVar(cp_model.NewConstant(12), cp_model.NewConstant(2), - cp_model.NewConstant(14)); - const IntervalVar weekend_2 = - cp_model.NewIntervalVar(cp_model.NewConstant(19), cp_model.NewConstant(2), - cp_model.NewConstant(21)); + const IntervalVar weekend_0 = cp_model.NewIntervalVar(5, 2, 7); + const IntervalVar weekend_1 = cp_model.NewIntervalVar(12, 2, 14); + const IntervalVar weekend_2 = cp_model.NewIntervalVar(19, 2, 21); // No Overlap constraint. cp_model.AddNoOverlap( @@ -918,7 +912,7 @@ void RankingSampleSat() { for (int t = 0; t < kNumTasks; ++t) { const IntVar start = cp_model.NewIntVar(horizon); - const IntVar duration = cp_model.NewConstant(t + 1); + const int64_t duration = t + 1; const IntVar end = cp_model.NewIntVar(horizon); const BoolVar presence = t < kNumTasks / 2 ? cp_model.TrueVar() : cp_model.NewBoolVar(); diff --git a/ortools/sat/samples/no_overlap_sample_sat.cc b/ortools/sat/samples/no_overlap_sample_sat.cc index a682598681..f45305c62e 100644 --- a/ortools/sat/samples/no_overlap_sample_sat.cc +++ b/ortools/sat/samples/no_overlap_sample_sat.cc @@ -25,35 +25,29 @@ void NoOverlapSampleSat() { const Domain horizon(0, kHorizon); // Task 0, duration 2. const IntVar start_0 = cp_model.NewIntVar(horizon); - const IntVar duration_0 = cp_model.NewConstant(2); + const int64_t duration_0 = 2; const IntVar end_0 = cp_model.NewIntVar(horizon); const IntervalVar task_0 = cp_model.NewIntervalVar(start_0, duration_0, end_0); // Task 1, duration 4. const IntVar start_1 = cp_model.NewIntVar(horizon); - const IntVar duration_1 = cp_model.NewConstant(4); + const int64_t duration_1 = 4; const IntVar end_1 = cp_model.NewIntVar(horizon); const IntervalVar task_1 = cp_model.NewIntervalVar(start_1, duration_1, end_1); // Task 2, duration 3. const IntVar start_2 = cp_model.NewIntVar(horizon); - const IntVar duration_2 = cp_model.NewConstant(3); + const int64_t duration_2 = 3; const IntVar end_2 = cp_model.NewIntVar(horizon); const IntervalVar task_2 = cp_model.NewIntervalVar(start_2, duration_2, end_2); // Week ends. - const IntervalVar weekend_0 = - cp_model.NewIntervalVar(cp_model.NewConstant(5), cp_model.NewConstant(2), - cp_model.NewConstant(7)); - const IntervalVar weekend_1 = - cp_model.NewIntervalVar(cp_model.NewConstant(12), cp_model.NewConstant(2), - cp_model.NewConstant(14)); - const IntervalVar weekend_2 = - cp_model.NewIntervalVar(cp_model.NewConstant(19), cp_model.NewConstant(2), - cp_model.NewConstant(21)); + const IntervalVar weekend_0 = cp_model.NewIntervalVar(5, 2, 7); + const IntervalVar weekend_1 = cp_model.NewIntervalVar(12, 2, 14); + const IntervalVar weekend_2 = cp_model.NewIntervalVar(19, 2, 21); // No Overlap constraint. cp_model.AddNoOverlap( diff --git a/ortools/sat/samples/ranking_sample_sat.cc b/ortools/sat/samples/ranking_sample_sat.cc index 80cd15cd5f..cc05e970f5 100644 --- a/ortools/sat/samples/ranking_sample_sat.cc +++ b/ortools/sat/samples/ranking_sample_sat.cc @@ -84,7 +84,7 @@ void RankingSampleSat() { for (int t = 0; t < kNumTasks; ++t) { const IntVar start = cp_model.NewIntVar(horizon); - const IntVar duration = cp_model.NewConstant(t + 1); + const int64_t duration = t + 1; const IntVar end = cp_model.NewIntVar(horizon); const BoolVar presence = t < kNumTasks / 2 ? cp_model.TrueVar() : cp_model.NewBoolVar();