public void GetConnectionInnovationNumber_Test()
    {
        GeneCounter connectionCounter = new GeneCounter(10);

        //Check the amount before
        Assert.AreEqual(1, mutationLog.ConnectionMutations.Count);

        //Insert an existing connection
        int existingConnection = mutationLog.GetConnectionInnovationNumber(1, 2, connectionCounter);

        //Check the amount after getting the existing connection
        Assert.AreEqual(1, mutationLog.ConnectionMutations.Count);
        Assert.AreEqual(1, existingConnection);

        //Insert new connection
        int newConnection = mutationLog.GetConnectionInnovationNumber(2, 1, connectionCounter);

        //Check the amount after the inserting the new connection
        Assert.AreEqual(2, mutationLog.ConnectionMutations.Count);
        Assert.AreEqual(10, newConnection);

        //Insert new connection again
        newConnection = mutationLog.GetConnectionInnovationNumber(2, 1, connectionCounter);

        //Check the amount after the inserting the new connection
        Assert.AreEqual(2, mutationLog.ConnectionMutations.Count);
        Assert.AreEqual(10, newConnection);
    }
Example #2
0
    /// <summary>
    /// Create the start genome
    /// </summary>
    private void SetStartGenome()
    {
        _nodeCounter       = new GeneCounter(0);
        _connectionCounter = new GeneCounter(0);

        _startGenome = new Genome();

        //5 input nodes + 1 bias node
        _startGenome.AddNodeGene(new NodeGene(_nodeCounter.GetNewNumber(), NodeGeneType.INPUT, 0f, ActivationFunctionHelper.Function.STEEPENED_SIGMOID));
        _startGenome.AddNodeGene(new NodeGene(_nodeCounter.GetNewNumber(), NodeGeneType.INPUT, 0f, ActivationFunctionHelper.Function.STEEPENED_SIGMOID));
        _startGenome.AddNodeGene(new NodeGene(_nodeCounter.GetNewNumber(), NodeGeneType.INPUT, 0f, ActivationFunctionHelper.Function.STEEPENED_SIGMOID));
        _startGenome.AddNodeGene(new NodeGene(_nodeCounter.GetNewNumber(), NodeGeneType.INPUT, 0f, ActivationFunctionHelper.Function.STEEPENED_SIGMOID));
        _startGenome.AddNodeGene(new NodeGene(_nodeCounter.GetNewNumber(), NodeGeneType.INPUT, 0f, ActivationFunctionHelper.Function.STEEPENED_SIGMOID));
        _startGenome.AddNodeGene(new NodeGene(_nodeCounter.GetNewNumber(), NodeGeneType.INPUT, 0f, ActivationFunctionHelper.Function.STEEPENED_SIGMOID));

        //OutputNodes
        _startGenome.AddNodeGene(new NodeGene(_nodeCounter.GetNewNumber(), NodeGeneType.OUTPUT, 1f, ActivationFunctionHelper.Function.STEEPENED_SIGMOID));
        _startGenome.AddNodeGene(new NodeGene(_nodeCounter.GetNewNumber(), NodeGeneType.OUTPUT, 1f, ActivationFunctionHelper.Function.STEEPENED_SIGMOID));

        //Add connections to first output nde
        _startGenome.AddConnectionGene(new ConnectionGene(0, 6, Random.Range(-1f, 1f), true, _connectionCounter.GetNewNumber()));
        _startGenome.AddConnectionGene(new ConnectionGene(1, 6, Random.Range(-1f, 1f), true, _connectionCounter.GetNewNumber()));
        _startGenome.AddConnectionGene(new ConnectionGene(2, 6, Random.Range(-1f, 1f), true, _connectionCounter.GetNewNumber()));
        _startGenome.AddConnectionGene(new ConnectionGene(3, 6, Random.Range(-1f, 1f), true, _connectionCounter.GetNewNumber()));
        _startGenome.AddConnectionGene(new ConnectionGene(4, 6, Random.Range(-1f, 1f), true, _connectionCounter.GetNewNumber()));
        _startGenome.AddConnectionGene(new ConnectionGene(5, 6, Random.Range(-1f, 1f), true, _connectionCounter.GetNewNumber()));

        //Connection to second ouztputNode
        _startGenome.AddConnectionGene(new ConnectionGene(0, 7, Random.Range(-1f, 1f), true, _connectionCounter.GetNewNumber()));
        _startGenome.AddConnectionGene(new ConnectionGene(1, 7, Random.Range(-1f, 1f), true, _connectionCounter.GetNewNumber()));
        _startGenome.AddConnectionGene(new ConnectionGene(2, 7, Random.Range(-1f, 1f), true, _connectionCounter.GetNewNumber()));
        _startGenome.AddConnectionGene(new ConnectionGene(3, 7, Random.Range(-1f, 1f), true, _connectionCounter.GetNewNumber()));
        _startGenome.AddConnectionGene(new ConnectionGene(4, 7, Random.Range(-1f, 1f), true, _connectionCounter.GetNewNumber()));
        _startGenome.AddConnectionGene(new ConnectionGene(5, 7, Random.Range(-1f, 1f), true, _connectionCounter.GetNewNumber()));
    }
