read_graphviz()中的boost ::图,传递给构造 [英] read_graphviz() in Boost::Graph, pass to constructor

查看:350
本文介绍了read_graphviz()中的boost ::图,传递给构造的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用了一个Python库生成以下的GraphViz .DOT文件。

http://pastebin.com/mL7ck9Zp

我想现在读入C ++的升压::图这样我就可以使用它的boost ::图的图书馆算法。

不过,我需要做一些preprocessing。特别是,我想创建一个字符串构造一个捆绑的财产,有read_graphviz()传递字符串中的标签字段中的点文件写入字符串的构造函数。

我如何去这样做?


解决方案

要实现的第一件事是,Boost文档样本几乎的始终是指从实际的样品产生/:的库/图形/例子/ read_graphviz.cpp

要实现第二件事是,BGL是非常通用的。高度。它实现了多本泛型在提升物业地图

最后,观察,从自由形式解析(至少动态/非类型化的文本形式)到某种的通用的 MutableGraph 模型的是挑战极限。

这说明了你会怎么有在<一个阅读的文档中的重要部分href=\"http://www.boost.org/doc/libs/1_57_0/libs/property_map/doc/dynamic_property_map.html#fred-s-info-revisited\"相对=nofollow>的文档进行property_map 。

总之,因为确实样品似乎有点过时了,让我来演示:


  1. 包含解析器的实现为一个翻译单元:

     的#include&LT;库/图/ src目录/ read_graphviz_new.cpp&GT;

    这样BGL仍然是一个只有标题库。


  2. preFER捆绑的属性,这些天:

     结构顶点{
        标准::字符串名称,标签,形状;
    };结构边缘{
        性病::字符串标签;
        双权重; //也许你需要这个以后还有,只是一个例子
    };typedef的财产&LT; graph_name_t,标准::字符串&GT; graph_p;
    的typedef的adjacency_list&LT;血管内皮细胞,血管内皮细胞,directedS,顶点,边graph_p&GT; graph_t;

    我们将填写标签形状名称顶点和边。


  3. 的动态属性映射是那里的奇迹发生:

     的dynamic_properties DP / *(ignore_other_properties)* /;

    这个类提供了多种基础的属性映射通过(姓名,typeid的(为key_type))。

    这意味着你可以注册绑定的属性,它们映射到graphviz的属性名称:

      INT的main(){
        //构造一个空的图形和prepare的dynamic_property_maps。
        graph_t图(0);    dynamic_properties的DP(ignore_other_properties);
        dp.property(NODE_ID,得到(安培;顶点::名称,图形));
        dp.property(标签,得到(安培;顶点::标签,图表));
        dp.property(形,得到(安培;顶点::形状,图形));
        dp.property(标签,得到(安培;边缘::标签,图表));


      

    这真的就是这么简单。的(阅读上的捆绑属性<魔法/ A>,通过页面发现的<$ C C>的adjacency_list 模板 $)。


    虽然我们并不需要它,让我们扔在混合图形性能太(如文档样本中):

      //使用ref_property_map打开图形属性到属性图
        提高:: ref_property_map&LT; graph_t *,标准::字符串&GT;的gname(get_property(图表,graph_name));
        dp.property(名,的gname);


  4. 现在所有剩下的是阅读的图形。

    嘛。好吧。让我们把它写退了出去过,但有一个新的图名,则:

     的std :: ifstream的点(input.dot);如果(read_graphviz(点,图形,DP / *NODE_ID* /)){
        性病::法院LT&;&LT; 图名称:'&LT;&LT; get_property(图,graph_name)LT;&LT; '\\ n;
        get_property(图,graph_name)=让我们给它一个名字;
        write_graphviz_dp(标准::法院,图形,DP / *NODE_ID* /);
    }


  5. 不要忘了链接到升压的正则表达式


完整演示

<大骨节病> 住在Coliru

 的#include&LT;升压/图/ adjacency_list.hpp&GT;
#包括LT&;升压/图/ graphviz.hpp&GT;
#包括LT&;提升/ property_map / dynamic_property_map.hpp&GT;
#包括LT&;库/图/ src目录/ read_graphviz_new.cpp&GT;
#包括LT&;升压/图/ graph_utility.hpp&GT;使用名字空间boost;结构顶点{
    标准::字符串名称,标签,形状;
};结构边缘{
    性病::字符串标签;
    双权重; //也许你需要这个以后还有,只是一个例子
};typedef的财产&LT; graph_name_t,标准::字符串&GT; graph_p;
的typedef的adjacency_list&LT;血管内皮细胞,血管内皮细胞,directedS,顶点,边graph_p&GT; graph_t;诠释主(){
    //构造一个空的图形和prepare的dynamic_property_maps。
    graph_t图(0);    dynamic_properties的DP / *(ignore_other_properties)* /;
    dp.property(NODE_ID,得到(安培;顶点::名称,图形));
    dp.property(标签,得到(安培;顶点::标签,图表));
    dp.property(形,得到(安培;顶点::形状,图形));
    dp.property(标签,得到(安培;边缘::标签,图表));    //使用ref_property_map打开图形属性到属性图
    提高:: ref_property_map&LT; graph_t *,标准::字符串&GT;的gname(get_property(图表,graph_name));
    dp.property(名,的gname);    性病:: ifstream的点(input.dot);    如果(read_graphviz(点,图形,DP / *NODE_ID* /)){
        性病::法院LT&;&LT; 图名称:'&LT;&LT; get_property(图,graph_name)LT;&LT; '\\ n;
        get_property(图,graph_name)=让我们给它一个名字;
        write_graphviz_dp(标准::法院,图形,DP / *NODE_ID* /);
    }
}

