问题
I have very simple graph
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>;
}
I'm trying to import it with the follow code
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));
but this code is changing names of vertices to this:
strict digraph G {
0;
1;
2;
3;
4;
5;
0 -> 1;
1 -> 2;
1 -> 3;
1 -> 4;
2 -> 4;
3 -> 4;
4 -> 5;
}
How to import my graph with preserving id of vertices?
Or the easier solution is to change type of vertex from String to complex class?
回答1:
Update March 4 2020:
If you are using the 1.4.1 SNAPSHOT release (or beyond), there's an easier way to obtain the desired result: simply use importer.setVertexFactory(id->id);
Only in case the user supplies such as factory, it is called with the vertex identifier from the file. The method given the vertex identifier from the file should return an actual graph vertex. The user returned vertex is added directly into the graph without using the vertex supplier.
If no such factory is provided, the default behavior is to acquire a new vertex from the graph vertex supplier and associate the original identifier from the file as an attribute of the new vertex.
Applying this to the above example, we get:
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);
Original answer:
Here's one way to do it. This approach uses 2 steps. In the first step, I read the graph as you did. The vertex names can be stored in an attribute map. In the second step I create a new graph which uses the structure of the first graph, but renames the vertices.
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);
来源:https://stackoverflow.com/questions/60461351/using-vertex-string-ids-as-the-actual-vertices-while-importing-graph-jgrapht-1