package com.nus;

import Jama.Matrix;

/**
 * Created by duy on 20/1/15.
 */
public class LMSolver {
  // Configuration parameters for Levenberg-Marquadt algorithm
  private double lambda;
  private int maxNumIter;
  private double termEpsilon;

  private IErrorFunc errorFunc;

  public LMSolver(IErrorFunc inErrorFunc) {
    this.lambda = 0.001;
    this.maxNumIter = 10;
    this.termEpsilon = 0.00001;
    this.errorFunc = inErrorFunc;
  }

  public LMSolver(
      double lambda,
      int maxNumIter,
      double termEpsilon,
      IErrorFunc errorFunc) {
    this.lambda = lambda;
    this.maxNumIter = maxNumIter;
    this.termEpsilon = termEpsilon;
    this.errorFunc = errorFunc;
  }

  public double getLambda() {
    return lambda;
  }

  public void setLambda(double lambda) {
    this.lambda = lambda;
  }

  public int getMaxNumIter() {
    return maxNumIter;
  }

  public IErrorFunc getErrorFunc() {
    return errorFunc;
  }

  public void setMaxNumIter(int maxNumIter) {
    this.maxNumIter = maxNumIter;
  }

  public double getTermEpsilon() {
    return termEpsilon;
  }

  public void setTermEpsilon(double termEpsilon) {
    this.termEpsilon = termEpsilon;
  }

  /**
   * Applies Levenberg-Marquadt on the input error function with the input
   * initial guess of optimization parameters
   *
   * @param optParams A vector of initial guess of values of parameters
   *                  for optimization
   */
  public void solve(double[] optParams) {
    int iter = 0;
    int count = 0;
    boolean stopFlag;
    int numOptParams = optParams.length;

    double errValue = errorFunc.eval(optParams);

    double curLambda = lambda;

    do {
      stopFlag = false;
      iter++;

      // Compute matrices and vectors needed in augmented normal equation
      double[] gradient = errorFunc.jacobian(optParams);
      double[][] modifiedHessian = errorFunc.hessian(optParams);
      for (int i = 0; i < numOptParams; ++i) {
        modifiedHessian[i][i] *= (1 + curLambda);
      }

      // Solve augmented normal equation
      Matrix direction = solveMatrixEq(
        new Matrix(modifiedHessian),
        (new Matrix(gradient, numOptParams)).uminus()
      );
      double[] newOptParams = (new Matrix(optParams, numOptParams))
        .plus(direction).getRowPackedCopy();

      double newErrValue = errorFunc.eval(newOptParams);

      if (Math.abs(newErrValue - errValue) < termEpsilon) {
        count++;
        if (count == 4) {
          stopFlag = true;
        }
      } else {
        count = 0;
      }

      if (newErrValue > errValue) {
        curLambda *= 10.0;
      } else {
        curLambda /= 10.0;
        errValue = newErrValue;
        for (int i = 0; i < numOptParams; ++i) {
          optParams[i] = newOptParams[i];
        }
      }

      if (iter > maxNumIter) {
        stopFlag = true;
      }

    } while (!stopFlag);
  }

  private static Matrix solveMatrixEq(Matrix A, Matrix b) {
    return A.lu().solve(b);
  }
}

@@ -84,17 +84,17 @@
  class L
-M
+m
 Solver %7B
@@ -174,22 +174,23 @@
  double 
-lambda
+damping
 ;%0A  priv
@@ -279,25 +279,25 @@
 %0A%0A  public L
-M
+m
 Solver(IErro
@@ -326,22 +326,23 @@
    this.
-lambda
+damping
  = 0.001
@@ -450,17 +450,17 @@
 public L
-M
+m
 Solver(%0A
@@ -472,22 +472,23 @@
  double 
-lambda
+damping
 ,%0A      
@@ -564,39 +564,41 @@
  %7B%0A    this.
-lambda = lambda
+damping = damping
 ;%0A    this.m
@@ -713,22 +713,23 @@
 uble get
-Lambda
+Damping
 () %7B%0A   
@@ -736,22 +736,23 @@
  return 
-lambda
+damping
 ;%0A  %7D%0A%0A 
@@ -771,22 +771,23 @@
  set
-Lambda
+Damping
 (double 
 lamb
@@ -782,22 +782,23 @@
 (double 
-lambda
+damping
 ) %7B%0A    
@@ -806,23 +806,25 @@
 his.
-lambda = lambda
+damping = damping
 ;%0A  
@@ -1647,20 +1647,17 @@
 ble 
-curL
+l
 ambda = 
 lamb
@@ -1652,22 +1652,23 @@
 ambda = 
-lambda
+damping
 ;%0A%0A    d
@@ -1991,20 +1991,17 @@
 *= (1 + 
-curL
+l
 ambda);%0A
@@ -2585,28 +2585,25 @@
 ) %7B%0A        
-curL
+l
 ambda *= 10.
@@ -2632,12 +2632,9 @@
     
-curL
+l
 ambd

Change file name and variable name