【问题标题】:How do I attach objects to the nodes and edges of a graph using the Boost Graph Library?如何使用 Boost 图形库将对象附加到图形的节点和边?
【发布时间】:2014-03-20 22:34:11
【问题描述】:

我想通过将正确封装的类附加到图形节点和边来更有效地使用 Boost 图形库。我对附加 int 或 POD 结构不感兴趣。根据其他 StackOverFlow 文章的建议,我开发了以下示例应用程序。谁能告诉我我需要在 EdgeInfo 类上添加什么魔法来编译这个东西?

我正在使用带有 Boost 1.54.0 的 Visual Studio 2010。

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

【问题讨论】:

  • 我承认我没有动力去解决这个问题。你看过Bundled properties吗?它们似乎是一种更易于使用的方法。另外,您知道BOOST_INSTALL_PROPERTY 显然减轻了一些繁文缛节吗?

标签: c++ boost boost-graph


【解决方案1】:

当我运行您的代码时,由于 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 类!= 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 类,并带有指向图的顶点图或边图的指针。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-21
    • 1970-01-01
    • 2011-03-03
    相关资源
    最近更新 更多