public LM_NBMT(NBMTHost gH, int gnadj, int gnpts, int nresp) throws Exception // Constructor sets up fields and drives iterations. { myH = gH; nadj = gnadj; npts = gnpts; this.nresp = nresp; delta = new double[nadj]; beta = new double[nadj]; alpha = new double[nadj][nadj]; amatrix = new double[nadj][nadj]; lambda = LAMBDAZERO; int niter = 0; boolean done = false; PrintWriter out = new PrintWriter(new FileWriter("LM.txt")); do { done = bLMiter(out); niter++; out.println("New parameters: "); Printer.printArray(myH.getParms(), out); logger.info("niter: " + niter); out.println("niter: " + niter); } while (!done && (niter < LMITER)); out.close(); }
private boolean bLMiter(PrintWriter out) throws Exception // Each call performs one LM iteration. // Returns true if done with iterations; false=wants more. // Global nadj, npts; needs nadj, myH to be preset. // Ref: M.Lampton, Computers in Physics v.11 pp.110-115 1997. { // PrintWriter out = new PrintWriter(new FileWriter("LM.txt")); PrintWriter out_SSQ = new PrintWriter(new FileWriter("SSQ_LM.txt")); sos = myH.dComputeResid(); if (sos == BIGVAL) { logger.debug("bLMiter finds faulty initial dComputeResid()"); return false; } sosprev = sos; logger.info("sosprev: " + sosprev); out.println("sosprev: " + sosprev); // out.println("bLMiter..sos= "+sos); // if (!myH.bBuildJacobian_forward()) if (!myH.bBuildJacobian()) { logger.debug("bLMiter finds bBuildJacobian()=false"); return false; } logger.info("jacobian[i][j]: "); out.println("jacobian[i][j]: "); Printer.printMatrix(myH.dGetFullJac(), out); for (int k = 0; k < nadj; k++) // get downhill gradient beta { beta[k] = 0.0; for (int i = 0; i < npts * nresp; i++) beta[k] -= myH.dGetResid(i) * myH.dGetJac(i, k); } logger.info("beta[i]: "); out.println("beta[i]: "); Printer.printArray(beta, out); for (int k = 0; k < nadj; k++) // get curvature matrix alpha for (int j = 0; j < nadj; j++) { alpha[j][k] = 0.0; for (int i = 0; i < npts * nresp; i++) alpha[j][k] += myH.dGetJac(i, j) * myH.dGetJac(i, k); } logger.info("alpha[i][j]: "); out.println("alpha[i][j]: "); Printer.printMatrix(alpha, out); double rrise = 0; do /// damping loop searches for one downhill step { // System.out.println(" lambda = "+lambda); for (int k = 0; k < nadj; k++) // copy and damp it for (int j = 0; j < nadj; j++) amatrix[j][k] = alpha[j][k] + ((j == k) ? lambda : 0.0); logger.info("amatrix[i][j]: "); out.println("amatrix[i][j]: "); Printer.printMatrix(amatrix, out); Algebra.gaussj(amatrix, nadj); // invert logger.info("amatrix[i][j] inverted: "); out.println("amatrix[i][j] inverted: "); Printer.printMatrix(amatrix, out); for (int k = 0; k < nadj; k++) // compute delta[] { delta[k] = 0.0; for (int j = 0; j < nadj; j++) delta[k] += amatrix[j][k] * beta[j]; } logger.info("delta[k]: "); out.println("delta[k]: "); Printer.printArray(delta, out); sos = myH.dNudge(delta); // try it out. out_SSQ.println("SSQ: " + sos); if (sos == BIGVAL) { logger.info("LMinner failed SOS step"); return false; } rrise = (sos - sosprev) / (1 + sos); logger.info("rrise: " + rrise); out.println("rrise: " + rrise); if (rrise <= 0.0) // good step! { out.println("lambda: " + lambda); logger.info("lambda: " + lambda); lambda *= LMSHRINK; // shrink lambda break; // leave lmInner. } for (int q = 0; q < nadj; q++) // reverse course! delta[q] *= -1.0; myH.dNudge(delta); // sosprev should still be OK if (rrise < LMTOL) // finished but keep prev parms break; // leave inner loop lambda *= LMBOOST; // else try more damping. out.println("lambda: " + lambda); logger.info("lambda: " + lambda); } while (lambda < LAMBDAMAX); boolean done = (rrise > -LMTOL) || (lambda > LAMBDAMAX); // out.close(); out_SSQ.close(); return done; }