【问题标题】:How to access edge information in Boost Graph?如何访问 Boost Graph 中的边缘信息?
【发布时间】:2020-01-11 11:37:46
【问题描述】:

主要问题:

我能够创建一个图实现,并将信息结构分配给顶点和边:

struct vertex_info {std::string name;};
struct edge_info {std::string name;};

typedef boost::adjacency_list<
  boost::vecS,
  boost::vecS,
  boost::undirectedS,
  vertex_info,
  edge_info> UndirectedGraph;

对于UndirectedGraphg 的实例,我可以轻松地遍历顶点并访问它们的信息:

for(size_t i=0; i<boost::num_vertices(g); i++){
  std::cout << g[i].name << std::endl;
}

但我无法弄清楚如何对边缘做同样的事情。我遇到了一些迭代器来遍历所有边缘,但是我无法将这些边缘作为某种对象或具有属性的东西来访问。如何获取g的边缘信息?

一个最小的工作演示:

#include <iostream>
#include <utility>
#include <vector>
#include <string>

#include "boost/graph/graph_traits.hpp"
#include "boost/graph/adjacency_list.hpp"

int main(int argc, char *argv[])
{

  //Add vertex information struct
  struct vertex_info {
    std::string name;
  };

  //Add edge information struct
  struct edge_info {
    std::string name;
  };

  //Typedef my graph implimentation
  typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, vertex_info, edge_info> UndirectedGraph;

  //Our set of edges, and count N: (0-7) and 8
  enum {C, D, G, I, S, J, L, H, N};
  const char *name = "CDGISJLH";

  //Create a vector of edges
  typedef std::pair<int, int> Edge;
  std::vector<Edge> edgeVec;
  edgeVec.push_back(Edge(C,D));
  edgeVec.push_back(Edge(D,G));
  edgeVec.push_back(Edge(I,G));
  edgeVec.push_back(Edge(G,L));
  edgeVec.push_back(Edge(H,G));
  edgeVec.push_back(Edge(I,S));
  edgeVec.push_back(Edge(S,J));
  edgeVec.push_back(Edge(L,J));
  edgeVec.push_back(Edge(H,J));

  //Now we can initialize our graph using iterators from our above vector
  UndirectedGraph g(edgeVec.begin(), edgeVec.end(), N);

  std::cout << num_edges(g) << "\n";  //Outputs: 9

  //loop over vertices, access "name" property
  for(size_t i=0; i<boost::num_vertices(g); i++){
    //And add information to the edges
    g[i].name = "foo";
  }

  //We can access the first vertice and print the property
  std::cout << g[0].name << std::endl; //Outputs: foo

  //Edge iterator for or graph
  typedef boost::graph_traits<UndirectedGraph>::edge_iterator edge_iterator;

  //Iterate through all the edges
  std::pair<edge_iterator, edge_iterator> ei = boost::edges(g);
  for(edge_iterator edge_iter = ei.first; edge_iter != ei.second; ++edge_iter) {
   //How can I access the edge property???

  }
}

【问题讨论】:

  • 试过edge_iter-&gt;name?文档说“Dereferencing an edge iterator gives an edge object.”-参考boost.org/doc/libs/1_35_0/libs/graph/doc/quick_tour.html
  • @jweyrich 你会这么认为,对,但不幸的是:‘class boost::detail::edge_desc_impl&lt;boost::undirected_tag, long unsigned int&gt;’ has no member named ‘name’; did you mean ‘Base’?
  • 根据文档,取消引用 edge_iter 指针应该会给您一个边缘对象 - 在您的情况下,它的类型是 edge_info 并具有名为 name 的命名成员。也许我以某种方式误读了文档。
  • @jweyrich,是的,我也这样解释文档,但似乎不起作用。而且我找不到简单的解决方法。这就是发生的事情:coliru.stacked-crooked.com/a/5d0766e1770c179b。现在,我将只使用像 map&lt;pair&gt; 这样的单独容器来存储边缘信息,直到我弄清楚为止。

标签: c++ c++11 boost graph


【解决方案1】:

可能不是完全您正在寻找的,但确实实现了您所追求的

#include <iostream>
#include <utility>
#include <vector>
#include <string>

#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>

namespace boost {
enum edge_myname_t { edge_myname };
BOOST_INSTALL_PROPERTY(boost::edge, myname);
}