Example #3
0
    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);
        }
    }
Example #4
0
    /// <summary>
    /// Create the start genome
    /// </summary>
    private void SetStartGenome()
    {
        _nodeCounter       = new GeneCounter(0);
        _connectionCounter = new GeneCounter(0);

        _startGenome = new Genome();

        int amountPlayerInputs = PlayerController.GetAmountOfInputs(_levelViewWidht, _levelViewHeight);

        List <NodeGene> tmpInputNodes = new List <NodeGene>();

        //Crate input nodes
        for (int i = 0; i < amountPlayerInputs; i++)
        {
            NodeGene node = new NodeGene(_nodeCounter.GetNewNumber(), NodeGeneType.INPUT, 0f, ActivationFunctionHelper.Function.SIGMOID);
            _startGenome.AddNodeGene(node);
            tmpInputNodes.Add(node);
        }

        //Create output nodes
        NodeGene outputNode1 = new NodeGene(_nodeCounter.GetNewNumber(), NodeGeneType.OUTPUT, 1f, ActivationFunctionHelper.Function.SIGMOID);
        NodeGene outputNode2 = new NodeGene(_nodeCounter.GetNewNumber(), NodeGeneType.OUTPUT, 1f, ActivationFunctionHelper.Function.SIGMOID);

        _startGenome.AddNodeGene(outputNode1);
        _startGenome.AddNodeGene(outputNode2);

        //Create connections
        for (int i = 0; i < amountPlayerInputs; i++)
        {
            _startGenome.AddConnectionGene(new ConnectionGene(tmpInputNodes[i].ID, outputNode1.ID, Random.Range(-1f, 1f), true, _connectionCounter.GetNewNumber()));
            _startGenome.AddConnectionGene(new ConnectionGene(tmpInputNodes[i].ID, outputNode2.ID, Random.Range(-1f, 1f), true, _connectionCounter.GetNewNumber()));
        }
    }
Example #5
0
    // Use this for initialization
    void Start()
    {
        Genome parent3GenomeSimple = new Genome();

        //Create the input nodes
        parent3GenomeSimple.AddNodeGene(new NodeGene(1, NodeGeneType.INPUT, 0f));
        parent3GenomeSimple.AddNodeGene(new NodeGene(2, NodeGeneType.INPUT, 0f));
        parent3GenomeSimple.AddNodeGene(new NodeGene(3, NodeGeneType.INPUT, 0f));

        //Create the output node
        parent3GenomeSimple.AddNodeGene(new NodeGene(4, NodeGeneType.OUTPUT, 1f));

        //Create connections
        parent3GenomeSimple.AddConnectionGene(new ConnectionGene(1, 4, 1.0, true, 1));
        parent3GenomeSimple.AddConnectionGene(new ConnectionGene(2, 4, 1.0, true, 2));
        parent3GenomeSimple.AddConnectionGene(new ConnectionGene(3, 4, 1.0, true, 3));


        //Init the connection gene counter with 11
        connectionCounter = new GeneCounter(4);
        nodeCounter       = new GeneCounter(5);

        manager.Callback = this;

        manager.CreateInitialPopulation(parent3GenomeSimple, nodeCounter, connectionCounter, 100);
    }
Example #6
0
    /// <summary>
    /// Get an InnovationNumber for the connection between the given nodes.
    /// If there is already and entry for the connection, the existing InnovationNumber will be returned
    /// If it is a new connection, a new number will be generated with the connectionMutationCounter and after that directly stored
    /// </summary>
    /// <param name="inNodeID">the in node of the new connection</param>
    /// <param name="outNodeID">the out node of the new connection</param>
    /// <param name="connectionMutationCounter">GeneCounter to generate a new number if necessary</param>
    /// <returns>the InnovationNumber for the connection</returns>
    public int GetConnectionInnovationNumber(int inNodeID, int outNodeID, GeneCounter connectionMutationCounter)
    {
        int innovationNumber = IsConnectionExisting(inNodeID, outNodeID);

        //If node is existing return the value
        if (innovationNumber != -1)
        {
            return(innovationNumber);
        }

        innovationNumber = connectionMutationCounter.GetNewNumber();

        //Store new mutation
        AddConnectionMutation(inNodeID, outNodeID, innovationNumber);
        return(innovationNumber);
    }
