简体   繁体   English

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

[英]How do I attach objects to the nodes and edges of a graph using the Boost Graph Library?

I would like to use the Boost Graph Library more effectively by attaching properly encapsulated classes to graph nodes & edges. 我想通过将正确封装的类附加到图形节点和边上来更有效地使用Boost Graph Library。 I am not interested in attaching int's or POD struct's. 我对附加int或POD结构不感兴趣。 Following suggestions on other StackOverFlow articles, I have developed the following sample app. 根据其他StackOverFlow文章的建议,我开发了以下示例应用程序。 Can anybody tell me the magic I need to sprinkle onto the EdgeInfo class to make this thing compile? 有人能告诉我我需要撒在EdgeInfo类上的魔力才能使它编译吗?

I am using Visual Studio 2010 with Boost 1.54.0. 我将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));
}
//------------------------------------------------------------------------

When I run your code i get an error in numeric_limits that results from a distance map in dijkstra. 当我运行您的代码时,由于dijkstra中的距离图导致了numeric_limits错误。

" Error 1 error C2440: '' : cannot convert from 'int' to 'D' c:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\include\\limits 92 " probably from this part of http://www.boost.org/doc/libs/1_55_0/boost/graph/dijkstra_shortest_paths.hpp “错误1错误C2440:”:无法从'int'转换为'D'c:\\ Program Files(x86)\\ Microsoft Visual Studio 10.0 \\ VC \\ include \\ limits 92“可能来自http:// www的这一部分.boost.org / DOC /库/ 1_55_0 /升压/图形/ 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)());

I think there may be an easier way to tie a real class for your nodes and edges. 我认为,为节点和边缘绑定真实类可能是一种更简单的方法。 Its more trouble than its worth to create vertex and edge property classes that will provide all the needed tagged properties (index, weight, color, etc) needed for most boost algorihtms. 创建值得提供大多数提升算法所需的所有必需的标记属性(索引,权重,颜色等)的顶点和边属性类,比其价值更大。

Don't forget Edge class != Edge property. 不要忘记Edge类!= Edge属性。

The edge class is really the graph_traits::edge_discriptor. 边缘类实际上是graph_traits :: edge_discriptor。

Properties are the data associated with each edge. 属性是与每个边关联的数据。 Same for vertex. 顶点相同。

I would use bundled properties and add a pointer to your class in each one. 我将使用捆绑的属性,并在每个属性中添加一个指向您的类的指针。

Here is an example 这是一个例子

#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();
}
//------------------------------------------------------------------------

Also I see you are using vecS, meaning that both vectors and edges are stored as vectors with a fixed ordering. 另外,我看到您正在使用vecS,这意味着向量和边均以固定顺序存储为向量。

You could just have a class that stores your Edge and Vertex classes with a pointer to the vertex map or edge map for the graph. 您可能只有一个类,用于存储Edge和Vertex类以及指向该图的顶点映射或边缘映射的指针。

I don't know your goals for this project, but I would definitely have higher level classes than manage all of this boost stuff behind the scenes. 我不知道您对这个项目的目标,但是与在幕后管理所有这些增强功能相比,我肯定有更高层次的课程。 Meaning storing classes in a vector with an index look up would be hidden and encapsulated from applications that want to use your nice graph class. 意味着将类存储在具有索引查找的向量中,对于希望使用漂亮的图类的应用程序将被隐藏和封装。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM