package za.redbridge.experiment;

import org.encog.neural.neat.NEATNeuronType;
import org.encog.neural.neat.training.NEATGenome;
import org.encog.neural.neat.training.NEATLinkGene;
import org.encog.neural.neat.training.NEATNeuronGene;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

import za.redbridge.experiment.MMNEAT.training.MMNEATNeuronGene;

/**
 * Basic methods to save a genome as a Graphviz ".dot" file so that it can be visualized.
 *
 * Created by jamie on 2014/10/06.
 */
public class GraphvizEngine {

    private static final Logger log = LoggerFactory.getLogger(GraphvizEngine.class);

    public static void saveGenome(NEATGenome genome, Path path) {
        try (BufferedWriter writer = Files.newBufferedWriter(path)) {
            writer.write("digraph G {");
            writer.newLine();

            writeNodes(writer, genome);

            writer.write("}");
            writer.newLine();
            writer.flush();
        } catch (IOException e) {
            log.error("Failed to save graphviz representation of network", e);
        }
    }

    private static void writeNodes(BufferedWriter writer, NEATGenome genome) throws IOException {
        List<NEATNeuronGene> neurons = genome.getNeuronsChromosome();
        for (NEATNeuronGene neuron : neurons) {
            writer.write("  ");
            writer.write(String.valueOf(neuron.getId()));
            if (neuron.getNeuronType() == NEATNeuronType.Input
                    && neuron instanceof MMNEATNeuronGene) {
                MMNEATNeuronGene mmneatNeuronGene = (MMNEATNeuronGene) neuron;
                writer.write(" [ label=\"" + neuron.getNeuronType()
                        + "\\n" + mmneatNeuronGene.getInputSensorType() + "\" ];");
            } else {
                writer.write(" [ label=\"" + neuron.getNeuronType() + "\" ];");
            }
            writer.newLine();
        }

        List<NEATLinkGene> links = genome.getLinksChromosome();
        for (NEATLinkGene link : links) {
            writer.write("  ");
            writer.write(link.getFromNeuronID() + " -> " + link.getToNeuronID());
            if (link.isEnabled()) {
                writer.write(" [ label=\"" + String.format("%.3f", link.getWeight()) + "\" ];");
            } else {
                writer.write(" [ style=\"dashed\" ];");
            }
            writer.newLine();
        }
    }
}

@@ -23,24 +23,105 @@
 xperiment;%0A%0A
+import org.encog.neural.neat.NEATLink;%0Aimport org.encog.neural.neat.NEATNetwork;%0A
 import org.e
@@ -1050,18 +1050,24 @@
   writeN
-od
+euronGen
 es(write
@@ -1075,16 +1075,104 @@
 , genome
+.getNeuronsChromosome());%0A            writeLinkGenes(writer, genome.getLinksChromosome()
 );%0A%0A    
@@ -1416,18 +1416,24 @@
 d writeN
-od
+euronGen
 es(Buffe
@@ -1454,117 +1454,70 @@
 er, 
-NEATGenome genome) throws IOException %7B%0A        List%3CNEATNeuronGene%3E neurons = genome.getNeuronsChromosome();
+List%3CNEATNeuronGene%3E neurons)%0A            throws IOException %7B
 %0A   
@@ -2165,72 +2165,135 @@
   %7D%0A
-%0A        List%3CNEATLinkGene%3E links = genome.getLinksChromosome();
+    %7D%0A%0A    private static void writeLinkGenes(BufferedWriter writer, List%3CNEATLinkGene%3E links)%0A            throws IOException %7B
 %0A   
@@ -2714,11 +2714,891 @@
  %7D%0A    %7D
+%0A%0A    public static void saveNetwork(NEATNetwork network, Path path) %7B%0A        try (BufferedWriter writer = Files.newBufferedWriter(path)) %7B%0A            writer.write(%22digraph G %7B%22);%0A            writer.newLine();%0A%0A            writeLinks(writer, network.getLinks());%0A%0A            writer.write(%22%7D%22);%0A            writer.newLine();%0A            writer.flush();%0A        %7D catch (IOException e) %7B%0A            log.error(%22Failed to save graphviz representation of network%22, e);%0A        %7D%0A    %7D%0A%0A    private static void writeLinks(BufferedWriter writer, NEATLink%5B%5D links)%0A            throws IOException %7B%0A        for (NEATLink link : links) %7B%0A            writer.write(%22  %22);%0A            writer.write(link.getFromNeuron() + %22 -%3E %22 + link.getToNeuron());%0A            writer.write(%22 %5B label=%5C%22%22 + String.format(%22%25.3f%22, link.getWeight()) + %22%5C%22 %5D;%22);%0A            writer.newLine();%0A        %7D%0A    %7D
 %0A%7D%0A

Add ability to save network as graphviz graph