OR-Tools  9.6
sparse_column.h
Go to the documentation of this file.
1 // Copyright 2010-2022 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_SPARSE_COLUMN_H_
15 #define OR_TOOLS_LP_DATA_SPARSE_COLUMN_H_
16 
17 #include <vector>
18 
20 
21 namespace operations_research {
22 namespace glop {
23 
24 // TODO(user): Consider using kInvalidRow for this?
25 const RowIndex kNonPivotal(-1);
26 
27 // Specialization of SparseVectorEntry and SparseColumnIterator for the
28 // SparseColumn class. In addition to index(), it also provides row() for better
29 // readability on the client side.
30 class SparseColumnEntry : public SparseVectorEntry<RowIndex> {
31  public:
32  // Returns the row of the current entry.
33  RowIndex row() const { return index(); }
34 
35  protected:
36  SparseColumnEntry(const RowIndex* indices, const Fractional* coefficients,
37  EntryIndex i)
38  : SparseVectorEntry<RowIndex>(indices, coefficients, i) {}
39 };
41 
42 class ColumnView;
43 
44 // A SparseColumn is a SparseVector<RowIndex>, with a few methods renamed
45 // to help readability on the client side.
46 class SparseColumn : public SparseVector<RowIndex, SparseColumnIterator> {
47  friend class ColumnView;
48 
49  public:
51 
52  // Use a separate API to get the row and coefficient of entry #i.
53  RowIndex EntryRow(EntryIndex i) const { return GetIndex(i); }
54  Fractional EntryCoefficient(EntryIndex i) const { return GetCoefficient(i); }
55  RowIndex GetFirstRow() const { return GetFirstIndex(); }
56  RowIndex GetLastRow() const { return GetLastIndex(); }
59  }
62  }
63 };
64 
65 // Class to iterate on the entries of a given column with the same interface
66 // as for SparseColumn.
67 class ColumnView {
68  public:
69  // Clients should pass Entry by value rather than by reference.
70  // This is because SparseColumnEntry is small (2 pointers and an index) and
71  // previous profiling of this type of use showed no performance penalty
72  // (see cl/51057736).
73  // Example: for(const Entry e : column_view)
76 
77  ColumnView(EntryIndex num_entries, const RowIndex* rows,
78  const Fractional* const coefficients)
79  : num_entries_(num_entries), rows_(rows), coefficients_(coefficients) {}
80  explicit ColumnView(const SparseColumn& column)
81  : num_entries_(column.num_entries()),
82  rows_(column.index_),
83  coefficients_(column.coefficient_) {}
84  EntryIndex num_entries() const { return num_entries_; }
85  Fractional EntryCoefficient(EntryIndex i) const {
86  return coefficients_[i.value()];
87  }
89  return EntryCoefficient(EntryIndex(0));
90  }
91  RowIndex EntryRow(EntryIndex i) const { return rows_[i.value()]; }
92  RowIndex GetFirstRow() const { return EntryRow(EntryIndex(0)); }
93 
94  Iterator begin() const {
95  return Iterator(this->rows_, this->coefficients_, EntryIndex(0));
96  }
97 
98  Iterator end() const {
99  return Iterator(this->rows_, this->coefficients_, num_entries_);
100  }
101 
103  Fractional value(0.0);
104  for (const auto e : *this) {
105  if (e.row() == index) {
106  // Keep in mind the vector may contains several entries with the same
107  // index. In such a case the last one is returned.
108  // TODO(user): investigate whether an optimized version of
109  // LookUpCoefficient for "clean" columns yields speed-ups.
110  value = e.coefficient();
111  }
112  }
113  return value;
114  }
115 
116  bool IsEmpty() const { return num_entries_ == EntryIndex(0); }
117 
118  private:
119  const EntryIndex num_entries_;
120  const RowIndex* const rows_;
121  const Fractional* const coefficients_;
122 };
123 
124 // --------------------------------------------------------
125 // RandomAccessSparseColumn
126 // --------------------------------------------------------
127 // A RandomAccessSparseColumn is a mix between a DenseColumn and a SparseColumn.
128 // It makes it possible to populate a dense column from a sparse column in
129 // O(num_entries) instead of O(num_rows), and to access an entry in O(1).
130 // As the constructor runs in O(num_rows), a RandomAccessSparseColumn should be
131 // used several times to amortize the creation cost.
133  public:
134  // Creates a RandomAccessSparseColumn.
135  // Runs in O(num_rows).
136  explicit RandomAccessSparseColumn(RowIndex num_rows);
137  virtual ~RandomAccessSparseColumn();
138 
139  // Clears the column.
140  // Runs in O(num_entries).
141  void Clear();
142 
143  void Resize(RowIndex num_rows);
144 
145  // Sets value at row.
146  // Runs in O(1).
147  void SetCoefficient(RowIndex row, Fractional value) {
148  column_[row] = value;
149  MarkRowAsChanged(row);
150  }
151 
152  // Adds value to the current value at row.
153  // Runs in O(1).
155  column_[row] += value;
156  MarkRowAsChanged(row);
157  }
158 
159  // Populates from a sparse column.
160  // Runs in O(num_entries).
161  void PopulateFromSparseColumn(const SparseColumn& sparse_column);
162 
163  // Populates a sparse column from the lazy dense column.
164  // Runs in O(num_entries).
165  void PopulateSparseColumn(SparseColumn* sparse_column) const;
166 
167  // Returns the number of rows.
168  // Runs in O(1).
169  RowIndex GetNumberOfRows() const { return RowIndex(column_.size()); }
170 
171  // Returns the value in position row.
172  // Runs in O(1).
173  Fractional GetCoefficient(RowIndex row) const { return column_[row]; }
174 
175  private:
176  // Keeps a trace of which rows have been changed.
177  void MarkRowAsChanged(RowIndex row) {
178  if (!changed_[row]) {
179  changed_[row] = true;
180  row_change_.push_back(row);
181  }
182  }
183 
184  // The dense version of the column.
185  DenseColumn column_;
186 
187  // Dense Boolean vector used to mark changes.
188  DenseBooleanColumn changed_;
189 
190  // Stack to store changes.
191  std::vector<RowIndex> row_change_;
192 
193  DISALLOW_COPY_AND_ASSIGN(RandomAccessSparseColumn);
194 };
195 
196 } // namespace glop
197 } // namespace operations_research
198 
199 #endif // OR_TOOLS_LP_DATA_SPARSE_COLUMN_H_
ColumnView(EntryIndex num_entries, const RowIndex *rows, const Fractional *const coefficients)
Definition: sparse_column.h:77
Fractional LookUpCoefficient(RowIndex index) const
VectorIterator< Entry > Iterator
Definition: sparse_column.h:75
Fractional EntryCoefficient(EntryIndex i) const
Definition: sparse_column.h:85
ColumnView(const SparseColumn &column)
Definition: sparse_column.h:80
RowIndex EntryRow(EntryIndex i) const
Definition: sparse_column.h:91
void AddToCoefficient(RowIndex row, Fractional value)
void PopulateSparseColumn(SparseColumn *sparse_column) const
void PopulateFromSparseColumn(const SparseColumn &sparse_column)
void SetCoefficient(RowIndex row, Fractional value)
Definition: sparse_column.h:30
SparseColumnEntry(const RowIndex *indices, const Fractional *coefficients, EntryIndex i)
Definition: sparse_column.h:36
RowIndex row() const
Definition: sparse_column.h:33
void ApplyRowPermutation(const RowPermutation &p)
Definition: sparse_column.h:57
void ApplyPartialRowPermutation(const RowPermutation &p)
Definition: sparse_column.h:60
Fractional EntryCoefficient(EntryIndex i) const
Definition: sparse_column.h:54
RowIndex EntryRow(EntryIndex i) const
Definition: sparse_column.h:53
Index index() const
int64_t value
absl::Span< const double > coefficients
int index
RowIndex row
Definition: markowitz.cc:185
const RowIndex kNonPivotal(-1)
StrictITIVector< RowIndex, Fractional > DenseColumn
Definition: lp_types.h:370
StrictITIVector< RowIndex, bool > DenseBooleanColumn
Definition: lp_types.h:373
Collection of objects used to extend the Constraint Solver library.
int column
Definition: parse_proto.cc:32