OR-Tools  9.0
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_SPARSE_VECTOR_VIEW_H_
46 #define OR_TOOLS_MATH_OPT_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"
58 #include "ortools/base/logging.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
138 // other 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>.
146 // Common use for this overload is when T = std::string. See other overloads for
147 // other values-types.
148 template <typename T>
150  const google::protobuf::RepeatedField<int64_t>& ids,
151  const google::protobuf::RepeatedPtrField<T>& values) {
152  return SparseVectorView<const T*>(ids, values);
153 }
154 
155 // Returns a view for values in a SparseDoubleVectorProto, SparseBoolVectorProto
156 // or similar structure. For such cases, it is preferred over the two-argument
157 // overloads. See other overloads for other values-types.
158 template <typename SparseVectorProto,
159  typename T = sparse_value_type<SparseVectorProto>>
160 SparseVectorView<T> MakeView(const SparseVectorProto& sparse_vector) {
161  return SparseVectorView<T>(sparse_vector.ids(), sparse_vector.values());
162 }
163 
165 // Inline implementations
167 
168 template <typename T>
169 SparseVectorView<T>::const_iterator::const_iterator(
170  const SparseVectorView<T>* view, bool at_end)
171  : view_(view) {
172  if (at_end) {
173  index_ = view_->ids_size();
174  }
175 }
176 
177 template <typename T>
178 typename SparseVectorView<T>::const_iterator::value_type
180  return {view_->ids(index_), view_->values(index_)};
181 }
182 
183 template <typename T>
186  DCHECK_LT(index_, view_->ids_size());
187  ++index_;
188  return *this;
189 }
190 
191 template <typename T>
193  const const_iterator& other) const {
194  DCHECK_EQ(view_, other.view_);
195  return index_ != other.index_;
196 }
197 
198 template <typename T>
200  const {
201  DCHECK_EQ(ids_size(), values_size());
202  return const_iterator(this, /*at_end=*/false);
203 }
204 
205 template <typename T>
207  DCHECK_EQ(ids_size(), values_size());
208  return const_iterator(this, /*at_end=*/true);
209 }
210 
211 template <typename T>
212 template <typename IndexType>
213 absl::flat_hash_map<IndexType, T> SparseVectorView<T>::as_map() {
214  absl::flat_hash_map<IndexType, T> result;
215  CHECK_EQ(ids_size(), values_size());
216  result.reserve(ids_size());
217  for (const auto& [id, value] : *this) {
218  gtl::InsertOrDie(&result, IndexType(id), value);
219  }
220  return result;
221 }
222 
223 } // namespace math_opt
224 } // namespace operations_research
225 
226 #endif // OR_TOOLS_MATH_OPT_SPARSE_VECTOR_VIEW_H_
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:705
#define DCHECK_LT(val1, val2)
Definition: base/logging.h:896
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:893
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
int index
Definition: pack.cc:509