Beispiel #1
0
        private static void WriteConnection(XmlElement xmlConnections, FloatFastConnection connectionGene)
        {
            XmlElement xmlConnection = XmlUtilities.AddElement(xmlConnections, "connection");

            XmlUtilities.AddAttribute(xmlConnection, "src-id", connectionGene.sourceNeuronIdx.ToString());
            XmlUtilities.AddAttribute(xmlConnection, "tgt-id", connectionGene.targetNeuronIdx.ToString());
            XmlUtilities.AddAttribute(xmlConnection, "weight", connectionGene.weight.ToString());
        }
Beispiel #2
0
        /// <summary>
        /// Standard qquicksort algorithm.
        /// </summary>
        /// <param name="left"></param>
        /// <param name="right"></param>
        private static void QuickSortFastConnections(int left, int right)
        {
            do
            {
                int i = left;
                int j = right;
                FloatFastConnection x = fastConnectionArray[(i + j) >> 1];
                do
                {
                    while (CompareKeys(ref fastConnectionArray[i], ref x) < 0)
                    {
                        i++;
                    }
                    while (CompareKeys(ref x, ref fastConnectionArray[j]) < 0)
                    {
                        j--;
                    }

                    System.Diagnostics.Debug.Assert(i >= left && j <= right, "(i>=left && j<=right)  Sort failed - Is your IComparer bogus?");
                    if (i > j)
                    {
                        break;
                    }
                    if (i < j)
                    {
                        FloatFastConnection key = fastConnectionArray[i];
                        fastConnectionArray[i] = fastConnectionArray[j];
                        fastConnectionArray[j] = key;
                    }
                    i++;
                    j--;
                } while (i <= j);

                if (j - left <= right - i)
                {
                    if (left < j)
                    {
                        QuickSortFastConnections(left, j);
                    }
                    left = i;
                }
                else
                {
                    if (i < right)
                    {
                        QuickSortFastConnections(i, right);
                    }
                    right = j;
                }
            } while (left < right);
        }
Beispiel #3
0
        // This is a quick sort algorithm that manipulates FastConnection structures. Although this
        // is the same sorting technique used internally by Array.Sort this is approximately 10 times
        // faster because it eliminates the need for boxing and unboxing of the structs.
        // So although this code could be replcaed by a single Array.Sort statement, the pay off
        // was though to be worth it.

        private static int CompareKeys(ref FloatFastConnection a, ref FloatFastConnection b)
        {
            int diff = a.sourceNeuronIdx - b.sourceNeuronIdx;

            if (diff == 0)
            {
                // Secondary sort on targetNeuronIdx.
                return(a.targetNeuronIdx - b.targetNeuronIdx);
            }
            else
            {
                return(diff);
            }
        }
