public void MutateAgent_Weight_Test() { MutationLog mutationLog = new MutationLog(); AgentObject customAgent = new CustomAgent(populationManager, parent2Genome, 10); Assert.AreEqual(6, customAgent.Genome.Nodes.Count); Assert.AreEqual(9, customAgent.Genome.Connections.Count); Dictionary <int, double> weights = new Dictionary <int, double>(); foreach (int key in customAgent.Genome.Connections.Keys) { weights.Add(key, customAgent.Genome.Connections[key].Weight); } //Mutate weights populationManager.MutateAgent(customAgent, 0f, 0f, 1f, nodeInnovationCounter, connectionInnovationCounter, mutationLog); //Nodes should not have changed Assert.AreEqual(6, customAgent.Genome.Nodes.Count); Assert.AreEqual(9, customAgent.Genome.Connections.Count); Assert.AreEqual(14, connectionInnovationCounter.GetNewNumber()); Assert.AreEqual(11, nodeInnovationCounter.GetNewNumber()); foreach (int key in weights.Keys) { Assert.AreNotEqual(weights[key], customAgent.Genome.Connections[key].Weight); } }
public void MutateAgent_Node_Test() { MutationLog mutationLog = new MutationLog(); AgentObject customAgent = new CustomAgent(populationManager, parent2Genome, 10); Assert.AreEqual(6, customAgent.Genome.Nodes.Count); Assert.AreEqual(9, customAgent.Genome.Connections.Count); Dictionary <int, double> weights = new Dictionary <int, double>(); foreach (int key in customAgent.Genome.Connections.Keys) { weights.Add(key, customAgent.Genome.Connections[key].Weight); } //Can fail sometimes, when a disabled connection is selected populationManager.MutateAgent(customAgent, 0f, 1f, 0f, nodeInnovationCounter, connectionInnovationCounter, mutationLog); //1 Node shoudl be added and 2 connections Assert.AreEqual(7, customAgent.Genome.Nodes.Count); Assert.AreEqual(12, nodeInnovationCounter.GetNewNumber()); Assert.AreEqual(11, customAgent.Genome.Connections.Count); Assert.AreEqual(16, connectionInnovationCounter.GetNewNumber()); //WEights should not have changed foreach (int key in weights.Keys) { Assert.AreEqual(weights[key], customAgent.Genome.Connections[key].Weight); } }
public void CreateInitialPopulation(Genome startingGenome, GeneCounter nodeInnovationCounter, GeneCounter connectionInnovationCounter, int populationSize, bool randomizeWeights) { _generation = 0; _nodeInnovationCounter = nodeInnovationCounter; _connectionInnovationCounter = connectionInnovationCounter; _populationSize = populationSize; _mutationLog = new MutationLog(); _agents = new List <AgentObject>(); _species = new List <Species>(); for (int i = 0; i < _populationSize; i++) { Genome randomGenome = new Genome(startingGenome); if (randomizeWeights) { foreach (ConnectionGene con in randomGenome.Connections.Values) { con.Weight = Random.Range(-1f, 1f); } } AgentObject agent = _callback.InitNewAgent(this, randomGenome); _agents.Add(agent); } PlaceAgentInSpecies(_agents, _species); //Notify the callback if not existing if (_callback != null) { _callback.AgentsInitializedCallback(_agents, _species, _generation); } }
public void SetUp() { mutationLog = new MutationLog(); node1 = new NodeGene(1, NodeGeneType.HIDDEN, 0.5f); node2 = new NodeGene(2, NodeGeneType.OUTPUT, 1f); connection1 = new ConnectionGene(1, 2, 0.5f, true, 1); connection2 = new ConnectionGene(2, 1, 1f, false, 2); mutationLog.AddConnectionMutation(connection1); mutationLog.AddNodeMutation(connection1, node1); }
public void AddConnectionMutation(AgentObject agent, int amountTries, MutationLog mutationLog, GeneCounter connectionInnovationCounter) { List <int> nodeKeys = agent.Genome.Nodes.Keys.ToList(); for (int i = 0; i < amountTries; i++) { //Selet two random nodes NodeGene inNode = agent.Genome.Nodes[nodeKeys[Random.Range(0, nodeKeys.Count)]]; NodeGene outNode = agent.Genome.Nodes[nodeKeys[Random.Range(0, nodeKeys.Count)]]; //If mutation is possible, mutate the agent if (agent.Genome.IsConnectionPossible(inNode, outNode)) { int innovationNumber = mutationLog.GetConnectionInnovationNumber(inNode.ID, outNode.ID, connectionInnovationCounter); agent.Genome.AddConnectionMutation(inNode, outNode, innovationNumber); break; } } }
public void MutateAgent_Connection_Test() { MutationLog mutationLog = new MutationLog(); AgentObject customAgent = new CustomAgent(populationManager, parent2Genome, 10); Assert.AreEqual(6, customAgent.Genome.Nodes.Count); Assert.AreEqual(9, customAgent.Genome.Connections.Count); Dictionary <int, double> weights = new Dictionary <int, double>(); foreach (int key in customAgent.Genome.Connections.Keys) { weights.Add(key, customAgent.Genome.Connections[key].Weight); } //Mutate connections, test multiple times, because there can be invalid connecionts for (int i = 0; i < 100; i++) { populationManager.MutateAgent(customAgent, 1f, 0f, 0f, nodeInnovationCounter, connectionInnovationCounter, mutationLog); //If a connection occurs, leave the loop if (customAgent.Genome.Connections.Count >= 10) { break; } } //Nodes should not have changed Assert.AreEqual(6, customAgent.Genome.Nodes.Count); Assert.AreEqual(11, nodeInnovationCounter.GetNewNumber()); Assert.AreEqual(10, customAgent.Genome.Connections.Count); Assert.AreEqual(15, connectionInnovationCounter.GetNewNumber()); //WEights should not have changed foreach (int key in weights.Keys) { Assert.AreEqual(weights[key], customAgent.Genome.Connections[key].Weight); } }
public void AddNodeMutation(AgentObject agent, int amountTries, MutationLog mutationLog, GeneCounter connectionInnovationCounter, GeneCounter nodeCounter) { List <int> connectionKeys = agent.Genome.Connections.Keys.OrderBy(x => x).ToList(); if (connectionKeys.Count <= 0) { return; } for (int i = 0; i < amountTries; i++) { ConnectionGene connection = null; //Check the size of the genome, if the genome is small, take an older gene if (agent.Genome.Nodes.Keys.Count <= _SIZE_THRESHOLD) { connection = agent.Genome.Connections[connectionKeys[Random.Range(0, Mathf.RoundToInt(connectionKeys.Count - (Mathf.Sqrt(connectionKeys.Count))))]]; } else { //Select random connection connection = agent.Genome.Connections[connectionKeys[Random.Range(0, connectionKeys.Count)]]; } //If mutation is possible, mutate the agent if (agent.Genome.IsNodePossible(connection)) { //int nodeID = mutationLog.GetNodeID(connection.InnovationNumber, nodeCounter); int nodeID = mutationLog.GetNodeID(connection.InnovationNumber, agent.Genome.Nodes.Keys.ToList(), nodeCounter); int innovationNumberInToNewNode = mutationLog.GetConnectionInnovationNumber(connection.InNode, nodeID, connectionInnovationCounter); int innovationNumberNewNodeToOut = mutationLog.GetConnectionInnovationNumber(nodeID, connection.OutNode, connectionInnovationCounter); agent.Genome.AddNodeMutation(connection, nodeID, innovationNumberInToNewNode, innovationNumberNewNodeToOut); break; } } }
/// <summary> /// Mutate the given agent with different probabilities /// </summary> /// <param name="agent">The agent that should be mutated</param> /// <param name="addConnectionMutationChance">chance to add a connection. Should be between 0f and 1f</param> /// <param name="addNodeMutationChance">chance to add a node. Should be between 0f and 1f</param> /// <param name="mutationWeightChance">chance to mutate the weights. Should be between 0f and 1f</param> /// <param name="nodeInnovationCounter">a node innovation counter</param> /// <param name="connectionInnovationCounter">a connection innovation counter</param> public void MutateAgent(AgentObject agent, float addConnectionMutationChance, float addNodeMutationChance, float mutationWeightChance, GeneCounter nodeInnovationCounter, GeneCounter connectionInnovationCounter, MutationLog mutationLog) { //Mutate weights if (Random.Range(0f, 1f) <= mutationWeightChance) { agent.Genome.MutateConnectionWeight(); } //Mutate Node if (Random.Range(0f, 1f) <= addNodeMutationChance) { AddNodeMutation(agent, _AMOUNT_MUTATION_TRIES, mutationLog, connectionInnovationCounter, nodeInnovationCounter); } //Mutate Connection if (Random.Range(0f, 1f) <= addConnectionMutationChance) { AddConnectionMutation(agent, _AMOUNT_MUTATION_TRIES, mutationLog, connectionInnovationCounter); } }