/// <summary> /// Find value x that minimizes the scalar function f(x), constrained within bounds, using the Golden Section algorithm. /// For more options and diagnostics consider to use <see cref="GoldenSectionMinimizer"/> directly. /// </summary> public static double OfScalarFunctionConstrained(Func <double, double> function, double lowerBound, double upperBound, double tolerance = 1e-5, int maxIterations = 1000) { var objective = ObjectiveFunction.ScalarValue(function); var result = GoldenSectionMinimizer.Minimum(objective, lowerBound, upperBound, tolerance, maxIterations); return(result.MinimizingPoint); }
public void Test_Works() { var algorithm = new GoldenSectionMinimizer(1e-5, 1000); var f1 = new Func <double, double>(x => (x - 3) * (x - 3)); var obj = ObjectiveFunction.ScalarValue(f1); var r1 = GoldenSectionMinimizer.Minimum(obj, -100, 100); Assert.That(Math.Abs(r1.MinimizingPoint - 3.0), Is.LessThan(1e-4)); }
// try this for multiparameter optimization: https://numerics.mathdotnet.com/api/MathNet.Numerics.Optimization.TrustRegion/index.htm // Golden Section Minimizer public static Value Argmin(Value function, Value lowerBound, Value upperBound, Value tolerance, Netlist netlist, Style style, int s) { if (!(lowerBound is NumberValue) || !(upperBound is NumberValue)) { throw new Error("argmin: expecting numbers for lower and upper bounds"); } double lower = (lowerBound as NumberValue).value; double upper = (upperBound as NumberValue).value; if (lower > upper) { throw new Error("argmin: lower bound greater than upper bound"); } if (!(function is FunctionValue)) { throw new Error("argmin: expecting a function as first argument"); } FunctionValue closure = function as FunctionValue; if (closure.parameters.parameters.Count != 1) { throw new Error("argmin: initial values and function parameters have different lengths"); } IScalarObjectiveFunction objectiveFunction = ObjectiveFunction.ScalarValue( (double parameter) => { List <Value> arguments = new List <Value>(); arguments.Add(new NumberValue(parameter)); bool autoContinue = netlist.autoContinue; netlist.autoContinue = true; Value result = closure.ApplyReject(arguments, netlist, style, s); if (result == null) { throw new Error("Objective function returned null"); } netlist.autoContinue = autoContinue; if (!(result is NumberValue)) { throw new Error("Objective function must return a number, not: " + result.Format(style)); } KGui.gui.GuiOutputAppendText("argmin: parameter=" + Style.FormatSequence(arguments, ", ", x => x.Format(style)) + " => cost=" + result.Format(style) + Environment.NewLine); return((result as NumberValue).value); }); try { ScalarMinimizationResult result = GoldenSectionMinimizer.Minimum(objectiveFunction, lower, upper); if (result.ReasonForExit == ExitCondition.Converged || result.ReasonForExit == ExitCondition.BoundTolerance) { KGui.gui.GuiOutputAppendText("argmin: converged with parameter=" + result.MinimizingPoint + " and reason '" + result.ReasonForExit + "'" + Environment.NewLine); return(new NumberValue(result.MinimizingPoint)); } else { throw new Error("reason '" + result.ReasonForExit.ToString() + "'"); } } catch (Exception e) { throw new Error("argmin ended: " + ((e.InnerException == null) ? e.Message : e.InnerException.Message)); } // somehow we need to recatch the inner exception coming from CostAndGradient }
/// <summary> /// 只有一个参数时的拟合方法 /// </summary> public double[] ScalarHuberLossSolver() { var f1 = new Func <double, double>(ScalarHuberLoss); var obj = ObjectiveFunction.ScalarValue(f1); var r1 = GoldenSectionMinimizer.Minimum(obj, -10, 10); var theta1 = r1.MinimizingPoint; Console.WriteLine("theta1 = " + theta1);//最小时的 x 值 -> theta1 Console.WriteLine("Minimum Loss = " + ScalarHuberLoss(theta1)); scalarPred = new double[_xArr.Length]; for (var i = 0; i < _xArr.Length; i++) { //输出预测的y值 scalarPred[i] = theta1 * _xArr[i]; } return(scalarPred); }