Beispiel #4
0
        static public ModularNetwork DecodeToModularNetwork(NeatGenome.NeatGenome g)
        {
            int inputCount  = g.InputNeuronCount;
            int outputCount = g.OutputNeuronCount;
            int neuronCount = g.NeuronGeneList.Count;

            IActivationFunction[] activationFunctions = new IActivationFunction[neuronCount];
            float[] biasList = new float[neuronCount];

            Dictionary <long, int> neuronLookup = new Dictionary <long, int>(neuronCount);

            // Create an array of the activation functions for each non-module node node in the genome.
            // Start with a bias node if there is one in the genome.
            // The genome's neuron list is assumed to be ordered by type, with the bias node appearing first.
            int neuronGeneIndex = 0;

            for (; neuronGeneIndex < neuronCount; neuronGeneIndex++)
            {
                if (g.NeuronGeneList[neuronGeneIndex].NeuronType != NeuronType.Bias)
                {
                    break;
                }
                activationFunctions[neuronGeneIndex] = g.NeuronGeneList[neuronGeneIndex].ActivationFunction;
                neuronLookup.Add(g.NeuronGeneList[neuronGeneIndex].InnovationId, neuronGeneIndex);
            }
            int biasCount = neuronGeneIndex;

            for (; neuronGeneIndex < neuronCount; neuronGeneIndex++)
            {
                activationFunctions[neuronGeneIndex] = g.NeuronGeneList[neuronGeneIndex].ActivationFunction;
                neuronLookup.Add(g.NeuronGeneList[neuronGeneIndex].InnovationId, neuronGeneIndex);
                biasList[neuronGeneIndex] = g.NeuronGeneList[neuronGeneIndex].Bias;
            }

            // Create an array of the activation functions, inputs, and outputs for each module in the genome.
            ModulePacket[] modules = new ModulePacket[g.ModuleGeneList.Count];
            for (int i = g.ModuleGeneList.Count - 1; i >= 0; i--)
            {
                modules[i].function = g.ModuleGeneList[i].Function;
                // Must translate input and output IDs to array locations.
                modules[i].inputLocations = new int[g.ModuleGeneList[i].InputIds.Count];
                for (int j = g.ModuleGeneList[i].InputIds.Count - 1; j >= 0; j--)
                {
                    modules[i].inputLocations[j] = neuronLookup[g.ModuleGeneList[i].InputIds[j]];
                }
                modules[i].outputLocations = new int[g.ModuleGeneList[i].OutputIds.Count];
                for (int j = g.ModuleGeneList[i].OutputIds.Count - 1; j >= 0; j--)
                {
                    modules[i].outputLocations[j] = neuronLookup[g.ModuleGeneList[i].OutputIds[j]];
                }
            }

            // ConnectionGenes point to a neuron's innovation ID. Translate this ID to the neuron's index in the neuron array.
            FloatFastConnection[] connections = new FloatFastConnection[g.ConnectionGeneList.Count];
            for (int connectionGeneIndex = g.ConnectionGeneList.Count - 1; connectionGeneIndex >= 0; connectionGeneIndex--)
            {
                ConnectionGene connectionGene = g.ConnectionGeneList[connectionGeneIndex];
                connections[connectionGeneIndex].sourceNeuronIdx = neuronLookup[connectionGene.SourceNeuronId];
                connections[connectionGeneIndex].targetNeuronIdx = neuronLookup[connectionGene.TargetNeuronId];
                connections[connectionGeneIndex].weight          = (float)connectionGene.Weight;

                connections[connectionGeneIndex].learningRate  = connectionGene.learningRate;
                connections[connectionGeneIndex].A             = connectionGene.A;
                connections[connectionGeneIndex].B             = connectionGene.B;
                connections[connectionGeneIndex].C             = connectionGene.C;
                connections[connectionGeneIndex].D             = connectionGene.D;
                connections[connectionGeneIndex].modConnection = connectionGene.modConnection;
            }

            ModularNetwork mn = new ModularNetwork(biasCount, inputCount, outputCount, neuronCount, connections, biasList, activationFunctions, modules);

            if (g.networkAdaptable)
            {
                mn.adaptable = true;
            }
            if (g.networkModulatory)
            {
                mn.modulatory = true;
            }

            mn.genome = g;
            return(mn);
        }
