繁体   English   中英

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

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

我想通过将正确封装的类附加到图形节点和边上来更有效地使用Boost Graph Library。 我对附加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));
}
//------------------------------------------------------------------------

当我运行您的代码时,由于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 /库/ 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)());

我认为,为节点和边缘绑定真实类可能是一种更简单的方法。 创建值得提供大多数提升算法所需的所有必需的标记属性(索引,权重,颜色等)的顶点和边属性类,比其价值更大。

不要忘记Edge类!= 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类以及指向该图的顶点映射或边缘映射的指针。

我不知道您对这个项目的目标,但是与在幕后管理所有这些增强功能相比,我肯定有更高层次的课程。 意味着将类存储在具有索引查找的向量中,对于希望使用漂亮的图类的应用程序将被隐藏和封装。

暂无
暂无

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

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