提升图不允许循环引用

时间:2014-05-21 00:03:37

标签: c++ boost boost-graph

我是新手来推广图表,正在研究最适合我需求的图表。我需要创建一个依赖图并给出一个顶点,我需要访问进出边。我正在考虑使用Directed = bidirectionalS的adjacency_list。

但是我需要确保当我调用add_edge并导致循环引用时它必须输出错误。我似乎无法找到如何做到这一点。

3 个答案:

答案 0 :(得分:2)

一般来说,只有一种方法可以发现图形是否是一个循环:遍历所有节点。

因此,您只需要在添加每条边后检查图形是否仍然是循环的。

但是,根据您添加节点的方式,您可以进行优化。如果,例如通过遍历DFS顺序的源节点来添加边缘,您可以只跟踪节点"看到"在当前路径中并拒绝为这些路径添加边缘。

基于topological_sort Live On Coliru 的简单示例:

#include <iostream>  // for std::cout
#include <boost/graph/adjacency_list.hpp>

#include <boost/graph/graphviz.hpp>
#include <boost/graph/topological_sort.hpp>
#include <boost/function_output_iterator.hpp>

using namespace boost;

int main()
{
    srand(time(0));

    typedef adjacency_list<vecS, vecS, bidirectionalS> Graph;
    const int num_vertices = 10;
    Graph g(num_vertices);

    // add random edges to the graph object
    for (size_t i = 0; i < 10; ++i)
    {
        auto f = rand()%num_vertices,
             s = rand()%num_vertices;

        add_edge(f, s, g);
        try {
            topological_sort(g, boost::make_function_output_iterator([](int){}));
        } catch(not_a_dag const& e)
        {
            remove_edge(f, s, g);
            std::cerr << "dropped edge: " << e.what() << "\n";
        }
    }

    write_graphviz(std::cout, g);
}

创建像

这样的随机DAG

enter image description here

答案 1 :(得分:0)

在增强图中,双向表示边将具有源顶点和目标顶点。 以下是它的例子:

#include <QtCore/QCoreApplication>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/subgraph.hpp>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
using namespace std;
using namespace boost;


typedef boost::subgraph<boost::adjacency_list< boost::listS,
        boost::vecS,
        boost::bidirectionalS,
        boost::property<boost::vertex_index_t, int , property<boost::vertex_color_t, boost::default_color_type > > ,
        boost::property<boost::edge_index_t,int, property<boost::edge_color_t , default_color_type> > > >
        Graph;

 const int num_vertices = 5;
  Graph g(num_vertices);

  add_edge(0, 1, g);
  add_edge(1, 2, g);
  add_edge(1, 3, g);
  add_edge(2, 4, g);
  add_edge(3, 4, g);

  boost::graph_traits<Graph>::vertex_iterator VertexItr, VertexItr_end;
  boost::graph_traits<Graph>::in_edge_iterator in, in_end;
  boost::graph_traits<Graph>::out_edge_iterator out,out_end;

   typedef boost::graph_traits < Graph >::adjacency_iterator adjacency_iterator;

   // This loop is for getting in edges at vertex
  cout<<"In Edge :- "<<endl;

  for(boost::tie(VertexItr,VertexItr_end) = vertices(g); VertexItr != VertexItr_end; ++VertexItr) {
    cout << *VertexItr << " <-- ";
    for (boost::tie(in,in_end) = in_edges(*VertexItr, g); in != in_end; ++in)
      cout << source(*in, g) << "  ";
    cout << endl;
  }

  // This loop is for getting out edges from vertex
  cout<<endl<<"Out Edge :- "<<endl;
  for(boost::tie(VertexItr,VertexItr_end) = vertices(g); VertexItr != VertexItr_end; ++VertexItr) {
      cout<<*VertexItr<<"--->";
    for (boost::tie(out,out_end) = out_edges(*VertexItr, g); out != out_end; ++out)
      cout << target(*out, g) << "  ";
      cout << endl;
  }

  // This loop is for getting the neighbour vertices of vertex
  typedef boost::property_map<Graph, boost::vertex_index_t>::type IndexMap;
    IndexMap index = get(boost::vertex_index, g);
    cout<<"Adjacent vertices"<<endl;
    for(boost::tie(VertexItr,VertexItr_end) = vertices(g); VertexItr != VertexItr_end; ++VertexItr) {
        cout<<*VertexItr<<"--->";
    std::pair<adjacency_iterator, adjacency_iterator> neighbors =
      boost::adjacent_vertices(vertex(*VertexItr,g), g);

    for(; neighbors.first != neighbors.second; ++neighbors.first)
      {
      std::cout << index[*neighbors.first] << " ";
      }
    cout<<endl;
    }

return a.exec();
}

答案 2 :(得分:0)

我在boost文档中找到了讨论如何检测依赖关系的这一部分:

http://www.boost.org/doc/libs/1_55_0/libs/graph/doc/file_dependency_example.html#sec:cycles

但是对于adjacency_list,VertexList和EdgeList必须是vecS类型。这里有关于此的讨论: How to print a boost graph in graphviz with one of the properties displayed?