Beispiel #5
0
        static public FastConcurrentMultiplicativeNetwork DecodeToFastConcurrentMultiplicativeNetwork(NeatGenome.NeatGenome g, IActivationFunction activationFn)
        {
            int outputNeuronCount = g.OutputNeuronCount;
            int neuronGeneCount   = g.NeuronGeneList.Count;

            // Slightly inefficient - determine the number of bias nodes. Fortunately there is not actually
            // any reason to ever have more than one bias node - although there may be 0.
            int neuronGeneIdx = 0;

            for (; neuronGeneIdx < neuronGeneCount; neuronGeneIdx++)
            {
                if (g.NeuronGeneList[neuronGeneIdx].NeuronType != NeuronType.Bias)
                {
                    break;
                }
            }
            int biasNodeCount    = neuronGeneIdx;
            int inputNeuronCount = g.InputNeuronCount;

            // ConnectionGenes point to a neuron ID. We need to map this ID to a 0 based index for
            // efficiency. To do this we build a table of indexes (ints) keyed on neuron ID.
            // TODO: An alternative here would be to forgo the building of a table and do a binary
            // search directly on the NeuronGeneList - probably a good idea to use a heuristic based upon
            // neuroncount*connectioncount that decides on which technique to use. Small networks will
            // likely be faster to decode using the binary search.

            // Actually we can partly achieve the above optimzation by using HybridDictionary instead of Hashtable.
            // Although creating a table is a bit expensive.
            HybridDictionary neuronIndexTable = new HybridDictionary(neuronGeneCount);

            for (int i = 0; i < neuronGeneCount; i++)
            {
                neuronIndexTable.Add(g.NeuronGeneList[i].InnovationId, i);
            }

            // Count how many of the connections are actually enabled. TODO: make faster - store disable count?
            int connectionGeneCount = g.ConnectionGeneList.Count;
            int connectionCount     = connectionGeneCount;

            //			for(int i=0; i<connectionGeneCount; i++)
            //			{
            //				if(g.ConnectionGeneList[i].Enabled)
            //					connectionCount++;
            //			}

            // Now we can build the connection array(s).
            FloatFastConnection[] connectionArray = new FloatFastConnection[connectionCount];
            int connectionIdx = 0;

            for (int connectionGeneIdx = 0; connectionGeneIdx < connectionCount; connectionGeneIdx++)
            {
                ConnectionGene connectionGene = g.ConnectionGeneList[connectionIdx];
                connectionArray[connectionIdx].sourceNeuronIdx = (int)neuronIndexTable[connectionGene.SourceNeuronId];
                connectionArray[connectionIdx].targetNeuronIdx = (int)neuronIndexTable[connectionGene.TargetNeuronId];
                connectionArray[connectionIdx].weight          = (float)connectionGene.Weight;
                connectionIdx++;
            }

            // Now sort the connection array on sourceNeuronIdx, secondary sort on targetNeuronIdx.
            // TODO: custom sort routine to prevent boxing/unboxing required by Array.Sort(ValueType[])
            //Array.Sort(connectionArray, fastConnectionComparer);
            QuickSortFastConnections(0, fastConnectionArray.Length - 1);

            return(new FastConcurrentMultiplicativeNetwork(
                       biasNodeCount, inputNeuronCount,
                       outputNeuronCount, neuronGeneCount,
                       connectionArray, activationFn));
        }
        static public ModularNetwork DecodeToModularNetwork(NeatGenome.NeatGenome g)
        {
            int inputCount  = g.InputNeuronCount;
            int outputCount = g.OutputNeuronCount;
            int neuronCount = g.NeuronGeneList.Count;

            IActivationFunction[] activationFunctions = new IActivationFunction[neuronCount];
            float[] biasList = new float[neuronCount];

            Dictionary <uint, int> neuronLookup = new Dictionary <uint, int>(neuronCount);

            // Schrum: In case there are output neurons out of order
            g.NeuronGeneList.NeuronSortCheck();

            // Create an array of the activation functions for each non-module node node in the genome.
            // Start with a bias node if there is one in the genome.
            // The genome's neuron list is assumed to be ordered by type, with the bias node appearing first.
            int neuronGeneIndex = 0;

            for (; neuronGeneIndex < neuronCount; neuronGeneIndex++)
            {
                if (g.NeuronGeneList[neuronGeneIndex].NeuronType != NeuronType.Bias)
                {
                    break;
                }
                activationFunctions[neuronGeneIndex] = g.NeuronGeneList[neuronGeneIndex].ActivationFunction;
                neuronLookup.Add(g.NeuronGeneList[neuronGeneIndex].InnovationId, neuronGeneIndex);
            }
            int biasCount = neuronGeneIndex;

            // Schrum: debug
            //Console.WriteLine("start (after bias): " + g.GenomeId);

            // Schrum: Debugging
            //NeuronType expectedType = NeuronType.Input;

            for (; neuronGeneIndex < neuronCount; neuronGeneIndex++)
            {
                activationFunctions[neuronGeneIndex] = g.NeuronGeneList[neuronGeneIndex].ActivationFunction;
                // Schrum: Debug

                /*
                 * if (expectedType != g.NeuronGeneList[neuronGeneIndex].NeuronType)
                 * {
                 *  if (expectedType == NeuronType.Input && g.NeuronGeneList[neuronGeneIndex].NeuronType == NeuronType.Output)
                 *  {
                 *      expectedType = NeuronType.Output;
                 *  }
                 *  else if (expectedType == NeuronType.Output && g.NeuronGeneList[neuronGeneIndex].NeuronType == NeuronType.Hidden)
                 *  {
                 *      expectedType = NeuronType.Hidden;
                 *  }
                 *  else
                 *  {
                 *      // Error condition:
                 *      Console.WriteLine("Error with genome: " + g.GenomeId);
                 *
                 *      XmlDocument doc = new XmlDocument();
                 *      XmlGenomeWriterStatic.Write(doc, (SharpNeatLib.NeatGenome.NeatGenome)g);
                 *      FileInfo oFileInfo = new FileInfo("ProblemGenome.xml");
                 *      doc.Save(oFileInfo.FullName);
                 *
                 *      Environment.Exit(1);
                 *  }
                 * }
                 */
                neuronLookup.Add(g.NeuronGeneList[neuronGeneIndex].InnovationId, neuronGeneIndex);
                biasList[neuronGeneIndex] = g.NeuronGeneList[neuronGeneIndex].Bias;
            }

            // Create an array of the activation functions, inputs, and outputs for each module in the genome.
            ModulePacket[] modules = new ModulePacket[g.ModuleGeneList.Count];
            for (int i = g.ModuleGeneList.Count - 1; i >= 0; i--)
            {
                modules[i].function = g.ModuleGeneList[i].Function;
                // Must translate input and output IDs to array locations.
                modules[i].inputLocations = new int[g.ModuleGeneList[i].InputIds.Count];
                for (int j = g.ModuleGeneList[i].InputIds.Count - 1; j >= 0; j--)
                {
                    modules[i].inputLocations[j] = neuronLookup[g.ModuleGeneList[i].InputIds[j]];
                }
                modules[i].outputLocations = new int[g.ModuleGeneList[i].OutputIds.Count];
                for (int j = g.ModuleGeneList[i].OutputIds.Count - 1; j >= 0; j--)
                {
                    modules[i].outputLocations[j] = neuronLookup[g.ModuleGeneList[i].OutputIds[j]];
                }
            }

            // ConnectionGenes point to a neuron's innovation ID. Translate this ID to the neuron's index in the neuron array.
            FloatFastConnection[] connections = new FloatFastConnection[g.ConnectionGeneList.Count];
            for (int connectionGeneIndex = g.ConnectionGeneList.Count - 1; connectionGeneIndex >= 0; connectionGeneIndex--)
            {
                ConnectionGene connectionGene = g.ConnectionGeneList[connectionGeneIndex];
                connections[connectionGeneIndex].sourceNeuronIdx = neuronLookup[connectionGene.SourceNeuronId];
                connections[connectionGeneIndex].targetNeuronIdx = neuronLookup[connectionGene.TargetNeuronId];
                connections[connectionGeneIndex].weight          = (float)connectionGene.Weight;

                connections[connectionGeneIndex].learningRate  = connectionGene.learningRate;
                connections[connectionGeneIndex].A             = connectionGene.A;
                connections[connectionGeneIndex].B             = connectionGene.B;
                connections[connectionGeneIndex].C             = connectionGene.C;
                connections[connectionGeneIndex].D             = connectionGene.D;
                connections[connectionGeneIndex].modConnection = connectionGene.modConnection;
            }

            ModularNetwork mn = new ModularNetwork(biasCount, inputCount, outputCount, g.OutputsPerPolicy, neuronCount, connections, biasList, activationFunctions, modules);

            if (g.networkAdaptable)
            {
                mn.adaptable = true;
            }
            if (g.networkModulatory)
            {
                mn.modulatory = true;
            }

            mn.genome = g;
            return(mn);
        }