OR-Tools  8.0
scattered_vector.h
Go to the documentation of this file.
1 // Copyright 2010-2018 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 #ifndef OR_TOOLS_LP_DATA_SCATTERED_VECTOR_H_
15 #define OR_TOOLS_LP_DATA_SCATTERED_VECTOR_H_
16 
17 #include <cmath>
18 #include <limits>
19 
21 #include "ortools/base/int_type.h"
23 #include "ortools/base/logging.h"
25 #include "ortools/util/bitset.h"
26 
27 namespace operations_research {
28 namespace glop {
29 
30 // A class representing an entry of a scattered vector. The i-th nonzero
31 // element of the vector is assumed to be located at indices[i] and its value is
32 // coefficients[indices[i]], i.e., coefficients is a dense array.
33 template <typename IndexType>
35  public:
36  using Index = IndexType;
37 
38  Index index() const { return index_[i_.value()]; }
40  return coefficient_[index_[i_.value()].value()];
41  }
42 
43  protected:
45  EntryIndex i)
46  : i_(i), index_(indices), coefficient_(coefficients) {}
47 
48  EntryIndex i_;
49  const Index* index_;
51 };
52 
53 // A simple struct that contains a DenseVector and its non-zero indices.
54 // TODO(user): This should be changed from struct to class.
55 template <typename Index,
56  typename Iterator = VectorIterator<ScatteredVectorEntry<Index>>>
59 
60  // This can be left empty in which case we just have the dense representation
61  // above. Otherwise, it should always be a superset of the actual non-zeros.
62  bool non_zeros_are_sorted = false;
63  std::vector<Index> non_zeros;
64 
65  // Temporary vector used in some sparse computation on the ScatteredVector.
66  // True indicates a possible non-zero value. Note that its state is not always
67  // consistent.
69 
70  // In many cases there is a choice between treating the ScatteredVector as
71  // dense or as sparse. By default, dense algorithms are used when the
72  // proportion of non-zero entries is greater than
73  // kDefaultRatioForUsingDenseIteration.
74  //
75  // TODO(user): The constant should depend on what algorithm is used. Clearing
76  // a dense vector is a lot more efficient than doing more complex stuff. Clean
77  // this up by extracting all the currently used constants in one place with
78  // meaningful names.
79  constexpr static const double kDefaultRatioForUsingDenseIteration = 0.8;
80 
83 
84  // The iterator syntax for (auto entry : v) where v is a ScatteredVector only
85  // works when non_zeros is populated (i.e., when the vector is treated as
86  // sparse).
87  Iterator begin() const {
88  DCHECK(!non_zeros.empty() || IsAllZero(values));
89  return Iterator(this->non_zeros.data(), this->values.data(), EntryIndex(0));
90  }
91  Iterator end() const {
92  return Iterator(this->non_zeros.data(), this->values.data(),
93  EntryIndex(non_zeros.size()));
94  }
95 
96  // Add the given value to the vector at position index. This interface
97  // encapsulates usage of the "is_non_zero" array, which should not be
98  // explicitly referenced outside of this struct.
100  values[index] += value;
101  if (!is_non_zero[index] && value != 0.0) {
102  is_non_zero[index] = true;
103  non_zeros.push_back(index);
104  non_zeros_are_sorted = false;
105  }
106  }
107 
108  // Sorting the non-zeros is not always needed, but it allows us to have
109  // exactly the same behavior while using a sparse iteration or a dense one. So
110  // we always do it after a Solve().
112  if (!non_zeros_are_sorted) {
113  std::sort(non_zeros.begin(), non_zeros.end());
114  non_zeros_are_sorted = true;
115  }
116  }
117 
118  // Returns true if it is more advantageous to use a dense iteration rather
119  // than using the non-zeros positions.
121  double ratio_for_using_dense_representation) const {
122  if (non_zeros.empty()) return true;
123  return static_cast<double>(non_zeros.size()) >
124  ratio_for_using_dense_representation *
125  static_cast<double>(values.size().value());
126  }
127 
128  bool ShouldUseDenseIteration() const {
130  }
131 
132  // Efficiently clears the is_non_zero vector.
134  if (ShouldUseDenseIteration()) {
135  is_non_zero.assign(values.size(), false);
136  } else {
137  is_non_zero.resize(values.size(), false);
138  for (const Index index : non_zeros) {
139  is_non_zero[index] = false;
140  }
141  DCHECK(IsAllFalse(is_non_zero));
142  }
143  }
144 
145  // Update the is_non_zero vector to be consistent with the non_zeros vector.
147  ClearSparseMask();
148  for (const Index index : non_zeros) is_non_zero[index] = true;
149  }
150 
151  // If the proportion of non-zero entries is too large, clears the vector of
152  // non-zeros.
153  void ClearNonZerosIfTooDense(double ratio_for_using_dense_representation) {
154  if (ShouldUseDenseIteration(ratio_for_using_dense_representation)) {
155  ClearSparseMask();
156  non_zeros.clear();
157  }
158  }
159 
162  }
163 };
164 
165 // Specializations used in the code.
166 class ScatteredColumnEntry : public ScatteredVectorEntry<RowIndex> {
167  public:
168  // Returns the row of the current entry.
169  RowIndex row() const { return index(); }
170 
171  protected:
172  ScatteredColumnEntry(const RowIndex* indices, const Fractional* coefficients,
173  EntryIndex i)
174  : ScatteredVectorEntry<RowIndex>(indices, coefficients, i) {}
175 };
176 
177 class ScatteredRowEntry : public ScatteredVectorEntry<ColIndex> {
178  public:
179  // Returns the column of the current entry.
180  ColIndex column() const { return index(); }
181 
182  protected:
183  ScatteredRowEntry(const ColIndex* indices, const Fractional* coefficients,
184  EntryIndex i)
185  : ScatteredVectorEntry<ColIndex>(indices, coefficients, i) {}
186 };
187 
190 
192  : public ScatteredVector<RowIndex, ScatteredColumnIterator> {};
193 struct ScatteredRow : public ScatteredVector<ColIndex, ScatteredRowIterator> {};
194 
195 inline const ScatteredRow& TransposedView(const ScatteredColumn& c) {
196  return reinterpret_cast<const ScatteredRow&>(c);
197 }
198 inline const ScatteredColumn& TransposedView(const ScatteredRow& r) {
199  return reinterpret_cast<const ScatteredColumn&>(r);
200 }
201 
202 } // namespace glop
203 } // namespace operations_research
204 
205 #endif // OR_TOOLS_LP_DATA_SCATTERED_VECTOR_H_
operations_research::glop::ScatteredVectorEntry::index_
const Index * index_
Definition: scattered_vector.h:49
operations_research::glop::ScatteredVector::ClearNonZerosIfTooDense
void ClearNonZerosIfTooDense()
Definition: scattered_vector.h:160
operations_research::glop::ScatteredColumnEntry::row
RowIndex row() const
Definition: scattered_vector.h:169
operations_research::glop::ScatteredVector::operator[]
Fractional & operator[](Index index)
Definition: scattered_vector.h:82
operations_research::glop::ScatteredVector::ClearNonZerosIfTooDense
void ClearNonZerosIfTooDense(double ratio_for_using_dense_representation)
Definition: scattered_vector.h:153
coefficients
std::vector< double > coefficients
Definition: sat/lp_utils.cc:287
operations_research::glop::ScatteredVector::ClearSparseMask
void ClearSparseMask()
Definition: scattered_vector.h:133
operations_research::glop::ScatteredVector::end
Iterator end() const
Definition: scattered_vector.h:91
operations_research::glop::ScatteredVector
Definition: scattered_vector.h:57
operations_research::glop::StrictITIVector< Index, Fractional >
operations_research::glop::IsAllFalse
bool IsAllFalse(const BoolVector &v)
Definition: lp_data/lp_utils.h:231
logging.h
operations_research::glop::StrictITIVector::assign
void assign(IntType size, const T &v)
Definition: lp_types.h:274
value
int64 value
Definition: demon_profiler.cc:43
operations_research::glop::ScatteredVector::begin
Iterator begin() const
Definition: scattered_vector.h:87
operations_research::glop::ScatteredVectorEntry
Definition: scattered_vector.h:34
operations_research::glop::ScatteredVector::ShouldUseDenseIteration
bool ShouldUseDenseIteration(double ratio_for_using_dense_representation) const
Definition: scattered_vector.h:120
operations_research::glop::ScatteredVector::non_zeros
std::vector< Index > non_zeros
Definition: scattered_vector.h:63
operations_research
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...
Definition: dense_doubly_linked_list.h:21
operations_research::glop::ScatteredVectorEntry::i_
EntryIndex i_
Definition: scattered_vector.h:48
operations_research::glop::ScatteredColumn
Definition: scattered_vector.h:192
operations_research::glop::StrictITIVector::resize
void resize(IntType size)
Definition: lp_types.h:269
operations_research::glop::ScatteredVectorEntry::coefficient
Fractional coefficient() const
Definition: scattered_vector.h:39
operations_research::glop::ScatteredRowEntry::ScatteredRowEntry
ScatteredRowEntry(const ColIndex *indices, const Fractional *coefficients, EntryIndex i)
Definition: scattered_vector.h:183
index
int index
Definition: pack.cc:508
operations_research::glop::ScatteredRowEntry
Definition: scattered_vector.h:177
operations_research::glop::ScatteredRowEntry::column
ColIndex column() const
Definition: scattered_vector.h:180
operations_research::glop::Fractional
double Fractional
Definition: lp_types.h:77
operations_research::glop::ScatteredVectorEntry::index
Index index() const
Definition: scattered_vector.h:38
operations_research::glop::ScatteredVector::is_non_zero
StrictITIVector< Index, bool > is_non_zero
Definition: scattered_vector.h:68
operations_research::glop::ScatteredVector::RepopulateSparseMask
void RepopulateSparseMask()
Definition: scattered_vector.h:146
operations_research::glop::ScatteredColumnEntry::ScatteredColumnEntry
ScatteredColumnEntry(const RowIndex *indices, const Fractional *coefficients, EntryIndex i)
Definition: scattered_vector.h:172
int_type.h
operations_research::glop::StrictITIVector::size
IntType size() const
Definition: lp_types.h:276
operations_research::glop::ScatteredRow
Definition: scattered_vector.h:193
operations_research::glop::ScatteredVector::values
StrictITIVector< Index, Fractional > values
Definition: scattered_vector.h:58
int_type_indexed_vector.h
operations_research::glop::ScatteredVector::non_zeros_are_sorted
bool non_zeros_are_sorted
Definition: scattered_vector.h:62
basictypes.h
operations_research::glop::ScatteredVector::kDefaultRatioForUsingDenseIteration
constexpr static const double kDefaultRatioForUsingDenseIteration
Definition: scattered_vector.h:79
operations_research::glop::TransposedView
const ScatteredRow & TransposedView(const ScatteredColumn &c)
Definition: scattered_vector.h:195
operations_research::glop::ScatteredVector::ShouldUseDenseIteration
bool ShouldUseDenseIteration() const
Definition: scattered_vector.h:128
operations_research::glop::VectorIterator
Definition: lp_types.h:356
operations_research::glop::ScatteredVectorEntry::coefficient_
const Fractional * coefficient_
Definition: scattered_vector.h:50
operations_research::glop::ScatteredColumnEntry
Definition: scattered_vector.h:166
operations_research::glop::ScatteredVector::Add
void Add(Index index, Fractional value)
Definition: scattered_vector.h:99
operations_research::glop::Index
int32 Index
Definition: lp_types.h:37
operations_research::glop::IsAllZero
bool IsAllZero(const Container &input)
Definition: lp_data/lp_utils.h:222
operations_research::glop::ScatteredVector::SortNonZerosIfNeeded
void SortNonZerosIfNeeded()
Definition: scattered_vector.h:111
lp_types.h
operations_research::glop::ScatteredVectorEntry::ScatteredVectorEntry
ScatteredVectorEntry(const Index *indices, const Fractional *coefficients, EntryIndex i)
Definition: scattered_vector.h:44
operations_research::glop::ScatteredVector::operator[]
Fractional operator[](Index index) const
Definition: scattered_vector.h:81
bitset.h