OR-Tools  9.1
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/sparse_containers.pb.h"
61
62namespace operations_research {
63namespace math_opt {
64
65// Recovers the values-type of a SparseVector type like SparseDoubleVector or
66// SparseBoolVector.
67template <typename SparseVector>
68using sparse_value_type = typename std::remove_reference<
69 decltype(SparseVector().values())>::type::value_type;
70
71// Abstracts sparse ids-values structures like SparseDoubleVector and mimics
72// its .ids()/.values() API. It additionally provides const range iterations
73// over the (id, value) pairs and conversion to a map.
74//
75// The returned iterators are proper STL forward iterators that can be used with
76// STL containers. For example to build a vector of pairs of values, one can
77// simply use the iterators:
78//
79// const auto view = MakeView(arg);
80// const std::vector v(view.begin(), view.end());
81//
82// Constructor SparseVectorView<T>(ids, values) will not check if ids and values
83// have the same length. However, iterator functions and .as_map() will CHECK
84// fail if ids and values do not have the same length.
85template <typename T>
87 public:
88 using value_type = std::pair<int64_t, T>;
89
91 public:
94 using pointer = void;
95 using const_pointer = void;
96 using difference_type = int;
97 using iterator_category = std::forward_iterator_tag;
98
99 value_type operator*() const;
101 bool operator!=(const const_iterator& other) const;
102
103 private:
104 friend class SparseVectorView;
105
106 inline explicit const_iterator(const SparseVectorView* view,
107 bool at_end = false);
108
109 const SparseVectorView* view_ = nullptr;
110 int index_ = 0;
111 };
112
113 SparseVectorView(absl::Span<const int64_t> ids, absl::Span<const T> values)
114 : ids_(std::move(ids)), values_(std::move(values)) {}
116
117 inline const_iterator begin() const;
118 inline const_iterator end() const;
119
120 absl::Span<const int64_t> ids() const { return ids_; }
121 int64_t ids(int index) const { return ids_[index]; }
122 int ids_size() const { return ids_.size(); }
123 absl::Span<const T> values() const { return values_; }
124 int values_size() const { return values_.size(); }
125 const T& values(int index) const { return values_[index]; }
126
127 // It should be possible to construct an IndexType from an integer
128 template <typename IndexType>
129 absl::flat_hash_map<IndexType, T> as_map();
130
131 private:
132 absl::Span<const int64_t> ids_;
133 absl::Span<const T> values_;
134};
135
136// Returns a view for values that are vector-like collection like
137// std::vector<T> or google::protobuf::RepeatedField<T>. See other overloads for other
138// values-types.
139template <typename Collection, typename T = typename Collection::value_type>
140SparseVectorView<T> MakeView(absl::Span<const int64_t> ids,
141 const Collection& values) {
142 return SparseVectorView<T>(ids, values);
143}
144
145// Returns a view for values that are google::protobuf::RepeatedPtrField<T>. Common use
146// for this overload is when T = std::string. See other overloads for other
147// values-types.
148template <typename T>
149SparseVectorView<const T*> MakeView(const google::protobuf::RepeatedField<int64_t>& ids,
150 const google::protobuf::RepeatedPtrField<T>& values) {
151 return SparseVectorView<const T*>(ids, values);
152}
153
154// Returns a view for values in a SparseDoubleVectorProto, SparseBoolVectorProto
155// or similar structure. For such cases, it is preferred over the two-argument
156// overloads. See other overloads for other values-types.
157template <typename SparseVectorProto,
158 typename T = sparse_value_type<SparseVectorProto>>
159SparseVectorView<T> MakeView(const SparseVectorProto& sparse_vector) {
160 return SparseVectorView<T>(sparse_vector.ids(), sparse_vector.values());
161}
162
164// Inline implementations
166
167template <typename T>
168SparseVectorView<T>::const_iterator::const_iterator(
169 const SparseVectorView<T>* view, bool at_end)
170 : view_(view) {
171 if (at_end) {
172 index_ = view_->ids_size();
173 }
174}
175
176template <typename T>
177typename SparseVectorView<T>::const_iterator::value_type
179 return {view_->ids(index_), view_->values(index_)};
180}
181
182template <typename T>
185 DCHECK_LT(index_, view_->ids_size());
186 ++index_;
187 return *this;
188}
189
190template <typename T>
192 const const_iterator& other) const {
193 DCHECK_EQ(view_, other.view_);
194 return index_ != other.index_;
195}
196
197template <typename T>
199 const {
200 DCHECK_EQ(ids_size(), values_size());
201 return const_iterator(this, /*at_end=*/false);
202}
203
204template <typename T>
206 DCHECK_EQ(ids_size(), values_size());
207 return const_iterator(this, /*at_end=*/true);
208}
209
210template <typename T>
211template <typename IndexType>
212absl::flat_hash_map<IndexType, T> SparseVectorView<T>::as_map() {
213 absl::flat_hash_map<IndexType, T> result;
214 CHECK_EQ(ids_size(), values_size());
215 result.reserve(ids_size());
216 for (const auto& [id, value] : *this) {
217 gtl::InsertOrDie(&result, IndexType(id), value);
218 }
219 return result;
220}
221
222} // namespace math_opt
223} // namespace operations_research
224
225#endif // OR_TOOLS_MATH_OPT_CORE_SPARSE_VECTOR_VIEW_H_
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:698
#define DCHECK_LT(val1, val2)
Definition: base/logging.h:889
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:886
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
bool operator!=(const STLCountingAllocator< T, A > &a, const STLCountingAllocator< T, A > &b)
Definition: stl_util.h:985
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)
Collection of objects used to extend the Constraint Solver library.
LinearExpr operator*(LinearExpr lhs, double rhs)
Definition: linear_expr.cc:154
STL namespace.
int index
Definition: pack.cc:509