20 #include "absl/status/status.h"
21 #include "absl/status/statusor.h"
29 #include "ortools/math_opt/model.pb.h"
30 #include "ortools/math_opt/model_update.pb.h"
31 #include "ortools/math_opt/sparse_containers.pb.h"
45 absl::Status VariablesValid(
const VariablesProto& variables) {
47 <<
"Bad variable ids";
50 {.allow_positive_infinity = false},
"lower_bounds"));
53 {.allow_negative_infinity = false},
"upper_bounds"));
56 return absl::OkStatus();
59 absl::Status VariableUpdatesValid(
const VariableUpdatesProto& variable_updates,
61 const int64_t old_var_id_ub) {
63 {.allow_positive_infinity = false}))
64 <<
"Bad lower bounds";
66 {.allow_negative_infinity = false}))
67 <<
"Bad upper bounds";
72 <<
"lower bound update on invalid variable id";
75 <<
"upper bound update on invalid variable id";
78 <<
"integer update on invalid variable id";
79 return absl::OkStatus();
82 absl::Status ObjectiveValid(
const ObjectiveProto& objective,
86 <<
"Objective offset invalid";
88 const auto linear_coefficients =
MakeView(objective.linear_coefficients());
91 {.allow_positive_infinity =
false, .allow_negative_infinity =
false}))
92 <<
"Linear objective coefficients bad";
94 <<
"Objective.linear_coefficients.ids not found in Variables.ids";
98 <<
"Objective.quadratic_coefficients invalid";
101 <<
"Objective.quadratic_coefficients invalid";
102 if (
const int64_t priority = objective.priority(); priority < 0) {
104 <<
"expected Objective.priority to be nonnegative but found "
108 return absl::OkStatus();
112 absl::Status ObjectiveUpdatesValid(
113 const ObjectiveUpdatesProto& objective_updates,
117 <<
"Offset update invalid";
120 MakeView(objective_updates.linear_coefficients()),
121 {.allow_positive_infinity = false, .allow_negative_infinity = false}))
122 <<
"Linear objective coefficients invalid";
126 <<
"Objective.quadratic_coefficients invalid";
129 <<
"Linear coefficients ids not found in variable ids";
132 <<
"quadratic_coefficients invalid";
133 if (objective_updates.has_priority_update()) {
134 const int64_t priority = objective_updates.priority_update();
137 <<
"expected Objective.priority to be nonnegative but found "
142 return absl::OkStatus();
145 absl::Status AuxiliaryObjectivesUpdatesValid(
146 const AuxiliaryObjectivesUpdatesProto& objectives,
147 const IdNameBiMap&
variable_ids,
const IdNameBiMap& objective_ids) {
148 for (
const auto& [
id, new_objective] : objectives.new_objectives()) {
150 <<
"bad new auxiliary objective with id: " << id;
152 for (
const auto& [
id, objective_update] : objectives.objective_updates()) {
153 if (!objective_ids.HasId(
id)) {
155 <<
"objective update on auxiliary objective not present in model "
161 return absl::OkStatus();
164 absl::Status LinearConstraintsValid(
165 const LinearConstraintsProto& linear_constraints) {
167 <<
"Bad linear constraint ids";
169 MakeView(linear_constraints.ids(), linear_constraints.lower_bounds()),
170 {.allow_positive_infinity = false},
"lower_bounds"));
172 MakeView(linear_constraints.ids(), linear_constraints.upper_bounds()),
173 {.allow_negative_infinity = false},
"upper_bounds"));
174 return absl::OkStatus();
177 absl::Status LinearConstraintUpdatesValid(
178 const LinearConstraintUpdatesProto& linear_constraint_updates,
179 const IdNameBiMap& linear_constraint_ids,
const int64_t old_lin_con_id_ub) {
182 {.allow_positive_infinity = false}))
183 <<
"Bad lower bounds";
186 {.allow_negative_infinity = false}))
187 <<
"Bad upper bounds";
189 linear_constraint_ids, old_lin_con_id_ub))
190 <<
"lower bound update on invalid linear constraint id";
192 linear_constraint_ids, old_lin_con_id_ub))
193 <<
"upper bound update on invalid linear constraint id";
194 return absl::OkStatus();
197 absl::Status LinearConstraintMatrixIdsValidForUpdate(
198 const SparseDoubleMatrixProto& matrix,
199 const IdNameBiMap& linear_constraint_ids,
const IdNameBiMap&
variable_ids) {
201 <<
"Unknown linear_constraint_id";
203 <<
"Unknown variable_id";
204 return absl::OkStatus();
210 template <
typename Constra
intType>
211 absl::Status ValidateConstraintMap(
212 const google::protobuf::Map<int64_t, ConstraintType>& constraints,
213 const IdNameBiMap& variable_universe) {
214 for (
const auto& [
id, constraint] : constraints) {
216 <<
"invalid constraint with id: " << id;
218 return absl::OkStatus();
228 const bool check_names) {
232 <<
"ModelProto.variables are invalid.";
234 <<
"ModelProto.objective is invalid";
235 for (
const auto& [
id, objective] :
model.auxiliary_objectives()) {
237 <<
"ModelProto.auxiliary_objectives is invalid with objective id: "
241 <<
"ModelProto.linear_constraints are invalid";
243 <<
"ModelProto.linear_constraint_matrix invalid";
245 model_summary.linear_constraints,
246 model_summary.variables))
247 <<
"ModelProto.linear_constraint_matrix ids are inconsistent";
250 model_summary.variables))
251 <<
"ModelProto.quadratic_constraints invalid";
253 ValidateConstraintMap(
model.sos1_constraints(), model_summary.variables))
254 <<
"ModelProto.sos1_constraints invalid";
256 ValidateConstraintMap(
model.sos2_constraints(), model_summary.variables))
257 <<
"ModelProto.sos2_constraints invalid";
259 model_summary.variables))
260 <<
"ModelProto.indicator_constraints invalid";
262 return model_summary;
272 const int64_t old_var_id_ub = model_update.new_variables().ids_size() > 0
273 ? model_update.new_variables().ids(0)
275 const int64_t old_lin_con_id_ub =
276 model_update.new_linear_constraints().ids_size() > 0
277 ? model_update.new_linear_constraints().ids(0)
281 <<
"ModelUpdateProto.variable_updates invalid";
282 RETURN_IF_ERROR(ObjectiveUpdatesValid(model_update.objective_updates(),
284 <<
"ModelUpdateProto.objective_update invalid";
286 model_update.auxiliary_objectives_updates(), model_summary.
variables,
288 <<
"ModelUpdateProto.auxiliary_objectives_updates invalid";
290 model_update.linear_constraint_updates(),
292 <<
"ModelUpdateProto.linear_constraint_updates invalid";
294 <<
"ModelUpdateProto.new_variables invalid";
295 RETURN_IF_ERROR(LinearConstraintsValid(model_update.new_linear_constraints()))
296 <<
"ModelUpdateProto.new_linear_constraints invalid";
299 <<
"ModelUpdateProto.linear_constraint_matrix_updates invalid";
302 model_update.linear_constraint_matrix_updates(),
304 <<
"invalid linear constraint matrix update";
307 model_update.quadratic_constraint_updates().new_constraints(),
309 <<
"ModelUpdateProto.quadratic_constraint_updates.new_constraints "
312 model_update.sos1_constraint_updates().new_constraints(),
314 <<
"ModelUpdateProto.sos1_constraint_updates.new_constraints invalid";
316 model_update.sos2_constraint_updates().new_constraints(),
318 <<
"ModelUpdateProto.sos2_constraint_updates.new_constraints invalid";
320 model_update.indicator_constraint_updates().new_constraints(),
322 <<
"ModelUpdateProto.indicator_constraint_updates.new_constraints "
325 return absl::OkStatus();
#define ASSIGN_OR_RETURN(lhs, rexpr)
#define RETURN_IF_ERROR(expr)
int64_t next_free_id() const
absl::Span< const int64_t > variable_ids
absl::Status ValidateModelUpdate(const ModelUpdateProto &model_update, ModelSummary &model_summary)
absl::Status SparseMatrixIdsAreKnown(const SparseDoubleMatrixProto &matrix, const IdNameBiMap &row_ids, const IdNameBiMap &column_ids)
absl::Status CheckValues(const SparseVectorView< T > &vector_view, absl::string_view value_name="values")
absl::Status ValidateConstraint(const IndicatorConstraintProto &constraint, const IdNameBiMap &variable_universe)
absl::Status CheckIdsRangeAndStrictlyIncreasing(absl::Span< const int64_t > ids)
absl::Status CheckIdsSubset(absl::Span< const int64_t > ids, const IdNameBiMap &universe, std::optional< int64_t > upper_bound)
absl::Status SparseMatrixValid(const SparseDoubleMatrixProto &matrix, const bool enforce_upper_triangular)
absl::Status CheckIdsAndValues(const SparseVectorView< T > &vector_view, absl::string_view value_name="values")
absl::StatusOr< ModelSummary > ValidateModel(const ModelProto &model, const bool check_names)
SparseVectorView< T > MakeView(absl::Span< const int64_t > ids, const Collection &values)
absl::Status CheckScalarNoNanNoInf(const double d)
Collection of objects used to extend the Constraint Solver library.
StatusBuilder InvalidArgumentErrorBuilder()
absl::Status Update(const ModelUpdateProto &model_update)
static absl::StatusOr< ModelSummary > Create(const ModelProto &model, bool check_names=true)
IdNameBiMap linear_constraints
IdNameBiMap auxiliary_objectives