1 package net.bmahe.genetics4j.neat.util;
2
3 import java.util.List;
4 import java.util.Map;
5 import java.util.Map.Entry;
6 import java.util.Objects;
7 import java.util.Set;
8
9 import net.bmahe.genetics4j.neat.Connection;
10 import net.bmahe.genetics4j.neat.chromosomes.NeatChromosome;
11
12 public class GraphvizFormatter {
13
14 public String format(final NeatChromosome neatChromosome, final Map<Integer, String> nodeNames) {
15 Objects.requireNonNull(neatChromosome);
16 Objects.requireNonNull(nodeNames);
17
18 final List<Connection> connections = neatChromosome.getConnections();
19 final StringBuilder graphStringBuilder = new StringBuilder();
20
21 graphStringBuilder.append("""
22 digraph g {
23 rankdir=LR;
24 root[style="invis"]
25 end[style="invis"]
26 """);
27
28 final Set<Integer> inputNodeIndices = Set.copyOf(neatChromosome.getInputNodeIds());
29 for (final Integer inputNodeIndex : inputNodeIndices) {
30 graphStringBuilder.append("\troot -> ")
31 .append(inputNodeIndex)
32 .append(" [style=\"invis\"]")
33 .append(System.lineSeparator());
34 }
35
36 final Set<Integer> outputNodeIndices = Set.copyOf(neatChromosome.getOutputNodeIds());
37 for (final Integer outputNodeIndex : outputNodeIndices) {
38 graphStringBuilder.append("\t")
39 .append(outputNodeIndex)
40 .append(" -> end")
41 .append(" [style=\"invis\"]")
42 .append(System.lineSeparator());
43 }
44
45 for (final Connection connection : connections) {
46
47 final int fromNodeIndex = connection.fromNodeIndex();
48 final int toNodeIndex = connection.toNodeIndex();
49 final int innovation = connection.innovation();
50 final boolean enabled = connection.isEnabled();
51 final float weight = connection.weight();
52
53 final StringBuilder connectionStrBuilder = new StringBuilder();
54 connectionStrBuilder.append(fromNodeIndex);
55 connectionStrBuilder.append(" -> ");
56 connectionStrBuilder.append(toNodeIndex);
57 connectionStrBuilder.append(" [ ");
58 if (enabled == false) {
59 connectionStrBuilder.append("style=\"dashed\", ");
60 }
61 connectionStrBuilder.append(String.format("label=\"innovation=%d, weight=%.03f\"", innovation, weight));
62 connectionStrBuilder.append(" ] ");
63 connectionStrBuilder.append(System.lineSeparator());
64
65 graphStringBuilder.append("\t");
66 graphStringBuilder.append(connectionStrBuilder.toString());
67 }
68
69 for (final Entry<Integer, String> nodeNamesEntry : nodeNames.entrySet()) {
70
71 graphStringBuilder.append("\t")
72 .append(Integer.toString(nodeNamesEntry.getKey()))
73 .append("[ ")
74 .append("label=\"")
75 .append(nodeNamesEntry.getValue())
76 .append("\"")
77 .append(" ]")
78 .append(System.lineSeparator());
79 }
80
81 graphStringBuilder.append("}");
82 return graphStringBuilder.toString();
83 }
84 }