如何使用setS顶点列表创建boost子图?

时间:2015-06-06 23:33:27

标签: c++ boost graph

以下代码有错误:

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子图?

谢谢,

3 个答案:

答案 0 :(得分:1)

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

  

要创建图形和子图形,首先要创建根图形对象。这里我们使用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问题上提出这个问题。

答案 1 :(得分:0)

我找到了 1)setS可以用作outedges和edge列表 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;
}

答案 2 :(得分:0)

正如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作为我的顶点描述符。令人感到奇怪的是,似乎没有修复提升。