private static void _printResult(RegressionResult result) { // a bit of reflection fun, why not... PropertyInfo[] properties = result.GetType().GetProperties(); foreach (PropertyInfo p in properties) { Console.WriteLine(p.Name + ": " + p.GetValue(result, null).ToString()); } }
private static readonly double JITTER = 1e-10d; // a small value used to protect against floating point noise #endregion Fields #region Methods public static RegressionResult Regress(SimplexConstant[] simplexConstants, double convergenceTolerance, int maxEvaluations, ObjectiveFunctionDelegate objectiveFunction) { // confirm that we are in a position to commence if (objectiveFunction == null) throw new InvalidOperationException("ObjectiveFunction must be set to a valid ObjectiveFunctionDelegate"); if (simplexConstants == null) throw new InvalidOperationException("SimplexConstants must be initialized"); #if DEBUG //this is the coniditional compilation symbols in the project property >>build section Console.Write("inside nelder mead regression:"); #endif // create the initial simplex int numDimensions = simplexConstants.Length; int numVertices = numDimensions + 1; #if DEBUG Console.Write("numVertices: {0}", numVertices ); #endif Vector[] vertices = _initializeVertices(simplexConstants); double[] errorValues = new double[numVertices]; int evaluationCount = 0; TerminationReason terminationReason = TerminationReason.Unspecified; ErrorProfile errorProfile; errorValues = _initializeErrorValues(vertices, objectiveFunction); #if DEBUG || LOG_MODE Console.WriteLine("\n=====Start the Nelder-Mead Algorithm for Optimization.........."); #endif // iterate until we converge, or complete our permitted number of iterations while (true) { #if LOG_MODE if (evaluationCount % 100 == 0) { Console.Write("......"+evaluationCount+ "/"+maxEvaluations ); } #endif errorProfile = _evaluateSimplex(errorValues); // see if the range in point heights is small enough to exit if (_hasConverged(convergenceTolerance, errorProfile, errorValues)) { terminationReason = TerminationReason.Converged; break; } #if DEBUG Console.WriteLine("not converged"); #endif // attempt a reflection of the simplex double reflectionPointValue = _tryToScaleSimplex(-1.0, ref errorProfile, vertices, errorValues, objectiveFunction); ++evaluationCount; #if DEBUG Console.WriteLine("Got a reflection point"); #endif if (reflectionPointValue <= errorValues[errorProfile.LowestIndex]) { // it's better than the best point, so attempt an expansion of the simplex double expansionPointValue = _tryToScaleSimplex(2.0, ref errorProfile, vertices, errorValues, objectiveFunction); ++evaluationCount; } else if (reflectionPointValue >= errorValues[errorProfile.NextHighestIndex]) { // it would be worse than the second best point, so attempt a contraction to look // for an intermediate point double currentWorst = errorValues[errorProfile.HighestIndex]; double contractionPointValue = _tryToScaleSimplex(0.5, ref errorProfile, vertices, errorValues, objectiveFunction); ++evaluationCount; if (contractionPointValue >= currentWorst) { // that would be even worse, so let's try to contract uniformly towards the low point; // don't bother to update the error profile, we'll do it at the start of the // next iteration _shrinkSimplex(errorProfile, vertices, errorValues, objectiveFunction); evaluationCount += numVertices; // that required one function evaluation for each vertex; keep track } } // check to see if we have exceeded our alloted number of evaluations if (evaluationCount >= maxEvaluations) { terminationReason = TerminationReason.MaxFunctionEvaluations; break; } } #if LOG_MODE Console.WriteLine("Done!!"); #endif RegressionResult regressionResult = new RegressionResult(terminationReason, vertices[errorProfile.LowestIndex].Components, errorValues[errorProfile.LowestIndex], evaluationCount); return regressionResult; }
private static readonly double JITTER = 1e-10d; // a small value used to protect against floating point noise public static RegressionResult Regress(SimplexConstant[] simplexConstants, double convergenceTolerance, int maxEvaluations, ObjectiveFunctionDelegate objectiveFunction) { // confirm that we are in a position to commence if (objectiveFunction == null) { throw new InvalidOperationException("ObjectiveFunction must be set to a valid ObjectiveFunctionDelegate"); } if (simplexConstants == null) { throw new InvalidOperationException("SimplexConstants must be initialized"); } // create the initial simplex int numDimensions = simplexConstants.Length; int numVertices = numDimensions + 1; Vector[] vertices = _initializeVertices(simplexConstants); double[] errorValues = new double[numVertices]; int evaluationCount = 0; TerminationReason terminationReason = TerminationReason.Unspecified; ErrorProfile errorProfile; errorValues = _initializeErrorValues(vertices, objectiveFunction); // iterate until we converge, or complete our permitted number of iterations while (true) { errorProfile = _evaluateSimplex(errorValues); // see if the range in point heights is small enough to exit if (_hasConverged(convergenceTolerance, errorProfile, errorValues)) { terminationReason = TerminationReason.Converged; break; } // attempt a reflection of the simplex double reflectionPointValue = _tryToScaleSimplex(-1.0, ref errorProfile, vertices, errorValues, objectiveFunction); ++evaluationCount; if (reflectionPointValue <= errorValues[errorProfile.LowestIndex]) { // it's better than the best point, so attempt an expansion of the simplex double expansionPointValue = _tryToScaleSimplex(2.0, ref errorProfile, vertices, errorValues, objectiveFunction); ++evaluationCount; } else if (reflectionPointValue >= errorValues[errorProfile.NextHighestIndex]) { // it would be worse than the second best point, so attempt a contraction to look // for an intermediate point double currentWorst = errorValues[errorProfile.HighestIndex]; double contractionPointValue = _tryToScaleSimplex(0.5, ref errorProfile, vertices, errorValues, objectiveFunction); ++evaluationCount; if (contractionPointValue >= currentWorst) { // that would be even worse, so let's try to contract uniformly towards the low point; // don't bother to update the error profile, we'll do it at the start of the // next iteration _shrinkSimplex(errorProfile, vertices, errorValues, objectiveFunction); evaluationCount += numVertices; // that required one function evaluation for each vertex; keep track } } // check to see if we have exceeded our alloted number of evaluations if (evaluationCount >= maxEvaluations) { terminationReason = TerminationReason.MaxFunctionEvaluations; break; } } RegressionResult regressionResult = new RegressionResult(terminationReason, vertices[errorProfile.LowestIndex].Components, errorValues[errorProfile.LowestIndex], evaluationCount); return(regressionResult); }