public virtual void EvaluatePopulation(Population pop, EvolutionAlgorithm ea)
        {
            // Evaluate in single-file each genome within the population.
            // Only evaluate new genomes (those with EvaluationCount==0).
            int count = pop.GenomeList.Count;
            for(int i=0; i<count; i++)
            {
                IGenome g = pop.GenomeList[i];
                if(g.EvaluationCount!=0)
                    continue;

                INetwork network = g.Decode(activationFn);
                if(network==null)
                {	// Future genomes may not decode - handle the possibility.
                    g.Fitness = EvolutionAlgorithm.MIN_GENOME_FITNESS;
                }
                else
                {
                    g.Fitness = Math.Max(networkEvaluator.EvaluateNetwork(network), EvolutionAlgorithm.MIN_GENOME_FITNESS);
                }

                // Reset these genome level statistics.
                g.TotalFitness = g.Fitness;
                g.EvaluationCount = 1;

                // Update master evaluation counter.
                evaluationCount++;
            }
        }
Exemplo n.º 2
0
 public void initializeEvolution(int populationSize, NeatGenome seedGenome)
 {
     if (seedGenome == null)
     {
         initializeEvolution(populationSize);
         return;
     }
     logOutput = new StreamWriter(outputFolder + "logfile.txt");
     IdGenerator idgen = new IdGeneratorFactory().CreateIdGenerator(seedGenome);
     ea = new EvolutionAlgorithm(new Population(idgen, GenomeFactory.CreateGenomeList(seedGenome, populationSize, experiment.DefaultNeatParameters, idgen)), experiment.PopulationEvaluator, experiment.DefaultNeatParameters);
 }
Exemplo n.º 3
0
        public NoveltyThread(JSPopulationEvaluator jsPop, AssessGenotypeFunction assess, int popSize)
        {
            //save our objects for executing later!
            popEval = jsPop;
            populationSize = popSize;

            autoEvent = new AutoResetEvent(false);

            waitNextTime = true;

            novelThread = new Thread(delegate()
                {
                    autoEvent.WaitOne();

                    //we'll start by testing with 0 parents, and popsize of 15 yay!
                    noveltyRun = EvolutionManager.SharedEvolutionManager.initializeEvolutionAlgorithm(popEval, populationSize, assess);

                    //let our algoirhtm know we want to do novelty gosh darnit
                    if(noveltyRun.multiobjective != null)
                         noveltyRun.multiobjective.doNovelty = true;

                    //we make sure we don't wait in this loop, since we just got started!
                    waitNextTime = false;

                    while (true)
                    {
                        //this will cause us to pause!
                        if (waitNextTime)
                        {
                            waitNextTime = false;
                            autoEvent.WaitOne();
                        }
                        // Start the stopwatch we'll use to measure eval performance
                        Stopwatch sw = Stopwatch.StartNew();

                        //run the generation
                        noveltyRun.PerformOneGeneration();

                        // Stop the stopwatch
                        sw.Stop();

                        // Report the results
                        Console.WriteLine("Time used per gen (float): {0} ms", sw.Elapsed.TotalMilliseconds);
                        Console.WriteLine("Time used per gen (rounded): {0} ms", sw.ElapsedMilliseconds);

                    }
                });

            novelThread.Start();
        }
Exemplo n.º 4
0
        //private static Random random;
        public static void Main(string[] args)
        {
            Util.Initialize(args[0]);
            var idgen = new IdGenerator();
            IExperiment experiment = new LimitExperiment();

            XmlSerializer ser = new XmlSerializer(typeof(Settings));
            //Settings settings = new Settings()
            //{
            //    SmallBlind = 1,
            //    BigBlind = 2,
            //    GamesPerIndividual = 100,
            //    LogFile = "mutlithreaded_log.txt",
            //    MaxHandsPerTourney = 200,
            //    PlayersPerGame = 6,
            //    StackSize = 124,
            //    Threads = 4
            //};
            //ser.Serialize(new StreamWriter("settings.xml"), settings);
            Settings settings = (Settings)ser.Deserialize(new StreamReader("settings.xml"));
            var eval = new PokerPopulationEvaluator<SimpleLimitNeuralNetPlayer2, RingGamePlayerEvaluator>(settings);

            var ea = new EvolutionAlgorithm(
                new Population(idgen,
                               GenomeFactory.CreateGenomeList(experiment.DefaultNeatParameters,
                                              idgen, experiment.InputNeuronCount,
                                              experiment.OutputNeuronCount,
                                              experiment.DefaultNeatParameters.pInitialPopulationInterconnections,
                                              experiment.DefaultNeatParameters.populationSize)),
                                              eval,
                experiment.DefaultNeatParameters);

            Console.WriteLine("Starting real evolution");
            for (int i = 0; true; i++)
            {
                Console.WriteLine("Generation {0}", i + 1);
                ea.PerformOneGeneration();
                Console.WriteLine("Champion Fitness={0}", ea.BestGenome.Fitness);
                var doc = new XmlDocument();
                XmlGenomeWriterStatic.Write(doc, (NeatGenome)ea.BestGenome);
                FileInfo oFileInfo = new FileInfo("genomes_simple\\" + "bestGenome" + i.ToString() + ".xml");
                doc.Save(oFileInfo.FullName);
            }
        }
        public void EvaluatePopulation(Population pop, EvolutionAlgorithm ea)
        {
            int count = pop.GenomeList.Count;
            evalPack e;
            IGenome g;
            int i;

            for (i = 0; i < count; i++)
            {
                //Console.WriteLine(i);
                sem.WaitOne();
                g = pop.GenomeList[i];
                e = new evalPack(networkEvaluator, activationFn, g, i % HyperNEATParameters.numThreads,(int)ea.Generation);
                ThreadPool.QueueUserWorkItem(new WaitCallback(evalNet), e);
                // Update master evaluation counter.
                evaluationCount++;

                /*if(printFinalPositions)
                    file.WriteLine(g.Behavior.behaviorList[0].ToString() + ", " + g.Behavior.behaviorList[1].ToString());//*/
            }
            //Console.WriteLine("waiting for last threads..");
           for (int j = 0; j < HyperNEATParameters.numThreads; j++)
            {
           		sem.WaitOne();
              //  Console.WriteLine("waiting");
			}
            for (int j = 0; j < HyperNEATParameters.numThreads; j++)
            {
				//Console.WriteLine("releasing");
       
                sem.Release();
            }
            //Console.WriteLine("generation done...");
            //calulate novelty scores...
            if(ea.NeatParameters.noveltySearch)
            {
                if(ea.NeatParameters.noveltySearch)
                {
                    ea.CalculateNovelty();
                }
            }

        }
		public virtual void EvaluatePopulation(Population pop, EvolutionAlgorithm ea)
		{
			// Evaluate in single-file each genome within the population. 
			// Only evaluate new genomes (those with EvaluationCount==0).
			int count = pop.GenomeList.Count;
			for(int i=0; i<count; i++)
			{
				IGenome g = pop.GenomeList[i];
				if(g.EvaluationCount!=0)
					continue;

				INetwork network = g.Decode(activationFn);
				if(network==null)
				{	// Future genomes may not decode - handle the possibility.
					g.Fitness = EvolutionAlgorithm.MIN_GENOME_FITNESS;
				}
				else
				{
				    BehaviorType behavior;
					g.Fitness = Math.Max(networkEvaluator.EvaluateNetwork(network,out behavior), EvolutionAlgorithm.MIN_GENOME_FITNESS);                    
                    g.RealFitness = g.Fitness;
		            g.Behavior = behavior;
		        }

				// Reset these genome level statistics.
				g.TotalFitness = g.Fitness;
				g.EvaluationCount = 1;

				// Update master evaluation counter.
				evaluationCount++;
			}
			
			if(ea.NeatParameters.noveltySearch)
            {
                if(ea.NeatParameters.noveltySearch && ea.noveltyInitialized)
                {
                    ea.CalculateNovelty();
                }
            }
		}