打印(前注意空名称,以及更新的图形name属性,后):

 图形名称:''
图G {
NAME =让我们给它一个名字;
N0 [标签=A9 \\ n,外形为长方体];
N1 [标签= - [0.48%,19.42%],形状椭圆=];
N11 [标号=+ 0%,0%],形状=椭圆];
N12 [标签= - [0%,0.75%],形状椭圆=];
N13 [标签=+ 0.03%,1.33%],形状椭圆=];
N14 [标签= - [0%,0.75%],形状椭圆=];
N15 [标号=+ 0%,0%],形状=椭圆];
N16 [标号=+ 0%,0%],形状=椭圆];
N17 [标签=A14 \\ n,外形为长方体];
N18 [标签=+ 0.03%,2.51%],形状椭圆=];
N19 [标签=A15 \\ n,外形为长方体];
N2 [标签=A15 \\ n,外形为长方体];
N20 [标签=A6 \\ n,外形为长方体];
N21 [标签=A2 \\ n,外形为长方体];
N22 [标签= - [0%,1.11%],形状椭圆=];
N23 [标号=+ 0%,1%],形状=椭圆];
N25 [标签= - [0%,2.18%],形状椭圆=];
N26 [标签=+ [0%,1.79%],形状椭圆=];
N27 [标号= - [0%,1%],形状=椭圆];
N28 [标号= - [0%,0%],形状=椭圆];
N29 [标号= - [0%,0%],形状=椭圆];
N3 [标签=A11 \\ n,外形为长方体];
N30 [标号= - [0%,0%],形状=椭圆];
N31 [标号= - [0%,0%],形状=椭圆];
N32 [标号= - [0%,1%],形状=椭圆];
N33 [标签=A13 \\ n,外形为长方体];
N34 [标号=+ 0%,1%],形状=椭圆];
N35 [标号= - [0%,0%],形状=椭圆];
N36 [标签= - [0.01%,1.21%],形状椭圆=];
N38 [标签=A12 \\ n,外形为长方体];
N39 [标号= - [0%,1%],形状=椭圆];
N4 [标签=A4 \\ n,外形为长方体];
N40 [标签=+ [0%,1.17%],形状椭圆=];
N42 [标号= - [0%,0%],形状=椭圆];
N43 [标签=A12 \\ n,外形为长方体];
N44 [标签=+ [0%,1.11%],形状椭圆=];
N45 [标号= - [0%,1%],形状=椭圆];
N47 [标号= - [0%,0%],形状=椭圆];
N49 [标签=+ [0%,1.17%],形状椭圆=];
N5 [标号=+ 0%,0%],形状=椭圆];
N52 [标签=+ [0%,0.75%],形状椭圆=];
N54 [标签=A13 \\ n,外形为长方体];
N55 [标签=A14 \\ n,外形为长方体];
N56 [标号= - [0.03%,2.5%],形状=椭圆];
N57 [标签=+ 0.01%,2.27%],形状椭圆=];
N59 [标号= - [0%,0%],形状=椭圆];
N6 [标签=A7 \\ n,外形为长方体];
N60 [标号=+ 0%,1%],形状=椭圆];
N63 [标签=A15 \\ n,外形为长方体];
N64 [标签=+ 0.05%,1.34%],形状椭圆=];
N65 [标签=A15 \\ n,外形为长方体];
N66 [标号= - [0%,1%],形状=椭圆];
N67 [标签=+ 0.02%,2.44%],形状椭圆=];
N7 [标签=A14 \\ n,外形为长方体];
N71 [标签=+ 0.21%,3.83%],形状椭圆=];
N8 [标签=+ [0%,1.57%],形状椭圆=];
N9 [标签= - [0.01%,1.22%],形状椭圆=];
n0-&GT; N1 [标签= F]
n0-&GT; N2 [标签= T]
n17-&GT; N18 [标签=&LT; = 110];
n17-&GT; N19 [标签=设备110];
n19-&GT; N20 [标签=&LT; = 8];
n19-&GT; N49 [标签=→8];
N2-&GT; N3 [标签=&LT; = 228];
N2-&GT; N71 [标签=&GT; 228];
n20-&GT; N21 [标签= AA];
n20-&GT; N25 [标签= C]。
n20-&GT; N26 [标签= CC];
n20-&GT; N27 [标签= D]。
n20-&GT; N28 [标签= E]
n20-&GT; N29 [标签= FF];
n20-&GT; N30 [标签= I]
n20-&GT; N31 [标签= J]。
n20-&GT; N32 [标签= K]
n20-&GT; N33 [标签= M]。
n20-&GT; N38 [标签= Q]
n20-&GT; N42 [标签= R]。
n20-&GT; N43 [标签= W]
n20-&GT; N47 [标签= X];
n21-&GT; N22 [标签=&LT; = 41];
n21-&GT; N23 [标签=&GT; 41];
-N 3 - &GT; N4 [标签=&LT; = 3];
-N 3 - &GT; N63 [标签=&GT; 3];
n33-&GT; N34 [标签= G]。
n33-&GT; N35 [标签= P]。
n33-&GT; N36 [标签= S]。
n38-&GT; N39 [标签= F]
n38-&GT; N40 [标签= T]
N4-&GT; N5 [标签= L];
N4-&GT; N6 [标签= U];
N4-&GT; N54 [标签= Y]
n43-&GT; N44 [标签= F]
n43-&GT; N45 [标签= T]
n54-&GT; N55 [标签= G]。
n54-&GT; N59 [标签= P]。
n54-&GT; N60 [标签= S]。
n55-&GT; N56 [标签=&LT; = 204];
n55-&GT; N57 [标签=&GT; 204];
N6-&GT; N7 [标签= BB];
N6-&GT; N11 [标签= DD]。
N6-&GT; N12 [标签= FF];
N6-&GT; N13 [标签= H];
N6-&GT; N14 [标签= J]。
N6-&GT; N15 [标签= N];
N6-&GT; N16 [标签= O];
N6-&GT; N17 [标签= V]
N6-&GT; N52 [标签= Z]。
n63-&GT; N64 [标签=&LT; = 4];
n63-&GT; N65 [标签=&GT; 4];
n65-&GT; N66 [标签=&LT; = 5];
n65-&GT; N67 [标签=&GT; 5];
N 7 - &GT; n8 [标签=&LT; = 164];
N 7 - &GT; N9 [标签=&GT; 164];
}

