【问题标题】:Can I get boost::write_graphviz to write only the edges?我可以让 boost::write_graphviz 只写边缘吗?
【发布时间】:2014-08-06 05:10:53
【问题描述】:

我试图让 BGL 输出一个只有边缘的文件,因为我正在做一个最大连接组件并且我不想擦除顶点但如果没有边缘我也不想绘制它们.

我现在的点文件是:

graph G {
0;
1;
2;
3;
4;
5;
6;
7;
8;
9;
10;
11;
12;
0--1 [label="-3"];
0--5 [label="-2"];
2--3 [label="-8"];
3--8 [label="-4"];
4--5 [label="-1"];
4--6 [label="-6"];
4--7 [label="-5"];
4--8 [label="-10"];
8--9 [label="-9"];
}

我通过运行打印它

boost::write_graphviz(myfile, G, boost::default_writer(), make_edge_writer(w_map));

make_edge_writer(w_map) 确保我打印出重量(忽略负号,我实际上是在做一个最大生成树,但我的玩具示例有正边)。

现在,graphviz 在我的正确图形中绘制了 9 个顶点,以及单独的顶点 {10、11、12)。如果我手动将我的点文件编辑为:

graph G {
0--1 [label="-3"];
0--5 [label="-2"];
2--3 [label="-8"];
3--8 [label="-4"];
4--5 [label="-1"];
4--6 [label="-6"];
4--7 [label="-5"];
4--8 [label="-10"];
8--9 [label="-9"];
}

然后运行graphviz,我得到相同的图减去多余的顶点!这基本上意味着graphviz不需要事先知道顶点,对吧?

那么,有谁知道我怎样才能让write_graphviz 事先不写顶点索引?我不想删除这些顶点,因为在实际示例中,多余的顶点可能在图中,然后我的顶点编号与我的输入不对应..

另外,这真的没什么大不了的,但它一直困扰着我,我想知道是否有人知道该怎么做。我尝试从 boost::default_writer() 更改为我自己的代码(没有做任何事情),但似乎没有任何区别。

【问题讨论】:

    标签: c++ boost graph


    【解决方案1】:

    三段式回答

    • 在 Graphviz 中预定义顶点很有用

    你想过滤掉节点

    • 您可以调整PropertyWriter
    • 您可以调整图形渲染器

    我建议第一个(因为“表达你的意图”)或后者(因为“关注点分离”)。

    在 Graphviz 中预定义顶点很有用

    Graphviz 不需要事先知道顶点,除非它们需要一些非默认属性。

     0 [label="Node 0"];
     1 [shape="Mrect"];
    
     0 -- 1; // works
    

    但是

     0 [label="Node 0"] -- 1 [shape="Mrect"]; // doesn't work
    

    事实上

     0 [label="Node 0"];
     0 -- 1 [label="oops"]; // oops
    

    在边上设置“oops”标签,而不是 id 为 1 的顶点。


    调整PropertyWriter

    我想说的是,您真正想要做的是过滤掉具有零个相邻顶点的顶点。如果您坚持不这样做,您可以为 EdgePropertyWriter 传入自定义 PropertyWriter 实现。我认为这对你有用

      template <class Name>
      class my_vertex_writer {
      public:
        my_vertex_writer(Graph& g) : g_(g) {}
    
        template <class Vertex>
        void operator()(std::ostream& out, const Vertex& v) const {
             // pseudo-code!
             if (0 == boost::size(in_edges(v, g_)))
                out << "[style=\"invis\"]";
        }
      private:
        Graph& g_;
      };
    

    调整渲染器

    您可以使用gvpr 对输出进行后处理:

    gvpr -c 'N[$.degree==0]{$.style="invis"}' test.dot | dot -Tpng > test.png
    

    或者,要真正消除空间使用:

    gvpr -c 'N[$.degree==0]{delete(0,$);}' test.dot | dot -Tpng > test.png
    

    出于某种原因,我似乎需要重复此操作(我确信前往 gvpr documentation 可以解决此问题):

    cat test.dot | 
        gvpr -c 'N[$.degree==0]{delete(0,$)}' |
        gvpr -c 'N[$.degree==0]{delete(0,$)}' |
        gvpr -c 'N[$.degree==0]{delete(0,$)}' |
        dot -Tpng > test.png
    

    【讨论】:

    • 哇,感谢您的全面回答!请注意:在 Windows 上,您需要将 ' 替换为 " 才能使其正常工作。所以这批可能看起来像:set PATH=&lt;YOUR_GRAPHVIZ_PATH&gt;\bin;%PATH% gvpr -c "N[$.degree==0]{delete(0,$);}" graph.dot | dot -Tpng &gt; graph.png
    猜你喜欢
    • 2012-06-25
    • 1970-01-01
    • 2015-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多