/// <summary> /// Construct a function regression evaluator with the provided parameter sampling info and function to regress. /// </summary> public FnRegressionEvaluator(IFunction fn, ParamSamplingInfo paramSamplingInfo, double gradientMseWeight, IBlackBoxProbe blackBoxProbe) { _paramSamplingInfo = paramSamplingInfo; _gradientMseWeight = gradientMseWeight; _yMseWeight = 1.0 - gradientMseWeight; _blackBoxProbe = blackBoxProbe; // Predetermine target responses. int sampleCount = _paramSamplingInfo._sampleCount; _yArrTarget = new double[sampleCount]; _gradientArrTarget = new double[sampleCount]; FunctionProbe fnProbe = new FunctionProbe(paramSamplingInfo); fnProbe.Probe(fn, _yArrTarget); FnRegressionUtils.CalcGradients(paramSamplingInfo, _yArrTarget, _gradientArrTarget); }
/// <summary> /// Evaluate the provided IBlackBox against the XOR problem domain and return its fitness score. /// </summary> public FitnessInfo Evaluate(IBlackBox box) { int sampleCount = _paramSamplingInfo._sampleCount; // TODO: We can avoid a memory allocation here by allocating at construction time, but this requires modification of // ParallelGenomeListEvaluator to utilise multiple evaluators (one per thread). double[] yArr = new double[sampleCount]; double[] gradientArr = new double[sampleCount]; // Probe the black box over the full range of the input parameter. _blackBoxProbe.Probe(box, yArr); // Calc gradients. FnRegressionUtils.CalcGradients(_paramSamplingInfo, yArr, gradientArr); // Calc y position mean squared error (MSE), and apply weighting. double yMse = FnRegressionUtils.CalcMeanSquaredError(yArr, _yArrTarget); yMse *= _yMseWeight; // Calc gradient mean squared error. double gradientMse = FnRegressionUtils.CalcMeanSquaredError(gradientArr, _gradientArrTarget); gradientMse *= _gradientMseWeight; // Calc fitness as the inverse of MSE (higher value is fitter). // Add a constant to avoid divide by zero, and to constrain the fitness range between bad and good solutions; // this allows the selection strategy to select solutions that are mediocre and therefore helps preserve diversity. double fitness = 20.0 / (yMse + gradientMse + 0.02); // Test for stopping condition (near perfect response). if (fitness >= 100000.0) { _stopConditionSatisfied = true; } _evalCount++; return(new FitnessInfo(fitness, fitness)); }