public static OptimisationReport NiuDunLaFuSunStep( MatrixChains chain, double[] angles, boolean printStep) { // see: http://code.google.com/p/efficient-java-matrix-library/wiki/SolvingLinearSystems int l = angles.length; DenseMatrix64F J = get2d(chain, angles); DenseMatrix64F grad = get1d(chain, angles); DenseMatrix64F propose = vector(l); boolean solved = CommonOps.solve(J, grad, propose); for (int i = 0; i < l; ++i) { if (Double.isNaN(propose.data[i])) { solved = false; } } OptimisationReport togo = new OptimisationReport(); try { if (!solved) { throw new RuntimeException("Failed to solve update equation"); } CommonOps.scale(-1, propose); if (printStep) { EigenDecomposition<DenseMatrix64F> decomp = DecompositionFactory.eigSymm(l, false); boolean posed = decomp.decompose(J); if (!posed) { throw new RuntimeException("Failed to decompose matrix"); } double[] eigs = eigs(decomp); System.out.println("Computed eigenvalues " + printVec(eigs)); togo.eigenvalues = eigs; } tryProposal(chain, propose, grad, angles, printStep, togo); } catch (Exception e) { System.out.println( "Failed to find suitable proposal from Newton step - trying gradient step"); propose.set(grad); CommonOps.scale(-1, propose); tryProposal(chain, propose, grad, angles, printStep, togo); } return togo; }
private static boolean verifyProposal( MatrixChains chain, double[] angles, double[] newAng, DenseMatrix64F grad, DenseMatrix64F propose, OptimisationReport report) { for (int i = 0; i < newAng.length; ++i) { if (newAng[i] <= 0 || newAng[i] >= 2 * Math.PI) { System.out.println("Rejected out of range angle " + newAng[i] + " at index " + i); return false; } } double descent = dot(grad.data, propose.data); if (descent > 0) { throw new RuntimeException("Non-reducing gradient direction with slope " + descent); } double oldF = f(chain, angles); double newF = f(chain, newAng); if (newF > oldF + 1e-4 * descent) { System.out.println("Rejected failure of descent step to " + newF); return false; } DenseMatrix64F newGrad = get1d(chain, newAng); // These would both be negative numbers reflecting correct gradient direction double newDescent = dot(newGrad.data, propose.data); if (newDescent < 0.99 * descent) { System.out.println( "Rejected failure of gradient reduce step from " + descent + " to " + newDescent); return false; } report.fval = newF; report.gradn = Math.sqrt(dot(newGrad.data, newGrad.data)); report.angles = newAng; return true; }
public static OptimisationReport runNewton(MatrixChains chains, double[] angles) { System.out.println("f: " + Newton.f(chains, angles)); System.out.println(); DenseMatrix64F dby1 = Newton.get1d(chains, angles); System.out.println("dby1: " + dby1); System.out.println("numDiff: " + Newton.numDiff1d(chains, angles, 1e-6)); System.out.println(); DenseMatrix64F dby11 = Newton.get2d(chains, angles); System.out.println("dby11: " + dby11); System.out.println("numDiff: " + Newton.numDiff2d(chains, angles, 1e-5)); OptimisationReport report = runNewtonRun(chains, angles, 25); if (report.gradn >= chains.tolerance) { report.status = "FAILED"; } else { int minIndex = diagnoseEigenvalues(report.eigenvalues); if (minIndex == -1) { report.status = "RIGID"; } else { report.status = "LOOSE"; chains.regularise = 1e-1; chains.initialPoint = angles; System.out.println("Beginning 2nd run with regularisation " + chains.regularise); report = runNewtonRun(chains, angles, 30); report.status = (report.gradn >= chains.tolerance) ? "LOOSE-FAILED" : "LOOSE"; System.out.println("Original vector was " + printVec(angles)); chains.regularise = 1e-4; chains.initialPoint = report.angles; System.out.println("Beginning 3nd run with regularisation " + chains.regularise); report = runNewtonRun(chains, report.angles, 30); report.status = (report.gradn >= chains.tolerance) ? "LOOSE-FAILED" : "LOOSE"; System.out.println("Original vector was " + printVec(angles)); } } System.out.println("Optimisation concluded - the configuration is " + report.status); return report; }