如何使用Boost Graph Library将对象附加到图形的节点和边缘?

时间:2014-03-20 22:34:11

标签: c++ boost boost-graph

我想通过将正确封装的类附加到图形节点来更有效地使用Boost图形库。边缘。我对附加int或POD结构不感兴趣。根据其他StackOverFlow文章的建议,我开发了以下示例应用程序。任何人都可以告诉我我需要在EdgeInfo类上进行编译吗?

我正在使用Visual Studio 2010和Boost 1.54.0。

//------------------------------------------------------------------------
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <iostream>
//------------------------------------------------------------------------
struct VertexInfo
{
    struct Tag
    {
        typedef boost::vertex_property_tag  kind;
        static  std::size_t const           num; // ???
    };
    typedef boost::property<Tag, VertexInfo>    Property;
};
std::size_t const VertexInfo::Tag::num = reinterpret_cast<std::size_t> (&VertexInfo::Tag::num);
//------------------------------------------------------------------------
class EdgeInfo
{
    int     _nWeight;
public:
    int     getWeight () const              {return _nWeight;}
    struct Tag
    {
        typedef boost::edge_property_tag    kind;
        static  std::size_t const           num; // ???
    };
    typedef boost::property<boost::edge_weight_t, int>  Weight;
    typedef boost::property<Tag, EdgeInfo>              Property;
    EdgeInfo (int nWeight = 9999) : _nWeight (nWeight)   {}
};
std::size_t const EdgeInfo::Tag::num = reinterpret_cast<std::size_t> (&EdgeInfo::Tag::num);
//------------------------------------------------------------------------
typedef boost::property<boost::edge_weight_t, int>  EdgeProperty;
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, VertexInfo::Property, EdgeProperty>       GraphWorking;
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, VertexInfo::Property, EdgeInfo::Property> GraphBroken;
//------------------------------------------------------------------------
template<typename GraphType, typename EdgeType> void
dijkstra (GraphType g, EdgeType e)
{
    typedef boost::graph_traits<GraphType>::vertex_descriptor   VertexDesc;
    typedef boost::graph_traits<GraphType>::edge_descriptor     EdgeDesc;

    VertexDesc u = add_vertex (g);
    VertexDesc v = add_vertex (g);
    std::pair<EdgeDesc, bool> result = add_edge (u, v, e, g);
    std::vector<VertexDesc> vecParent (num_vertices (g), 0);

    dijkstra_shortest_paths (g, u, boost::predecessor_map (&vecParent[0]));
}
//------------------------------------------------------------------------
int
main (int argc, char** argv)
{
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
    std::cout   << "Buy a new compiler\n";
#else
    std::cout   << "Your compiler is fine\n";
#endif
    GraphWorking gWorking;
    GraphBroken gBroken;

    dijkstra (gWorking, 3);
    dijkstra (gBroken, EdgeInfo (4));
}
//------------------------------------------------------------------------

1 个答案:

答案 0 :(得分:0)

当我运行你的代码时,我在dijkstra中的距离地图中得到一个numeric_limits错误。

” 错误1错误C2440:'':无法从'int'转换为'D'c:\ Program Files(x86)\ Microsoft Visual Studio 10.0 \ VC \ include \ limits 92 “ 可能来自http://www.boost.org/doc/libs/1_55_0/boost/graph/dijkstra_shortest_paths.hpp

的这一部分
 typedef typename property_traits<DistanceMap>::value_type D;
  D inf = choose_param(get_param(params, distance_inf_t()),
                       (std::numeric_limits<D>::max)());

我认为可能有一种更简单的方法来为节点和边缘绑定一个真正的类。创建顶点和边缘属性类比提供大多数增强算法所需的所有标记属性(索引,权重,颜色等)更麻烦。

不要忘记边缘类!=边缘属性。

edge类实际上是graph_traits :: edge_discriptor。

属性是与每条边相关联的数据。顶点相同。

我会使用捆绑属性并在每个属性中添加指向您的类的指针。

这是一个例子

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/property_map/property_map.hpp>
#include <iostream>

