Google OR-Tools v9.12
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
model_solve_parameters.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 <stdint.h>
17
18#include <initializer_list>
19#include <optional>
20#include <utility>
21
22#include "absl/algorithm/container.h"
23#include "absl/log/check.h"
24#include "absl/status/status.h"
25#include "absl/status/statusor.h"
26#include "absl/time/time.h"
27#include "google/protobuf/repeated_field.h"
35#include "ortools/math_opt/model_parameters.pb.h"
36#include "ortools/math_opt/solution.pb.h"
37#include "ortools/math_opt/sparse_containers.pb.h"
40
41namespace operations_research {
42namespace math_opt {
43
44using ::google::protobuf::RepeatedField;
45
54
59
61 const ModelStorage* const expected_storage) const {
62 for (const SolutionHint& hint : solution_hints) {
63 RETURN_IF_ERROR(hint.CheckModelStorage(expected_storage))
64 << "invalid hint in solution_hints";
65 }
66 if (initial_basis.has_value()) {
67 RETURN_IF_ERROR(initial_basis->CheckModelStorage(expected_storage))
68 << "invalid initial_basis";
69 }
70 RETURN_IF_ERROR(variable_values_filter.CheckModelStorage(expected_storage))
71 << "invalid variable_values_filter";
72 RETURN_IF_ERROR(dual_values_filter.CheckModelStorage(expected_storage))
73 << "invalid dual_values_filter";
75 quadratic_dual_values_filter.CheckModelStorage(expected_storage))
76 << "invalid quadratic_dual_values_filter";
77 RETURN_IF_ERROR(reduced_costs_filter.CheckModelStorage(expected_storage))
78 << "invalid reduced_costs_filter";
79 for (const auto [var, unused] : branching_priorities) {
81 /*storage=*/var.storage(),
82 /*expected_storage=*/expected_storage))
83 << "invalid variable " << var << " in branching_priorities";
84 }
85 for (const auto& [objective, params] : objective_parameters) {
87 /*storage=*/objective.storage(),
88 /*expected_storage=*/expected_storage))
89 << "invalid objective " << objective << " in objective_parameters";
90 }
91 for (const LinearConstraint lazy_linear_constraint :
94 /*storage=*/lazy_linear_constraint.storage(),
95 /*expected_storage=*/expected_storage))
96 << "invalid LinearConstraint " << lazy_linear_constraint
97 << " in lazy_linear_constraints";
98 }
99 return absl::OkStatus();
100}
101
103 const ModelStorage* expected_storage) const {
104 for (const auto& [v, _] : variable_values) {
106 /*storage=*/v.storage(),
107 /*expected_storage=*/expected_storage))
108 << "invalid variable " << v << " in variable_values";
109 }
110 for (const auto& [c, _] : dual_values) {
112 /*storage=*/c.storage(),
113 /*expected_storage=*/expected_storage))
114 << "invalid constraint " << c << " in dual_values";
115 }
116 return absl::OkStatus();
117}
118
120 SolutionHintProto hint;
121 *hint.mutable_variable_values() = VariableValuesToProto(variable_values);
122 *hint.mutable_dual_values() = LinearConstraintValuesToProto(dual_values);
123 return hint;
124}
125
126absl::StatusOr<ModelSolveParameters::SolutionHint>
128 const Model& model, const SolutionHintProto& hint_proto) {
131 VariableValuesFromProto(model.storage(), hint_proto.variable_values()),
132 _ << "failed to parse SolutionHintProto.variable_values");
135 model.storage(), hint_proto.dual_values()),
136 _ << "failed to parse SolutionHintProto.dual_values");
137 return SolutionHint{
138 .variable_values = std::move(variable_values),
139 .dual_values = std::move(dual_values),
140 };
141}
142
143absl::StatusOr<ObjectiveParametersProto>
145 ObjectiveParametersProto params;
147 params.set_objective_degradation_absolute_tolerance(
149 }
151 params.set_objective_degradation_relative_tolerance(
153 }
154 if (time_limit < absl::InfiniteDuration()) {
156 time_limit, params.mutable_time_limit()));
157 }
158 return params;
159}
160
161absl::StatusOr<ModelSolveParameters::ObjectiveParameters>
163 const ObjectiveParametersProto& proto) {
164 ObjectiveParameters result;
165 if (proto.has_objective_degradation_absolute_tolerance()) {
167 proto.objective_degradation_absolute_tolerance();
168 }
169 if (proto.has_objective_degradation_relative_tolerance()) {
171 proto.objective_degradation_relative_tolerance();
172 }
173 if (proto.has_time_limit()) {
175 util_time::DecodeGoogleApiProto(proto.time_limit()),
176 _ << "invalid time_limit");
177 } else {
178 result.time_limit = absl::InfiniteDuration();
179 }
180 return result;
181}
182
183// TODO: b/315974557 - Return an error if a RepeatedField is too long.
184absl::StatusOr<ModelSolveParametersProto> ModelSolveParameters::Proto() const {
185 ModelSolveParametersProto ret;
186 *ret.mutable_variable_values_filter() = variable_values_filter.Proto();
187 *ret.mutable_dual_values_filter() = dual_values_filter.Proto();
188 *ret.mutable_quadratic_dual_values_filter() =
190 *ret.mutable_reduced_costs_filter() = reduced_costs_filter.Proto();
191
192 if (initial_basis.has_value()) {
193 *ret.mutable_initial_basis() = initial_basis->Proto();
194 }
195
196 for (const SolutionHint& solution_hint : solution_hints) {
197 *ret.add_solution_hints() = solution_hint.Proto();
198 }
199 if (!branching_priorities.empty()) {
200 RepeatedField<int64_t>& variable_ids =
201 *ret.mutable_branching_priorities()->mutable_ids();
202 RepeatedField<int32_t>& variable_values =
203 *ret.mutable_branching_priorities()->mutable_values();
204 variable_ids.Reserve(static_cast<int>(branching_priorities.size()));
205 variable_values.Reserve(static_cast<int>(branching_priorities.size()));
206 for (const Variable& key : SortedKeys(branching_priorities)) {
207 variable_ids.Add(key.id());
208 variable_values.Add(branching_priorities.at(key));
209 }
210 }
211 for (const auto& [objective, params] : objective_parameters) {
212 if (objective.id().has_value()) {
214 ((*ret.mutable_auxiliary_objective_parameters())[*objective.id()]),
215 params.Proto(),
216 _ << "invalid parameters for objective " << *objective.id());
217 } else {
218 OR_ASSIGN_OR_RETURN3(*ret.mutable_primary_objective_parameters(),
219 params.Proto(),
220 _ << "invalid parameters for primary objective");
221 }
222 }
223 if (!lazy_linear_constraints.empty()) {
224 RepeatedField<int64_t>& lazy_linear_constraint_ids =
225 *ret.mutable_lazy_linear_constraint_ids();
226 lazy_linear_constraint_ids.Reserve(
227 static_cast<int>(lazy_linear_constraints.size()));
228 for (const LinearConstraint lazy_linear_constraint :
230 lazy_linear_constraint_ids.Add(lazy_linear_constraint.id());
231 }
232 absl::c_sort(lazy_linear_constraint_ids);
233 }
234 return ret;
235}
236
237absl::StatusOr<ModelSolveParameters> ModelSolveParameters::FromProto(
238 const Model& model, const ModelSolveParametersProto& proto) {
242 VariableFilterFromProto(model, proto.variable_values_filter()),
243 _ << "invalid variable_values_filter");
245 result.dual_values_filter,
246 LinearConstraintFilterFromProto(model, proto.dual_values_filter()),
247 _ << "invalid dual_values_filter");
250 model, proto.quadratic_dual_values_filter()),
251 _ << "invalid quadratic_dual_values_filter");
254 VariableFilterFromProto(model, proto.reduced_costs_filter()),
255 _ << "invalid reduced_costs_filter");
256 if (proto.has_initial_basis()) {
258 result.initial_basis,
259 Basis::FromProto(model.storage(), proto.initial_basis()),
260 _ << "invalid initial_basis");
261 }
262 for (int i = 0; i < proto.solution_hints_size(); ++i) {
264 SolutionHint hint,
265 SolutionHint::FromProto(model, proto.solution_hints(i)),
266 _ << "invalid solution_hints[" << i << "]");
267 result.solution_hints.push_back(std::move(hint));
268 }
271 VariableValuesFromProto(model.storage(), proto.branching_priorities()),
272 _ << "invalid branching_priorities");
273 if (proto.has_primary_objective_parameters()) {
275 auto primary_objective_params,
276 ObjectiveParameters::FromProto(proto.primary_objective_parameters()),
277 _ << "invalid primary_objective_parameters");
278 result.objective_parameters.try_emplace(
280 std::move(primary_objective_params));
281 }
282 for (const auto& [id, aux_obj_params_proto] :
283 proto.auxiliary_objective_parameters()) {
284 if (!model.has_auxiliary_objective(id)) {
286 << "invalid auxiliary_objective_parameters with id: " << id
287 << ", objective not in the model";
288 }
290 auto aux_obj_params,
291 ObjectiveParameters::FromProto(aux_obj_params_proto),
292 _ << "invalid auxiliary_objective_parameters with id: " << id);
293 result.objective_parameters.try_emplace(
294 Objective::Auxiliary(model.storage(), AuxiliaryObjectiveId{id}),
295 std::move(aux_obj_params));
296 }
297 for (int64_t lin_con : proto.lazy_linear_constraint_ids()) {
298 if (!model.has_linear_constraint(lin_con)) {
300 << "invalid lazy_linear_constraint with id: " << lin_con
301 << ", constraint not in the model";
302 }
303 result.lazy_linear_constraints.insert(model.linear_constraint(lin_con));
304 }
305 return result;
306}
307
308} // namespace math_opt
309} // namespace operations_research
#define RETURN_IF_ERROR(expr)
bool has_auxiliary_objective(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:1579
const ModelStorage * storage() const
Definition model.h:916
bool has_linear_constraint(int64_t id) const
Returns true if this id has been created and not yet deleted.
Definition model.h:1098
LinearConstraint linear_constraint(int64_t id) const
Will CHECK if has_linear_constraint(id) is false.
Definition model.h:1106
static Objective Primary(const ModelStorage *storage)
Returns an object that refers to the primary objective of the model.
Definition objective.h:220
static Objective Auxiliary(const ModelStorage *storage, AuxiliaryObjectiveId id)
Returns an object that refers to an auxiliary objective of the model.
Definition objective.h:224
absl::Status CheckModelStorage(const ModelStorage *const storage, const ModelStorage *const expected_storage)
Definition key_types.h:168
An object oriented wrapper for quadratic constraints in ModelStorage.
Definition gurobi_isv.cc:28
absl::flat_hash_map< Variable, V > VariableMap
MapFilter< KeyType > MakeSkipAllFilter()
Definition map_filter.h:142
absl::flat_hash_map< LinearConstraint, V > LinearConstraintMap
SparseDoubleVectorProto LinearConstraintValuesToProto(const LinearConstraintMap< double > &linear_constraint_values)
Returns the proto equivalent of linear_constraint_values.
absl::StatusOr< LinearConstraintMap< double > > LinearConstraintValuesFromProto(const ModelStorage *const model, const SparseDoubleVectorProto &lin_cons_proto)
absl::StatusOr< VariableMap< double > > VariableValuesFromProto(const ModelStorage *const model, const SparseDoubleVectorProto &vars_proto)
absl::StatusOr< MapFilter< LinearConstraint > > LinearConstraintFilterFromProto(const Model &model, const SparseVectorFilterProto &proto)
Definition map_filter.cc:46
SparseDoubleVectorProto VariableValuesToProto(const VariableMap< double > &variable_values)
Returns the proto equivalent of variable_values.
absl::StatusOr< MapFilter< QuadraticConstraint > > QuadraticConstraintFilterFromProto(const Model &model, const SparseVectorFilterProto &proto)
Definition map_filter.cc:67
std::vector< typename Map::key_type > SortedKeys(const Map &map)
Definition key_types.h:87
absl::StatusOr< MapFilter< Variable > > VariableFilterFromProto(const Model &model, const SparseVectorFilterProto &proto)
Definition map_filter.cc:28
In SWIG mode, we don't want anything besides these top-level includes.
inline ::absl::StatusOr< absl::Duration > DecodeGoogleApiProto(const google::protobuf::Duration &proto)
Definition protoutil.h:42
inline ::absl::StatusOr< google::protobuf::Duration > EncodeGoogleApiProto(absl::Duration d)
Definition protoutil.h:27
StatusBuilder InvalidArgumentErrorBuilder()
static absl::StatusOr< Basis > FromProto(const ModelStorage *model, const BasisProto &basis_proto)
Definition solution.cc:183
Parameters for an individual objective in a multi-objective model.
static absl::StatusOr< ObjectiveParameters > FromProto(const ObjectiveParametersProto &proto)
absl::StatusOr< ObjectiveParametersProto > Proto() const
Returns the proto equivalent of this object.
static absl::StatusOr< SolutionHint > FromProto(const Model &model, const SolutionHintProto &hint_proto)
absl::Status CheckModelStorage(const ModelStorage *expected_storage) const
absl::Status CheckModelStorage(const ModelStorage *expected_storage) const
MapFilter< QuadraticConstraint > quadratic_dual_values_filter
MapFilter< LinearConstraint > dual_values_filter
The filter that is applied to dual_values of DualSolution and DualRay.
ObjectiveMap< ObjectiveParameters > objective_parameters
Parameters for individual objectives in a multi-objective model.
static ModelSolveParameters OnlySomePrimalVariables(const Collection &variables)
absl::StatusOr< ModelSolveParametersProto > Proto() const
MapFilter< Variable > reduced_costs_filter
The filter that is applied to reduced_costs of DualSolution and DualRay.
static absl::StatusOr< ModelSolveParameters > FromProto(const Model &model, const ModelSolveParametersProto &proto)
absl::flat_hash_set< LinearConstraint > lazy_linear_constraints
#define OR_ASSIGN_OR_RETURN3(lhs, rexpr, error_expression)