/// <summary> /// Computes the maximum descent possible from the vector x in the direction dir. /// </summary> /// <param name="func">Function to find it the greatest descent possible in the given direction.</param> /// <param name="x">Current vector of the minimization Quasi-Newton algorithm.</param> /// <param name="dir">Descent direction vector for the current vector.</param> /// <returns>The value of the maximum descent possible.</returns> public static double Wolfe(CompiledFunc func, Vector x, Vector dir) { double a = 0; double ai = 1; double fPrev = 0, fCurr = 0, diff = 0; double fZero = func.Eval(x); var normDir = dir.Normalize(); double diffZero = (func.Differentiate(x)*normDir).Sum(); while(ai < MaxAlpha) { fPrev = func.Eval(x + a*dir); fCurr = func.Eval(x + ai*dir); if (fCurr > fZero + C1*ai*diffZero || (fCurr > fPrev && ai > 1)) return Zoom(func, x, dir, a, ai, fZero, diffZero); diff = (func.Differentiate(x + ai*dir)*normDir).Sum(); if (Math.Abs(diff) <= -C2*diffZero) return ai; if (diff >= 0) return Zoom(func, x, dir, ai, a, fZero, diffZero); a = ai; ai *= 1.5; } return ai; }
/// <summary> /// Computes the BFGS correction formula for inverse hessiana approximation. /// </summary> /// <param name="func">Function to find it the hessiana approximation.</param> /// <param name="b">Current inverse approximation of the hessiana.</param> /// <param name="x">Current vector of the minimization Quasi-Newton algorithm.</param> /// <param name="x1">Next vector of the minimization Quasi-Newton algorithm.</param> /// <returns>Returns a matrix representing the next step in inverse hessiana approximation.s</returns> public static Matrix Bfgs(CompiledFunc func, Matrix b, Vector x, Vector x1) { var sk = new Matrix(x1 - x); var yk = new Matrix(func.Differentiate(x1) - func.Differentiate(x)); var t = b.Dot(sk.Transpose()).Dot(sk).Dot(b)/sk.Dot(b).Dot(sk.Transpose())[0,0]; var t1 = yk.Transpose().Dot(yk)/yk.Dot(sk.Transpose())[0,0]; return b - t + t1; }
protected override Vector Minimize(CompiledFunc f, Vector x = null, Tuple<Vector, Vector> bounds = null) { CurrentIteration = 0; var b = Matrix.Identity(x.Length); var x1 = new Vector(x); Vector d; double a; while (CurrentIteration < IterationsNumber) { CurrentIteration++; d = -b.Dot(f.Differentiate(x)); a = Searcher(f, x, d); x1 = x + a*d; b = Corrector(f, b, x, x1); if (!Algebra.IsValid(x1) || Algebra.Norm(x1 - x) <= EPS) break; x = x1; } return x; }
private static double Zoom(CompiledFunc func, Vector x, Vector dir, double aLow, double aHigh, double fZero, double diffZero) { var normDir = dir.Normalize(); double aMid = 0; double fValue = 0; double diff = 0; while (Math.Abs(aLow - aHigh) > EPS) { aMid = aLow + (aHigh - aLow)/2; fValue = func.Eval(x + aMid*dir); if (fValue > fZero + C1*aMid*diffZero || fValue >= func.Eval(x + aLow*dir)) aHigh = aMid; else { diff = (func.Differentiate(x + aMid*dir)*normDir).Sum(); if (Math.Abs(diff) <= -C2*diffZero) return aMid; if (diff*(aHigh - aLow) >= 0) aHigh = aLow; aLow = aMid; } } return aMid; }