Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "graph_optimizer_sparse.h"
00018
00019 #include <iostream>
00020 #include <iomanip>
00021 #include <algorithm>
00022 #include <iterator>
00023 #include <cassert>
00024 #include <algorithm>
00025
00026 #include "estimate_propagator.h"
00027 #include "solver.h"
00028 #include "batch_stats.h"
00029 #include "g2o/stuff/timeutil.h"
00030 #include "g2o/stuff/macros.h"
00031 #include "g2o/config.h"
00032
00033 #include <typeinfo>
00034
00035 namespace g2o{
00036 using namespace std;
00037
00038
00039 SparseOptimizer::SparseOptimizer(){
00040 _method=GaussNewton;
00041 _currentLambda = -1.;
00042 _solver = 0;
00043 _forceStopFlag = 0;
00044 _tau = 1e-5;
00045 _goodStepUpperScale = 2./3.;
00046 _goodStepLowerScale = 1./3.;
00047 _userLambdaInit = 0;
00048 _statistics = 0;
00049 _maxTrialsAfterFailure = 10;
00050 }
00051
00052
00053
00054 SparseOptimizer::~SparseOptimizer(){
00055 delete _solver;
00056 delete[] _statistics;
00057 }
00058
00059
00060
00061 void SparseOptimizer::computeActiveErrors()
00062 {
00063 for (EdgeContainer::const_iterator
00064 it = _activeEdges.begin();
00065 it != _activeEdges.end();
00066 it++)
00067 {
00068 OptimizableGraph::Edge* e = *it;
00069 e->computeError();
00070 if (e->robustKernel()) e->robustifyError();
00071 }
00072 }
00073
00074
00075
00076 double SparseOptimizer::activeChi2( ) const
00077 {
00078 double chi = 0.0;
00079 for (EdgeContainer::const_iterator
00080 it = _activeEdges.begin();
00081 it != _activeEdges.end();
00082 it++)
00083 {
00084 const OptimizableGraph::Edge* e = *it;
00085 chi += e->chi2();
00086 }
00087 return chi;
00088 }
00089
00090
00091
00092 OptimizableGraph::Vertex* SparseOptimizer::findGauge(){
00093 if (vertices().empty())
00094 return 0;
00095
00096 int maxDim=0;
00097 for (HyperGraph::VertexIDMap::iterator
00098 it = vertices().begin();
00099 it != vertices().end();
00100 it++)
00101 {
00102 OptimizableGraph::Vertex* v =
00103 static_cast<OptimizableGraph::Vertex*>(it->second);
00104 maxDim = std::max(maxDim,v->dimension());
00105 }
00106
00107 OptimizableGraph::Vertex* rut=0;
00108 for (HyperGraph::VertexIDMap::iterator
00109 it = vertices().begin();
00110 it != vertices().end();
00111 it++)
00112 {
00113 OptimizableGraph::Vertex* v =
00114 static_cast<OptimizableGraph::Vertex*>(it->second);
00115 if (v->dimension()==maxDim)
00116 {
00117 rut=v;
00118 break;
00119 }
00120 }
00121 return rut;
00122 }
00123
00124
00125
00126 bool SparseOptimizer::gaugeFreedom()
00127 {
00128 if (vertices().empty())
00129 return false;
00130
00131 int maxDim=0;
00132 for (HyperGraph::VertexIDMap::iterator
00133 it = vertices().begin();
00134 it != vertices().end();
00135 it++)
00136 {
00137 OptimizableGraph::Vertex* v =
00138 static_cast<OptimizableGraph::Vertex*>(it->second);
00139 maxDim = std::max(maxDim,v->dimension());
00140 }
00141
00142 for (HyperGraph::VertexIDMap::iterator
00143 it = vertices().begin();
00144 it != vertices().end();
00145 it++)
00146 {
00147 OptimizableGraph::Vertex* v =
00148 static_cast<OptimizableGraph::Vertex*>(it->second);
00149 if (v->dimension() == maxDim)
00150 {
00151
00152 for (HyperGraph::EdgeSet::const_iterator
00153 eit = v->edges().begin();
00154 eit != v->edges().end();
00155 ++eit)
00156 {
00157 OptimizableGraph::Edge* e =
00158 static_cast<OptimizableGraph::Edge*>(*eit);
00159 if (e->vertices().size() == 1 && e->dimension() == maxDim)
00160 return false;
00161 }
00162 }
00163 }
00164 return true;
00165 }
00166
00167
00168
00169 bool SparseOptimizer::buildIndexMapping
00170 (SparseOptimizer::VertexContainer& vlist)
00171 {
00172 if (! vlist.size())
00173 {
00174 _ivMap.clear();
00175 return false;
00176 }
00177
00178 _ivMap.resize(vlist.size());
00179 size_t i = 0;
00180
00181
00182
00183
00184
00185
00186 for (int k=0; k<2; k++)
00187 for (VertexContainer::iterator it=vlist.begin(); it!=vlist.end(); it++)
00188 {
00189 OptimizableGraph::Vertex* v = *it;
00190 if (! v->fixed())
00191 {
00192 if (static_cast<int>(v->marginalized()) == k)
00193 {
00194 v->setTempIndex(i);
00195 _ivMap[i]=v;
00196 i++;
00197 }
00198 }else v->setTempIndex(-1);
00199 }
00200
00201 _ivMap.resize(i);
00202 return true;
00203 }
00204
00205
00206
00207 void SparseOptimizer::clearIndexMapping()
00208 {
00209 for (size_t i=0; i<_ivMap.size(); i++)
00210 {
00211 _ivMap[i]->setTempIndex(-1);
00212 _ivMap[i]=0;
00213 }
00214 }
00215
00216
00217
00218 double SparseOptimizer::computeLambdaInit()
00219 {
00220 if (_userLambdaInit>0) return _userLambdaInit;
00221 double maxDiagonal=0.;
00222 for (size_t k = 0; k < _ivMap.size(); k++)
00223 {
00224 OptimizableGraph::Vertex* v=_ivMap[k];
00225 assert(v);
00226 int dim = v->dimension();
00227 for (int j = 0; j < dim; ++j)
00228 maxDiagonal = std::max(fabs(v->hessian(j,j)),maxDiagonal);
00229 }
00230 return _tau*maxDiagonal;
00231 }
00232
00233
00234
00235 double SparseOptimizer::computeScale(double currentLMLambda, Solver* solver)
00236 {
00237 double scale=0;
00238 for (size_t j=0; j < solver->vectorSize(); j++)
00239 scale += solver->x()[j]
00240 * (currentLMLambda * solver->x()[j] + solver->b()[j]);
00241
00242 return scale;
00243 }
00244
00245
00246
00247 bool SparseOptimizer::initializeOptimization(int level)
00248 {
00249 HyperGraph::VertexSet vset;
00250
00251 for (VertexIDMap::iterator
00252 it = vertices().begin();
00253 it != vertices().end();
00254 it++)
00255 vset.insert(it->second);
00256
00257 return initializeOptimization(vset,level);
00258 }
00259
00260
00261
00262 bool SparseOptimizer::initializeOptimization
00263 (HyperGraph::VertexSet& vset, int level)
00264 {
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 clearIndexMapping();
00278 _activeVertices.clear();
00279 _activeVertices.reserve(vset.size());
00280 _activeEdges.clear();
00281
00282 set<Edge*> auxEdgeSet;
00283
00284 for (HyperGraph::VertexSet::iterator
00285 it = vset.begin();
00286 it != vset.end();
00287 it++)
00288 {
00289 OptimizableGraph::Vertex* v= (OptimizableGraph::Vertex*) *it;
00290 const OptimizableGraph::EdgeSet& vEdges=v->edges();
00291
00292 int levelEdges=0;
00293 for (OptimizableGraph::EdgeSet::const_iterator
00294 it = vEdges.begin();
00295 it != vEdges.end();
00296 it++)
00297 {
00298 OptimizableGraph::Edge* e =
00299 reinterpret_cast<OptimizableGraph::Edge*>(*it);
00300 if (level < 0 || e->level() == level)
00301 {
00302 bool allVerticesOK = true;
00303 for (vector<HyperGraph::Vertex*>::const_iterator
00304 vit = e->vertices().begin();
00305 vit != e->vertices().end();
00306 ++vit)
00307 {
00308 if (vset.find(*vit) == vset.end())
00309 {
00310 allVerticesOK = false;
00311 break;
00312 }
00313 }
00314
00315 if (allVerticesOK)
00316 {
00317 auxEdgeSet.insert(reinterpret_cast<OptimizableGraph::Edge*>(*it));
00318 levelEdges++;
00319 }
00320 }
00321 }
00322 if (levelEdges) _activeVertices.push_back(v);
00323 }
00324
00325 _activeEdges.reserve(auxEdgeSet.size());
00326 for (set<Edge*>::iterator
00327 it = auxEdgeSet.begin();
00328 it != auxEdgeSet.end();
00329 ++it)
00330 _activeEdges.push_back(*it);
00331
00332 sortVectorContainers();
00333 return buildIndexMapping(_activeVertices);
00334 }
00335
00336
00337
00338 bool SparseOptimizer::initializeOptimization(HyperGraph::EdgeSet& eset)
00339 {
00340 clearIndexMapping();
00341 _activeVertices.clear();
00342 _activeEdges.clear();
00343 _activeEdges.reserve(eset.size());
00344 set<Vertex*> auxVertexSet;
00345 for (HyperGraph::EdgeSet::iterator
00346 it = eset.begin();
00347 it != eset.end();
00348 it++)
00349 {
00350 OptimizableGraph::Edge* e=(OptimizableGraph::Edge*)(*it);
00351 for (vector<HyperGraph::Vertex*>::const_iterator
00352 vit = e->vertices().begin();
00353 vit != e->vertices().end();
00354 ++vit)
00355 auxVertexSet.insert(static_cast<OptimizableGraph::Vertex*>(*vit));
00356
00357 _activeEdges.push_back(reinterpret_cast<OptimizableGraph::Edge*>(*it));
00358 }
00359
00360 _activeVertices.reserve(auxVertexSet.size());
00361 for (set<Vertex*>::iterator
00362 it = auxVertexSet.begin();
00363 it != auxVertexSet.end();
00364 ++it)
00365 _activeVertices.push_back(*it);
00366
00367 sortVectorContainers();
00368 return buildIndexMapping(_activeVertices);
00369 }
00370
00371
00372
00373 void SparseOptimizer::computeInitialGuess()
00374 {
00375 OptimizableGraph::VertexSet emptySet;
00376 std::set<Vertex*> backupVertices;
00377
00378 HyperGraph::VertexSet fixedVertices;
00379 for (EdgeContainer::iterator
00380 it = _activeEdges.begin();
00381 it != _activeEdges.end();
00382 ++it)
00383 {
00384 OptimizableGraph::Edge* e = *it;
00385 for (size_t i = 0; i < e->vertices().size(); ++i)
00386 {
00387 OptimizableGraph::Vertex* v =
00388 static_cast<OptimizableGraph::Vertex*>(e->vertices()[i]);
00389
00390 if (v->fixed()) fixedVertices.insert(v);
00391 else
00392 {
00393
00394 for (EdgeSet::const_iterator
00395 vedgeIt = v->edges().begin();
00396 vedgeIt != v->edges().end();
00397 ++vedgeIt)
00398 {
00399 OptimizableGraph::Edge* vedge =
00400 static_cast<OptimizableGraph::Edge*>(*vedgeIt);
00401 if ( vedge->vertices().size() == 1
00402 && vedge->initialEstimatePossible(emptySet, v) > 0.)
00403 {
00404
00405 vedge->initialEstimate(emptySet, v);
00406 fixedVertices.insert(v);
00407 }
00408 }
00409 }
00410
00411 if (v->tempIndex() == -1)
00412 {
00413 std::set<Vertex*>::const_iterator foundIt = backupVertices.find(v);
00414 if (foundIt == backupVertices.end()) {
00415 v->push();
00416 backupVertices.insert(v);
00417 }
00418 }
00419 }
00420 }
00421
00422 EstimatePropagator estimatePropagator(this);
00423 EstimatePropagator::PropagateCost costFunction(this);
00424 estimatePropagator.propagate(fixedVertices, costFunction);
00425
00426
00427 for (std::set<Vertex*>::iterator
00428 it = backupVertices.begin();
00429 it != backupVertices.end();
00430 ++it)
00431 {
00432 Vertex* v = *it;
00433 v->pop();
00434 }
00435 if (verbose())
00436 {
00437 computeActiveErrors();
00438 cerr << "iteration= -1\t chi2= " << activeChi2()
00439 << "\t time= 0.0"
00440 << "\t cumTime= 0.0"
00441 << "\t (using initial guess from spanning tree)" << endl;
00442 }
00443 }
00444
00445
00446
00447 int SparseOptimizer::optimize(int iterations, bool online)
00448 {
00449
00450 bool useSchur=false;
00451 for (VertexContainer::iterator
00452 it = _activeVertices.begin();
00453 it != _activeVertices.end();
00454 it++)
00455 {
00456 OptimizableGraph::Vertex* v= *it;
00457 if (v->marginalized())
00458 {
00459 useSchur=true;
00460 break;
00461 }
00462 }
00463
00464
00465 double t;
00466 Solver* solver = _solver;
00467 if (useSchur){
00468 if (_solver->supportsSchur())
00469 _solver->setSchur(true);
00470 } else {
00471 if (_solver->supportsSchur())
00472 _solver->setSchur(false);
00473 }
00474
00475
00476 solver->init(online);
00477 solver->setLevenberg(_method == LevenbergMarquardt);
00478
00479 int cjIterations=0;
00480 double cumTime=0;
00481 double currentChi=0;
00482 double tempChi=0;
00483 if (_method == LevenbergMarquardt)
00484 {
00485
00486 computeActiveErrors();
00487
00488 currentChi = activeChi2();
00489 tempChi = currentChi;
00490 }
00491 bool ok=true;
00492
00493 double ni=2.;
00494
00495
00496
00497 for (int i=0; i<iterations && ! terminate() && ok; i++)
00498 {
00499 preIteration(i);
00500
00501 G2OBatchStatistics* cstat = _statistics ? &(_statistics[i]) : 0;
00502 globalStats = cstat;
00503 if (cstat)
00504 {
00505 cstat->iteration = i;
00506 cstat->numEdges = _activeEdges.size();
00507 cstat->numVertices = _activeVertices.size();
00508 }
00509
00510
00511
00512
00513 double ts = get_time();
00514 if (i == 0 && !online)
00515 {
00516 ok = solver->buildStructure();
00517 if (! ok)
00518 {
00519 cerr << __PRETTY_FUNCTION__
00520 << ": Failure while building CCS structure\n";
00521 return 0;
00522 }
00523 }
00524
00525
00526
00527 t = get_time();
00528 computeActiveErrors();
00529 if (cstat) cstat->timeResiduals = get_time() - t;
00530
00531
00532
00533 t = get_time();
00534 linearizeSystem();
00535 if (cstat) cstat->timeLinearize = get_time()-t;
00536
00537
00538
00539
00540 t = get_time();
00541 solver->buildSystem();
00542 if (cstat) cstat->timeQuadraticForm = get_time()-t;
00543
00544
00545
00546 if (_method == GaussNewton)
00547 {
00548 t = get_time();
00549 ok = solver->solve();
00550 if (cstat) cstat->timeLinearSolution = get_time()-t;
00551
00552 t = get_time();
00553 update(solver->x());
00554 if (cstat) cstat->timeUpdate = get_time()-t;
00555
00556 } else if (_method == LevenbergMarquardt)
00557 {
00558 if (i==0) _currentLambda = computeLambdaInit();
00559
00560 double rho = 0;
00561 int qmax = 0;
00562 do
00563 {
00564 push(_activeVertices);
00565 if (cstat) cstat->levenbergIterations++;
00566
00567
00568
00569
00570 t = get_time();
00571 solver->setLambda(_currentLambda);
00572
00573
00574
00575 bool ok2 = solver->solve();
00576 if (cstat) cstat->timeLinearSolution+=get_time()-t;
00577
00578
00579
00580
00581
00582 t = get_time();
00583 update(solver->x());
00584 if (cstat) cstat->timeUpdate = get_time()-t;
00585
00586
00587
00588
00589 solver->setLambda(- _currentLambda);
00590
00591
00592
00593 t = get_time();
00594 computeActiveErrors();
00595 tempChi = activeChi2();
00596
00597
00598
00599
00600 if (! ok2) tempChi = std::numeric_limits<double>::max();
00601
00602 rho = (currentChi-tempChi);
00603 double scale = computeScale(_currentLambda, solver);
00604 scale += 1e-3;
00605 rho /= scale ;
00606
00607 if (rho > 0)
00608 {
00609 double alpha = 1.-pow((2*rho-1),3);
00610
00611
00612 alpha = std::min(alpha, _goodStepUpperScale);
00613 double scaleFactor = std::max(_goodStepLowerScale, alpha);
00614
00615 _currentLambda *= scaleFactor;
00616
00617 ni = 2;
00618 currentChi = tempChi;
00619 t = get_time();
00620 discardTop(_activeVertices);
00621 } else
00622 {
00623 _currentLambda *= ni;
00624 ni *= 2;
00625 t = get_time();
00626
00627 pop(_activeVertices);
00628 }
00629 qmax++;
00630 } while (rho < 0 && qmax < _maxTrialsAfterFailure && ! terminate());
00631
00632 if (qmax == _maxTrialsAfterFailure || fabs(rho) < 1e-15 )
00633 i = iterations;
00634 }
00635
00636
00637 bool errorComputed = false;
00638 if (cstat)
00639 {
00640 computeActiveErrors();
00641 errorComputed = true;
00642 cstat->chi2 = activeChi2();
00643 cstat->timeIteration = get_time()-ts;
00644 }
00645
00646 double dts = get_time()-ts;
00647 cumTime += dts;
00648 if (verbose())
00649 {
00650 if (! errorComputed) computeActiveErrors();
00651 cerr << "iteration= " << i
00652 << "\t chi2= " << FIXED(activeChi2())
00653 << "\t time= " << dts
00654 << "\t cumTime= " << cumTime
00655 << "\t lambda= " << FIXED(_currentLambda)
00656 << "\t edges= " << _activeEdges.size()
00657 << "\t schur= " << useSchur << endl;
00658 }
00659 ++cjIterations;
00660 postIteration(i);
00661 }
00662
00663 if (! ok) return 0;
00664 return cjIterations;
00665 }
00666
00667
00668
00669 void SparseOptimizer::linearizeSystem()
00670 {
00671 # ifdef G2O_OPENMP
00672 # pragma omp parallel for default (shared) if (_activeEdges.size() > 50)
00673 # endif
00674 for (size_t k = 0; k < _activeEdges.size(); ++k)
00675 {
00676 OptimizableGraph::Edge* e = _activeEdges[k];
00677
00678 e->linearizeOplus();
00679 }
00680 }
00681
00682
00683
00684 void SparseOptimizer::update(double* update)
00685 {
00686
00687 for (size_t i=0; i < _ivMap.size(); ++i)
00688 {
00689 OptimizableGraph::Vertex* v = _ivMap[i];
00690 v->oplus(update);
00691 update += v->dimension();
00692 }
00693 }
00694
00695
00696
00697 bool SparseOptimizer::updateInitialization(HyperGraph::VertexSet& vset, HyperGraph::EdgeSet& eset)
00698 {
00699 std::vector<HyperGraph::Vertex*> newVertices;
00700 newVertices.reserve(vset.size());
00701 _activeVertices.reserve(_activeVertices.size() + vset.size());
00702
00703
00704 _activeEdges.reserve(_activeEdges.size() + eset.size());
00705 for (HyperGraph::EdgeSet::iterator it = eset.begin(); it != eset.end(); ++it)
00706 _activeEdges.push_back(static_cast<OptimizableGraph::Edge*>(*it));
00707
00708
00709 size_t next = _ivMap.size();
00710 for (HyperGraph::VertexSet::iterator it = vset.begin(); it != vset.end(); ++it) {
00711 OptimizableGraph::Vertex* v=static_cast<OptimizableGraph::Vertex*>(*it);
00712 if (! v->fixed()){
00713 if (! v->marginalized()){
00714 v->setTempIndex(next);
00715 _ivMap.push_back(v);
00716 newVertices.push_back(v);
00717 _activeVertices.push_back(v);
00718 next++;
00719 }
00720 else
00721 abort();
00722 }
00723 else {
00724 v->setTempIndex(-1);
00725 }
00726 }
00727
00728
00729
00730 return _solver->updateStructure(newVertices, eset);
00731 }
00732
00733
00734
00735 void SparseOptimizer::sortVectorContainers()
00736 {
00737
00738 sort(_activeVertices.begin(), _activeVertices.end(), VertexIDCompare());
00739 sort(_activeEdges.begin(), _activeEdges.end(), EdgeIDCompare());
00740 }
00741
00742
00743
00744 void SparseOptimizer::clear() {
00745 _ivMap.clear();
00746 _activeVertices.clear();
00747 _activeEdges.clear();
00748 HyperGraph::clear();
00749 }
00750
00751
00752
00753 SparseOptimizer::VertexContainer::const_iterator SparseOptimizer::findActiveVertex(OptimizableGraph::Vertex* v) const
00754 {
00755 VertexContainer::const_iterator lower = lower_bound(_activeVertices.begin(), _activeVertices.end(), v, VertexIDCompare());
00756 if (lower == _activeVertices.end())
00757 return _activeVertices.end();
00758 if ((*lower) == v)
00759 return lower;
00760 return _activeVertices.end();
00761 }
00762
00763
00764
00765 SparseOptimizer::EdgeContainer::const_iterator SparseOptimizer::findActiveEdge(OptimizableGraph::Edge* e) const
00766 {
00767 EdgeContainer::const_iterator lower = lower_bound(_activeEdges.begin(), _activeEdges.end(), e, EdgeIDCompare());
00768 if (lower == _activeEdges.end())
00769 return _activeEdges.end();
00770 if ((*lower) == e)
00771 return lower;
00772 return _activeEdges.end();
00773 }
00774
00775
00776
00777 void SparseOptimizer::push(SparseOptimizer::VertexContainer& vlist)
00778 {
00779 for (VertexContainer::iterator it = vlist.begin(); it != vlist.end(); ++it)
00780 (*it)->push();
00781 }
00782
00783
00784
00785 void SparseOptimizer::pop(SparseOptimizer::VertexContainer& vlist)
00786 {
00787 for (VertexContainer::iterator it = vlist.begin(); it != vlist.end(); ++it)
00788 (*it)->pop();
00789 }
00790
00791
00792
00793 void SparseOptimizer::push(HyperGraph::VertexSet& vlist)
00794 {
00795 for (HyperGraph::VertexSet::iterator
00796 it = vlist.begin();
00797 it != vlist.end();
00798 ++it)
00799 {
00800 OptimizableGraph::Vertex* v = dynamic_cast<OptimizableGraph::Vertex*>(*it);
00801 if (v) v->push();
00802 else cerr << "FATAL PUSH SET" << endl;
00803 }
00804 }
00805
00806
00807
00808 void SparseOptimizer::pop(HyperGraph::VertexSet& vlist)
00809 {
00810 for (HyperGraph::VertexSet::iterator it = vlist.begin(); it != vlist.end(); ++it){
00811 OptimizableGraph::Vertex* v = dynamic_cast<OptimizableGraph::Vertex*> (*it);
00812 if (v)
00813 v->pop();
00814 else
00815 cerr << "FATAL POP SET" << endl;
00816 }
00817 }
00818
00819
00820
00821 void SparseOptimizer::discardTop(SparseOptimizer::VertexContainer& vlist)
00822 {
00823 for (VertexContainer::iterator it = vlist.begin(); it != vlist.end(); ++it)
00824 (*it)->discardTop();
00825 }
00826
00827
00828 void SparseOptimizer::setVerbose(bool verbose)
00829 {
00830 _verbose = verbose;
00831 }
00832
00833
00834
00835 void SparseOptimizer::setMethod(SparseOptimizer::Method method)
00836 {
00837 _method = method;
00838 }
00839
00840
00841
00842 void SparseOptimizer::setSolver(Solver* solver)
00843 {
00844 _solver = solver;
00845 }
00846
00847
00848
00849 void SparseOptimizer::setUserLambdaInit(double lambda)
00850 {
00851 _userLambdaInit = lambda;
00852 }
00853
00854
00855
00856 bool SparseOptimizer::computeMarginals()
00857 {
00858 return _solver->computeMarginals();
00859 }
00860
00861
00862
00863 bool SparseOptimizer::computeMarginals(SparseBlockMatrix<MatrixXd>& spinv, const std::vector<std::pair<int, int> >& blockIndices){
00864 return _solver->computeMarginals(spinv, blockIndices);
00865 }
00866
00867
00868
00869 void SparseOptimizer::setMaxTrialsAfterFailure(int max_trials)
00870 {
00871 _maxTrialsAfterFailure = max_trials;
00872 }
00873
00874
00875
00876 void SparseOptimizer::setForceStopFlag(bool* flag)
00877 {
00878 _forceStopFlag=flag;
00879 }
00880
00881
00882
00883 bool SparseOptimizer::removeVertex(Vertex* v)
00884 {
00885 if (v->tempIndex() >= 0) {
00886 clearIndexMapping();
00887 _ivMap.clear();
00888 }
00889 return HyperGraph::removeVertex(v);
00890 }
00891
00892 }