OR-Tools  9.6
sparse_vector_view.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 // A read only view for sparse vectors that implements various utilities.
15 //
16 // This header defines:
17 // * SparseVectorView<T>: a sparse vector as a span of int64_t ids and another
18 // span of values of type T. The underlying data is not owned and the user
19 // must ensure the data outlives the view.
20 // * Overloaded MakeView factories to avoid explicit template arguments.
21 //
22 // The utilities implemented by SparseVectorView<T> include:
23 // * const range iterations over the (id, value) pairs.
24 // * .as_map<IdT>() member function that returns the view as a
25 // absl::flat_hash_map<IdT, T>
26 
27 // Example:
28 // const std::vector<int64_t> ids = {2, 5, 7};
29 // const std::vector<double> values= {1.0, 3.0, 1.0};
30 // const SparseVectorView<double> view = MakeView(ids, values);
31 //
32 // Now view.ids => [2, 5, 7] and view.values => [1.0, 3.0, 1.0]. To iterate over
33 // the (id, value) pairs:
34 //
35 // for(const auto [id, value] : view) {
36 // ...
37 // }
38 //
39 // To get a map that casts the ids to the strong int type VariableId:
40 //
41 // auto map = view.as_map<VariableId>();
42 //
43 // For more information, see the class comments below.
44 
45 #ifndef OR_TOOLS_MATH_OPT_CORE_SPARSE_VECTOR_VIEW_H_
46 #define OR_TOOLS_MATH_OPT_CORE_SPARSE_VECTOR_VIEW_H_
47 
48 #include <stdint.h>
49 
50 #include <cstdint>
51 #include <iterator>
52 #include <utility>
53 
54 #include "absl/container/flat_hash_map.h"
55 #include "absl/types/span.h"
56 #include "google/protobuf/message.h"
58 #include "ortools/base/logging.h"
59 #include "ortools/base/map_util.h"
60 #include "ortools/math_opt/core/arrow_operator_proxy.h" // IWYU pragma: export
62 #include "ortools/math_opt/sparse_containers.pb.h"
63 
64 namespace operations_research {
65 namespace math_opt {
66 
67 // Recovers the values-type of a SparseVector type like SparseDoubleVector or
68 // SparseBoolVector.
69 template <typename SparseVector>
70 using sparse_value_type = typename std::remove_reference<
71  decltype(SparseVector().values())>::type::value_type;
72 
73 // Abstracts sparse ids-values structures like SparseDoubleVector and mimics
74 // its .ids()/.values() API. It additionally provides const range iterations
75 // over the (id, value) pairs and conversion to a map.
76 //
77 // The returned iterators are proper STL forward iterators that can be used with
78 // STL containers. For example to build a vector of pairs of values, one can
79 // simply use the iterators:
80 //
81 // const auto view = MakeView(arg);
82 // const std::vector v(view.begin(), view.end());
83 //
84 // Constructor SparseVectorView<T>(ids, values) will not check if ids and values
85 // have the same length. However, iterator functions and .as_map() will CHECK
86 // fail if ids and values do not have the same length.
87 template <typename T>
89  public:
90  using value_type = std::pair<int64_t, T>;
91 
93  public:
96  using pointer = void;
97  using const_pointer = void;
98  using difference_type = int;
99  using iterator_category = std::forward_iterator_tag;
100 
101  reference operator*() const;
104  bool operator==(const const_iterator& other) const;
105  bool operator!=(const const_iterator& other) const;
106 
107  private:
108  friend class SparseVectorView;
109 
110  inline explicit const_iterator(const SparseVectorView* view,
111  bool at_end = false);
112 
113  const SparseVectorView* view_ = nullptr;
114  int index_ = 0;
115  };
116 
117  SparseVectorView(absl::Span<const int64_t> ids, absl::Span<const T> values)
118  : ids_(std::move(ids)), values_(std::move(values)) {}
120 
121  inline const_iterator begin() const;
122  inline const_iterator end() const;
123 
124  absl::Span<const int64_t> ids() const { return ids_; }
125  int64_t ids(int index) const { return ids_[index]; }
126  int ids_size() const { return ids_.size(); }
127  absl::Span<const T> values() const { return values_; }
128  int values_size() const { return values_.size(); }
129  const T& values(int index) const { return values_[index]; }
130 
131  // It should be possible to construct an IndexType from an integer
132  template <typename IndexType>
133  absl::flat_hash_map<IndexType, T> as_map();
134 
135  private:
136  absl::Span<const int64_t> ids_;
137  absl::Span<const T> values_;
138 };
139 
140 // Returns a view for values that are vector-like collection like
141 // std::vector<T> or google::protobuf::RepeatedField<T>. See other overloads for
142 // other values-types.
143 template <typename Collection, typename T = typename Collection::value_type>
144 SparseVectorView<T> MakeView(absl::Span<const int64_t> ids,
145  const Collection& values) {
146  return SparseVectorView<T>(ids, values);
147 }
148 
149 // Returns a view for values that are google::protobuf::RepeatedPtrField<T>.
150 // Common use for this overload is when T = std::string. See other overloads for
151 // other values-types.
152 template <typename T>
154  const google::protobuf::RepeatedField<int64_t>& ids,
155  const google::protobuf::RepeatedPtrField<T>& values) {
156  return SparseVectorView<const T*>(ids, values);
157 }
158 
159 // Returns a view for values in a SparseDoubleVectorProto, SparseBoolVectorProto
160 // or similar structure. For such cases, it is preferred over the two-argument
161 // overloads. See other overloads for other values-types.
162 template <typename SparseVectorProto,
163  typename T = sparse_value_type<SparseVectorProto>>
164 SparseVectorView<T> MakeView(const SparseVectorProto& sparse_vector) {
165  return SparseVectorView<T>(sparse_vector.ids(), sparse_vector.values());
166 }
167 
168 // Returns a view for values in a SparseVector. For this case it is preferred
169 // over the two-argument overloads. See other overloads for other values-types.
170 template <typename T>
172  return SparseVectorView<T>(sparse_vector.ids, sparse_vector.values);
173 }
174 
176 // Inline implementations
178 
179 template <typename T>
180 SparseVectorView<T>::const_iterator::const_iterator(
181  const SparseVectorView<T>* view, bool at_end)
182  : view_(view) {
183  if (at_end) {
184  index_ = view_->ids_size();
185  }
186 }
187 
188 template <typename T>
189 typename SparseVectorView<T>::const_iterator::reference
191  return {view_->ids(index_), view_->values(index_)};
192 }
193 
194 template <typename T>
199 }
200 
201 template <typename T>
204  DCHECK_LT(index_, view_->ids_size());
205  ++index_;
206  return *this;
207 }
208 
209 template <typename T>
211  const const_iterator& other) const {
212  DCHECK_EQ(view_, other.view_);
213  return index_ == other.index_;
214 }
215 
216 template <typename T>
218  const const_iterator& other) const {
219  return !(*this == other);
220 }
221 
222 template <typename T>
224  const {
225  DCHECK_EQ(ids_size(), values_size());
226  return const_iterator(this, /*at_end=*/false);
227 }
228 
229 template <typename T>
231  DCHECK_EQ(ids_size(), values_size());
232  return const_iterator(this, /*at_end=*/true);
233 }
234 
235 template <typename T>
236 template <typename IndexType>
237 absl::flat_hash_map<IndexType, T> SparseVectorView<T>::as_map() {
238  absl::flat_hash_map<IndexType, T> result;
239  CHECK_EQ(ids_size(), values_size());
240  result.reserve(ids_size());
241  for (const auto& [id, value] : *this) {
242  gtl::InsertOrDie(&result, IndexType(id), value);
243  }
244  return result;
245 }
246 
247 } // namespace math_opt
248 } // namespace operations_research
249 
250 #endif // OR_TOOLS_MATH_OPT_CORE_SPARSE_VECTOR_VIEW_H_
internal::ArrowOperatorProxy< reference > operator->() const
SparseVectorView(absl::Span< const int64_t > ids, absl::Span< const T > values)
absl::Span< const int64_t > ids() const
absl::flat_hash_map< IndexType, T > as_map()
int64_t value
int index
void InsertOrDie(Collection *const collection, const typename Collection::value_type &value)
Definition: map_util.h:154
typename std::remove_reference< decltype(SparseVector().values())>::type::value_type sparse_value_type
bool operator!=(const IndicatorConstraint &lhs, const IndicatorConstraint &rhs)
SparseVectorView< T > MakeView(absl::Span< const int64_t > ids, const Collection &values)
Collection of objects used to extend the Constraint Solver library.
LinearExpr operator*(LinearExpr lhs, double rhs)
Definition: linear_expr.cc:158
LinearRange operator==(const LinearExpr &lhs, const LinearExpr &rhs)
Definition: linear_expr.cc:184
std::optional< int64_t > end