00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "marginal_covariance_cholesky.h"
00018
00019 #include <algorithm>
00020 #include <cassert>
00021 using namespace std;
00022
00023 namespace g2o {
00024
00025 struct MatrixElem
00026 {
00027 int r, c;
00028 MatrixElem(int r_, int c_) : r(r_), c(c_) {}
00029 bool operator<(const MatrixElem& other) const
00030 {
00031 return c > other.c || (c == other.c && r > other.r);
00032 }
00033 };
00034
00035 MarginalCovarianceCholesky::MarginalCovarianceCholesky() :
00036 _n(0), _Ap(0), _Ai(0), _Ax(0), _perm(0)
00037 {
00038 }
00039
00040 MarginalCovarianceCholesky::~MarginalCovarianceCholesky()
00041 {
00042 }
00043
00044 void MarginalCovarianceCholesky::setCholeskyFactor(int n, int* Lp, int* Li, double* Lx, int* permInv)
00045 {
00046 _n = n;
00047 _Ap = Lp;
00048 _Ai = Li;
00049 _Ax = Lx;
00050 _perm = permInv;
00051
00052
00053 _diag.resize(n);
00054 for (int r = 0; r < n; ++r) {
00055 const int& sc = _Ap[r];
00056 assert(r == _Ai[sc] && "Error in CCS storage of L");
00057 _diag[r] = 1.0 / _Ax[sc];
00058 }
00059 }
00060
00061 void MarginalCovarianceCholesky::computeCovariance(const std::vector<OptimizableGraph::Vertex*>& vertices)
00062 {
00063 int maxDimension = -1;
00064 _map.clear();
00065 vector<MatrixElem> elemsToCompute;
00066 for (size_t i = 0; i < vertices.size(); ++i) {
00067 OptimizableGraph::Vertex* v = vertices[i];
00068 int vdim = v->dimension();
00069 int base = v->colInHessian();
00070 maxDimension = std::max(vdim, maxDimension);
00071 for (int rr = 0; rr < vdim; ++rr)
00072 for (int cc = rr; cc < vdim; ++cc) {
00073 int r = _perm ? _perm[rr + base] : rr + base;
00074 int c = _perm ? _perm[cc + base] : cc + base;
00075 if (r > c)
00076 swap(r, c);
00077 elemsToCompute.push_back(MatrixElem(r, c));
00078 }
00079 }
00080
00081
00082 sort(elemsToCompute.begin(), elemsToCompute.end());
00083
00084
00085 for (size_t i = 0; i < elemsToCompute.size(); ++i) {
00086 const MatrixElem& me = elemsToCompute[i];
00087 computeEntry(me.r, me.c);
00088 }
00089
00090 #ifdef _MSC_VER
00091 double* cov = new double[maxDimension * maxDimension];
00092 #else // allocation from the stack
00093 double cov[maxDimension * maxDimension];
00094 #endif
00095
00096
00097 for (size_t i = 0; i < vertices.size(); ++i) {
00098 OptimizableGraph::Vertex* v = vertices[i];
00099 int vdim = v->dimension();
00100 int base = v->colInHessian();
00101 for (int rr = 0; rr < vdim; ++rr)
00102 for (int cc = rr; cc < vdim; ++cc) {
00103 int r = _perm ? _perm[rr + base] : rr + base;
00104 int c = _perm ? _perm[cc + base] : cc + base;
00105 if (r > c)
00106 swap(r, c);
00107 int idx = computeIndex(r, c);
00108 LookupMap::const_iterator foundIt = _map.find(idx);
00109 assert(foundIt != _map.end());
00110 cov[rr*vdim + cc] = foundIt->second;
00111 if (rr != cc)
00112 cov[cc*vdim + rr] = foundIt->second;
00113 }
00114 v->setUncertainty(cov);
00115 }
00116 #ifdef _MSC_VER
00117 delete[] cov;
00118 #endif
00119 }
00120
00121 double MarginalCovarianceCholesky::computeEntry(int r, int c)
00122 {
00123 assert(r <= c);
00124 int idx = computeIndex(r, c);
00125
00126 LookupMap::const_iterator foundIt = _map.find(idx);
00127 if (foundIt != _map.end()) {
00128 return foundIt->second;
00129 }
00130
00131
00132 double s = 0.;
00133 const int& sc = _Ap[r];
00134 const int& ec = _Ap[r+1];
00135 for (int j = sc+1; j < ec; ++j) {
00136 const int& rr = _Ai[j];
00137 double val = rr < c ? computeEntry(rr, c) : computeEntry(c, rr);
00138 s += val * _Ax[j];
00139 }
00140
00141 double result;
00142 if (r == c) {
00143 const double& diagElem = _diag[r];
00144 result = diagElem * (diagElem - s);
00145 } else {
00146 result = -s * _diag[r];
00147 }
00148 _map[idx] = result;
00149 return result;
00150 }
00151
00152 void MarginalCovarianceCholesky::computeCovariance(double** covBlocks, const std::vector<int>& blockIndices)
00153 {
00154 _map.clear();
00155 int base = 0;
00156 vector<MatrixElem> elemsToCompute;
00157 for (size_t i = 0; i < blockIndices.size(); ++i) {
00158 int nbase = blockIndices[i];
00159 int vdim = nbase - base;
00160 for (int rr = 0; rr < vdim; ++rr)
00161 for (int cc = rr; cc < vdim; ++cc) {
00162 int r = _perm ? _perm[rr + base] : rr + base;
00163 int c = _perm ? _perm[cc + base] : cc + base;
00164 if (r > c)
00165 swap(r, c);
00166 elemsToCompute.push_back(MatrixElem(r, c));
00167 }
00168 base = nbase;
00169 }
00170
00171
00172 sort(elemsToCompute.begin(), elemsToCompute.end());
00173
00174
00175 for (size_t i = 0; i < elemsToCompute.size(); ++i) {
00176 const MatrixElem& me = elemsToCompute[i];
00177 computeEntry(me.r, me.c);
00178 }
00179
00180
00181 base = 0;
00182 for (size_t i = 0; i < blockIndices.size(); ++i) {
00183 int nbase = blockIndices[i];
00184 int vdim = nbase - base;
00185 double* cov = covBlocks[i];
00186 for (int rr = 0; rr < vdim; ++rr)
00187 for (int cc = rr; cc < vdim; ++cc) {
00188 int r = _perm ? _perm[rr + base] : rr + base;
00189 int c = _perm ? _perm[cc + base] : cc + base;
00190 if (r > c)
00191 swap(r, c);
00192 int idx = computeIndex(r, c);
00193 LookupMap::const_iterator foundIt = _map.find(idx);
00194 assert(foundIt != _map.end());
00195 cov[rr*vdim + cc] = foundIt->second;
00196 if (rr != cc)
00197 cov[cc*vdim + rr] = foundIt->second;
00198 }
00199 base = nbase;
00200 }
00201 }
00202
00203
00204 void MarginalCovarianceCholesky::computeCovariance(SparseBlockMatrix<MatrixXd>& spinv, const std::vector<int>& rowBlockIndices, const std::vector< std::pair<int, int> >& blockIndices)
00205 {
00206
00207 spinv = SparseBlockMatrix<MatrixXd>(&rowBlockIndices[0],
00208 &rowBlockIndices[0],
00209 rowBlockIndices.size(),
00210 rowBlockIndices.size(), true);
00211 _map.clear();
00212 vector<MatrixElem> elemsToCompute;
00213 for (size_t i = 0; i < blockIndices.size(); ++i) {
00214 int blockRow=blockIndices[i].first;
00215 int blockCol=blockIndices[i].second;
00216 assert (blockRow>=0);
00217 assert (blockRow < (int)rowBlockIndices.size());
00218 assert (blockCol>=0);
00219 assert (blockCol < (int)rowBlockIndices.size());
00220
00221 int rowBase=spinv.rowBaseOfBlock(blockRow);
00222 int colBase=spinv.colBaseOfBlock(blockCol);
00223
00224 MatrixXd *block=spinv.block(blockRow, blockCol, true);
00225 assert(block);
00226 for (int iRow=0; iRow<block->rows(); iRow++)
00227 for (int iCol=0; iCol<block->cols(); iCol++){
00228 int rr=rowBase+iRow;
00229 int cc=colBase+iCol;
00230 int r = _perm ? _perm[rr] : rr;
00231 int c = _perm ? _perm[cc] : cc;
00232 if (r > c)
00233 swap(r, c);
00234 elemsToCompute.push_back(MatrixElem(r, c));
00235 }
00236 }
00237
00238
00239 sort(elemsToCompute.begin(), elemsToCompute.end());
00240
00241
00242 for (size_t i = 0; i < elemsToCompute.size(); ++i) {
00243 const MatrixElem& me = elemsToCompute[i];
00244 computeEntry(me.r, me.c);
00245 }
00246
00247
00248 for (size_t i = 0; i < blockIndices.size(); ++i) {
00249 int blockRow=blockIndices[i].first;
00250 int blockCol=blockIndices[i].second;
00251 int rowBase=spinv.rowBaseOfBlock(blockRow);
00252 int colBase=spinv.colBaseOfBlock(blockCol);
00253
00254 MatrixXd *block=spinv.block(blockRow, blockCol);
00255 assert(block);
00256 for (int iRow=0; iRow<block->rows(); iRow++)
00257 for (int iCol=0; iCol<block->cols(); iCol++){
00258 int rr=rowBase+iRow;
00259 int cc=colBase+iCol;
00260 int r = _perm ? _perm[rr] : rr;
00261 int c = _perm ? _perm[cc] : cc;
00262 if (r > c)
00263 swap(r, c);
00264 int idx = computeIndex(r, c);
00265 LookupMap::const_iterator foundIt = _map.find(idx);
00266 assert(foundIt != _map.end());
00267 (*block)(iRow, iCol) = foundIt->second;
00268 }
00269 }
00270 }
00271
00272 }