c++ - Boost 有向图 : comparing edges of a vertex

标签 c++ algorithm boost graph

简要背景: 我正在构建语义图,使用带有邻接表的 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;

我需要做的一件事是将一个较小的图(子图)处理到我的主图中。

这样做包括在需要时复制节点指针,如果顶点不存在则将子图中的顶点复制到主图中,最重要的是,将子图中找到的每个顶点的边复制到主图中一个,如果尚未建立的话。

前两个任务并不那么复杂。 但是,我一辈子都找不到比较两条边的方法:

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

编译器在上面的最后一个 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>’

暗示我的 lambda 捕获参数应该是一对(我猜是一个实际的边缘?)。

所以,我的问题是: 如何找到我的顶点的出边中是否存在相似边?

最佳答案

您将 a 声明为迭代器:

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

将迭代器与边进行比较没有意义。

相反,取消引用迭代器以获得它“指向”的边缘:

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

这为我编译:查看 Live on Coliru

其他问题:

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

    • 语句没有效果(查找的结果未被使用)
    • 你是在用散列来查找东西吗?!这几乎可以肯定是设计错误。如果 Hash() 返回一个散列,您不能使用它来识别节点。相反,哈希表使用它来标识要在其中对节点进行排序的存储桶。但是,要识别一个节点,你需要做一个相等性测试(不同的节点可以共享相同的散列)
  • lambda 按值获取参数。这是低效的

    典型的代码会看到

    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;
}

关于c++ - Boost 有向图 : comparing edges of a vertex,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20450011/

相关文章:

arrays - 确定 array2 是否是 array1 的子数组的最有效算法?

algorithm - 对一组 3D 点进行三角测量

c++ - 如何在boost::program_options::variable_map中存储数据?

c++ - 是否可以使用基类和派生类来实现 Qt Application Plugin?

c++ - 初始化模板数组

algorithm - Disjoint Set Forest 来调度作业

C++ "Proper"异常处理方式

c++ - Asio tcp 套接字上的未初始化读取错误

c++ - 为什么字符串文字中的值会发生变化

c++ - 在 C++ 中初始化动态数组的正确方法