g2o
Loading...
Searching...
No Matches
csparse_wrapper.cpp
Go to the documentation of this file.
1// g2o - General Graph Optimization
2// Copyright (C) 2011 R. Kuemmerle, G. Grisetti, W. Burgard
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright notice,
10// this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27#include "csparse_wrapper.h"
28
29#include <cassert>
30#include <cstddef>
31#include <cstring>
32#include <memory>
33
34#include "csparse_extension.h"
35#include "csparse_helper.h"
37
38namespace g2o {
39namespace csparse {
40
44struct CSparseExt : public cs {
46 nzmax = 0;
47 m = 0;
48 n = 0;
49 p = 0;
50 i = 0;
51 x = 0;
52 nz = -1; // tag as CCS formatted matrix
53 }
54 CSparseExt(CSparseExt const&) = delete;
55 CSparseExt& operator=(CSparseExt const&) = delete;
57 delete[] p;
58 delete[] i;
59 delete[] x;
60 }
62};
63
68 public:
69 Impl() = default;
72 cs_sfree(symbolicDecomposition);
73 symbolicDecomposition = nullptr;
74 }
75 if (numericCholesky) {
76 cs_nfree(numericCholesky);
77 numericCholesky = nullptr;
78 }
79 delete[] csWorkspace;
80 csWorkspace = nullptr;
81 delete[] csIntWorkspace;
82 csIntWorkspace = nullptr;
83 }
84
86 // re-allocate the temporary workspace for cholesky
87 if (csWorkspaceSize < ccsA.n) {
88 csWorkspaceSize = csWorkspaceSize == 0 ? ccsA.n : 2 * ccsA.n;
89 delete[] csWorkspace;
90 csWorkspace = new double[csWorkspaceSize];
91 delete[] csIntWorkspace;
92 csIntWorkspace = new int[2 * csWorkspaceSize];
93 }
94 }
95
96 css* symbolicDecomposition = nullptr;
98 double* csWorkspace = nullptr;
99 int* csIntWorkspace = nullptr;
100 csn* numericCholesky = nullptr;
102};
103
104CSparse::CSparse() : pImpl(std::make_unique<Impl>()) {}
105
106CSparse::~CSparse() = default;
107
109 if (pImpl->numericCholesky) {
110 cs_nfree(pImpl->numericCholesky);
111 pImpl->numericCholesky = nullptr;
112 }
113}
114
115bool CSparse::hasFactor() const { return pImpl->numericCholesky != nullptr; }
116
117bool CSparse::amd(const SparseView& sparseView, VectorXI& result) {
118 // prepare block structure for the CSparse call
119 cs auxBlock;
120 auxBlock.nzmax = sparseView.nzmax;
121 auxBlock.m = sparseView.m;
122 auxBlock.n = sparseView.n;
123 auxBlock.p = sparseView.p;
124 auxBlock.i = sparseView.i;
125 auxBlock.x = NULL; // no values
126 auxBlock.nz = -1; // CCS format
127
128 // AMD ordering on the block structure
129 int* permutation = cs_amd(1, &auxBlock);
130 if (!permutation) return false;
131 result.resize(auxBlock.m);
132 VectorXI::ConstMapType permutation_map(permutation, result.size());
133 result = permutation_map;
134 cs_free(permutation);
135 return true;
136}
137
139 CSparseExt& sparse = pImpl->ccsA;
140 return CSparse::SparseView(sparse.m, sparse.n, sparse.nzmax, sparse.p,
141 sparse.i, sparse.x, sparse.columnsAllocated);
142}
143
145 csn* factor = pImpl->numericCholesky;
146 return CSparse::FactorView(factor->L->n, factor->L->p, factor->L->i,
147 factor->L->x, pImpl->symbolicDecomposition->pinv);
148}
149
150bool CSparse::solve(double* x, double* b) const {
151 pImpl->prepareWorkspace();
152
153 if (x != b) memcpy(x, b, pImpl->ccsA.n * sizeof(double));
155 &pImpl->ccsA, x, pImpl->symbolicDecomposition, pImpl->csWorkspace,
156 pImpl->csIntWorkspace);
157 return static_cast<bool>(ok);
158}
159
161 freeSymbolic();
162 pImpl->symbolicDecomposition = cs_schol(1, &pImpl->ccsA);
163 return pImpl->symbolicDecomposition != nullptr;
164}
165
166bool CSparse::analyze_p(int* permutation) {
167 freeSymbolic();
168 pImpl->symbolicDecomposition = static_cast<css*>(cs_calloc(1, sizeof(css)));
169 int n = pImpl->ccsA.n;
170 pImpl->symbolicDecomposition->pinv = cs_pinv(permutation, n);
171 cs* C = cs_symperm(&pImpl->ccsA, pImpl->symbolicDecomposition->pinv, 0);
172 pImpl->symbolicDecomposition->parent = cs_etree(C, 0);
173 int* post = cs_post(pImpl->symbolicDecomposition->parent, n);
174 int* c = cs_counts(C, pImpl->symbolicDecomposition->parent, post, 0);
175 cs_free(post);
176 cs_spfree(C);
177 pImpl->symbolicDecomposition->cp =
178 static_cast<int*>(cs_malloc(n + 1, sizeof(int)));
179 pImpl->symbolicDecomposition->unz = pImpl->symbolicDecomposition->lnz =
180 cs_cumsum(pImpl->symbolicDecomposition->cp, c, n);
181 cs_free(c);
182 if (pImpl->symbolicDecomposition->lnz < 0) {
183 cs_sfree(pImpl->symbolicDecomposition);
184 pImpl->symbolicDecomposition = nullptr;
185 }
186 return pImpl->symbolicDecomposition != nullptr;
187}
188
190 if (pImpl->symbolicDecomposition) return pImpl->symbolicDecomposition->lnz;
191 return -1;
192}
193
195 pImpl->prepareWorkspace();
196 freeFactor();
198 &pImpl->ccsA, pImpl->symbolicDecomposition, pImpl->csIntWorkspace,
199 pImpl->csWorkspace);
200
201 return pImpl->numericCholesky != nullptr;
202}
203
205 return pImpl->symbolicDecomposition != nullptr;
206}
207
209 if (pImpl->symbolicDecomposition != nullptr) {
210 cs_sfree(pImpl->symbolicDecomposition);
211 pImpl->symbolicDecomposition = nullptr;
212 }
213}
214
215bool CSparse::writeSparse(const std::string& filename) const {
216 return csparse_extension::writeCs2Octave(filename.c_str(), &pImpl->ccsA,
217 true);
218}
219
220} // namespace csparse
221} // namespace g2o
bool amd(const SparseView &sparseView, VectorXI &result)
compute AMD ordering on the given SparseView, store into result
bool solve(double *x, double *b) const
std::unique_ptr< Impl > pImpl
bool analyze_p(int *permutation)
bool writeSparse(const std::string &filename) const
csn * cs_chol_workspace(const cs *A, const css *S, int *cin, double *xin)
bool writeCs2Octave(const char *filename, const cs *A, bool upperTriangular)
int cs_cholsolsymb(const cs *A, double *b, const css *S, double *x, int *work)
Eigen::Matrix< int, Eigen::Dynamic, 1, Eigen::ColMajor > VectorXI
Definition eigen_types.h:41
Definition jet.h:876
Our C++ version of the csparse struct.
CSparseExt(CSparseExt const &)=delete
CSparseExt & operator=(CSparseExt const &)=delete
View onto the cholesky factor.
View onto the sparse matrix structure of CSparse using CCS storage.