21 #include "absl/status/status.h" 22 #include "absl/strings/str_cat.h" 26 #include "ortools/math_opt/model_parameters.pb.h" 27 #include "ortools/math_opt/result.pb.h" 28 #include "ortools/math_opt/solution.pb.h" 29 #include "ortools/math_opt/sparse_containers.pb.h" 39 constexpr
double kInf = std::numeric_limits<double>::infinity();
46 for (
int i = 0; i < result.primal_solutions_size(); ++i) {
50 <<
"Invalid primal_solutions[" << i <<
"]";
52 for (
int i = 0; i < result.primal_rays_size(); ++i) {
56 <<
"Invalid primal_rays[" << i <<
"]";
58 for (
int i = 0; i < result.dual_solutions_size(); ++i) {
61 <<
"Invalid dual_solutions[" << i <<
"]";
63 for (
int i = 0; i < result.dual_rays_size(); ++i) {
66 <<
"Invalid dual_rays[" << i <<
"]";
68 for (
int i = 0; i < result.basis_size(); ++i) {
75 return absl::OkStatus();
90 absl::Status IsFiltered(
const SparseVectorView<T>& vector_view,
91 const SparseVectorFilterProto& filter,
92 const IdNameBiMap& all_items) {
94 SparseVectorFilterPredicate predicate(filter);
97 for (
int i = 0; i < vector_view.ids_size(); ++i) {
98 const int64_t
id = vector_view.ids(i);
99 if (!predicate.AcceptsAndUpdate(
id, vector_view.values(i))) {
100 return absl::InvalidArgumentError(
101 absl::StrCat(
"sparse vector should not contain the pair (id: ",
id,
102 ", value: ", vector_view.values(i),
") (at index: ", i,
103 ") that should have been filtered"));
109 if (filter.skip_zero_values()) {
110 return absl::OkStatus();
113 const int expected_size =
114 filter.filter_by_ids() ? filter.filtered_ids_size() : all_items.Size();
115 if (vector_view.ids_size() != expected_size) {
116 return absl::InvalidArgumentError(absl::StrCat(
117 "sparse vector should contain ", expected_size,
" values but contains ",
118 vector_view.ids_size(),
" instead"));
121 return absl::OkStatus();
132 absl::Status IsValidSolutionVector(
const SparseDoubleVectorProto& vector,
133 const SparseVectorFilterProto& filter,
134 const IdNameBiMap& all_items) {
135 const auto vector_view =
MakeView(vector);
138 {.allow_positive_infinity =
false, .allow_negative_infinity =
false}));
140 return absl::OkStatus();
146 const SparseVectorFilterProto& filter,
148 RETURN_IF_ERROR(IsValidSolutionVector(primal_solution.variable_values(),
150 <<
"Invalid PrimalSolutionProto.variable_values";
152 <<
"Invalid PrimalSolutionProto.objective_value";
153 return absl::OkStatus();
157 const SparseVectorFilterProto& filter,
159 RETURN_IF_ERROR(IsValidSolutionVector(primal_ray.variable_values(), filter,
161 <<
"Invalid PrimalRayProto.variable_values";
162 return absl::OkStatus();
169 dual_solution.dual_values(),
parameters.dual_linear_constraints_filter(),
171 <<
"Invalid DualSolutionProto.dual_values";
175 <<
"Invalid DualSolutionProto.reduced_costs";
177 <<
"Invalid DualSolutionProto.objective_value";
178 return absl::OkStatus();
185 dual_ray.dual_values(),
parameters.dual_linear_constraints_filter(),
187 <<
"Invalid DualRayProto.dual_values";
191 <<
"Invalid DualRayProto.reduced_costs";
192 return absl::OkStatus();
202 for (
auto [
id,
value] : status_vector_view) {
203 if (!BasisStatus_IsValid(
value)) {
204 return absl::InvalidArgumentError(
205 absl::StrCat(
"Invalid status: ",
value,
" for id ",
id));
207 if (
value == BasisStatus::INVALID) {
208 return absl::InvalidArgumentError(
209 absl::StrCat(
"Found BasisStatus::INVALID for id ",
id));
212 return absl::OkStatus();
217 const auto constraint_status_view =
MakeView(basis.constraint_status());
218 const auto variable_status_view =
MakeView(basis.variable_status());
220 << absl::StrCat(
"BasisProto.constraint_status invalid");
222 << absl::StrCat(
"BasisProto.variable_status invalid");
226 "BasisProto.constraint_status.ids",
"model_summary.linear_constraints"));
228 basis.variable_status().ids(), model_summary.
variables,
229 "BasisProto.variable_status.ids",
"model_summary.variables"));
231 int non_basic_variables = 0;
232 for (
const auto [
id,
value] : constraint_status_view) {
233 if (
value != BasisStatus::BASIC) {
234 non_basic_variables++;
237 for (
auto [
id,
value] : variable_status_view) {
238 if (
value != BasisStatus::BASIC) {
239 non_basic_variables++;
243 return absl::InvalidArgumentError(absl::StrCat(
244 "Inconsistent number of non-basic variable+constraints: ",
245 non_basic_variables,
", variables: ", model_summary.
variables.
Size()));
247 return absl::OkStatus();
absl::Status ValidateDualSolution(const DualSolutionProto &dual_solution, const ModelSolveParametersProto ¶meters, const ModelSummary &model_summary)
absl::Status ValidateDualRay(const DualRayProto &dual_ray, const ModelSolveParametersProto ¶meters, const ModelSummary &model_summary)
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 CheckScalarNoNanNoInf(const double d)
absl::Status ValidatePrimalRay(const PrimalRayProto &primal_ray, const SparseVectorFilterProto &filter, const ModelSummary &model_summary)
absl::Status CheckIdsIdentical(absl::Span< const int64_t > first_ids, const IdNameBiMap &second_ids, absl::string_view first_description, absl::string_view second_description)
absl::Status ValidatePrimalSolution(const PrimalSolutionProto &primal_solution, const SparseVectorFilterProto &filter, const ModelSummary &model_summary)
IdNameBiMap linear_constraints
absl::Status ValidateResult(const SolveResultProto &result, const ModelSolveParametersProto ¶meters, const ModelSummary &model_summary)
absl::Status CheckIdsSubset(absl::Span< const int64_t > ids, const IdNameBiMap &universe, absl::string_view ids_description, absl::string_view universe_description)
Collection of objects used to extend the Constraint Solver library.
#define RETURN_IF_ERROR(expr)
absl::Status SparseBasisStatusVectorIsValid(const SparseVectorView< int > &status_vector_view)
absl::Status ValidateBasis(const BasisProto &basis, const ModelSummary &model_summary)
absl::Status CheckIdsAndValuesSize(const SparseVectorView< T > &vector_view, absl::string_view value_name="values")