public void TryGetEligibleConnectionToSplit() { var nn = new NeatNueralNetwork(1, 1); // if there are no innovations then there should be no eligible connections to split var pass = ((DefaultMutater)nn.Mutater).TryGetEligibleConnectionToSplit(out _, nn); // at this point the innovaiton should be enabled and eligble for splitting Assert.True(pass); // if there are only disbaled connections then there are no eligible connections nn.Innovations[0].Enabled = false; pass = ((DefaultMutater)nn.Mutater).TryGetEligibleConnectionToSplit(out var eligibleCons, nn); Assert.False(pass); Assert.Empty(eligibleCons); // enable it so there is an eligible connection nn.Innovations[0].Enabled = true; pass = ((DefaultMutater)nn.Mutater).TryGetEligibleConnectionToSplit(out eligibleCons, nn); // there should be 1 eligible connection returned Assert.True(pass); Assert.Single(eligibleCons); }
public void AddInnovation() { // make sure when we add innovations that conlifcting conventions are not violated and duplicate innovations always return their original ids var left = new NeatNueralNetwork(3, 2); var leftInn = new Innovation() { InputNode = 0, OutputNode = 3, Weight = 2.0f, Enabled = true, }; var right = new NeatNueralNetwork(3, 2); var rightInn = new Innovation() { InputNode = 0, OutputNode = 3, Weight = 0.334f, Enabled = false, }; left.AddInnovation(leftInn).Wait(); right.AddInnovation(rightInn).Wait(); // even through both innovatiuons arer different objects they should both hash the same and therefor be assigned the same id number by the global innovations list Assert.Equal(left.Innovations[0].Id, right.Innovations[0].Id); }
public void ConstructorWorks() { var nn = new NeatNueralNetwork(3, 2); // both arrays should be instantiated when the constructor is called Assert.NotNull(nn.Innovations); }
public void AddNode() { NeatNueralNetwork.GlobalInnovations.Clear(); var nn = new NeatNueralNetwork(1, 1); // we shouldnt be able to add a node if there are no innovations Assert.Equal(AddNodeResult.success, ((DefaultMutater)nn.Mutater).AddNode(nn).Result); // when we split the connection the new node should have the same weight as the original connection, and the // original input node should have a weight of 1 to prevent the new topology from impacting the fittness too badly of the new // topolgy Assert.False(nn.Innovations[0].Enabled); // make sure the innovation was properly recorded in the global innovations and the old connection was disabled Assert.Equal(3, nn.Innovations.Length); // make sure that the hashes for the new innovations were recorded Assert.Contains(nn.Innovations[1].Hash(), nn.InnovationHashes); Assert.Contains(nn.Innovations[2].Hash(), nn.InnovationHashes); Assert.True(NeatNueralNetwork.GlobalInnovations.InnovationHashes.ContainsKey(nn.Innovations[1].Hash())); Assert.True(NeatNueralNetwork.GlobalInnovations.InnovationHashes.ContainsKey(nn.Innovations[2].Hash())); // make sure the node that was created was added to the genome }
public void Check() { NeatNueralNetwork nn = (NeatNueralNetwork)CreateExampleNetwork(); int[][] layers = nn.PhenotypeGenerator.GetLayers(nn); // remember that the 0th layer is the output layer(it simplifies genotype construction) Assert.Equal(new int[] { 3 }, layers[0]); // the first layer(input layer) should have 0 1 and 2 Assert.Equal(new int[] { 0, 1, 2 }, layers[1]); // the hidden layer should only have 4 Assert.Equal(new int[] { 4 }, layers[2]); }
public void AddLocalAndGlobalInnovation() { NeatNueralNetwork.GlobalInnovations.Clear().Wait(); Assert.Empty(NeatNueralNetwork.GlobalInnovations.InnovationHashes); Assert.Empty(NeatNueralNetwork.GlobalInnovations.Innovations); // since these are static and the tests are multi-threaded we should clear previous values so this test remains accurate var nn = new NeatNueralNetwork(3, 2); Assert.Equal(3 * 2, NeatNueralNetwork.GlobalInnovations.InnovationHashes.Count); Assert.Equal(3 * 2, nn.Innovations.Length); Assert.Equal(3 * 2, NeatNueralNetwork.GlobalInnovations.Innovations.Count()); Assert.Equal(3 * 2, NeatNueralNetwork.GlobalInnovations.Count()); Assert.Equal(3, nn.Innovations[0].OutputNode); }
public void AddConnection() { var nn = new NeatNueralNetwork(1, 1); var inn = new Innovation() { Enabled = true, InputNode = 0, OutputNode = 1, Weight = 0.122221d }; // forcibly add an innovation to verify that we can't add duplicate connections nn.InnovationHashes.Add(inn.Hash()); Assert.Equal(AddConnectionResult.alreadyExists, ((DefaultMutater)nn.Mutater).AddConnection(nn).Result); nn.InnovationHashes.Clear(); Assert.Equal(AddConnectionResult.success, ((DefaultMutater)nn.Mutater).AddConnection(nn).Result); }
public async Task CalculatesCorrectly() { var nn = new NeatNueralNetwork(1, 1); // force mutation await((DefaultMutater)nn.Mutater).AddConnection(nn); nn.GeneratePhenotype(); double[] inputs = new double[] { 1 }; return; // evaluate the network double[] result = nn.Evaluator.Evaluate(inputs, nn); // make sure we only got the amount of outputnodes we originally started with Assert.Single(result); // make sure the number was squishified Assert.True(result[0] >= 0); Assert.True(result[0] <= 1); // further complicate the network to verify that recursion works correctly await((DefaultMutater)nn.Mutater).AddNode(nn); nn.GeneratePhenotype(); // now there should be a node inbetween the input and output, however becuase NEAT mutation dictates normal mutation of a node // as the original connection has it's weight set to 1 we should expect a similar or the same number from the second recursive eval double storedVal = result[0]; result = nn.Evaluator.Evaluate(inputs, nn); // make sure we only got the amount of outputnodes we originally started with Assert.Single(result); // make sure the number was squishified Assert.True(result[0] > 0); Assert.True(result[0] <= 1); Assert.Equal(storedVal, result[0]); // further complicate the network to ensure the 3rd level of recursion works as well await((DefaultMutater)nn.Mutater).AddNode(nn); nn.GeneratePhenotype(); storedVal = result[0]; result = nn.Evaluator.Evaluate(inputs, nn); // make sure we only got the amount of outputnodes we originally started with Assert.Single(result); // make sure the number was squishified Assert.True(result[0] > 0); Assert.True(result[0] <= 1); Assert.Equal(storedVal, result[0]); }