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 "optimizable_graph.h"
00018
00019 #include <cassert>
00020 #include <iostream>
00021 #include <iomanip>
00022 #include <fstream>
00023 #include <algorithm>
00024
00025 #include "estimate_propagator.h"
00026 #include "factory.h"
00027 #include "solver_property.h"
00028 #include "hyper_graph_action.h"
00029
00030 #include "g2o/stuff/macros.h"
00031 #include "g2o/stuff/color_macros.h"
00032 #include "g2o/stuff/string_tools.h"
00033 #include "g2o/stuff/misc.h"
00034
00035 namespace g2o {
00036
00037 using namespace std;
00038
00039 OptimizableGraph::Vertex::Vertex() :
00040 HyperGraph::Vertex(),
00041 _graph(0), _userData(0), _tempIndex(-1), _fixed(false), _marginalized(false),
00042 _colInHessian(-1)
00043 {
00044
00045 }
00046
00047 OptimizableGraph::Vertex::~Vertex()
00048 {
00049 delete _userData;
00050 }
00051
00052 OptimizableGraph::Vertex* OptimizableGraph::Vertex::clone() const
00053 {
00054
00055 return 0;
00056 }
00057
00058 bool OptimizableGraph::Vertex::setEstimateData(const double *)
00059 {
00060 return false;
00061 }
00062
00063 bool OptimizableGraph::Vertex::getEstimateData(double *) const
00064 {
00065 return false;
00066 }
00067
00068 int OptimizableGraph::Vertex::estimateDimension() const
00069 {
00070 return -1;
00071 }
00072
00073 bool OptimizableGraph::Vertex::setMinimalEstimateData(const double *)
00074 {
00075 return false;
00076 }
00077
00078 bool OptimizableGraph::Vertex::getMinimalEstimateData(double *) const
00079 {
00080 return false;
00081 }
00082
00083 int OptimizableGraph::Vertex::minimalEstimateDimension() const
00084 {
00085 return -1;
00086 }
00087
00088
00089 OptimizableGraph::Edge::Edge() :
00090 HyperGraph::Edge(),
00091 _dimension(-1), _level(0), _robustKernel(false), _huberWidth(1.)
00092 {
00093 }
00094
00095 bool OptimizableGraph::Edge::setMeasurementData(const double *)
00096 {
00097 return false;
00098 }
00099
00100 bool OptimizableGraph::Edge::getMeasurementData(double *) const
00101 {
00102 return false;
00103 }
00104
00105 int OptimizableGraph::Edge::measurementDimension() const
00106 {
00107 return -1;
00108 }
00109
00110 bool OptimizableGraph::Edge::setMeasurementFromState(){
00111 return false;
00112 }
00113
00114
00115 OptimizableGraph::Edge* OptimizableGraph::Edge::clone() const
00116 {
00117
00118 return 0;
00119 }
00120
00121 OptimizableGraph::OptimizableGraph()
00122 {
00123 _upperGraph=0; _lowerGraph=0; _nextEdgeId = 0; _edge_has_id = false;
00124 _graphActions.resize(AT_NUM_ELEMENTS);
00125 }
00126
00127 OptimizableGraph::~OptimizableGraph()
00128 {
00129 clear();
00130 }
00131
00132 bool OptimizableGraph::addVertex(Vertex* v, Data* userData)
00133 {
00134 Vertex* inserted = vertex(v->id());
00135 if (inserted)
00136 return false;
00137 if (userData)
00138 v->setUserData(userData);
00139 HyperGraph::addVertex(v);
00140 OptimizableGraph::Vertex* ov=dynamic_cast<OptimizableGraph::Vertex*>(v);
00141 assert(ov);
00142 ov->_graph=this;
00143 return true;
00144 }
00145
00146 bool OptimizableGraph::addEdge(OptimizableGraph::Edge* e)
00147 {
00148 OptimizableGraph::Edge* eresult = dynamic_cast<OptimizableGraph::Edge*>(HyperGraph::addEdge(e));
00149 if (! eresult)
00150 return false;
00151 e->_internalId = _nextEdgeId++;
00152 return true;
00153 }
00154
00155 int OptimizableGraph::optimize(int , bool ) {return 0;}
00156
00157 double OptimizableGraph::chi2() const
00158 {
00159 double chi = 0.0;
00160 for (OptimizableGraph::EdgeSet::const_iterator it = this->edges().begin(); it != this->edges().end(); it++) {
00161 const OptimizableGraph::Edge* e = static_cast<const OptimizableGraph::Edge*>(*it);
00162 chi += e->chi2();
00163 }
00164 return chi;
00165 }
00166
00167 void OptimizableGraph::push()
00168 {
00169 for (OptimizableGraph::VertexIDMap::iterator it=_vertices.begin(); it!=_vertices.end(); it++) {
00170 OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(it->second);
00171 v->push();
00172 }
00173 }
00174
00175 void OptimizableGraph::pop()
00176 {
00177 for (OptimizableGraph::VertexIDMap::iterator it=_vertices.begin(); it!=_vertices.end(); it++) {
00178 OptimizableGraph::Vertex* v= static_cast<OptimizableGraph::Vertex*>(it->second);
00179 v->pop();
00180 }
00181 }
00182
00183 void OptimizableGraph::discardTop()
00184 {
00185 for (OptimizableGraph::VertexIDMap::iterator it=_vertices.begin(); it!=_vertices.end(); it++) {
00186 OptimizableGraph::Vertex* v= static_cast<OptimizableGraph::Vertex*>(it->second);
00187 v->discardTop();
00188 }
00189 }
00190
00191 void OptimizableGraph::push(HyperGraph::VertexSet& vset)
00192 {
00193 for (HyperGraph::VertexSet::iterator it=vset.begin(); it!=vset.end(); it++) {
00194 OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(*it);
00195 v->push();
00196 }
00197 }
00198
00199 void OptimizableGraph::pop(HyperGraph::VertexSet& vset)
00200 {
00201 for (HyperGraph::VertexSet::iterator it=vset.begin(); it!=vset.end(); it++) {
00202 OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(*it);
00203 v->pop();
00204 }
00205 }
00206
00207 void OptimizableGraph::discardTop(HyperGraph::VertexSet& vset)
00208 {
00209 for (HyperGraph::VertexSet::iterator it=vset.begin(); it!=vset.end(); it++) {
00210 OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(*it);
00211 v->discardTop();
00212 }
00213 }
00214
00215 void OptimizableGraph::setFixed(HyperGraph::VertexSet& vset, bool fixed)
00216 {
00217 for (HyperGraph::VertexSet::iterator it=vset.begin(); it!=vset.end(); it++) {
00218 OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(*it);
00219 v->setFixed(fixed);
00220 }
00221 }
00222
00223
00224 bool OptimizableGraph::load(istream& is, bool createEdges)
00225 {
00226 set<string> warnedUnknownTypes;
00227 stringstream currentLine;
00228 string token;
00229
00230 Factory* factory = Factory::instance();
00231
00232 while (1) {
00233 int bytesRead = readLine(is, currentLine);
00234 if (bytesRead == -1)
00235 break;
00236 currentLine >> token;
00237 if (bytesRead == 0 || token.size() == 0 || token[0] == '#')
00238 continue;
00239
00240
00241 if (_renamedTypesLookup.size() > 0) {
00242 map<string, string>::const_iterator foundIt = _renamedTypesLookup.find(token);
00243 if (foundIt != _renamedTypesLookup.end()) {
00244 token = foundIt->second;
00245 }
00246 }
00247
00248 HyperGraph::HyperGraphElement* element = factory->construct(token);
00249
00250 if (! element) {
00251 if (warnedUnknownTypes.count(token) != 1) {
00252 warnedUnknownTypes.insert(token);
00253 cerr << CL_RED(__PRETTY_FUNCTION__ << " unknown type: " << token) << endl;
00254 }
00255 continue;
00256 }
00257
00258 if (dynamic_cast<Vertex*>(element)) {
00259 Vertex* v = static_cast<Vertex*>(element);
00260 int id;
00261 currentLine >> id;
00262 bool r = v->read(currentLine);
00263 if (! r)
00264 cerr << __PRETTY_FUNCTION__ << ": Error reading vertex " << token << " " << id << endl;
00265 v->setId(id);
00266 if (!addVertex(v)) {
00267 cerr << __PRETTY_FUNCTION__ << ": Failure adding Vertex, " << token << " " << id << endl;
00268 delete v;
00269 }
00270 }
00271 else if (dynamic_cast<Edge*>(element)) {
00272 Edge* e = static_cast<Edge*>(element);
00273 int numV = e->vertices().size();
00274 if (_edge_has_id){
00275 int id;
00276 currentLine >> id;
00277 e->setId(id);
00278 }
00279
00280 if (numV == 2) {
00281 int id1, id2;
00282 currentLine >> id1 >> id2;
00283 Vertex* from = vertex(id1);
00284 Vertex* to = vertex(id2);
00285 int doInit=0;
00286 if ((!from || !to) ) {
00287 if (! createEdges) {
00288 cerr << __PRETTY_FUNCTION__ << ": Unable to find vertices for edge " << token << " " << id1 << " <-> " << id2 << endl;
00289 delete e;
00290 } else {
00291 if (! from) {
00292 from=e->createFrom();
00293 from->setId(id1);
00294 addVertex(from);
00295 doInit=2;
00296 }
00297 if (! to) {
00298 to=e->createTo();
00299 to->setId(id2);
00300 addVertex(to);
00301 doInit=1;
00302 }
00303 }
00304 }
00305 if (from && to) {
00306 e->read(currentLine);
00307 e->vertices()[0] = from;
00308 e->vertices()[1] = to;
00309 if (!addEdge(e)) {
00310 cerr << __PRETTY_FUNCTION__ << ": Unable to add edge " << token << " " << id1 << " <-> " << id2 << endl;
00311 delete e;
00312 } else {
00313 switch (doInit){
00314 case 1:
00315 {
00316 HyperGraph::VertexSet fromSet;
00317 fromSet.insert(from);
00318 e->initialEstimate(fromSet, to);
00319 break;
00320 }
00321 case 2:
00322 {
00323 HyperGraph::VertexSet toSet;
00324 toSet.insert(to);
00325 e->initialEstimate(toSet, from);
00326 break;
00327 }
00328 default:;
00329 }
00330 }
00331 }
00332 }
00333 else {
00334 vector<int> ids;
00335 ids.resize(numV);
00336 for (int l = 0; l < numV; ++l)
00337 currentLine >> ids[l];
00338 bool vertsOkay = true;
00339 for (int l = 0; l < numV; ++l) {
00340 e->vertices()[l] = vertex(ids[l]);
00341 if (e->vertices()[l] == 0) {
00342 vertsOkay = false;
00343 break;
00344 }
00345 }
00346 if (! vertsOkay) {
00347 cerr << __PRETTY_FUNCTION__ << ": Unable to find vertices for edge " << token;
00348 for (int l = 0; l < numV; ++l) {
00349 if (l > 0)
00350 cerr << " <->";
00351 cerr << " " << ids[l];
00352 }
00353 delete e;
00354 } else {
00355 bool r = e->read(currentLine);
00356 if (!r || !addEdge(e)) {
00357 cerr << __PRETTY_FUNCTION__ << ": Unable to add edge " << token;
00358 for (int l = 0; l < numV; ++l) {
00359 if (l > 0)
00360 cerr << " <->";
00361 cerr << " " << ids[l];
00362 }
00363 delete e;
00364 }
00365 }
00366
00367 }
00368
00369 }
00370
00371 }
00372
00373 return true;
00374 }
00375
00376 bool OptimizableGraph::load(const char* filename, bool createEdges)
00377 {
00378 ifstream ifs(filename);
00379 if (!ifs) {
00380 cerr << __PRETTY_FUNCTION__ << " unable to open file " << filename << endl;
00381 return false;
00382 }
00383 return load(ifs, createEdges);
00384 }
00385
00386 bool OptimizableGraph::save(const char* filename, int level) const
00387 {
00388 ofstream ofs(filename);
00389 if (!ofs)
00390 return false;
00391 return save(ofs, level);
00392 }
00393
00394 bool OptimizableGraph::save(ostream& os, int level) const
00395 {
00396 Factory* factory = Factory::instance();
00397
00398 set<Vertex*, VertexIDCompare> verticesToSave;
00399 for (HyperGraph::EdgeSet::const_iterator it = edges().begin(); it != edges().end(); ++it) {
00400 OptimizableGraph::Edge* e = static_cast<OptimizableGraph::Edge*>(*it);
00401 if (e->level() == level) {
00402 for (vector<HyperGraph::Vertex*>::const_iterator it = e->vertices().begin(); it != e->vertices().end(); ++it) {
00403 verticesToSave.insert(static_cast<OptimizableGraph::Vertex*>(*it));
00404 }
00405 }
00406 }
00407
00408 for (set<Vertex*, VertexIDCompare>::const_iterator it = verticesToSave.begin(); it != verticesToSave.end(); ++it){
00409 OptimizableGraph::Vertex* v = *it;
00410 string tag = factory->tag(v);
00411 if (tag.size() > 0) {
00412 os << tag << " " << v->id() << " ";
00413 v->write(os);
00414 os << endl;
00415 }
00416 }
00417
00418 EdgeContainer edgesToSave;
00419 for (HyperGraph::EdgeSet::const_iterator it = edges().begin(); it != edges().end(); ++it) {
00420 const OptimizableGraph::Edge* e = dynamic_cast<const OptimizableGraph::Edge*>(*it);
00421 if (e->level() == level)
00422 edgesToSave.push_back(const_cast<Edge*>(e));
00423 }
00424 sort(edgesToSave.begin(), edgesToSave.end(), EdgeIDCompare());
00425
00426 for (EdgeContainer::const_iterator it = edgesToSave.begin(); it != edgesToSave.end(); ++it) {
00427 OptimizableGraph::Edge* e = *it;
00428 string tag = factory->tag(e);
00429 if (tag.size() > 0) {
00430 os << tag << " ";
00431 if (_edge_has_id)
00432 os << e->id() << " ";
00433 for (vector<HyperGraph::Vertex*>::const_iterator it = e->vertices().begin(); it != e->vertices().end(); ++it) {
00434 OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(*it);
00435 os << v->id() << " ";
00436 }
00437 e->write(os);
00438 os << endl;
00439 }
00440 }
00441
00442 return os.good();
00443 }
00444
00445
00446 bool OptimizableGraph::saveSubset(ostream& os, HyperGraph::VertexSet& vset, int level)
00447 {
00448 Factory* factory = Factory::instance();
00449
00450 for (HyperGraph::VertexSet::const_iterator it=vset.begin(); it!=vset.end(); it++){
00451 OptimizableGraph::Vertex* v = dynamic_cast<OptimizableGraph::Vertex*>(*it);
00452 string tag = factory->tag(const_cast<OptimizableGraph::Vertex*>(v));
00453 if (tag.size() > 0) {
00454 os << tag << " " << v->id() << " ";
00455 v->write(os);
00456 os << endl;
00457 }
00458 }
00459 for (HyperGraph::EdgeSet::const_iterator it = edges().begin(); it != edges().end(); ++it) {
00460 OptimizableGraph::Edge* e = dynamic_cast< OptimizableGraph::Edge*>(*it);
00461 if (e->level() != level)
00462 continue;
00463
00464 bool verticesInEdge = true;
00465 for (vector<HyperGraph::Vertex*>::const_iterator it = e->vertices().begin(); it != e->vertices().end(); ++it) {
00466 if (vset.find(*it) == vset.end()) {
00467 verticesInEdge = false;
00468 break;
00469 }
00470 }
00471 if (! verticesInEdge)
00472 continue;
00473
00474 string tag = factory->tag(const_cast<OptimizableGraph::Edge*>(e));
00475 if (tag.size() > 0) {
00476 os << tag << " ";
00477 if (_edge_has_id)
00478 os << e->id() << " ";
00479 for (vector<HyperGraph::Vertex*>::const_iterator it = e->vertices().begin(); it != e->vertices().end(); ++it) {
00480 OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(*it);
00481 os << v->id() << " ";
00482 }
00483 e->write(os);
00484 os << endl;
00485 }
00486
00487 }
00488
00489 return os.good();
00490 }
00491
00492 bool OptimizableGraph::saveSubset(ostream& os, HyperGraph::EdgeSet& eset)
00493 {
00494 Factory* factory = Factory::instance();
00495
00496 std::set<OptimizableGraph::Vertex*> vset;
00497 for (HyperGraph::EdgeSet::const_iterator it = eset.begin(); it != eset.end(); ++it) {
00498 HyperGraph::Edge* e = *it;
00499 for (vector<HyperGraph::Vertex*>::const_iterator it = e->vertices().begin(); it != e->vertices().end(); ++it) {
00500 OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(*it);
00501 vset.insert(v);
00502 }
00503 }
00504
00505 for (std::set<OptimizableGraph::Vertex*>::const_iterator it=vset.begin(); it!=vset.end(); ++it){
00506 OptimizableGraph::Vertex* v = dynamic_cast<OptimizableGraph::Vertex*>(*it);
00507 string tag = factory->tag(const_cast<OptimizableGraph::Vertex*>(v));
00508 if (tag.size() > 0) {
00509 os << tag << " " << v->id() << " ";
00510 v->write(os);
00511 os << endl;
00512 }
00513 }
00514
00515 for (HyperGraph::EdgeSet::const_iterator it = eset.begin(); it != eset.end(); ++it) {
00516 OptimizableGraph::Edge* e = dynamic_cast< OptimizableGraph::Edge*>(*it);
00517 string tag = factory->tag(const_cast<OptimizableGraph::Edge*>(e));
00518 if (tag.size() == 0)
00519 continue;
00520
00521 bool verticesInEdge = true;
00522 for (vector<HyperGraph::Vertex*>::const_iterator it = e->vertices().begin(); it != e->vertices().end(); ++it) {
00523 OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(*it);
00524 if (vset.find(v) == vset.end()) {
00525 verticesInEdge = false;
00526 break;
00527 }
00528 }
00529 if (! verticesInEdge)
00530 continue;
00531
00532 os << tag << " ";
00533 for (vector<HyperGraph::Vertex*>::const_iterator it = e->vertices().begin(); it != e->vertices().end(); ++it) {
00534 OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(*it);
00535 os << v->id() << " ";
00536 }
00537 e->write(os);
00538 os << endl;
00539 }
00540
00541 return os.good();
00542 }
00543
00544 void OptimizableGraph::addGraph(OptimizableGraph* g){
00545 for (HyperGraph::VertexIDMap::iterator it=g->vertices().begin(); it!=g->vertices().end(); it++){
00546 OptimizableGraph::Vertex* v= (OptimizableGraph::Vertex*)(it->second);
00547 if (vertex(v->id()))
00548 continue;
00549 OptimizableGraph::Vertex* v2=v->clone();
00550 v2->edges().clear();
00551 v2->setTempIndex(-1);
00552 addVertex(v2);
00553 }
00554 for (HyperGraph::EdgeSet::iterator it=g->edges().begin(); it!=g->edges().end(); it++){
00555 OptimizableGraph::Edge* e = (OptimizableGraph::Edge*)(*it);
00556 OptimizableGraph::Edge* en = e->clone();
00557 en->resize(e->vertices().size());
00558 int cnt = 0;
00559 for (vector<HyperGraph::Vertex*>::const_iterator it = e->vertices().begin(); it != e->vertices().end(); ++it) {
00560 OptimizableGraph::Vertex* v = (OptimizableGraph::Vertex*) vertex((*it)->id());
00561 assert(v);
00562 en->vertices()[cnt++] = v;
00563 }
00564 addEdge(en);
00565 }
00566 }
00567
00568 int OptimizableGraph::maxDimension() const{
00569 int maxDim=0;
00570 for (HyperGraph::VertexIDMap::const_iterator it=vertices().begin(); it!=vertices().end(); it++){
00571 const OptimizableGraph::Vertex* v= static_cast< const OptimizableGraph::Vertex*>(it->second);
00572 maxDim = std::max(maxDim, v->dimension());
00573 }
00574 return maxDim;
00575 }
00576
00577 void OptimizableGraph::setRenamedTypesFromString(const std::string& types)
00578 {
00579 Factory* factory = Factory::instance();
00580 vector<string> typesMap = strSplit(types, ",");
00581 for (size_t i = 0; i < typesMap.size(); ++i) {
00582 vector<string> m = strSplit(typesMap[i], "=");
00583 if (m.size() != 2) {
00584 cerr << __PRETTY_FUNCTION__ << ": unable to extract type map from " << typesMap[i] << endl;
00585 continue;
00586 }
00587 string typeInFile = trim(m[0]);
00588 string loadedType = trim(m[1]);
00589 if (! factory->knowsTag(loadedType)) {
00590 cerr << __PRETTY_FUNCTION__ << ": unknown type " << loadedType << endl;
00591 continue;
00592 }
00593
00594 _renamedTypesLookup[typeInFile] = loadedType;
00595 }
00596
00597 cerr << "# load look up table" << endl;
00598 for (std::map<std::string, std::string>::const_iterator it = _renamedTypesLookup.begin(); it != _renamedTypesLookup.end(); ++it) {
00599 cerr << "#\t" << it->first << " -> " << it->second << endl;
00600 }
00601 }
00602
00603 bool OptimizableGraph::isSolverSuitable(const SolverProperty& solverProperty, const std::set<int>& vertDims_) const
00604 {
00605 std::set<int> auxDims;
00606 if (vertDims_.size() == 0) {
00607 auxDims = dimensions();
00608 }
00609 const set<int>& vertDims = vertDims_.size() == 0 ? auxDims : vertDims_;
00610 bool suitableSolver = true;
00611 if (vertDims.size() == 2) {
00612 if (solverProperty.requiresMarginalize) {
00613 suitableSolver = vertDims.count(solverProperty.poseDim) == 1 && vertDims.count(solverProperty.landmarkDim) == 1;
00614 }
00615 else {
00616 suitableSolver = solverProperty.poseDim == -1;
00617 }
00618 } else if (vertDims.size() == 1) {
00619 suitableSolver = vertDims.count(solverProperty.poseDim) == 1 || solverProperty.poseDim == -1;
00620 } else {
00621 suitableSolver = solverProperty.poseDim == -1 && !solverProperty.requiresMarginalize;
00622 }
00623 return suitableSolver;
00624 }
00625
00626 std::set<int> OptimizableGraph::dimensions() const
00627 {
00628 std::set<int> auxDims;
00629 for (VertexIDMap::const_iterator it = vertices().begin(); it != vertices().end(); ++it) {
00630 OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(it->second);
00631 auxDims.insert(v->dimension());
00632 }
00633 return auxDims;
00634 }
00635
00636 void OptimizableGraph::preIteration(int iter)
00637 {
00638 HyperGraphActionSet& actions = _graphActions[AT_PREITERATION];
00639 if (actions.size() > 0) {
00640 HyperGraphAction::ParametersIteration params(iter);
00641 for (HyperGraphActionSet::iterator it = actions.begin(); it != actions.end(); ++it) {
00642 (*(*it))(this, ¶ms);
00643 }
00644 }
00645 }
00646
00647 void OptimizableGraph::postIteration(int iter)
00648 {
00649 HyperGraphActionSet& actions = _graphActions[AT_POSTITERATION];
00650 if (actions.size() > 0) {
00651 HyperGraphAction::ParametersIteration params(iter);
00652 for (HyperGraphActionSet::iterator it = actions.begin(); it != actions.end(); ++it) {
00653 (*(*it))(this, ¶ms);
00654 }
00655 }
00656 }
00657
00658 bool OptimizableGraph::addPostIterationAction(HyperGraphAction* action)
00659 {
00660 std::pair<HyperGraphActionSet::iterator, bool> insertResult = _graphActions[AT_POSTITERATION].insert(action);
00661 return insertResult.second;
00662 }
00663
00664 bool OptimizableGraph::addPreIterationAction(HyperGraphAction* action)
00665 {
00666 std::pair<HyperGraphActionSet::iterator, bool> insertResult = _graphActions[AT_PREITERATION].insert(action);
00667 return insertResult.second;
00668 }
00669
00670 bool OptimizableGraph::removePreIterationAction(HyperGraphAction* action)
00671 {
00672 return _graphActions[AT_PREITERATION].erase(action) > 0;
00673 }
00674
00675 bool OptimizableGraph::removePostIterationAction(HyperGraphAction* action)
00676 {
00677 return _graphActions[AT_POSTITERATION].erase(action) > 0;
00678 }
00679
00680 }