OR-Tools  9.6
sparse_matrix_validator.cc
Go to the documentation of this file.
1 // Copyright 2010-2022 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 <cmath>
17 #include <cstdint>
18 #include <string>
19 
20 #include "absl/status/status.h"
21 #include "absl/strings/str_cat.h"
22 #include "absl/types/span.h"
25 #include "ortools/math_opt/sparse_containers.pb.h"
27 
29 
30 absl::Status SparseMatrixValid(const SparseDoubleMatrixProto& matrix,
31  const bool enforce_upper_triangular) {
32  const int nnz = matrix.row_ids_size();
33  if (nnz != matrix.column_ids_size()) {
35  << "Expected row_id.size=" << nnz
36  << " equal to column_ids.size=" << matrix.column_ids_size();
37  }
38  if (nnz != matrix.coefficients_size()) {
40  << "Expected row_id.size=" << nnz
41  << " equal to coefficients.size=" << matrix.coefficients_size();
42  }
43  int64_t previous_row = -1;
44  int64_t previous_col = -1;
45  for (int i = 0; i < nnz; ++i) {
46  const int64_t row = matrix.row_ids(i);
47  if (row < 0) {
49  << "row_ids should be nonnegative, but found id: " << row
50  << " (at index: " << i << ")";
51  }
52  const int64_t col = matrix.column_ids(i);
53  if (col < 0) {
55  << "column_ids should be nonnegative, but found id: " << col
56  << " (at index: " << i << ")";
57  }
58  if (enforce_upper_triangular && row > col) {
60  << "lower triangular entry at [" << row << ", " << col
61  << "] (at index: " << i << ")";
62  }
63  if (row < previous_row) {
65  << "row_ids should be nondecreasing, but found ids ["
66  << previous_row << ", " << row << "] at indices [" << i - 1 << ", "
67  << i << "]";
68  } else if (row == previous_row) {
69  if (previous_col >= col) {
71  << "column_ids should be strictly increasing within a row, but "
72  "for row_id: "
73  << row << " found [" << previous_col << ", " << col
74  << "] at indices, [" << i - 1 << ", " << i << "]";
75  }
76  }
77  // When row > previous_row, we have a new row, nothing to check.
78  if (!std::isfinite(matrix.coefficients(i))) {
80  << "Expected finite coefficients without NaN, but at row_id: "
81  << row << ", column_id: " << col
82  << " found coefficient: " << matrix.coefficients(i)
83  << " (at index: " << i << ")";
84  }
85  previous_row = row;
86  previous_col = col;
87  }
88  return absl::OkStatus();
89 }
90 
91 absl::Status SparseMatrixIdsAreKnown(const SparseDoubleMatrixProto& matrix,
92  const IdNameBiMap& row_ids,
93  const IdNameBiMap& column_ids) {
94  RETURN_IF_ERROR(CheckIdsSubset(matrix.row_ids(), row_ids))
95  << "Unknown row_id";
96  RETURN_IF_ERROR(CheckIdsSubset(matrix.column_ids(), column_ids))
97  << "Unknown column_id";
98  return absl::OkStatus();
99 }
100 
101 } // namespace operations_research::math_opt
#define RETURN_IF_ERROR(expr)
ColIndex col
Definition: markowitz.cc:186
RowIndex row
Definition: markowitz.cc:185
absl::Status SparseMatrixIdsAreKnown(const SparseDoubleMatrixProto &matrix, const IdNameBiMap &row_ids, const IdNameBiMap &column_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)
StatusBuilder InvalidArgumentErrorBuilder()