blob: 0a1b945193d275a6d2a211de567532012106be06 [file] [log] [blame]
Austin Schuh70cc9552019-01-21 19:46:48 -08001// Ceres Solver - A fast non-linear least squares minimizer
2// Copyright 2015 Google Inc. All rights reserved.
3// http://ceres-solver.org/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are met:
7//
8// * Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13// * Neither the name of Google Inc. nor the names of its contributors may be
14// used to endorse or promote products derived from this software without
15// specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27// POSSIBILITY OF SUCH DAMAGE.
28//
29// Author: sameeragarwal@google.com (Sameer Agarwal)
30
31#ifndef CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_
32#define CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_
33
34#include <vector>
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080035
Austin Schuh70cc9552019-01-21 19:46:48 -080036#include "ceres/internal/port.h"
37#include "ceres/sparse_matrix.h"
38#include "ceres/types.h"
39#include "glog/logging.h"
40
41namespace ceres {
42
43struct CRSMatrix;
44
45namespace internal {
46
47class TripletSparseMatrix;
48
Austin Schuh1d1e6ea2020-12-23 21:56:30 -080049class CERES_EXPORT_INTERNAL CompressedRowSparseMatrix : public SparseMatrix {
Austin Schuh70cc9552019-01-21 19:46:48 -080050 public:
51 enum StorageType {
52 UNSYMMETRIC,
53 // Matrix is assumed to be symmetric but only the lower triangular
54 // part of the matrix is stored.
55 LOWER_TRIANGULAR,
56 // Matrix is assumed to be symmetric but only the upper triangular
57 // part of the matrix is stored.
58 UPPER_TRIANGULAR
59 };
60
61 // Create a matrix with the same content as the TripletSparseMatrix
62 // input. We assume that input does not have any repeated
63 // entries.
64 //
65 // The storage type of the matrix is set to UNSYMMETRIC.
66 //
67 // Caller owns the result.
68 static CompressedRowSparseMatrix* FromTripletSparseMatrix(
69 const TripletSparseMatrix& input);
70
71 // Create a matrix with the same content as the TripletSparseMatrix
72 // input transposed. We assume that input does not have any repeated
73 // entries.
74 //
75 // The storage type of the matrix is set to UNSYMMETRIC.
76 //
77 // Caller owns the result.
78 static CompressedRowSparseMatrix* FromTripletSparseMatrixTransposed(
79 const TripletSparseMatrix& input);
80
81 // Use this constructor only if you know what you are doing. This
82 // creates a "blank" matrix with the appropriate amount of memory
83 // allocated. However, the object itself is in an inconsistent state
84 // as the rows and cols matrices do not match the values of
85 // num_rows, num_cols and max_num_nonzeros.
86 //
87 // The use case for this constructor is that when the user knows the
88 // size of the matrix to begin with and wants to update the layout
89 // manually, instead of going via the indirect route of first
90 // constructing a TripletSparseMatrix, which leads to more than
91 // double the peak memory usage.
92 //
93 // The storage type is set to UNSYMMETRIC.
94 CompressedRowSparseMatrix(int num_rows, int num_cols, int max_num_nonzeros);
95
96 // Build a square sparse diagonal matrix with num_rows rows and
97 // columns. The diagonal m(i,i) = diagonal(i);
98 //
99 // The storage type is set to UNSYMMETRIC
100 CompressedRowSparseMatrix(const double* diagonal, int num_rows);
101
102 // SparseMatrix interface.
103 virtual ~CompressedRowSparseMatrix();
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800104 void SetZero() final;
105 void RightMultiply(const double* x, double* y) const final;
106 void LeftMultiply(const double* x, double* y) const final;
107 void SquaredColumnNorm(double* x) const final;
108 void ScaleColumns(const double* scale) final;
109 void ToDenseMatrix(Matrix* dense_matrix) const final;
110 void ToTextFile(FILE* file) const final;
111 int num_rows() const final { return num_rows_; }
112 int num_cols() const final { return num_cols_; }
113 int num_nonzeros() const final { return rows_[num_rows_]; }
114 const double* values() const final { return &values_[0]; }
115 double* mutable_values() final { return &values_[0]; }
Austin Schuh70cc9552019-01-21 19:46:48 -0800116
117 // Delete the bottom delta_rows.
118 // num_rows -= delta_rows
119 void DeleteRows(int delta_rows);
120
121 // Append the contents of m to the bottom of this matrix. m must
122 // have the same number of columns as this matrix.
123 void AppendRows(const CompressedRowSparseMatrix& m);
124
125 void ToCRSMatrix(CRSMatrix* matrix) const;
126
127 CompressedRowSparseMatrix* Transpose() const;
128
129 // Destructive array resizing method.
130 void SetMaxNumNonZeros(int num_nonzeros);
131
132 // Non-destructive array resizing method.
133 void set_num_rows(const int num_rows) { num_rows_ = num_rows; }
134 void set_num_cols(const int num_cols) { num_cols_ = num_cols; }
135
136 // Low level access methods that expose the structure of the matrix.
137 const int* cols() const { return &cols_[0]; }
138 int* mutable_cols() { return &cols_[0]; }
139
140 const int* rows() const { return &rows_[0]; }
141 int* mutable_rows() { return &rows_[0]; }
142
143 const StorageType storage_type() const { return storage_type_; }
144 void set_storage_type(const StorageType storage_type) {
145 storage_type_ = storage_type;
146 }
147
148 const std::vector<int>& row_blocks() const { return row_blocks_; }
149 std::vector<int>* mutable_row_blocks() { return &row_blocks_; }
150
151 const std::vector<int>& col_blocks() const { return col_blocks_; }
152 std::vector<int>* mutable_col_blocks() { return &col_blocks_; }
153
154 // Create a block diagonal CompressedRowSparseMatrix with the given
155 // block structure. The individual blocks are assumed to be laid out
156 // contiguously in the diagonal array, one block at a time.
157 //
158 // Caller owns the result.
159 static CompressedRowSparseMatrix* CreateBlockDiagonalMatrix(
160 const double* diagonal, const std::vector<int>& blocks);
161
162 // Options struct to control the generation of random block sparse
163 // matrices in compressed row sparse format.
164 //
165 // The random matrix generation proceeds as follows.
166 //
167 // First the row and column block structure is determined by
168 // generating random row and column block sizes that lie within the
169 // given bounds.
170 //
171 // Then we walk the block structure of the resulting matrix, and with
172 // probability block_density detemine whether they are structurally
173 // zero or not. If the answer is no, then we generate entries for the
174 // block which are distributed normally.
175 struct RandomMatrixOptions {
176 // Type of matrix to create.
177 //
178 // If storage_type is UPPER_TRIANGULAR (LOWER_TRIANGULAR), then
179 // create a square symmetric matrix with just the upper triangular
180 // (lower triangular) part. In this case, num_col_blocks,
181 // min_col_block_size and max_col_block_size will be ignored and
182 // assumed to be equal to the corresponding row settings.
183 StorageType storage_type = UNSYMMETRIC;
184
185 int num_row_blocks = 0;
186 int min_row_block_size = 0;
187 int max_row_block_size = 0;
188 int num_col_blocks = 0;
189 int min_col_block_size = 0;
190 int max_col_block_size = 0;
191
192 // 0 < block_density <= 1 is the probability of a block being
193 // present in the matrix. A given random matrix will not have
194 // precisely this density.
195 double block_density = 0.0;
196 };
197
198 // Create a random CompressedRowSparseMatrix whose entries are
199 // normally distributed and whose structure is determined by
200 // RandomMatrixOptions.
201 //
202 // Caller owns the result.
203 static CompressedRowSparseMatrix* CreateRandomMatrix(
204 RandomMatrixOptions options);
205
206 private:
207 static CompressedRowSparseMatrix* FromTripletSparseMatrix(
208 const TripletSparseMatrix& input, bool transpose);
209
210 int num_rows_;
211 int num_cols_;
212 std::vector<int> rows_;
213 std::vector<int> cols_;
214 std::vector<double> values_;
215 StorageType storage_type_;
216
217 // If the matrix has an underlying block structure, then it can also
218 // carry with it row and column block sizes. This is auxilliary and
219 // optional information for use by algorithms operating on the
220 // matrix. The class itself does not make use of this information in
221 // any way.
222 std::vector<int> row_blocks_;
223 std::vector<int> col_blocks_;
224};
225
226} // namespace internal
227} // namespace ceres
228
229#endif // CERES_INTERNAL_COMPRESSED_ROW_SPARSE_MATRIX_H_