Ejemplo n.º 1
0
        public static NeuralGraph generateFullyConnected(int nbInputs, int nbOutputs)
        {
            NeuralGraph graph = new NeuralGraph(nbInputs, nbOutputs);

            // Use specific innovation numbers such that all graphs created through this method are identical
            int innovation = 0;

            foreach (Neuron input in graph.getInputNeurons())
            {
                foreach (Neuron output in graph.getOutputNeurons())
                {
                    graph.addConnection(new Connection(input, output, -1, innovation++, true));
                }
            }

            return(graph);
        }
Ejemplo n.º 2
0
        private static void addClonedConnection(Connection connection, NeuralGraph child, Dictionary <Neuron, Neuron> addedNeurons, bool disabled)
        {
            Neuron[] oldNeurons = new Neuron[] { connection.getSource(), connection.getDest() };
            Neuron[] newNeurons = new Neuron[oldNeurons.Length];

            for (int i = 0; i < oldNeurons.Length; i++)
            {
                if (oldNeurons[i].getType() != NeuronType.Hidden)
                {
                    // TODO !Important! If we allow recurrent connections on outputs, need to clone the outputs too
                    newNeurons[i] = oldNeurons[i];
                    continue;
                }
                if (!addedNeurons.ContainsKey(oldNeurons[i]))
                {
                    newNeurons[i] = oldNeurons[i].clone();
                    addedNeurons.Add(oldNeurons[i], newNeurons[i]);
                    child.addHiddenNeuron(newNeurons[i]);
                }
                else
                {
                    newNeurons[i] = addedNeurons[oldNeurons[i]];
                }
            }

            Dictionary <Neuron, Dictionary <Neuron, Connection> > childConnections = child.getConnections();

            if (childConnections.ContainsKey(newNeurons[1]) && childConnections[newNeurons[1]].ContainsKey(newNeurons[0]))
            {
                // If the link already exists, enable it
                if (!disabled)
                {
                    childConnections[newNeurons[1]][newNeurons[0]].enable();
                }
            }
            else
            {
                Connection newConnection = new Connection(newNeurons[0], newNeurons[1], connection.getParentInnovation(), connection.getInnovation(), true);
                newConnection.setDisabled(disabled);
                child.addConnection(newConnection);
            }
        }
Ejemplo n.º 3
0
        public Individual mutate(NEATConfig config)
        {
            Individual  newIndiv = clone();
            NeuralGraph newGraph = newIndiv.getGraph();

            if (Utils.rand.NextDouble() < config.newConnectionProb)
            {
                // Select two random neurons and create (or enable) a link in-between
                int hiddenCount = newGraph.getHiddenNeurons().Count();
                int inputCount  = newGraph.getInputNeurons().Count();
                int outputCount = newGraph.getOutputNeurons().Count();

                // Select the input and output neurons
                int    sourceIndex = Utils.rand.Next(hiddenCount + inputCount + outputCount);
                int    destIndex = Utils.rand.Next(hiddenCount + outputCount);
                Neuron source, dest;

                if (sourceIndex < hiddenCount)
                {
                    source = newGraph.getHiddenNeurons()[sourceIndex];
                }
                else if (sourceIndex < hiddenCount + inputCount)
                {
                    source = newGraph.getInputNeurons()[sourceIndex - hiddenCount];
                }
                else
                {
                    source = newGraph.getOutputNeurons()[sourceIndex - hiddenCount - inputCount];
                }

                if (destIndex < hiddenCount)
                {
                    dest = newGraph.getHiddenNeurons()[destIndex];
                }
                else
                {
                    dest = newGraph.getOutputNeurons()[destIndex - hiddenCount];
                }

                Connection connection;
                if (!newGraph.getConnections()[dest].TryGetValue(source, out connection))
                {
                    connection = new Connection(source, dest, -1); // TODO what the crap is the parent innovation supposed to be here
                    newGraph.addConnection(connection);
                }
                else
                {
                    connection.enable();
                }
            }

            if (Utils.rand.NextDouble() < config.newNodeProb)
            {
                // When adding a node, disable a connection and replace it by a neuron and two connections
                // The new input connection to that neuron has weight of 1, while output has same weight as disabled connection
                Connection connection = newGraph.getConnectionList()[Utils.rand.Next(newGraph.getConnectionList().Count)];
                connection.disable();
                Neuron     neuron   = new Neuron(NeuronType.Hidden);
                Connection newConn1 = new Connection(connection.getSource(), neuron, connection.getInnovation());
                Connection newConn2 = new Connection(neuron, connection.getDest(), connection.getInnovation());
                newGraph.addHiddenNeuron(neuron);
                newGraph.addConnection(newConn1);
                newGraph.addConnection(newConn2);
            }

            // Mutate each connection weight
            foreach (Connection connection in newGraph.getConnectionList())
            {
                if (Utils.rand.NextDouble() < config.mutationProb)
                {
                    if (Utils.rand.NextDouble() < config.uniformPerturbationMutationProb)
                    {
                        connection.setWeight(connection.getWeight() + Utils.rand.NextDouble() * 2 * config.perturbationStep - config.perturbationStep);
                    }
                    else
                    {
                        connection.setWeight(Utils.nextGaussian(0, 1));
                    }
                }
            }

            return(newIndiv);
        }