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 <queue> 28 #include <deque> 29 #include <vector> 30 #include <assert.h> 31 #include <iostream> 32 #include "hyper_dijkstra.h" 33 #include "g2o/stuff/macros.h" 34 35 namespace g2o{ 36 37 using namespace std; 38 perform(HyperGraph::Vertex * v,HyperGraph::Vertex * vParent,HyperGraph::Edge * e)39 number_t HyperDijkstra::TreeAction::perform(HyperGraph::Vertex* v, HyperGraph::Vertex* vParent, HyperGraph::Edge* e){ 40 (void) v; 41 (void) vParent; 42 (void) e; 43 return std::numeric_limits<number_t>::max(); 44 } 45 perform(HyperGraph::Vertex * v,HyperGraph::Vertex * vParent,HyperGraph::Edge * e,number_t distance)46 number_t HyperDijkstra::TreeAction::perform(HyperGraph::Vertex* v, HyperGraph::Vertex* vParent, HyperGraph::Edge* e, number_t distance){ 47 if (distance==-1) 48 return perform (v,vParent,e); 49 return std::numeric_limits<number_t>::max(); 50 } 51 AdjacencyMapEntry(HyperGraph::Vertex * child_,HyperGraph::Vertex * parent_,HyperGraph::Edge * edge_,number_t distance_)52 HyperDijkstra::AdjacencyMapEntry::AdjacencyMapEntry(HyperGraph::Vertex* child_, HyperGraph::Vertex* parent_, 53 HyperGraph::Edge* edge_, number_t distance_) 54 : _child(child_), _parent(parent_), _edge(edge_), _distance(distance_) {} 55 HyperDijkstra(HyperGraph * g)56 HyperDijkstra::HyperDijkstra(HyperGraph* g): _graph(g) 57 { 58 for (HyperGraph::VertexIDMap::const_iterator it=_graph->vertices().begin(); it!=_graph->vertices().end(); ++it){ 59 AdjacencyMapEntry entry(it->second, 0,0,std::numeric_limits< number_t >::max()); 60 _adjacencyMap.insert(make_pair(entry.child(), entry)); 61 } 62 } 63 reset()64 void HyperDijkstra::reset() 65 { 66 for (HyperGraph::VertexSet::iterator it=_visited.begin(); it!=_visited.end(); ++it){ 67 AdjacencyMap::iterator at=_adjacencyMap.find(*it); 68 assert(at!=_adjacencyMap.end()); 69 at->second=AdjacencyMapEntry(at->first,0,0,std::numeric_limits< number_t >::max()); 70 } 71 _visited.clear(); 72 } 73 74 operator <(const HyperDijkstra::AdjacencyMapEntry & a,const HyperDijkstra::AdjacencyMapEntry & b)75 bool operator<(const HyperDijkstra::AdjacencyMapEntry& a, const HyperDijkstra::AdjacencyMapEntry& b) 76 { 77 return a.distance()>b.distance(); 78 } 79 80 shortestPaths(HyperGraph::VertexSet & vset,HyperDijkstra::CostFunction * cost,number_t maxDistance,number_t comparisonConditioner,bool directed,number_t maxEdgeCost)81 void HyperDijkstra::shortestPaths(HyperGraph::VertexSet& vset, HyperDijkstra::CostFunction* cost, 82 number_t maxDistance, number_t comparisonConditioner, bool directed, number_t maxEdgeCost) 83 { 84 reset(); 85 std::priority_queue< AdjacencyMapEntry > frontier; 86 for (HyperGraph::VertexSet::iterator vit=vset.begin(); vit!=vset.end(); ++vit){ 87 HyperGraph::Vertex* v=*vit; 88 assert(v!=0); 89 AdjacencyMap::iterator it=_adjacencyMap.find(v); 90 if (it == _adjacencyMap.end()) { 91 cerr << __PRETTY_FUNCTION__ << "Vertex " << v->id() << " is not in the adjacency map" << endl; 92 } 93 assert(it!=_adjacencyMap.end()); 94 it->second._distance=0.; 95 it->second._parent=0; 96 frontier.push(it->second); 97 } 98 99 while(! frontier.empty()){ 100 AdjacencyMapEntry entry=frontier.top(); 101 frontier.pop(); 102 HyperGraph::Vertex* u=entry.child(); 103 AdjacencyMap::iterator ut=_adjacencyMap.find(u); 104 if (ut == _adjacencyMap.end()) { 105 cerr << __PRETTY_FUNCTION__ << "Vertex " << u->id() << " is not in the adjacency map" << endl; 106 } 107 assert(ut!=_adjacencyMap.end()); 108 number_t uDistance=ut->second.distance(); 109 110 std::pair< HyperGraph::VertexSet::iterator, bool> insertResult=_visited.insert(u); (void) insertResult; 111 HyperGraph::EdgeSet::iterator et=u->edges().begin(); 112 while (et != u->edges().end()){ 113 HyperGraph::Edge* edge=*et; 114 ++et; 115 116 if (directed && edge->vertex(0) != u) 117 continue; 118 119 for (size_t i = 0; i < edge->vertices().size(); ++i) { 120 HyperGraph::Vertex* z = edge->vertex(i); 121 if (z == u) 122 continue; 123 124 number_t edgeDistance=(*cost)(edge, u, z); 125 if (edgeDistance==std::numeric_limits< number_t >::max() || edgeDistance > maxEdgeCost) 126 continue; 127 number_t zDistance=uDistance+edgeDistance; 128 //cerr << z->id() << " " << zDistance << endl; 129 130 AdjacencyMap::iterator ot=_adjacencyMap.find(z); 131 assert(ot!=_adjacencyMap.end()); 132 133 if (zDistance+comparisonConditioner<ot->second.distance() && zDistance<maxDistance){ 134 ot->second._distance=zDistance; 135 ot->second._parent=u; 136 ot->second._edge=edge; 137 frontier.push(ot->second); 138 } 139 } 140 } 141 } 142 } 143 shortestPaths(HyperGraph::Vertex * v,HyperDijkstra::CostFunction * cost,number_t maxDistance,number_t comparisonConditioner,bool directed,number_t maxEdgeCost)144 void HyperDijkstra::shortestPaths(HyperGraph::Vertex* v, HyperDijkstra::CostFunction* cost, number_t maxDistance, 145 number_t comparisonConditioner, bool directed, number_t maxEdgeCost) 146 { 147 HyperGraph::VertexSet vset; 148 vset.insert(v); 149 shortestPaths(vset, cost, maxDistance, comparisonConditioner, directed, maxEdgeCost); 150 } 151 computeTree(AdjacencyMap & amap)152 void HyperDijkstra::computeTree(AdjacencyMap& amap) 153 { 154 for (AdjacencyMap::iterator it=amap.begin(); it!=amap.end(); ++it){ 155 AdjacencyMapEntry& entry(it->second); 156 entry._children.clear(); 157 } 158 for (AdjacencyMap::iterator it=amap.begin(); it!=amap.end(); ++it){ 159 AdjacencyMapEntry& entry(it->second); 160 HyperGraph::Vertex* parent=entry.parent(); 161 if (!parent){ 162 continue; 163 } 164 HyperGraph::Vertex* v=entry.child(); 165 assert (v==it->first); 166 167 AdjacencyMap::iterator pt=amap.find(parent); 168 assert(pt!=amap.end()); 169 pt->second._children.insert(v); 170 } 171 } 172 173 visitAdjacencyMap(AdjacencyMap & amap,TreeAction * action,bool useDistance)174 void HyperDijkstra::visitAdjacencyMap(AdjacencyMap& amap, TreeAction* action, bool useDistance) 175 { 176 177 typedef std::deque<HyperGraph::Vertex*> Deque; 178 Deque q; 179 // scans for the vertices without the parent (whcih are the roots of the trees) and applies the action to them. 180 for (AdjacencyMap::iterator it=amap.begin(); it!=amap.end(); ++it){ 181 AdjacencyMapEntry& entry(it->second); 182 if (! entry.parent()) { 183 action->perform(it->first,0,0); 184 q.push_back(it->first); 185 } 186 } 187 188 //std::cerr << "q.size()" << q.size() << endl; 189 int count=0; 190 while (! q.empty()){ 191 HyperGraph::Vertex* parent=q.front(); 192 q.pop_front(); 193 ++count; 194 AdjacencyMap::iterator parentIt=amap.find(parent); 195 if (parentIt==amap.end()) { 196 continue; 197 } 198 //cerr << "parent= " << parent << " parent id= " << parent->id() << "\t children id ="; 199 HyperGraph::VertexSet& childs(parentIt->second.children()); 200 for (HyperGraph::VertexSet::iterator childsIt=childs.begin(); childsIt!=childs.end(); ++childsIt){ 201 HyperGraph::Vertex* child=*childsIt; 202 //cerr << child->id(); 203 AdjacencyMap::iterator adjacencyIt=amap.find(child); 204 assert (adjacencyIt!=amap.end()); 205 HyperGraph::Edge* edge=adjacencyIt->second.edge(); 206 207 assert(adjacencyIt->first==child); 208 assert(adjacencyIt->second.child()==child); 209 assert(adjacencyIt->second.parent()==parent); 210 if (! useDistance) { 211 action->perform(child, parent, edge); 212 } else { 213 action->perform(child, parent, edge, adjacencyIt->second.distance()); 214 } 215 q.push_back(child); 216 } 217 //cerr << endl; 218 } 219 220 } 221 connectedSubset(HyperGraph::VertexSet & connected,HyperGraph::VertexSet & visited,HyperGraph::VertexSet & startingSet,HyperGraph * g,HyperGraph::Vertex * v,HyperDijkstra::CostFunction * cost,number_t distance,number_t comparisonConditioner,number_t maxEdgeCost)222 void HyperDijkstra::connectedSubset(HyperGraph::VertexSet& connected, HyperGraph::VertexSet& visited, 223 HyperGraph::VertexSet& startingSet, 224 HyperGraph* g, HyperGraph::Vertex* v, 225 HyperDijkstra::CostFunction* cost, number_t distance, 226 number_t comparisonConditioner, number_t maxEdgeCost) 227 { 228 typedef std::queue<HyperGraph::Vertex*> VertexDeque; 229 visited.clear(); 230 connected.clear(); 231 VertexDeque frontier; 232 HyperDijkstra dv(g); 233 connected.insert(v); 234 frontier.push(v); 235 while (! frontier.empty()){ 236 HyperGraph::Vertex* v0=frontier.front(); 237 frontier.pop(); 238 dv.shortestPaths(v0, cost, distance, comparisonConditioner, false, maxEdgeCost); 239 for (HyperGraph::VertexSet::iterator it=dv.visited().begin(); it!=dv.visited().end(); ++it){ 240 visited.insert(*it); 241 if (startingSet.find(*it)==startingSet.end()) 242 continue; 243 std::pair<HyperGraph::VertexSet::iterator, bool> insertOutcome=connected.insert(*it); 244 if (insertOutcome.second){ // the node was not in the connectedSet; 245 frontier.push(dynamic_cast<HyperGraph::Vertex*>(*it)); 246 } 247 } 248 } 249 } 250 operator ()(HyperGraph::Edge *,HyperGraph::Vertex *,HyperGraph::Vertex *)251 number_t UniformCostFunction::operator () (HyperGraph::Edge* /*edge*/, HyperGraph::Vertex* /*from*/, HyperGraph::Vertex* /*to*/) 252 { 253 return 1.; 254 } 255 256 }; 257