int main(int argc, char* argv[]) {
  // Add vertex information struct
  struct vertex_info {
    std::string name;
  };

  // Add edge information struct
  //struct edge_info {
    //std::string name;
  //};

  using EdgeName = boost::property<boost::edge_myname_t, std::string>;

  // Typedef my graph implimentation
  using UndirectedGraph =
      boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,
                            vertex_info, EdgeName>;

  // Our set of edges, and count N: (0-7) and 8
  enum { C, D, G, I, S, J, L, H, N };
  const char* name = "CDGISJLH";

  // Create a vector of edges
  //using Edge = std::pair<int, int>;
  //std::vector<Edge> edgeVec;
  //edgeVec.push_back(Edge(C, D));
  //edgeVec.push_back(Edge(D, G));
  //edgeVec.push_back(Edge(I, G));
  //edgeVec.push_back(Edge(G, L));
  //edgeVec.push_back(Edge(H, G));
  //edgeVec.push_back(Edge(I, S));
  //edgeVec.push_back(Edge(S, J));
  //edgeVec.push_back(Edge(L, J));
  //edgeVec.push_back(Edge(H, J));

  // Now we can initialize our graph using iterators from our above vector
  UndirectedGraph g(N);
  //UndirectedGraph g(edgeVec.begin(), edgeVec.end(), N);

  boost::add_edge(C, D, EdgeName("#1"), g);
  boost::add_edge(D, G, EdgeName("#2"), g);
  boost::add_edge(I, G, EdgeName("#3"), g);
  boost::add_edge(G, L, EdgeName("#4"), g);
  boost::add_edge(H, G, EdgeName("#5"), g);
  boost::add_edge(I, S, EdgeName("#6"), g);
  boost::add_edge(S, J, EdgeName("#7"), g);
  boost::add_edge(L, J, EdgeName("#8"), g);
  boost::add_edge(H, J, EdgeName("#9"), g);

  boost::property_map<UndirectedGraph, boost::edge_myname_t>::type get_name =
      boost::get(boost::edge_myname, g);

  std::cout << num_edges(g) << "\n";  // Outputs: 9

  // loop over vertices, access "name" property
  for (size_t i = 0; i < boost::num_vertices(g); i++) {
    // And add information to the edges
    g[i].name = "foo";
  }

  // We can access the first vertice and print the property
  std::cout << g[0].name << std::endl;  // Outputs: foo

  // Edge iterator for or graph
  using EdgeIterator = boost::graph_traits<UndirectedGraph>::edge_iterator;

  // Iterate through all the edges
  std::pair<EdgeIterator, EdgeIterator> ei = boost::edges(g);
  for (EdgeIterator edge_iter = ei.first; edge_iter != ei.second; ++edge_iter) {
    // How can I access the edge property???
    std::cout << get_name[*edge_iter] << "\n";
  }
}

我只是针对自己的可读性问题稍微修改了一些代码。

作为参考,请查看this

【讨论】:

  • 谢谢,这似乎是一个很好的解决方法,但幸运的是我在没有额外的 Boost 糖的情况下让它工作。我发布了我的答案。
【解决方案2】:

我通过这个例子找出了问题:https://www.boost.org/doc/libs/1_71_0/libs/graph/doc/bundles.html

修复:

虽然我仍然不完全了解它是如何工作的。看来您必须使用edge_iter 作为g 的某种索引:

//Edge iterator for or graph
typedef boost::graph_traits<MRFGraph>::edge_iterator edge_iterator;

//Iterate through all the edges
std::pair<edge_iterator, edge_iterator> ei = boost::edges(g);
for(edge_iterator edge_iter = ei.first; edge_iter != ei.second; ++edge_iter) {
  g[*edge_iter].name = "bar";
  std::cout << *edge_iter << ": " << g[*edge_iter].name << std::endl;
}

输出:

如果我将它添加到最小的工作演示中,它会产生以下输出:

9
foo
(0,1): bar
(1,2): bar
(3,2): bar
(2,6): bar
(7,2): bar
(3,4): bar
(4,5): bar
(6,5): bar
(7,5): bar

【讨论】:

    猜你喜欢
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-06
    • 2021-05-20
    • 2019-08-01
    • 1970-01-01
    相关资源
    最近更新 更多