public void InnovationNumberTest() { // Genome Genome gen1 = new Genome(r); Assert.IsTrue(gen1.GetInnovationNumber() == 0); // Create 3 sensors gen1.AddNode(new Node(Node.ENodeType.SENSOR, 1)); gen1.AddNode(new Node(Node.ENodeType.SENSOR, 2)); gen1.AddNode(new Node(Node.ENodeType.SENSOR, 3)); // Create 1 output gen1.AddNode(new Node(Node.ENodeType.OUTPUT, 4)); // Create 1 hidden node gen1.AddNode(new Node(Node.ENodeType.HIDDEN, 5)); // Add connections from the paper gen1.AddConnectionGene(1, 4, 0.5f); Assert.IsTrue(gen1.GetInnovationNumber() == 1); gen1.AddConnectionGene(2, 4, false); Assert.IsTrue(gen1.GetInnovationNumber() == 2); gen1.AddConnectionGene(3, 4); Assert.IsTrue(gen1.GetInnovationNumber() == 3); gen1.AddConnectionGene(2, 5); Assert.IsTrue(gen1.GetInnovationNumber() == 4); gen1.AddConnectionGene(5, 4); Assert.IsTrue(gen1.GetInnovationNumber() == 5); gen1.AddConnectionGene(1, 5, true); Assert.IsTrue(gen1.GetInnovationNumber() == 6); }
public void SetupTest() { r = new Random(0); // Genome gen = new Genome(r); // Create 3 sensors gen.AddNode(new Node(Node.ENodeType.SENSOR, 1)); gen.AddNode(new Node(Node.ENodeType.SENSOR, 2)); gen.AddNode(new Node(Node.ENodeType.SENSOR, 3)); // Create 1 output gen.AddNode(new Node(Node.ENodeType.OUTPUT, 4)); // Create 1 hidden node gen.AddNode(new Node(Node.ENodeType.HIDDEN, 5)); // Add connections from the paper gen.AddConnectionGene(1, 4, 0.5f); gen.AddConnectionGene(2, 4, false); gen.AddConnectionGene(3, 4); gen.AddConnectionGene(2, 5); gen.AddConnectionGene(5, 4); gen.AddConnectionGene(1, 5, 8, true); }
public void Initialize(int input, int output) { Genome genome = new Genome(); for (int i = 0; i < input; i++) { Node node = new Node(Node.NodeType.INPUT, i + 1); genome.AddNode(node); } for (int i = input; i < output + input; i++) { Node node = new Node(Node.NodeType.OUTPUT, i + 1); genome.AddNode(node); } int inno = 0; for (int i = 1; i <= input; i++) { for (int j = input + 1; j <= output + input; j++) { genome.AddConnection(new Connection(i, j, 0f, true, ++inno)); } } _brain = genome; _initialized = true; }
public void Start() { vision.Add(0); vision.Add(1); vision.Add(2); for (int i = 0; i < 3; i++) { Node node = new Node(Node.NodeType.INPUT, i + 1); genome.AddNode(node); } genome.AddNode(new Node(Node.NodeType.OUTPUT, 4)); genome.AddNode(new Node(Node.NodeType.OUTPUT, 5)); genome.AddNode(new Node(Node.NodeType.OUTPUT, 6)); //genome.AddNode(new Node(Node.NodeType.HIDDEN, 5)); //genome.AddNode(new Node(Node.NodeType.HIDDEN, 6)); genome.AddConnection(new Connection(1, 4, 0f, true, 1)); genome.AddConnection(new Connection(2, 5, 0f, true, 2)); genome.AddConnection(new Connection(3, 6, 0f, true, 3)); foreach (Connection c in genome.Connections.Values) { History.AddConnectionToInnovationHistoryDebug(c); } gameObject.GetComponent <GenomePrinter>().Draw(genome); Genome.DebugPrint(genome); History.SetInnovationDebug(3); }
private void Start() { for (int i = 0; i < 2; i++) { Node node = new Node(Node.NodeType.INPUT, i + 1); genome.AddNode(node); } genome.AddNode(new Node(Node.NodeType.OUTPUT, 3)); genome.AddNode(new Node(Node.NodeType.HIDDEN, 4)); genome.AddConnection(new Connection(1, 4, 0.2f, true, 1)); genome.AddConnection(new Connection(2, 4, 0.4f, true, 2)); genome.AddConnection(new Connection(4, 3, 1f, true, 3)); genome.AddConnection(new Connection(1, 3, -0.3f, true, 4)); History.SetInnovationDebug(4); /* * for (int i = 0; i < 30; i++) * { * genome.Mutate(); * } * */ ForwardProp(); GetComponent <GenomePrinter>().Draw(genome); }
public void AddGenomesToSpeciesTest() { UnitTests.RandomStub randomStub = new UnitTests.RandomStub(); Simulation sim = new Simulation(randomStub, gen, 10); // Create some fake species and genomes Species species1 = new Species(randomStub); // Two genomes are matching, one is not so we should get 2 species (with 2 and 1 Genomes respectively) Genome gen1 = new Genome(randomStub); Genome gen2 = new Genome(randomStub); Genome gen3 = new Genome(randomStub); gen3.ParentSimulation = sim; gen3.AddNode(new Node(Node.ENodeType.SENSOR, 1)); gen3.AddNode(new Node(Node.ENodeType.SENSOR, 2)); gen3.AddNode(new Node(Node.ENodeType.OUTPUT, 3)); gen3.AddNode(new Node(Node.ENodeType.OUTPUT, 4)); gen3.AddConnectionGene(1, 2, true); gen3.AddConnectionGene(1, 3, true); gen3.AddConnectionGene(1, 4, true); sim.Species.Clear(); sim.AddGenomesToSpecies(new List <Genome> { gen1, gen2, gen3 }); Assert.AreEqual(2, sim.Species.Count); Assert.AreEqual(2, sim.Species[0].Genomes.Count); Assert.AreEqual(1, sim.Species[1].Genomes.Count); }
public void InsertGeneTest_Null_ExpectedException() { UnitTests.RandomStub randomStub = new UnitTests.RandomStub(); randomStub.NextIntValue = 0; randomStub.NextDoubleValue = 0.0; Genome genome = new Genome(randomStub); genome.AddNode(new Node(Node.ENodeType.SENSOR, 1)); genome.AddNode(new Node(Node.ENodeType.OUTPUT, 2)); genome.InsertConnectionGene(null); }
public void FindConnectionGeneToSplitTest_NoGenes_Expected_False() { Genome genome = new Genome(r); genome.AddNode(new Node(Node.ENodeType.SENSOR, 1)); genome.AddNode(new Node(Node.ENodeType.OUTPUT, 2)); int connectionIndex = -1; bool found = genome.FindConnectionGeneToSplit(out connectionIndex); Assert.AreEqual(false, found); Assert.AreEqual(-1, connectionIndex); }
public static Genome Crossover(Genome parent1, Genome parent2, Random r) //Creates a child genome from two parent genomes. Parent 1 has higher fitness. { Genome child = new Genome(); List <Genome.NodeGene> parent1nodes = parent1.GetNodes(); Dictionary <int, Genome.ConnectionGene> parent1connections = parent1.GetConnections(); Dictionary <int, Genome.ConnectionGene> parent2connections = parent2.GetConnections(); foreach (Genome.NodeGene p1node in parent1nodes) { child.AddNode(p1node); } foreach (Genome.ConnectionGene p1con in parent1connections.Values) { if (parent2connections.ContainsKey(p1con.GetInnovation())) { child.AddConnection(r.Next(100) < 50 ? p1con : parent2connections[p1con.GetInnovation()]); } else { child.AddConnection(p1con); } } return(child); }
public void FindConnectionGeneToSplitTest_Correct_Expected_True() { UnitTests.RandomStub randomStub = new UnitTests.RandomStub(); randomStub.NextIntValue = 0; randomStub.NextDoubleValue = 0.0; Genome genome = new Genome(randomStub); genome.AddNode(new Node(Node.ENodeType.SENSOR, 1)); genome.AddNode(new Node(Node.ENodeType.OUTPUT, 2)); genome.AddConnectionGene(1, 2, true); int connectionIndex = -1; bool found = genome.FindConnectionGeneToSplit(out connectionIndex); Assert.AreEqual(true, found); Assert.AreEqual(0, connectionIndex); }
public void TestAddNodeMutation() { Simulation tmpSim = new Simulation(r, gen1, 1); gen1.ParentSimulation = tmpSim; List <Innovation> innovations = new List <Innovation>(); Genome gen3 = new Genome(r); gen3.ParentSimulation = tmpSim; gen3.AddNode(new Node(Node.ENodeType.SENSOR, 1)); gen3.AddNode(new Node(Node.ENodeType.SENSOR, 2)); gen3.AddNode(new Node(Node.ENodeType.OUTPUT, 3)); gen3.AddConnectionGene(1, 3, 0.5f); gen3.AddConnectionGene(2, 3, 1.0f); Assert.IsTrue(gen3.Nodes.Count == 3); gen3.AddNodeMutation(innovations); Assert.IsTrue(gen3.Nodes.Count == 4); }
public void TestAddConnectionMutation() { List <Innovation> innovations = new List <Innovation>(); Simulation tmpSim = new Simulation(r, gen1, 1); gen1.ParentSimulation = tmpSim; Genome gen4 = new Genome(r); gen4.ParentSimulation = tmpSim; // Create 3 sensors gen4.AddNode(new Node(Node.ENodeType.SENSOR, 1)); gen4.AddNode(new Node(Node.ENodeType.SENSOR, 2)); gen4.AddNode(new Node(Node.ENodeType.SENSOR, 3)); // Create 1 output gen4.AddNode(new Node(Node.ENodeType.OUTPUT, 4)); // Create 1 hidden node gen4.AddNode(new Node(Node.ENodeType.HIDDEN, 5)); // Add connections from the paper gen4.AddConnectionGene(1, 4); gen4.AddConnectionGene(2, 4); gen4.AddConnectionGene(3, 4); gen4.AddConnectionGene(2, 5); gen4.AddConnectionGene(5, 4); Assert.IsTrue(gen4.ConnectionGenes.Count == 5); gen4.AddConnectionMutation(innovations); Assert.IsTrue(gen4.ConnectionGenes.Count == 6); }
public void FindFirstNonInputNodeTest() { Assert.AreEqual(3, gen1.FindFirstNonInputNode()); // Genome 1 Genome newGenome = new Genome(r); // Create 3 sensors & 1 bias newGenome.AddNode(new Node(Node.ENodeType.SENSOR, 1)); newGenome.AddNode(new Node(Node.ENodeType.SENSOR, 2)); newGenome.AddNode(new Node(Node.ENodeType.SENSOR, 3)); newGenome.AddNode(new Node(Node.ENodeType.BIAS, 4)); // Create 1 output newGenome.AddNode(new Node(Node.ENodeType.OUTPUT, 4)); // Create 1 hidden node newGenome.AddNode(new Node(Node.ENodeType.HIDDEN, 5)); Assert.AreEqual(4, newGenome.FindFirstNonInputNode()); }
private static void PoleBalanceSingleTest(Random r) { Genome startGenome = new Genome(r); startGenome.AddNode(new Node(Node.ENodeType.SENSOR, 1)); startGenome.AddNode(new Node(Node.ENodeType.SENSOR, 2)); startGenome.AddNode(new Node(Node.ENodeType.SENSOR, 3)); startGenome.AddNode(new Node(Node.ENodeType.SENSOR, 4)); startGenome.AddNode(new Node(Node.ENodeType.SENSOR, 5)); startGenome.AddNode(new Node(Node.ENodeType.OUTPUT, 6)); startGenome.AddNode(new Node(Node.ENodeType.OUTPUT, 7)); startGenome.AddConnectionGene(1, 6, 0.0f); startGenome.AddConnectionGene(2, 6, 0.0f); startGenome.AddConnectionGene(3, 6, 0.0f); startGenome.AddConnectionGene(4, 6, 0.0f); startGenome.AddConnectionGene(5, 6, 0.0f); startGenome.AddConnectionGene(1, 7, 0.0f); startGenome.AddConnectionGene(2, 7, 0.0f); startGenome.AddConnectionGene(3, 7, 0.0f); startGenome.AddConnectionGene(4, 7, 0.0f); startGenome.AddConnectionGene(5, 7, 0.0f); // Run simulation Simulation sim = new Simulation(r, startGenome, 150); int numberOfRuns = 200; int numnodes; // Used to figure out how many nodes should be visited during activation int thresh; // How many visits will be allowed before giving up (for loop detection) int MAX_STEPS = 100000; bool solutionFound = false; Genome bestGenome = null; for (int i = 0; i < numberOfRuns; ++i) { double epochBestFitness = 0.0f; float avgConnectionGenes = 0.0f; // Evaluate all genomes foreach (Genome gen in sim.Genomes) { Network network = gen.GetNetwork(); numnodes = gen.Nodes.Count; thresh = numnodes * 2; gen.Fitness = Go_cart(network, MAX_STEPS, thresh, r); if (gen.Fitness > epochBestFitness) { epochBestFitness = gen.Fitness; } avgConnectionGenes += gen.ConnectionGenes.Count; if (gen.Fitness >= MAX_STEPS) { bestGenome = gen; solutionFound = true; break; } } avgConnectionGenes /= sim.Genomes.Count; Console.WriteLine(String.Format("Epoch {0} | best: {1} | avg genes: {2} | species: {3}", i, epochBestFitness, avgConnectionGenes, sim.Species.Count)); if (solutionFound) { break; } sim.Epoch(); } if (solutionFound) { Console.WriteLine(String.Format("Solution network nodes count: {0} | connections count: {1}", bestGenome.Nodes.Count, bestGenome.ConnectionGenes.Count)); } else { Console.WriteLine("Solution NOT found!"); } }
private static void XorTest(Random r) { Genome xorGene = new Genome(r); xorGene.AddNode(new Node(Node.ENodeType.SENSOR, 1)); xorGene.AddNode(new Node(Node.ENodeType.SENSOR, 2)); xorGene.AddNode(new Node(Node.ENodeType.SENSOR, 3)); xorGene.AddNode(new Node(Node.ENodeType.OUTPUT, 4)); xorGene.AddConnectionGene(1, 4, 0.0f); xorGene.AddConnectionGene(2, 4, 0.0f); xorGene.AddConnectionGene(3, 4, 0.0f); // Run simulation Simulation sim = new Simulation(r, xorGene, 150); sim.Parameters.AreConnectionWeightsCapped = false; sim.Parameters.MaxWeight = 1.0f; sim.Parameters.WeightMutationPower = 2.5f; int numberOfRuns = 200; bool solutionFound = false; Genome bestGenome = null; float[] output = { 0.0f, 0.0f, 0.0f, 0.0f }; float[] bestOutput = new float[4]; float[,] input = { { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f } }; for (int i = 0; i < numberOfRuns; ++i) { double epochBestFitness = 0.0f; float avgConnectionGenes = 0.0f; // Evaluate all genomes foreach (Genome gen in sim.Genomes) { Network network = gen.GetNetwork(); //network.ActivationFunction = new NeuralEvolution.ActivationFunctions.ReLU(); bool couldActivate = true; for (int inputIdx = 0; inputIdx < 4; ++inputIdx) { float[] inputRow = new float[3]; for (int k = 0; k < 3; ++k) { inputRow[k] = input[inputIdx, k]; } network.SetInput(inputRow); if (!network.Activate()) { couldActivate = false; } // Relax network int networkDepth = network.GetMaxDepth(); for (int relax = 0; relax <= networkDepth; ++relax) { network.Activate(); } output[inputIdx] = network.Output[0].Activation; network.Reset(); } float errorsum = (float)(Math.Abs(output[0]) + Math.Abs(1.0 - output[1]) + Math.Abs(1.0 - output[2]) + Math.Abs(output[3])); if (!couldActivate) { errorsum = 4; } gen.Fitness = Math.Pow((4.0 - errorsum), 2); gen.Error = errorsum; if (gen.Fitness > epochBestFitness) { bestOutput[0] = output[0]; bestOutput[1] = output[1]; bestOutput[2] = output[2]; bestOutput[3] = output[3]; epochBestFitness = gen.Fitness; } avgConnectionGenes += gen.ConnectionGenes.Count; if ((output[0] < 0.5f) && (output[1] >= 0.5f) && (output[2] >= 0.5f) && (output[3] < 0.5f)) { bestOutput[0] = output[0]; bestOutput[1] = output[1]; bestOutput[2] = output[2]; bestOutput[3] = output[3]; bestGenome = gen; solutionFound = true; break; } } avgConnectionGenes /= sim.Genomes.Count; Console.WriteLine(String.Format("Epoch {0} | best: {1} | best output: [{2}, {3}, {4}, {5}] | avg genes: {6} | species: {7}", i, epochBestFitness, bestOutput[0], bestOutput[1], bestOutput[2], bestOutput[3], avgConnectionGenes, sim.Species.Count)); // We found a solution so we can exit already if (solutionFound) { break; } // Advance to the next step of simulation sim.Epoch(); } if (solutionFound) { Console.WriteLine(String.Format("Solution found: [{0}, {1}, {2}, {3}]", bestOutput[0], bestOutput[1], bestOutput[2], bestOutput[3])); Console.WriteLine(String.Format("Solution network nodes count: {0} | connections count: {1}", bestGenome.Nodes.Count, bestGenome.ConnectionGenes.Count)); } else { Console.WriteLine("Solution NOT found!"); } }
private void InitSimulation() { Console.WriteLine("Would you like to save all best snakes? [Yn]"); var key = Console.ReadKey().Key; if (key == ConsoleKey.Y) { this.saveAllBestSnakes = true; } Console.WriteLine(""); Console.WriteLine("--- Simulation started ---"); Snake.StartingLength = 1; // 3;// int.Parse(this.startingSnakeLength.text); Genome startGenome = new Genome(rnd); int startIdx = 1; int bias = 0; // 1 node is used as a bias (always 1.0) // 3 nodes are used to store distance to the walls // 3 nodes are used to store distance to the snake itself (to avoid collisions with self), // 3 nodes are used to store distance to food int inputs = 3 + 3 + 3; int hidden = 0; int outputs = 3; // 3 outputs. Direction of movement - left, right, straight for (int i = 0; i < bias; ++i) { startGenome.AddNode(new Node(Node.ENodeType.BIAS, startIdx++)); } int inputStart = startIdx; for (int i = 0; i < inputs; ++i) { startGenome.AddNode(new Node(Node.ENodeType.SENSOR, startIdx++)); } int hiddenStart = startIdx; for (int i = 0; i < hidden; ++i) { startGenome.AddNode(new Node(Node.ENodeType.HIDDEN, startIdx++)); } // Output: Move left, straight, right int outputStart = startIdx; for (int i = 0; i < outputs; ++i) { startGenome.AddNode(new Node(Node.ENodeType.OUTPUT, startIdx++)); } if (hidden > 0) { for (int i = 0; i < hidden; ++i) { for (int j = 0; j < inputs; ++j) { startGenome.AddConnectionGene(inputStart + j, hiddenStart + i, 0.0f); } for (int j = 0; j < outputs; ++j) { startGenome.AddConnectionGene(hiddenStart + i, outputStart + j, 0.0f); } } } else { // Walls distance /*startGenome.AddConnectionGene(2, outputStart + 0, 0.0f); * startGenome.AddConnectionGene(3, outputStart + 1, 0.0f); * startGenome.AddConnectionGene(4, outputStart + 2, 0.0f); * * // Tails distance * startGenome.AddConnectionGene(5, outputStart + 0, 0.0f); * startGenome.AddConnectionGene(6, outputStart + 1, 0.0f); * startGenome.AddConnectionGene(7, outputStart + 2, 0.0f); * * // Food distance * startGenome.AddConnectionGene(8, outputStart + 0, 0.0f); * startGenome.AddConnectionGene(9, outputStart + 1, 0.0f); * startGenome.AddConnectionGene(10, outputStart + 2, 0.0f);*/ for (int i = 0; i < inputs; ++i) { //for(int j = 0; j < outputs; ++j) //startGenome.AddConnectionGene(inputStart + i, outputStart + j, 0.0f); startGenome.AddConnectionGene(inputStart + i, outputStart + rnd.Next(outputs), 0.0f); } } // Connect bias node to every output for (int i = 0; i < bias; ++i) { for (int j = 0; j < outputs; ++j) { startGenome.AddConnectionGene(i + 1, outputStart + j, 0.0f); } } // Set up simulation - but don't start it sim = new Simulation(rnd, startGenome, 15000); sim.Parameters.AddNodeProbability = 0.02f; sim.Parameters.AddConnectionProbability = 0.1f; sim.Parameters.WeightMutationPower = 1.0f; sim.Parameters.MutateConnectionWeightsProbability = 0.8f; sim.Parameters.MutateToggleEnabledProbability = 0.05f; sim.Parameters.MutateReenableProbability = 0.025f; sim.Parameters.SurvivalThreshold = 0.01f; sim.Parameters.AreConnectionWeightsCapped = true; sim.Parameters.MaxWeight = 1.0f; sim.Parameters.MaxSpeciesGenerationsWithoutImprovement = 70; sim.Parameters.MaxGeneralGenerationsWithoutImprovement = 80; }
public Generation MakeFirstGeneration(InnovationGenerator generator, InnovationGenerator genomeGenerator, int initialPopulationSize, int selectionAlgorithm, int reproductionsPerGenome, int nBest) { // check if there is a Lua implementation of this LuaFunction func = LuaState["MakeFirstGeneration"] as LuaFunction; if (func != null) { try { return((Generation)func.Call(generator, initialPopulationSize)?.First()); } catch (Exception e) { logger.Error(e, "Error running lua code for first generation."); } } Generation generation = new Generation(0, selectionAlgorithm, reproductionsPerGenome, nBest); Genome genome = new Genome(0); int inputs = Data.Constants.NetworkInputs; int outputs = Data.Constants.NetworkOutputs; List <int> inputIds = new List <int>(inputs); // input nodes for (int i = 0; i < inputs; i++) { int currentId = generator.Innovate(); inputIds.Add(currentId); genome.AddNode(new Node(currentId, NodeType.Input, int.MinValue)); } // output nodes for (int i = 0; i < outputs; i++) { int currentId = generator.Innovate(); genome.AddNode(new Node(currentId, NodeType.Output, int.MaxValue)); foreach (int hiddenId in inputIds) { genome.AddConnection(new Connection(hiddenId, currentId, Double() * 4f - 2f, true, generator.Innovate())); } } Species original = new Species(genome); generation.Species.Add(original); for (int i = 0; i < initialPopulationSize; i++) { Genome g = genome.Copy(); g.Mutate(generator); g.Id = genomeGenerator.Innovate(); original.AddGenome(g); } return(generation); }