| Source for file LevenbergMarquardt.phpDocumentation is available at LevenbergMarquardt.php 
// Levenberg-Marquardt in PHP// http://www.idiom.com/~zilla/Computer/Javanumeric/LM.java     * Calculate the current sum-squared-error     * Chi-squared is the distribution of squared Gaussian errors,        for ($i = 0; $i < $npts; ++$i) {            $d = $y[$i] - $f->val($x[$i], $a);    }    //    function chiSquared()     * Minimize E = sum {(y[k] - f(x[k],a)) / s[k]}^2     * The individual errors are optionally scaled by s[k].     * Note that LMfunc implements the value and gradient of f(x,a),     * NOT the value and gradient of E with respect to a!     * @param x array of domain points, each may be multidimensional     * @param y corresponding array of values     * @param a the parameters/state of the model     * @param vary false to indicate the corresponding a[k] is to be held fixed     * @param s2 sigma^2 for point i     * @param lambda blend between steepest descent (lambda high) and     *     jump to bottom of quadratic (lambda zero).     * @param termepsilon termination accuracy (0.01)     * @param maxiter    stop and return after this many iterations if not done     * @param verbose    set to zero (no prints), 1, 2     * @return the new lambda for future iterations.     *   Can use this and maxiter to interleave the LM descent with some other     *   task, setting maxiter to something small.    function solve($x, $a, $y, $s, $vary, $f, $lambda, $termepsilon, $maxiter, $verbose) {            print("solve x[" .count($x) ."][" .count($x[0]) ."]");            print(" a[" .count($a) ."]");            println(" y[".count(length) ."]");        // g = gradient, H = hessian, d = step to minimum        //double[] d = new double[nparm];        for($i = 0; $i < $npts; ++$i) {            $oos2[$i] = 1. /($s[$i] *$s[$i]);        $term = 0;    // termination count test            for( $r = 0; $r < $nparm; ++$r) {                for( $c = 0; $c < $nparm; ++$c) {                    for( $i = 0; $i < $npts; ++$i) {                        if ($i == 0) $H[$r][$c] = 0.;                        $H[$r][$c] += ($oos2[$i] * $f->grad($xi, $a, $r) * $f->grad($xi, $a, $c));            // boost diagonal towards gradient descent            for( $r = 0; $r < $nparm; ++$r)                $H[$r][$r] *= (1. + $lambda);            for( $r = 0; $r < $nparm; ++$r) {                for( $i = 0; $i < $npts; ++$i) {                    if ($i == 0) $g[$r] = 0.;                    $g[$r] += ($oos2[$i] * ($y[$i] -$f->val($xi,$a)) * $f->grad($xi, $a, $r));            // scale (for consistency with NR, not necessary)                for( $r = 0; $r < $nparm; ++$r) {                    for( $c = 0; $c < $nparm; ++$c) {            // solve H d = -g, evaluate error at new location            //double[] d = DoubleMatrix.solve(H, g);//            double[] d = (new Matrix(H)).lu().solve(new Matrix(g, nparm)).getRowPackedCopy();            //double[] na = DoubleVector.add(a, d);//            double[] na = (new Matrix(a, nparm)).plus(new Matrix(d, nparm)).getRowPackedCopy();//            double e1 = chiSquared(x, na, y, s, f);//                System.out.println("\n\niteration "+iter+" lambda = "+lambda);//                System.out.print("a = ");//                (new Matrix(a, nparm)).print(10, 2);//                    System.out.print("H = ");//                    (new Matrix(H)).print(10, 2);//                    System.out.print("g = ");//                    (new Matrix(g, nparm)).print(10, 2);//                    System.out.print("d = ");//                    (new Matrix(d, nparm)).print(10, 2);//                System.out.print("e0 = " + e0 + ": ");//                System.out.print("moved from ");//                (new Matrix(a, nparm)).print(10, 2);//                System.out.print("e1 = " + e1 + ": ");//                    System.out.print("to ");//                    (new Matrix(na, nparm)).print(10, 2);//                    System.out.println("move rejected");            // termination test (slightly different than NR)//            if (Math.abs(e1-e0) > termepsilon) {//                    System.out.println("terminating after " + iter + " iterations");//            if (iter >= maxiter) done = true;            // in the C++ version, found that changing this to e1 >= e0            // was not a good idea.  See comment there.//            if (e1 > e0 || Double.isNaN(e1)) { // new location worse than before//            } else {        // new location better, accept new parameters//                // simply assigning a = na will not get results copied back to caller//                for( int i = 0; i < nparm; i++ ) {//                    if (vary[i]) a[i] = na[i];}    //    class LevenbergMarquardt |