diff --git a/src/main/java/org/apache/commons/math/optimization/general/AbstractLeastSquaresOptimizer.java b/src/main/java/org/apache/commons/math/optimization/general/AbstractLeastSquaresOptimizer.java index c4b19855a..007e13f9d 100644 --- a/src/main/java/org/apache/commons/math/optimization/general/AbstractLeastSquaresOptimizer.java +++ b/src/main/java/org/apache/commons/math/optimization/general/AbstractLeastSquaresOptimizer.java @@ -84,6 +84,12 @@ public abstract class AbstractLeastSquaresOptimizer implements DifferentiableMul /** Current residuals. */ protected double[] residuals; + + /** Weighted Jacobian */ + protected double[][] wjacobian; + + /** Weighted residuals */ + protected double[] wresiduals; /** Cost value (square root of the sum of the residuals). */ protected double cost; @@ -189,9 +195,10 @@ public abstract class AbstractLeastSquaresOptimizer implements DifferentiableMul } for (int i = 0; i < rows; i++) { final double[] ji = jacobian[i]; - final double factor = -Math.sqrt(residualsWeights[i]); + double wi = Math.sqrt(residualsWeights[i]); for (int j = 0; j < cols; ++j) { - ji[j] *= factor; + ji[j] *= -1.0; + wjacobian[i][j] = ji[j]*wi; } } } @@ -219,6 +226,7 @@ public abstract class AbstractLeastSquaresOptimizer implements DifferentiableMul for (int i = 0; i < rows; i++) { final double residual = targetValues[i] - objective[i]; residuals[i] = residual; + wresiduals[i]= residual*Math.sqrt(residualsWeights[i]); cost += residualsWeights[i] * residual * residual; index += cols; } @@ -270,7 +278,7 @@ public abstract class AbstractLeastSquaresOptimizer implements DifferentiableMul for (int j = i; j < cols; ++j) { double sum = 0; for (int k = 0; k < rows; ++k) { - sum += jacobian[k][i] * jacobian[k][j]; + sum += wjacobian[k][i] * wjacobian[k][j]; } jTj[i][j] = sum; jTj[j][i] = sum; @@ -342,6 +350,9 @@ public abstract class AbstractLeastSquaresOptimizer implements DifferentiableMul cols = point.length; jacobian = new double[rows][cols]; + wjacobian = new double[rows][cols]; + wresiduals = new double[rows]; + cost = Double.POSITIVE_INFINITY; return doOptimize(); diff --git a/src/main/java/org/apache/commons/math/optimization/general/LevenbergMarquardtOptimizer.java b/src/main/java/org/apache/commons/math/optimization/general/LevenbergMarquardtOptimizer.java index b41456eff..286f82c7d 100644 --- a/src/main/java/org/apache/commons/math/optimization/general/LevenbergMarquardtOptimizer.java +++ b/src/main/java/org/apache/commons/math/optimization/general/LevenbergMarquardtOptimizer.java @@ -270,7 +270,7 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer { VectorialPointValuePair current = new VectorialPointValuePair(point, objective); while (true) { for (int i=0;i 0) ? -Math.sqrt(ak2) : Math.sqrt(ak2); double betak = 1.0 / (ak2 - akk * alpha); beta[pk] = betak; // transform the current column diagR[pk] = alpha; - jacobian[k][pk] -= alpha; + wjacobian[k][pk] -= alpha; // transform the remaining columns for (int dk = cols - 1 - k; dk > 0; --dk) { double gamma = 0; - for (int j = k; j < jacobian.length; ++j) { - gamma += jacobian[j][pk] * jacobian[j][permutation[k + dk]]; + for (int j = k; j < wjacobian.length; ++j) { + gamma += wjacobian[j][pk] * wjacobian[j][permutation[k + dk]]; } gamma *= betak; - for (int j = k; j < jacobian.length; ++j) { - jacobian[j][permutation[k + dk]] -= gamma * jacobian[j][pk]; + for (int j = k; j < wjacobian.length; ++j) { + wjacobian[j][permutation[k + dk]] -= gamma * wjacobian[j][pk]; } } @@ -874,11 +874,11 @@ public class LevenbergMarquardtOptimizer extends AbstractLeastSquaresOptimizer { int pk = permutation[k]; double gamma = 0; for (int i = k; i < rows; ++i) { - gamma += jacobian[i][pk] * y[i]; + gamma += wjacobian[i][pk] * y[i]; } gamma *= beta[pk]; for (int i = k; i < rows; ++i) { - y[i] -= gamma * jacobian[i][pk]; + y[i] -= gamma * wjacobian[i][pk]; } } } diff --git a/src/test/java/org/apache/commons/math/optimization/general/GaussNewtonOptimizerTest.java b/src/test/java/org/apache/commons/math/optimization/general/GaussNewtonOptimizerTest.java index ab70034bf..901e3150c 100644 --- a/src/test/java/org/apache/commons/math/optimization/general/GaussNewtonOptimizerTest.java +++ b/src/test/java/org/apache/commons/math/optimization/general/GaussNewtonOptimizerTest.java @@ -472,8 +472,8 @@ extends TestCase { VectorialPointValuePair optimum = optimizer.optimize(circle, target, weights, new double[] { 0, 0 }); - assertEquals(-0.1517383071957963, optimum.getPointRef()[0], 1.0e-8); - assertEquals(0.2074999736353867, optimum.getPointRef()[1], 1.0e-8); + assertEquals(-0.1517383071957963, optimum.getPointRef()[0], 1.0e-6); + assertEquals(0.2074999736353867, optimum.getPointRef()[1], 1.0e-6); assertEquals(0.04268731682389561, optimizer.getRMS(), 1.0e-8); }