//Runs the attack on one PUF model, the cores are used to evaluate the CRPs of one model (in parallel) so the method will run as fast as possible
        public static double ClassicalAttackXORAPUFSingle(int bitNumber, int numXOR)
        {
            //Generate a PUF
            double aPUFMean      = 0.0;
            double aPUFVar       = 1.0;
            double aPUFMeanNoise = 0.0;
            double aPUFNoiseVar  = 0.0;

            //Create the XOR APUF
            XORArbiterPUF xPUF = new XORArbiterPUF(numXOR, bitNumber, aPUFMean, aPUFVar, aPUFMeanNoise, aPUFNoiseVar);

            //Arrays for storing the training data
            sbyte[][] trainingData         = new sbyte[AppConstants.TrainingSize][]; //these will be phi vectors
            sbyte[][] allTrainingResponses = new sbyte[1][];                         //first index PUF, second index sample
            allTrainingResponses[0] = new sbyte[AppConstants.TrainingSize];

            Random[] rGenArray = new Random[AppConstants.CoreNumber];
            for (int i = 0; i < AppConstants.CoreNumber; i++)
            {
                rGenArray[i] = new Random((int)DateTime.Now.Ticks);
                System.Threading.Thread.Sleep(10); //prevent the random number generators from being the same
            }
            DataGeneration.GenerateTrainingDataParallel(xPUF, trainingData, allTrainingResponses, rGenArray);
            Console.Out.WriteLine("Data Generation Complete.");

            //create the objective function for parallel runs
            ObjectiveFunctionResponseXOR rObj = new ObjectiveFunctionResponseXOR();

            //Start the attack run
            var    watch           = System.Diagnostics.Stopwatch.StartNew();
            Random randomGenerator = new Random((int)DateTime.Now.Ticks);;
            int    dimensionNumber = (bitNumber + 1) * xPUF.GetPUFNum(); //the weights of all the XOR APUFs

            sbyte[] trainingResponse = allTrainingResponses[0];
            //Generate the first solution randomly for CMA-ES
            double[] firstSolution = new double[dimensionNumber];
            for (int i = 0; i < firstSolution.Length; i++)
            {
                firstSolution[i] = randomGenerator.NextDouble();
            }
            Console.Out.WriteLine("Beginning CMA-ES");
            //The next line uses maximum parallelism on a single run
            CMAESCandidate solutionCMAES = CMAESMethods.ComputeCMAES(dimensionNumber, rObj, trainingData, trainingResponse, firstSolution, randomGenerator);
            double         solutionVal   = solutionCMAES.GetObjectiveFunctionValue();

            double[] computedSolution = solutionCMAES.GetWeightVector(); //store the solution in independent memory
            Console.Out.WriteLine("CMA-ES finished.");
            watch.Stop();
            Console.Out.WriteLine("Elapsed Time is " + watch.ElapsedMilliseconds.ToString());

            //turn off parallelism
            AppConstants.UseParallelismOnSingleCMAES = false;

            //measure the accuracy
            Random randomGenerator2 = new Random((int)DateTime.Now.Ticks);

            sbyte[][] testingData     = new sbyte[AppConstants.TestingSize][]; //these will be phi vectors
            sbyte[]   testingResponse = new sbyte[AppConstants.TestingSize];
            DataGeneration.GenerateTrainingData(xPUF, testingData, testingResponse, randomGenerator2);
            double accMeasure = rObj.ObjFunValue(computedSolution, testingData, testingResponse);

            Console.Out.WriteLine("The accuracy for the XOR APUF is " + accMeasure.ToString());
            return(accMeasure);
        }