OR-Tools  9.3
sparse_vector_view.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// 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"
60#include "ortools/math_opt/core/arrow_operator_proxy.h" // IWYU pragma: export
62#include "ortools/math_opt/sparse_containers.pb.h"
63
64namespace operations_research {
65namespace math_opt {
66
67// Recovers the values-type of a SparseVector type like SparseDoubleVector or
68// SparseBoolVector.
69template <typename SparseVector>
70using 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.
87template <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.
143template <typename Collection, typename T = typename Collection::value_type>
144SparseVectorView<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.
152template <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.
162template <typename SparseVectorProto,
163 typename T = sparse_value_type<SparseVectorProto>>
164SparseVectorView<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.
170template <typename T>
172 return SparseVectorView<T>(sparse_vector.ids, sparse_vector.values);
173}
174
176// Inline implementations
178
179template <typename T>
180SparseVectorView<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
188template <typename T>
189typename SparseVectorView<T>::const_iterator::reference
191 return {view_->ids(index_), view_->values(index_)};
192}
193
194template <typename T>
199}
200
201template <typename T>
204 DCHECK_LT(index_, view_->ids_size());
205 ++index_;
206 return *this;
207}
208
209template <typename T>
211 const const_iterator& other) const {
212 DCHECK_EQ(view_, other.view_);
213 return index_ == other.index_;
214}
215
216template <typename T>
218 const const_iterator& other) const {
219 return !(*this == other);
220}
221
222template <typename T>
224 const {
225 DCHECK_EQ(ids_size(), values_size());
226 return const_iterator(this, /*at_end=*/false);
227}
228
229template <typename T>
231 DCHECK_EQ(ids_size(), values_size());
232 return const_iterator(this, /*at_end=*/true);
233}
234
235template <typename T>
236template <typename IndexType>
237absl::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_
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:703
#define DCHECK_LT(val1, val2)
Definition: base/logging.h:894
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:891
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
SparseVectorView< T > MakeView(absl::Span< const int64_t > ids, const Collection &values)
bool operator!=(const LinearConstraint &lhs, const LinearConstraint &rhs)
Collection of objects used to extend the Constraint Solver library.
LinearExpr operator*(LinearExpr lhs, double rhs)
Definition: linear_expr.cc:154
LinearRange operator==(const LinearExpr &lhs, const LinearExpr &rhs)
Definition: linear_expr.cc:180
STL namespace.
std::optional< int64_t > end