我使用
python库生成以下GraphViz .dot文件.
我现在想把它读成C的Boost :: Graph,这样我就可以使用Boost :: Graph的库算法了.
但是,我需要做一些预处理.特别是,我想用字符串构造函数创建一个捆绑属性,并让read_graphviz()将点文件中label字段中的字符串传递给字符串构造函数.
我该怎么做呢?
解决方法
首先要意识到的是,Boost文档样本几乎总是引用/从实际样本生成:
libs/graph/example/read_graphviz.cpp
要意识到的第二件事是BGL非常通用.高度.它在Boost Property Maps的概念上实现了很多这种通用性.
最后,观察从“自由形式”(至少动态/无类型文本形式)解析为某种通用MutableGraph模型正在推动极限.
这解释了如何阅读the docs for property_map下的文档的重要部分.
无论如何,因为the sample确实有点过时了,请允许我证明:
>将解析器的实现包含在一个翻译单元中:
#include <libs/graph/src/read_graphviz_new.cpp>
这样BGL仍然是一个只有头的库.
>这些天喜欢捆绑的属性:
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;
我们将填充顶点和边的标签,形状,名称.
>动态属性映射是魔术发生的地方:
dynamic_properties dp/*(ignore_other_properties)*/;
此类提供对由(name,typeid(key_type))标识的各种底层property maps的类型擦除访问.
这意味着您可以注册捆绑的属性,并将它们映射到graphviz属性名称:
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,get(&Edge::label,graph));
That’s really all there is to it. (Read up on the 07006,found via the 07007).
虽然我们不需要它,但我们也将图形属性抛出混合(如文档示例中所示):
// 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,"node_id"*/); }
>不要忘记链接到Boost Regex
完整的演示
#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,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",graph)); // Use ref_property_map to turn a graph property into a property map boost::ref_property_map<graph_t *,gname); std::ifstream dot("input.dot"); if (read_graphviz(dot,"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,"node_id"*/); } }
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%,shape=ellipse]; n15 [label="+ [0%,shape=ellipse]; n16 [label="+ [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%,shape=ellipse]; n28 [label="- [0%,shape=ellipse]; n29 [label="- [0%,shape=ellipse]; n3 [label="A11\n",shape=Box]; n30 [label="- [0%,shape=ellipse]; n31 [label="- [0%,shape=ellipse]; n32 [label="- [0%,shape=ellipse]; n33 [label="A13\n",shape=Box]; n34 [label="+ [0%,shape=ellipse]; n35 [label="- [0%,shape=ellipse]; n36 [label="- [0.01%,1.21%]",shape=ellipse]; n38 [label="A12\n",shape=Box]; n39 [label="- [0%,shape=ellipse]; n4 [label="A4\n",shape=Box]; n40 [label="+ [0%,1.17%]",shape=ellipse]; n42 [label="- [0%,shape=ellipse]; n43 [label="A12\n",shape=Box]; n44 [label="+ [0%,shape=ellipse]; n45 [label="- [0%,shape=ellipse]; n47 [label="- [0%,shape=ellipse]; n49 [label="+ [0%,shape=ellipse]; n5 [label="+ [0%,shape=ellipse]; n52 [label="+ [0%,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%,shape=ellipse]; n6 [label="A7\n",shape=Box]; n60 [label="+ [0%,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%,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"]; }