OR-Tools  9.6
math_opt_proto_utils.h
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 
14 #ifndef OR_TOOLS_MATH_OPT_CORE_MATH_OPT_PROTO_UTILS_H_
15 #define OR_TOOLS_MATH_OPT_CORE_MATH_OPT_PROTO_UTILS_H_
16 
17 #include <cstdint>
18 #include <optional>
19 #include <type_traits>
20 
21 #include "absl/container/flat_hash_set.h"
22 #include "absl/status/status.h"
23 #include "absl/strings/string_view.h"
24 #include "absl/log/check.h"
25 #include "ortools/math_opt/callback.pb.h"
26 #include "ortools/math_opt/model.pb.h"
27 #include "ortools/math_opt/model_update.pb.h"
28 #include "ortools/math_opt/result.pb.h"
29 #include "ortools/math_opt/sparse_containers.pb.h"
30 
31 namespace operations_research {
32 namespace math_opt {
33 
34 inline int NumVariables(const VariablesProto& variables) {
35  return variables.ids_size();
36 }
37 
38 inline int NumConstraints(const LinearConstraintsProto& linear_constraints) {
39  return linear_constraints.ids_size();
40 }
41 
42 inline int NumMatrixNonzeros(const SparseDoubleMatrixProto& matrix) {
43  return matrix.row_ids_size();
44 }
45 
46 // Returns the id of the first variable if there is one. If the input proto is
47 // valid, this will also be the smallest id.
48 inline std::optional<int64_t> FirstVariableId(const VariablesProto& variables) {
49  return variables.ids().empty() ? std::nullopt
50  : std::make_optional(variables.ids()[0]);
51 }
52 
53 // Returns the id of the first linear constraint if there is one. If the input
54 // proto is valid, this will also be the smallest id.
55 inline std::optional<int64_t> FirstLinearConstraintId(
56  const LinearConstraintsProto& linear_constraints) {
57  return linear_constraints.ids().empty()
58  ? std::nullopt
59  : std::make_optional(linear_constraints.ids()[0]);
60 }
61 
62 // Removes the items in the sparse double vector for all indices whose value is
63 // exactly 0.0.
64 //
65 // NaN values are kept in place.
66 //
67 // The function asserts that input is a valid sparse vector, i.e. that the
68 // number of values and ids match.
69 void RemoveSparseDoubleVectorZeros(SparseDoubleVectorProto& sparse_vector);
70 
71 // A utility class that tests if a pair (id, value) should be filtered based on
72 // an input SparseVectorFilterProto.
73 //
74 // This predicate expects the input is sorted by ids. In non-optimized builds,
75 // it will check that this is the case.
77  public:
78  // Builds a predicate based on the input filter. A reference to this filter is
79  // kept so the caller must make sure this filter outlives the predicate.
80  //
81  // The filter.filtered_ids is expected to be sorted and not contain
82  // duplicates. In non-optimized builds, it will be CHECKed.
83  explicit SparseVectorFilterPredicate(const SparseVectorFilterProto& filter);
84 
85  // Returns true if the input value should be kept, false if it should be
86  // ignored since it is not selected by the filter.
87  //
88  // This function is expected to be called with strictly increasing ids. In
89  // non-optimized builds it will CHECK that this is the case. It updates an
90  // internal counter when filtering by ids.
91  template <typename Value>
92  bool AcceptsAndUpdate(const int64_t id, const Value& value);
93 
94  private:
95  const SparseVectorFilterProto& filter_;
96 
97  // Index of the next element to consider in filter_.filtered_ids().
98  int next_filtered_id_index_ = 0;
99 
100 #ifndef NDEBUG
101  // Invariant: next input id must be >= next_input_id_lower_bound_.
102  //
103  // The initial value is 0 since all ids are expected to be non-negative.
104  int64_t next_input_id_lower_bound_ = 0;
105 #endif // NDEBUG
106 };
107 
108 // Returns the callback_registration.request_registration as a set of enums.
109 absl::flat_hash_set<CallbackEventProto> EventSet(
110  const CallbackRegistrationProto& callback_registration);
111 
112 // Sets the reason to TERMINATION_REASON_FEASIBLE if feasible = true and
113 // TERMINATION_REASON_NO_SOLUTION_FOUND otherwise.
114 TerminationProto TerminateForLimit(const LimitProto limit, bool feasible,
115  absl::string_view detail = {});
116 
117 TerminationProto FeasibleTermination(const LimitProto limit,
118  absl::string_view detail = {});
119 
120 TerminationProto NoSolutionFoundTermination(const LimitProto limit,
121  absl::string_view detail = {});
122 
123 TerminationProto TerminateForReason(TerminationReasonProto reason,
124  absl::string_view detail = {});
125 
126 enum class SupportType {
127  kNotSupported = 1,
128  kSupported = 2,
129  kNotImplemented = 3,
130 };
131 
140 };
141 
142 // Returns an InvalidArgumentError (respectively, UnimplementedError) if a
143 // problem structure is present in `model` and not supported (resp., not yet
144 // implemented) according to `support_menu`.
145 absl::Status ModelIsSupported(const ModelProto& model,
146  const SupportedProblemStructures& support_menu,
147  absl::string_view solver_name);
148 
149 // Returns false if a problem structure is present in `update` and not
150 // not implemented or supported according to `support_menu`.
151 bool UpdateIsSupported(const ModelUpdateProto& update,
152  const SupportedProblemStructures& support_menu);
153 
155 // Inline functions implementations.
157 
158 template <typename Value>
160  const Value& value) {
161 #ifndef NDEBUG
162  CHECK_GE(id, next_input_id_lower_bound_)
163  << "This function must be called with strictly increasing ids.";
164 
165  // Update the range of the next expected id. We expect input to be strictly
166  // increasing.
167  next_input_id_lower_bound_ = id + 1;
168 #endif // NDEBUG
169 
170  // For this predicate we use `0` as the zero to test with since as of today we
171  // only have SparseDoubleVectorProto and SparseBoolVectorProto. The `bool`
172  // type is an integral type so the comparison with 0 will indeed be equivalent
173  // to keeping only `true` values.
174  if (filter_.skip_zero_values() && value == 0) {
175  return false;
176  }
177 
178  if (!filter_.filter_by_ids()) {
179  return true;
180  }
181 
182  // Skip all filtered_ids that are smaller than the input id.
183  while (next_filtered_id_index_ < filter_.filtered_ids_size() &&
184  filter_.filtered_ids(next_filtered_id_index_) < id) {
185  ++next_filtered_id_index_;
186  }
187 
188  if (next_filtered_id_index_ == filter_.filtered_ids_size()) {
189  // We filter by ids and there are no more ids that should pass.
190  return false;
191  }
192 
193  // The previous loop ensured that the element at next_filtered_id_index_ is
194  // the first element greater or equal to id.
195  return id == filter_.filtered_ids(next_filtered_id_index_);
196 }
197 
198 } // namespace math_opt
199 } // namespace operations_research
200 
201 #endif // OR_TOOLS_MATH_OPT_CORE_MATH_OPT_PROTO_UTILS_H_
SparseVectorFilterPredicate(const SparseVectorFilterProto &filter)
bool AcceptsAndUpdate(const int64_t id, const Value &value)
int64_t value
GRBmodel * model
TerminationProto FeasibleTermination(const LimitProto limit, const absl::string_view detail)
int NumMatrixNonzeros(const SparseDoubleMatrixProto &matrix)
int NumVariables(const VariablesProto &variables)
std::optional< int64_t > FirstLinearConstraintId(const LinearConstraintsProto &linear_constraints)
absl::Status ModelIsSupported(const ModelProto &model, const SupportedProblemStructures &support_menu, const absl::string_view solver_name)
bool UpdateIsSupported(const ModelUpdateProto &update, const SupportedProblemStructures &support_menu)
TerminationProto TerminateForLimit(const LimitProto limit, const bool feasible, const absl::string_view detail)
TerminationProto NoSolutionFoundTermination(const LimitProto limit, const absl::string_view detail)
int NumConstraints(const LinearConstraintsProto &linear_constraints)
TerminationProto TerminateForReason(const TerminationReasonProto reason, const absl::string_view detail)
absl::flat_hash_set< CallbackEventProto > EventSet(const CallbackRegistrationProto &callback_registration)
void RemoveSparseDoubleVectorZeros(SparseDoubleVectorProto &sparse_vector)
std::optional< int64_t > FirstVariableId(const VariablesProto &variables)
std::function< int64_t(const Model &)> Value(IntegerVariable v)
Definition: integer.h:1795
Collection of objects used to extend the Constraint Solver library.