Exemplo n.º 7
0
		private void Mutate_AddConnection(EvolutionAlgorithm ea)
		{
			// We are always guaranteed to have enough neurons to form connections - because the input/output neurons are
			// fixed. Any domain that doesn't require input/outputs is a bit nonsensical!

			// Make a fixed number of attempts at finding a suitable connection to add. 
			
			if(neuronGeneList.Count>1)
			{	// At least 2 neurons, so we have a chance at creating a connection.

				for(int attempts=0; attempts<5; attempts++)
				{
					// Select candidate source and target neurons. Any neuron can be used as the source. Input neurons 
					// should not be used as a target
					int srcNeuronIdx; 
					int tgtNeuronIdx;
				
					/* Here's some code for adding connections that attempts to avoid any recursive conenctions
					 * within a network by only linking to neurons with innovation id's greater than the source neuron.
					 * Unfortunately this doesn't work because new neurons with large innovations ID's are inserted 
					 * randomly through a network's topology! Hence this code remains here in readyness to be resurrected
					 * as part of some future work to support feedforward nets.
//					if(ea.NeatParameters.feedForwardOnly)
//					{
//						/* We can ensure that all networks are feedforward only by only adding feedforward connections here.
//						 * Feed forward connections fall into one of the following categories.  All references to indexes 
//						 * are indexes within this genome's neuronGeneList:
//						 * 1) Source neuron is an input or hidden node, target is an output node.
//						 * 2) Source is an input or hidden node, target is a hidden node with an index greater than the source node's index.
//						 * 3) Source is an output node, target is an output node with an index greater than the source node's index.
//						 * 
//						 * These rules are easier to understand if you understand how the different types if neuron are arranged within
//						 * the neuronGeneList array. Neurons are arranged in the following order:
//						 * 
//						 * 1) A single bias neuron is always first.
//						 * 2) Experiment specific input neurons.
//						 * 3) Output neurons.
//						 * 4) Hidden neurons.
//						 * 
//						 * The quantity and innovationID of all neurons within the first 3 categories remains fixed throughout the life
//						 * of an experiment, hence we always know where to find the bias, input and output nodes. The number of hidden nodes
//						 * can vary as ne nodes are created, pruned away or perhaps dropped during crossover, however they are always arranged
//						 * newest to oldest, or in other words sorted by innovation idea, lowest ID first. 
//						 * 
//						 * If output neurons were at the end of the list with hidden nodes in the middle then generating feedforward 
//						 * connections would be as easy as selecting a target neuron with a higher index than the source neuron. However, that
//						 * type of arrangement is not conducive to the operation of other routines, hence this routine is a little bit more
//						 * complicated as a result.
//						 */
//					
//						// Ok, for a source neuron we can pick any neuron except the last output neuron.
//						int neuronIdxCount = neuronGeneList.Count;
//						int neuronIdxBound = neuronIdxCount-1;
//
//						// Generate count-1 possibilities and avoid the last output neuron's idx.
//						srcNeuronIdx = (int)Math.Floor(Utilities.NextDouble() * neuronIdxBound);
//						if(srcNeuronIdx>inputBiasOutputNeuronCountMinus2) srcNeuronIdx++;
//						
//
//						// Now generate a target idx depending on what type of neuron srcNeuronIdx is pointing to.
//						if(srcNeuronIdx<inputAndBiasNeuronCount)
//						{	// Source is a bias or input neuron. Target can be any output or hidden neuron.
//							tgtNeuronIdx = inputAndBiasNeuronCount + (int)Math.Floor(Utilities.NextDouble() * (neuronIdxCount-inputAndBiasNeuronCount));
//						}
//						else if(srcNeuronIdx<inputBiasOutputNeuronCount)
//						{	// Source is an output neuron, but not the last output neuron. Target can be any output neuron with an index
//							// greater than srcNeuronIdx.
//							tgtNeuronIdx = (inputAndBiasNeuronCount+1) + (int)Math.Floor(Utilities.NextDouble() * ((inputBiasOutputNeuronCount-1)-srcNeuronIdx));
//						}
//						else 
//						{	// Source is a hidden neuron. Target can be any hidden neuron after srcNeuronIdx or any output neuron.
//							tgtNeuronIdx = (int)Math.Floor(Utilities.NextDouble() * ((neuronIdxBound-srcNeuronIdx)+outputNeuronCount));
//
//							if(tgtNeuronIdx<outputNeuronCount)
//							{	// Map to an output neuron idx.
//								tgtNeuronIdx += inputAndBiasNeuronCount;
//							}
//							else
//							{
//								// Map to one of the hidden neurons after srcNeuronIdx.
//								tgtNeuronIdx = (tgtNeuronIdx-outputNeuronCount)+srcNeuronIdx+1;
//							}
//						}
//					}

//					// Source neuron can by any neuron. Target neuron is any neuron except input neurons.
//					srcNeuronIdx = (int)Math.Floor(Utilities.NextDouble() * neuronGeneList.Count);
//					tgtNeuronIdx = inputAndBiasNeuronCount + (int)Math.Floor(Utilities.NextDouble() * (neuronGeneList.Count-inputAndBiasNeuronCount));
//
//                  NeuronGene sourceNeuron = neuronGeneList[srcNeuronIdx];
//                  NeuronGene targetNeuron = neuronGeneList[tgtNeuronIdx];

                    // Find all potential inputs, or quit if there are not enough. 
                    // Neurons cannot be inputs if they are dummy input nodes of a module.
                    NeuronGeneList potentialInputs = new NeuronGeneList();
                    foreach (NeuronGene n in neuronGeneList) {
                        if (!(n.ActivationFunction is ModuleInputNeuron)) {
                            potentialInputs.Add(n);
                        }
                    }
                    if (potentialInputs.Count < 1)
                        return;

                    // Find all potential outputs, or quit if there are not enough.
                    // Neurons cannot be outputs if they are dummy input or output nodes of a module, or network input or bias nodes.
                    NeuronGeneList potentialOutputs = new NeuronGeneList();
                    foreach (NeuronGene n in neuronGeneList) {
                        if (n.NeuronType != NeuronType.Bias && n.NeuronType != NeuronType.Input
                                && !(n.ActivationFunction is ModuleInputNeuron)
                                && !(n.ActivationFunction is ModuleOutputNeuron)) {
                            potentialOutputs.Add(n);
                        }
                    }
                    if (potentialOutputs.Count < 1)
                        return;

                    NeuronGene sourceNeuron = potentialInputs[Utilities.Next(potentialInputs.Count)];
                    NeuronGene targetNeuron = potentialOutputs[Utilities.Next(potentialOutputs.Count)];

					// Check if a connection already exists between these two neurons.
					uint sourceId = sourceNeuron.InnovationId;
					uint targetId = targetNeuron.InnovationId;

					if(!TestForExistingConnection(sourceId, targetId))
					{
						// Check if a matching mutation has already occured on another genome. 
						// If so then re-use the connection ID.
						ConnectionEndpointsStruct connectionKey = new ConnectionEndpointsStruct(sourceId, targetId);
						ConnectionGene existingConnection = (ConnectionGene)ea.NewConnectionGeneTable[connectionKey];
						ConnectionGene newConnectionGene;
						if(existingConnection==null)
						{	// Create a new connection with a new ID and add it to the Genome.
							newConnectionGene = new ConnectionGene(ea.NextInnovationId, sourceId, targetId,
								(Utilities.NextDouble() * ea.NeatParameters.connectionWeightRange/4.0) - ea.NeatParameters.connectionWeightRange/8.0);

							// Register the new connection with NewConnectionGeneTable.
							ea.NewConnectionGeneTable.Add(connectionKey, newConnectionGene);

							// Add the new gene to this genome. We have a new ID so we can safely append the gene to the end 
							// of the list without risk of breaking the innovation ID order.
							connectionGeneList.Add(newConnectionGene);
						}
						else
						{	// Create a new connection, re-using the ID from existingConnection, and add it to the Genome.
							newConnectionGene = new ConnectionGene(existingConnection.InnovationId, sourceId, targetId,
								(Utilities.NextDouble() * ea.NeatParameters.connectionWeightRange/4.0) - ea.NeatParameters.connectionWeightRange/8.0);

							// Add the new gene to this genome. We are re-using an ID so we must ensure the connection gene is
							// inserted into the correct position (sorted by innovation ID).
							connectionGeneList.InsertIntoPosition(newConnectionGene);
						}
					
						return;
					}
				}
			}

			// We couldn't find a valid connection to create. Instead of doing nothing lets perform connection
			// weight mutation.
			Mutate_ConnectionWeights(ea);
		}