//Fancy Edge class
class EdgeData
{
    int _data;
public:
    EdgeData(){
        _data=0;
    }

    EdgeData(int data){
        _data= data;
    }

    void printHello(){
        std::cout << "hello " << _data << std::endl;
    }


};


//Fancy Vert class
class VertexData
{
    int _data;
public:
    VertexData(){
        _data=0;
    }

    VertexData(int data){
        _data= data;
    }

    void printHello(){
        std::cout << "hello " << _data << std::endl;
    }


};

//bundled properties
struct VertexProps
{
    VertexData* data;
};

struct EdgeProps
{
    size_t weight;
    EdgeData* data;
};


//Graph
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
    VertexProps,EdgeProps> Graph;

//helpers
//Vertex
typedef boost::graph_traits<Graph>::vertex_descriptor Vertex; 
//Edge
typedef boost::graph_traits<Graph>::edge_descriptor Edge;



//------------------------------------------------------------------------
template<typename GraphType> void
  templateFunction (GraphType g)
{
    typedef boost::graph_traits<GraphType>::edge_iterator edge_iter;
    std::pair<edge_iter, edge_iter> ep;
    edge_iter ei, ei_end;
    ep = edges(g);
    ei_end = ep.second;

    for (ei = ep.first; ei != ei_end; ++ei){
        g[*ei].data->printHello();
    }

}

//if you want to alter the graph use referenced &graph
template<typename GraphType,typename EdgePropType> void
  templateFuctionProps(GraphType &g, EdgePropType e)
{
    typedef boost::graph_traits<GraphType>::vertex_descriptor   VertexDesc;

    VertexDesc v = add_vertex(g);
    VertexDesc u = add_vertex(g);

    //add an edge with the Edge property
    add_edge(v,u,e,g);
}
//------------------------------------------------------------------------
int
main (int argc, char** argv)
{
    Graph g;

    //vertex holder
    std::vector<Vertex> verts;

    //add some verts
    for(size_t i = 0; i < 5; ++i){
        Vertex v = add_vertex(g);
        g[v].data = new VertexData(i%2);
        verts.push_back(v);
    }

    //add some edges
    for(size_t i = 0; i < 4; ++i){
        std::pair<Edge,bool> p = add_edge(verts.at(i),verts.at(i+1),g);
        Edge e = p.first;
        g[e].data = new EdgeData(i%3);
        g[e].weight = 5;
    }

    //iterate edges and call a class function
    typedef boost::graph_traits<Graph>::edge_iterator edge_iter;
    std::pair<edge_iter, edge_iter> ep;
    edge_iter ei, ei_end;
    ep = edges(g);
    ei_end = ep.second;
    for (ei = ep.first; ei != ei_end; ++ei){
        g[*ei].data->printHello();
    }


    std::cout << "Iterate with template with template " << std::endl;
    templateFunction(g);


    //Use an edge property in a function
    EdgeProps edgeProp;
    edgeProp.weight = 5;
    edgeProp.data = new EdgeData(150);
    std::cout << "Modity graph with template function " << std::endl;
    templateFuctionProps(g,edgeProp);

    std::cout << "Iterate again with template" << std::endl;
    templateFunction(g);

    //getting the weight property
    boost::property_map<Graph,size_t EdgeProps::*>::type w
        = get(&EdgeProps::weight, g);


    std::cout << "Print weights" << std::endl;
    ep = edges(g);
    ei_end = ep.second;
    for (ei = ep.first; ei != ei_end; ++ei){
        std::cout << w[*ei] << std::endl;
    }

    std::cin.get();
}
//------------------------------------------------------------------------

我也看到你正在使用vecS,这意味着向量和边都存储为具有固定顺序的向量。

您可以只使用一个类来存储Edge和Vertex类,并使用指向图的顶点贴图或边缘贴图的指针。

我不知道你对这个项目的目标,但我肯定会有更高级别的课程,而不是在幕后管理所有这些提升的东西。意味着在具有索引查找的向量中存储类将被隐藏并封装在想要使用您的漂亮图类的应用程序中。