简体   繁体   English

Boost有向图:比较顶点的边

[英]Boost directed graph: comparing edges of a vertex

A brief background: I'm building a semantic graph, using BGL directed graphs with an adjacency list: 简要背景:我正在使用带有邻接列表的BGL有向图来构建语义图:

class SemanticGraph
{
  public:
    typedef std::shared_ptr< Node > Node_ptr;
    typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::directedS, Node_ptr > Graph;
    typedef boost::graph_traits< Graph >::vertex_descriptor Vertex;
    typedef boost::graph_traits< Graph >::edge_descriptor Edge;

One of the things I need to be able to do, is process a smaller graph (a subgraph) into my main graph. 我需要做的一件事是将一个较小的图(一个子图)处理到我的主图中。

Doing so, involves copying the Node pointers if needed, copying the vertices from the subgraph into the main graph if they don't already exist, and most importantly, copying the edges for each vertex found in the subgraph, into the main one, if not already established. 为此,需要复制节点指针;如果子顶点不存在,则将其从子图中复制到主图中;最重要的是,如果需要,将子图中找到的每个顶点的边复制到主图中。尚未建立。

The first two tasks are not that complicated. 前两个任务并不那么复杂。 However, I cannot for the life of me, find a way to compare two edges: 但是,我无法终生,无法找到一种比较两个优势的方法:

 void AddSubGraph( SemanticGraph subgraph )
 {
      typename boost::graph_traits<Graph>::vertex_iterator it, end;
      Vertex vertex;

      for ( auto node : subgraph._nodes )
      {
        if ( !findNode( node ) )
           _nodes.push_back( node );

        boost::tie( it, end ) = boost::vertices( _graph );
        std::find_if( it, end, [&]( const Vertex vertex ){ return _graph[*it]->Hash() == node->Hash(); });

        if ( it == end )
          vertex = boost::add_vertex( node, _graph );
        else
          vertex = boost::vertex( *it, _graph );

        boost::tie( it, end ) = boost::vertices( subgraph._graph );
        std::find_if( it, end, [&]( const Vertex vertex ){ return subgraph._graph[*it]->Hash() == node->Hash(); });

        auto subgraph_vertex = boost::vertex( *it, subgraph._graph );
        typename boost::graph_traits<Graph>::out_edge_iterator a, z;

        // Iterate subgraph's vertex out edges
        for ( boost::tie ( a, z ) = boost::out_edges( subgraph_vertex, subgraph._graph );
              a != z;
              ++a )
        {
           typename boost::graph_traits<Graph>::out_edge_iterator my_edge, edge_end;
           boost::tie ( my_edge, edge_end ) = boost::out_edges( vertex, _graph );
           // How can I see if the same edge as the one pointed by edge iterator a, exists in my vertex's edges?
           std::find_if( my_edge, edge_end, [&]( const Edge edge ){ return edge == a; });
        }
      }
    }

The compiler throws a warning at the last std::find_if above ^^: 编译器在^^上方的最后一个std :: find_if处发出警告:

‘const Edge {aka const boost::detail::edge_desc_impl<boost::directed_tag, long unsigned int>}’ is not derived from ‘const std::pair<_T1, _T2>’

Hinting that my lambda captured parameter should be a pair (I'm guessing an actual edge?). 提示我的lambda捕获参数应该是一对(我猜是实际边缘吗?)。

So, my question is: How can I find if that similar edge exists in my vertex's out edges? 因此,我的问题是: 如何找到顶点的外边缘中是否存在相似的边缘?

you declared a as an iterator: 您声明a一个迭代器:

typename boost::graph_traits<Graph>::out_edge_iterator a, z;

It doesn't make sense to compare an iterator to an edge. 将迭代器与边缘进行比较没有任何意义。

Instead, dereference the iterator to get the edge it is "pointing to": 相反,请取消引用迭代器以获取其“指向”的边缘:

std::find_if(my_edge, edge_end, 
     [&](const Edge edge) { return edge == *a; });

This compiles for me: See it Live on Coliru 这为我编译: 在Coliru上实时观看

Other problems: 其他问题:

  • std::find_if(it, end, [&](const Vertex vertex) { return _graph[*it]->Hash() == node->Hash(); });

    • statement has no effect (the result of the find is unused) 语句无效(未使用查找结果)
    • you are looking things up by a hash?! 您正在通过哈希查找事物吗? This is almost certainly a design error. 这几乎可以肯定是设计错误。 If Hash() returns a hash, you CANNOT use it to identify nodes. 如果Hash()返回哈希,则不能使用它来标识节点。 Instead hash-tables use it to identify the the bucket in which to sort the node. 相反,哈希表使用它来标识在其中对节点进行排序的存储桶。 However, to identify a node, you need to do an equality test (different Nodes can share the same hash) 但是,要标识节点,您需要进行相等性测试 (不同的节点可以共享相同的哈希)
  • the lambdas take their arguments by value. Lambda通过值来接受论点。 This is inefficient 这是低效的

    Typical code would see 典型的代码会看到

     vertex_iterator match = std::find_if(it, end, [&](Vertex const& vertex) { return _graph[*it] == node; });` if (end != match) { // yes `match` is a match } 
#include <boost/graph/adjacency_list.hpp>
#include <memory>

struct Node
{
    int id;
    size_t Hash() const { return id; }
    bool operator<(const Node& other) const { return id < other.id; }
    bool operator==(const Node& other) const { return id==other.id; }
};

class SemanticGraph
{
public:
    typedef std::shared_ptr< Node > Node_ptr;
    typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::directedS, Node_ptr > Graph;
    typedef boost::graph_traits< Graph >::vertex_descriptor Vertex;
    typedef boost::graph_traits< Graph >::edge_descriptor Edge;

    std::vector<Node_ptr> _nodes;
    Graph _graph;

    bool findNode(Node_ptr const& n) const { return std::find(begin(_nodes), end(_nodes), n) != end(_nodes); }

    void AddSubGraph(SemanticGraph subgraph)
    {
        typename boost::graph_traits<Graph>::vertex_iterator it, end;
        Vertex vertex;
        for(auto node : subgraph._nodes)
        {
            if(!findNode(node))
            {
                _nodes.push_back(node);
            }
            boost::tie(it, end) = boost::vertices(_graph);
            std::find_if(it, end, [&](const Vertex vertex) { return _graph[*it]->Hash() == node->Hash(); });
            if(it == end)
                vertex = boost::add_vertex(node, _graph);
            else
                vertex = boost::vertex(*it, _graph);

            boost::tie(it, end) = boost::vertices(subgraph._graph);

            std::find_if(it, end, [&](const Vertex vertex) { return subgraph._graph[*it]->Hash() == node->Hash(); });

            auto subgraph_vertex = boost::vertex(*it, subgraph._graph);
            typename boost::graph_traits<Graph>::out_edge_iterator a, z;

            // Iterate subgraph's vertex out edges
            for(boost::tie(a, z) = boost::out_edges(subgraph_vertex, subgraph._graph);
                    a != z;
                    ++a)
            {
                typename boost::graph_traits<Graph>::out_edge_iterator my_edge, edge_end;
                boost::tie(my_edge, edge_end) = boost::out_edges(vertex, _graph);
                // How can I see if the same edge as the one pointed by edge iterator a, exists in my vertex's edges?
                std::find_if(my_edge, edge_end, [&](const Edge edge) { return edge == *a; });
            }
        }
    }
};

int main()
{
    SemanticGraph g;
}

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

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