Exemplo n.º 8
0
        private void Mutate_AddModule(EvolutionAlgorithm ea)
        {
            // Find all potential inputs, or quit if there are not enough. 
            // Neurons cannot be inputs if they are dummy input nodes created for another module.
            NeuronGeneList potentialInputs = new NeuronGeneList();
            foreach (NeuronGene n in neuronGeneList) {
                if (!(n.ActivationFunction is ModuleInputNeuron)) {
                    potentialInputs.Add(n);
                }
            }
            if (potentialInputs.Count < 1)
                return;

            // Find all potential outputs, or quit if there are not enough.
            // Neurons cannot be outputs if they are dummy input or output nodes created for another module, or network input or bias nodes.
            NeuronGeneList potentialOutputs = new NeuronGeneList();
            foreach (NeuronGene n in neuronGeneList) {
                if (n.NeuronType != NeuronType.Bias && n.NeuronType != NeuronType.Input
                        && !(n.ActivationFunction is ModuleInputNeuron)
                        && !(n.ActivationFunction is ModuleOutputNeuron)) {
                    potentialOutputs.Add(n);
                }
            }
            if (potentialOutputs.Count < 1)
                return;

            // Pick a new function for the new module.
            IModule func = ModuleFactory.GetRandom();

            // Choose inputs uniformly at random, with replacement.
            // Create dummy neurons to represent the module's inputs.
            // Create connections between the input nodes and the dummy neurons.
            IActivationFunction inputFunction = ActivationFunctionFactory.GetActivationFunction("ModuleInputNeuron");
            List<uint> inputDummies = new List<uint>(func.InputCount);
            for (int i = 0; i < func.InputCount; i++) {
                NeuronGene newNeuronGene = new NeuronGene(ea.NextInnovationId, NeuronType.Hidden, inputFunction);
                neuronGeneList.Add(newNeuronGene);

                uint sourceId = potentialInputs[Utilities.Next(potentialInputs.Count)].InnovationId;
                uint targetId = newNeuronGene.InnovationId;

                inputDummies.Add(targetId);

                // Create a new connection with a new ID and add it to the Genome.
                ConnectionGene newConnectionGene = new ConnectionGene(ea.NextInnovationId, sourceId, targetId,
                    (Utilities.NextDouble() * ea.NeatParameters.connectionWeightRange) - ea.NeatParameters.connectionWeightRange / 2.0);

                // Register the new connection with NewConnectionGeneTable.
                ConnectionEndpointsStruct connectionKey = new ConnectionEndpointsStruct(sourceId, targetId);
                ea.NewConnectionGeneTable.Add(connectionKey, newConnectionGene);

                // Add the new gene to this genome. We have a new ID so we can safely append the gene to the end 
                // of the list without risk of breaking the innovation ID order.
                connectionGeneList.Add(newConnectionGene);
            }

            // Choose outputs uniformly at random, with replacement.
            // Create dummy neurons to represent the module's outputs.
            // Create connections between the output nodes and the dummy neurons.
            IActivationFunction outputFunction = ActivationFunctionFactory.GetActivationFunction("ModuleOutputNeuron");
            List<uint> outputDummies = new List<uint>(func.OutputCount);
            for (int i = 0; i < func.OutputCount; i++) {
                NeuronGene newNeuronGene = new NeuronGene(ea.NextInnovationId, NeuronType.Hidden, outputFunction);
                neuronGeneList.Add(newNeuronGene);

                uint sourceId = newNeuronGene.InnovationId;
                uint targetId = potentialOutputs[Utilities.Next(potentialOutputs.Count)].InnovationId;

                outputDummies.Add(sourceId);

                // Create a new connection with a new ID and add it to the Genome.
                ConnectionGene newConnectionGene = new ConnectionGene(ea.NextInnovationId, sourceId, targetId,
                    (Utilities.NextDouble() * ea.NeatParameters.connectionWeightRange) - ea.NeatParameters.connectionWeightRange / 2.0);

                // Register the new connection with NewConnectionGeneTable.
                ConnectionEndpointsStruct connectionKey = new ConnectionEndpointsStruct(sourceId, targetId);
                ea.NewConnectionGeneTable.Add(connectionKey, newConnectionGene);

                // Add the new gene to this genome. We have a new ID so we can safely append the gene to the end 
                // of the list without risk of breaking the innovation ID order.
                connectionGeneList.Add(newConnectionGene);
            }

            // Pick a new ID for the new module and create it.
            // Modules do not participate in history comparisons, so we will always create a new innovation ID.
            // We can change this here if it becomes a problem.
            ModuleGene newModule = new ModuleGene(ea.NextInnovationId, func, inputDummies, outputDummies);
            moduleGeneList.Add(newModule);
        }
        /// <summary>
        /// Initializes the EA using an initial population that has already been read into object format.
        /// </summary>
        /// <param name="pop"></param>
        public void initalizeEvolution(Population pop)
        {
            LogOutput = Logging ? new StreamWriter(Path.Combine(OutputFolder, "log.txt")) : null;
            FinalPositionOutput = FinalPositionLogging ? new StreamWriter(Path.Combine(OutputFolder, "final-position.txt")) : null;
            ArchiveModificationOutput = FinalPositionLogging ? new StreamWriter(Path.Combine(OutputFolder, "archive-mods.txt")) : null;
            ComplexityOutput = new StreamWriter(Path.Combine(OutputFolder, "complexity.txt"));
            ComplexityOutput.WriteLine("avg,stdev,min,max");

            if (FinalPositionLogging)
            {
                FinalPositionOutput.WriteLine("ID,x,y");
                ArchiveModificationOutput.WriteLine("ID,action,time,x,y");
            }

            EA = new EvolutionAlgorithm(pop, experiment.PopulationEvaluator, experiment.DefaultNeatParameters);
            EA.outputFolder = OutputFolder;
            EA.neatBrain = NEATBrain;
        }
Exemplo n.º 10
0
 public void initializeEvolution(int populationSize, NeatGenome seedGenome)
 {
     if (seedGenome == null)
     {
         initializeEvolution(populationSize);
         return;
     }
     if (logOutput != null)
         logOutput.Close();
     logOutput = new StreamWriter(outputFolder + "logfile.txt");
     IdGenerator idgen = new IdGeneratorFactory().CreateIdGenerator(seedGenome);
     ea = new EvolutionAlgorithm(new Population(idgen, GenomeFactory.CreateGenomeList(seedGenome, populationSize, neatParams, idgen)), populationEval, neatParams);
 }
Exemplo n.º 11
0
 public void initalizeEvolution(Population pop)
 {
     if (logOutput != null)
         logOutput.Close();
     logOutput = new StreamWriter(outputFolder + "logfile.txt");
     //IdGenerator idgen = new IdGeneratorFactory().CreateIdGenerator(pop.GenomeList);
     ea = new EvolutionAlgorithm(pop, populationEval, neatParams);
 }
