Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
objective_storage.cc
Go to the documentation of this file.
1// Copyright 2010-2024 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 <optional>
19#include <string>
20#include <utility>
21#include <vector>
22
23#include "absl/algorithm/container.h"
24#include "absl/container/flat_hash_set.h"
25#include "absl/log/check.h"
26#include "absl/strings/string_view.h"
27#include "absl/types/span.h"
31#include "ortools/math_opt/model.pb.h"
32#include "ortools/math_opt/model_update.pb.h"
33#include "ortools/math_opt/sparse_containers.pb.h"
36
38
40 const VariableId deleted_variable, const VariableId variable_checkpoint,
41 const SparseSymmetricMatrix& quadratic_terms) {
42 if (deleted_variable >= variable_checkpoint) {
43 return;
44 }
45 linear_coefficients.erase(deleted_variable);
46 for (const VariableId v2 :
47 quadratic_terms.RelatedVariables(deleted_variable)) {
48 if (v2 < variable_checkpoint) {
50 {std::min(deleted_variable, v2), std::max(deleted_variable, v2)});
51 }
52 }
53}
54
55ObjectiveProto ObjectiveStorage::ObjectiveData::Proto() const {
56 ObjectiveProto proto;
57 proto.set_maximize(maximize);
58 proto.set_priority(priority);
59 proto.set_offset(offset);
60 *proto.mutable_linear_coefficients() = linear_terms.Proto();
61 *proto.mutable_quadratic_coefficients() = quadratic_terms.Proto();
62 proto.set_name(name);
63 return proto;
64}
65
67 const int64_t priority, const absl::string_view name) {
68 const AuxiliaryObjectiveId id = next_id_++;
69 CHECK(!auxiliary_objectives_.contains(id));
70 {
71 ObjectiveData& data = auxiliary_objectives_[id];
72 data.priority = priority;
73 data.name = std::string(name);
74 }
75 return id;
76}
77
78std::vector<AuxiliaryObjectiveId> ObjectiveStorage::AuxiliaryObjectives()
79 const {
80 std::vector<AuxiliaryObjectiveId> ids;
81 ids.reserve(num_auxiliary_objectives());
82 for (const auto& [id, unused] : auxiliary_objectives_) {
83 ids.push_back(id);
84 }
85 return ids;
86}
87
88std::vector<AuxiliaryObjectiveId> ObjectiveStorage::SortedAuxiliaryObjectives()
89 const {
90 std::vector<AuxiliaryObjectiveId> ids = AuxiliaryObjectives();
91 absl::c_sort(ids);
92 return ids;
93}
94
95std::pair<ObjectiveProto, google::protobuf::Map<int64_t, ObjectiveProto>>
97 google::protobuf::Map<int64_t, ObjectiveProto> auxiliary_objectives;
98 for (const auto& [id, objective] : auxiliary_objectives_) {
99 auxiliary_objectives[id.value()] = objective.Proto();
100 }
101 return {primary_objective_.Proto(), std::move(auxiliary_objectives)};
102}
103
104namespace {
105
106void EnsureHasValue(std::optional<ObjectiveUpdatesProto>& update) {
107 if (!update.has_value()) {
108 update.emplace();
109 }
110}
111
112} // namespace
113
114std::optional<ObjectiveUpdatesProto> ObjectiveStorage::ObjectiveData::Update(
115 const Diff::SingleObjective& diff_data,
116 const absl::flat_hash_set<VariableId>& deleted_variables,
117 absl::Span<const VariableId> new_variables) const {
118 std::optional<ObjectiveUpdatesProto> update_proto;
119
120 if (diff_data.direction) {
121 EnsureHasValue(update_proto);
122 update_proto->set_direction_update(maximize);
123 }
124 if (diff_data.priority) {
125 EnsureHasValue(update_proto);
126 update_proto->set_priority_update(priority);
127 }
128 if (diff_data.offset) {
129 EnsureHasValue(update_proto);
130 update_proto->set_offset_update(offset);
131 }
132 for (const VariableId v : SortedSetElements(diff_data.linear_coefficients)) {
133 EnsureHasValue(update_proto);
134 update_proto->mutable_linear_coefficients()->add_ids(v.value());
135 update_proto->mutable_linear_coefficients()->add_values(
136 linear_terms.get(v));
137 }
138 for (const VariableId v : new_variables) {
139 const double val = linear_terms.get(v);
140 if (val != 0.0) {
141 EnsureHasValue(update_proto);
142 update_proto->mutable_linear_coefficients()->add_ids(v.value());
143 update_proto->mutable_linear_coefficients()->add_values(val);
144 }
145 }
146 SparseDoubleMatrixProto quadratic_update = quadratic_terms.Update(
147 deleted_variables, new_variables, diff_data.quadratic_coefficients);
148 if (!quadratic_update.row_ids().empty()) {
149 // Do not set the field if there is no quadratic term changes.
150 EnsureHasValue(update_proto);
151 *update_proto->mutable_quadratic_coefficients() =
152 std::move(quadratic_update);
153 }
154 return update_proto;
155}
156
157std::pair<ObjectiveUpdatesProto, AuxiliaryObjectivesUpdatesProto>
159 const Diff& diff, const absl::flat_hash_set<VariableId>& deleted_variables,
160 absl::Span<const VariableId> new_variables) const {
161 AuxiliaryObjectivesUpdatesProto auxiliary_result;
162
163 for (const AuxiliaryObjectiveId id : diff.deleted) {
164 auxiliary_result.add_deleted_objective_ids(id.value());
165 }
166 absl::c_sort(*auxiliary_result.mutable_deleted_objective_ids());
167
168 for (const auto& [id, objective] : auxiliary_objectives_) {
169 // Note that any `Delete()`d objective will not be in the `objectives_` map.
170 // Hence, each entry is either new (if not extracted) or potentially an
171 // update on an existing objective.
172 if (!diff.objective_tracked(id)) {
173 // An un-extracted objective goes in the `new_objectives` map. It is fresh
174 // and so there is no need to update, so we continue.
175 (*auxiliary_result.mutable_new_objectives())[id.value()] =
176 auxiliary_objectives_.at(id).Proto();
177 continue;
178 }
179
180 // `Diff` provides no guarantees on which objectives will have entries in
181 // `objective_diffs`; a missing entry is equivalent to one with an empty
182 // key.
183 std::optional<ObjectiveUpdatesProto> update_proto =
184 objective.Update(gtl::FindWithDefault(diff.objective_diffs, id),
185 deleted_variables, new_variables);
186 if (update_proto.has_value()) {
187 // If the update message is empty we do not export it. This is
188 // particularly important for auxiliary objectives as we do not want to
189 // add empty map entries.
190 (*auxiliary_result.mutable_objective_updates())[id.value()] =
191 *std::move(update_proto);
192 }
193 }
194
195 return {primary_objective_
198 deleted_variables, new_variables)
199 .value_or(ObjectiveUpdatesProto{}),
200 std::move(auxiliary_result)};
201}
202
204 const VariableId variable_checkpoint, Diff& diff) const {
205 diff.objective_checkpoint = std::max(diff.objective_checkpoint, next_id_);
208 diff.objective_diffs.clear();
209 diff.deleted.clear();
210}
211
212} // namespace operations_research::math_opt
const SparseSymmetricMatrix & quadratic_terms(ObjectiveId id) const
std::pair< ObjectiveProto, google::protobuf::Map< int64_t, ObjectiveProto > > Proto() const
std::vector< AuxiliaryObjectiveId > SortedAuxiliaryObjectives() const
const absl::flat_hash_map< VariableId, double > & linear_terms(ObjectiveId id) const
void AdvanceCheckpointInDiff(VariableId variable_checkpoint, Diff &diff) const
Updates the checkpoint and clears all stored changes in diff.
std::vector< AuxiliaryObjectiveId > AuxiliaryObjectives() const
The AuxiliaryObjectivesIds in use (not deleted), order not defined.
AuxiliaryObjectiveId AddAuxiliaryObjective(int64_t priority, absl::string_view name)
std::pair< ObjectiveUpdatesProto, AuxiliaryObjectivesUpdatesProto > Update(const Diff &diff, const absl::flat_hash_set< VariableId > &deleted_variables, absl::Span< const VariableId > new_variables) const
SparseDoubleMatrixProto Update(const absl::flat_hash_set< VariableId > &deleted_variables, absl::Span< const VariableId > new_variables, const absl::flat_hash_set< std::pair< VariableId, VariableId > > &dirty) const
std::vector< VariableId > RelatedVariables(VariableId variable) const
CpModelProto proto
The output proto.
const std::string name
A name for logging purposes.
int64_t value
const MapUtilMappedT< Collection > & FindWithDefault(const Collection &collection, const KeyType &key, const MapUtilMappedT< Collection > &value)
Definition map_util.h:36
An object oriented wrapper for quadratic constraints in ModelStorage.
Definition gurobi_isv.cc:28
constexpr ObjectiveId kPrimaryObjectiveId
std::vector< T > SortedSetElements(const absl::flat_hash_set< T > &elements)
Definition sorted.h:28
absl::flat_hash_set< std::pair< VariableId, VariableId > > quadratic_coefficients
void DeleteVariable(VariableId deleted_variable, VariableId variable_checkpoint, const SparseSymmetricMatrix &quadratic_terms)
absl::flat_hash_map< ObjectiveId, SingleObjective > objective_diffs
absl::flat_hash_set< AuxiliaryObjectiveId > deleted