/** * Initializes the CMA parameter set for given mu, lambda and a population. The initialSigma * parameter is used as initial sigma directly unless it is <0, in that case the average range is * used as initial sigma. * * @param params the CMA parameter set to be used - its data are overwritten * @param mu ES mu parameter * @param lambda ES lambda parameter * @param pop associated Population * @param initialSigma initial sigma or -1 to indicate the usage of average range * @return */ public static CMAParamSet initCMAParams( CMAParamSet params, int mu, int lambda, double[] center, double[][] range, double initialSigma) { // those are from initialize: params.firstAdaptionDone = false; params.range = range; int dim = params.range.length; params.eigenvalues = new double[dim]; Arrays.fill(params.eigenvalues, 1.); params.meanX = new double[dim]; params.pathC = new double[dim]; params.pathS = new double[dim]; params.mC = Matrix.identity(dim, dim); params.mB = Matrix.identity(dim, dim); // from adaptAfterSel params.weights = initWeights(mu, lambda); double muEff = getMuEff(params.weights, mu); params.c_sig = (muEff + 2) / (muEff + dim + 3); // c_u_sig = Math.sqrt(c_sig * (2.-c_sig)); params.d_sig = params.c_sig + 1 + 2 * Math.max(0, Math.sqrt((muEff - 1) / (dim + 1)) - 1); if (initialSigma < 0) { // this means we scale the average range if (initialSigma != -0.25 && (initialSigma != -0.5)) { EVAERROR.errorMsgOnce("Warning, unexpected initial sigma in CMAParamSet!"); } initialSigma = -initialSigma * Mathematics.getAvgRange(params.range); } if (initialSigma <= 0) { EVAERROR.errorMsgOnce("warning: initial sigma <= zero! Working with converged population?"); initialSigma = 10e-10; } params.sigma = initialSigma; // System.out.println("INitial sigma: "+sigma); params.firstSigma = params.sigma; // System.out.println("new center is " + BeanInspector.toString(center)); params.meanX = center; // this might be ok? return params; }
/** * True if the subswarm is active and all particles are completely converged (i.e. the stddev over * the past 3 iterations is < epsilson) */ @Override public boolean shouldDeactivateSubswarm(ParticleSubSwarmOptimization subswarm) { if (!subswarm.isActive()) { return false; } if (subswarm.getFitnessArchiveSize() < haltingWindow) { EVAERROR.errorMsgOnce( "Warning: halting window length " + haltingWindow + " too long for sub swarm template, which stores only " + subswarm.getFitnessArchiveSize() + " fitness values!"); } return (isConverged(subswarm.getPopulation())); }
private double[] repairMutation(double[] x, double[][] range) { EVAERROR.errorMsgOnce( "Warning, brute-forcing constraints! Too large initial sigma? (pot. multiple errors)"); Mathematics.projectToRange(x, range); return x; }
/** * Perform the main adaption of sigma and C using evolution paths. The evolution path is deduced * from the center of the selected population compared to the old mean value. See Hansen&Kern 04 * for further information. * * @param oldGen * @param selectedP */ public void adaptAfterSelection(Population oldGen, Population selectedP) { Population selectedSorted = selectedP.getSortedBestFirst(new AbstractEAIndividualComparator(-1)); int mu, lambda; mu = selectedP.size(); lambda = oldGen.size(); int generation = oldGen.getGeneration(); if (mu >= lambda) { // try to override by oldGen additional data: if (oldGen.hasData(EvolutionStrategies.esMuParam)) mu = (Integer) oldGen.getData(EvolutionStrategies.esMuParam); if (oldGen.hasData(EvolutionStrategies.esLambdaParam)) lambda = (Integer) oldGen.getData(EvolutionStrategies.esLambdaParam); } if (mu >= lambda) { mu = Math.max(1, lambda / 2); EVAERROR.errorMsgOnce( "Warning: invalid mu/lambda ratio! Setting mu to lambda/2 = " + mu + ", lambda = " + lambda); } CMAParamSet params; if (oldGen.getGeneration() <= 1) { // init new param set. At gen < 1 we shouldnt be called, but better do it once too // often if (oldGen.hasData(cmaParamsKey)) params = CMAParamSet.initCMAParams( (CMAParamSet) oldGen.getData(cmaParamsKey), mu, lambda, oldGen, getInitSigma(oldGen)); else params = CMAParamSet.initCMAParams(mu, lambda, oldGen, getInitSigma(oldGen)); } else { if (!oldGen.hasData(cmaParamsKey)) { if (oldGen.getGeneration() > 1) EVAERROR.errorMsgOnce("Error: population lost cma parameters. Incompatible optimizer?"); params = CMAParamSet.initCMAParams(mu, lambda, oldGen, getInitSigma(oldGen)); } else params = (CMAParamSet) oldGen.getData(cmaParamsKey); } if (lambda == 1 && (oldGen.size() == 1) && (selectedP.size() == 1) && (oldGen.getEAIndividual(0).equals(selectedP.getEAIndividual(0)))) { // nothing really happened, so do not adapt and just store default params lastParams = (CMAParamSet) params.clone(); oldGen.putData(cmaParamsKey, params); selectedP.putData(cmaParamsKey, params); return; } if (TRACE_1) { System.out.println("WCMA adaptGenerational **********"); // System.out.println("newPop measures: " + // BeanInspector.toString(newPop.getPopulationMeasures())); System.out.println("mu_eff: " + CMAParamSet.getMuEff(params.weights, mu)); System.out.println(params.toString()); System.out.println("*********************************"); } double[] newMeanX = calcMeanX(params.weights, selectedSorted); if (TRACE_1) System.out.println("newMeanX: " + BeanInspector.toString(newMeanX)); int dim = params.meanX.length; double[] BDz = new double[dim]; for (int i = 0; i < dim; i++) { /* calculate xmean and BDz~N(0,C) */ // Eq. 4 from HK04, most right term BDz[i] = Math.sqrt(CMAParamSet.getMuEff(params.weights, mu)) * (newMeanX[i] - params.meanX[i]) / getSigma(params, i); } // if (TRACE_2) System.out.println("BDz is " + BeanInspector.toString(BDz)); double[] newPathS = params.pathS.clone(); double[] newPathC = params.pathC.clone(); double[] zVect = new double[dim]; /* calculate z := D^(-1) * B^(-1) * BDz into artmp, we could have stored z instead */ for (int i = 0; i < dim; ++i) { double sum = 0.; for (int j = 0; j < dim; ++j) { sum += params.mB.get(j, i) * BDz[j]; // times B transposed, (Eq 4) in HK04 } if (params.eigenvalues[i] < 0) { EVAERROR.errorMsgOnce( "Warning: negative eigenvalue in MutateESRankMuCMA! (possibly multiple cases)"); zVect[i] = 0; } else { zVect[i] = sum / Math.sqrt(params.eigenvalues[i]); if (!checkValidDouble(zVect[i])) { System.err.println("Error, infinite zVect entry!"); zVect[i] = 0; // TODO MK } } } /* cumulation for sigma (ps) using B*z */ for (int i = 0; i < dim; ++i) { double sum = 0.; for (int j = 0; j < dim; ++j) sum += params.mB.get(i, j) * zVect[j]; newPathS[i] = (1. - params.c_sig) * params.pathS[i] + Math.sqrt(params.c_sig * (2. - params.c_sig)) * sum; if (!checkValidDouble(newPathS[i])) { System.err.println("Error, infinite pathS!"); } } // System.out.println("pathS diff: " + BeanInspector.toString(Mathematics.vvSub(newPathS, // pathS))); // System.out.println("newPathS is " + BeanInspector.toString(newPathS)); double psNorm = Mathematics.norm(newPathS); double hsig = 0; if (psNorm / Math.sqrt(1. - Math.pow(1. - params.c_sig, 2. * generation)) / expRandStepLen < 1.4 + 2. / (dim + 1.)) { hsig = 1; } for (int i = 0; i < dim; ++i) { newPathC[i] = (1. - getCc()) * params.pathC[i] + hsig * Math.sqrt(getCc() * (2. - getCc())) * BDz[i]; checkValidDouble(newPathC[i]); } // TODO missing: "remove momentum in ps" if (TRACE_1) { System.out.println("newPathC: " + BeanInspector.toString(newPathC)); System.out.println("newPathS: " + BeanInspector.toString(newPathS)); } if (TRACE_1) System.out.println("Bef: C is \n" + params.mC.toString()); if (params.meanX == null) params.meanX = newMeanX; updateCov(params, newPathC, newMeanX, hsig, mu, selectedSorted); updateBD(params); if (TRACE_2) System.out.println("Aft: C is " + params.mC.toString()); /* update of sigma */ double sigFact = Math.exp(((psNorm / expRandStepLen) - 1) * params.c_sig / params.d_sig); if (Double.isInfinite(sigFact)) params.sigma *= 10.; // in larger search spaces sigma tends to explode after init. else params.sigma *= sigFact; if (!testAndCorrectNumerics(params, generation, selectedSorted)) { // parameter seemingly exploded... params = CMAParamSet.initCMAParams( params, mu, lambda, params.meanX, ((InterfaceDataTypeDouble) oldGen.getEAIndividual(0)).getDoubleRange(), params.firstSigma); } if (TRACE_1) { System.out.println("sigma=" + params.sigma); System.out.print("psLen=" + (psNorm) + " "); outputParams(params, mu); } // take over data params.meanX = newMeanX; params.pathC = newPathC; params.pathS = newPathS; params.firstAdaptionDone = true; lastParams = (CMAParamSet) params.clone(); oldGen.putData(cmaParamsKey, params); selectedP.putData(cmaParamsKey, params); // if (TRACE_2) System.out.println("sampling around " + BeanInspector.toString(meanX)); }
@Override public void optimize() { // System.out.println("opt. called"); AbstractEAIndividual indy; // if ((this.indyhash == null) || (this.indyhash.size() <1)) initialize(); for (int i = 0; i < this.population.size(); i++) { indy = this.population.get(i); if (!indy.hasData(gradientKey)) { // System.out.println("new indy to hash"); // Hashtable history = new Hashtable(); int[] lock = new int[((InterfaceDataTypeDouble) indy).getDoubleData().length]; double[] wstepsize = new double[((InterfaceDataTypeDouble) indy).getDoubleData().length]; for (int li = 0; li < lock.length; li++) { lock[li] = 0; } for (int li = 0; li < lock.length; li++) { wstepsize[li] = 1.0; } double fitness = 0; indy.putData(lockKey, lock); indy.putData(lastFitnessKey, fitness); indy.putData(stepSizeKey, globalinitstepsize); indy.putData(wStepSizeKey, wstepsize); // indyhash.put(indy, history); } else { // System.out.println("indy already in hash"); } } // System.out.println("hashtable built"); for (int i = 0; i < this.population.size(); i++) { indy = this.population.get(i); double[][] range = ((InterfaceDataTypeDouble) indy).getDoubleRange(); double[] params = ((InterfaceDataTypeDouble) indy).getDoubleData(); indy.putData(oldParamsKey, params); int[] lock = (int[]) indy.getData(lockKey); double indystepsize = (Double) indy.getData(stepSizeKey); if ((this.optimizationProblem instanceof InterfaceFirstOrderDerivableProblem) && (indy instanceof InterfaceDataTypeDouble)) { for (int iterations = 0; iterations < this.iterations; iterations++) { double[] oldgradient = indy.hasData(gradientKey) ? (double[]) indy.getData(gradientKey) : null; double[] wstepsize = (double[]) indy.getData(wStepSizeKey); double[] oldchange = null; double[] gradient = ((InterfaceFirstOrderDerivableProblem) optimizationProblem) .getFirstOrderGradients(params); if ((oldgradient != null) && (wstepsize != null)) { // LOCAL adaption for (int li = 0; li < wstepsize.length; li++) { double prod = gradient[li] * oldgradient[li]; if (prod < 0) { wstepsize[li] = wDecreaseStepSize * wstepsize[li]; } else if (prod > 0) { wstepsize[li] = wIncreaseStepSize * wstepsize[li]; } wstepsize[li] = (wstepsize[li] < localminstepsize) ? localminstepsize : wstepsize[li]; wstepsize[li] = (wstepsize[li] > localmaxstepsize) ? localmaxstepsize : wstepsize[li]; } } double[] newparams = new double[params.length]; indy.putData(gradientKey, gradient); double[] change = new double[params.length]; if (indy.hasData(changesKey)) { oldchange = (double[]) indy.getData(changesKey); } boolean dograddesc = (this.momentumterm) && (oldchange != null); for (int j = 0; j < newparams.length; j++) { if (lock[j] == 0) { double tempstepsize = 1; if (this.localStepSizeAdaption) { tempstepsize *= wstepsize[j]; } if (this.globalStepSizeAdaption) { tempstepsize *= indystepsize; } double wchange = signum(tempstepsize * gradient[j]) * Math.min( maximumabsolutechange, Math.abs(tempstepsize * gradient[j])); // indystepsize * gradient[j]; if (this.manhattan) { wchange = this.signum(wchange) * tempstepsize; } if (dograddesc) { wchange += this.momentumweigth * oldchange[j]; } newparams[j] = params[j] - wchange; if (newparams[j] < range[j][0]) { newparams[j] = range[j][0]; } if (newparams[j] > range[j][1]) { newparams[j] = range[j][1]; } // for (int g = 0; g < newparams.length; g++) { // System.out.println("Param " + g +": " + newparams[g]); // } change[j] += wchange; } else { lock[j]--; } } params = newparams; indy.putData(changesKey, change); } // end loop iterations ((InterfaceDataTypeDouble) indy).setDoubleGenotype(params); } // end if ((this.problem instanceof InterfaceFirstOrderDerivableProblem) && (indy instanceof // InterfaceDataTypeDouble)) { else { String msg = "Warning, problem of type InterfaceFirstOrderDerivableProblem and template of type InterfaceDataTypeDouble is required for " + this.getClass(); EVAERROR.errorMsgOnce(msg); Class<?>[] clsArr = ReflectPackage.getAssignableClasses( InterfaceFirstOrderDerivableProblem.class.getName(), true, true); msg += " (available: "; for (Class<?> cls : clsArr) { msg = msg + " " + cls.getSimpleName(); } msg += ")"; throw new RuntimeException(msg); } } // for loop population size this.optimizationProblem.evaluate(this.population); population.incrGeneration(); if (this.recovery) { for (int i = 0; i < this.population.size(); i++) { indy = this.population.get(i); if (indy.getFitness()[0] > recoverythreshold) { ((InterfaceDataTypeDouble) indy) .setDoublePhenotype((double[]) indy.getData(oldParamsKey)); double[] changes = (double[]) indy.getData(changesKey); int[] lock = (int[]) indy.getData(lockKey); int indexmaxchange = 0; double maxchangeval = Double.NEGATIVE_INFINITY; for (int j = 0; j < changes.length; j++) { if ((changes[j] > maxchangeval) && (lock[j] == 0)) { indexmaxchange = j; maxchangeval = changes[j]; } } lock[indexmaxchange] = recoverylocksteps; indy.putData(lockKey, lock); } else { } } this.optimizationProblem.evaluate(this.population); population.incrGeneration(); } if (this.globalStepSizeAdaption) { // System.out.println("gsa main"); for (int i = 0; i < this.population.size(); i++) { indy = this.population.get(i); if (indy.getData(lastFitnessKey) != null) { double lastfit = (Double) indy.getData(lastFitnessKey); double indystepsize = (Double) indy.getData(stepSizeKey); if (lastfit < indy.getFitness()[0]) { // GLOBAL adaption indystepsize *= wDecreaseStepSize; } else { indystepsize *= wIncreaseStepSize; } indystepsize = (indystepsize > globalmaxstepsize) ? globalmaxstepsize : indystepsize; indystepsize = (indystepsize < globalminstepsize) ? globalminstepsize : indystepsize; indy.putData(stepSizeKey, indystepsize); } indy.putData(lastFitnessKey, indy.getFitness()[0]); } } this.firePropertyChangedEvent(Population.NEXT_GENERATION_PERFORMED); }