Exemplo n.º 12
0
		public override IGenome CreateOffspring_Sexual(EvolutionAlgorithm ea, IGenome parent)
		{
            NeatGenome otherParent = parent as NeatGenome;
            if (otherParent == null)
                return null;
            
            // Build a list of connections in either this genome or the other parent.
			CorrelationResults correlationResults = CorrelateConnectionGeneLists(connectionGeneList, otherParent.connectionGeneList);			
			Debug.Assert(correlationResults.PerformIntegrityCheck(), "CorrelationResults failed integrity check.");

			//----- Connection Genes.
			// We will temporarily store the offspring's genes in newConnectionGeneList and keeping track of which genes
			// exist with newConnectionGeneTable. Here we ensure these objects are created, and if they already existed
			// then ensure they are cleared. Clearing existing objects is more efficient that creating new ones because
			// allocated memory can be re-used.

            // Key = connection key, value = index in newConnectionGeneList.
			if(newConnectionGeneTable==null)
			{	// Provide a capacity figure to the new Hashtable. The offspring will be the same length (or thereabouts).
				newConnectionGeneTable = new Hashtable(connectionGeneList.Count);
			}
			else
			{
				newConnectionGeneTable.Clear();
			}
			//TODO: No 'capacity' constructor on CollectionBase. Create modified/custom CollectionBase.
			// newConnectionGeneList must be constructed on each call because it is passed to a new NeatGenome 
			// at construction time and a permanent reference to the list is kept.
            newConnectionGeneList = new ConnectionGeneList(ConnectionGeneList.Count);

			// A switch that stores which parent is fittest 1 or 2. Chooses randomly if both are equal. More efficient to calculate this just once.
			byte fitSwitch;
			if(Fitness > otherParent.Fitness)
				fitSwitch = 1;
			else if(Fitness < otherParent.Fitness)
				fitSwitch = 2;
			else
			{	// Select one of the parents at random to be the 'master' genome during crossover.
				if(Utilities.NextDouble() < 0.5)
					fitSwitch = 1;
				else
					fitSwitch = 2;
			}

			bool combineDisjointExcessFlag = Utilities.NextDouble() < ea.NeatParameters.pDisjointExcessGenesRecombined;

			// Loop through the correlationResults, building a table of ConnectionGenes from the parents that will make it into our 
			// new [single] offspring. We use a table keyed on connection end points to prevent passing connections to the offspring 
			// that may have the same end points but a different innovation number - effectively we filter out duplicate connections.
			int idxBound = correlationResults.CorrelationItemList.Count;
			for(int i=0; i<idxBound; i++)
			{
				CreateOffspring_Sexual_ProcessCorrelationItem((CorrelationItem)correlationResults.CorrelationItemList[i], fitSwitch, combineDisjointExcessFlag, ea.NeatParameters);
			}

			//----- Neuron Genes.
			// Build a neuronGeneList by analysing each connection's neuron end-point IDs.
			// This strategy has the benefit of eliminating neurons that are no longer connected too.
			// Remember to always keep all input, output and bias neurons though!
            NeuronGeneList newNeuronGeneList = new NeuronGeneList(neuronGeneList.Count);

			// Keep a table of the NeuronGene ID's keyed by ID so that we can keep track of which ones have been added.
            // Key = innovation ID, value = null for some reason.
			if(newNeuronGeneTable==null)
				newNeuronGeneTable = new Hashtable(neuronGeneList.Count);
			else
				newNeuronGeneTable.Clear();

			// Get the input/output neurons from this parent. All Genomes share these neurons, they do not change during a run.
			idxBound = neuronGeneList.Count;
			for(int i=0; i<idxBound; i++)
			{
				if(neuronGeneList[i].NeuronType != NeuronType.Hidden)
				{
					newNeuronGeneList.Add(new NeuronGene(neuronGeneList[i]));
					newNeuronGeneTable.Add(neuronGeneList[i].InnovationId, null);
				}
				else
				{	// No more bias, input or output nodes. break the loop.
					break;
				}
			}

			// Now analyse the connections to determine which NeuronGenes are required in the offspring.
            // Loop through every connection in the child, and add to the child those hidden neurons that are sources or targets of the connection.
			idxBound = newConnectionGeneList.Count;
			for(int i=0; i<idxBound; i++)
			{
                NeuronGene neuronGene;
				ConnectionGene connectionGene = newConnectionGeneList[i];
				if(!newNeuronGeneTable.ContainsKey(connectionGene.SourceNeuronId))
				{	
                    //TODO: DAVID proper activation function
					// We can safely assume that any missing NeuronGenes at this point are hidden heurons.
                   neuronGene = this.neuronGeneList.GetNeuronById(connectionGene.SourceNeuronId);
                    if (neuronGene != null)
                        newNeuronGeneList.Add(new NeuronGene(neuronGene));
                    else
                        newNeuronGeneList.Add(new NeuronGene(otherParent.NeuronGeneList.GetNeuronById(connectionGene.SourceNeuronId)));
                    //newNeuronGeneList.Add(new NeuronGene(connectionGene.SourceNeuronId, NeuronType.Hidden, ActivationFunctionFactory.GetActivationFunction("SteepenedSigmoid")));
					newNeuronGeneTable.Add(connectionGene.SourceNeuronId, null);
				}

				if(!newNeuronGeneTable.ContainsKey(connectionGene.TargetNeuronId))
				{	
                    //TODO: DAVID proper activation function
					// We can safely assume that any missing NeuronGenes at this point are hidden heurons.
                    neuronGene = this.neuronGeneList.GetNeuronById(connectionGene.TargetNeuronId);
                    if (neuronGene != null)
                        newNeuronGeneList.Add(new NeuronGene(neuronGene));
                    else
                        newNeuronGeneList.Add(new NeuronGene(otherParent.NeuronGeneList.GetNeuronById(connectionGene.TargetNeuronId)));
                    //newNeuronGeneList.Add(new NeuronGene(connectionGene.TargetNeuronId, NeuronType.Hidden, ActivationFunctionFactory.GetActivationFunction("SteepenedSigmoid")));
					newNeuronGeneTable.Add(connectionGene.TargetNeuronId, null);
				}
			}

            // Determine which modules to pass on to the child in the same way.
            // For each module in this genome or in the other parent, if it was referenced by even one connection add it and all its dummy neurons to the child.
            List<ModuleGene> newModuleGeneList = new List<ModuleGene>();

            // Build a list of modules the child might have, which is a union of the parents' module lists, but they are all copies so we can't just do a union.
            List<ModuleGene> unionParentModules = new List<ModuleGene>(moduleGeneList);
            foreach (ModuleGene moduleGene in otherParent.moduleGeneList) {
                bool alreadySeen = false;
                foreach (ModuleGene match in unionParentModules) {
                    if (moduleGene.InnovationId == match.InnovationId) {
                        alreadySeen = true;
                        break;
                    }
                }
                if (!alreadySeen) {
                    unionParentModules.Add(moduleGene);
                }
            }

            foreach (ModuleGene moduleGene in unionParentModules) {
                // Examine each neuron in the child to determine whether it is part of a module.
                foreach (List<uint> dummyNeuronList in new List<uint>[] { moduleGene.InputIds, moduleGene.OutputIds }) {
                    foreach (uint dummyNeuronId in dummyNeuronList) {
                        if (newNeuronGeneTable.ContainsKey(dummyNeuronId)) {
                            goto childHasModule;
                        }
                    }
                }

                continue; // the child does not contain this module, so continue the loop and check for the next module.
            childHasModule: // the child does contain this module, so make sure the child gets all the nodes the module requires to work.

                // Make sure the child has all the neurons in the given module.
                newModuleGeneList.Add(new ModuleGene(moduleGene));
                foreach (List<uint> dummyNeuronList in new List<uint>[] { moduleGene.InputIds, moduleGene.OutputIds }) {
                    foreach (uint dummyNeuronId in dummyNeuronList) {
                        if (!newNeuronGeneTable.ContainsKey(dummyNeuronId)) {
                            newNeuronGeneTable.Add(dummyNeuronId, null);
                            NeuronGene neuronGene = this.neuronGeneList.GetNeuronById(dummyNeuronId);
                            if (neuronGene != null) {
                                newNeuronGeneList.Add(new NeuronGene(neuronGene));
                            } else {
                                newNeuronGeneList.Add(new NeuronGene(otherParent.NeuronGeneList.GetNeuronById(dummyNeuronId)));
                            }
                        }
                    }
                }
            }

			// TODO: Inefficient code?
			newNeuronGeneList.SortByInnovationId();
            // Schrum: Need to calculate this because of Module Mutation adding extra outputs
            int revisedOutputCount = 0;
            foreach(NeuronGene n in newNeuronGeneList) {
                if (n.NeuronType == NeuronType.Output) 
                    revisedOutputCount++;
            }

			// newConnectionGeneList is already sorted because it was generated by passing over the list returned by
			// CorrelateConnectionGeneLists() - which is always in order.

            // Schrum: Modified to add outputsPerPolicy as a parameter, and use revisedOutputCount
			return new NeatGenome(ea.NextGenomeId, newNeuronGeneList, newModuleGeneList, newConnectionGeneList, inputNeuronCount, revisedOutputCount, outputsPerPolicy);
		}
