OR-Tools  9.2
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
56#include "google/protobuf/message.h"
57#include "absl/container/flat_hash_map.h"
58#include "absl/types/span.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 other
142// 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>. Common use
150// for this overload is when T = std::string. See other overloads for other
151// values-types.
152template <typename T>
153SparseVectorView<const T*> MakeView(const google::protobuf::RepeatedField<int64_t>& ids,
154 const google::protobuf::RepeatedPtrField<T>& values) {
155 return SparseVectorView<const T*>(ids, values);
156}
157
158// Returns a view for values in a SparseDoubleVectorProto, SparseBoolVectorProto
159// or similar structure. For such cases, it is preferred over the two-argument
160// overloads. See other overloads for other values-types.
161template <typename SparseVectorProto,
162 typename T = sparse_value_type<SparseVectorProto>>
163SparseVectorView<T> MakeView(const SparseVectorProto& sparse_vector) {
164 return SparseVectorView<T>(sparse_vector.ids(), sparse_vector.values());
165}
166
167// Returns a view for values in a SparseVector. For this case it is preferred
168// over the two-argument overloads. See other overloads for other values-types.
169template <typename T>
171 return SparseVectorView<T>(sparse_vector.ids, sparse_vector.values);
172}
173
175// Inline implementations
177
178template <typename T>
179SparseVectorView<T>::const_iterator::const_iterator(
180 const SparseVectorView<T>* view, bool at_end)
181 : view_(view) {
182 if (at_end) {
183 index_ = view_->ids_size();
184 }
185}
186
187template <typename T>
188typename SparseVectorView<T>::const_iterator::reference
190 return {view_->ids(index_), view_->values(index_)};
191}
192
193template <typename T>
198}
199
200template <typename T>
203 DCHECK_LT(index_, view_->ids_size());
204 ++index_;
205 return *this;
206}
207
208template <typename T>
210 const const_iterator& other) const {
211 DCHECK_EQ(view_, other.view_);
212 return index_ == other.index_;
213}
214
215template <typename T>
217 const const_iterator& other) const {
218 return !(*this == other);
219}
220
221template <typename T>
223 const {
224 DCHECK_EQ(ids_size(), values_size());
225 return const_iterator(this, /*at_end=*/false);
226}
227
228template <typename T>
230 DCHECK_EQ(ids_size(), values_size());
231 return const_iterator(this, /*at_end=*/true);
232}
233
234template <typename T>
235template <typename IndexType>
236absl::flat_hash_map<IndexType, T> SparseVectorView<T>::as_map() {
237 absl::flat_hash_map<IndexType, T> result;
238 CHECK_EQ(ids_size(), values_size());
239 result.reserve(ids_size());
240 for (const auto& [id, value] : *this) {
241 gtl::InsertOrDie(&result, IndexType(id), value);
242 }
243 return result;
244}
245
246} // namespace math_opt
247} // namespace operations_research
248
249#endif // OR_TOOLS_MATH_OPT_CORE_SPARSE_VECTOR_VIEW_H_
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:702
#define DCHECK_LT(val1, val2)
Definition: base/logging.h:893
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:890
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
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.
int index
Definition: pack.cc:509
std::optional< int64_t > end