Example #7
0
    /*
     *
     * /// <summary>
     * /// Get an ID for the a new node that will be splaced between the given connection.
     * /// If there is already an entry for the node, the existing id will be returned.
     * /// If it is a new node a new numer will be generated with the GeneCounter and after that directly stored.
     * /// </summary>
     * /// <param name="connectionInnovationNumber">innovationNumber of the conenction that will be splitted</param>
     * /// <param name="nodeMutationCounter">to generate a new node ID if necessary</param>
     * /// <returns>an ID for the node</returns>
     * public int GetNodeID(int connectionInnovationNumber, GeneCounter nodeMutationCounter)
     * {
     *  int nodeID = IsNodeExisting(connectionInnovationNumber);
     *
     *  //If node is existing return the value
     *  if (nodeID != -1) return nodeID;
     *
     *  nodeID = nodeMutationCounter.GetNewNumber();
     *
     *  //Add node to the list
     *  AddNodeMutation(connectionInnovationNumber, nodeID);
     *
     *  return nodeID;
     *
     * }
     *
     */

    /// <summary>
    /// Get an id for a new node.
    /// If the mutation has already occured, an existing id will be returned.
    /// If the mutation is new, a new id will be generated and stored in the log
    /// </summary>
    /// <param name="connectionInnovationNumber">the innovation number of the splitted connection</param>
    /// <param name="nodeIDs">a list with all node ids' of the genome</param>
    /// <param name="nodeMutationCounter">a node mutation counter to generate a new id if necessary</param>
    /// <returns>an id for the node</returns>
    public int GetNodeID(int connectionInnovationNumber, List <int> nodeIDs, GeneCounter nodeMutationCounter)
    {
        List <int> existingNodeIDs = IsNodeExisting(connectionInnovationNumber);

        foreach (int existingID in existingNodeIDs)
        {
            //If the node Id list does not contain one of the existing nodes, break the loop
            if (!nodeIDs.Contains(existingID))
            {
                return(existingID);
            }
        }

        //If the id is new, add an entry in the log
        int newID = nodeMutationCounter.GetNewNumber();

        AddNodeMutation(connectionInnovationNumber, newID);
        return(newID);
    }
    public void GetNodeID_Test()
    {
        GeneCounter nodeCounter   = new GeneCounter(10);
        List <int>  nodesInGenome = new List <int>();

        //Get an existing node
        int result = mutationLog.GetNodeID(connection1.InnovationNumber, nodesInGenome, nodeCounter);

        Assert.AreEqual(node1.ID, result);

        //Get a new node number
        nodesInGenome.Add(result);
        int result2 = mutationLog.GetNodeID(connection1.InnovationNumber, nodesInGenome, nodeCounter);

        Assert.AreEqual(10, result2);
        Assert.AreEqual(2, mutationLog.NodeMutations[connection1.InnovationNumber].Count);

        //Get the second node again
        int result3 = mutationLog.GetNodeID(connection1.InnovationNumber, nodesInGenome, nodeCounter);

        Assert.AreEqual(10, result3);
        Assert.AreEqual(2, mutationLog.NodeMutations[connection1.InnovationNumber].Count);
    }
Example #9
0
    /// <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);
        }
    }
