// Sets up the genetic task
            public override void Init(int nGPU)
            {
                currentGen = 0;
                m_weights = 0;

                // Load the relevant kernels
                m_coeffGenKernel = MyKernelFactory.Instance.Kernel(nGPU, @"Genetic\CosyneGenetics", "generateCoefficients");
                m_geneticKernel = MyKernelFactory.Instance.Kernel(nGPU, @"Genetic\CosyneGenetics", "grow");
                m_extractKernel = MyKernelFactory.Instance.Kernel(nGPU, @"Genetic\CosyneGenetics", "extractCoeffs");
                m_cosineGenKernel = MyKernelFactory.Instance.Kernel(nGPU, @"Genetic\CosyneGenetics", "createCosineMatrix");
                m_implantKernel = MyKernelFactory.Instance.Kernel(nGPU, @"Genetic\CosyneGenetics", "implantCoeffs");

                // Init the random generator
                m_rand = new Random();

                // Set up coefficient Generation
                m_coeffGenKernel.SetupExecution(Owner.PopulationSize);
                // Set up genetic recombination
                m_geneticKernel.SetupExecution(Owner.PopulationSize);

                // This finds the first nn group in the network. Possibility of getting a list of networks and evolving them all seperately?
                List<MyNode> ch = Owner.Owner.Network.Children;
                foreach (MyNode n in ch)
                {
                    if (n is MyNeuralNetworkGroup)
                    {
                        nn = n as MyNeuralNetworkGroup;
                        MyLog.INFO.WriteLine("Evolving the layers of node: " + nn.Name);
                        break;
                    }
                }
                if (nn == null)
                {
                    throw new NullReferenceException("There is no top level NeuralNetworkGroup.");
                }

                // Construct the layerlist which is to be read from and written to
                constructLayerList(nn);

                // This is how big the weight matrix will be
                arr_size = (int)Math.Ceiling(Math.Sqrt(m_weights));

                // Get the relevant execution plan
                m_executionPlan = Owner.Owner.SimulationHandler.Simulation.ExecutionPlan[0];

                #region MemoryBlocks
                // Initialise the population
                population = new List<MyMemoryBlock<float>>();
                outputPop = new List<MyMemoryBlock<float>>();
                for (int i = 0; i < Owner.PopulationSize; i++)
                {
                    population.Add(new MyMemoryBlock<float>());
                    population[i].Owner = Owner;
                    population[i].Count = arr_size * arr_size;
                    population[i].AllocateMemory();

                    outputPop.Add(new MyMemoryBlock<float>());
                    outputPop[i].Owner = Owner;
                    outputPop[i].Count = arr_size * arr_size;
                    outputPop[i].AllocateMemory();
                }

                // Allocate space to manipulate weight matrices on the device
                cudaMatrices = new MyMemoryBlock<float>();
                cudaMatrices.Owner = Owner;
                cudaMatrices.Count = arr_size * arr_size * Owner.PopulationSize;
                cudaMatrices.AllocateDevice();

                // Allocate a memory block for the Cosine matrix
                multiplier = new MyMemoryBlock<float>();
                multiplier.Owner = Owner;
                multiplier.Count = arr_size * arr_size;
                multiplier.AllocateDevice();

                // Fill the cosine Matrices
                m_cosineGenKernel.SetupExecution(arr_size);
                m_cosineGenKernel.Run(multiplier, arr_size);

                // Allocate space needed for chromosomes
                chromosomePop = new MyMemoryBlock<float>();
                chromosomePop.Owner = Owner;
                if (DirectEvolution)
                    chromosomePop.Count = m_weights * Owner.PopulationSize;
                else
                    chromosomePop.Count = CoefficientsSaved * Owner.PopulationSize;
                chromosomePop.AllocateMemory();

                // Allocate some space for noise to seed the cuda_rand generator
                noise = new MyMemoryBlock<float>();
                noise.Owner = Owner;
                noise.Count = Owner.PopulationSize;
                noise.AllocateMemory();

                // Write some noise to the initial array
                for (int i = 0; i < Owner.PopulationSize; i++)
                {
                    noise.Host[i] = (float)m_rand.NextDouble() * 100000 + (float)m_rand.NextDouble() * 40;
                }
                noise.SafeCopyToDevice();

                // Allocate space for the fitnesses
                fitnesses = new MyMemoryBlock<float>();
                fitnesses.Owner = Owner;
                fitnesses.Count = Owner.PopulationSize;
                fitnesses.AllocateMemory();

                // Allocate some temporary storage
                tempMB = new MyMemoryBlock<float>();
                tempPop = new MyMemoryBlock<float>();
                tempMB.Owner = Owner;
                tempMB.Count = CoefficientsSaved;
                tempMB.AllocateDevice();

                tempPop.Owner = Owner;
                tempPop.Count = arr_size * arr_size;
                tempPop.AllocateDevice();

                marking = new MyMemoryBlock<int>();
                marking.Owner = Owner;
                marking.Count = CoefficientsSaved * Owner.PopulationSize;
                marking.AllocateDevice();
                #endregion

                // Check saved Coeffs size
                if (CoefficientsSaved > m_weights)
                {
                    MyLog.WARNING.Write("Saving more Coefficients than exist in the weight matrix. Setting to max permissable value\n");
                    CoefficientsSaved = m_weights;
                }

                if (CoefficientsSaved == m_weights)
                {
                    MyLog.INFO.Write("Saving a coefficient for every weight. Evolving weights directly\n");
                    DirectEvolution = true;
                }

                if (DirectEvolution)
                    CoefficientsSaved = m_weights;

                // Generate the rest of the population
                if (DirectEvolution)
                    m_coeffGenKernel.Run(chromosomePop, CoefficientsSaved, noise, Owner.PopulationSize, WeightMagnitude);
                else
                    m_coeffGenKernel.Run(chromosomePop, CoefficientsSaved, noise, Owner.PopulationSize, Alpha);

                //Disable Backprop tasks in Network
                if (nn.GetActiveBackpropTask() != null)
                {
                    if (!nn.GetActiveBackpropTask().DisableLearning)
                    {
                        MyLog.WARNING.WriteLine("Disabling backprop learning for Neural Network");
                        nn.GetActiveBackpropTask().DisableLearning = true;
                    }
                }
            }
            // Sets up the genetic task
            public override void Init(int nGPU)
            {
                currentGen = 0;
                m_weights  = 0;


                // Load the relevant kernels
                m_coeffGenKernel  = MyKernelFactory.Instance.Kernel(nGPU, @"Genetic\CosyneGenetics", "generateCoefficients");
                m_geneticKernel   = MyKernelFactory.Instance.Kernel(nGPU, @"Genetic\CosyneGenetics", "grow");
                m_extractKernel   = MyKernelFactory.Instance.Kernel(nGPU, @"Genetic\CosyneGenetics", "extractCoeffs");
                m_cosineGenKernel = MyKernelFactory.Instance.Kernel(nGPU, @"Genetic\CosyneGenetics", "createCosineMatrix");
                m_implantKernel   = MyKernelFactory.Instance.Kernel(nGPU, @"Genetic\CosyneGenetics", "implantCoeffs");

                // Init the random generator
                m_rand = new Random();

                // Set up coefficient Generation
                m_coeffGenKernel.SetupExecution(Owner.PopulationSize);
                // Set up genetic recombination
                m_geneticKernel.SetupExecution(Owner.PopulationSize);


                // This finds the first nn group in the network. Possibility of getting a list of networks and evolving them all seperately?
                List <MyNode> ch = Owner.Owner.Network.Children;

                foreach (MyNode n in ch)
                {
                    if (n is MyNeuralNetworkGroup)
                    {
                        nn = n as MyNeuralNetworkGroup;
                        MyLog.INFO.WriteLine("Evolving the layers of node: " + nn.Name);
                        break;
                    }
                }
                if (nn == null)
                {
                    throw new NullReferenceException("There is no top level NeuralNetworkGroup.");
                }

                // Construct the layerlist which is to be read from and written to
                constructLayerList(nn);

                // This is how big the weight matrix will be
                arr_size = (int)Math.Ceiling(Math.Sqrt(m_weights));

                // Get the relevant execution plan
                m_executionPlan = Owner.Owner.SimulationHandler.Simulation.ExecutionPlan;

                #region MemoryBlocks
                // Initialise the population
                population = new List <MyMemoryBlock <float> >();
                outputPop  = new List <MyMemoryBlock <float> >();
                for (int i = 0; i < Owner.PopulationSize; i++)
                {
                    population.Add(new MyMemoryBlock <float>());
                    population[i].Owner = Owner;
                    population[i].Count = arr_size * arr_size;
                    population[i].AllocateMemory();

                    outputPop.Add(new MyMemoryBlock <float>());
                    outputPop[i].Owner = Owner;
                    outputPop[i].Count = arr_size * arr_size;
                    outputPop[i].AllocateMemory();
                }

                // Allocate space to manipulate weight matrices on the device
                cudaMatrices       = new MyMemoryBlock <float>();
                cudaMatrices.Owner = Owner;
                cudaMatrices.Count = arr_size * arr_size * Owner.PopulationSize;
                cudaMatrices.AllocateDevice();

                // Allocate a memory block for the Cosine matrix
                multiplier       = new MyMemoryBlock <float>();
                multiplier.Owner = Owner;
                multiplier.Count = arr_size * arr_size;
                multiplier.AllocateDevice();

                // Fill the cosine Matrices
                m_cosineGenKernel.SetupExecution(arr_size);
                m_cosineGenKernel.Run(multiplier, arr_size);

                // Allocate space needed for chromosomes
                chromosomePop       = new MyMemoryBlock <float>();
                chromosomePop.Owner = Owner;
                if (DirectEvolution)
                {
                    chromosomePop.Count = m_weights * Owner.PopulationSize;
                }
                else
                {
                    chromosomePop.Count = CoefficientsSaved * Owner.PopulationSize;
                }
                chromosomePop.AllocateMemory();

                // Allocate some space for noise to seed the cuda_rand generator
                noise       = new MyMemoryBlock <float>();
                noise.Owner = Owner;
                noise.Count = Owner.PopulationSize;
                noise.AllocateMemory();

                // Write some noise to the initial array
                for (int i = 0; i < Owner.PopulationSize; i++)
                {
                    noise.Host[i] = (float)m_rand.NextDouble() * 100000 + (float)m_rand.NextDouble() * 40;
                }
                noise.SafeCopyToDevice();

                // Allocate space for the fitnesses
                fitnesses       = new MyMemoryBlock <float>();
                fitnesses.Owner = Owner;
                fitnesses.Count = Owner.PopulationSize;
                fitnesses.AllocateMemory();


                // Allocate some temporary storage
                tempMB       = new MyMemoryBlock <float>();
                tempPop      = new MyMemoryBlock <float>();
                tempMB.Owner = Owner;
                tempMB.Count = CoefficientsSaved;
                tempMB.AllocateDevice();

                tempPop.Owner = Owner;
                tempPop.Count = arr_size * arr_size;
                tempPop.AllocateDevice();

                marking       = new MyMemoryBlock <int>();
                marking.Owner = Owner;
                marking.Count = CoefficientsSaved * Owner.PopulationSize;
                marking.AllocateDevice();
                #endregion

                // Check saved Coeffs size
                if (CoefficientsSaved > m_weights)
                {
                    MyLog.WARNING.Write("Saving more Coefficients than exist in the weight matrix. Setting to max permissable value\n");
                    CoefficientsSaved = m_weights;
                }

                if (CoefficientsSaved == m_weights)
                {
                    MyLog.INFO.Write("Saving a coefficient for every weight. Evolving weights directly\n");
                    DirectEvolution = true;
                }

                if (DirectEvolution)
                {
                    CoefficientsSaved = m_weights;
                }


                // Generate the rest of the population
                if (DirectEvolution)
                {
                    m_coeffGenKernel.Run(chromosomePop, CoefficientsSaved, noise, Owner.PopulationSize, WeightMagnitude);
                }
                else
                {
                    m_coeffGenKernel.Run(chromosomePop, CoefficientsSaved, noise, Owner.PopulationSize, Alpha);
                }


                //Disable Backprop tasks in Network
                if (nn.GetActiveBackpropTask() != null)
                {
                    if (!nn.GetActiveBackpropTask().DisableLearning)
                    {
                        MyLog.WARNING.WriteLine("Disabling backprop learning for Neural Network");
                        nn.GetActiveBackpropTask().DisableLearning = true;
                    }
                }
            }