20#include "absl/status/status.h"
21#include "absl/status/statusor.h"
48 <<
"Bad variable ids";
51 {.allow_positive_infinity = false},
"lower_bounds"));
54 {.allow_negative_infinity = false},
"upper_bounds"));
57 return absl::OkStatus();
62 const int64_t old_var_id_ub) {
64 {.allow_positive_infinity = false}))
65 <<
"Bad lower bounds";
67 {.allow_negative_infinity = false}))
68 <<
"Bad upper bounds";
72 variable_ids, old_var_id_ub))
73 <<
"lower bound update on invalid variable id";
75 variable_ids, old_var_id_ub))
76 <<
"upper bound update on invalid variable id";
78 variable_ids, old_var_id_ub))
79 <<
"integer update on invalid variable id";
80 return absl::OkStatus();
87 <<
"Objective offset invalid";
89 const auto linear_coefficients =
MakeView(objective.linear_coefficients());
92 {.allow_positive_infinity =
false, .allow_negative_infinity =
false}))
93 <<
"Linear objective coefficients bad";
95 <<
"Objective.linear_coefficients.ids not found in Variables.ids";
99 <<
"Objective.quadratic_coefficients invalid";
101 variable_ids, variable_ids))
102 <<
"Objective.quadratic_coefficients invalid";
103 if (
const int64_t priority = objective.priority(); priority < 0) {
105 <<
"expected Objective.priority to be nonnegative but found "
109 return absl::OkStatus();
113absl::Status ObjectiveUpdatesValid(
118 <<
"Offset update invalid";
121 MakeView(objective_updates.linear_coefficients()),
122 {.allow_positive_infinity = false, .allow_negative_infinity = false}))
123 <<
"Linear objective coefficients invalid";
127 <<
"Objective.quadratic_coefficients invalid";
130 <<
"Linear coefficients ids not found in variable ids";
132 objective_updates.quadratic_coefficients(), variable_ids, variable_ids))
133 <<
"quadratic_coefficients invalid";
134 if (objective_updates.has_priority_update()) {
135 const int64_t priority = objective_updates.priority_update();
138 <<
"expected Objective.priority to be nonnegative but found "
143 return absl::OkStatus();
146absl::Status AuxiliaryObjectivesUpdatesValid(
149 for (
const auto& [
id, new_objective] : objectives.new_objectives()) {
150 if (objectives.objective_updates().contains(
id)) {
152 <<
"objective update on new auxiliary objective with "
157 <<
"bad new auxiliary objective with id: " << id;
159 for (
const auto&
id : objectives.deleted_objective_ids()) {
160 if (objectives.objective_updates().contains(
id)) {
162 <<
"objective update on deleted auxiliary objective with "
167 for (
const auto& [
id, objective_update] : objectives.objective_updates()) {
168 if (!objective_ids.HasId(
id)) {
170 <<
"objective update on auxiliary objective not present in model "
174 RETURN_IF_ERROR(ObjectiveUpdatesValid(objective_update, variable_ids));
176 return absl::OkStatus();
179absl::Status LinearConstraintsValid(
182 <<
"Bad linear constraint ids";
184 MakeView(linear_constraints.ids(), linear_constraints.lower_bounds()),
185 {.allow_positive_infinity = false},
"lower_bounds"));
187 MakeView(linear_constraints.ids(), linear_constraints.upper_bounds()),
188 {.allow_negative_infinity = false},
"upper_bounds"));
189 return absl::OkStatus();
192absl::Status LinearConstraintUpdatesValid(
194 const IdNameBiMap& linear_constraint_ids,
const int64_t old_lin_con_id_ub) {
197 {.allow_positive_infinity = false}))
198 <<
"Bad lower bounds";
201 {.allow_negative_infinity = false}))
202 <<
"Bad upper bounds";
204 linear_constraint_ids, old_lin_con_id_ub))
205 <<
"lower bound update on invalid linear constraint id";
207 linear_constraint_ids, old_lin_con_id_ub))
208 <<
"upper bound update on invalid linear constraint id";
209 return absl::OkStatus();
212absl::Status LinearConstraintMatrixIdsValidForUpdate(
216 <<
"Unknown linear_constraint_id";
218 <<
"Unknown variable_id";
219 return absl::OkStatus();
225template <
typename Constra
intType>
226absl::Status ValidateConstraintMap(
227 const google::protobuf::Map<int64_t, ConstraintType>& constraints,
229 for (
const auto& [
id, constraint] : constraints) {
231 <<
"invalid constraint with id: " << id;
233 return absl::OkStatus();
243 const bool check_names) {
247 <<
"ModelProto.variables are invalid.";
248 RETURN_IF_ERROR(ObjectiveValid(model.objective(), model_summary.variables))
249 <<
"ModelProto.objective is invalid";
250 for (
const auto& [
id, objective] : model.auxiliary_objectives()) {
252 <<
"ModelProto.auxiliary_objectives is invalid with objective id: "
256 <<
"ModelProto.linear_constraints are invalid";
258 <<
"ModelProto.linear_constraint_matrix invalid";
260 model_summary.linear_constraints,
261 model_summary.variables))
262 <<
"ModelProto.linear_constraint_matrix ids are inconsistent";
265 model_summary.variables))
266 <<
"ModelProto.quadratic_constraints invalid";
267 RETURN_IF_ERROR(ValidateConstraintMap(model.second_order_cone_constraints(),
268 model_summary.variables))
269 <<
"ModelProto.second_order_cone_constraints invalid";
271 ValidateConstraintMap(model.sos1_constraints(), model_summary.variables))
272 <<
"ModelProto.sos1_constraints invalid";
274 ValidateConstraintMap(model.sos2_constraints(), model_summary.variables))
275 <<
"ModelProto.sos2_constraints invalid";
277 model_summary.variables))
278 <<
"ModelProto.indicator_constraints invalid";
280 return model_summary;
288 ModelSummary& model_summary) {
290 const int64_t old_var_id_ub = model_update.new_variables().ids_size() > 0
291 ? model_update.new_variables().ids(0)
292 : model_summary.variables.next_free_id();
293 const int64_t old_lin_con_id_ub =
294 model_update.new_linear_constraints().ids_size() > 0
295 ? model_update.new_linear_constraints().ids(0)
296 : model_summary.linear_constraints.next_free_id();
298 model_summary.variables, old_var_id_ub))
299 <<
"ModelUpdateProto.variable_updates invalid";
300 RETURN_IF_ERROR(ObjectiveUpdatesValid(model_update.objective_updates(),
301 model_summary.variables))
302 <<
"ModelUpdateProto.objective_update invalid";
304 model_update.auxiliary_objectives_updates(), model_summary.variables,
305 model_summary.auxiliary_objectives))
306 <<
"ModelUpdateProto.auxiliary_objectives_updates invalid";
308 model_update.linear_constraint_updates(),
309 model_summary.linear_constraints, old_lin_con_id_ub))
310 <<
"ModelUpdateProto.linear_constraint_updates invalid";
312 <<
"ModelUpdateProto.new_variables invalid";
313 RETURN_IF_ERROR(LinearConstraintsValid(model_update.new_linear_constraints()))
314 <<
"ModelUpdateProto.new_linear_constraints invalid";
317 <<
"ModelUpdateProto.linear_constraint_matrix_updates invalid";
320 model_update.linear_constraint_matrix_updates(),
321 model_summary.linear_constraints, model_summary.variables))
322 <<
"invalid linear constraint matrix update";
325 model_update.quadratic_constraint_updates().new_constraints(),
326 model_summary.variables))
327 <<
"ModelUpdateProto.quadratic_constraint_updates.new_constraints "
330 model_update.second_order_cone_constraint_updates().new_constraints(),
331 model_summary.variables))
332 <<
"ModelUpdateProto.second_order_cone_constraint_updates.new_"
333 "constraints invalid";
335 model_update.sos1_constraint_updates().new_constraints(),
336 model_summary.variables))
337 <<
"ModelUpdateProto.sos1_constraint_updates.new_constraints invalid";
339 model_update.sos2_constraint_updates().new_constraints(),
340 model_summary.variables))
341 <<
"ModelUpdateProto.sos2_constraint_updates.new_constraints invalid";
343 model_update.indicator_constraint_updates().new_constraints(),
344 model_summary.variables))
345 <<
"ModelUpdateProto.indicator_constraint_updates.new_constraints "
348 return absl::OkStatus();
#define ASSIGN_OR_RETURN(lhs, rexpr)
#define RETURN_IF_ERROR(expr)
absl::Status ValidateModelUpdate(const ModelUpdateProto &model_update, ModelSummary &model_summary)
absl::Status CheckValues(const SparseVectorView< T > &vector_view, absl::string_view value_name="values")
absl::Status SparseMatrixIdsAreKnown(const SparseDoubleMatrixProto &matrix, const IdNameBiMap &row_ids, const IdNameBiMap &column_ids)
SparseVectorView< T > MakeView(absl::Span< const int64_t > ids, const Collection &values)
absl::Status CheckIdsAndValues(const SparseVectorView< T > &vector_view, absl::string_view value_name="values")
absl::Status ValidateConstraint(const IndicatorConstraintProto &constraint, const IdNameBiMap &variable_universe)
absl::Status CheckIdsSubset(absl::Span< const int64_t > ids, const IdNameBiMap &universe, std::optional< int64_t > upper_bound)
absl::Status CheckScalarNoNanNoInf(const double d)
absl::Status SparseMatrixValid(const SparseDoubleMatrixProto &matrix, const bool enforce_upper_triangular)
absl::Status CheckIdsRangeAndStrictlyIncreasing(absl::Span< const int64_t > ids)
absl::StatusOr< ModelSummary > ValidateModel(const ModelProto &model, const bool check_names)
StatusBuilder InvalidArgumentErrorBuilder()
static absl::StatusOr< ModelSummary > Create(const ModelProto &model, bool check_names=true)