Exemplo n.º 13
0
		private void Mutate_ConnectionWeights(EvolutionAlgorithm ea)
		{
			// Determine the type of weight mutation to perform.
			int groupCount = ea.NeatParameters.ConnectionMutationParameterGroupList.Count;
			double[] probabilties = new double[groupCount];
			for(int i=0; i<groupCount; i++)
			{
				probabilties[i] = ((ConnectionMutationParameterGroup)ea.NeatParameters.ConnectionMutationParameterGroupList[i]).ActivationProportion;
			}

			// Get a reference to the group we will be using.			
			ConnectionMutationParameterGroup paramGroup = (ConnectionMutationParameterGroup)ea.NeatParameters.ConnectionMutationParameterGroupList[RouletteWheel.SingleThrow(probabilties)];

			// Perform mutations of the required type.
			if(paramGroup.SelectionType==ConnectionSelectionType.Proportional)
			{
				bool mutationOccured=false;
				int connectionCount = connectionGeneList.Count;
				for(int i=0; i<connectionCount; i++)
				{
					if(Utilities.NextDouble() < paramGroup.Proportion)
					{
						MutateConnectionWeight(connectionGeneList[i], ea.NeatParameters, paramGroup);
						mutationOccured = true;
					}
				}
				if(!mutationOccured && connectionCount>0)
				{	// Perform at least one mutation. Pick a gene at random.
					MutateConnectionWeight(	connectionGeneList[(int)(Utilities.NextDouble() * connectionCount)],
											ea.NeatParameters,
											paramGroup);
				}
			}
			else // if(paramGroup.SelectionType==ConnectionSelectionType.FixedQuantity)
			{
				// Determine how many mutations to perform. At least one - if there are any genes.
				int connectionCount = connectionGeneList.Count;
				int mutations = Math.Min(connectionCount, Math.Max(1, paramGroup.Quantity));
				if(mutations==0) return;

				// The mutation loop. Here we pick an index at random and scan forward from that point
				// for the first non-mutated gene. This prevents any gene from being mutated more than once without
				// too much overhead. In fact it's optimal for small numbers of mutations where clashes are unlikely 
				// to occur.
				for(int i=0; i<mutations; i++)
				{
					// Pick an index at random.
					int index = (int)(Utilities.NextDouble()*connectionCount);
					ConnectionGene connectionGene = connectionGeneList[index];

					// Scan forward and find the first non-mutated gene.
					while(connectionGeneList[index].IsMutated)
					{	// Increment index. Wrap around back to the start if we go off the end.
						if(++index==connectionCount)
							index=0; 
					}
					
					// Mutate the gene at 'index'.
					MutateConnectionWeight(connectionGeneList[index], ea.NeatParameters, paramGroup);
					connectionGeneList[index].IsMutated = true;
				}
			}
		}
Exemplo n.º 14
0
		/// <summary>
		/// We define a simple neuron structure as a neuron that has a single outgoing or single incoming connection.
		/// With such a structure we can easily eliminate the neuron and shift it's connections to an adjacent neuron.
		/// If the neuron's non-linearity was not being used then such a mutation is a simplification of the network
		/// structure that shouldn't adversly affect its functionality.
		/// </summary>
		private void Mutate_DeleteSimpleNeuronStructure(EvolutionAlgorithm ea)
		{
			// We will use the NeuronConnectionLookupTable to find the simple structures.
			EnsureNeuronConnectionLookupTable();

			// Build a list of candidate simple neurons to choose from.
			ArrayList simpleNeuronIdList = new ArrayList();

			foreach(NeuronConnectionLookup lookup in neuronConnectionLookupTable.Values)
			{
				// If we test the connection count with <=1 then we also pick up neurons that are in dead-end circuits, 
				// RemoveSimpleNeuron is then able to delete these neurons from the network structure along with any 
				// associated connections.
                // All neurons that are part of a module would appear to be dead-ended, but skip removing them anyway.
                if (lookup.neuronGene.NeuronType == NeuronType.Hidden
                            && !(lookup.neuronGene.ActivationFunction is ModuleInputNeuron)
                            && !(lookup.neuronGene.ActivationFunction is ModuleOutputNeuron) ) {
					if((lookup.incomingList.Count<=1) || (lookup.outgoingList.Count<=1))
						simpleNeuronIdList.Add(lookup.neuronGene.InnovationId);
				}
			}

			// Are there any candiate simple neurons?
			if(simpleNeuronIdList.Count==0)
			{	// No candidate neurons. As a fallback lets delete a connection.
				Mutate_DeleteConnection();
				return;
			}

			// Pick a simple neuron at random.
			int idx = (int)Math.Floor(Utilities.NextDouble() * simpleNeuronIdList.Count);
			uint neuronId = (uint)simpleNeuronIdList[idx];
			RemoveSimpleNeuron(neuronId, ea);
		}
Exemplo n.º 15
0
 public void initializeEvolution(int populationSize)
 {
     logOutput = new StreamWriter(outputFolder + "logfile.txt");
     IdGenerator idgen = new IdGenerator();
     ea = new EvolutionAlgorithm(new Population(idgen, GenomeFactory.CreateGenomeList(experiment.DefaultNeatParameters, idgen, experiment.InputNeuronCount, experiment.OutputNeuronCount, experiment.OutputsPerPolicy, experiment.DefaultNeatParameters.pInitialPopulationInterconnections, populationSize)), experiment.PopulationEvaluator, experiment.DefaultNeatParameters);
 }
