Ticket #3078: BGLTest.4.cpp

File BGLTest.4.cpp, 4.8 KB (added by Artyom Arabadji <sneg.vx@…>, 13 years ago)

Simplified version

Line 
1#include <iostream>
2#include <deque>
3
4#include <boost/graph/adjacency_list.hpp>
5#include <boost/graph/visitors.hpp>
6#include <boost/graph/graph_utility.hpp>
7
8/***
9 * Type defines for our graph ( Called MotionGraph )
10 ***/
11typedef boost::adjacency_list< boost::listS, boost::vecS, boost::bidirectionalS > MyGraph;
12typedef boost::graph_traits< MyGraph >::vertex_descriptor MyVertex;
13typedef boost::graph_traits< MyGraph >::edge_descriptor MyEdge;
14
15/***
16 * @desc
17 * PathRecorder class is a template for creating
18 * path recorders which utilise visitor concepts
19 * in BGL. I.e. as a search algorithm runs,
20 * PathRecorder is called to fill in a "predecessor map"
21 * which records how to get to a specific vertex and stores
22 * edges with their targets as keys.
23 ***/
24class PathRecorder
25{
26 typedef boost::property_map< MyGraph, boost::vertex_index_t >::type VertexId_PMap;
27 typedef boost::iterator_property_map< std::vector< MyEdge >::iterator, VertexId_PMap, MyEdge, MyEdge & > PredEdgeMap;
28
29public:
30 /**
31 * @desc
32 * Update an entry inside a map
33 **/
34 void put( MyVertex target, MyEdge e )
35 {
36 boost::put( predEdgeMap, target, e );
37 }
38
39 /**
40 * @desc
41 * Get MyEdge to target
42 **/
43 MyEdge getEdge( MyVertex target ) const
44 {
45 return boost::get( predEdgeMap, target );
46 }
47
48 PathRecorder( const MyGraph &graph ) : g( graph ),
49 edges( std::vector< MyEdge >( boost::num_vertices( g ) ) ),
50 Vertex_id( boost::get( boost::vertex_index, g ) ),
51 predEdgeMap( edges.begin(), Vertex_id )
52 {
53 }
54 ~PathRecorder( void ) { }
55 PathRecorder( const PathRecorder & ) { }
56protected:
57 const MyGraph g;
58 std::vector< MyEdge > edges;
59 VertexId_PMap Vertex_id;
60 PredEdgeMap predEdgeMap;
61};
62
63
64/**
65@desc
66ForwardEdge is a visitor which tries to decide whether
67to replace a newly discovered edge with the edge inside
68a DFS tree (predecessor map).
69Forward Edge is an edge (U,V) and both U, V have already
70been discovered by DFS.
71**/
72struct TestForwardEdge : public boost::base_visitor< TestForwardEdge >
73{
74 typedef boost::on_forward_or_cross_edge event_filter;
75
76 TestForwardEdge( PathRecorder &__pr ) : pr( __pr ) { }
77
78 void operator()( MyEdge e, const MyGraph &g )
79 {
80 // simplified method, simply overwrite
81 pr.put( boost::target( e, g ), e );
82 }
83
84 PathRecorder pr;
85};
86
87/**
88@desc
89PredRecorder adds a tree edge to predecessor map.
90Tree edge is the first edge for pair of vertices
91(U, V) that was ever discovered.
92**/
93struct TestPredRecorder : public boost::base_visitor< TestPredRecorder >
94{
95 typedef boost::on_tree_edge event_filter;
96
97 TestPredRecorder( PathRecorder &__pr ) : pr( __pr ) { }
98
99 void operator()( MyEdge e, const MyGraph &g )
100 {
101 // simplified method, simply overwrite
102 pr.put( boost::target( e, g ), e );
103 }
104
105 PathRecorder pr;
106};
107
108
109void getPath( std::deque< MyVertex > &agenda, MyVertex start, MyVertex end, MyGraph &g, PathRecorder &pr )
110{
111 MyEdge cur = pr.getEdge( end );
112
113 while( cur.m_eproperty )
114 {
115 agenda.push_front( boost::target( cur, g ) );
116 agenda.push_front( boost::source( cur, g ) );
117
118 cur = pr.getEdge( boost::source( cur, g ) );
119 }
120
121 if( agenda.empty() || agenda.front() != start )
122 {
123 agenda.clear();
124 }
125}
126
127void search( std::deque< MyVertex > &agenda, MyVertex start, MyVertex end, MyGraph &g )
128{
129 std::vector< unsigned short > c( boost::num_vertices( g ) );
130
131 typedef boost::property_map< MyGraph, boost::vertex_index_t >::type VertexId_PMap;
132 VertexId_PMap vertex_id = boost::get( boost::vertex_index, g );
133 typedef boost::iterator_property_map< std::vector< unsigned short >::iterator, VertexId_PMap, unsigned short, unsigned short & > ColourMap;
134
135 PathRecorder pr( g );
136
137 boost::depth_first_visit(
138 g,
139 start,
140 boost::make_dfs_visitor( boost::make_list( TestPredRecorder( pr ), TestForwardEdge( pr ) ) ),
141 ColourMap( c.begin(), vertex_id )
142 );
143
144 getPath( agenda, start, end, g, pr );
145}
146
147void test( MyGraph &g, MyVertex one, MyVertex two )
148{
149 std::deque< MyVertex > mg;
150
151 search( mg, one, two, g );
152
153 if( mg.empty() )
154 {
155 std::cout << "Destination unreachable" << std::endl;
156 return;
157 }
158
159 std::cout << "Path from " << one << " to " << two << ":" << std::endl;
160
161 for( int i = 0; i < mg.size(); ++i )
162 {
163 std::cout << mg.at( i ) << ( i != mg.size() - 1 ? " -> " : "\n" );
164 }
165}
166
167int main( void )
168{
169 int vertices = 5;
170
171 MyGraph g( vertices );
172
173 typedef std::pair< MyVertex, MyVertex > Pair;
174
175 Pair edges[] = {
176 Pair( 0,1 ),
177 Pair( 2,0 ),
178 Pair( 3,2 ),
179 Pair( 4,1 ),
180 Pair( 0,3 ),
181 Pair( 2,4 ),
182 Pair( 3,4 ),
183 Pair( 4,1 ),
184 Pair( 2,1 ),
185 Pair( 2,1 )
186 };
187
188 for( int i = 0; i < 10; ++i )
189 {
190 boost::add_edge( edges[i].first, edges[i].second, g );
191 }
192
193 test( g, 1, 4 );
194 test( g, 4, 0 );
195 test( g, 3, 0 );
196 test( g, 2, 3 );
197 test( g, 1, 0 );
198
199 return 0;
200}
201