Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
model_storage.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 <memory>
18#include <new>
19#include <optional>
20#include <string>
21#include <utility>
22#include <vector>
23
24#include "absl/base/nullability.h"
25#include "absl/log/check.h"
26#include "absl/memory/memory.h"
27#include "absl/status/status.h"
28#include "absl/status/statusor.h"
29#include "absl/strings/string_view.h"
30#include "absl/types/span.h"
45
46namespace operations_research {
47namespace math_opt {
48
49absl::StatusOr<absl::Nonnull<std::unique_ptr<ModelStorage>>>
50ModelStorage::FromModelProto(const ModelProto& model_proto) {
51 // We don't check names since ModelStorage does not do so before exporting
52 // models. Thus a model built by ModelStorage can contain duplicated
53 // names. And since we use FromModelProto() to implement Clone(), we must make
54 // sure duplicated names don't fail.
55 RETURN_IF_ERROR(ValidateModel(model_proto, /*check_names=*/false).status());
56
57 auto storage = std::make_unique<ModelStorage>(model_proto.name(),
58 model_proto.objective().name());
59
60 // Add variables.
61 storage->AddVariables(model_proto.variables());
62
63 // Set the objective.
64 storage->set_is_maximize(kPrimaryObjectiveId,
65 model_proto.objective().maximize());
66 storage->set_objective_offset(kPrimaryObjectiveId,
67 model_proto.objective().offset());
68 storage->UpdateLinearObjectiveCoefficients(
69 kPrimaryObjectiveId, model_proto.objective().linear_coefficients());
70 storage->UpdateQuadraticObjectiveCoefficients(
71 kPrimaryObjectiveId, model_proto.objective().quadratic_coefficients());
72
73 // Set the auxiliary objectives.
74 storage->AddAuxiliaryObjectives(model_proto.auxiliary_objectives());
75
76 // Add linear constraints.
77 storage->AddLinearConstraints(model_proto.linear_constraints());
78
79 // Set the linear constraints coefficients.
80 storage->UpdateLinearConstraintCoefficients(
81 model_proto.linear_constraint_matrix());
82
83 // Add quadratic constraints.
84 storage->copyable_data_.quadratic_constraints.AddConstraints(
85 model_proto.quadratic_constraints());
86
87 // Add SOC constraints.
88 storage->copyable_data_.soc_constraints.AddConstraints(
89 model_proto.second_order_cone_constraints());
90
91 // Add SOS constraints.
92 storage->copyable_data_.sos1_constraints.AddConstraints(
93 model_proto.sos1_constraints());
94 storage->copyable_data_.sos2_constraints.AddConstraints(
95 model_proto.sos2_constraints());
96
97 // Add indicator constraints.
98 storage->copyable_data_.indicator_constraints.AddConstraints(
99 model_proto.indicator_constraints());
100
101 return storage;
102}
103
104void ModelStorage::UpdateObjective(const ObjectiveId id,
105 const ObjectiveUpdatesProto& update) {
106 if (update.has_direction_update()) {
107 set_is_maximize(id, update.direction_update());
108 }
109 if (update.has_priority_update()) {
110 set_objective_priority(id, update.priority_update());
111 }
112 if (update.has_offset_update()) {
113 set_objective_offset(id, update.offset_update());
114 }
115 UpdateLinearObjectiveCoefficients(id, update.linear_coefficients());
116 UpdateQuadraticObjectiveCoefficients(id, update.quadratic_coefficients());
117}
118
119void ModelStorage::UpdateLinearObjectiveCoefficients(
120 const ObjectiveId id, const SparseDoubleVectorProto& coefficients) {
121 for (const auto [var_id, value] : MakeView(coefficients)) {
122 set_linear_objective_coefficient(id, VariableId(var_id), value);
123 }
124}
125
126void ModelStorage::UpdateQuadraticObjectiveCoefficients(
127 const ObjectiveId id, const SparseDoubleMatrixProto& coefficients) {
128 for (int i = 0; i < coefficients.row_ids_size(); ++i) {
129 // This call is valid since this is an upper triangular matrix; there is no
130 // duplicated terms.
131 set_quadratic_objective_coefficient(id, VariableId(coefficients.row_ids(i)),
132 VariableId(coefficients.column_ids(i)),
133 coefficients.coefficients(i));
134 }
135}
136
137void ModelStorage::UpdateLinearConstraintCoefficients(
138 const SparseDoubleMatrixProto& coefficients) {
139 for (int i = 0; i < coefficients.row_ids_size(); ++i) {
140 // This call is valid since there are no duplicated pairs.
141 set_linear_constraint_coefficient(
142 LinearConstraintId(coefficients.row_ids(i)),
143 VariableId(coefficients.column_ids(i)), coefficients.coefficients(i));
144 }
145}
146
147absl::Nonnull<std::unique_ptr<ModelStorage>> ModelStorage::Clone(
148 const std::optional<absl::string_view> new_name) const {
149 // We leverage the private copy constructor that copies copyable_data_ but not
150 // update_trackers_ here.
151 std::unique_ptr<ModelStorage> clone =
152 absl::WrapUnique(new ModelStorage(*this));
153 if (new_name.has_value()) {
154 clone->copyable_data_.name = *new_name;
155 }
156 return clone;
157}
158
159VariableId ModelStorage::AddVariable(const double lower_bound,
160 const double upper_bound,
161 const bool is_integer,
162 const absl::string_view name) {
163 return copyable_data_.variables.Add(lower_bound, upper_bound, is_integer,
164 name);
165}
166
167void ModelStorage::AddVariables(const VariablesProto& variables) {
168 const bool has_names = !variables.names().empty();
169 for (int v = 0; v < variables.ids_size(); ++v) {
170 // Make sure the ids of the new Variables in the model match the proto,
171 // which are potentially non-consecutive (note that variables has been
172 // validated).
173 ensure_next_variable_id_at_least(VariableId(variables.ids(v)));
174 AddVariable(variables.lower_bounds(v),
175 /*upper_bound=*/variables.upper_bounds(v),
176 /*is_integer=*/variables.integers(v),
177 has_names ? variables.names(v) : absl::string_view());
178 }
179}
180
181void ModelStorage::DeleteVariable(const VariableId id) {
182 CHECK(copyable_data_.variables.contains(id));
183 const auto& trackers = update_trackers_.GetUpdatedTrackers();
184 // Reuse output of GetUpdatedTrackers() only once to ensure a consistent view,
185 // do not call UpdateAndGetLinearConstraintDiffs() etc.
186 copyable_data_.objectives.DeleteVariable(
187 id,
189 copyable_data_.linear_constraints.DeleteVariable(
190 id,
192 trackers));
193 copyable_data_.quadratic_constraints.DeleteVariable(id);
194 copyable_data_.soc_constraints.DeleteVariable(id);
195 copyable_data_.sos1_constraints.DeleteVariable(id);
196 copyable_data_.sos2_constraints.DeleteVariable(id);
197 copyable_data_.indicator_constraints.DeleteVariable(id);
198 copyable_data_.variables.Delete(
199 id,
201}
202
203std::vector<VariableId> ModelStorage::variables() const {
204 return copyable_data_.variables.Variables();
205}
206
207std::vector<VariableId> ModelStorage::SortedVariables() const {
208 return copyable_data_.variables.SortedVariables();
209}
210
211LinearConstraintId ModelStorage::AddLinearConstraint(
212 const double lower_bound, const double upper_bound,
213 const absl::string_view name) {
214 return copyable_data_.linear_constraints.Add(lower_bound, upper_bound, name);
215}
216
217void ModelStorage::AddLinearConstraints(
218 const LinearConstraintsProto& linear_constraints) {
219 const bool has_names = !linear_constraints.names().empty();
220 for (int c = 0; c < linear_constraints.ids_size(); ++c) {
221 // Make sure the ids of the new linear constraints in the model match the
222 // proto, which are potentially non-consecutive (note that
223 // linear_constraints has been validated).
224 ensure_next_linear_constraint_id_at_least(
225 LinearConstraintId(linear_constraints.ids(c)));
226 // This call is valid since ids are unique and increasing.
227 AddLinearConstraint(
228 /*lower_bound=*/linear_constraints.lower_bounds(c),
229 /*upper_bound=*/linear_constraints.upper_bounds(c),
230 has_names ? linear_constraints.names(c) : absl::string_view());
231 }
232}
233
234void ModelStorage::DeleteLinearConstraint(const LinearConstraintId id) {
235 CHECK(copyable_data_.linear_constraints.contains(id));
236 copyable_data_.linear_constraints.Delete(id,
237 UpdateAndGetLinearConstraintDiffs());
238}
239
240std::vector<LinearConstraintId> ModelStorage::LinearConstraints() const {
241 return copyable_data_.linear_constraints.LinearConstraints();
242}
243
244std::vector<LinearConstraintId> ModelStorage::SortedLinearConstraints() const {
245 return copyable_data_.linear_constraints.SortedLinearConstraints();
246}
247
248void ModelStorage::AddAuxiliaryObjectives(
249 const google::protobuf::Map<int64_t, ObjectiveProto>& objectives) {
250 for (const int64_t raw_id : SortedMapKeys(objectives)) {
252 ensure_next_auxiliary_objective_id_at_least(id);
253 const ObjectiveProto& proto = objectives.at(raw_id);
254 AddAuxiliaryObjective(proto.priority(), proto.name());
255 set_is_maximize(id, proto.maximize());
256 set_objective_offset(id, proto.offset());
257 for (const auto [raw_var_id, coeff] :
258 MakeView(proto.linear_coefficients())) {
259 set_linear_objective_coefficient(id, VariableId(raw_var_id), coeff);
260 }
261 }
262}
263
264// TODO: b/315974557 - Return an error if any of the Proto() methods called
265// tries to create a very long RepeatedField.
266ModelProto ModelStorage::ExportModel(const bool remove_names) const {
267 ModelProto result;
268 result.set_name(copyable_data_.name);
269 *result.mutable_variables() = copyable_data_.variables.Proto();
270 {
271 auto [primary, auxiliary] = copyable_data_.objectives.Proto();
272 *result.mutable_objective() = std::move(primary);
273 *result.mutable_auxiliary_objectives() = std::move(auxiliary);
274 }
275 {
276 auto [constraints, matrix] = copyable_data_.linear_constraints.Proto();
277 *result.mutable_linear_constraints() = std::move(constraints);
278 *result.mutable_linear_constraint_matrix() = std::move(matrix);
279 }
280 *result.mutable_quadratic_constraints() =
281 copyable_data_.quadratic_constraints.Proto();
282 *result.mutable_second_order_cone_constraints() =
283 copyable_data_.soc_constraints.Proto();
284 *result.mutable_sos1_constraints() = copyable_data_.sos1_constraints.Proto();
285 *result.mutable_sos2_constraints() = copyable_data_.sos2_constraints.Proto();
286 *result.mutable_indicator_constraints() =
287 copyable_data_.indicator_constraints.Proto();
288 // Performance can be improved when remove_names is true by just not
289 // extracting the names above instead of clearing them below, but this will
290 // be more code, see discussion on cl/549469633 and prototype in cl/549369764.
291 if (remove_names) {
292 RemoveNames(result);
293 }
294 return result;
295}
296
297std::optional<ModelUpdateProto>
298ModelStorage::UpdateTrackerData::ExportModelUpdate(
299 const ModelStorage& storage, const bool remove_names) const {
300 // We must detect the empty case to prevent unneeded copies and merging in
301 // ExportModelUpdate().
302
303 if (storage.copyable_data_.variables.diff_is_empty(dirty_variables) &&
304 storage.copyable_data_.objectives.diff_is_empty(dirty_objective) &&
305 storage.copyable_data_.linear_constraints.diff_is_empty(
306 dirty_linear_constraints) &&
307 storage.copyable_data_.quadratic_constraints.diff_is_empty(
308 dirty_quadratic_constraints) &&
309 storage.copyable_data_.soc_constraints.diff_is_empty(
310 dirty_soc_constraints) &&
311 storage.copyable_data_.sos1_constraints.diff_is_empty(
312 dirty_sos1_constraints) &&
313 storage.copyable_data_.sos2_constraints.diff_is_empty(
314 dirty_sos2_constraints) &&
315 storage.copyable_data_.indicator_constraints.diff_is_empty(
316 dirty_indicator_constraints)) {
317 return std::nullopt;
318 }
319
320 ModelUpdateProto result;
321
322 // Variable/constraint deletions.
323 {
324 VariableStorage::UpdateResult variable_update =
325 storage.copyable_data_.variables.Update(dirty_variables);
326 *result.mutable_deleted_variable_ids() = std::move(variable_update.deleted);
327 *result.mutable_variable_updates() = std::move(variable_update.updates);
328 *result.mutable_new_variables() = std::move(variable_update.creates);
329 }
330 const std::vector<VariableId> new_variables =
331 storage.copyable_data_.variables.VariablesFrom(
332 dirty_variables.checkpoint);
333
334 // Linear constraint updates
335 {
337 storage.copyable_data_.linear_constraints.Update(
338 dirty_linear_constraints, dirty_variables.deleted, new_variables);
339 *result.mutable_deleted_linear_constraint_ids() =
340 std::move(lin_con_update.deleted);
341 *result.mutable_linear_constraint_updates() =
342 std::move(lin_con_update.updates);
343 *result.mutable_new_linear_constraints() =
344 std::move(lin_con_update.creates);
345 *result.mutable_linear_constraint_matrix_updates() =
346 std::move(lin_con_update.matrix_updates);
347 }
348
349 // Quadratic constraint updates
351 storage.copyable_data_.quadratic_constraints.Update(
352 dirty_quadratic_constraints);
353
354 // Second-order cone constraint updates
355 *result.mutable_second_order_cone_constraint_updates() =
356 storage.copyable_data_.soc_constraints.Update(dirty_soc_constraints);
357
358 // SOS constraint updates
359 *result.mutable_sos1_constraint_updates() =
360 storage.copyable_data_.sos1_constraints.Update(dirty_sos1_constraints);
361 *result.mutable_sos2_constraint_updates() =
362 storage.copyable_data_.sos2_constraints.Update(dirty_sos2_constraints);
363
364 // Indicator constraint updates
365 *result.mutable_indicator_constraint_updates() =
366 storage.copyable_data_.indicator_constraints.Update(
367 dirty_indicator_constraints);
368
369 // Update the objective
370 {
371 auto [primary, auxiliary] = storage.copyable_data_.objectives.Update(
372 dirty_objective, dirty_variables.deleted, new_variables);
373 *result.mutable_objective_updates() = std::move(primary);
374 *result.mutable_auxiliary_objectives_updates() = std::move(auxiliary);
375 }
376 if (remove_names) {
377 RemoveNames(result);
378 }
379 // Note: Named returned value optimization (NRVO) does not apply here.
380 return {std::move(result)};
381}
382
383void ModelStorage::UpdateTrackerData::AdvanceCheckpoint(
384 const ModelStorage& storage) {
385 storage.copyable_data_.variables.AdvanceCheckpointInDiff(dirty_variables);
386 storage.copyable_data_.objectives.AdvanceCheckpointInDiff(
387 dirty_variables.checkpoint, dirty_objective);
388 storage.copyable_data_.linear_constraints.AdvanceCheckpointInDiff(
389 dirty_variables.checkpoint, dirty_linear_constraints);
390 storage.copyable_data_.quadratic_constraints.AdvanceCheckpointInDiff(
391 dirty_quadratic_constraints);
392 storage.copyable_data_.soc_constraints.AdvanceCheckpointInDiff(
393 dirty_soc_constraints);
394 storage.copyable_data_.sos1_constraints.AdvanceCheckpointInDiff(
395 dirty_sos1_constraints);
396 storage.copyable_data_.sos2_constraints.AdvanceCheckpointInDiff(
397 dirty_sos2_constraints);
398 storage.copyable_data_.indicator_constraints.AdvanceCheckpointInDiff(
399 dirty_indicator_constraints);
400}
401
402UpdateTrackerId ModelStorage::NewUpdateTracker() {
403 return update_trackers_.NewUpdateTracker(
404 copyable_data_.variables, copyable_data_.objectives,
405 copyable_data_.linear_constraints, copyable_data_.quadratic_constraints,
406 copyable_data_.soc_constraints, copyable_data_.sos1_constraints,
407 copyable_data_.sos2_constraints, copyable_data_.indicator_constraints);
408}
409
410void ModelStorage::DeleteUpdateTracker(const UpdateTrackerId update_tracker) {
411 update_trackers_.DeleteUpdateTracker(update_tracker);
412}
413
414std::optional<ModelUpdateProto> ModelStorage::ExportModelUpdate(
415 const UpdateTrackerId update_tracker, const bool remove_names) const {
416 return update_trackers_.GetData(update_tracker)
417 .ExportModelUpdate(*this, remove_names);
418}
419
420void ModelStorage::AdvanceCheckpoint(UpdateTrackerId update_tracker) {
421 update_trackers_.GetData(update_tracker).AdvanceCheckpoint(*this);
422}
423
424absl::Status ModelStorage::ApplyUpdateProto(
425 const ModelUpdateProto& update_proto) {
426 // Check the update first.
427 {
428 // Do not check for duplicate names, as with FromModelProto();
429 ModelSummary summary(/*check_names=*/false);
430 // IdNameBiMap requires Insert() calls to be in sorted id order.
431 for (const VariableId id : SortedVariables()) {
432 RETURN_IF_ERROR(summary.variables.Insert(id.value(), variable_name(id)))
433 << "invalid variable id in model";
434 }
435 RETURN_IF_ERROR(summary.variables.SetNextFreeId(
436 copyable_data_.variables.next_id().value()));
437 for (const AuxiliaryObjectiveId id : SortedAuxiliaryObjectives()) {
439 summary.auxiliary_objectives.Insert(id.value(), objective_name(id)))
440 << "invalid auxiliary objective id in model";
441 }
442 RETURN_IF_ERROR(summary.auxiliary_objectives.SetNextFreeId(
443 copyable_data_.objectives.next_id().value()));
444 for (const LinearConstraintId id : SortedLinearConstraints()) {
445 RETURN_IF_ERROR(summary.linear_constraints.Insert(
446 id.value(), linear_constraint_name(id)))
447 << "invalid linear constraint id in model";
448 }
449 RETURN_IF_ERROR(summary.linear_constraints.SetNextFreeId(
450 copyable_data_.linear_constraints.next_id().value()));
451 for (const auto id : SortedConstraints<QuadraticConstraintId>()) {
452 RETURN_IF_ERROR(summary.quadratic_constraints.Insert(
453 id.value(), copyable_data_.quadratic_constraints.data(id).name))
454 << "invalid quadratic constraint id in model";
455 }
456 RETURN_IF_ERROR(summary.quadratic_constraints.SetNextFreeId(
457 copyable_data_.quadratic_constraints.next_id().value()));
458 for (const auto id : SortedConstraints<SecondOrderConeConstraintId>()) {
459 RETURN_IF_ERROR(summary.second_order_cone_constraints.Insert(
460 id.value(), copyable_data_.soc_constraints.data(id).name))
461 << "invalid second-order cone constraint id in model";
462 }
463 RETURN_IF_ERROR(summary.second_order_cone_constraints.SetNextFreeId(
464 copyable_data_.soc_constraints.next_id().value()));
465 for (const Sos1ConstraintId id : SortedConstraints<Sos1ConstraintId>()) {
466 RETURN_IF_ERROR(summary.sos1_constraints.Insert(
467 id.value(), constraint_data(id).name()))
468 << "invalid SOS1 constraint id in model";
469 }
470 RETURN_IF_ERROR(summary.sos1_constraints.SetNextFreeId(
471 copyable_data_.sos1_constraints.next_id().value()));
472 for (const Sos2ConstraintId id : SortedConstraints<Sos2ConstraintId>()) {
473 RETURN_IF_ERROR(summary.sos2_constraints.Insert(
474 id.value(), constraint_data(id).name()))
475 << "invalid SOS2 constraint id in model";
476 }
477 RETURN_IF_ERROR(summary.sos2_constraints.SetNextFreeId(
478 copyable_data_.sos2_constraints.next_id().value()));
479
480 for (const IndicatorConstraintId id :
481 SortedConstraints<IndicatorConstraintId>()) {
482 RETURN_IF_ERROR(summary.indicator_constraints.Insert(
483 id.value(), constraint_data(id).name));
484 }
485 RETURN_IF_ERROR(summary.indicator_constraints.SetNextFreeId(
486 copyable_data_.indicator_constraints.next_id().value()));
487
488 RETURN_IF_ERROR(ValidateModelUpdate(update_proto, summary))
489 << "update not valid";
490 }
491
492 // Remove deleted variables and constraints.
493 for (const int64_t v_id : update_proto.deleted_variable_ids()) {
494 DeleteVariable(VariableId(v_id));
495 }
496 for (const int64_t o_id :
497 update_proto.auxiliary_objectives_updates().deleted_objective_ids()) {
498 DeleteAuxiliaryObjective(AuxiliaryObjectiveId(o_id));
499 }
500 for (const int64_t c_id : update_proto.deleted_linear_constraint_ids()) {
501 DeleteLinearConstraint(LinearConstraintId(c_id));
502 }
503 for (const int64_t c_id :
504 update_proto.quadratic_constraint_updates().deleted_constraint_ids()) {
505 DeleteAtomicConstraint(QuadraticConstraintId(c_id));
506 }
507 for (const int64_t c_id : update_proto.second_order_cone_constraint_updates()
508 .deleted_constraint_ids()) {
509 DeleteAtomicConstraint(SecondOrderConeConstraintId(c_id));
510 }
511 for (const int64_t c_id :
512 update_proto.sos1_constraint_updates().deleted_constraint_ids()) {
513 DeleteAtomicConstraint(Sos1ConstraintId(c_id));
514 }
515 for (const int64_t c_id :
516 update_proto.sos2_constraint_updates().deleted_constraint_ids()) {
517 DeleteAtomicConstraint(Sos2ConstraintId(c_id));
518 }
519 for (const int64_t c_id :
520 update_proto.indicator_constraint_updates().deleted_constraint_ids()) {
521 DeleteAtomicConstraint(IndicatorConstraintId(c_id));
522 }
523
524 // Update existing variables' properties.
525 for (const auto [v_id, lb] :
526 MakeView(update_proto.variable_updates().lower_bounds())) {
527 set_variable_lower_bound(VariableId(v_id), lb);
528 }
529 for (const auto [v_id, ub] :
530 MakeView(update_proto.variable_updates().upper_bounds())) {
531 set_variable_upper_bound(VariableId(v_id), ub);
532 }
533 for (const auto [v_id, is_integer] :
534 MakeView(update_proto.variable_updates().integers())) {
535 set_variable_is_integer(VariableId(v_id), is_integer);
536 }
537
538 // Update existing constraints' properties.
539 for (const auto [c_id, lb] :
540 MakeView(update_proto.linear_constraint_updates().lower_bounds())) {
541 set_linear_constraint_lower_bound(LinearConstraintId(c_id), lb);
542 }
543 for (const auto [c_id, ub] :
544 MakeView(update_proto.linear_constraint_updates().upper_bounds())) {
545 set_linear_constraint_upper_bound(LinearConstraintId(c_id), ub);
546 }
547
548 // Add the new variables and constraints.
549 AddVariables(update_proto.new_variables());
550 AddAuxiliaryObjectives(
551 update_proto.auxiliary_objectives_updates().new_objectives());
552 AddLinearConstraints(update_proto.new_linear_constraints());
553 copyable_data_.quadratic_constraints.AddConstraints(
554 update_proto.quadratic_constraint_updates().new_constraints());
555 copyable_data_.soc_constraints.AddConstraints(
556 update_proto.second_order_cone_constraint_updates().new_constraints());
557 copyable_data_.sos1_constraints.AddConstraints(
558 update_proto.sos1_constraint_updates().new_constraints());
559 copyable_data_.sos2_constraints.AddConstraints(
560 update_proto.sos2_constraint_updates().new_constraints());
561 copyable_data_.indicator_constraints.AddConstraints(
562 update_proto.indicator_constraint_updates().new_constraints());
563
564 // Update the primary objective.
565 UpdateObjective(kPrimaryObjectiveId, update_proto.objective_updates());
566
567 // Update the auxiliary objectives.
568 for (const auto& [raw_id, objective_update] :
569 update_proto.auxiliary_objectives_updates().objective_updates()) {
570 UpdateObjective(AuxiliaryObjectiveId(raw_id), objective_update);
571 }
572
573 // Update the linear constraints' coefficients.
574 UpdateLinearConstraintCoefficients(
575 update_proto.linear_constraint_matrix_updates());
576
577 return absl::OkStatus();
578}
579
580} // namespace math_opt
581} // namespace operations_research
#define RETURN_IF_ERROR(expr)
void set_name(Arg_ &&arg, Args_... args)
::operations_research::math_opt::QuadraticConstraintUpdatesProto *PROTOBUF_NONNULL mutable_quadratic_constraint_updates()
An object oriented wrapper for quadratic constraints in ModelStorage.
Definition gurobi_isv.cc:28
absl::Status ValidateModelUpdate(const ModelUpdateProto &model_update, ModelSummary &model_summary)
ElementId< ElementType::kAuxiliaryObjective > AuxiliaryObjectiveId
Definition elements.h:266
ElementId< ElementType::kVariable > VariableId
Definition elements.h:264
constexpr ObjectiveId kPrimaryObjectiveId
SparseVectorView< T > MakeView(absl::Span< const int64_t > ids, const Collection &values)
ElementId< ElementType::kQuadraticConstraint > QuadraticConstraintId
Definition elements.h:267
ElementId< ElementType::kLinearConstraint > LinearConstraintId
Definition elements.h:265
auto MakeUpdateDataFieldRange(const UpdateTrackers &trackers)
Definition iterators.h:121
void RemoveNames(ModelProto &model)
Removes the model, variables and constraints names of the provided model.
std::optional< AuxiliaryObjectiveId > ObjectiveId
nullopt denotes the primary objective.
ElementId< ElementType::kIndicatorConstraint > IndicatorConstraintId
Definition elements.h:268
std::vector< K > SortedMapKeys(const absl::flat_hash_map< K, V > &in_map)
Definition sorted.h:55
absl::StatusOr< ModelSummary > ValidateModel(const ModelProto &model, const bool check_names)
In SWIG mode, we don't want anything besides these top-level includes.