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