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