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