/** Revises the CMA-ES distribution to reflect the current fitness results in the provided subpopulation. */ public void UpdateDistribution(IEvolutionState state, Subpopulation subpop) { // % Sort by fitness and compute weighted mean into xmean // [arfitness, arindex] = sort(arfitness); % minimization // xmean = arx(:,arindex(1:mu))*weights; % recombination % Eq.39 // counteval += lambda; // only need partial sort? ((List <Individual>)subpop.Individuals).Sort(); SimpleMatrixD artmp = new SimpleMatrixD(GenomeSize, mu); SimpleMatrixD xold = xmean; xmean = new SimpleMatrixD(GenomeSize, 1); for (int i = 0; i < mu; i++) { DoubleVectorIndividual dvind = (DoubleVectorIndividual)subpop.Individuals[i]; // won't modify the genome SimpleMatrixD arz = new SimpleMatrixD(GenomeSize, 1, true, dvind.genome); arz = (arz.minus(xold).divide(sigma)); for (int j = 0; j < GenomeSize; j++) { xmean.set(j, 0, xmean.get(j, 0) + weights[i] * dvind.genome[j]); artmp.set(j, i, arz.get(j, 0)); } } // % Cumulation: Update evolution paths SimpleMatrixD y = xmean.minus(xold).divide(sigma); SimpleMatrixD bz = invsqrtC.mult(y); SimpleMatrixD bz_scaled = bz.scale(Math.Sqrt(cs * (2.0 - cs) * mueff)); ps = ps.scale(1.0 - cs).plus(bz_scaled); double h_sigma_value = ((ps.dot(ps) / (1.0 - Math.Pow(1.0 - cs, 2.0 * (state.Generation + 1)))) / GenomeSize); int hsig = (h_sigma_value < (2.0 + (4.0 / (GenomeSize + 1)))) ? 1 : 0; SimpleMatrixD y_scaled = y.scale(hsig * Math.Sqrt(cc * (2.0 - cc) * mueff)); pc = pc.scale(1.0 - cc).plus(y_scaled); // % Adapt covariance matrix C c = c.scale(1.0 - c1 - cmu); c = c.plus(pc.mult(pc.transpose()).plus(c.scale((1.0 - hsig) * cc * (2.0 - cc))).scale(c1)); c = c.plus((artmp.mult(SimpleMatrixD.diag(weights).mult(artmp.transpose()))).scale(cmu)); // % Adapt step-size sigma sigma = sigma * Math.Exp((cs / damps) * (ps.normF() / chiN - 1.0)); // % Update B and D from C if ((state.Generation - lastEigenDecompositionGeneration) > 1.0 / ((c1 + cmu) * GenomeSize * 10.0)) { lastEigenDecompositionGeneration = state.Generation; // make sure the matrix is symmetric (it should be already) // not sure if this is necessary for (int i = 0; i < GenomeSize; i++) { for (int j = 0; j < i; j++) { c.set(j, i, c.get(i, j)); } } // this copy gets modified by the decomposition DMatrixRMaj copy = c.copy().getMatrix(); EigenDecomposition <DMatrixRMaj> eig = DecompositionFactory_DDRM.eig(GenomeSize, true, true); if (eig.decompose(copy)) { SimpleMatrixD dinv = new SimpleMatrixD(GenomeSize, GenomeSize); for (int i = 0; i < GenomeSize; i++) { double eigrt = Math.Sqrt(eig.getEigenValue(i).real); d.set(i, i, eigrt); dinv.set(i, i, 1 / eigrt); CommonOps_DDRM.insert(eig.getEigenVector(i), b.getMatrix(), 0, i); } invsqrtC = b.mult(dinv.mult(b.transpose())); CommonOps_DDRM.mult(b.getMatrix(), d.getMatrix(), bd); } else { state.Output.Fatal("CMA-ES eigendecomposition failed. "); } } CommonOps_DDRM.scale(sigma, bd, sbd); // % Break, if fitness is good enough or condition exceeds 1e14, better termination methods are advisable // if arfitness(1) <= stopfitness || max(D) > 1e7 * min(D) // break; // end if (useAltTermination && CommonOps_DDRM.elementMax(d.diag().getMatrix()) > 1e7 * CommonOps_DDRM.elementMin(d.diag().getMatrix())) { state.Evaluator.SetRunCompleted("CMAESSpecies: Stopped because matrix condition exceeded limit."); } }