public CMAESCandidate(double[] weightIN, sbyte[][] trainingDataIN, sbyte[] targetsIN, PUFObjectiveFunction functionIN)
 {
     //WeightVector = (double[])weightIN.Clone();
     //TrainingData = (double[][])trainingDataIN.Clone();
     //Targets = (double[][])targetsIN.Clone();
     WeightVector     = weightIN;
     TrainingData     = trainingDataIN;
     Targets          = targetsIN;
     FunctionP        = functionIN;
     ObjFunctionValue = FunctionP.ObjFunValue(WeightVector, TrainingData, Targets);
 }
Exemple #2
0
        //standard CMA-ES with maximum parallelization

        public static CMAESCandidate ComputeCMAESBecker(int dimensionNumber, PUFObjectiveFunction pFunction, sbyte[][] trainingData, sbyte[] targets, double[] initialWeightVector, Random randomGenerator)
        {
            int             n     = dimensionNumber + 1; //number of weights + epsilon
            Matrix <double> xMean = Matrix <double> .Build.Dense(n, 1);

            CMAESCandidate c11 = new CMAESCandidate(initialWeightVector, trainingData, targets, pFunction);

            Console.Out.WriteLine("Starting Point Accuracy");
            Console.Out.WriteLine(c11.GetObjectiveFunctionValue().ToString());

            CMAESCandidate globalBestCandidate = null;

            double sigma = 0.5;
            //double stopfitness = 1e-10;
            //double stopfitness = 0.99;
            double stopfitness = double.MaxValue;
            int    stopeval    = AppConstants.MaxIterationNumberCMAES;
            //double stopeval = AppConstants.MaxEvaluations
            //Strategy parameter setting: Selection
            int lambdaVal = (int)(4.0 + Math.Floor(3.0 * Math.Log(n)));  //population size, note lambda keyword reserved by python so lambda->lambdaVal
            //lambdaVal = AppConstants.PopulationSizeCMAES #change by KRM cause I think we need more sampling
            double          mu      = lambdaVal / 2.0;
            Matrix <double> weights = Matrix <double> .Build.Dense((int)mu, 1);  //weights = numpy.matrix(weightsPrime, dtype = float).reshape(mu, 1)

            for (int i = 0; i < (int)mu; i++)
            {
                weights[i, 0] = Math.Log(mu + 0.5) - Math.Log(i + 1); //weights[i, 0] = math.log(mu + 0.5) - math.log((i + 1))#use i+1 instead of i in this case to match matlab indexing
            }
            mu = Math.Floor(mu);
            double sumWeights = 0.0;

            for (int i = 0; i < weights.RowCount; i++)
            {
                sumWeights = sumWeights + weights[i, 0];
            }
            //Divide by the sum
            for (int i = 0; i < weights.RowCount; i++)
            {
                weights[i, 0] = weights[i, 0] / sumWeights;
            }
            //Computation for the mueff variable
            double mueffNum = 0.0;
            double mueffDem = 0.0;

            for (int i = 0; i < weights.RowCount; i++)
            {
                mueffNum = weights[i, 0] + mueffNum;
                mueffDem = weights[i, 0] * weights[i, 0] + mueffDem;
            }
            mueffNum = mueffNum * mueffNum;
            double mueff = mueffNum / mueffDem;

            // Strategy parameter setting: Adaptation
            double cc    = (4.0 + mueff / n) / (n + 4.0 + 2.0 * mueff / n);                                     //#time constant for cumulation for C
            double cs    = (mueff + 2.0) / (n + mueff + 5.0);                                                   //#t-const for cumulation for sigma control
            double c1    = 2.0 / ((n + 1.3) * (n + 1.3) + mueff);                                               //#learning rate for rank-one update of C
            double cmu   = Math.Min(1.0 - c1, 2.0 * (mueff - 2.0 + 1.0 / mueff) / ((n + 2) * (n + 2) + mueff)); //# and for rank-mu update
            double damps = 1.0 + 2.0 * Math.Max(0, Math.Sqrt((mueff - 1) / (n + 1)) - 1) + cs;                  //# damping for sigma

            //Initialize dynamic (internal) strategy parameters and constants
            //evolution paths for C and sigma
            Matrix <double> pc = Matrix <double> .Build.Dense(n, 1);

            Matrix <double> ps = Matrix <double> .Build.Dense(n, 1);

            Matrix <double> D = Matrix <double> .Build.Dense(n, 1);

            for (int i = 0; i < n; i++)
            {
                pc[i, 0] = 0;
                ps[i, 0] = 0;
                D[i, 0]  = 1.0;
            }
            //Create B Matrix
            Matrix <double> B = Matrix <double> .Build.Dense(n, n);

            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    if (i == j)
                    {
                        B[i, j] = 1.0;
                    }
                    else
                    {
                        B[i, j] = 0.0;
                    }
                }
            }
            //Create C Matrix
            Matrix <double> dSquare = Matrix <double> .Build.Dense(n, 1);

            for (int i = 0; i < n; i++)
            {
                dSquare[i, 0] = D[i, 0] * D[i, 0];
            }
            Matrix <double> C = B * Diagonalize1DMatrix(dSquare) * B.Transpose(); //C = B * self.diag(DSquare) * numpy.transpose(B)
            //Create invertsqrtC Matrix
            Matrix <double> oneOverD = Matrix <double> .Build.Dense(n, 1);

            for (int i = 0; i < n; i++)
            {
                oneOverD[i, 0] = 1.0 / D[i, 0];
            }
            Matrix <double> invsqrtC  = B * Diagonalize1DMatrix(oneOverD) * B.Transpose();
            double          eigeneval = 0; //track update of B and D
            double          chiN      = Math.Pow(n, 0.5) * (1.0 - 1.0 / (4.0 * n) + 1.0 / (21.0 * Math.Pow(n, 2.0)));
            int             counteval = 0;

            //the next 40 lines contain the 20 lines of interesting code
            //CMAESCandidate[] candidateArray = new CMAESCandidate[lambdaVal];
            List <CMAESCandidate> candidateArray = new List <CMAESCandidate>();

            for (int i = 0; i < lambdaVal; i++)
            {
                candidateArray.Add(new CMAESCandidate());
            }

            while (counteval < stopeval)
            {
                Matrix <double> arx = Matrix <double> .Build.Dense(n, lambdaVal);

                //fill in the initial solutions
                for (int i = 0; i < lambdaVal; i++)
                {
                    Matrix <double> randD = Matrix <double> .Build.Dense(n, 1);

                    for (int j = 0; j < n; j++)
                    {
                        randD[j, 0] = D[j, 0] * GenerateRandomNormalVariableForCMAES(randomGenerator, 0, 1.0);
                    }
                    Matrix <double> inputVector      = xMean + sigma * B * randD;
                    double[]        tempWeightVector = new double[inputVector.RowCount];
                    for (int k = 0; k < inputVector.RowCount; k++)
                    {
                        tempWeightVector[k] = inputVector[k, 0];
                    }
                    candidateArray[i] = new CMAESCandidate(tempWeightVector, trainingData, targets, pFunction);
                    counteval         = counteval + 1;
                }
                candidateArray.Sort(); //This maybe problematic, not sure about sorting in C#
                candidateArray.Reverse();
                Matrix <double> xOld = xMean.Clone();
                //Get the new mean value
                Matrix <double> arxSubset = Matrix <double> .Build.Dense(n, (int)mu); //in Maltab this variable would be "arx(:,arindex(1:mu))

                //This replaces line  arxSubset[:, i] = CandidateList[i].InputVector
                for (int i = 0; i < mu; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        arxSubset[j, i] = candidateArray[i].GetWeightVector()[j];
                    }
                }
                xMean = arxSubset * weights; //Line 76 Matlab
                //Cumulation: Update evolution paths
                ps = (1 - cs) * ps + Math.Sqrt(cs * (2.0 - cs) * mueff) * invsqrtC * (xMean - xOld) / sigma;
                //Compute ps.^2 equivalent
                double psSquare = 0;
                for (int i = 0; i < ps.RowCount; i++)
                {
                    psSquare = psSquare + ps[i, 0] * ps[i, 0];
                }

                //Compute hsig
                double hSig         = 0.0;
                double term1ForHsig = psSquare / (1.0 - Math.Pow(1.0 - cs, 2.0 * counteval / lambdaVal)) / n;
                double term2ForHsig = 2.0 + 4.0 / (n + 1.0);
                if (term1ForHsig < term2ForHsig)
                {
                    hSig = 1.0;
                }
                //Compute pc, Line 82 Matlab
                pc = (1.0 - cc) * pc + hSig * Math.Sqrt(cc * (2.0 - cc) * mueff) * (xMean - xOld) / sigma;
                //Adapt covariance matrix C
                Matrix <double> repmatMatrix = Tile((int)mu, xOld); //NOT SURE IF THIS IS RIGHT IN C# FIX repmatMatrix = numpy.tile(xold, mu)
                Matrix <double> artmp        = (1.0 / sigma) * (arxSubset - repmatMatrix);
                // C = (1-c1-cmu) * C  + c1 * (pc * pc' + (1-hsig) * cc*(2-cc) * C) + cmu * artmp * diag(weights) * artmp' #This is the original Matlab line for reference
                C = (1.0 - c1 - cmu) * C + c1 * (pc * pc.Transpose() + (1 - hSig) * cc * (2.0 - cc) * C) + cmu * artmp * Diagonalize1DMatrix(weights) * artmp.Transpose();
                //Adapt step size sigma
                //sigma = sigma * Math.Exp((cs / damps) * (numpy.linalg.norm(ps) / chiN - 1))
                sigma = sigma * Math.Exp((cs / damps) * (ps.L2Norm() / chiN - 1)); //NOT SURE IF THIS IS RIGHT FIX IN C#
                //Update B and D from C
                if ((counteval - eigeneval) > (lambdaVal / (c1 + cmu) / n / 10.0))
                {
                    eigeneval = counteval;
                    //C = numpy.triu(C) + numpy.transpose(numpy.triu(C, 1)) #enforce symmetry
                    C = C.UpperTriangle() + C.StrictlyUpperTriangle().Transpose(); //NOT SURE IF THIS IS RIGHT FIX IN C#

                    //eigen decomposition
                    Evd <double> eigen = C.Evd();
                    B = eigen.EigenVectors;
                    Vector <System.Numerics.Complex> vectorEigenValues = eigen.EigenValues;
                    for (int i = 0; i < vectorEigenValues.Count; i++)
                    {
                        D[i, 0] = vectorEigenValues[i].Real;
                    }
                    //take sqrt of D
                    for (int i = 0; i < vectorEigenValues.Count; i++)
                    {
                        D[i, 0] = Math.Sqrt(D[i, 0]);
                    }

                    for (int i = 0; i < n; i++)
                    {
                        oneOverD[i, 0] = 1.0 / D[i, 0];
                    }
                    Matrix <double> middleTerm = Diagonalize1DMatrix(oneOverD); //#Built in Numpy function doesn't create the right size matrix in this case (ex: Numpy gives 1x1 but should be 5x5)
                    invsqrtC = B * middleTerm * B.Transpose();
                }

                globalBestCandidate = candidateArray[0];
                //Termination Conditions
                //bestCandidate = candidateArray[0]; //Array index 0 has the smallest objective function value
                //if (bestCandidate.GetObjectiveFunctionValue() < currentBestValue)
                //{
                //    currentBestValue = bestCandidate.GetObjectiveFunctionValue();
                //    globalBestCandidate = (CMAESCandidate)bestCandidate.Clone();
                //}
                //if (bestCandidate.GetObjectiveFunctionValue() >= stopfitness)
                //{
                //    return globalBestCandidate;
                //}

                //Add in extra termination conditions
                //if (bestCandidate.GetObjectiveFunctionValue() == currentBestValue)
                //{
                //    repeatCount = repeatCount + 1;

                //}
                //else
                //{
                //    repeatCount = 0;
                //}
                ////we have repeated too many times
                //if (repeatCount > 10)
                //{
                //    Console.Out.WriteLine("CMA-ES terminated to due to repeated best.");
                //    return globalBestCandidate;
                //}
                Console.Out.WriteLine("Iteration #" + counteval.ToString());
                //Console.Out.WriteLine("Best Value=" + (1.0 - currentBestValue).ToString());
                Console.Out.WriteLine("Current Value=" + (candidateArray[candidateArray.Count - 1].GetObjectiveFunctionValue()).ToString());
            }//end while loop
            return(globalBestCandidate); //just in case everything terminates
        }
