在导入图形时使用顶点字符串 ID 作为实际顶点 (jgrapht 1.4)
Using vertex String IDs as the actual vertices while importing graph (jgrapht 1.4)
我有非常简单的图表
strict digraph G {
<assembly-raw-file>;
<dataset-processing>;
<feature-processing-1>;
<feature-processing-2>;
<mh.permute-variables-and-hyper-params>;
<mh.finish>;
<assembly-raw-file> -> <dataset-processing>;
<dataset-processing> -> <feature-processing-1>;
<dataset-processing> -> <feature-processing-2>;
<dataset-processing> -> <mh.permute-variables-and-hyper-params>;
<feature-processing-1> -> <mh.permute-variables-and-hyper-params>;
<feature-processing-2> -> <mh.permute-variables-and-hyper-params>;
<mh.permute-variables-and-hyper-params> -> <mh.finish>;
}
我正在尝试使用以下代码导入它
DirectedAcyclicGraph<String, DefaultEdge> processGraph = new DirectedAcyclicGraph<>(
SupplierUtil.createStringSupplier(), SupplierUtil.DEFAULT_EDGE_SUPPLIER, false);
DOTImporter<String, DefaultEdge> importer = new DOTImporter<>();
importer.importGraph(processGraph, new StringReader(wpy.processesGraph));
但是此代码将顶点名称更改为:
strict digraph G {
0;
1;
2;
3;
4;
5;
0 -> 1;
1 -> 2;
1 -> 3;
1 -> 4;
2 -> 4;
3 -> 4;
4 -> 5;
}
如何在保留顶点 ID 的情况下导入我的图?
或者更简单的解决方案是将顶点类型从字符串更改为复杂 class?
2020 年 3 月 4 日更新:
如果您使用的是 1.4.1 SNAPSHOT 版本(或更高版本),有一种更简单的方法可以获得所需的结果:只需使用 importer.setVertexFactory(id->id);
只有在用户提供工厂等情况下,才会使用文件中的顶点标识符调用它。从文件中给出顶点标识符的方法应该 return 一个实际的图形顶点。用户 returned 顶点直接添加到图中,而不使用顶点供应商。
如果没有提供这样的工厂,默认行为是从图顶点供应商处获取一个新顶点,并将文件中的原始标识符关联为新顶点的属性。
将此应用于上面的示例,我们得到:
String input="strict digraph G {\n" +
" <assembly-raw-file>;\n" +
" <dataset-processing>;\n" +
" <feature-processing-1>;\n" +
" <feature-processing-2>;\n" +
" <mh.permute-variables-and-hyper-params>;\n" +
" <mh.finish>;\n" +
" <assembly-raw-file> -> <dataset-processing>;\n" +
" <dataset-processing> -> <feature-processing-1>;\n" +
" <dataset-processing> -> <feature-processing-2>;\n" +
" <dataset-processing> -> <mh.permute-variables-and-hyper-params>;\n" +
" <feature-processing-1> -> <mh.permute-variables-and-hyper-params>;\n" +
" <feature-processing-2> -> <mh.permute-variables-and-hyper-params>;\n" +
" <mh.permute-variables-and-hyper-params> -> <mh.finish>;\n" +
"}";
Graph<String, DefaultEdge> graph = new SimpleDirectedGraph<>(DefaultEdge.class);
DOTImporter<String, DefaultEdge> importer = new DOTImporter<>();
importer.setVertexFactory(id->id);
importer.importGraph(graph, new StringReader(input));
System.out.println(graph);
原回答:
这是一种方法。这种方法使用 2 个步骤。第一步,我像你一样读了图表。顶点名称可以存储在属性映射中。在第二步中,我创建了一个新图,它使用第一个图的结构,但重命名了顶点。
String input="strict digraph G {\n" +
" <assembly-raw-file>;\n" +
" <dataset-processing>;\n" +
" <feature-processing-1>;\n" +
" <feature-processing-2>;\n" +
" <mh.permute-variables-and-hyper-params>;\n" +
" <mh.finish>;\n" +
" <assembly-raw-file> -> <dataset-processing>;\n" +
" <dataset-processing> -> <feature-processing-1>;\n" +
" <dataset-processing> -> <feature-processing-2>;\n" +
" <dataset-processing> -> <mh.permute-variables-and-hyper-params>;\n" +
" <feature-processing-1> -> <mh.permute-variables-and-hyper-params>;\n" +
" <feature-processing-2> -> <mh.permute-variables-and-hyper-params>;\n" +
" <mh.permute-variables-and-hyper-params> -> <mh.finish>;\n" +
"}";
Graph<String, DefaultEdge> graph = new SimpleDirectedGraph<>(SupplierUtil.createStringSupplier(), SupplierUtil.DEFAULT_EDGE_SUPPLIER, false);
//Import the graph; the vertex names are stored as 'ID' in the attribute map
DOTImporter<String, DefaultEdge> importer = new DOTImporter<>();
Map<String, Map<String, Attribute>> attrs = new HashMap<>();
importer.addVertexAttributeConsumer((p, a) -> {
Map<String, Attribute> map = attrs.computeIfAbsent(p.getFirst(), k -> new HashMap<>());
map.put(p.getSecond(), a);
});
importer.importGraph(graph, new StringReader(input));
//Create a new graph, thereby creating String vertices equal to the ID attribute values
Graph<String,DefaultEdge> labeledGraph=new SimpleDirectedGraph<>(DefaultEdge.class);
for(String v : graph.vertexSet())
labeledGraph.addVertex(attrs.get(v).get("ID").getValue());
for(DefaultEdge e : graph.edgeSet()){
String source = graph.getEdgeSource(e);
String target = graph.getEdgeTarget(e);
String sourceID=attrs.get(source).get("ID").getValue();
String targetID=attrs.get(target).get("ID").getValue();
labeledGraph.addEdge(sourceID, targetID);
}
System.out.println(labeledGraph);
我有非常简单的图表
strict digraph G {
<assembly-raw-file>;
<dataset-processing>;
<feature-processing-1>;
<feature-processing-2>;
<mh.permute-variables-and-hyper-params>;
<mh.finish>;
<assembly-raw-file> -> <dataset-processing>;
<dataset-processing> -> <feature-processing-1>;
<dataset-processing> -> <feature-processing-2>;
<dataset-processing> -> <mh.permute-variables-and-hyper-params>;
<feature-processing-1> -> <mh.permute-variables-and-hyper-params>;
<feature-processing-2> -> <mh.permute-variables-and-hyper-params>;
<mh.permute-variables-and-hyper-params> -> <mh.finish>;
}
我正在尝试使用以下代码导入它
DirectedAcyclicGraph<String, DefaultEdge> processGraph = new DirectedAcyclicGraph<>(
SupplierUtil.createStringSupplier(), SupplierUtil.DEFAULT_EDGE_SUPPLIER, false);
DOTImporter<String, DefaultEdge> importer = new DOTImporter<>();
importer.importGraph(processGraph, new StringReader(wpy.processesGraph));
但是此代码将顶点名称更改为:
strict digraph G {
0;
1;
2;
3;
4;
5;
0 -> 1;
1 -> 2;
1 -> 3;
1 -> 4;
2 -> 4;
3 -> 4;
4 -> 5;
}
如何在保留顶点 ID 的情况下导入我的图?
或者更简单的解决方案是将顶点类型从字符串更改为复杂 class?
2020 年 3 月 4 日更新:
如果您使用的是 1.4.1 SNAPSHOT 版本(或更高版本),有一种更简单的方法可以获得所需的结果:只需使用 importer.setVertexFactory(id->id);
只有在用户提供工厂等情况下,才会使用文件中的顶点标识符调用它。从文件中给出顶点标识符的方法应该 return 一个实际的图形顶点。用户 returned 顶点直接添加到图中,而不使用顶点供应商。
如果没有提供这样的工厂,默认行为是从图顶点供应商处获取一个新顶点,并将文件中的原始标识符关联为新顶点的属性。
将此应用于上面的示例,我们得到:
String input="strict digraph G {\n" +
" <assembly-raw-file>;\n" +
" <dataset-processing>;\n" +
" <feature-processing-1>;\n" +
" <feature-processing-2>;\n" +
" <mh.permute-variables-and-hyper-params>;\n" +
" <mh.finish>;\n" +
" <assembly-raw-file> -> <dataset-processing>;\n" +
" <dataset-processing> -> <feature-processing-1>;\n" +
" <dataset-processing> -> <feature-processing-2>;\n" +
" <dataset-processing> -> <mh.permute-variables-and-hyper-params>;\n" +
" <feature-processing-1> -> <mh.permute-variables-and-hyper-params>;\n" +
" <feature-processing-2> -> <mh.permute-variables-and-hyper-params>;\n" +
" <mh.permute-variables-and-hyper-params> -> <mh.finish>;\n" +
"}";
Graph<String, DefaultEdge> graph = new SimpleDirectedGraph<>(DefaultEdge.class);
DOTImporter<String, DefaultEdge> importer = new DOTImporter<>();
importer.setVertexFactory(id->id);
importer.importGraph(graph, new StringReader(input));
System.out.println(graph);
原回答:
这是一种方法。这种方法使用 2 个步骤。第一步,我像你一样读了图表。顶点名称可以存储在属性映射中。在第二步中,我创建了一个新图,它使用第一个图的结构,但重命名了顶点。
String input="strict digraph G {\n" +
" <assembly-raw-file>;\n" +
" <dataset-processing>;\n" +
" <feature-processing-1>;\n" +
" <feature-processing-2>;\n" +
" <mh.permute-variables-and-hyper-params>;\n" +
" <mh.finish>;\n" +
" <assembly-raw-file> -> <dataset-processing>;\n" +
" <dataset-processing> -> <feature-processing-1>;\n" +
" <dataset-processing> -> <feature-processing-2>;\n" +
" <dataset-processing> -> <mh.permute-variables-and-hyper-params>;\n" +
" <feature-processing-1> -> <mh.permute-variables-and-hyper-params>;\n" +
" <feature-processing-2> -> <mh.permute-variables-and-hyper-params>;\n" +
" <mh.permute-variables-and-hyper-params> -> <mh.finish>;\n" +
"}";
Graph<String, DefaultEdge> graph = new SimpleDirectedGraph<>(SupplierUtil.createStringSupplier(), SupplierUtil.DEFAULT_EDGE_SUPPLIER, false);
//Import the graph; the vertex names are stored as 'ID' in the attribute map
DOTImporter<String, DefaultEdge> importer = new DOTImporter<>();
Map<String, Map<String, Attribute>> attrs = new HashMap<>();
importer.addVertexAttributeConsumer((p, a) -> {
Map<String, Attribute> map = attrs.computeIfAbsent(p.getFirst(), k -> new HashMap<>());
map.put(p.getSecond(), a);
});
importer.importGraph(graph, new StringReader(input));
//Create a new graph, thereby creating String vertices equal to the ID attribute values
Graph<String,DefaultEdge> labeledGraph=new SimpleDirectedGraph<>(DefaultEdge.class);
for(String v : graph.vertexSet())
labeledGraph.addVertex(attrs.get(v).get("ID").getValue());
for(DefaultEdge e : graph.edgeSet()){
String source = graph.getEdgeSource(e);
String target = graph.getEdgeTarget(e);
String sourceID=attrs.get(source).get("ID").getValue();
String targetID=attrs.get(target).get("ID").getValue();
labeledGraph.addEdge(sourceID, targetID);
}
System.out.println(labeledGraph);