【问题标题】:Boost Graph edge comparison not workingBoost Graph边缘比较不起作用
【发布时间】:2016-01-21 10:33:13
【问题描述】:

我正在尝试用图表做一些统计数据(比较 2 个图表)。但是当我比较边缘时会出现问题。

所以,我创建了两个带有一些边的图,然后是一些用于顶点和边操作的模板。对于顶点,它工作得很好,但对于边缘,它不能正常工作。

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/reverse_graph.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/graph/graph_utility.hpp>
typedef boost::adjacency_list < boost::vecS, boost::vecS,
                            boost::undirectedS > Graph;

template <typename T> std::set<T> operator-(const std::set<T>& a,
                                            const std::set<T>& b)
{
    std::set<T> r;
    std::set_difference(
                        a.begin(), a.end(),
                        b.begin(), b.end(),
                        std::inserter(r, r.end()));

    return r;
}

template <typename T> std::set<T> operator/(const std::set<T>& a,
                                            const std::set<T>& b)
{
    std::set<T> r;
    std::set_intersection(
                          a.begin(), a.end(),
                          b.begin(), b.end(),
                          std::inserter(r, r.end()));

    return r;
}



void compare(const Graph& a, const Graph& b)
{
    std::set<Graph::vertex_descriptor > av, bv, samev, extrav, missingv;
    std::set<Graph::edge_descriptor> ae, be, re, samee, extrae, missinge;

    BGL_FORALL_VERTICES_T(v, a, Graph) av.insert(v);
    BGL_FORALL_VERTICES_T(v, b, Graph) bv.insert(v);
    samev    = (av / bv);
    extrav   = (bv - av);
    missingv = (av - bv);


    BGL_FORALL_EDGES_T(e, a, Graph) ae.insert(e);
    BGL_FORALL_EDGES_T(e, b, Graph) be.insert(e);

    samee    = (ae / be);
    extrae   = (be - ae);
    missinge = (ae - be);

    // TODO(silgon): reverse_graph
    // boost::reverse_graph<Graph> r(b);
    // BGL_FORALL_EDGES_T(e, r, Graph) re.insert(e);
    std::cout << "---- Vertices ----\n"
              << "same: " << samev.size() << std::endl
              << "extra: " << extrav.size() << std::endl
              << "missing: " << missingv.size() << std::endl;

    std::cout << "---- Edges ----\n"
              << "same: " << samee.size() << std::endl
              << "extra: " << extrae.size() << std::endl
              << "missing: " << missinge.size() << std::endl;
}

int main()
{
    Graph a;
    {
        boost::graph_traits<Graph>::vertex_descriptor v, u, y;
        u = boost::vertex(1, a);
        v = boost::vertex(2, a);
        y = boost::vertex(3, a);
        boost::add_edge(u, v, a);
    }
    Graph b;
    {
        boost::graph_traits<Graph>::vertex_descriptor v, u, y;
        u = vertex(1, b);
        v = vertex(2, b);
        y = vertex(3, b);
        boost::add_edge(u, v, b);
        boost::add_edge(y, v, b);
    }

    const char* name = "123456";
    std::cout << "---Graph1---" << "\n";
    boost::print_graph(a);
    std::cout << "Edges: ";
    boost::print_edges(a,name);
    std::cout << "---Graph2---" << "\n";
    boost::print_graph(b);
    std::cout << "Edges: ";
    boost::print_edges(b,name);

    compare(a,b);
}

程序的结果如下:

---Graph1---
0 <--> 
1 <--> 2 
2 <--> 1 
Edges: (2,3) 
---Graph2---
0 <--> 
1 <--> 2 
2 <--> 1 3 
3 <--> 2 
Edges: (2,3) (4,3) 
---- Vertices ----
same: 3
extra: 1
missing: 0
---- Edges ----
same: 0
extra: 2
missing: 1

您可以看到其中一条边是相同的 (2,3),但是在执行操作时它没有考虑到它,因此在结果中它说相同:0,并且额外或缺失的结果都不起作用.

【问题讨论】:

  • Graph 的确切 typedef 是什么,即您使用哪种图形表示?这会影响edge_descriptor 使用的实际类型以及edge_descriptor 存储的内容。我怀疑在您的情况下它不仅仅是一对vertex_descriptors,因此不一定在图表之间具有可比性。
  • 对不起,我忘了把它放在代码中。我这里也有代码:ideone.com/D1Gk1w
  • 顺便说一下,我刚刚检查了无向图和有向图,结果是一样的

标签: c++ boost graph boost-graph


【解决方案1】:

深入研究 Boost 的 edge_descriptor 实现(在 boost/graph/detail/edge.hpp 中,我们发现每个边描述符都存储了源和目标 vertex_descriptors,但还有一个指向边属性的指针。对于两条边,这个指针是不同的vertex_descriptors 在其他方面是相同的。

这意味着您需要定义自己的 edge_descriptor 比较器,用于您的 std::sets 和 set_intersection/set_difference 操作,例如像这样:

struct edge_cmp
{
  bool operator () (const Graph::edge_descriptor& a, const Graph::edge_descriptor& b) const
  {
    if (a.m_source < b.m_source) { return true; }
    if (a.m_source > b.m_source) { return false; }
    return (a.m_target < b.m_target);
  }
};

这种类型的比较器对象必须传递给您构造的所有集合,以及交集/差集调用。

I've forked your code on ideone 并进行了相应的修改。输出:

---- Vertices ----
same: 3
extra: 1
missing: 0
---- Edges ----
same: 1
extra: 1
missing: 0

【讨论】:

    【解决方案2】:

    作为我的问题的临时解决方案,而不是:

    std::set<Graph::edge_descriptor> ae
    BGL_FORALL_EDGES_T(e, a, Graph) ae.insert(e)
    

    我为边缘做了以下代码。

    std::set<std::pair<unsigned long, unsigned long> > ae;
    BGL_FORALL_EDGES_T(e, ga, Graph) gae.insert(std::make_pair(e.m_source, 
                                                               e.m_target));
    

    问题是boost图的边缘有“m_eproperty”,我真的不知道为什么会出现,它包含像0x125d0c0这样的值。然后我根据边缘的源和目标创建了一对,然后我以与上面相同的方式(使用模板)进行评估。

    【讨论】:

      猜你喜欢
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 2020-01-11
      • 1970-01-01
      • 1970-01-01
      • 2014-11-18
      • 2014-10-24
      • 2012-06-08
      相关资源
      最近更新 更多