Exemplo n.º 16
0
        static void Main(string[] args)
        {
            string folder = "";
            NeatGenome seedGenome = null;
            string filename = null;
            string shape = "triangle";
            bool isMulti = false;

            for (int j = 0; j < args.Length; j++)
            {
                if(j <= args.Length - 2)
                    switch (args[j])
                    {
                        case "-seed": filename = args[++j];
                            Console.WriteLine("Attempting to use seed from file " + filename);
                            break;
                        case "-folder": folder = args[++j];
                            Console.WriteLine("Attempting to output to folder " + folder);
                            break;
                        case "-shape": shape = args[++j];
                            Console.WriteLine("Attempting to do experiment with shape " + shape);
                            break;
                        case "-multi": isMulti = Boolean.Parse(args[++j]);
                            Console.WriteLine("Experiment is heterogeneous? " + isMulti);
                            break;
                    }
            }

            if(filename!=null)
            {
                try
                {
                    XmlDocument document = new XmlDocument();
                    document.Load(filename);
                    seedGenome = XmlNeatGenomeReaderStatic.Read(document);
                }
                catch (Exception e)
                {
                    System.Console.WriteLine("Problem loading genome. \n" + e.Message);
                }
            }

            double maxFitness = 0;
            int maxGenerations = 1000;
            int populationSize = 150;
            int inputs = 4;
            IExperiment exp = new SkirmishExperiment(inputs, 1, isMulti, shape);
            StreamWriter SW;
            SW = File.CreateText(folder + "logfile.txt");
            XmlDocument doc;
            FileInfo oFileInfo;
            IdGenerator idgen;
            EvolutionAlgorithm ea;
            if (seedGenome == null)
            {
                idgen = new IdGenerator();
                ea = new EvolutionAlgorithm(new Population(idgen, GenomeFactory.CreateGenomeList(exp.DefaultNeatParameters, idgen, exp.InputNeuronCount, exp.OutputNeuronCount, exp.DefaultNeatParameters.pInitialPopulationInterconnections, populationSize)), exp.PopulationEvaluator, exp.DefaultNeatParameters);

            }
            else
            {
                idgen = new IdGeneratorFactory().CreateIdGenerator(seedGenome);
                ea = new EvolutionAlgorithm(new Population(idgen, GenomeFactory.CreateGenomeList(seedGenome, populationSize, exp.DefaultNeatParameters, idgen)), exp.PopulationEvaluator, exp.DefaultNeatParameters);
            }
            for (int j = 0; j < maxGenerations; j++)
            {
                DateTime dt = DateTime.Now;
                ea.PerformOneGeneration();
                if (ea.BestGenome.Fitness > maxFitness)
                {
                    maxFitness = ea.BestGenome.Fitness;
                    doc = new XmlDocument();
                    XmlGenomeWriterStatic.Write(doc, (NeatGenome)ea.BestGenome);
                    oFileInfo = new FileInfo(folder + "bestGenome" + j.ToString() + ".xml");
                    doc.Save(oFileInfo.FullName);

                    // This will output the substrate, uncomment if you want that
                    /* doc = new XmlDocument();
                     XmlGenomeWriterStatic.Write(doc, (NeatGenome) SkirmishNetworkEvaluator.substrate.generateMultiGenomeModulus(ea.BestGenome.Decode(null),5));
                     oFileInfo = new FileInfo(folder + "bestNetwork" + j.ToString() + ".xml");
                     doc.Save(oFileInfo.FullName);
                     */

                   
                }
                Console.WriteLine(ea.Generation.ToString() + " " + ea.BestGenome.Fitness + " " + (DateTime.Now.Subtract(dt)));
                //Do any post-hoc stuff here

                SW.WriteLine(ea.Generation.ToString() + " " + (maxFitness).ToString());

            }
            SW.Close();

            doc = new XmlDocument();
            XmlGenomeWriterStatic.Write(doc, (NeatGenome)ea.BestGenome, ActivationFunctionFactory.GetActivationFunction("NullFn"));
            oFileInfo = new FileInfo(folder + "bestGenome.xml");
            doc.Save(oFileInfo.FullName);

        }
Exemplo n.º 17
0
 /// <summary>
 /// Sexual reproduction. No mutation performed.
 /// </summary>
 /// <param name="parent"></param>
 /// <returns></returns>
 public abstract IGenome CreateOffspring_Sexual(EvolutionAlgorithm ea, IGenome parent);
Exemplo n.º 18
0
 /// <summary>
 /// Asexual reproduction with built in mutation.
 /// </summary>
 /// <returns></returns>
 public abstract IGenome CreateOffspring_Asexual(EvolutionAlgorithm ea);
Exemplo n.º 19
0
		private void RemoveSimpleNeuron(uint neuronId, EvolutionAlgorithm ea)
		{
			// Create new connections that connect all of the incoming and outgoing neurons
			// that currently exist for the simple neuron. 
			NeuronConnectionLookup lookup = (NeuronConnectionLookup)neuronConnectionLookupTable[neuronId];
			foreach(ConnectionGene incomingConnection in lookup.incomingList)
			{
				foreach(ConnectionGene outgoingConnection in lookup.outgoingList)
				{
					if(TestForExistingConnection(incomingConnection.SourceNeuronId, outgoingConnection.TargetNeuronId))
					{	// Connection already exists.
						continue;
					}

					// Test for matching connection within NewConnectionGeneTable.
					ConnectionEndpointsStruct connectionKey = new ConnectionEndpointsStruct(incomingConnection.SourceNeuronId, 
																							outgoingConnection.TargetNeuronId);
					ConnectionGene existingConnection = (ConnectionGene)ea.NewConnectionGeneTable[connectionKey];
					ConnectionGene newConnectionGene;
					if(existingConnection==null)
					{	// No matching connection found. Create a connection with a new ID.
						newConnectionGene = new ConnectionGene(ea.NextInnovationId,
							incomingConnection.SourceNeuronId,
							outgoingConnection.TargetNeuronId,
							(Utilities.NextDouble() * ea.NeatParameters.connectionWeightRange) - ea.NeatParameters.connectionWeightRange/2.0);

						// Register the new ID with NewConnectionGeneTable.
						ea.NewConnectionGeneTable.Add(connectionKey, newConnectionGene);
	
						// Add the new gene to the genome.
						connectionGeneList.Add(newConnectionGene);
					}
					else
					{	// Matching connection found. Re-use its ID.
						newConnectionGene = new ConnectionGene(existingConnection.InnovationId,
							incomingConnection.SourceNeuronId,
							outgoingConnection.TargetNeuronId,
							(Utilities.NextDouble() * ea.NeatParameters.connectionWeightRange) - ea.NeatParameters.connectionWeightRange/2.0);

						// Add the new gene to the genome. Use InsertIntoPosition() to ensure we don't break the sort 
						// order of the connection genes.
						connectionGeneList.InsertIntoPosition(newConnectionGene);
					}

					
				}
			}

			// Delete the old connections.
			foreach(ConnectionGene incomingConnection in lookup.incomingList)
				connectionGeneList.Remove(incomingConnection);

			foreach(ConnectionGene outgoingConnection in lookup.outgoingList)
			{	
				// Filter out recurrent connections - they will have already been 
				// deleted in the loop through 'lookup.incomingList'.
				if(outgoingConnection.TargetNeuronId != neuronId)
					connectionGeneList.Remove(outgoingConnection);
			}

			// Delete the simple neuron - it no longer has any connections to or from it.
			neuronGeneList.Remove(neuronId);
		}
Exemplo n.º 20
0
 public void initalizeEvolution(Population pop)
 {
     logOutput = new StreamWriter(outputFolder + "logfile.txt");
     //IdGenerator idgen = new IdGeneratorFactory().CreateIdGenerator(pop.GenomeList);
     ea = new EvolutionAlgorithm(pop, experiment.PopulationEvaluator, experiment.DefaultNeatParameters);
 }
Exemplo n.º 21
0
		/// <summary>
		/// Asexual reproduction with built in mutation.
		/// </summary>
		/// <returns></returns>
		public override IGenome CreateOffspring_Asexual(EvolutionAlgorithm ea)
		{
			// Make an exact copy this Genome.
			NeatGenome offspring = new NeatGenome(this, ea.NextGenomeId);

			// Mutate the new genome.
			offspring.Mutate(ea);
			return offspring;
		}
