/** Method: Try steffensen acceleration (if error, return -1) * f - function * x - independent variable * min - min value of the interval * max - max value of the interval * val - value to add (0 if pure root search) * iterations - number of iterations */ internal double TrySteffensenAcceleration(function f, derivative d, double x, double val, double iterations) { double gx = f(x) - val; int i = 0; double xi = -1; double xiMin1 = -1; double xiMin2 = -1; while (Math.Abs(gx) > epsilon) { if (d(x) == 0) { return(0); } if (i < 4 || i % 2 == 0 || xi - 2 * xiMin1 + xiMin2 == 0) { x = x - gx / d(x); } else { x = GetAitkenIteration(xiMin2, xiMin1, xi); } gx = f(x) - val; xiMin2 = xiMin1; xiMin1 = xi; xi = x; i++; if (i > maxIterations) { throw new Exception("Exceed maximun iterations"); } } iterations = i; return(x); }
//Расчёт значения производной в точке public double GetDerivative(derivative function, int k, uint round = 0) { if (round != 0) { return(Math.Round(function(points[0, k], points[1, k]), (int)round)); } else { return(function(points[0, k], points[1, k])); } }
/** Method: Bisection root search numerical method * f - function * d - first derivative * min - min value of the interval * max - max value of the interval * val - value to add (0 if pure root search) * eps - epsilon for solution validation * maxIt - maximum of iterations */ internal double MonotoneBisection(function f, derivative d, double min, double max, double val, double eps, ref int it, int maxIt) { double dMin = d(min); double dMax = d(max); if (dMin * dMax < 0) { throw new ArgumentException("This method is only for monotone intervals"); } return(MonotoneBisectionRec(f, min, max, val, (dMin > 0), eps, ref it, maxIt)); }
/** Method: * Metodo Steffenson, que es una forma mas rapida de encontrar una raiz o cero de una función * Si va es cero entonces encuantra la raiz de la funcion * si no, encuentra la inversa de la función * f - function * d - first derivative * x - independent variable * val - Valor para el cual se desea buscar la inversa de la función */ internal double SteffensenAcceleration(function f, derivative d, double x, double val) { double gxAnt = double.MaxValue; epsilon = 0.005; double gx = f(x) - val; int i = 0; double xi = -1; double xiMin1 = -1; double xiMin2 = -1; while (Math.Abs(gx) > epsilon) { if (d(x) == 0) { return(0); } if (i < 4 || i % 2 == 0 || xi - 2 * xiMin1 + xiMin2 == 0) { x = x - gx / d(x); } else { x = GetAitkenIteration(xiMin2, xiMin1, xi); } gx = f(x) - val; if (Math.Abs(gx) > Math.Abs(gxAnt)) { return(xi); } gxAnt = gx; xiMin2 = xiMin1; xiMin1 = xi; xi = x; i++; if (i > maxIterations) { return(0); } } iterations = i; return(x); }
/** Method: * Metodo Newton Raphson para encontrar una raiz o cero de una función</para> * Si val es cero entonces encuantra la raiz de la funcion, * si no, encuentra la inversa de la función * f - function * d - first derivative * x - independent variable * val - Valor para el cual se desea buscar la inversa de la función */ internal double NewtonRaphson(function f, derivative d, double x, double val) { int i = 0; double gx = f(x) - val; while (Math.Abs(gx) > epsilon) { if (d(x) == 0) { return(0); } x = x - gx / d(x); gx = f(x) - val; i++; if (i > maxIterations) { throw new Exception("Exceed the maximun iterations"); } } return(x); }
/** Method: * Metodo Newton Raphson para encontrar una raiz o cero de una función * Si val es cero entonces encuantra la raiz de la funcion * si no, encuentra la inversa de la función <paramref name="f"/> en val * f - function * d - first derivative * d2 - second derivative * min - min value of the interval * max - max value of the interval * val - value to add (0 if pure root search) * eps - epsilon for solution validation * maxIt - maximum of iterations */ internal double NewtonRaphsonOneRoot(function f, derivative d, derivative2 d2, double min, double max, double val) { if ((f(min) - val) * f(max) - val > 0) { throw new ArgumentException("No zero between these values"); } double nr = 0; double x; int i = 0; while (nr == 0) { x = GetFourierValue(f, d2, min, max, val); nr = NewtonRaphson(f, d, x, val); if (i > maxIterations) { throw new Exception("Exceed the maximun iterations"); } i++; } return(nr); }
/** Method: * Metodo Steffenson, que es una forma mas rapida de encontrar una raiz o cero de una función * Si val es cero entonces encuantra la raiz de la funcion * si no, encuentra la inversa de la función * f - function * d - first derivative * d2 - second derivative * min - min value of the interval * max - max value of the interval * val - value to add (0 if pure root search) * maxIterations - maximum of iterations */ internal double SteffensenAccOneRoot(function f, derivative d, derivative2 d2, double min, double max, double val, int maxIterations) { if ((f(min) - val) * f(max) - val > 0) { throw new Exception("No zero between these values"); } double st = 0; double x; int i = 0; while (st == 0) { x = GetFourierValue(f, d2, min, max, val); st = SteffensenAcceleration(f, d, x, val); i++; if (i > maxIterations) { throw new Exception("Exceed maximun iterations"); } } //Console.WriteLine("val = " + val + " , st = " + st + " , it = " + i); return(st); }
static void Main(string[] args) { Func <double, double, double> func = (x1, x2) => (100 * Math.Pow(x1, 2) + Math.Pow(x2, 2)); derivative[] masDerivatives = new derivative[2]; masDerivatives[0] = ((x1, x2) => (200 * x1)); masDerivatives[1] = ((x1, x2) => (2 * x2)); secondDerivative[,] masSecondDerivatives = new secondDerivative[2, 2]; masSecondDerivatives[0, 0] = ((x1, x2) => (200)); masSecondDerivatives[0, 1] = ((x1, x2) => (0)); masSecondDerivatives[1, 0] = ((x1, x2) => (0)); masSecondDerivatives[1, 1] = ((x1, x2) => (2)); double[,] points = new double[2, 12]; points[0, 0] = 0; points[1, 0] = 1; Gradient gradient1 = new Gradient(points, 0.1, 0.15, 10, 0.5, 3, masDerivatives, masSecondDerivatives, 3, func); Gradient gradient2 = new Gradient(points, 0.1, 0.15, 10, 0.5, 3, masDerivatives, masSecondDerivatives, 3, func); Gradient gradient3 = new Gradient(points, 0.1, 0.15, 10, 0.5, 3, masDerivatives, masSecondDerivatives, 3, func); //gradient1.RegisterHandler(func); //gradient2.RegisterHandler(func); //gradient3.RegisterHandler(func); Console.WriteLine("Метод Ньютона: "); Console.WriteLine(); gradient1.SearchMinNyuton(); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Метод сопряжённых градиентов: "); Console.WriteLine(); gradient2.SearchMinConjugateGradients(); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Метод наискорейшего градиентного спуска: "); Console.WriteLine(); gradient3.SearchMinFast(); }
//Расчёт значения производной в точке public double GetDerivative(derivative function, int k) { return(function(points[0, k], points[1, k])); }