public void NoRoot() { Func <double, double> f1 = x => x * x + 4; Func <double, double> df1 = x => 2 * x; Assert.That(() => RobustNewtonRaphson.FindRoot(f1, df1, -5, 5, 1e-14, 50, 20), Throws.TypeOf <NonConvergenceException>()); }
public void Pole() { Func <double, double> f1 = x => 1 / (x - 2) + 2; Func <double, double> df1 = x => - 1 / (x * x - 4 * x + 4); Assert.AreEqual(1.5, RobustNewtonRaphson.FindRoot(f1, df1, 1, 2, 1e-14, 100, 20)); Assert.AreEqual(1.5, RobustNewtonRaphson.FindRoot(f1, df1, 1, 6, 1e-14, 100, 20)); Assert.AreEqual(1.5, FindRoots.OfFunctionDerivative(f1, df1, 1, 6)); Func <double, double> f2 = x => - 1 / (x - 2) + 2; Func <double, double> df2 = x => 1 / (x * x - 4 * x + 4); Assert.AreEqual(2.5, RobustNewtonRaphson.FindRoot(f2, df2, 2, 3, 1e-14, 100, 20)); Assert.AreEqual(2.5, RobustNewtonRaphson.FindRoot(f2, df2, -2, 3, 1e-14, 100, 20)); Assert.AreEqual(2.5, FindRoots.OfFunctionDerivative(f2, df2, -2, 3)); Func <double, double> f3 = x => 1 / (x - 2) + x + 2; Func <double, double> df3 = x => - 1 / (x * x - 4 * x + 4) + 1; Assert.AreEqual(-Constants.Sqrt3, RobustNewtonRaphson.FindRoot(f3, df3, -2, -1, 1e-14, 100, 20), 1e-14); Assert.AreEqual(Constants.Sqrt3, RobustNewtonRaphson.FindRoot(f3, df3, 1, 1.99, 1e-14, 100, 20)); Assert.AreEqual(Constants.Sqrt3, RobustNewtonRaphson.FindRoot(f3, df3, -1.5, 1.99, 1e-14, 100, 20)); Assert.AreEqual(Constants.Sqrt3, RobustNewtonRaphson.FindRoot(f3, df3, 1, 6, 1e-14, 100, 20)); Func <double, double> f4 = x => 1 / (2 - x) - x + 6; Func <double, double> df4 = x => 1 / (x * x - 4 * x + 4) - 1; Assert.AreEqual(4 + Constants.Sqrt3, RobustNewtonRaphson.FindRoot(f4, df4, 5, 6, 1e-14, 100, 20), 1e-14); Assert.AreEqual(4 - Constants.Sqrt3, RobustNewtonRaphson.FindRoot(f4, df4, 2.01, 3, 1e-14, 100, 20)); Assert.AreEqual(4 - Constants.Sqrt3, RobustNewtonRaphson.FindRoot(f4, df4, 2.01, 5, 1e-14, 100, 20)); Assert.AreEqual(4 - Constants.Sqrt3, RobustNewtonRaphson.FindRoot(f4, df4, -2, 4, 1e-14, 100, 20)); }
public double IV(OptionContractType optionType, double S, double K, double T, double r, double q, double optionMarketPrice) { Func <double, double> f = sigma => Premium(optionType, S, K, T, sigma, r, q) - optionMarketPrice; Func <double, double> df = sigma => Vega(S, K, T, sigma, r, q); return(RobustNewtonRaphson.FindRoot(f, df, lowerBound: 0, upperBound: 100, accuracy: 0.001)); }
public void LocalMinima() { Func <double, double> f1 = x => x * x * x - 2 * x + 2; Func <double, double> df1 = x => 3 * x * x - 2; Assert.AreEqual(0, f1(RobustNewtonRaphson.FindRoot(f1, df1, -5, 5, 1e-14, 100, 20))); Assert.AreEqual(0, f1(RobustNewtonRaphson.FindRoot(f1, df1, -2, 4, 1e-14, 100, 20))); }
static public double IV(OptionType type, double s, double x, double r, double q, decimal optionPrice, int days) { double t = Convert.ToDouble(days) / 365; Func <double, double> f = sigma => Convert.ToDouble(Price(type, s, x, r, q, sigma, days) - optionPrice); Func <double, double> df = sigma => Vega(s, x, r, q, sigma, days); return(RobustNewtonRaphson.FindRoot(f, df, lowerBound: 0, upperBound: 100, accuracy: 0.001)); }
/// <summary>Find a solution of the equation f(x)=0.</summary> /// <param name="f">The function to find roots from.</param> /// <param name="df">The first derivative of the function to find roots from.</param> /// <param name="lowerBound">The low value of the range where the root is supposed to be.</param> /// <param name="upperBound">The high value of the range where the root is supposed to be.</param> /// <param name="accuracy">Desired accuracy. The root will be refined until the accuracy or the maximum number of iterations is reached. Example: 1e-14.</param> /// <param name="maxIterations">Maximum number of iterations. Example: 100.</param> public static double OfFunctionDerivative(Func <double, double> f, Func <double, double> df, double lowerBound, double upperBound, double accuracy = 1e-8, int maxIterations = 100) { double root; if (RobustNewtonRaphson.TryFindRoot(f, df, lowerBound, upperBound, accuracy, maxIterations, 20, out root)) { return(root); } return(OfFunction(f, lowerBound, upperBound, accuracy, maxIterations)); }
/// <summary>Find a solution of the equation f(x)=0.</summary> /// <param name="f">The function to find roots from.</param> /// <param name="df">The first derivative of the function to find roots from.</param> /// <param name="lowerBound">The low value of the range where the root is supposed to be.</param> /// <param name="upperBound">The high value of the range where the root is supposed to be.</param> /// <param name="accuracy">Desired accuracy. The root will be refined until the accuracy or the maximum number of iterations is reached. Example: 1e-14.</param> /// <param name="maxIterations">Maximum number of iterations. Example: 100.</param> public static double OfFunctionDerivative(Func <double, double> f, Func <double, double> df, double lowerBound, double upperBound, double accuracy = 1e-8, int maxIterations = 100) { double root; if (RobustNewtonRaphson.TryFindRoot(f, df, lowerBound, upperBound, accuracy, maxIterations, 20, out root)) { return(root); } if (Bisection.TryFindRoot(f, lowerBound, upperBound, accuracy, maxIterations, out root)) { return(root); } throw new NonConvergenceException(Resources.RootFindingFailed); }
public void Cubic() { // with complex roots (looking for the real root only): 3x^3 + 4x^2 + 5x + 6, derivative 9x^2 + 8x + 5 Func <double, double> f1 = x => Evaluate.Polynomial(x, 6, 5, 4, 3); Func <double, double> df1 = x => Evaluate.Polynomial(x, 5, 8, 9); Assert.AreEqual(-1.265328088928, RobustNewtonRaphson.FindRoot(f1, df1, -2, -1, 1e-10, 100, 20), 1e-6); Assert.AreEqual(-1.265328088928, RobustNewtonRaphson.FindRoot(f1, df1, -5, 5, 1e-10, 100, 20), 1e-6); // real roots only: 2x^3 + 4x^2 - 50x + 6, derivative 6x^2 + 8x - 50 Func <double, double> f2 = x => Evaluate.Polynomial(x, 6, -50, 4, 2); Func <double, double> df2 = x => Evaluate.Polynomial(x, -50, 8, 6); Assert.AreEqual(-6.1466562197069, RobustNewtonRaphson.FindRoot(f2, df2, -8, -5, 1e-10, 100, 20), 1e-6); Assert.AreEqual(0.12124737195841, RobustNewtonRaphson.FindRoot(f2, df2, -1, 1, 1e-10, 100, 20), 1e-6); Assert.AreEqual(4.0254088477485, RobustNewtonRaphson.FindRoot(f2, df2, 3, 5, 1e-10, 100, 20), 1e-6); }
public void MultipleRoots() { // Roots at -2, 2 Func <double, double> f1 = x => x * x - 4; Func <double, double> df1 = x => 2 * x; Assert.AreEqual(0, f1(RobustNewtonRaphson.FindRoot(f1, df1, -5, 5, 1e-14, 100, 20))); Assert.AreEqual(-2, RobustNewtonRaphson.FindRoot(f1, df1, -5, -1, 1e-14, 100, 20)); Assert.AreEqual(2, RobustNewtonRaphson.FindRoot(f1, df1, 1, 4, 1e-14, 100, 20)); Assert.AreEqual(0, f1(RobustNewtonRaphson.FindRoot(x => - f1(x), x => - df1(x), -5, 5, 1e-14, 100, 20))); Assert.AreEqual(-2, RobustNewtonRaphson.FindRoot(x => - f1(x), x => - df1(x), -5, -1, 1e-14, 100, 20)); Assert.AreEqual(2, RobustNewtonRaphson.FindRoot(x => - f1(x), x => - df1(x), 1, 4, 1e-14, 100, 20)); // Roots at 3, 4 Func <double, double> f2 = x => (x - 3) * (x - 4); Func <double, double> df2 = x => 2 * x - 7; Assert.AreEqual(0, f2(RobustNewtonRaphson.FindRoot(f2, df2, -5, 5, 1e-14, 100, 20))); Assert.AreEqual(3, RobustNewtonRaphson.FindRoot(f2, df2, -5, 3.5, 1e-14, 100, 20)); Assert.AreEqual(4, RobustNewtonRaphson.FindRoot(f2, df2, 3.2, 5, 1e-14, 100, 20)); Assert.AreEqual(3, RobustNewtonRaphson.FindRoot(f2, df2, 2.1, 3.9, 0.001, 50, 20), 0.001); Assert.AreEqual(3, RobustNewtonRaphson.FindRoot(f2, df2, 2.1, 3.4, 0.001, 50, 20), 0.001); }
public double InventorySpaceUpperBound(double nextPeriodInventorySpaceLowerBound, double nextPeriodInventorySpaceUpperBound, double currentPeriodMinInventory, double currentPeriodMaxInventory, double inventoryPercentLoss) { double currentPeriodMaxInjectWithdrawAtMaxInventory = _maxInjectWithdrawPolynomial.Evaluate(currentPeriodMaxInventory); double currentPeriodMinInjectWithdrawAtMaxInventory = _minInjectWithdrawPolynomial.Evaluate(currentPeriodMaxInventory); double nextPeriodMaxInventoryFromThisPeriodMaxInventory = currentPeriodMaxInventory + currentPeriodMaxInjectWithdrawAtMaxInventory; double nextPeriodMinInventoryFromThisPeriodMaxInventory = currentPeriodMaxInventory + currentPeriodMinInjectWithdrawAtMaxInventory; if (nextPeriodMinInventoryFromThisPeriodMaxInventory <= nextPeriodInventorySpaceUpperBound && nextPeriodInventorySpaceLowerBound <= nextPeriodMaxInventoryFromThisPeriodMaxInventory) { // No need to solve root as next period inventory space can be reached from the current period max inventory return(currentPeriodMaxInventory); } double PolyToSolve(double inventory) => inventory * (1 - inventoryPercentLoss) + _minInjectWithdrawPolynomial.Evaluate(inventory) - nextPeriodInventorySpaceUpperBound; double PolyToSolve1StDeriv(double inventory) => (1 - inventoryPercentLoss) + _minInjectWithdrawPolynomial1StDeriv.Evaluate(inventory); if (!RobustNewtonRaphson.TryFindRoot(PolyToSolve, PolyToSolve1StDeriv, currentPeriodMinInventory, currentPeriodMaxInventory, _newtonRaphsonAccuracy, _newtonRaphsonMaxNumIterations, _newtonRaphsonSubdivision, out double thisPeriodMaxInventory)) { throw new ApplicationException("Cannot solve for the current period inventory space upper bound. Try changing Newton Raphson parameters."); } if (thisPeriodMaxInventory < currentPeriodMinInventory)// TODO allow tolerance? If so, need to think how this will feed through to other parts of code. { throw new ApplicationException("Inventory constraints cannot be satisfied."); } return(Math.Min(thisPeriodMaxInventory, currentPeriodMaxInventory)); }
public Vector <double>[] bvpsolver_zzz(Func <double, Vector <double>, Vector <double> > system, double ya, double yb, double xa, double xb, int N) { //先求解方程得到初始斜率的估计值,再进行打靶法迭代。--zzz Vector <double>[] res; Vector <double> y0; double s_guess, s_guess_pre; double fais, fais_pre; double dfai, ds; int count = 0; //计算20组s_guess和fais,然后样条插值得到连续函数,再通过解方程,得到使fais=0的初始s_guess int M = 50; double[] sLst = Vector <double> .Build.Dense(M, i => yb / M *i).ToArray(); double[] faisLst = new double[M]; count = 0; while (count < M) { y0 = Vector <double> .Build.DenseOfArray(new[] { ya, sLst[count] }); // observer_pr ob_pr = this->write_targetFunc_end; res = RungeKutta.FourthOrder(y0, xa, xb, N, system); faisLst[count] = res[N - 1][0] - yb; count++; } //样条插值得到连续函数 var cubicSpl = CubicSpline.InterpolateNatural(sLst, faisLst); /*如果初始值离解太远,牛顿法会不收敛。故采用Mathnet包中的RobustNewtonRaphson * double s_cur = 0, s_next; * count = 0; * while (count < 1000) * { * fais = cubicSpl.Interpolate(s_cur); * dfaids = cubicSpl.Differentiate(s_cur); * if (fais < 1e-5 && fais > -1e-5) * { * break; * } * * s_next = s_cur - fais / dfaids; * s_cur = s_next; * count += 1; * }*/ //解方程fais=0,得到初始斜率s_guess。该法先尝试牛顿法,如失败会采用二分法(bisection)。 s_guess = RobustNewtonRaphson.FindRoot(cubicSpl.Interpolate, cubicSpl.Differentiate, 0, yb, 1e-5); //利用解得的s_guess,构造s_guess_pre,目的是求导数dfai/ds。 if (s_guess == 0) { s_guess_pre = 1e-2; } else { s_guess_pre = s_guess * 0.99; } //求s_guess_pre对应的fais_pre,目的是求导数dfai/ds。 y0 = Vector <double> .Build.DenseOfArray(new[] { ya, s_guess_pre }); res = RungeKutta.FourthOrder(y0, xa, xb, N, system); fais_pre = res[N - 1][0] - yb; count = 0; while (count < 50) { y0 = Vector <double> .Build.DenseOfArray(new[] { ya, s_guess }); res = RungeKutta.FourthOrder(y0, xa, xb, N, system); fais = res[N - 1][0] - yb; dfai = fais - fais_pre; ds = s_guess - s_guess_pre; if (fais < 1e-5 && fais > -1e-5) { break; } fais_pre = fais; s_guess_pre = s_guess; s_guess = s_guess - fais * ds / dfai; count++; } return(res); }