【问题标题】:How to create boost subgraph with setS vertices list?如何使用 setS 顶点列表创建提升子图?
【发布时间】:2015-06-06 23:33:26
【问题描述】:

以下代码有错误:

AAA.cpp:23:15:   required from here
   .../boost/include/boost/graph/subgraph.hpp:333:5: error: static assertion failed: (!is_same<edge_index_type,
   boost::detail::error_property_not_found>::value)

AAA.cpp:27:21: error: no matching function for call to ‘add_vertex(foo(int, char**)::<anonymous enum>, Graph&)’

AAA.cpp:27:21: note: candidates are:
   .../boost/include/boost/graph/subgraph.hpp: In instantiation of ‘boost::subgraph<Graph>::subgraph(boost::subgraph<Graph>::vertices_size_type,
   const graph_property_type&) [with Graph =
   boost::adjacency_list<boost::setS, boost::setS, boost::directedS,
   boost::no_property, boost::no_property, boost::no_property,
   boost::setS>; boost::subgraph<Graph>::vertices_size_type = long
   unsigned int; boost::subgraph<Graph>::graph_property_type =
   boost::no_property]’:
#include <boost/config.hpp>
#include <iostream>
#include <boost/graph/subgraph.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_utility.hpp>

int foo(int,char*[])
{
    using namespace boost;
    typedef subgraph< 
        adjacency_list<
            setS, 
            setS, 
            directedS,
            no_property,
            no_property,
            no_property, // graph prop
            setS // edgelist
            > 
        > Graph;

    const int N = 6;
    Graph G0(N);
    enum { A, B, C, D, E, F}; 

    Graph& G1 = G0.create_subgraph();
    add_vertex(C, G1); // global vertex C becomes local A1 for G1

    return 0;
}

如果我将顶点列表的 setS 更改为 vecS,则可以编译它。 如何使用 setS 顶点列表创建 boost 子图?

谢谢,

【问题讨论】:

    标签: c++ boost graph


    【解决方案1】:

    首先,对于 VertexContainer,它不会使用 vecS 进行编译:

    要创建图和子图,首先创建根图对象。这里我们使用 adjacency_list 作为底层图实现。底层图类型需要有 vertex_index 和 edge_index 内部属性,所以我们在邻接表中添加一个边索引属性。 (docs)

    所以让我们添加一些东西。现在它编译:

    Live On Coliru

    #include <boost/config.hpp>
    #include <iostream>
    #include <boost/graph/subgraph.hpp>
    #include <boost/graph/adjacency_list.hpp>
    #include <boost/graph/graph_utility.hpp>
    
    int main()
    {
        using namespace boost;
        using containerS = vecS;
        typedef subgraph< adjacency_list<containerS, containerS, directedS,
                property<vertex_index_t, size_t>,
                property<edge_index_t, size_t>
            >
        > Graph;
    
        const int N = 6;
        Graph G0(N);
        enum { A, B, C, D, E, F}; 
    
        Graph& G1 = G0.create_subgraph();
        Graph::vertex_descriptor CG1 = add_vertex(G1);
        Graph::vertex_descriptor EG1 = add_vertex(G1);
    
        add_edge(CG1, EG1, G1);
    
        print_graph(G0);
        std::cout << "SUBGRAPH:\n";
        print_graph(G1);
    }
    

    打印

    0 --> 
    1 --> 
    2 --> 
    3 --> 
    4 --> 
    5 --> 
    6 --> 7 
    7 --> 
    SUBGRAPH:
    0 --> 1 
    1 --> 
    

    使用setS

    坦率地说,尽管文档间接表明可以选择 listSsetS 之类的东西,但老实说,我认为这行不通。

    问题似乎在于local_to_globalm_global_vertex 是如何实现的。

    这可能是人为限制/未实现的功能。您可能想在开发者列表/Trac 问题中提出这个问题。

    【讨论】:

    【解决方案2】:

    我发现 1) setS 可以用作外边和边列表 2)必须定义vertex_index和edge_index 3)我们也可以同时使用捆绑属性

    以下代码有效。

    #include <boost/config.hpp>
    #include <iostream>
    #include <boost/graph/subgraph.hpp>
    #include <boost/graph/adjacency_list.hpp>
    #include <boost/graph/graph_utility.hpp>
    
    int foo(int,char*[])
    {
        using namespace boost;
      typedef adjacency_list_traits<vecS, vecS, directedS> Traits;
    
      struct EEE {
          int p;
      };
    
      struct VVV {
          int p;
      };
    
      typedef subgraph< 
        adjacency_list<
            setS, 
            vecS, 
            directedS,
            property<vertex_color_t, int, VVV>,
            property<edge_index_t, int, EEE>,
            no_property, // graph prop
            setS // edgelist
            > 
        > Graph;
    
     const int N = 6;
     Graph G0(N);
     enum { A, B, C, D, E, F};     // for conveniently refering to vertices in G0
    
     Graph& G1 = G0.create_subgraph();
     Graph& G2 = G0.create_subgraph();
     enum { A1, B1, C1 };          // for conveniently refering to vertices in G1
      enum { A2, B2 };              // for conveniently refering to vertices in G2
    
      add_vertex(C, G1); // global vertex C becomes local A1 for G1
      add_vertex(E, G1); // global vertex E becomes local B1 for G1
      add_vertex(F, G1); // global vertex F becomes local C1 for G1
    
      add_vertex(A, G2); // global vertex A becomes local A1 for G2
      add_vertex(B, G2); // global vertex B becomes local B1 for G2
    
      add_edge(A, B, G0);
      add_edge(B, C, G0);
      add_edge(B, D, G0);
      add_edge(E, B, G0);
      add_edge(E, F, G0);
      add_edge(F, D, G0);
    
      add_edge(A1, C1, G1); // (A1,C1) is subgraph G1 local indices for (C,F).
    
      Graph::vertex_iterator vi, vi_end;
      VVV vvv;
      EEE eee;
      for (tie(vi, vi_end) = vertices(G0); vi != vi_end; ++vi) {
         G0[*vi].p = 42;
         auto e = add_edge(*vi, *vi, G0);
         G0[e.first] = eee;
      }
      return 0;
    }
    

    【讨论】:

      【解决方案3】:

      正如sehe 所指出的,我们可以轻松实现local_to_global,例如:

      vertex_descriptor local_to_global(vertex_descriptor u_local) const
          { return is_root() ? u_local : m_global_vertex[get(get(vertex_index, m_graph), u_local)]; }
      

      在我的情况下,我必须在保持顶点迭代器/描述符稳定的同时添加和删除顶点,因此我需要使用listS 作为我的顶点描述符。奇怪的是,boost 似乎并没有解决这个问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-27
        • 2014-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-03
        • 1970-01-01
        相关资源
        最近更新 更多