TuttleOFX
1
|
00001 // custom host 00002 #include <tuttle/common/utils/global.hpp> 00003 #include <tuttle/host/graph/InternalGraph.hpp> 00004 #include <tuttle/host/graph/GraphExporter.hpp> 00005 #include <tuttle/host/graph/Visitors.hpp> 00006 00007 #include <boost/graph/graph_utility.hpp> 00008 //#include <boost/bind.hpp> 00009 00010 #include <iostream> 00011 #include <vector> 00012 00013 namespace tuttle { 00014 namespace host { 00015 namespace graph { 00016 00017 class TestVertex 00018 { 00019 public: 00020 typedef std::string Key; 00021 public: 00022 TestVertex() {} 00023 TestVertex( const std::string& name ) : _name( name ) {} 00024 ~TestVertex() {} 00025 std::string _name; 00026 const std::string& getName() const { return _name; } 00027 const std::string& getKey() const { return getName(); } 00028 friend std::ostream& operator<<( std::ostream& os, const TestVertex& v ); 00029 }; 00030 inline std::ostream& operator<<( std::ostream& os, const TestVertex& v ) 00031 { 00032 os /*<< " _name:"*/ << v._name; 00033 return os; 00034 } 00035 00036 class TestEdge 00037 { 00038 public: 00039 TestEdge() {} 00040 TestEdge( const std::string& in, const std::string& out ) 00041 : _nameIn( in ) 00042 , _nameOut( out ) 00043 , _name( out + "->" + in ) 00044 {} 00045 00046 ~TestEdge() {} 00047 std::string _nameIn; 00048 std::string _nameOut; 00049 std::string _name; 00050 const std::string& getName() const { return _name; } 00051 const std::string& getInAttrName() const { return _nameIn; } 00052 friend std::ostream& operator<<( std::ostream& os, const TestEdge& v ); 00053 }; 00054 inline std::ostream& operator<<( std::ostream& os, const TestEdge& e ) 00055 { 00056 os << e._name; 00057 return os; 00058 } 00059 00060 template<class G> 00061 struct vertex_label_writer 00062 { 00063 vertex_label_writer( const G& g ) : _g( g ) {} 00064 template<class Vertex> 00065 void operator()( std::ostream& out, const Vertex& v ) const 00066 { 00067 out << dotEntry( "type", "vertex" ); 00068 out << dotEntry( "label", _g[v].getName() ); 00069 } 00070 00071 private: 00072 const G& _g; 00073 }; 00074 00075 template<class G> 00076 struct edge_label_writer 00077 { 00078 edge_label_writer( const G& g ) : _g( g ) {} 00079 template<class Edge> 00080 void operator()( std::ostream& out, const Edge& e ) const 00081 { 00082 out << dotEntry( "type", "vertex" ); 00083 out << dotEntry( "label", _g[e].getName() ); 00084 } 00085 00086 private: 00087 const G& _g; 00088 }; 00089 00090 template<template<typename> class T, class G> 00091 T<G> make( const G& g ) 00092 { 00093 return T<G>( g ); 00094 } 00095 00096 template<> 00097 void exportAsDOT<TestVertex, TestEdge>( std::ostream& os, const InternalGraph<TestVertex, TestEdge >& g ) 00098 { 00099 std::map<std::string, std::string> graph_attr, vertex_attr, edge_attr; 00100 graph_attr["size"] = "6,6"; 00101 graph_attr["rankdir"] = "LR"; 00102 graph_attr["ratio"] = "fill"; 00103 graph_attr["label"] = "TuttleOFX"; 00104 vertex_attr["shape"] = "circle"; 00105 vertex_attr["color"] = "dodgerblue4"; 00106 vertex_attr["fontcolor"] = "dodgerblue4"; 00107 edge_attr["style"] = "dashed"; 00108 edge_attr["minlen"] = "1"; 00109 edge_attr["color"] = "darkslategray"; 00110 edge_attr["fontcolor"] = "darkslategray"; 00111 00112 using namespace boost; 00113 boost::write_graphviz( os, 00114 g.getGraph(), 00115 make<vertex_label_writer>( g.getGraph() ), 00116 make<edge_label_writer>( g.getGraph() ), 00117 boost::make_graph_attributes_writer( graph_attr, vertex_attr, edge_attr ) ); 00118 00119 } 00120 00121 } 00122 } 00123 } 00124 00125 #define BOOST_TEST_MODULE tuttle_boostgraph 00126 #include <tuttle/test/unit_test.hpp> 00127 00128 BOOST_AUTO_TEST_SUITE( tuttle_boostgraph_suite ) 00129 00130 using namespace boost::unit_test; 00131 00132 BOOST_AUTO_TEST_CASE( test_export ) 00133 { 00134 using namespace tuttle::host; 00135 00136 typedef graph::InternalGraph<graph::TestVertex, graph::TestEdge> InternalGraph; 00137 typedef InternalGraph::vertex_descriptor Descriptor; 00138 typedef std::map<std::string, int> InstanceCountMap; 00139 00140 std::string n1( "v1" ); 00141 std::string n2( "v2" ); 00142 std::string n3( "v3" ); 00143 00144 InternalGraph graph; 00145 std::map<std::string, Descriptor> nodesDescriptor; 00146 nodesDescriptor[n1] = graph.addVertex( graph::TestVertex( n1 ) ); 00147 nodesDescriptor[n2] = graph.addVertex( graph::TestVertex( n2 ) ); 00148 nodesDescriptor[n3] = graph.addVertex( graph::TestVertex( n3 ) ); 00149 00150 graph.addEdge( nodesDescriptor[n1], nodesDescriptor[n2], graph::TestEdge( n1, n2 ) ); 00151 graph.addEdge( nodesDescriptor[n2], nodesDescriptor[n3], graph::TestEdge( n2, n3 ) ); 00152 00153 TUTTLE_TLOG( TUTTLE_TRACE, "graph:" ); 00154 boost::print_graph( graph.getGraph() ); 00155 00156 InternalGraph graphT; 00157 graphT.copyTransposed( graph ); 00158 00159 TUTTLE_TLOG( TUTTLE_TRACE, "graphT:" ); 00160 boost::print_graph( graphT.getGraph() ); 00161 00162 graph::exportAsDOT<graph::TestVertex, graph::TestEdge>( "boostgraphtest.dot", graph ); 00163 graph::exportAsDOT<graph::TestVertex, graph::TestEdge>( "boostgraphTtest.dot", graphT ); 00164 00165 TUTTLE_TLOG( TUTTLE_TRACE, "__________________________________________________" ); 00166 TUTTLE_TLOG( TUTTLE_TRACE, "graph:" ); 00167 // std::vector<boost::default_color_type > colormap(boost::num_vertices(graph.getGraph())); 00168 graph::visitor::Test_dfs<InternalGraph> testVisitorA( graph ); 00169 // boost::depth_first_search( graph.getGraph(), boost::root_vertex(nodesDescriptor[n1]), boost::visitor(testVisitorA) );//, colormap ); 00170 graph.depthFirstVisit( testVisitorA, nodesDescriptor[n1] ); 00171 00172 TUTTLE_TLOG( TUTTLE_TRACE, "__________________________________________________" ); 00173 TUTTLE_TLOG( TUTTLE_TRACE, "graphT:" ); 00174 00175 std::map<std::string, InternalGraph::vertex_descriptor> mmap; 00176 for( InternalGraph::vertex_iterator i = vertices( graphT.getGraph() ).first, iEnd = vertices( graphT.getGraph() ).second; 00177 i != iEnd; 00178 ++i ) 00179 { 00180 TUTTLE_TLOG( TUTTLE_TRACE, "pp: " << graphT.getGraph()[*i]._name ); 00181 mmap[graphT.getGraph()[*i]._name] = *i; 00182 // TUTTLE_TLOG( TUTTLE_TRACE, "pp: "<< graphT.getGraph()[*i]._name ); 00183 } 00184 00185 graph::visitor::Test_dfs<InternalGraph> testVisitorB( graph ); 00186 // boost::depth_first_search( graphT.getGraph(), boost::visitor(testVisitorB) ); 00187 00188 graphT.depthFirstVisit( testVisitorB, mmap["v3"] ); 00189 00190 // graph_traits<graph_type>::out_edge_iterator ei, edge_end; 00191 // for( boost::tie(ei, edge_end) = out_edges(*i, g); ei != edge_end; ++ei ) 00192 // std::cout << " --" << name[*ei] << "--> " << id[target(*ei, g)] << " "; 00193 } 00194 00195 BOOST_AUTO_TEST_CASE( check_cycle ) 00196 { 00197 using namespace tuttle::host; 00198 00199 typedef graph::InternalGraph<graph::TestVertex, graph::TestEdge> InternalGraph; 00200 typedef InternalGraph::vertex_descriptor Descriptor; 00201 typedef std::map<std::string, int> InstanceCountMap; 00202 00203 std::string n1( "v1" ); 00204 std::string n2( "v2" ); 00205 std::string n3( "v3" ); 00206 00207 InternalGraph graph; 00208 std::map<std::string, Descriptor> nodesDescriptor; 00209 nodesDescriptor[n1] = graph.addVertex( graph::TestVertex( n1 ) ); 00210 nodesDescriptor[n2] = graph.addVertex( graph::TestVertex( n2 ) ); 00211 nodesDescriptor[n3] = graph.addVertex( graph::TestVertex( n3 ) ); 00212 00213 graph.addEdge( nodesDescriptor[n1], nodesDescriptor[n2], graph::TestEdge( n1, n2 ) ); 00214 graph.addEdge( nodesDescriptor[n2], nodesDescriptor[n3], graph::TestEdge( n2, n3 ) ); 00215 00216 BOOST_CHECK_THROW( 00217 graph.addEdge( nodesDescriptor[n3], nodesDescriptor[n2], graph::TestEdge( n3, n2 ) ), 00218 exception::Logic ); 00219 BOOST_CHECK_THROW( 00220 graph.addEdge( nodesDescriptor[n3], nodesDescriptor[n1], graph::TestEdge( n3, n1 ) ), 00221 exception::Logic ); 00222 00223 TUTTLE_TLOG( TUTTLE_TRACE, "graph:" ); 00224 boost::print_graph( graph.getGraph() ); 00225 } 00226 00227 BOOST_AUTO_TEST_CASE( test_create_add_remove_simple ) 00228 { 00229 typedef boost::adjacency_list< boost::setS, boost::vecS, boost::bidirectionalS > TestGraph; 00230 TestGraph graph; 00231 00232 // add vertices 00233 TestGraph::vertex_descriptor vd1 = boost::add_vertex( graph ); 00234 TestGraph::vertex_descriptor vd2 = boost::add_vertex( graph ); 00235 TestGraph::vertex_descriptor vd3 = boost::add_vertex( graph ); 00236 TestGraph::vertex_descriptor vd4 = boost::add_vertex( graph ); 00237 00238 BOOST_CHECK_EQUAL( boost::num_vertices( graph ), 4 ); 00239 BOOST_CHECK_EQUAL( boost::num_edges( graph ), 0 ); 00240 00241 boost::add_edge( vd1, vd2, graph ); 00242 boost::add_edge( vd2, vd3, graph ); 00243 boost::add_edge( vd3, vd4, graph ); 00244 00245 BOOST_CHECK_EQUAL( boost::num_vertices( graph ), 4 ); 00246 BOOST_CHECK_EQUAL( boost::num_edges( graph ), 3 ); 00247 00248 boost::clear_vertex( vd3, graph ); 00249 boost::remove_vertex( vd3, graph ); 00250 00251 BOOST_CHECK_EQUAL( boost::num_vertices( graph ), 3 ); 00252 BOOST_CHECK_EQUAL( boost::num_edges( graph ), 1 ); 00253 00254 boost::add_edge( 00255 graph.vertex_set()[1], 00256 graph.vertex_set()[2], 00257 graph ); 00258 00259 BOOST_CHECK_EQUAL( boost::num_vertices( graph ), 3 ); 00260 BOOST_CHECK_EQUAL( boost::num_edges( graph ), 2 ); 00261 } 00262 00263 /* 00264 * Stupid test to check insertion, remove of vertices and edges. 00265 */ 00266 BOOST_AUTO_TEST_CASE( test_create_add_remove ) 00267 { 00268 using namespace tuttle::host; 00269 typedef boost::adjacency_list< boost::listS, boost::vecS, boost::undirectedS, graph::TestVertex, graph::TestEdge > TestGraph; 00270 TestGraph graph; 00271 00272 // add vertices 00273 for( std::size_t i = 0; i < 20; ++i ) 00274 { 00275 TestGraph::vertex_descriptor vd = boost::add_vertex( graph ); 00276 graph[vd]._name = "a" + boost::lexical_cast<std::string > ( i ); 00277 } 00278 00279 BOOST_CHECK_EQUAL( boost::num_vertices( graph ), 20 ); 00280 BOOST_CHECK_EQUAL( boost::num_edges( graph ), 0 ); 00281 00282 // add edges 00283 for( std::size_t i = 5; i < 8; ++i ) 00284 { 00285 TestGraph::edge_descriptor ed = boost::add_edge( 00286 graph.vertex_set()[i], 00287 graph.vertex_set()[i+1], 00288 graph ).first; 00289 } 00290 00291 BOOST_CHECK_EQUAL( boost::num_vertices( graph ), 20 ); 00292 BOOST_CHECK_EQUAL( boost::num_edges( graph ), 3 ); 00293 00294 // remove some vertices 00295 for( std::size_t i = 0; i < 5; ++i ) 00296 { 00297 TestGraph::vertex_descriptor vd = graph.vertex_set()[0]; 00298 boost::clear_vertex( vd, graph ); // remove in and out edges 00299 boost::remove_vertex( vd, graph ); // finally remove the vertex from the boost graph 00300 } 00301 00302 BOOST_CHECK_EQUAL( boost::num_vertices( graph ), 20-5 ); 00303 BOOST_CHECK_EQUAL( boost::num_edges( graph ), 3 ); 00304 00305 // edges 00306 for( std::size_t i = 9; i < 14; ++i ) 00307 { 00308 TestGraph::edge_descriptor ed = boost::add_edge( 00309 graph.vertex_set()[i], 00310 graph.vertex_set()[i+1], 00311 graph ).first; 00312 } 00313 00314 BOOST_CHECK_EQUAL( boost::num_vertices( graph ), 20-5 ); 00315 BOOST_CHECK_EQUAL( boost::num_edges( graph ), 8 ); 00316 00317 // add some vertices 00318 for( std::size_t i = 0; i < 7; ++i ) 00319 { 00320 TestGraph::vertex_descriptor vd = boost::add_vertex( graph ); 00321 graph[vd]._name = "b" + boost::lexical_cast<std::string > ( i ); 00322 } 00323 00324 BOOST_CHECK_EQUAL( boost::num_vertices( graph ), 20 - 5 + 7 ); 00325 BOOST_CHECK_EQUAL( boost::num_edges( graph ), 8 ); 00326 00327 // //zero some_property for all vertices 00328 // for( Graph::vertex_iterator i = vertices( graph ).first, iEnd = vertices( graph ).second; 00329 // i != iEnd; 00330 // ++i ) 00331 // { 00332 // TUTTLE_TLOG( TUTTLE_TRACE, ": " << graph[*i]._name ); 00333 // } 00334 } 00335 00336 00337 BOOST_AUTO_TEST_SUITE_END() 00338