Example #10
0
    public void SetUp()
    {
        populationManager = new PopulationManager
        {
            Callback = this
        };

        //-----------------------------------------------------------------------------------
        // Parent 1
        //-----------------------------------------------------------------------------------

        parent1Genome = new Genome();

        //Create the input nodes
        parent1Genome.AddNodeGene(new NodeGene(1, NodeGeneType.INPUT, 0f));
        parent1Genome.AddNodeGene(new NodeGene(2, NodeGeneType.INPUT, 0f));
        parent1Genome.AddNodeGene(new NodeGene(3, NodeGeneType.INPUT, 0f));

        //Create the output node
        parent1Genome.AddNodeGene(new NodeGene(4, NodeGeneType.OUTPUT, 1f));

        //Create hidden node
        parent1Genome.AddNodeGene(new NodeGene(5, NodeGeneType.HIDDEN, 0.5f));

        //Create connections
        parent1Genome.AddConnectionGene(new ConnectionGene(1, 4, 1.0, true, 1));
        parent1Genome.AddConnectionGene(new ConnectionGene(2, 4, 1.0, false, 2));
        parent1Genome.AddConnectionGene(new ConnectionGene(3, 4, 1.0, true, 3));
        parent1Genome.AddConnectionGene(new ConnectionGene(2, 5, 1.0, true, 4));
        parent1Genome.AddConnectionGene(new ConnectionGene(5, 4, 1.0, true, 5));
        parent1Genome.AddConnectionGene(new ConnectionGene(1, 5, 1.0, true, 8));

        //-----------------------------------------------------------------------------------
        // Parent 2
        //-----------------------------------------------------------------------------------

        parent2Genome = new Genome();

        //Create the input nodes
        parent2Genome.AddNodeGene(new NodeGene(1, NodeGeneType.INPUT, 0f));
        parent2Genome.AddNodeGene(new NodeGene(2, NodeGeneType.INPUT, 0f));
        parent2Genome.AddNodeGene(new NodeGene(3, NodeGeneType.INPUT, 0f));

        //Create the output node
        parent2Genome.AddNodeGene(new NodeGene(4, NodeGeneType.OUTPUT, 1f));

        //Create hidden node
        parent2Genome.AddNodeGene(new NodeGene(5, NodeGeneType.HIDDEN, 0.4f));
        parent2Genome.AddNodeGene(new NodeGene(6, NodeGeneType.HIDDEN, 0.5f));

        //Create connections
        parent2Genome.AddConnectionGene(new ConnectionGene(1, 4, 1.0, true, 1));
        parent2Genome.AddConnectionGene(new ConnectionGene(2, 4, 1.0, false, 2));
        parent2Genome.AddConnectionGene(new ConnectionGene(3, 4, 1.0, true, 3));
        parent2Genome.AddConnectionGene(new ConnectionGene(2, 5, 1.0, true, 4));
        parent2Genome.AddConnectionGene(new ConnectionGene(5, 4, 1.0, false, 5));
        parent2Genome.AddConnectionGene(new ConnectionGene(5, 6, 1.0, true, 6));
        parent2Genome.AddConnectionGene(new ConnectionGene(6, 4, 1.0, true, 7));
        parent2Genome.AddConnectionGene(new ConnectionGene(3, 5, 1.0, true, 9));
        parent2Genome.AddConnectionGene(new ConnectionGene(1, 6, 1.0, true, 10));

        //-----------------------------------------------------------------------------------
        // Parent 3
        //-----------------------------------------------------------------------------------

        parent3GenomeSimple = new Genome();
        //Create the input nodes
        parent3GenomeSimple.AddNodeGene(new NodeGene(7, NodeGeneType.INPUT, 0f));
        parent3GenomeSimple.AddNodeGene(new NodeGene(8, NodeGeneType.INPUT, 0f));
        parent3GenomeSimple.AddNodeGene(new NodeGene(9, NodeGeneType.INPUT, 0f));

        //Create the output node
        parent3GenomeSimple.AddNodeGene(new NodeGene(10, NodeGeneType.OUTPUT, 1f));

        //Create connections
        parent3GenomeSimple.AddConnectionGene(new ConnectionGene(7, 10, 1.0, true, 11));
        parent3GenomeSimple.AddConnectionGene(new ConnectionGene(8, 10, 1.0, true, 12));
        parent3GenomeSimple.AddConnectionGene(new ConnectionGene(9, 10, 1.0, true, 13));


        //Init the connection gene counter with 11
        connectionInnovationCounter = new GeneCounter(14);
        nodeInnovationCounter       = new GeneCounter(11);

        //Set result values from callback to null
        resultAgentsInitalizedAgentList    = null;
        resultAgentsInitializedSpeciesList = null;
        resultAgentKilled     = null;
        resultAllAgentsKilled = false;

        //Set fine tuning parameters
        PopulationManager._FACTOR_EXCESS_GENES       = 1;
        PopulationManager._FACTOR_DISJOINT_GENES     = 1;
        PopulationManager._FACTOR_AVG_WEIGHT_DIF     = 0.4f;
        PopulationManager._THRESHOLD_NUMBER_OF_GENES = 20;
        PopulationManager._COMPABILITY_THRESHOLD     = 3;
    }
Example #11
0
    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;
            }
        }
    }
Example #12
0
    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;
            }
        }
    }