package bsearch.space; import org.nlogo.util.MersenneTwisterFast; /** characterizes a parameter that has a continuous (floating point) range on the interval [A,B) */ public strictfp class DoubleContinuousSpec extends ParameterSpec { private double dMin; private double dMax; public DoubleContinuousSpec(String name, double min, double max) { super(name); this.dMin = min; this.dMax = max; } public double getMin() { return dMin; } public double getMax() { return dMax; } public double enforceValidRange(double d) { if (d < dMin) return dMin; else if (d > dMax) return dMax; else return d; } @Override public Double generateRandomValue(MersenneTwisterFast rng) { return rng.nextDouble() * (dMax - dMin) + dMin; } /** * @param obj - Double - parameter value to be mutated * @param mutStrength - controls the magnitude of the Gaussian mutation. * (not to be confused with the mutation-rate, which controls the likelihood of mutation). For example, mutStrength=0.1 corresponds to a stdDev of 10% of the parameter's range This means that 68% of the time, the mutation will fall within +/- 10% and 95% of the time, the mutation will fall within +/- 20%. * @param rng - random number generator * @returns the result of adding Gaussian noise to the given parameter value, clamped to this parameter's min/max range. */ @Override public Double mutate(Object obj, double mutStrength, MersenneTwisterFast rng) { double mutStdDev = (dMax - dMin) * mutStrength; return enforceValidRange((Double)obj + mutStdDev * rng.nextGaussian()); } /** * Since this is a continuous real-valued representation, the size of the search space * becomes nearly infinite. For now, we use the special value -1 for this case. */ @Override public int choiceCount() { return -1 ; } @Override public String toString() { return "[ \"" + name + "\" [ " + dMin + " \"C\" " + dMax + " ]]"; } @Override public Object getValueFromChoice(long choice, long maxNumChoices) { return dMin + (dMax - dMin) * choice / (maxNumChoices - 1); } @Override public long getChoiceIndexFromValue(Object val, long maxNumChoices) { if (!(val instanceof Number)) { throw new IllegalStateException("Type mismatch: can't represent a non-number using this double-valued parameter specification."); } double dVal = ((Number) val).doubleValue(); return (long) StrictMath.round((dVal - dMin) * (maxNumChoices - 1) / (dMax - dMin)); } }