diff --git a/.idea/misc.xml b/.idea/misc.xml
index dd5f484..d4b854b 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,5 +3,7 @@
-
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index bfff7e5..92399bb 100644
--- a/README.md
+++ b/README.md
@@ -44,4 +44,4 @@ See also the list of [contributors](https://github.com/neuralm/Neuralm-Java-Clie
## License
-This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details
+This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
diff --git a/src/main/java/net/neuralm/client/NeuralmClient.java b/src/main/java/net/neuralm/client/NeuralmClient.java
index c80b868..1a8005f 100644
--- a/src/main/java/net/neuralm/client/NeuralmClient.java
+++ b/src/main/java/net/neuralm/client/NeuralmClient.java
@@ -31,10 +31,10 @@ public class NeuralmClient {
private final int port;
private final ISerializer serializer;
private final ReadHandler readHandler;
- AtomicBoolean isWriting = new AtomicBoolean(false);
+ final AtomicBoolean isWriting = new AtomicBoolean(false);
private AsynchronousTlsChannel channel;
private ByteBuffer writeBuffer = ByteBuffer.allocate(0);
- private Queue sendQueue = new LinkedBlockingDeque<>();
+ private final Queue sendQueue = new LinkedBlockingDeque<>();
/**
diff --git a/src/main/java/net/neuralm/client/ReadHandler.java b/src/main/java/net/neuralm/client/ReadHandler.java
index 469518c..026c136 100644
--- a/src/main/java/net/neuralm/client/ReadHandler.java
+++ b/src/main/java/net/neuralm/client/ReadHandler.java
@@ -1,18 +1,21 @@
package net.neuralm.client;
-import java.nio.ByteBuffer;
-import java.nio.channels.CompletionHandler;
import net.neuralm.client.messages.Message;
import net.neuralm.client.messages.MessageHeader;
import net.neuralm.client.messages.responses.Response;
import net.neuralm.client.messages.serializer.ISerializer;
+import java.nio.ByteBuffer;
+import java.nio.channels.CompletionHandler;
+
public class ReadHandler implements CompletionHandler {
private final NeuralmClient client;
MessageHeader currentHeader;
- ISerializer serializer;
+ final ISerializer serializer;
+
+ ByteBuffer currentBody;
public ReadHandler(NeuralmClient client, ISerializer serializer) {
this.client = client;
@@ -36,19 +39,24 @@ public void completed(Integer result, ByteBuffer attachment) {
}
client.startReading(currentHeader.getBodySize());
+ currentBody = ByteBuffer.allocate(currentHeader.getBodySize());
} else {
+ currentBody.put(bytes);
+
client.startReading();
- Object response = Message.deconstructMessageBody(serializer, currentHeader, bytes);
- if (response instanceof Response) {
- client.addResponse((Response) response);
- } else {
- System.err.println(String.format("Received response that wasn't a response! Bytes: %s", bytes));
- }
+ if (currentBody.position() == currentBody.capacity()) {
+ Object response = Message.deconstructMessageBody(serializer, currentHeader, currentBody.array());
- currentHeader = null;
- }
+ if (response instanceof Response) {
+ client.addResponse((Response) response);
+ } else {
+ System.err.println(String.format("Received response that wasn't a response! Bytes: %s", currentBody.array()));
+ }
+ currentHeader = null;
+ }
+ }
}
@Override
diff --git a/src/main/java/net/neuralm/client/entities/TrainingSession.java b/src/main/java/net/neuralm/client/entities/TrainingSession.java
index 7a5384e..5895ebe 100644
--- a/src/main/java/net/neuralm/client/entities/TrainingSession.java
+++ b/src/main/java/net/neuralm/client/entities/TrainingSession.java
@@ -1,14 +1,15 @@
package net.neuralm.client.entities;
-import java.util.UUID;
import net.neuralm.client.neat.TrainingRoom;
+import java.util.UUID;
+
public class TrainingSession {
- public UUID Id;
- public String StartedTimestamp;
- public String EndedTimestamp; //TODO: Make this an actual date object if possible, or maybe unix time
- public UUID UserId;
+ public UUID id;
+ public String startedTimestamp;
+ public String endedTimestamp; //TODO: Make this an actual date object if possible, or maybe unix time
+ public UUID userId;
public TrainingRoom trainingRoom;
}
diff --git a/src/main/java/net/neuralm/client/messages/Message.java b/src/main/java/net/neuralm/client/messages/Message.java
index 360a362..992699e 100644
--- a/src/main/java/net/neuralm/client/messages/Message.java
+++ b/src/main/java/net/neuralm/client/messages/Message.java
@@ -1,9 +1,10 @@
package net.neuralm.client.messages;
+import net.neuralm.client.messages.serializer.ISerializer;
+
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
-import net.neuralm.client.messages.serializer.ISerializer;
public class Message {
@@ -15,6 +16,13 @@ private Message(byte[] headerBytes, byte[] bodyBytes) {
this.bodyBytes = bodyBytes;
}
+ /**
+ * Construct a message object from the given object with the given serializer.
+ * It will be turned into bytes and a header will be created.
+ * @param serializer The serializer to use.
+ * @param message The object that should be turned into a message
+ * @return The message with the headerBytes and bodyBytes.
+ */
public static Message constructMessage(ISerializer serializer, Object message) {
byte[] bodyBytes = serializer.serialize(message);
byte[] messageTypeBytes = message.getClass().getSimpleName().getBytes(StandardCharsets.UTF_8);
@@ -25,6 +33,14 @@ public static Message constructMessage(ISerializer serializer, Object message) {
return new Message(headerBytes, bodyBytes);
}
+ /**
+ * Turn a byte array representing an object into that object.
+ * It will deserialize the bytes using the given serializer.
+ * @param serializer The serializer to use.
+ * @param header The header corresponding to the data being deserialized.
+ * @param bodyBytes The data to deserialize
+ * @return null if the serializer fails or no class corresponding to {@link MessageHeader#getTypeName()} is found.
+ */
public static Object deconstructMessageBody(ISerializer serializer, MessageHeader header, byte[] bodyBytes) {
Class> clazz;
try {
diff --git a/src/main/java/net/neuralm/client/messages/MessageHeader.java b/src/main/java/net/neuralm/client/messages/MessageHeader.java
index bac7c48..9a11138 100644
--- a/src/main/java/net/neuralm/client/messages/MessageHeader.java
+++ b/src/main/java/net/neuralm/client/messages/MessageHeader.java
@@ -7,7 +7,7 @@
public class MessageHeader {
private final int bodySize;
- private String typeName;
+ private final String typeName;
private MessageHeader(int bodySize, String typeName) {
this.bodySize = bodySize;
diff --git a/src/main/java/net/neuralm/client/messages/requests/GetOrganismsRequest.java b/src/main/java/net/neuralm/client/messages/requests/GetOrganismsRequest.java
index 0aae376..289c042 100644
--- a/src/main/java/net/neuralm/client/messages/requests/GetOrganismsRequest.java
+++ b/src/main/java/net/neuralm/client/messages/requests/GetOrganismsRequest.java
@@ -4,9 +4,9 @@
public class GetOrganismsRequest extends Request {
- public UUID trainingSessionID;
+ public final UUID trainingSessionID;
- public int amount;
+ public final int amount;
public GetOrganismsRequest(UUID trainingSessionID, int amount) {
this.trainingSessionID = trainingSessionID;
diff --git a/src/main/java/net/neuralm/client/messages/requests/PostOrganismsScoreRequest.java b/src/main/java/net/neuralm/client/messages/requests/PostOrganismsScoreRequest.java
index 8958057..e8a46fe 100644
--- a/src/main/java/net/neuralm/client/messages/requests/PostOrganismsScoreRequest.java
+++ b/src/main/java/net/neuralm/client/messages/requests/PostOrganismsScoreRequest.java
@@ -1,16 +1,17 @@
package net.neuralm.client.messages.requests;
+import net.neuralm.client.neat.Organism;
+
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
-import net.neuralm.client.neat.Organism;
public class PostOrganismsScoreRequest extends Request {
- public UUID trainingSessionId;
+ public final UUID trainingSessionId;
- public Map organismScores;
+ public final Map organismScores;
/**
* Create a PostOrganismsScoreRequest to send the organisms' score to the server
@@ -33,7 +34,7 @@ public PostOrganismsScoreRequest(UUID trainingSessionId, List organism
this(trainingSessionId, new HashMap<>(organisms.size()));
for (Organism organism : organisms) {
- organismScores.put(organism.id, organism.score);
+ organismScores.put(organism.getId(), organism.getScore());
}
}
}
diff --git a/src/main/java/net/neuralm/client/messages/requests/Request.java b/src/main/java/net/neuralm/client/messages/requests/Request.java
index fa0a78b..6abcda9 100644
--- a/src/main/java/net/neuralm/client/messages/requests/Request.java
+++ b/src/main/java/net/neuralm/client/messages/requests/Request.java
@@ -14,6 +14,7 @@ public class Request {
public Request() {
id = UUID.randomUUID();
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
+ //noinspection SpellCheckingInspection
date = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'.'SSSSSSS'Z'"));
}
diff --git a/src/main/java/net/neuralm/client/messages/responses/Response.java b/src/main/java/net/neuralm/client/messages/responses/Response.java
index dfc293b..fe954d7 100644
--- a/src/main/java/net/neuralm/client/messages/responses/Response.java
+++ b/src/main/java/net/neuralm/client/messages/responses/Response.java
@@ -30,6 +30,7 @@ public UUID getRequestId() {
* The time date this response was send.
* @return The date as a string in the following format: "yyyy-MM-dd'T'HH:mm:ss'.'SSSSSSS'Z'"
*/
+ @SuppressWarnings("SpellCheckingInspection")
public String getDateTime() {
return dateTime;
}
diff --git a/src/main/java/net/neuralm/client/messages/serializer/JsonSerializer.java b/src/main/java/net/neuralm/client/messages/serializer/JsonSerializer.java
index 06c1016..0320657 100644
--- a/src/main/java/net/neuralm/client/messages/serializer/JsonSerializer.java
+++ b/src/main/java/net/neuralm/client/messages/serializer/JsonSerializer.java
@@ -3,6 +3,8 @@
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
+import com.google.gson.JsonSyntaxException;
+
import java.nio.charset.StandardCharsets;
public class JsonSerializer implements ISerializer {
@@ -13,6 +15,9 @@ public JsonSerializer() {
this.gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
}
+ /**
+ * {@inheritDoc}
+ */
@Override
public byte[] serialize(Object message) {
String json = gson.toJson(message);
@@ -20,10 +25,21 @@ public byte[] serialize(Object message) {
return json.getBytes(StandardCharsets.UTF_8);
}
+ /**
+ * {@inheritDoc}
+ *
+ * @return The deserialized object, or null if a {@link JsonSyntaxException} occurred.
+ */
@Override
public T deserialize(byte[] bytes, Class type) {
String json = new String(bytes, StandardCharsets.UTF_8);
- return gson.fromJson(json, type);
+ try {
+ return gson.fromJson(json, type);
+ } catch (JsonSyntaxException exception) {
+ System.err.println(json);
+ exception.printStackTrace();
+ return null;
+ }
}
}
diff --git a/src/main/java/net/neuralm/client/neat/Brain.java b/src/main/java/net/neuralm/client/neat/Brain.java
deleted file mode 100644
index 761614a..0000000
--- a/src/main/java/net/neuralm/client/neat/Brain.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package net.neuralm.client.neat;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.UUID;
-import net.neuralm.client.neat.neurons.AbstractNeuron;
-import net.neuralm.client.neat.neurons.HiddenNeuron;
-import net.neuralm.client.neat.neurons.InputNeuron;
-import net.neuralm.client.neat.neurons.OutputNeuron;
-
-public class Brain {
-
- UUID id;
- UUID trainingRoomId;
- UUID organismId;
- private List connectionGenes = new ArrayList<>();
-
- private final List outputNeurons = new ArrayList<>();
- private final List inputNeurons = new ArrayList<>();
- private final HashMap neurons = new HashMap<>();
-
- private boolean buildStructure = false;
- private TrainingRoom trainingRoom;
- private Organism organism;
-
- public Brain() {
-
- }
-
- /**
- * Create a brain with the given trainingRoom and the given genes.
- *
- * @param trainingRoom The trainingRoom this brain is part of
- * @param genes Amount of genes
- */
- public Brain(TrainingRoom trainingRoom, List genes) {
- this.trainingRoom = trainingRoom;
- this.connectionGenes = genes;
- }
-
- /**
- * Evaluate the brain with the given inputs
- *
- * @param inputs A double array with the size {@link TrainingRoomSettings#getInputCount()}
- * @return A double array with size {@link TrainingRoomSettings#getOutputCount()} where index i has the output value of the output neuron with id {@link TrainingRoomSettings#getInputCount}+i
- */
- public double[] evaluate(double[] inputs) {
- if (trainingRoom == null) {
- throw new NullPointerException("trainingRoom is null, make sure Organism#initialize is called!");
- }
-
- if (!buildStructure) {
- for (int i = 0; i < trainingRoom.trainingRoomSettings.getInputCount(); i++) {
- InputNeuron neuron = new InputNeuron();
- inputNeurons.add(neuron);
- neurons.put(i, neuron);
- }
-
- for (int i = 0; i < trainingRoom.trainingRoomSettings.getOutputCount(); i++) {
- OutputNeuron neuron = new OutputNeuron();
- outputNeurons.add(neuron);
- neurons.put(trainingRoom.trainingRoomSettings.getInputCount() + i, neuron);
- }
-
- for (ConnectionGene connectionGene : connectionGenes) {
- connectionGene.initializeStructure(this);
- }
- buildStructure = true;
- }
-
- if (inputs.length != inputNeurons.size()) {
- throw new IllegalArgumentException(String.format("Input size %s does not match number of input neurons %s", inputs.length, inputNeurons.size()));
- }
-
- for (int i = 0; i < inputNeurons.size(); i++) {
- inputNeurons.get(i).setValue(inputs[i]);
- }
-
- double[] outputs = new double[outputNeurons.size()];
- for (int i = 0; i < outputNeurons.size(); i++) {
- outputs[i] = outputNeurons.get(i).getValue();
- }
-
- return outputs;
- }
-
- /**
- * Get a neuron with the given id or generate a new one if none exist.
- *
- * @param neuronId The neuron's id
- * @return A neuron
- */
- AbstractNeuron getNeuronOrCreate(int neuronId) {
- if (!neurons.containsKey(neuronId)) {
- neurons.put(neuronId, new HiddenNeuron());
- }
-
- return neurons.get(neuronId);
- }
-
- /**
- * Initialize the brain, this will make sure it is ready to be used.
- *
- * @param trainingRoom The trainingroom this brain is in.
- * @param organism The organism whose brain this is
- */
- public void initialize(TrainingRoom trainingRoom, Organism organism) {
- if (!trainingRoom.id.equals(trainingRoomId)) {
- throw new IllegalArgumentException(String.format("The given trainingRoomID %s does not match the expected trainingRoomID %s", trainingRoom.id, id));
- }
- if (!organism.id.equals(organismId)) {
- throw new IllegalArgumentException(String.format("The given organismId %s does not match the expected organismId %s", organism.id, organismId));
- }
-
- this.trainingRoom = trainingRoom;
- this.organism = organism;
- }
-}
diff --git a/src/main/java/net/neuralm/client/neat/ConnectionGene.java b/src/main/java/net/neuralm/client/neat/ConnectionGene.java
index 97ede6e..20e6143 100644
--- a/src/main/java/net/neuralm/client/neat/ConnectionGene.java
+++ b/src/main/java/net/neuralm/client/neat/ConnectionGene.java
@@ -1,42 +1,59 @@
package net.neuralm.client.neat;
+import net.neuralm.client.neat.nodes.AbstractNode;
+
import java.util.UUID;
-import net.neuralm.client.neat.neurons.AbstractNeuron;
public class ConnectionGene {
private UUID id;
- private UUID brainId;
- private int inID;
- private int outID;
+ private UUID organismId;
private int innovationNumber;
- private double weight;
- private boolean enabled;
- private AbstractNeuron inputNeuron;
- private AbstractNeuron outputNeuron;
+ public final int inNodeIdentifier;
+ public final int outNodeIdentifier;
+ public final double weight;
+ public final boolean enabled;
- public ConnectionGene() {
+ private AbstractNode in;
+ private AbstractNode out;
+ public ConnectionGene(int inNodeIdentifier, int outNodeIdentifier, double weight, boolean enabled, int innovationNumber, UUID id, UUID organismId) {
+ this(inNodeIdentifier, outNodeIdentifier, weight, enabled);
+ this.id = id;
+ this.organismId = organismId;
+ this.innovationNumber = innovationNumber;
}
- public ConnectionGene(int inId, int outId, double weight, boolean enabled) {
- this.inID = inId;
- this.outID = outId;
+ public ConnectionGene(int inNodeIdentifier, int outNodeIdentifier, double weight, boolean enabled) {
+ this.inNodeIdentifier = inNodeIdentifier;
+ this.outNodeIdentifier = outNodeIdentifier;
this.weight = weight;
this.enabled = enabled;
}
+ public void buildStructure(Organism organism) {
+ if (!enabled) return;
+
+ this.in = organism.getNodeFromIdentifier(inNodeIdentifier);
+ this.out = organism.getNodeFromIdentifier(outNodeIdentifier);
+ this.out.addDependency(this);
+ }
+
public double getValue() {
- return inputNeuron.getValue() * weight;
+ return in.getValue() * weight;
}
- void initializeStructure(Brain brain) {
- if (enabled) {
- inputNeuron = brain.getNeuronOrCreate(inID);
- outputNeuron = brain.getNeuronOrCreate(outID);
+ public UUID getId() {
+ return id;
+ }
+
+ public UUID getOrganismId() {
+ return organismId;
+ }
- outputNeuron.addDependency(this);
- }
+ public int getInnovationNumber() {
+ return innovationNumber;
}
+
}
diff --git a/src/main/java/net/neuralm/client/neat/Organism.java b/src/main/java/net/neuralm/client/neat/Organism.java
index 6a76085..4f2ef66 100644
--- a/src/main/java/net/neuralm/client/neat/Organism.java
+++ b/src/main/java/net/neuralm/client/neat/Organism.java
@@ -1,42 +1,155 @@
package net.neuralm.client.neat;
-import java.util.UUID;
+import net.neuralm.client.neat.nodes.AbstractNode;
+import net.neuralm.client.neat.nodes.HiddenNode;
+import net.neuralm.client.neat.nodes.InputNode;
+import net.neuralm.client.neat.nodes.OutputNode;
+
+import java.util.*;
public class Organism {
- public UUID id;
+ private final List connectionGenes;
+ private final List inputNodes;
+ private final List outputNodes;
+ private List hiddenNodes;
+ private UUID id;
+ private double score;
+ private String name;
+ private int generation;
- public UUID speciesId;
+ public Organism(List connectionGenes, int inputCount, int outputCount, UUID id, double score, String name, int generation) {
+ this(connectionGenes, inputCount, outputCount);
+ this.id = id;
+ this.score = score;
+ this.name = name;
+ this.generation = generation;
+ }
- public UUID brainId;
+ public Organism(List connectionGenes, int inputCount, int outputCount) {
+ this.connectionGenes = connectionGenes;
- public UUID trainingRoomId;
+ this.inputNodes = new ArrayList<>();
+ this.outputNodes = new ArrayList<>();
- public Brain brain;
+ for (int i = 0; i < inputCount; i++) {
+ InputNode a = new InputNode(i);
+ this.inputNodes.add(a);
+ }
- public double score;
+ for (int i = 0; i < outputCount; i++) {
+ OutputNode a = new OutputNode(i + inputCount);
+ this.outputNodes.add(a);
+ }
- public String name;
+ this.initialize();
+ }
- public int generation;
+ public List getInputNodes() {
+ return Collections.unmodifiableList(inputNodes);
+ }
- TrainingRoom trainingRoom;
+ public List getOutputNodes() {
+ return Collections.unmodifiableList(outputNodes);
+ }
+
+ public List getHiddenNodes() {
+ return Collections.unmodifiableList(hiddenNodes);
+ }
+
+ public UUID getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getGeneration() {
+ return generation;
+ }
+
+ public double getScore() {
+ return score;
+ }
+
+ public void setScore(double score) {
+ this.score = score;
+ }
+
+ public int getInputCount() {
+ return inputNodes.size();
+ }
+
+ public int getOutputCount() {
+ return outputNodes.size();
+ }
+
+ public List getConnectionGenes() {
+ return Collections.unmodifiableList(connectionGenes);
+ }
/**
- * Initialize the organism, this will set its trainingRoom and make sure the brain is ready to be used.
+ * Initialize the organism so it can be used.
+ * This will build the internal brain structure.
+ */
+ public void initialize() {
+ for (ConnectionGene connectionGene : connectionGenes) {
+ connectionGene.buildStructure(this);
+ }
+ }
+
+ /**
+ * Evaluate the organism, this will give the internal brain the given inputs and calculate the outputs.
*
- * @param trainingRoom The trainingroom this organism is part of.
+ * @param inputs The inputs for the brain.
+ * @return A double array with size of {@link #outputNodes}
*/
- public void initialize(TrainingRoom trainingRoom) {
- if (!trainingRoom.id.equals(trainingRoomId)) {
- throw new IllegalArgumentException(String.format("The given trainingRoomID %s does not match the expected trainingRoomID %s", trainingRoom.id, id));
+ public double[] evaluate(double[] inputs) {
+ if (inputs.length != inputNodes.size()) {
+ throw new IllegalArgumentException(String.format("inputs length ( %s ) should match inputnodes length ( %s )", inputs.length, inputNodes.size()));
}
- this.trainingRoom = trainingRoom;
- this.brain.initialize(trainingRoom, this);
+ for (int i = 0; i < inputs.length; i++) {
+ inputNodes.get(i).setValue(inputs[i]);
+ }
+
+ double[] outputs = new double[outputNodes.size()];
+
+ for (int i = 0; i < outputNodes.size(); i++) {
+ outputs[i] = outputNodes.get(i).getValue();
+ }
+
+ return outputs;
}
- public double[] evaluate(double[] inputs) {
- return this.brain.evaluate(inputs);
+ AbstractNode getNodeFromIdentifier(int nodeIdentifier) {
+ Optional optional = inputNodes.stream().filter(n -> n.nodeIdentifier == nodeIdentifier).findAny();
+
+ if (optional.isPresent()) {
+ return optional.get();
+ }
+
+ Optional outputNode = outputNodes.stream().filter(n -> n.nodeIdentifier == nodeIdentifier).findAny();
+
+ if (outputNode.isPresent()) {
+ return outputNode.get();
+ }
+
+ if (hiddenNodes == null) {
+ hiddenNodes = new ArrayList<>();
+ }
+
+ return hiddenNodes.stream().filter(n -> n.nodeIdentifier == nodeIdentifier).findAny().orElseGet(
+ () -> createAndAddNode(nodeIdentifier)
+ );
+ }
+
+ private HiddenNode createAndAddNode(int nodeIdentifier) {
+ HiddenNode node = new HiddenNode(nodeIdentifier);
+
+ hiddenNodes.add(node);
+
+ return node;
}
}
diff --git a/src/main/java/net/neuralm/client/neat/TrainingRoom.java b/src/main/java/net/neuralm/client/neat/TrainingRoom.java
index 5d5c8c8..63c1426 100644
--- a/src/main/java/net/neuralm/client/neat/TrainingRoom.java
+++ b/src/main/java/net/neuralm/client/neat/TrainingRoom.java
@@ -1,8 +1,9 @@
package net.neuralm.client.neat;
-import java.util.UUID;
import net.neuralm.client.entities.User;
+import java.util.UUID;
+
public class TrainingRoom {
public UUID id;
@@ -10,8 +11,5 @@ public class TrainingRoom {
public User owner;
public int generation;
public TrainingRoomSettings trainingRoomSettings;
- public double highestScore;
- public double lowestScore;
- public double averageScore;
}
diff --git a/src/main/java/net/neuralm/client/neat/TrainingRoomSettings.java b/src/main/java/net/neuralm/client/neat/TrainingRoomSettings.java
index 882f3d7..ec8b384 100644
--- a/src/main/java/net/neuralm/client/neat/TrainingRoomSettings.java
+++ b/src/main/java/net/neuralm/client/neat/TrainingRoomSettings.java
@@ -5,15 +5,15 @@
public class TrainingRoomSettings {
- static Random random = new Random();
+ static final Random random = new Random();
private UUID id = UUID.randomUUID();
private int organismCount = 100;
private int inputCount = 3;
private int outputCount = 1;
- private double c1 = 1;
- private double c2 = 0.4;
- private double c3 = 0.4;
+ private double speciesExcessGeneWeight = 1;
+ private double speciesDisjointGeneWeight = 0.4;
+ private double speciesAverageWeightDiffWeight = 0.4;
private double threshold = 3;
private double addConnectionChance = 0.05;
private double addNodeChance = 0.03;
@@ -62,30 +62,30 @@ public TrainingRoomSettings setOutputCount(int outputCount) {
return this;
}
- public double getC1() {
- return c1;
+ public double getSpeciesExcessGeneWeight() {
+ return speciesExcessGeneWeight;
}
- public TrainingRoomSettings setC1(double c1) {
- this.c1 = c1;
+ public TrainingRoomSettings setSpeciesExcessGeneWeight(double speciesExcessGeneWeight) {
+ this.speciesExcessGeneWeight = speciesExcessGeneWeight;
return this;
}
- public double getC2() {
- return c2;
+ public double getSpeciesDisjointGeneWeight() {
+ return speciesDisjointGeneWeight;
}
- public TrainingRoomSettings setC2(double c2) {
- this.c2 = c2;
+ public TrainingRoomSettings setSpeciesDisjointGeneWeight(double speciesDisjointGeneWeight) {
+ this.speciesDisjointGeneWeight = speciesDisjointGeneWeight;
return this;
}
- public double getC3() {
- return c3;
+ public double getSpeciesAverageWeightDiffWeight() {
+ return speciesAverageWeightDiffWeight;
}
- public TrainingRoomSettings setC3(double c3) {
- this.c3 = c3;
+ public TrainingRoomSettings setSpeciesAverageWeightDiffWeight(double speciesAverageWeightDiffWeight) {
+ this.speciesAverageWeightDiffWeight = speciesAverageWeightDiffWeight;
return this;
}
diff --git a/src/main/java/net/neuralm/client/neat/neurons/HiddenNeuron.java b/src/main/java/net/neuralm/client/neat/neurons/HiddenNeuron.java
deleted file mode 100644
index 932d537..0000000
--- a/src/main/java/net/neuralm/client/neat/neurons/HiddenNeuron.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package net.neuralm.client.neat.neurons;
-
-public class HiddenNeuron extends AbstractNeuron {
-
-}
diff --git a/src/main/java/net/neuralm/client/neat/neurons/OutputNeuron.java b/src/main/java/net/neuralm/client/neat/neurons/OutputNeuron.java
deleted file mode 100644
index 64ddccf..0000000
--- a/src/main/java/net/neuralm/client/neat/neurons/OutputNeuron.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package net.neuralm.client.neat.neurons;
-
-public class OutputNeuron extends AbstractNeuron {
-
-}
diff --git a/src/main/java/net/neuralm/client/neat/neurons/AbstractNeuron.java b/src/main/java/net/neuralm/client/neat/nodes/AbstractNode.java
similarity index 55%
rename from src/main/java/net/neuralm/client/neat/neurons/AbstractNeuron.java
rename to src/main/java/net/neuralm/client/neat/nodes/AbstractNode.java
index feadad3..d72c9fb 100644
--- a/src/main/java/net/neuralm/client/neat/neurons/AbstractNeuron.java
+++ b/src/main/java/net/neuralm/client/neat/nodes/AbstractNode.java
@@ -1,14 +1,29 @@
-package net.neuralm.client.neat.neurons;
+package net.neuralm.client.neat.nodes;
+
+import net.neuralm.client.neat.ConnectionGene;
import java.util.ArrayList;
import java.util.List;
-import net.neuralm.client.neat.ConnectionGene;
-public abstract class AbstractNeuron {
+public abstract class AbstractNode {
+
+ public final int nodeIdentifier;
+ private List dependencies;
+
+ public AbstractNode() {
+ this(-1);
+ }
- private List dependencies = new ArrayList();
+ AbstractNode(int nodeIdentifier) {
+ this.dependencies = new ArrayList<>();
+ this.nodeIdentifier = nodeIdentifier;
+ }
public double getValue() {
+ if(dependencies == null) {
+ dependencies = new ArrayList<>();
+ }
+
if (dependencies.size() == 0) {
return activationFunction(0);
}
@@ -19,6 +34,7 @@ public double getValue() {
for (ConnectionGene gene : dependencies) {
total += gene.getValue();
count++;
+
}
return activationFunction(total / count);
@@ -29,6 +45,10 @@ private double activationFunction(double x) {
}
public void addDependency(ConnectionGene connectionGene) {
+ if(dependencies == null) {
+ dependencies = new ArrayList<>();
+ }
+
dependencies.add(connectionGene);
}
}
diff --git a/src/main/java/net/neuralm/client/neat/nodes/HiddenNode.java b/src/main/java/net/neuralm/client/neat/nodes/HiddenNode.java
new file mode 100644
index 0000000..97e5625
--- /dev/null
+++ b/src/main/java/net/neuralm/client/neat/nodes/HiddenNode.java
@@ -0,0 +1,8 @@
+package net.neuralm.client.neat.nodes;
+
+public class HiddenNode extends AbstractNode {
+
+ public HiddenNode(int nodeIdentifier) {
+ super(nodeIdentifier);
+ }
+}
diff --git a/src/main/java/net/neuralm/client/neat/neurons/InputNeuron.java b/src/main/java/net/neuralm/client/neat/nodes/InputNode.java
similarity index 60%
rename from src/main/java/net/neuralm/client/neat/neurons/InputNeuron.java
rename to src/main/java/net/neuralm/client/neat/nodes/InputNode.java
index 881bcaa..1852868 100644
--- a/src/main/java/net/neuralm/client/neat/neurons/InputNeuron.java
+++ b/src/main/java/net/neuralm/client/neat/nodes/InputNode.java
@@ -1,11 +1,15 @@
-package net.neuralm.client.neat.neurons;
+package net.neuralm.client.neat.nodes;
import net.neuralm.client.neat.ConnectionGene;
-public class InputNeuron extends AbstractNeuron {
+public class InputNode extends AbstractNode {
private double value;
+ public InputNode(int nodeIdentifier) {
+ super(nodeIdentifier);
+ }
+
@Override
public double getValue() {
return value;
@@ -18,5 +22,6 @@ public void setValue(double value) {
@Override
public void addDependency(ConnectionGene connectionGene) {
System.err.println("Trying to add a dependency to an input!");
+ throw new IllegalArgumentException("Trying to add a dependency to an input!");
}
}
diff --git a/src/main/java/net/neuralm/client/neat/nodes/OutputNode.java b/src/main/java/net/neuralm/client/neat/nodes/OutputNode.java
new file mode 100644
index 0000000..b4cae39
--- /dev/null
+++ b/src/main/java/net/neuralm/client/neat/nodes/OutputNode.java
@@ -0,0 +1,8 @@
+package net.neuralm.client.neat.nodes;
+
+public class OutputNode extends AbstractNode {
+
+ public OutputNode(int nodeIdentifier) {
+ super(nodeIdentifier);
+ }
+}
diff --git a/src/test/java/net/neuralm/client/NeuralmClientMain.java b/src/test/java/net/neuralm/client/NeuralmClientMain.java
index 107e15d..742339e 100644
--- a/src/test/java/net/neuralm/client/NeuralmClientMain.java
+++ b/src/test/java/net/neuralm/client/NeuralmClientMain.java
@@ -1,36 +1,22 @@
package net.neuralm.client;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Random;
-import java.util.UUID;
import net.neuralm.client.entities.TrainingSession;
-import net.neuralm.client.messages.requests.AuthenticateRequest;
-import net.neuralm.client.messages.requests.CreateTrainingRoomRequest;
-import net.neuralm.client.messages.requests.EndTrainingSessionRequest;
-import net.neuralm.client.messages.requests.GetEnabledTrainingRoomsRequest;
-import net.neuralm.client.messages.requests.GetOrganismsRequest;
-import net.neuralm.client.messages.requests.PostOrganismsScoreRequest;
-import net.neuralm.client.messages.requests.RegisterRequest;
-import net.neuralm.client.messages.requests.Request;
-import net.neuralm.client.messages.requests.StartTrainingSessionRequest;
-import net.neuralm.client.messages.responses.AuthenticateResponse;
-import net.neuralm.client.messages.responses.CreateTrainingRoomResponse;
-import net.neuralm.client.messages.responses.GetEnabledTrainingRoomsResponse;
-import net.neuralm.client.messages.responses.GetOrganismsResponse;
-import net.neuralm.client.messages.responses.PostOrganismsScoreResponse;
-import net.neuralm.client.messages.responses.Response;
-import net.neuralm.client.messages.responses.StartTrainingSessionResponse;
+import net.neuralm.client.messages.requests.*;
+import net.neuralm.client.messages.responses.*;
import net.neuralm.client.messages.serializer.JsonSerializer;
import net.neuralm.client.neat.Organism;
import net.neuralm.client.neat.TrainingRoom;
import net.neuralm.client.neat.TrainingRoomSettings;
+import java.io.IOException;
+import java.util.Random;
+import java.util.UUID;
+
public class NeuralmClientMain {
private static UUID userId;
private static TrainingSession trainingSession;
- private static int i;
+ private static int organismBatchesProcessed;
public static void main(String... args) throws IOException, InterruptedException {
String host = args.length >= 1 ? args[0] : "127.0.0.1";
@@ -54,7 +40,8 @@ public static void main(String... args) throws IOException, InterruptedException
System.out.println(response.isSuccess() ? "Authenticated..." : String.format("Authenticating failed: %s", response.getMessage()));
userId = response.getUserId();
System.out.println(String.format("Creating room with name %s", trainingRoomName));
- client.send(new CreateTrainingRoomRequest(response.getUserId(), trainingRoomName, new TrainingRoomSettings().setOrganismCount(20).setInputCount(3).setOutputCount(1)));
+ client.send(new CreateTrainingRoomRequest(response.getUserId(), trainingRoomName, new TrainingRoomSettings().setOrganismCount(20).setInputCount(3).setOutputCount(1).setSeed(10).setAddConnectionChance(1).setAddNodeChance(1
+ )));
});
client.addListener("CreateTrainingRoomResponse", (changeEvent) -> {
@@ -89,7 +76,7 @@ public static void main(String... args) throws IOException, InterruptedException
if (response.isSuccess()) {
trainingSession = response.getTrainingSession();
- Request getOrganismRequest = new GetOrganismsRequest(trainingSession.Id, 10);
+ Request getOrganismRequest = new GetOrganismsRequest(trainingSession.id, 10);
client.send(getOrganismRequest);
} else {
System.err.println(String.format("StartTrainingSessionResponse failed %s", response.getMessage()));
@@ -104,12 +91,12 @@ public static void main(String... args) throws IOException, InterruptedException
Random random = new Random();
for (Organism organism : response.getOrganisms()) {
- organism.score = random.nextDouble() + 0.00001;
- organism.initialize(trainingSession.trainingRoom);
- System.out.println(organism.name + " has output: " + Arrays.toString(organism.evaluate(new double[]{0, 1, 2})));
+ organism.setScore(random.nextDouble() + 0.00001);
+ organism.initialize();
+// System.out.println(organism.name + " has output: " + Arrays.toString(organism.getValue(new double[]{0, 1, 2})));
}
- Request postOrganismsScoreRequest = new PostOrganismsScoreRequest(trainingSession.Id, response.getOrganisms());
+ Request postOrganismsScoreRequest = new PostOrganismsScoreRequest(trainingSession.id, response.getOrganisms());
client.send(postOrganismsScoreRequest);
} else {
System.err.println(String.format("GetOrganismsResponse failed %s", response.getMessage()));
@@ -120,12 +107,12 @@ public static void main(String... args) throws IOException, InterruptedException
PostOrganismsScoreResponse response = (PostOrganismsScoreResponse) changeEvent.getNewValue();
System.out.println(String.format("PostOrganismsScoreResponse was %s", response.isSuccess() ? "successful" : "unsuccessful"));
- i++;
- if (i == 3) {
- Request request = new EndTrainingSessionRequest(trainingSession.Id);
+ organismBatchesProcessed++;
+ if (organismBatchesProcessed == 3) {
+ Request request = new EndTrainingSessionRequest(trainingSession.id);
client.send(request);
} else {
- Request getOrganismRequest = new GetOrganismsRequest(trainingSession.Id, 10);
+ Request getOrganismRequest = new GetOrganismsRequest(trainingSession.id, 10);
client.send(getOrganismRequest);
}
});
diff --git a/src/test/java/net/neuralm/client/NeuralmClientTest.java b/src/test/java/net/neuralm/client/NeuralmClientTest.java
new file mode 100644
index 0000000..3cb2e57
--- /dev/null
+++ b/src/test/java/net/neuralm/client/NeuralmClientTest.java
@@ -0,0 +1,13 @@
+package net.neuralm.client;
+
+import org.junit.jupiter.api.Test;
+
+class NeuralmClientTest {
+
+ @Test
+ void start() {
+// NeuralmClient client = new NeuralmClient("api.neuralm.com", 9999, new JsonSerializer(), true, 5 * 1000);
+//
+// assertDoesNotThrow(client::start);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/net/neuralm/client/neat/BrainTest.java b/src/test/java/net/neuralm/client/neat/BrainTest.java
deleted file mode 100644
index 4b21336..0000000
--- a/src/test/java/net/neuralm/client/neat/BrainTest.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package net.neuralm.client.neat;
-
-import java.util.Arrays;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.CsvFileSource;
-
-class BrainTest {
-
- @ParameterizedTest
- @CsvFileSource(resources = "/evaluateTest.csv")
- void evaluate(double inA, double inB, double inC, double expected) {
- TrainingRoom room = new TrainingRoom();
- room.trainingRoomSettings = new TrainingRoomSettings().setInputCount(3).setOutputCount(1);
- Brain brain = new Brain(room, Arrays.asList(
-
- new ConnectionGene(0, 3, 1, true),
- new ConnectionGene(1, 3, 1, false),
- new ConnectionGene(2, 3, 1, true),
- new ConnectionGene(1, 4, 1, true),
- new ConnectionGene(4, 3, 1, true),
- new ConnectionGene(0, 4, 1, true)
-
- ));
-
- Assertions.assertEquals(expected, brain.evaluate(new double[]{inA, inB, inC})[0], 0.0000000001);
- }
-}
\ No newline at end of file
diff --git a/src/test/java/net/neuralm/client/neat/OrganismTest.java b/src/test/java/net/neuralm/client/neat/OrganismTest.java
new file mode 100644
index 0000000..44fab34
--- /dev/null
+++ b/src/test/java/net/neuralm/client/neat/OrganismTest.java
@@ -0,0 +1,56 @@
+package net.neuralm.client.neat;
+
+import com.google.gson.*;
+import net.neuralm.client.messages.serializer.JsonSerializer;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvFileSource;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+class OrganismTest {
+
+ @ParameterizedTest
+ @CsvFileSource(resources = "/evaluateTest.csv")
+ void getValue(double inA, double inB, double inC, double expected) {
+ Organism organism = new Organism(Arrays.asList(
+
+ new ConnectionGene(0, 3, 1, true),
+ new ConnectionGene(1, 3, 1, false),
+ new ConnectionGene(2, 3, 1, true),
+ new ConnectionGene(1, 4, 1, true),
+ new ConnectionGene(4, 3, 1, true),
+ new ConnectionGene(0, 4, 1, true)
+
+ ), 3, 1);
+
+ Assertions.assertEquals(expected, organism.evaluate(new double[]{inA, inB, inC})[0], 0.0000000001);
+ }
+
+ @Test
+ void parseJson() {
+ String json = "{\"Organisms\":[{\"Id\":\"1110df35-52f0-4bb5-8ce4-c68de3f50717\",\"ConnectionGenes\":[{\"Id\":\"ab1f8a88-f22c-49ce-e69c-08d7a435cc56\",\"OrganismId\":\"1110df35-52f0-4bb5-8ce4-c68de3f50717\",\"InNodeIdentifier\":0,\"OutNodeIdentifier\":2,\"Weight\":0.9468057444071425,\"Enabled\":true},{\"Id\":\"608c8dba-cb98-4e0d-e69d-08d7a435cc56\",\"OrganismId\":\"1110df35-52f0-4bb5-8ce4-c68de3f50717\",\"InNodeIdentifier\":1,\"OutNodeIdentifier\":2,\"Weight\":0.8501794032054857,\"Enabled\":true}],\"InputNodes\":[{\"Id\":\"23b86cf7-9feb-4e83-9b66-52ee08f002bb\",\"Layer\":0,\"NodeIdentifier\":1},{\"Id\":\"b29a8f7e-e9a9-4bea-b177-c41556650edd\",\"Layer\":0,\"NodeIdentifier\":0}],\"OutputNodes\":[{\"Id\":\"cbf2e2d9-edb9-4a22-be06-fc7c81a08d9b\",\"Layer\":0,\"NodeIdentifier\":2}],\"Score\":0,\"Name\":\"hah\",\"Generation\":2},{\"Id\":\"5f58a628-d6f9-4c89-894c-cc0cc67b4b58\",\"ConnectionGenes\":[{\"Id\":\"5e10a17e-d5ed-4f43-e6be-08d7a435cc56\",\"OrganismId\":\"5f58a628-d6f9-4c89-894c-cc0cc67b4b58\",\"InNodeIdentifier\":1,\"OutNodeIdentifier\":2,\"Weight\":0.8874416885839037,\"Enabled\":true},{\"Id\":\"2ce5cf89-401f-45f4-e6bf-08d7a435cc56\",\"OrganismId\":\"5f58a628-d6f9-4c89-894c-cc0cc67b4b58\",\"InNodeIdentifier\":0,\"OutNodeIdentifier\":2,\"Weight\":0.9468057444071425,\"Enabled\":true}],\"InputNodes\":[{\"Id\":\"04263382-c8a1-4d9b-ad8d-78ebd11d1634\",\"Layer\":0,\"NodeIdentifier\":1},{\"Id\":\"8f09d844-d41b-4aef-b518-bbb3b81ea4d1\",\"Layer\":0,\"NodeIdentifier\":0}],\"OutputNodes\":[{\"Id\":\"d9b4add4-8a76-4c13-91e4-30187428af54\",\"Layer\":0,\"NodeIdentifier\":2}],\"Score\":0,\"Name\":\"huv\",\"Generation\":2},{\"Id\":\"233ca2a9-016a-4165-9f04-d0cd30599466\",\"ConnectionGenes\":[{\"Id\":\"de88f87c-a903-4d91-e6c6-08d7a435cc56\",\"OrganismId\":\"233ca2a9-016a-4165-9f04-d0cd30599466\",\"InNodeIdentifier\":0,\"OutNodeIdentifier\":2,\"Weight\":-0.8599432335979972,\"Enabled\":true},{\"Id\":\"13c275df-3ca7-4ad7-e6c7-08d7a435cc56\",\"OrganismId\":\"233ca2a9-016a-4165-9f04-d0cd30599466\",\"InNodeIdentifier\":1,\"OutNodeIdentifier\":2,\"Weight\":0.9279808662496418,\"Enabled\":true}],\"InputNodes\":[{\"Id\":\"aab6743b-bd78-4601-8f44-36ced34d525c\",\"Layer\":0,\"NodeIdentifier\":0},{\"Id\":\"6c38d04f-568d-4ed4-9030-652c5fdb3f0b\",\"Layer\":0,\"NodeIdentifier\":1}],\"OutputNodes\":[{\"Id\":\"f7a8d5ee-2833-4c80-9454-6ffdf5586b9c\",\"Layer\":0,\"NodeIdentifier\":2}],\"Score\":0,\"Name\":\"meev\",\"Generation\":2},{\"Id\":\"a100859d-5c5f-4b32-bc4b-cf0f65744add\",\"ConnectionGenes\":[{\"Id\":\"84660026-932a-4d41-e6b8-08d7a435cc56\",\"OrganismId\":\"a100859d-5c5f-4b32-bc4b-cf0f65744add\",\"InNodeIdentifier\":1,\"OutNodeIdentifier\":2,\"Weight\":0.5511769361566645,\"Enabled\":true},{\"Id\":\"8937ed99-3ea7-4fe0-e6b9-08d7a435cc56\",\"OrganismId\":\"a100859d-5c5f-4b32-bc4b-cf0f65744add\",\"InNodeIdentifier\":0,\"OutNodeIdentifier\":2,\"Weight\":-0.6720582465045425,\"Enabled\":true}],\"InputNodes\":[{\"Id\":\"8f7a517c-39dc-421b-9718-163eb7c90d89\",\"Layer\":0,\"NodeIdentifier\":0},{\"Id\":\"ddc31fdb-cd5a-47b9-a256-7d43aaf7cb3e\",\"Layer\":0,\"NodeIdentifier\":1}],\"OutputNodes\":[{\"Id\":\"7428049a-dd70-4430-8ec1-6a3687d2814a\",\"Layer\":0,\"NodeIdentifier\":2}],\"Score\":0,\"Name\":\"wopoom\",\"Generation\":2},{\"Id\":\"879c8309-4542-4882-9ae0-f49aaee1ded1\",\"ConnectionGenes\":[{\"Id\":\"08544f7b-eafb-4d78-e6b0-08d7a435cc56\",\"OrganismId\":\"879c8309-4542-4882-9ae0-f49aaee1ded1\",\"InNodeIdentifier\":0,\"OutNodeIdentifier\":2,\"Weight\":-0.911530219908585,\"Enabled\":true},{\"Id\":\"8a42569d-1f19-421f-e6b1-08d7a435cc56\",\"OrganismId\":\"879c8309-4542-4882-9ae0-f49aaee1ded1\",\"InNodeIdentifier\":1,\"OutNodeIdentifier\":2,\"Weight\":0.5396867401617051,\"Enabled\":true}],\"InputNodes\":[{\"Id\":\"ecf569b1-9cc1-46b2-a070-27462634b1ba\",\"Layer\":0,\"NodeIdentifier\":1},{\"Id\":\"cc5293ae-d3e2-41af-8d5f-e23472e10638\",\"Layer\":0,\"NodeIdentifier\":0}],\"OutputNodes\":[{\"Id\":\"80461bd3-e8e6-4150-a38c-c78ec6a3b0ff\",\"Layer\":0,\"NodeIdentifier\":2}],\"Score\":0,\"Name\":\"kixityc\",\"Generation\":2},{\"Id\":\"dd44e9ea-6e1c-42f2-a713-de9f60f36e0f\",\"ConnectionGenes\":[{\"Id\":\"70978ca8-01a0-4ad3-e6ca-08d7a435cc56\",\"OrganismId\":\"dd44e9ea-6e1c-42f2-a713-de9f60f36e0f\",\"InNodeIdentifier\":0,\"OutNodeIdentifier\":2,\"Weight\":0.3642462377269968,\"Enabled\":true},{\"Id\":\"269e36a6-4185-421c-e6cb-08d7a435cc56\",\"OrganismId\":\"dd44e9ea-6e1c-42f2-a713-de9f60f36e0f\",\"InNodeIdentifier\":1,\"OutNodeIdentifier\":2,\"Weight\":0.8933658557913107,\"Enabled\":true}],\"InputNodes\":[{\"Id\":\"cf286c7e-df70-4f20-9705-81b37a71790b\",\"Layer\":0,\"NodeIdentifier\":0},{\"Id\":\"c65a7bc1-d0d4-4b1f-a495-f87cbadcf847\",\"Layer\":0,\"NodeIdentifier\":1}],\"OutputNodes\":[{\"Id\":\"c988fd4d-e05b-40a0-8e32-78f19fc5f751\",\"Layer\":0,\"NodeIdentifier\":2}],\"Score\":0,\"Name\":\"haafeezaab\",\"Generation\":2},{\"Id\":\"e9e90ef8-5c77-4c4f-9214-eeecbc890cc5\",\"ConnectionGenes\":[{\"Id\":\"fcbf70b3-6255-448e-e6aa-08d7a435cc56\",\"OrganismId\":\"e9e90ef8-5c77-4c4f-9214-eeecbc890cc5\",\"InNodeIdentifier\":0,\"OutNodeIdentifier\":2,\"Weight\":0.7500601238804219,\"Enabled\":true},{\"Id\":\"1646d659-0670-41cc-e6ab-08d7a435cc56\",\"OrganismId\":\"e9e90ef8-5c77-4c4f-9214-eeecbc890cc5\",\"InNodeIdentifier\":1,\"OutNodeIdentifier\":2,\"Weight\":0.9267026316498884,\"Enabled\":true}],\"InputNodes\":[{\"Id\":\"39ee22e9-1be8-44cf-bf2c-9334b4741a57\",\"Layer\":0,\"NodeIdentifier\":0},{\"Id\":\"45ea4559-3f38-48bd-b337-e3105225573e\",\"Layer\":0,\"NodeIdentifier\":1}],\"OutputNodes\":[{\"Id\":\"0051c8eb-ef42-4852-bc57-b2897cc9d73b\",\"Layer\":0,\"NodeIdentifier\":2}],\"Score\":0,\"Name\":\"cous\",\"Generation\":2},{\"Id\":\"cc95b2f0-b498-4291-b9fd-d6d1654b7459\",\"ConnectionGenes\":[{\"Id\":\"9c738b6b-7efd-480d-e6a6-08d7a435cc56\",\"OrganismId\":\"cc95b2f0-b498-4291-b9fd-d6d1654b7459\",\"InNodeIdentifier\":0,\"OutNodeIdentifier\":2,\"Weight\":0.8646167163572352,\"Enabled\":true},{\"Id\":\"3702122f-1df3-4761-e6a7-08d7a435cc56\",\"OrganismId\":\"cc95b2f0-b498-4291-b9fd-d6d1654b7459\",\"InNodeIdentifier\":1,\"OutNodeIdentifier\":2,\"Weight\":0.8874416885839037,\"Enabled\":true}],\"InputNodes\":[{\"Id\":\"1a4c974f-f4f3-4bab-bcba-675e0c222d44\",\"Layer\":0,\"NodeIdentifier\":1},{\"Id\":\"c028f4b5-3475-46a9-bf6d-d4ba999a9728\",\"Layer\":0,\"NodeIdentifier\":0}],\"OutputNodes\":[{\"Id\":\"985cc945-e4bd-44f1-b45c-bc14cb0af9f4\",\"Layer\":0,\"NodeIdentifier\":2}],\"Score\":0,\"Name\":\"gan\",\"Generation\":2},{\"Id\":\"9704e91d-ae1e-4ff7-9a02-c67d4f86182f\",\"ConnectionGenes\":[{\"Id\":\"1c65a50e-2c21-439e-e6ac-08d7a435cc56\",\"OrganismId\":\"9704e91d-ae1e-4ff7-9a02-c67d4f86182f\",\"InNodeIdentifier\":1,\"OutNodeIdentifier\":2,\"Weight\":-0.8779935286743537,\"Enabled\":false},{\"Id\":\"b9e266da-932b-4eeb-e6ad-08d7a435cc56\",\"OrganismId\":\"9704e91d-ae1e-4ff7-9a02-c67d4f86182f\",\"InNodeIdentifier\":0,\"OutNodeIdentifier\":2,\"Weight\":0.3642462377269968,\"Enabled\":true},{\"Id\":\"7f27e42d-778e-4fba-e6ae-08d7a435cc56\",\"OrganismId\":\"9704e91d-ae1e-4ff7-9a02-c67d4f86182f\",\"InNodeIdentifier\":1,\"OutNodeIdentifier\":3,\"Weight\":1,\"Enabled\":true},{\"Id\":\"68d79c3c-cf40-438b-e6af-08d7a435cc56\",\"OrganismId\":\"9704e91d-ae1e-4ff7-9a02-c67d4f86182f\",\"InNodeIdentifier\":3,\"OutNodeIdentifier\":2,\"Weight\":-0.8672354359027163,\"Enabled\":true}],\"InputNodes\":[{\"Id\":\"cccf3da0-cf42-4fb6-9749-660eb011359a\",\"Layer\":0,\"NodeIdentifier\":1},{\"Id\":\"06b715ea-adaa-40e3-8e7a-7f1dbecd069b\",\"Layer\":0,\"NodeIdentifier\":0}],\"OutputNodes\":[{\"Id\":\"0a7901ff-2a01-44be-adc9-8ffca05d8000\",\"Layer\":0,\"NodeIdentifier\":2}],\"Score\":0,\"Name\":\"hyz\",\"Generation\":2},{\"Id\":\"cb6d22f5-4d6c-4add-81ad-d7f518634fcc\",\"ConnectionGenes\":[{\"Id\":\"7474d31c-073d-4b39-e69b-08d7a435cc56\",\"OrganismId\":\"cb6d22f5-4d6c-4add-81ad-d7f518634fcc\",\"InNodeIdentifier\":0,\"OutNodeIdentifier\":2,\"Weight\":-0.36319920670390093,\"Enabled\":true}],\"InputNodes\":[{\"Id\":\"cc2f4aaa-79f1-40f5-bef2-4f8788269440\",\"Layer\":0,\"NodeIdentifier\":0},{\"Id\":\"3c2f4a2d-767a-4807-af5f-a40a3104dc64\",\"Layer\":0,\"NodeIdentifier\":1}],\"OutputNodes\":[{\"Id\":\"1b106372-4f1a-4200-9ada-4a3c5bc39a25\",\"Layer\":0,\"NodeIdentifier\":2}],\"Score\":0,\"Name\":\"piebacocauv\",\"Generation\":2}],\"Id\":\"33236a35-9ad4-46cb-aa07-8d68aef87fc4\",\"RequestId\":\"b873fb68-e983-47c8-a846-83b65846afb2\",\"DateTime\":\"2020-01-29T19:17:13.1786668Z\",\"Message\":\"The requested amount of organisms are not all available. The training room is close to a new generation.\",\"Success\":true}";
+
+ JsonParser parser = new JsonParser();
+ JsonObject object = parser.parse(json).getAsJsonObject();
+ JsonArray organisms = object.getAsJsonArray("Organisms");
+
+ Gson gson = new GsonBuilder().setFieldNamingStrategy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
+ for(int i = 0; i < organisms.size(); i++) {
+ System.out.println(organisms.get(i).toString());
+ Organism organism = gson.fromJson(organisms.get(i), Organism.class);
+ organism.initialize();
+ }
+ }
+
+ @ParameterizedTest
+ @CsvFileSource(resources = "/loadOrganismTest.csv")
+ void parseFromJsonEvaluate(String json, double inA, double inB, double inC, double expected) {
+ Organism organism = new JsonSerializer().deserialize(json.getBytes(StandardCharsets.UTF_8), Organism.class);
+ organism.initialize();
+
+ Assertions.assertEquals(expected, organism.evaluate(new double[]{inA, inB, inC})[0], 0.0000000001);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/loadOrganismTest.csv b/src/test/resources/loadOrganismTest.csv
new file mode 100644
index 0000000..8fe6a5d
--- /dev/null
+++ b/src/test/resources/loadOrganismTest.csv
@@ -0,0 +1,9 @@
+"{""Id"":""db63e5a8-c360-486b-a565-1762c06af5a5"",""ConnectionGenes"":[{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":1,""OutNodeIdentifier"":3,""InnovationNumber"":1,""Weight"":0.077578324814130739,""Enabled"":false},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":1,""OutNodeIdentifier"":7,""InnovationNumber"":13,""Weight"":1.0,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":7,""OutNodeIdentifier"":3,""InnovationNumber"":14,""Weight"":0.21575169973808883,""Enabled"":true}],""InputNodes"":[{""Id"":""4081e0ef-8c81-43cc-a321-01d35dd0a656"",""Layer"":0,""NodeIdentifier"":0},{""Id"":""5bfa5705-1475-4b18-9f45-5a8470a4be84"",""Layer"":0,""NodeIdentifier"":1},{""Id"":""37c0fe8e-7fcd-4454-9271-72a8ba9b4a77"",""Layer"":0,""NodeIdentifier"":2}],""OutputNodes"":[{""Id"":""b59f7079-2235-4730-9004-aa090d0bb7cd"",""Layer"":0,""NodeIdentifier"":3}],""Score"":0.0,""Name"":""qeel"",""Generation"":8}", 1, 2, 3, 0.5473659097472284
+"{""Id"":""db63e5a8-c360-486b-a565-1762c06af5a5"",""ConnectionGenes"":[{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":1,""OutNodeIdentifier"":3,""InnovationNumber"":1,""Weight"":0.077578324814130739,""Enabled"":false},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":1,""OutNodeIdentifier"":7,""InnovationNumber"":13,""Weight"":1.0,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":7,""OutNodeIdentifier"":3,""InnovationNumber"":14,""Weight"":0.21575169973808883,""Enabled"":true}],""InputNodes"":[{""Id"":""4081e0ef-8c81-43cc-a321-01d35dd0a656"",""Layer"":0,""NodeIdentifier"":0},{""Id"":""5bfa5705-1475-4b18-9f45-5a8470a4be84"",""Layer"":0,""NodeIdentifier"":1},{""Id"":""37c0fe8e-7fcd-4454-9271-72a8ba9b4a77"",""Layer"":0,""NodeIdentifier"":2}],""OutputNodes"":[{""Id"":""b59f7079-2235-4730-9004-aa090d0bb7cd"",""Layer"":0,""NodeIdentifier"":3}],""Score"":0.0,""Name"":""qeel"",""Generation"":8}", 1, 2, 5, 0.5473659097472284
+"{""Id"":""db63e5a8-c360-486b-a565-1762c06af5a5"",""ConnectionGenes"":[{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":1,""OutNodeIdentifier"":3,""InnovationNumber"":1,""Weight"":0.077578324814130739,""Enabled"":false},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":1,""OutNodeIdentifier"":7,""InnovationNumber"":13,""Weight"":1.0,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":7,""OutNodeIdentifier"":3,""InnovationNumber"":14,""Weight"":0.21575169973808883,""Enabled"":true}],""InputNodes"":[{""Id"":""4081e0ef-8c81-43cc-a321-01d35dd0a656"",""Layer"":0,""NodeIdentifier"":0},{""Id"":""5bfa5705-1475-4b18-9f45-5a8470a4be84"",""Layer"":0,""NodeIdentifier"":1},{""Id"":""37c0fe8e-7fcd-4454-9271-72a8ba9b4a77"",""Layer"":0,""NodeIdentifier"":2}],""OutputNodes"":[{""Id"":""b59f7079-2235-4730-9004-aa090d0bb7cd"",""Layer"":0,""NodeIdentifier"":3}],""Score"":0.0,""Name"":""qeel"",""Generation"":8}", 1, -1, 3, 0.5145020735663703
+
+"{""Id"":""db63e5a8-c360-486b-a565-1762c06af5a5"",""ConnectionGenes"":[{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":0,""OutNodeIdentifier"":3,""InnovationNumber"":0,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":1,""OutNodeIdentifier"":3,""InnovationNumber"":1,""Weight"":1.0,""Enabled"":false},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":2,""OutNodeIdentifier"":3,""InnovationNumber"":2,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":1,""OutNodeIdentifier"":4,""InnovationNumber"":3,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":4,""OutNodeIdentifier"":3,""InnovationNumber"":4,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":0,""OutNodeIdentifier"":4,""InnovationNumber"":5,""Weight"":1,""Enabled"":true}],""InputNodes"":[{""Id"":""4081e0ef-8c81-43cc-a321-01d35dd0a656"",""Layer"":0,""NodeIdentifier"":0},{""Id"":""5bfa5705-1475-4b18-9f45-5a8470a4be84"",""Layer"":0,""NodeIdentifier"":1},{""Id"":""37c0fe8e-7fcd-4454-9271-72a8ba9b4a77"",""Layer"":0,""NodeIdentifier"":2}],""OutputNodes"":[{""Id"":""b59f7079-2235-4730-9004-aa090d0bb7cd"",""Layer"":0,""NodeIdentifier"":3}],""Score"":0.0,""Name"":""qeel"",""Generation"":8}", 1 ,2 ,3 ,0.8328355518722748
+"{""Id"":""db63e5a8-c360-486b-a565-1762c06af5a5"",""ConnectionGenes"":[{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":0,""OutNodeIdentifier"":3,""InnovationNumber"":0,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":1,""OutNodeIdentifier"":3,""InnovationNumber"":1,""Weight"":1.0,""Enabled"":false},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":2,""OutNodeIdentifier"":3,""InnovationNumber"":2,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":1,""OutNodeIdentifier"":4,""InnovationNumber"":3,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":4,""OutNodeIdentifier"":3,""InnovationNumber"":4,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":0,""OutNodeIdentifier"":4,""InnovationNumber"":5,""Weight"":1,""Enabled"":true}],""InputNodes"":[{""Id"":""4081e0ef-8c81-43cc-a321-01d35dd0a656"",""Layer"":0,""NodeIdentifier"":0},{""Id"":""5bfa5705-1475-4b18-9f45-5a8470a4be84"",""Layer"":0,""NodeIdentifier"":1},{""Id"":""37c0fe8e-7fcd-4454-9271-72a8ba9b4a77"",""Layer"":0,""NodeIdentifier"":2}],""OutputNodes"":[{""Id"":""b59f7079-2235-4730-9004-aa090d0bb7cd"",""Layer"":0,""NodeIdentifier"":3}],""Score"":0.0,""Name"":""qeel"",""Generation"":8}", 3 ,2 ,1 ,0.8377227092646183
+"{""Id"":""db63e5a8-c360-486b-a565-1762c06af5a5"",""ConnectionGenes"":[{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":0,""OutNodeIdentifier"":3,""InnovationNumber"":0,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":1,""OutNodeIdentifier"":3,""InnovationNumber"":1,""Weight"":1.0,""Enabled"":false},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":2,""OutNodeIdentifier"":3,""InnovationNumber"":2,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":1,""OutNodeIdentifier"":4,""InnovationNumber"":3,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":4,""OutNodeIdentifier"":3,""InnovationNumber"":4,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":0,""OutNodeIdentifier"":4,""InnovationNumber"":5,""Weight"":1,""Enabled"":true}],""InputNodes"":[{""Id"":""4081e0ef-8c81-43cc-a321-01d35dd0a656"",""Layer"":0,""NodeIdentifier"":0},{""Id"":""5bfa5705-1475-4b18-9f45-5a8470a4be84"",""Layer"":0,""NodeIdentifier"":1},{""Id"":""37c0fe8e-7fcd-4454-9271-72a8ba9b4a77"",""Layer"":0,""NodeIdentifier"":2}],""OutputNodes"":[{""Id"":""b59f7079-2235-4730-9004-aa090d0bb7cd"",""Layer"":0,""NodeIdentifier"":3}],""Score"":0.0,""Name"":""qeel"",""Generation"":8}", 0 ,0 ,0 ,0.5415704832167999
+"{""Id"":""db63e5a8-c360-486b-a565-1762c06af5a5"",""ConnectionGenes"":[{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":0,""OutNodeIdentifier"":3,""InnovationNumber"":0,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":1,""OutNodeIdentifier"":3,""InnovationNumber"":1,""Weight"":1.0,""Enabled"":false},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":2,""OutNodeIdentifier"":3,""InnovationNumber"":2,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":1,""OutNodeIdentifier"":4,""InnovationNumber"":3,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":4,""OutNodeIdentifier"":3,""InnovationNumber"":4,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":0,""OutNodeIdentifier"":4,""InnovationNumber"":5,""Weight"":1,""Enabled"":true}],""InputNodes"":[{""Id"":""4081e0ef-8c81-43cc-a321-01d35dd0a656"",""Layer"":0,""NodeIdentifier"":0},{""Id"":""5bfa5705-1475-4b18-9f45-5a8470a4be84"",""Layer"":0,""NodeIdentifier"":1},{""Id"":""37c0fe8e-7fcd-4454-9271-72a8ba9b4a77"",""Layer"":0,""NodeIdentifier"":2}],""OutputNodes"":[{""Id"":""b59f7079-2235-4730-9004-aa090d0bb7cd"",""Layer"":0,""NodeIdentifier"":3}],""Score"":0.0,""Name"":""qeel"",""Generation"":8}", -1,-2,-3,0.2188253499884587
+"{""Id"":""db63e5a8-c360-486b-a565-1762c06af5a5"",""ConnectionGenes"":[{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":0,""OutNodeIdentifier"":3,""InnovationNumber"":0,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":1,""OutNodeIdentifier"":3,""InnovationNumber"":1,""Weight"":1.0,""Enabled"":false},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":2,""OutNodeIdentifier"":3,""InnovationNumber"":2,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":1,""OutNodeIdentifier"":4,""InnovationNumber"":3,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":4,""OutNodeIdentifier"":3,""InnovationNumber"":4,""Weight"":1,""Enabled"":true},{""Id"":""00000000-0000-0000-0000-000000000000"",""OrganismId"":""4bde222f-ef61-4bb9-a362-60abafbe5dba"",""InNodeIdentifier"":0,""OutNodeIdentifier"":4,""InnovationNumber"":5,""Weight"":1,""Enabled"":true}],""InputNodes"":[{""Id"":""4081e0ef-8c81-43cc-a321-01d35dd0a656"",""Layer"":0,""NodeIdentifier"":0},{""Id"":""5bfa5705-1475-4b18-9f45-5a8470a4be84"",""Layer"":0,""NodeIdentifier"":1},{""Id"":""37c0fe8e-7fcd-4454-9271-72a8ba9b4a77"",""Layer"":0,""NodeIdentifier"":2}],""OutputNodes"":[{""Id"":""b59f7079-2235-4730-9004-aa090d0bb7cd"",""Layer"":0,""NodeIdentifier"":3}],""Score"":0.0,""Name"":""qeel"",""Generation"":8}", -3,-2,-1,0.21281378940936574
\ No newline at end of file