//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: /** @author John Miller * @version 1.0 * @date Tue Apr 2 18:46:44 EDT 2013 * @see LICENSE (MIT style license file). */ package scalation.minima import math.abs import util.control.Breaks.{breakable, break} import scalation.calculus.Calculus.{derivative, FunctionS2S} //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: /** This class is used to find roots (zeroes) for a one-dimensional (scalar) * function f. If f is the derivative of some other function g, then this * technique can be used to find optima for g. * Caveat: Use Conjugate Gradient or Quasi-Newton for complex optimizations. * @param f the function to find roots of */ class NewtonRaphson (f: FunctionS2S) { private val EPSILON = 1E-9 // a number close to zero private val MAX_ITER = 100 // the maximum number of iterations //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: /** Solve for/find a root close to the starting point/guess x0. * @param x0 the starting point/guess */ def solve (x0: Double): Double = { var x = x0 // current point var f_x = -1. // function value at x var df_x = -1. // derivative value at x breakable { for (it <- 0 until MAX_ITER) { f_x = f(x) if (abs (f_x) < EPSILON) break // close to zero => quit df_x = derivative (f, x) if (abs (df_x) < EPSILON) df_x = EPSILON // derivative is too small x -= f_x / df_x // subtract the ratio }} // for printf ("solution x = %10.4f, df = %10.4f\n", x, f(x)) x } // solve } // NewtonRaphson //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: /** This object is used to test the NewtonRaphson class. */ object NewtonRaphsonTest extends App { def f (x: Double): Double = 2. * (x - 3.) val nr = new NewtonRaphson (f) nr.solve (0.) } // NewtonRaphsonTest