//Takes in weights, phi challenges and target response bits, gives average error of APUF model
        public override double ObjFunValue(double[] weightVector, sbyte[][] phiChallenges, sbyte[] targets)
        {
            double error = 0;

            if (AppConstants.UseParallelismOnSingleCMAES == true)
            {
                int           bitNum       = phiChallenges[0].Length - 1;
                double[]      errorArray   = new double[AppConstants.CoreNumber]; //Array for storing errors in parallel
                XORArbiterPUF xModel       = new XORArbiterPUF(bitNum, weightVector);
                int           sampleNumber = phiChallenges.Length;                //Number of challenge-response pairs (number of training samples)

                int blockSize = AppConstants.TrainingSize / AppConstants.CoreNumber;
                Parallel.For(0, AppConstants.CoreNumber, coreIndex =>
                             //for (int coreIndex = 0; coreIndex < AppConstants.CoreNumber; coreIndex++)
                {
                    for (int sampleIndex = coreIndex * blockSize; sampleIndex < (coreIndex + 1) * blockSize; sampleIndex++)
                    {
                        sbyte currentTarget = targets[sampleIndex];
                        sbyte modelOutput   = xModel.ComputeResponse(phiChallenges[sampleIndex]);
                        if (modelOutput != currentTarget)
                        {
                            errorArray[coreIndex]++;
                        }
                        //Console.Out.WriteLine(sampleIndex.ToString());
                    }
                });
                //Time to sum the errors together
                for (int i = 0; i < AppConstants.CoreNumber; i++)
                {
                    error = error + errorArray[i];
                }
                error = error / (double)sampleNumber; //Give the average error
            }
            else if (AppConstants.UseParallelismOnSingleCMAES == false)
            {
                int           bitNum       = phiChallenges[0].Length - 1;
                XORArbiterPUF xModel       = new XORArbiterPUF(bitNum, weightVector);
                int           sampleNumber = phiChallenges.Length; //Number of challenge-response pairs (number of training samples)
                for (int currentSample = 0; currentSample < sampleNumber; currentSample++)
                {
                    sbyte currentTarget = targets[currentSample];
                    sbyte modelOutput   = xModel.ComputeResponse(phiChallenges[currentSample]);
                    if (modelOutput != currentTarget)
                    {
                        error++;
                    }
                }
                error = error / (double)sampleNumber; //Give the average error
            }
            return(error);
        }