Exemple #3
0
        //Run the CMA-ES from a recovered file
        public static CMAESCandidate RecoveredCMAES(Random randomGenerator, int coreNumberForSaving, PUFObjectiveFunction pFunction, InvariantData invData, VariantData varData)
        {
            double stopFitness = 0.98;
            //non-specific variables (used by each core)
            int stopeval = invData.GetMaxEval();

            sbyte[][] trainingData = invData.GetTrainingData();
            sbyte[]   targets      = invData.GetTrainingResponseForPUF(coreNumberForSaving);

            //core specific variables (specific to each run of CMA-ES)
            int             counteval           = varData.GetCurrentEval();
            int             n                   = varData.GetDimensionNum();
            int             lambdaVal           = varData.GetLambda();
            Matrix <double> xMean               = varData.GetXMean();
            Matrix <double> D                   = varData.GetD();
            Matrix <double> B                   = varData.GetB();
            double          sigma               = varData.GetSigma();
            Matrix <double> weights             = varData.GetWeights();
            Matrix <double> ps                  = varData.GetPS();
            double          cs                  = varData.GetCS();
            double          mueff               = varData.GetMueff();
            double          cc                  = varData.GetCC();
            Matrix <double> pc                  = varData.GetPC();
            Matrix <double> invsqrtC            = varData.GetInvSqrtC();
            Matrix <double> C                   = varData.GetMatrixC();
            double          mu                  = varData.GetMu();
            double          c1                  = varData.GetC1();
            double          cmu                 = varData.GetCmu();
            double          damps               = varData.GetDamps();
            double          chiN                = varData.GetChiN();
            double          eigeneval           = varData.GetEigenVal();
            CMAESCandidate  globalBestCandidate = varData.GetGlobalBest();

            Matrix <double> oneOverD = Matrix <double> .Build.Dense(n, 1); //Don't need to copy this because we get it from D

            //just a sanity check
            if (varData.coreNumber != coreNumberForSaving)
            {
                throw new Exception("The saved core number and current core number don't match.");
            }

            //the next 40 lines contain the 20 lines of interesting code
            //CMAESCandidate[] candidateArray = new CMAESCandidate[lambdaVal];
            List <CMAESCandidate> candidateArray = new List <CMAESCandidate>();

            for (int i = 0; i < lambdaVal; i++)
            {
                candidateArray.Add(new CMAESCandidate());
            }

            while (counteval < stopeval)
            {
                Matrix <double> arx = Matrix <double> .Build.Dense(n, lambdaVal);

                //fill in the initial solutions
                for (int i = 0; i < lambdaVal; i++)
                {
                    Matrix <double> randD = Matrix <double> .Build.Dense(n, 1);

                    for (int j = 0; j < n; j++)
                    {
                        randD[j, 0] = D[j, 0] * GenerateRandomNormalVariableForCMAES(randomGenerator, 0, 1.0);
                    }
                    Matrix <double> inputVector      = xMean + sigma * B * randD;
                    double[]        tempWeightVector = new double[inputVector.RowCount];
                    for (int k = 0; k < inputVector.RowCount; k++)
                    {
                        tempWeightVector[k] = inputVector[k, 0];
                    }
                    candidateArray[i] = new CMAESCandidate(tempWeightVector, trainingData, targets, pFunction);
                    counteval         = counteval + 1;
                }
                candidateArray.Sort(); //This maybe problematic, not sure about sorting in C#
                candidateArray.Reverse();
                Matrix <double> xOld = xMean.Clone();
                //Get the new mean value
                Matrix <double> arxSubset = Matrix <double> .Build.Dense(n, (int)mu); //in Maltab this variable would be "arx(:,arindex(1:mu))

                //This replaces line  arxSubset[:, i] = CandidateList[i].InputVector
                for (int i = 0; i < mu; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        arxSubset[j, i] = candidateArray[i].GetWeightVector()[j];
                    }
                }
                xMean = arxSubset * weights; //Line 76 Matlab
                //Cumulation: Update evolution paths
                ps = (1 - cs) * ps + Math.Sqrt(cs * (2.0 - cs) * mueff) * invsqrtC * (xMean - xOld) / sigma;
                //Compute ps.^2 equivalent
                double psSquare = 0;
                for (int i = 0; i < ps.RowCount; i++)
                {
                    psSquare = psSquare + ps[i, 0] * ps[i, 0];
                }

                //Compute hsig
                double hSig         = 0.0;
                double term1ForHsig = psSquare / (1.0 - Math.Pow(1.0 - cs, 2.0 * counteval / lambdaVal)) / n;
                double term2ForHsig = 2.0 + 4.0 / (n + 1.0);
                if (term1ForHsig < term2ForHsig)
                {
                    hSig = 1.0;
                }
                //Compute pc, Line 82 Matlab
                pc = (1.0 - cc) * pc + hSig * Math.Sqrt(cc * (2.0 - cc) * mueff) * (xMean - xOld) / sigma;
                //Adapt covariance matrix C
                Matrix <double> repmatMatrix = Tile((int)mu, xOld); //NOT SURE IF THIS IS RIGHT IN C# FIX repmatMatrix = numpy.tile(xold, mu)
                Matrix <double> artmp        = (1.0 / sigma) * (arxSubset - repmatMatrix);
                // C = (1-c1-cmu) * C  + c1 * (pc * pc' + (1-hsig) * cc*(2-cc) * C) + cmu * artmp * diag(weights) * artmp' #This is the original Matlab line for reference
                C = (1.0 - c1 - cmu) * C + c1 * (pc * pc.Transpose() + (1 - hSig) * cc * (2.0 - cc) * C) + cmu * artmp * Diagonalize1DMatrix(weights) * artmp.Transpose();
                //Adapt step size sigma
                //sigma = sigma * Math.Exp((cs / damps) * (numpy.linalg.norm(ps) / chiN - 1))
                sigma = sigma * Math.Exp((cs / damps) * (ps.L2Norm() / chiN - 1)); //NOT SURE IF THIS IS RIGHT FIX IN C#
                //Update B and D from C
                if ((counteval - eigeneval) > (lambdaVal / (c1 + cmu) / n / 10.0))
                {
                    eigeneval = counteval;
                    //C = numpy.triu(C) + numpy.transpose(numpy.triu(C, 1)) #enforce symmetry
                    C = C.UpperTriangle() + C.StrictlyUpperTriangle().Transpose(); //NOT SURE IF THIS IS RIGHT FIX IN C#

                    //eigen decomposition
                    Evd <double> eigen = C.Evd();
                    B = eigen.EigenVectors;
                    Vector <System.Numerics.Complex> vectorEigenValues = eigen.EigenValues;
                    for (int i = 0; i < vectorEigenValues.Count; i++)
                    {
                        D[i, 0] = vectorEigenValues[i].Real;
                    }
                    //take sqrt of D
                    for (int i = 0; i < vectorEigenValues.Count; i++)
                    {
                        D[i, 0] = Math.Sqrt(D[i, 0]);
                    }

                    for (int i = 0; i < n; i++)
                    {
                        oneOverD[i, 0] = 1.0 / D[i, 0];
                    }
                    Matrix <double> middleTerm = Diagonalize1DMatrix(oneOverD); //#Built in Numpy function doesn't create the right size matrix in this case (ex: Numpy gives 1x1 but should be 5x5)
                    invsqrtC = B * middleTerm * B.Transpose();
                }

                globalBestCandidate = candidateArray[0];
                //Stopping condition
                if (globalBestCandidate.GetObjectiveFunctionValue() > stopFitness)
                {
                    return(globalBestCandidate);
                }

                //Time to save the state
                VariantData     varDataUpdated = new VariantData(coreNumberForSaving, counteval, n, lambdaVal, xMean, D, B, sigma, weights, ps, cs, mueff, cc, invsqrtC, C, mu, pc, c1, cmu, damps, chiN, eigeneval, globalBestCandidate);
                string          fname          = AppConstants.SaveDir + counteval.ToString() + "VariantData" + coreNumberForSaving.ToString();
                FileInfo        fi             = new FileInfo(fname);
                Stream          str            = fi.Open(FileMode.OpenOrCreate, FileAccess.Write);
                BinaryFormatter bf             = new BinaryFormatter();
                bf.Serialize(str, varDataUpdated);
                str.Close();

                Console.Out.WriteLine("Iteration #" + counteval.ToString());
                Console.Out.WriteLine("Current Value=" + (candidateArray[candidateArray.Count - 1].GetObjectiveFunctionValue()).ToString());
            }//end while loop
            return(globalBestCandidate); //just in case everything terminates
        }