OR-Tools  9.2
cp_model_objective.cc
Go to the documentation of this file.
1 // Copyright 2010-2021 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 
19 
20 namespace operations_research {
21 namespace sat {
22 
24  if (!cp_model->has_objective()) return;
25 
26  if (cp_model->objective().vars_size() == 1) {
27  // Canonicalize the objective to make it easier on us by always making the
28  // coefficient equal to 1.0.
29  const int old_ref = cp_model->objective().vars(0);
30  const int64_t old_coeff = cp_model->objective().coeffs(0);
31  const double muliplier = static_cast<double>(std::abs(old_coeff));
32  if (old_coeff < 0) {
33  cp_model->mutable_objective()->set_vars(0, NegatedRef(old_ref));
34  }
35  if (muliplier != 1.0) {
36  // TODO(user): deal with this case.
37  CHECK(cp_model->objective().domain().empty());
38 
39  double old_factor = cp_model->objective().scaling_factor();
40  if (old_factor == 0.0) old_factor = 1.0;
41  const double old_offset = cp_model->objective().offset();
42  cp_model->mutable_objective()->set_scaling_factor(old_factor * muliplier);
43  cp_model->mutable_objective()->set_offset(old_offset / muliplier);
44  }
45  cp_model->mutable_objective()->set_coeffs(0, 1.0);
46  return;
47  }
48 
49  // Compute trivial bounds on the objective, this is needed otherwise the
50  // overflow checker might not be happy with the new constraint we are about
51  // to create. Note that the model validator should make sure that there is no
52  // overflow in the computation below.
53  int64_t min_obj = 0;
54  int64_t max_obj = 0;
55  for (int i = 0; i < cp_model->objective().vars_size(); ++i) {
56  const int ref = cp_model->objective().vars(i);
57  const int var = PositiveRef(ref);
58  const int64_t coeff =
59  cp_model->objective().coeffs(i) * (RefIsPositive(ref) ? 1 : -1);
60  const int64_t value1 = cp_model->variables(var).domain(0) * coeff;
61  const int64_t value2 = cp_model->variables(var).domain(
62  cp_model->variables(var).domain_size() - 1) *
63  coeff;
64  min_obj += std::min(value1, value2);
65  max_obj += std::max(value1, value2);
66  }
67 
68  // Create the new objective var.
69  const int obj_ref = cp_model->variables_size();
70  {
71  IntegerVariableProto* obj = cp_model->add_variables();
72  Domain obj_domain(min_obj, max_obj);
73  if (!cp_model->objective().domain().empty()) {
74  obj_domain = obj_domain.IntersectionWith(
75  ReadDomainFromProto(cp_model->objective()));
76  }
77  FillDomainInProto(obj_domain, obj);
78  }
79 
80  // Add the linear constraint.
82  ct->add_domain(0);
83  ct->add_domain(0);
84  *(ct->mutable_vars()) = cp_model->objective().vars();
85  *(ct->mutable_coeffs()) = cp_model->objective().coeffs();
86  ct->add_vars(obj_ref);
87  ct->add_coeffs(-1);
88 
89  // Update the objective.
90  cp_model->mutable_objective()->clear_vars();
91  cp_model->mutable_objective()->clear_coeffs();
92  cp_model->mutable_objective()->add_vars(obj_ref);
93  cp_model->mutable_objective()->add_coeffs(1);
94  cp_model->mutable_objective()->clear_domain();
95 }
96 
97 } // namespace sat
98 } // namespace operations_research
#define CHECK(condition)
Definition: base/logging.h:495
int64_t min
Definition: alldiff_cst.cc:139
::operations_research::sat::IntegerVariableProto * add_variables()
int64_t max
Definition: alldiff_cst.cc:140
const ::operations_research::sat::IntegerVariableProto & variables(int index) const
::operations_research::sat::LinearConstraintProto * mutable_linear()
::operations_research::sat::ConstraintProto * add_constraints()
const ::operations_research::sat::CpObjectiveProto & objective() const
Domain IntersectionWith(const Domain &domain) const
Returns the intersection of D and domain.
We call domain any subset of Int64 = [kint64min, kint64max].
void FillDomainInProto(const Domain &domain, ProtoWithDomain *proto)
Collection of objects used to extend the Constraint Solver library.
::operations_research::sat::CpObjectiveProto * mutable_objective()
bool RefIsPositive(int ref)
IntVar * var
Definition: expr_array.cc:1874
void set_coeffs(int index, int64_t value)
void EncodeObjectiveAsSingleVariable(CpModelProto *cp_model)
Domain ReadDomainFromProto(const ProtoWithDomain &proto)
void set_vars(int index, int32_t value)
const Constraint * ct