Exemplo n.º 22
0
		private void Mutate(EvolutionAlgorithm ea)
		{
            // Schrum: Only allow Module Mutation if there are
            // as many or fewer output neurons than hidden neurons.
            int hiddenNeuronCount = this.neuronGeneList.Count - (inputNeuronCount + outputNeuronCount);
            bool moduleMutationAllowed = hiddenNeuronCount >= outputNeuronCount;

			// Determine the type of mutation to perform.
			double[] probabilities = new double[] 
			{
				ea.NeatParameters.pMutateAddNode,
				ea.NeatParameters.pMutateAddModule,
				ea.NeatParameters.pMutateAddConnection,
				ea.NeatParameters.pMutateDeleteConnection,
				ea.NeatParameters.pMutateDeleteSimpleNeuron,
				ea.NeatParameters.pMutateConnectionWeights,
                moduleMutationAllowed ? ea.NeatParameters.pMMP : 0, // Schrum: MM(Previous)
                moduleMutationAllowed ? ea.NeatParameters.pMMR : 0, // Schrum: MM(Random)
                moduleMutationAllowed ? ea.NeatParameters.pMMD : 0  // Schrum: MM(Duplicate)
			};

			int outcome = RouletteWheel.SingleThrow(probabilities);

			switch(outcome)
			{
				case 0:
					Mutate_AddNode(ea);
					break;
                case 1:
                    Mutate_AddModule(ea);
                    break;
                case 2:
                    Mutate_AddConnection(ea);
                    break;
                case 3:
					Mutate_DeleteConnection();
					break;
				case 4:
					Mutate_DeleteSimpleNeuronStructure(ea);
					break;
				case 5:
					Mutate_ConnectionWeights(ea);
					break;
                case 6: // Schrum: MM(P)
                    Module_Mutation_Previous(ea);
                    break;
                case 7: // Schrum: MM(R)
                    Module_Mutation_Random(ea);
                    break;
                case 8: // Schrum: MM(D)
                    Module_Mutation_Duplicate(ea);
                    break;
			}
		}
Exemplo n.º 23
0
		/// <summary>
		/// Clone this genome.
		/// </summary>
		/// <returns></returns>
		public override IGenome Clone(EvolutionAlgorithm ea)
		{
			// Utilise the copy constructor for cloning.
			return new NeatGenome(this, ea.NextGenomeId);
		}
Exemplo n.º 24
0
        // Schrum: Simple form of Module Mutation, MM(P)
        private void Module_Mutation_Previous(EvolutionAlgorithm ea)
        {
            // Push all output neurons together
            this.neuronGeneList.SortByNeuronOrder();
            int numModules = this.outputNeuronCount / this.outputsPerPolicy; // Should evenly divide
            int randomModule = Utilities.Next(numModules);
            // Because outputs come after inputs.
            // Although list is 0-indexed, the +1 is needed because the bias does not count as an input
            double outputLayer = neuronGeneList[1 + inputNeuronCount].Layer; 
            // Create the new module
            for (int i = 0; i < outputsPerPolicy; i++)
            {
                IActivationFunction outputActFunction = ActivationFunctionFactory.GetActivationFunction("BipolarSigmoid");
                NeuronGene newNeuronGene = new NeuronGene(null, ea.NextInnovationId, outputLayer, NeuronType.Output, outputActFunction);
                neuronGeneList.Add(newNeuronGene);
                // Link to the new neuron: bias, then inputs, then appropriate module, then neuron within that module
                uint sourceNeuron = neuronGeneList[1 + inputNeuronCount + (randomModule * outputsPerPolicy) + i].InnovationId;
                ConnectionGene connection = new ConnectionGene(ea.NextInnovationId, sourceNeuron, newNeuronGene.InnovationId, 1.0);
                connectionGeneList.InsertIntoPosition(connection);
                this.outputNeuronCount++; // Increase number of outputs
            }

            // Schrum: Debugging
            //Console.WriteLine("MM(P): outputNeuronCount=" + outputNeuronCount);
            // Schrum: More debugging
            /*
            this.neuronGeneList.SortByInnovationId();
            XmlDocument doc = new XmlDocument();
            XmlGenomeWriterStatic.Write(doc, (NeatGenome)this);
            FileInfo oFileInfo = new FileInfo("MMPNet.xml");
            doc.Save(oFileInfo.FullName);
            */
        }
Exemplo n.º 25
0
        public void initializeEvolution(int populationSize)
        {
            if (logOutput != null)
                logOutput.Close();

            logOutput = new StreamWriter(outputFolder + "logfile.txt");
            IdGenerator idgen = new IdGenerator();
            ea = new EvolutionAlgorithm(new Population(idgen, GenomeFactory.CreateGenomeList(neatParams, idgen, cppnInputs, cppnOutputs, neatParams.pInitialPopulationInterconnections, populationSize)), populationEval, neatParams);
        }
Exemplo n.º 26
0
        // Schrum: Module Mutation Random creates a new module with
        // completely random incoming links.
        private void Module_Mutation_Random(EvolutionAlgorithm ea)
        {
            // Push all output neurons together
            this.neuronGeneList.SortByNeuronOrder();
            int numModules = this.outputNeuronCount / this.outputsPerPolicy; // Should evenly divide
            int randomModule = Utilities.Next(numModules);
            // Because outputs come after inputs.
            // Although list is 0-indexed, the +1 is needed because the bias does not count as an input
            double outputLayer = neuronGeneList[1 + inputNeuronCount].Layer;
            // Create the new module one neuron per loop iteration
            for (int i = 0; i < outputsPerPolicy; i++)
            {
                // The activation function for the output layer
                IActivationFunction outputActFunction = ActivationFunctionFactory.GetActivationFunction("BipolarSigmoid");
                NeuronGene newNeuronGene = new NeuronGene(null, ea.NextInnovationId, outputLayer, NeuronType.Output, outputActFunction);
                neuronGeneList.Add(newNeuronGene);

                // Count links to random output neuron: bias, then inputs, then random module, then neuron within that module
                uint randomModuleInnovation = neuronGeneList[1 + inputNeuronCount + (randomModule * outputsPerPolicy) + i].InnovationId;
                int numIncoming = 0;
                foreach (ConnectionGene cg in this.ConnectionGeneList)
                {
                    // Count the link
                    if (cg.TargetNeuronId == randomModuleInnovation)
                        numIncoming++;
                }

                // Give the new module (up to) the same number of links as some other module
                for (int j = 0; j < numIncoming; j++) // Will always create ay least one link
                {
                    uint randomSource = NeuronGeneList[Utilities.Next(NeuronGeneList.Count)].InnovationId;
                    // Magic equation stolen from Mutate_AddConnection below
                    double randomWeight = (Utilities.NextDouble() * ea.NeatParameters.connectionWeightRange/4.0) - ea.NeatParameters.connectionWeightRange/8.0;
                    if (!TestForExistingConnection(randomSource, newNeuronGene.InnovationId)) // Only create each connection once
                    {
                        ConnectionGene connection = new ConnectionGene(ea.NextInnovationId, randomSource, newNeuronGene.InnovationId, randomWeight);
                        connectionGeneList.InsertIntoPosition(connection);
                    }
                }
                this.outputNeuronCount++; // Increase number of outputs
            }
        }
Exemplo n.º 27
0
        /// <summary>
        /// Initializes the EA with an initial population generated from a single seed genome.
        /// </summary>
        public void initializeEvolution(int populationSize, NeatGenome seedGenome)
        {
            if (seedGenome == null)
            {
                initializeEvolution(populationSize);
                return;
            }

            LogOutput = Logging ? new StreamWriter(Path.Combine(OutputFolder, "log.txt")) : null;
            FinalPositionOutput = FinalPositionLogging ? new StreamWriter(Path.Combine(OutputFolder,"final-position.txt")) : null;
            ArchiveModificationOutput = FinalPositionLogging ? new StreamWriter(Path.Combine(OutputFolder, "archive-mods.txt")) : null;
            ComplexityOutput = new StreamWriter(Path.Combine(OutputFolder, "complexity.txt"));
            ComplexityOutput.WriteLine("avg,stdev,min,max");
            if (FinalPositionLogging)
            {
                FinalPositionOutput.WriteLine("x,y");
                ArchiveModificationOutput.WriteLine("ID,action,time,x,y");
            }
            IdGenerator idgen = new IdGeneratorFactory().CreateIdGenerator(seedGenome);
            EA = new EvolutionAlgorithm(new Population(idgen, GenomeFactory.CreateGenomeList(seedGenome, populationSize, experiment.DefaultNeatParameters, idgen)), experiment.PopulationEvaluator, experiment.DefaultNeatParameters);
            EA.outputFolder = OutputFolder;
            EA.neatBrain = NEATBrain;
        }
