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 
55 #include "ortools/base/logging.h"
56 #include "google/protobuf/message.h"
57 #include "absl/container/flat_hash_map.h"
58 #include "absl/types/span.h"
59 #include "ortools/base/map_util.h"
60 #include "ortools/math_opt/sparse_containers.pb.h"
61 
62 namespace operations_research {
63 namespace math_opt {
64 
65 // Recovers the values-type of a SparseVector type like SparseDoubleVector or
66 // SparseBoolVector.
67 template <typename SparseVector>
68 using 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.
85 template <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.
139 template <typename Collection, typename T = typename Collection::value_type>
140 SparseVectorView<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.
148 template <typename T>
149 SparseVectorView<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.
157 template <typename SparseVectorProto,
158  typename T = sparse_value_type<SparseVectorProto>>
159 SparseVectorView<T> MakeView(const SparseVectorProto& sparse_vector) {
160  return SparseVectorView<T>(sparse_vector.ids(), sparse_vector.values());
161 }
162 
164 // Inline implementations
166 
167 template <typename T>
168 SparseVectorView<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 
176 template <typename T>
177 typename SparseVectorView<T>::const_iterator::value_type
179  return {view_->ids(index_), view_->values(index_)};
180 }
181 
182 template <typename T>
185  DCHECK_LT(index_, view_->ids_size());
186  ++index_;
187  return *this;
188 }
189 
190 template <typename T>
192  const const_iterator& other) const {
193  DCHECK_EQ(view_, other.view_);
194  return index_ != other.index_;
195 }
196 
197 template <typename T>
199  const {
200  DCHECK_EQ(ids_size(), values_size());
201  return const_iterator(this, /*at_end=*/false);
202 }
203 
204 template <typename T>
206  DCHECK_EQ(ids_size(), values_size());
207  return const_iterator(this, /*at_end=*/true);
208 }
209 
210 template <typename T>
211 template <typename IndexType>
212 absl::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_
absl::Span< const int64_t > ids() const
SparseVectorView< T > MakeView(absl::Span< const int64_t > ids, const Collection &values)
absl::flat_hash_map< IndexType, T > as_map()
void InsertOrDie(Collection *const collection, const typename Collection::value_type &value)
Definition: map_util.h:154
SparseVectorView(absl::Span< const int64_t > ids, absl::Span< const T > values)
LinearExpr operator *(LinearExpr lhs, double rhs)
Definition: linear_expr.cc:154
bool operator!=(const STLCountingAllocator< T, A > &a, const STLCountingAllocator< T, A > &b)
Definition: stl_util.h:985
int index
Definition: pack.cc:509
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:698
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:886
Collection of objects used to extend the Constraint Solver library.
int64_t value
typename std::remove_reference< decltype(SparseVector().values())>::type::value_type sparse_value_type
#define DCHECK_LT(val1, val2)
Definition: base/logging.h:889