I have used a python library to generate the following GraphViz .dot file.

http://pastebin.com/mL7ck9Zp

I want to now read it into C++'s Boost::Graph so I can use Boost::Graph's library algorithms on it.

However, I need to do some preprocessing. In particular, I want to create a bundled property with a string constructor and have read_graphviz() pass the string in the label field in the dot file into the string constructor.

How do I go about doing this?

解决方案

First thing to realize is that Boost documentation samples almost always refer to/are generated from the actual samples: libs/graph/example/read_graphviz.cpp

Second thing to realize is that BGL is highly generic. Highly. And it achieves much of this genericity on the concepts of Boost Property Maps.

Finally, observe that parsing from "free-form" (at least dynamically/untyped text form) into some kind of generic MutableGraph model is pushing the limits.

This explains how you would have to read important parts of the documentation under the docs for property_map.

Anyhow, since indeed the sample seems a bit dated, allow me to demonstrate:

  1. Include the implementation of the parser into one translation unit:

    #include <libs/graph/src/read_graphviz_new.cpp>
    

    This way BGL remains a header-only library.

  2. Prefer bundled properties these days:

    struct Vertex {
        std::string name, label, shape;
    };
    
    struct Edge {
        std::string label;
        double weight; // perhaps you need this later as well, just an example
    };
    
    typedef property<graph_name_t, std::string> graph_p;
    typedef adjacency_list<vecS, vecS, directedS, Vertex, Edge, graph_p> graph_t;
    

    We will be filling label, shape, name for vertices and edges.

  3. The dynamic property maps are where the magic happens:

    dynamic_properties dp/*(ignore_other_properties)*/;
    

    This class provides type-erased access to a variety of underlying property maps identified by (name, typeid(key_type)).

    This means you can register the bundled properties, and map them to the graphviz attribute names:

    int main() {
        // Construct an empty graph and prepare the dynamic_property_maps.
        graph_t graph(0);
    
        dynamic_properties dp(ignore_other_properties);
        dp.property("node_id", get(&Vertex::name,  graph));
        dp.property("label",   get(&Vertex::label, graph));
        dp.property("shape",   get(&Vertex::shape, graph));
        dp.property("label",   get(&Edge::label,   graph));
    

    That's really all there is to it. (Read up on the magic of Bundled Properties, found via the page for the adjacency_list template).

    Though we don't need it, let's throw the graph property in the mix too (as in the documentation sample):

        // Use ref_property_map to turn a graph property into a property map
        boost::ref_property_map<graph_t *, std::string> gname(get_property(graph, graph_name));
        dp.property("name",    gname);
    

  4. Now all that's left is reading the graph.

    Well. Okay then. And let's write it back out too, but with a new graph name, then:

    std::ifstream dot("input.dot");
    
    if (read_graphviz(dot, graph, dp/*, "node_id"*/)) {
        std::cout << "Graph name: '" << get_property(graph, graph_name) << "'\n";
        get_property(graph, graph_name) = "Let's give it a name";
        write_graphviz_dp(std::cout, graph, dp/*, "node_id"*/);
    }
    

  5. Don't forget to link to Boost Regex

Full Demo

Live On Coliru

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
#include <libs/graph/src/read_graphviz_new.cpp>
#include <boost/graph/graph_utility.hpp>

using namespace boost;

struct Vertex {
    std::string name, label, shape;
};

struct Edge {
    std::string label;
    double weight; // perhaps you need this later as well, just an example
};

typedef property<graph_name_t, std::string> graph_p;
typedef adjacency_list<vecS, vecS, directedS, Vertex, Edge, graph_p> graph_t;

int main() {
    // Construct an empty graph and prepare the dynamic_property_maps.
    graph_t graph(0);

    dynamic_properties dp/*(ignore_other_properties)*/;
    dp.property("node_id", get(&Vertex::name,  graph));
    dp.property("label",   get(&Vertex::label, graph));
    dp.property("shape",   get(&Vertex::shape, graph));
    dp.property("label",   get(&Edge::label,   graph));

    // Use ref_property_map to turn a graph property into a property map
    boost::ref_property_map<graph_t *, std::string> gname(get_property(graph, graph_name));
    dp.property("name",    gname);

    std::ifstream dot("input.dot");

    if (read_graphviz(dot, graph, dp/*, "node_id"*/)) {
        std::cout << "Graph name: '" << get_property(graph, graph_name) << "'\n";
        get_property(graph, graph_name) = "Let's give it a name";
        write_graphviz_dp(std::cout, graph, dp/*, "node_id"*/);
    }
}

Prints (note the empty name before, and the updated graph name attribute, after):

Graph name: ''
digraph G {
name="Let's give it a name";
n0 [label="A9\n", shape=box];
n1 [label="- [0.48%,19.42%]", shape=ellipse];
n11 [label="+ [0%,0%]", shape=ellipse];
n12 [label="- [0%,0.75%]", shape=ellipse];
n13 [label="+ [0.03%,1.33%]", shape=ellipse];
n14 [label="- [0%,0.75%]", shape=ellipse];
n15 [label="+ [0%,0%]", shape=ellipse];
n16 [label="+ [0%,0%]", shape=ellipse];
n17 [label="A14\n", shape=box];
n18 [label="+ [0.03%,2.51%]", shape=ellipse];
n19 [label="A15\n", shape=box];
n2 [label="A15\n", shape=box];
n20 [label="A6\n", shape=box];
n21 [label="A2\n", shape=box];
n22 [label="- [0%,1.11%]", shape=ellipse];
n23 [label="+ [0%,1%]", shape=ellipse];
n25 [label="- [0%,2.18%]", shape=ellipse];
n26 [label="+ [0%,1.79%]", shape=ellipse];
n27 [label="- [0%,1%]", shape=ellipse];
n28 [label="- [0%,0%]", shape=ellipse];
n29 [label="- [0%,0%]", shape=ellipse];
n3 [label="A11\n", shape=box];
n30 [label="- [0%,0%]", shape=ellipse];
n31 [label="- [0%,0%]", shape=ellipse];
n32 [label="- [0%,1%]", shape=ellipse];
n33 [label="A13\n", shape=box];
n34 [label="+ [0%,1%]", shape=ellipse];
n35 [label="- [0%,0%]", shape=ellipse];
n36 [label="- [0.01%,1.21%]", shape=ellipse];
n38 [label="A12\n", shape=box];
n39 [label="- [0%,1%]", shape=ellipse];
n4 [label="A4\n", shape=box];
n40 [label="+ [0%,1.17%]", shape=ellipse];
n42 [label="- [0%,0%]", shape=ellipse];
n43 [label="A12\n", shape=box];
n44 [label="+ [0%,1.11%]", shape=ellipse];
n45 [label="- [0%,1%]", shape=ellipse];
n47 [label="- [0%,0%]", shape=ellipse];
n49 [label="+ [0%,1.17%]", shape=ellipse];
n5 [label="+ [0%,0%]", shape=ellipse];
n52 [label="+ [0%,0.75%]", shape=ellipse];
n54 [label="A13\n", shape=box];
n55 [label="A14\n", shape=box];
n56 [label="- [0.03%,2.5%]", shape=ellipse];
n57 [label="+ [0.01%,2.27%]", shape=ellipse];
n59 [label="- [0%,0%]", shape=ellipse];
n6 [label="A7\n", shape=box];
n60 [label="+ [0%,1%]", shape=ellipse];
n63 [label="A15\n", shape=box];
n64 [label="+ [0.05%,1.34%]", shape=ellipse];
n65 [label="A15\n", shape=box];
n66 [label="- [0%,1%]", shape=ellipse];
n67 [label="+ [0.02%,2.44%]", shape=ellipse];
n7 [label="A14\n", shape=box];
n71 [label="+ [0.21%,3.83%]", shape=ellipse];
n8 [label="+ [0%,1.57%]", shape=ellipse];
n9 [label="- [0.01%,1.22%]", shape=ellipse];
n0->n1  [label=f];
n0->n2  [label=t];
n17->n18  [label="<=110"];
n17->n19  [label=">110"];
n19->n20  [label="<=8"];
n19->n49  [label=">8"];
n2->n3  [label="<=228"];
n2->n71  [label=">228"];
n20->n21  [label=aa];
n20->n25  [label=c];
n20->n26  [label=cc];
n20->n27  [label=d];
n20->n28  [label=e];
n20->n29  [label=ff];
n20->n30  [label=i];
n20->n31  [label=j];
n20->n32  [label=k];
n20->n33  [label=m];
n20->n38  [label=q];
n20->n42  [label=r];
n20->n43  [label=w];
n20->n47  [label=x];
n21->n22  [label="<=41"];
n21->n23  [label=">41"];
n3->n4  [label="<=3"];
n3->n63  [label=">3"];
n33->n34  [label=g];
n33->n35  [label=p];
n33->n36  [label=s];
n38->n39  [label=f];
n38->n40  [label=t];
n4->n5  [label=l];
n4->n6  [label=u];
n4->n54  [label=y];
n43->n44  [label=f];
n43->n45  [label=t];
n54->n55  [label=g];
n54->n59  [label=p];
n54->n60  [label=s];
n55->n56  [label="<=204"];
n55->n57  [label=">204"];
n6->n7  [label=bb];
n6->n11  [label=dd];
n6->n12  [label=ff];
n6->n13  [label=h];
n6->n14  [label=j];
n6->n15  [label=n];
n6->n16  [label=o];
n6->n17  [label=v];
n6->n52  [label=z];
n63->n64  [label="<=4"];
n63->n65  [label=">4"];
n65->n66  [label="<=5"];
n65->n67  [label=">5"];
n7->n8  [label="<=164"];
n7->n9  [label=">164"];
}

这篇关于read_graphviz()中的boost ::图,传递给构造的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