Exemplo n.º 28
0
        // Schrum: Module Mutation Duplicate creates a new module with
        // links copying those of another module.
        private void Module_Mutation_Duplicate(EvolutionAlgorithm ea)
        {
            // Push all output neurons together
            this.neuronGeneList.SortByNeuronOrder();
            int numModules = this.outputNeuronCount / this.outputsPerPolicy; // Should evenly divide
            int randomModule = Utilities.Next(numModules); // Duplicate this module
            // Because outputs come after inputs.
            // Although list is 0-indexed, the +1 is needed because the bias does not count as an input
            double outputLayer = neuronGeneList[1 + inputNeuronCount].Layer;
            // Create the new module one neuron per loop iteration
            for (int i = 0; i < outputsPerPolicy; i++)
            {
                // The activation function for the output layer
                IActivationFunction outputActFunction = ActivationFunctionFactory.GetActivationFunction("BipolarSigmoid");
                NeuronGene newNeuronGene = new NeuronGene(null, ea.NextInnovationId, outputLayer, NeuronType.Output, outputActFunction);
                neuronGeneList.Add(newNeuronGene);

                uint randomModuleInnovation = neuronGeneList[1 + inputNeuronCount + (randomModule * outputsPerPolicy) + i].InnovationId;
                // Copy each connection to the new module neuron
                int originalLength = ConnectionGeneList.Count; // Don't need to check the newly added connections
                for (int j = 0; j < originalLength; j++)
                {
                    ConnectionGene cg = ConnectionGeneList[j];
                    if (cg.TargetNeuronId == randomModuleInnovation)
                    {
                        // Copy the link
                        ConnectionGene connection = new ConnectionGene(ea.NextInnovationId, cg.SourceNeuronId, newNeuronGene.InnovationId, cg.Weight);
                        connectionGeneList.InsertIntoPosition(connection);
                    }
                }
                this.outputNeuronCount++; // Increase number of outputs
            }
        }
Exemplo n.º 29
0
 /// <summary>
 /// Initializes the EA with a random intial population.
 /// </summary>
 public void initializeEvolution(int populationSize)
 {
     LogOutput = Logging ? new StreamWriter(Path.Combine(OutputFolder, "log.txt")) : null;
     FinalPositionOutput = FinalPositionLogging ? new StreamWriter(Path.Combine(OutputFolder,"final-position.txt")) : null;
     ArchiveModificationOutput = FinalPositionLogging ? new StreamWriter(Path.Combine(OutputFolder, "archive-mods.txt")) : null;
     ComplexityOutput = new StreamWriter(Path.Combine(OutputFolder, "complexity.txt"));
     ComplexityOutput.WriteLine("avg,stdev,min,max");
     if (FinalPositionLogging)
     {
         FinalPositionOutput.WriteLine("ID,x,y");
         ArchiveModificationOutput.WriteLine("ID,action,time,x,y");
     }
     
     IdGenerator idgen = new IdGenerator();
     EA = new EvolutionAlgorithm(new Population(idgen, GenomeFactory.CreateGenomeList(experiment.DefaultNeatParameters, idgen, experiment.InputNeuronCount, experiment.OutputNeuronCount, experiment.DefaultNeatParameters.pInitialPopulationInterconnections, populationSize, SimExperiment.neatBrain)), experiment.PopulationEvaluator, experiment.DefaultNeatParameters);
     EA.outputFolder = OutputFolder;
     EA.neatBrain = NEATBrain;
 }
Exemplo n.º 30
0
        /// <summary>
        /// Add a new node to the Genome. We do this by removing a connection at random and inserting 
        /// a new node and two new connections that make the same circuit as the original connection.
        /// 
        /// This way the new node is properly integrated into the network from the outset.
        /// </summary>
        /// <param name="ea"></param>
        private void Mutate_AddNode(EvolutionAlgorithm ea)
		{
			if(connectionGeneList.Count==0)
				return;

			// Select a connection at random.
			int connectionToReplaceIdx = (int)Math.Floor(Utilities.NextDouble() * connectionGeneList.Count);
			ConnectionGene connectionToReplace = connectionGeneList[connectionToReplaceIdx];
				
			// Delete the existing connection. JOEL: Why delete old connection?
			//connectionGeneList.RemoveAt(connectionToReplaceIdx);

			// Check if this connection has already been split on another genome. If so then we should re-use the
			// neuron ID and two connection ID's so that matching structures within the population maintain the same ID.
			object existingNeuronGeneStruct = ea.NewNeuronGeneStructTable[connectionToReplace.InnovationId];

			NeuronGene newNeuronGene;
			ConnectionGene newConnectionGene1;
			ConnectionGene newConnectionGene2;
            IActivationFunction actFunct;
			if(existingNeuronGeneStruct==null)
			{	// No existing matching structure, so generate some new ID's.

                //TODO: DAVID proper random activation function
				// Replace connectionToReplace with two new connections and a neuron.
                actFunct=ActivationFunctionFactory.GetRandomActivationFunction(ea.NeatParameters);
                //newNeuronGene = new NeuronGene(ea.NextInnovationId, NeuronType.Hidden, actFunct);

                newNeuronGene = new NeuronGene(null, ea.NextInnovationId, (neuronGeneList.GetNeuronById(connectionToReplace.SourceNeuronId).Layer + neuronGeneList.GetNeuronById(connectionToReplace.TargetNeuronId).Layer) / 2.0, NeuronType.Hidden, actFunct);
			
				newConnectionGene1 = new ConnectionGene(ea.NextInnovationId, connectionToReplace.SourceNeuronId, newNeuronGene.InnovationId, 1.0);
				newConnectionGene2 = new ConnectionGene(ea.NextInnovationId, newNeuronGene.InnovationId, connectionToReplace.TargetNeuronId, connectionToReplace.Weight);

				// Register the new ID's with NewNeuronGeneStructTable.
				ea.NewNeuronGeneStructTable.Add(connectionToReplace.InnovationId,
												new NewNeuronGeneStruct(newNeuronGene, newConnectionGene1, newConnectionGene2));
			}
			else
			{	// An existing matching structure has been found. Re-use its ID's

                //TODO: DAVID proper random activation function
				// Replace connectionToReplace with two new connections and a neuron.
                actFunct = ActivationFunctionFactory.GetRandomActivationFunction(ea.NeatParameters);
				NewNeuronGeneStruct tmpStruct = (NewNeuronGeneStruct)existingNeuronGeneStruct;
                //newNeuronGene = new NeuronGene(tmpStruct.NewNeuronGene.InnovationId, NeuronType.Hidden, actFunct);
                newNeuronGene = new NeuronGene(null, tmpStruct.NewNeuronGene.InnovationId, tmpStruct.NewNeuronGene.Layer, NeuronType.Hidden, actFunct);
				
				newConnectionGene1 = new ConnectionGene(tmpStruct.NewConnectionGene_Input.InnovationId, connectionToReplace.SourceNeuronId, newNeuronGene.InnovationId, 1.0);
				newConnectionGene2 = new ConnectionGene(tmpStruct.NewConnectionGene_Output.InnovationId, newNeuronGene.InnovationId, connectionToReplace.TargetNeuronId, connectionToReplace.Weight);
			}

			// Add the new genes to the genome.
			neuronGeneList.Add(newNeuronGene);
			connectionGeneList.InsertIntoPosition(newConnectionGene1);
			connectionGeneList.InsertIntoPosition(newConnectionGene2);
		}