Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
sparse_vector_view.h
Go to the documentation of this file.
1// Copyright 2010-2024 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"
59#include "ortools/base/types.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)) {}
119 SparseVectorView() = default;
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 // Returns the map corresponding to this sparse vector.
132 //
133 // It should be possible to construct KeyType::IdType from an int64_t and
134 // KeyType from a Storage pointer and the build id. See cpp/key_types.h for
135 // details.
136 template <typename KeyType, typename Storage>
137 absl::flat_hash_map<KeyType, T> as_map(const Storage* storage);
138
139 private:
140 absl::Span<const int64_t> ids_;
141 absl::Span<const T> values_;
142};
143
144// Returns a view for values that are vector-like collection like
145// std::vector<T> or google::protobuf::RepeatedField<T>. See other overloads for
146// other values-types.
147template <typename Collection, typename T = typename Collection::value_type>
148SparseVectorView<T> MakeView(absl::Span<const int64_t> ids,
149 const Collection& values) {
150 return SparseVectorView<T>(ids, values);
151}
152
153// Returns a view for values that are google::protobuf::RepeatedPtrField<T>.
154// Common use for this overload is when T = std::string. See other overloads for
155// other values-types.
156template <typename T>
158 const google::protobuf::RepeatedField<int64_t>& ids,
159 const google::protobuf::RepeatedPtrField<T>& values) {
160 return SparseVectorView<const T*>(ids, values);
161}
162
163// Returns a view for values in a SparseDoubleVectorProto, SparseBoolVectorProto
164// or similar structure. For such cases, it is preferred over the two-argument
165// overloads. See other overloads for other values-types.
166template <typename SparseVectorProto,
168SparseVectorView<T> MakeView(const SparseVectorProto& sparse_vector) {
169 return SparseVectorView<T>(sparse_vector.ids(), sparse_vector.values());
170}
171
172// Returns a view for values in a SparseVector. For this case it is preferred
173// over the two-argument overloads. See other overloads for other values-types.
174template <typename T>
176 return SparseVectorView<T>(sparse_vector.ids, sparse_vector.values);
177}
178
180// Inline implementations
182
183template <typename T>
184SparseVectorView<T>::const_iterator::const_iterator(
185 const SparseVectorView<T>* view, bool at_end)
186 : view_(view) {
187 if (at_end) {
188 index_ = view_->ids_size();
189 }
190}
191
192template <typename T>
193typename SparseVectorView<T>::const_iterator::reference
194SparseVectorView<T>::const_iterator::operator*() const {
195 return {view_->ids(index_), view_->values(index_)};
197
198template <typename T>
204
205template <typename T>
208 DCHECK_LT(index_, view_->ids_size());
209 ++index_;
210 return *this;
211}
212
213template <typename T>
215 const const_iterator& other) const {
216 DCHECK_EQ(view_, other.view_);
217 return index_ == other.index_;
218}
219
220template <typename T>
222 const const_iterator& other) const {
223 return !(*this == other);
224}
225
226template <typename T>
228 const {
229 DCHECK_EQ(ids_size(), values_size());
230 return const_iterator(this, /*at_end=*/false);
231}
232
233template <typename T>
235 DCHECK_EQ(ids_size(), values_size());
236 return const_iterator(this, /*at_end=*/true);
237}
238
239template <typename T>
240template <typename KeyType, typename Storage>
241absl::flat_hash_map<KeyType, T> SparseVectorView<T>::as_map(
242 const Storage* storage) {
243 absl::flat_hash_map<KeyType, T> result;
244 CHECK_EQ(ids_size(), values_size());
245 result.reserve(ids_size());
246 for (const auto& [id, value] : *this) {
247 gtl::InsertOrDie(&result, KeyType(storage, typename KeyType::IdType(id)),
248 value);
249 }
250 return result;
251}
252
253} // namespace math_opt
254} // namespace operations_research
255
256#endif // OR_TOOLS_MATH_OPT_CORE_SPARSE_VECTOR_VIEW_H_
internal::ArrowOperatorProxy< reference > operator->() const
absl::flat_hash_map< KeyType, T > as_map(const Storage *storage)
SparseVectorView(absl::Span< const int64_t > ids, absl::Span< const T > values)
int64_t value
int index
void InsertOrDie(Collection *const collection, const typename Collection::value_type &value)
Definition map_util.h:159
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)
In SWIG mode, we don't want anything besides these top-level includes.
STL namespace.
std::vector< int64_t > ids
Should be sorted (in increasing order) with all elements distinct.
std::vector< T > values
Must have equal length to ids.