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