private double[] mutate(CMAParamSet params, double[] x, double[][] range, int count) { int dim = range.length; if (!Mathematics.isInRange(params.meanX, range)) { // TODO Im not sure why this can happen... System.err.println("Error in MutateESRankMuCMA.mutate !"); Mathematics.projectToRange(params.meanX, range); } // System.out.println("--- In mutate!"); if (params != null && (params.firstAdaptionDone)) { double[] sampl = new double[dim]; // generate scaled random vector (D * z) for (int i = 0; i < dim; ++i) { sampl[i] = Math.sqrt(params.eigenvalues[i]) * RNG.gaussianDouble(1.); if (Double.isNaN(sampl[i])) sampl[i] = 0; } // System.out.println("Sampling around " + BeanInspector.toString(meanX)); /* add mutation (sigma * B * (D*z)) */ addMutationStep(params, x, sampl); int cnt = 0; while (!Mathematics.isInRange(x, range)) { // % You may handle constraints here. You may either resample // % arz(:,k) and/or multiply it with a factor between -1 and 1 // % (the latter will decrease the overall step size) and // % recalculate arx accordingly. Do not change arx or arz in any // % other way. // multiply sampl by a no in [-1,1] and try again double r; // actually we use [-1,-0.5] or [0.5, 1] cnt++; if (cnt > 10 * x.length) { // well... lets give it up. Probably the meanX is close to the bounds in several // dimensions // which is unlikely to be solved by random sampling. // if (!Mathematics.isInRange(params.meanX, range)) { // System.err.println("Error in MutateESRankMuCMA.mutate !"); break; // } r = 0; } else { r = RNG.randomDouble(-0.5, 0.5); if (Math.abs(r) < 0.5) r += Math.signum(r) * 0.5; // r is in [-1,-0.5] or [0.5,1] } // System.out.println("Reducing step by " + r + " for " + // BeanInspector.toString(params.meanX)); Mathematics.svMult(r, sampl, sampl); addMutationStep(params, x, sampl); } } else { if (params == null) { System.err.println( "Error in MutateESRankMuCMA: parameter set was null! Skipping mutation..."); } // no valid meanX yet, so just do a gaussian jump with sigma for (int i = 0; i < dim; ++i) { x[i] += RNG.gaussianDouble(getSigma(params, i)); checkValidDouble(x[i]); } } if (!Mathematics.isInRange(params.meanX, range)) { System.err.println("Error B in MutateESRankMuCMA.mutate !"); } if (TRACE_1) System.out.println("mutated indy: " + BeanInspector.toString(x)); return x; }
private double[] mutateOrig(CMAParamSet params, double[] x, double[][] range, int count) { int dim = range.length; int maxRetries; if (checkRange) maxRetries = 100 * dim; else maxRetries = 0; // take the first sample, not matter in or out of range do { // this is a loop in case that the range needs to be checked and the current sampling fails // to keep the range if (params != null && (params.firstAdaptionDone)) { double[] sampl = new double[dim]; // generate scaled random vector (D * z) for (int i = 0; i < dim; ++i) { sampl[i] = Math.sqrt(params.eigenvalues[i]) * RNG.gaussianDouble(1.); if (Double.isNaN(sampl[i])) sampl[i] = 0; } // System.out.println("Sampling around " + BeanInspector.toString(meanX)); /* add mutation (sigma * B * (D*z)) */ for (int i = 0; i < dim; ++i) { double sum = 0.; for (int j = 0; j < dim; ++j) sum += params.mB.get(i, j) * sampl[j]; x[i] = params.meanX[i] + getSigma(params, i) * sum; checkValidDouble(x[i]); } } else { if (params == null) { System.err.println( "Error in MutateESRankMuCMA: parameter set was null! Skipping mutation..."); } // no valid meanX yet, so just do a gaussian jump with sigma for (int i = 0; i < dim; ++i) { x[i] += RNG.gaussianDouble(getSigma(params, i)); checkValidDouble(x[i]); } } } while ((maxRetries--) > 0 && !(Mathematics.isInRange(x, range))); if (checkRange && !(Mathematics.isInRange(x, range))) return repairMutation(x, range); // allow some nice tries before using brute force else return x; }