You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2013/07/30 17:04:23 UTC

svn commit: r1508481 [2/5] - in /commons/proper/math/trunk/src: main/java/org/apache/commons/math3/fitting/leastsquares/ main/java/org/apache/commons/math3/optim/ test/java/org/apache/commons/math3/fitting/leastsquares/ test/resources/org/apache/common...

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithConvergenceChecker.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithConvergenceChecker.java?rev=1508481&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithConvergenceChecker.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithConvergenceChecker.java Tue Jul 30 15:04:22 2013
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.fitting.leastsquares;
+
+import org.apache.commons.math3.optim.ConvergenceChecker;
+import org.apache.commons.math3.optim.PointVectorValuePair;
+
+/**
+ * Interface for "fluent-API" that advertizes a capability of the optimizer.
+ *
+ * @param <T> Concrete optimizer implementation.
+ *
+ * @version $Id$
+ * @since 3.3
+ */
+public interface WithConvergenceChecker<T> {
+    /**
+     * Creates a new instance with the specified parameter.
+     *
+     * @param checker Convergence checker.
+     * @return a new optimizer instance with all fields identical to this
+     * instance except for the given argument.
+     */
+    T withConvergenceChecker(ConvergenceChecker<PointVectorValuePair> checker);
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithConvergenceChecker.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithConvergenceChecker.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithMaxEvaluations.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithMaxEvaluations.java?rev=1508481&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithMaxEvaluations.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithMaxEvaluations.java Tue Jul 30 15:04:22 2013
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.fitting.leastsquares;
+
+/**
+ * Interface for "fluent-API" that advertizes a capability of the optimizer.
+ *
+ * @param <T> Concrete optimizer implementation.
+ *
+ * @version $Id$
+ * @since 3.3
+ */
+public interface WithMaxEvaluations<T> {
+    /**
+     * Creates a new instance with the specified parameter.
+     *
+     * @param maxEval Maximum number of evaluations of the model function.
+     * @return a new optimizer instance with all fields identical to this
+     * instance except for the given argument.
+     */
+    T withMaxEvaluations(int maxEval);
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithMaxEvaluations.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithMaxEvaluations.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithMaxIterations.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithMaxIterations.java?rev=1508481&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithMaxIterations.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithMaxIterations.java Tue Jul 30 15:04:22 2013
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.fitting.leastsquares;
+
+/**
+ * Interface for "fluent-API" that advertizes a capability of the optimizer.
+ *
+ * @param <T> Concrete optimizer implementation.
+ *
+ * @version $Id$
+ * @since 3.3
+ */
+public interface WithMaxIterations<T> {
+    /**
+     * Creates a new instance with the specified parameter.
+     *
+     * @param maxIter Maximum number of iterations.
+     * @return a new optimizer instance with all fields identical to this
+     * instance except for the given argument.
+     */
+    T withMaxIterations(int maxIter);
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithMaxIterations.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithMaxIterations.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithModelAndJacobian.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithModelAndJacobian.java?rev=1508481&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithModelAndJacobian.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithModelAndJacobian.java Tue Jul 30 15:04:22 2013
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.fitting.leastsquares;
+
+import org.apache.commons.math3.analysis.MultivariateVectorFunction;
+import org.apache.commons.math3.analysis.MultivariateMatrixFunction;
+
+/**
+ * Interface for "fluent-API" that advertizes a capability of the optimizer.
+ *
+ * @param <T> Concrete optimizer implementation.
+ *
+ * @version $Id$
+ * @since 3.3
+ */
+public interface WithModelAndJacobian<T> {
+    /**
+     * Creates a new instance with the specified parameters.
+     *
+     * @param model ModelFunction.
+     * @param jacobian Jacobian of the model function.
+     * @return a new optimizer instance with all fields identical to this
+     * instance except for the given arguments.
+     */
+    T withModelAndJacobian(MultivariateVectorFunction model,
+                           MultivariateMatrixFunction jacobian);
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithModelAndJacobian.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithModelAndJacobian.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithStartPoint.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithStartPoint.java?rev=1508481&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithStartPoint.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithStartPoint.java Tue Jul 30 15:04:22 2013
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.fitting.leastsquares;
+
+/**
+ * Interface for "fluent-API" that advertizes a capability of the optimizer.
+ *
+ * @param <T> Concrete optimizer implementation.
+ *
+ * @version $Id$
+ * @since 3.3
+ */
+public interface WithStartPoint<T> {
+    /**
+     * Creates a new instance with the specified parameter.
+     *
+     * @param start Initial guess for the parameters of the model function.
+     * @return a new optimizer instance with all fields identical to this
+     * instance except for the given argument.
+     */
+    T withStartPoint(double[] start);
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithStartPoint.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithStartPoint.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithTarget.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithTarget.java?rev=1508481&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithTarget.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithTarget.java Tue Jul 30 15:04:22 2013
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.fitting.leastsquares;
+
+/**
+ * Interface for "fluent-API" that advertizes a capability of the optimizer.
+ *
+ * @param <T> Concrete optimizer implementation.
+ *
+ * @version $Id$
+ * @since 3.3
+ */
+public interface WithTarget<T> {
+    /**
+     * Creates a new instance with the specified parameter.
+     *
+     * @param target Objective points of the model function.
+     * @return a new optimizer instance with all fields identical to this
+     * instance except for the given argument.
+     */
+    T withTarget(double[] target);
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithTarget.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithTarget.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithWeight.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithWeight.java?rev=1508481&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithWeight.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithWeight.java Tue Jul 30 15:04:22 2013
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.fitting.leastsquares;
+
+import org.apache.commons.math3.linear.RealMatrix;
+
+/**
+ * Interface for "fluent-API" that advertizes a capability of the optimizer.
+ *
+ * @param <T> Concrete optimizer implementation.
+ *
+ * @version $Id$
+ * @since 3.3
+ */
+public interface WithWeight<T> {
+    /**
+     * Creates a new instance with the specified parameter.
+     *
+     * @param weight Weight matrix of the observations.
+     * @return a new optimizer instance with all fields identical to this
+     * instance except for the given argument.
+     */
+    T withWeight(RealMatrix weight);
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithWeight.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/WithWeight.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/package-info.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/package-info.java?rev=1508481&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/package-info.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/package-info.java Tue Jul 30 15:04:22 2013
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This package provides algorithms that minimize the residuals
+ * between observations and model values.
+ * The {@link org.apache.commons.math3.fitting.leastsquares.AbstractLeastSquaresOptimizer
+ * non-linear least-squares optimizers} minimize the distance (called <em>cost</em> or
+ * <em>&chi;<sup>2</sup></em>) between model and observations.
+ *
+ * <br/>
+ * Algorithms in this category need access to a <em>model function</em>
+ * (represented by a {@link org.apache.commons.math3.analysis.MultivariateVectorFunction
+ * MultivariateVectorFunction}).
+ * Such a model predicts a set of values which the algorithm tries to match with a set
+ * of given set of {@link WithTarget observed values}.
+ * <br/>
+ * The algorithms implemented in this package also require that the user specifies the
+ * Jacobian matrix of the model (represented by a
+ * {@link org.apache.commons.math3.analysis.MultivariateMatrixFunction
+ * MultivariateMatrixFunction}).
+ */
+package org.apache.commons.math3.fitting.leastsquares;

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/fitting/leastsquares/package-info.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optim/BaseOptimizer.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optim/BaseOptimizer.java?rev=1508481&r1=1508480&r2=1508481&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optim/BaseOptimizer.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/optim/BaseOptimizer.java Tue Jul 30 15:04:22 2013
@@ -45,10 +45,21 @@ public abstract class BaseOptimizer<PAIR
      * @param checker Convergence checker.
      */
     protected BaseOptimizer(ConvergenceChecker<PAIR> checker) {
+        this(checker, 0, Integer.MAX_VALUE);
+    }
+
+    /**
+     * @param checker Convergence checker.
+     * @param maxEval Maximum number of objective function evaluations.
+     * @param maxIter Maximum number of algorithm iterations.
+     */
+    protected BaseOptimizer(ConvergenceChecker<PAIR> checker,
+                            int maxEval,
+                            int maxIter) {
         this.checker = checker;
 
-        evaluations = new Incrementor(0, new MaxEvalCallback());
-        iterations = new Incrementor(Integer.MAX_VALUE, new MaxIterCallback());
+        evaluations = new Incrementor(maxEval, new MaxEvalCallback());
+        iterations = new Incrementor(maxIter, new MaxIterCallback());
     }
 
     /**
@@ -144,6 +155,25 @@ public abstract class BaseOptimizer<PAIR
     }
 
     /**
+     * Performs the optimization.
+     *
+     * @return a point/value pair that satifies the convergence criteria.
+     * @throws TooManyEvaluationsException if the maximal number of
+     * evaluations is exceeded.
+     * @throws TooManyIterationsException if the maximal number of
+     * iterations is exceeded.
+     */
+    public PAIR optimize()
+        throws TooManyEvaluationsException,
+               TooManyIterationsException {
+        // Reset counters.
+        evaluations.resetCount();
+        iterations.resetCount();
+        // Perform optimization.
+        return doOptimize();
+    }
+
+    /**
      * Performs the bulk of the optimization algorithm.
      *
      * @return the point/value pair giving the optimal value of the

Added: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerAbstractTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerAbstractTest.java?rev=1508481&view=auto
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerAbstractTest.java (added)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerAbstractTest.java Tue Jul 30 15:04:22 2013
@@ -0,0 +1,643 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.fitting.leastsquares;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Arrays;
+import org.apache.commons.math3.analysis.MultivariateVectorFunction;
+import org.apache.commons.math3.analysis.MultivariateMatrixFunction;
+import org.apache.commons.math3.exception.ConvergenceException;
+import org.apache.commons.math3.exception.DimensionMismatchException;
+import org.apache.commons.math3.exception.NumberIsTooSmallException;
+import org.apache.commons.math3.geometry.euclidean.twod.Vector2D;
+import org.apache.commons.math3.linear.BlockRealMatrix;
+import org.apache.commons.math3.linear.RealMatrix;
+import org.apache.commons.math3.linear.DiagonalMatrix;
+import org.apache.commons.math3.optim.PointVectorValuePair;
+import org.apache.commons.math3.util.FastMath;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Some of the unit tests are re-implementations of the MINPACK
+ * <a href="http://www.netlib.org/minpack/ex/file17">file17</a> and
+ * <a href="http://www.netlib.org/minpack/ex/file22">file22</a> test files.
+ * The redistribution policy for MINPACK is available
+ * <a href="http://www.netlib.org/minpack/disclaimer">here</a>.
+ *
+ * <T> Concrete implementation of an optimizer.
+ *
+ * @version $Id$
+ */
+public abstract class AbstractLeastSquaresOptimizerAbstractTest<T extends AbstractLeastSquaresOptimizer &
+                                                                          WithTarget<T> &
+                                                                          WithWeight<T> &
+                                                                          WithModelAndJacobian<T> &
+                                                                          WithConvergenceChecker<T> &
+                                                                          WithStartPoint<T> &
+                                                                          WithMaxIterations<T> &
+                                                                          WithMaxEvaluations<T>> {
+    /**
+     * @return a concrete optimizer.
+     */
+    public abstract T createOptimizer();
+
+    /**
+     * @return the default number of allowed iterations (which will be
+     * used when not specified otherwise).
+     */
+    public abstract int getMaxIterations();
+
+    @Test
+    public void testGetIterations() {
+        T optim = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withTarget(new double[] { 1 })
+            .withWeight(new DiagonalMatrix(new double[] { 1 }))
+            .withStartPoint(new double[] { 3 })
+            .withModelAndJacobian(new MultivariateVectorFunction() {
+                    public double[] value(double[] point) {
+                        return new double[] {
+                            FastMath.pow(point[0], 4)
+                        };
+                    }},
+                new MultivariateMatrixFunction() {
+                    public double[][] value(double[] point) {
+                        return new double[][] {
+                            { 0.25 * FastMath.pow(point[0], 3) }
+                        };
+                    }
+                });
+
+        optim.optimize();
+        Assert.assertTrue(optim.getIterations() > 0);
+    }
+
+    @Test
+    public void testTrivial() {
+        LinearProblem problem
+            = new LinearProblem(new double[][] { { 2 } },
+                                new double[] { 3 });
+        T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(problem.getTarget())
+            .withWeight(new DiagonalMatrix(new double[] { 1 }))
+            .withStartPoint(new double[] { 0 });
+
+        PointVectorValuePair optimum = optimizer.optimize();
+
+        Assert.assertEquals(0, optimizer.computeRMS(optimum.getPoint()), 1e-10);
+        Assert.assertEquals(1.5, optimum.getPoint()[0], 1e-10);
+        Assert.assertEquals(3.0, optimum.getValue()[0], 1e-10);
+    }
+
+    @Test
+    public void testQRColumnsPermutation() {
+        LinearProblem problem
+            = new LinearProblem(new double[][] { { 1, -1 }, { 0, 2 }, { 1, -2 } },
+                                new double[] { 4, 6, 1 });
+
+        T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(problem.getTarget())
+            .withWeight(new DiagonalMatrix(new double[] { 1, 1, 1 }))
+            .withStartPoint(new double[] { 0, 0 });
+
+        PointVectorValuePair optimum = optimizer.optimize();
+
+        Assert.assertEquals(0, optimizer.computeRMS(optimum.getPoint()), 1e-10);
+        Assert.assertEquals(7, optimum.getPoint()[0], 1e-10);
+        Assert.assertEquals(3, optimum.getPoint()[1], 1e-10);
+        Assert.assertEquals(4, optimum.getValue()[0], 1e-10);
+        Assert.assertEquals(6, optimum.getValue()[1], 1e-10);
+        Assert.assertEquals(1, optimum.getValue()[2], 1e-10);
+    }
+
+    @Test
+    public void testNoDependency() {
+        LinearProblem problem = new LinearProblem(new double[][] {
+                { 2, 0, 0, 0, 0, 0 },
+                { 0, 2, 0, 0, 0, 0 },
+                { 0, 0, 2, 0, 0, 0 },
+                { 0, 0, 0, 2, 0, 0 },
+                { 0, 0, 0, 0, 2, 0 },
+                { 0, 0, 0, 0, 0, 2 }
+        }, new double[] { 0, 1.1, 2.2, 3.3, 4.4, 5.5 });
+        T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(problem.getTarget())
+            .withWeight(new DiagonalMatrix(new double[] { 1, 1, 1, 1, 1, 1 }))
+            .withStartPoint(new double[] { 0, 0, 0, 0, 0, 0 });
+
+        double[] optimum = optimizer.optimize().getPoint();
+        Assert.assertEquals(0, optimizer.computeRMS(optimum), 1e-10);
+        for (int i = 0; i < problem.target.length; ++i) {
+            Assert.assertEquals(0.55 * i, optimum[i], 1e-10);
+        }
+    }
+
+    @Test
+    public void testOneSet() {
+        LinearProblem problem = new LinearProblem(new double[][] {
+                {  1,  0, 0 },
+                { -1,  1, 0 },
+                {  0, -1, 1 }
+        }, new double[] { 1, 1, 1});
+
+        T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(problem.getTarget())
+            .withWeight(new DiagonalMatrix(new double[] { 1, 1, 1 }))
+            .withStartPoint(new double[] { 0, 0, 0 });
+
+        double[] optimum = optimizer.optimize().getPoint();
+        Assert.assertEquals(0, optimizer.computeRMS(optimum), 1e-10);
+        Assert.assertEquals(1, optimum[0], 1e-10);
+        Assert.assertEquals(2, optimum[1], 1e-10);
+        Assert.assertEquals(3, optimum[2], 1e-10);
+    }
+
+    @Test
+    public void testTwoSets() {
+        double epsilon = 1e-7;
+        LinearProblem problem = new LinearProblem(new double[][] {
+                {  2,  1,   0,  4,       0, 0 },
+                { -4, -2,   3, -7,       0, 0 },
+                {  4,  1,  -2,  8,       0, 0 },
+                {  0, -3, -12, -1,       0, 0 },
+                {  0,  0,   0,  0, epsilon, 1 },
+                {  0,  0,   0,  0,       1, 1 }
+        }, new double[] { 2, -9, 2, 2, 1 + epsilon * epsilon, 2});
+
+        T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(problem.getTarget())
+            .withWeight(new DiagonalMatrix(new double[] { 1, 1, 1, 1, 1, 1 }))
+            .withStartPoint(new double[] { 0, 0, 0, 0, 0, 0 });
+
+        double[] optimum = optimizer.optimize().getPoint();
+
+        Assert.assertEquals(0, optimizer.computeRMS(optimum), 1e-10);
+        Assert.assertEquals(3, optimum[0], 1e-10);
+        Assert.assertEquals(4, optimum[1], 1e-10);
+        Assert.assertEquals(-1, optimum[2], 1e-10);
+        Assert.assertEquals(-2, optimum[3], 1e-10);
+        Assert.assertEquals(1 + epsilon, optimum[4], 1e-10);
+        Assert.assertEquals(1 - epsilon, optimum[5], 1e-10);
+    }
+
+    @Test(expected=ConvergenceException.class)
+    public void testNonInvertible() throws Exception {
+        LinearProblem problem = new LinearProblem(new double[][] {
+                {  1, 2, -3 },
+                {  2, 1,  3 },
+                { -3, 0, -9 }
+        }, new double[] { 1, 1, 1 });
+
+        T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(problem.getTarget())
+            .withWeight(new DiagonalMatrix(new double[] { 1, 1, 1 }))
+            .withStartPoint(new double[] { 0, 0, 0 });
+
+        optimizer.optimize();
+    }
+
+    @Test
+    public void testIllConditioned() {
+        LinearProblem problem1 = new LinearProblem(new double[][] {
+                { 10, 7,  8,  7 },
+                {  7, 5,  6,  5 },
+                {  8, 6, 10,  9 },
+                {  7, 5,  9, 10 }
+        }, new double[] { 32, 23, 33, 31 });
+        T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(problem1.getModelFunction(),
+                                  problem1.getModelFunctionJacobian())
+            .withTarget(problem1.getTarget())
+            .withWeight(new DiagonalMatrix(new double[] { 1, 1, 1, 1 }))
+            .withStartPoint(new double[] { 0, 1, 2, 3 });
+
+        double[] optimum = optimizer.optimize().getPoint();
+
+        Assert.assertEquals(0, optimizer.computeRMS(optimum), 1e-10);
+        Assert.assertEquals(1, optimum[0], 1e-10);
+        Assert.assertEquals(1, optimum[1], 1e-10);
+        Assert.assertEquals(1, optimum[2], 1e-10);
+        Assert.assertEquals(1, optimum[3], 1e-10);
+
+        LinearProblem problem2 = new LinearProblem(new double[][] {
+                { 10.00, 7.00, 8.10, 7.20 },
+                {  7.08, 5.04, 6.00, 5.00 },
+                {  8.00, 5.98, 9.89, 9.00 },
+                {  6.99, 4.99, 9.00, 9.98 }
+        }, new double[] { 32, 23, 33, 31 });
+
+        optimizer = optimizer
+            .withModelAndJacobian(problem2.getModelFunction(),
+                                  problem2.getModelFunctionJacobian())
+            .withTarget(problem2.getTarget());
+
+        optimum = optimizer.optimize().getPoint();
+
+        Assert.assertEquals(0, optimizer.computeRMS(optimum), 1e-10);
+        Assert.assertEquals(-81, optimum[0], 1e-8);
+        Assert.assertEquals(137, optimum[1], 1e-8);
+        Assert.assertEquals(-34, optimum[2], 1e-8);
+        Assert.assertEquals( 22, optimum[3], 1e-8);
+    }
+
+    @Test
+    public void testMoreEstimatedParametersSimple() {
+        LinearProblem problem = new LinearProblem(new double[][] {
+                { 3, 2,  0, 0 },
+                { 0, 1, -1, 1 },
+                { 2, 0,  1, 0 }
+        }, new double[] { 7, 3, 5 });
+
+        T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(problem.getTarget())
+            .withWeight(new DiagonalMatrix(new double[] { 1, 1, 1 }))
+            .withStartPoint(new double[] { 7, 6, 5, 4 });
+
+        double[] optimum = optimizer.optimize().getPoint();
+        Assert.assertEquals(0, optimizer.computeRMS(optimum), 1e-10);
+    }
+
+    @Test
+    public void testMoreEstimatedParametersUnsorted() {
+        LinearProblem problem = new LinearProblem(new double[][] {
+                { 1, 1,  0,  0, 0,  0 },
+                { 0, 0,  1,  1, 1,  0 },
+                { 0, 0,  0,  0, 1, -1 },
+                { 0, 0, -1,  1, 0,  1 },
+                { 0, 0,  0, -1, 1,  0 }
+       }, new double[] { 3, 12, -1, 7, 1 });
+
+        T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(problem.getTarget())
+            .withWeight(new DiagonalMatrix(new double[] { 1, 1, 1, 1, 1 }))
+            .withStartPoint(new double[] { 2, 2, 2, 2, 2, 2 });
+
+        double[] optimum = optimizer.optimize().getPoint();
+
+        Assert.assertEquals(0, optimizer.computeRMS(optimum), 1e-10);
+        Assert.assertEquals(3, optimum[2], 1e-10);
+        Assert.assertEquals(4, optimum[3], 1e-10);
+        Assert.assertEquals(5, optimum[4], 1e-10);
+        Assert.assertEquals(6, optimum[5], 1e-10);
+    }
+
+    @Test
+    public void testRedundantEquations() {
+        LinearProblem problem = new LinearProblem(new double[][] {
+                { 1,  1 },
+                { 1, -1 },
+                { 1,  3 }
+        }, new double[] { 3, 1, 5 });
+
+        T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(problem.getTarget())
+            .withWeight(new DiagonalMatrix(new double[] { 1, 1, 1 }))
+            .withStartPoint(new double[] { 1, 1 });
+
+        double[] optimum = optimizer.optimize().getPoint();
+
+        Assert.assertEquals(0, optimizer.computeRMS(optimum), 1e-10);
+        Assert.assertEquals(2, optimum[0], 1e-10);
+        Assert.assertEquals(1, optimum[1], 1e-10);
+    }
+
+    @Test
+    public void testInconsistentEquations() {
+        LinearProblem problem = new LinearProblem(new double[][] {
+                { 1,  1 },
+                { 1, -1 },
+                { 1,  3 }
+        }, new double[] { 3, 1, 4 });
+
+        T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(problem.getTarget())
+            .withWeight(new DiagonalMatrix(new double[] { 1, 1, 1 }))
+            .withStartPoint(new double[] { 1, 1 });
+
+        double[] optimum = optimizer.optimize().getPoint();
+
+        Assert.assertTrue(optimizer.computeRMS(optimum) > 0.1);
+    }
+
+    @Test(expected=DimensionMismatchException.class)
+    public void testInconsistentSizes1() {
+        LinearProblem problem
+            = new LinearProblem(new double[][] { { 1, 0 },
+                                                 { 0, 1 } },
+                                new double[] { -1, 1 });
+        T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(problem.getTarget())
+            .withWeight(new DiagonalMatrix(new double[] { 1, 1 }))
+            .withStartPoint(new double[] { 0, 0 });
+
+        double[] optimum = optimizer.optimize().getPoint();
+
+        Assert.assertEquals(0, optimizer.computeRMS(optimum), 1e-10);
+        Assert.assertEquals(-1, optimum[0], 1e-10);
+        Assert.assertEquals(1, optimum[1], 1e-10);
+
+        optimizer.withWeight(new DiagonalMatrix(new double[] { 1 })).optimize();
+    }
+
+    @Test(expected=DimensionMismatchException.class)
+    public void testInconsistentSizes2() {
+        LinearProblem problem
+            = new LinearProblem(new double[][] { { 1, 0 }, { 0, 1 } },
+                                new double[] { -1, 1 });
+
+        T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(problem.getTarget())
+            .withWeight(new DiagonalMatrix(new double[] { 1, 1 }))
+            .withStartPoint(new double[] { 0, 0 });
+
+        double[] optimum = optimizer.optimize().getPoint();
+
+        Assert.assertEquals(0, optimizer.computeRMS(optimum), 1e-10);
+        Assert.assertEquals(-1, optimum[0], 1e-10);
+        Assert.assertEquals(1, optimum[1], 1e-10);
+
+        optimizer
+            .withTarget(new double[] { 1 })
+            .withWeight(new DiagonalMatrix(new double[] { 1 }))
+            .optimize();
+    }
+
+    @Test
+    public void testCircleFitting() {
+        CircleVectorial circle = new CircleVectorial();
+        circle.addPoint( 30,  68);
+        circle.addPoint( 50,  -6);
+        circle.addPoint(110, -20);
+        circle.addPoint( 35,  15);
+        circle.addPoint( 45,  97);
+
+        T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(circle.getModelFunction(),
+                                  circle.getModelFunctionJacobian())
+            .withTarget(new double[] { 0, 0, 0, 0, 0 })
+            .withWeight(new DiagonalMatrix(new double[] { 1, 1, 1, 1, 1 }))
+            .withStartPoint(new double[] { 98.680, 47.345 });
+
+        double[] optimum = optimizer.optimize().getPoint();
+        Assert.assertTrue(optimizer.getEvaluations() < 10);
+
+        double rms = optimizer.computeRMS(optimum);
+        Assert.assertEquals(1.768262623567235,  FastMath.sqrt(circle.getN()) * rms, 1e-10);
+
+        Vector2D center = new Vector2D(optimum[0], optimum[1]);
+        Assert.assertEquals(69.96016176931406, circle.getRadius(center), 1e-6);
+        Assert.assertEquals(96.07590211815305, center.getX(), 1e-6);
+        Assert.assertEquals(48.13516790438953, center.getY(), 1e-6);
+
+        double[][] cov = optimizer.computeCovariances(optimum, 1e-14);
+        Assert.assertEquals(1.839, cov[0][0], 0.001);
+        Assert.assertEquals(0.731, cov[0][1], 0.001);
+        Assert.assertEquals(cov[0][1], cov[1][0], 1e-14);
+        Assert.assertEquals(0.786, cov[1][1], 0.001);
+
+        // add perfect measurements and check errors are reduced
+        double  r = circle.getRadius(center);
+        for (double d= 0; d < 2 * FastMath.PI; d += 0.01) {
+            circle.addPoint(center.getX() + r * FastMath.cos(d), center.getY() + r * FastMath.sin(d));
+        }
+
+        double[] target = new double[circle.getN()];
+        Arrays.fill(target, 0);
+        double[] weights = new double[circle.getN()];
+        Arrays.fill(weights, 2);
+        optimizer = optimizer.withTarget(target).withWeight(new DiagonalMatrix(weights));
+        optimum = optimizer.optimize().getPoint();
+
+        cov = optimizer.computeCovariances(optimum, 1e-14);
+        Assert.assertEquals(0.0016, cov[0][0], 0.001);
+        Assert.assertEquals(3.2e-7, cov[0][1], 1e-9);
+        Assert.assertEquals(cov[0][1], cov[1][0], 1e-14);
+        Assert.assertEquals(0.0016, cov[1][1], 0.001);
+    }
+
+    @Test
+    public void testCircleFittingBadInit() {
+        CircleVectorial circle = new CircleVectorial();
+        double[][] points = circlePoints;
+        double[] target = new double[points.length];
+        Arrays.fill(target, 0);
+        double[] weights = new double[points.length];
+        Arrays.fill(weights, 2);
+        for (int i = 0; i < points.length; ++i) {
+            circle.addPoint(points[i][0], points[i][1]);
+        }
+        T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(circle.getModelFunction(),
+                                  circle.getModelFunctionJacobian())
+            .withTarget(target)
+            .withWeight(new DiagonalMatrix(weights))
+            .withStartPoint(new double[] { -12, -12 });
+
+        double[] optimum = optimizer.optimize().getPoint();
+
+        Vector2D center = new Vector2D(optimum[0], optimum[1]);
+        Assert.assertTrue(optimizer.getEvaluations() < 25);
+        Assert.assertEquals( 0.043, optimizer.computeRMS(optimum), 1e-3);
+        Assert.assertEquals( 0.292235,  circle.getRadius(center), 1e-6);
+        Assert.assertEquals(-0.151738,  center.getX(), 1e-6);
+        Assert.assertEquals( 0.2075001, center.getY(), 1e-6);
+    }
+
+    @Test
+    public void testCircleFittingGoodInit() {
+        CircleVectorial circle = new CircleVectorial();
+        double[][] points = circlePoints;
+        double[] target = new double[points.length];
+        Arrays.fill(target, 0);
+        double[] weights = new double[points.length];
+        Arrays.fill(weights, 2);
+        for (int i = 0; i < points.length; ++i) {
+            circle.addPoint(points[i][0], points[i][1]);
+        }
+        T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(circle.getModelFunction(),
+                                  circle.getModelFunctionJacobian())
+            .withTarget(target)
+            .withWeight(new DiagonalMatrix(weights))
+            .withStartPoint(new double[] { 0, 0 });
+
+        double[] optimum = optimizer.optimize().getPoint();
+
+        Assert.assertEquals(-0.1517383071957963, optimum[0], 1e-6);
+        Assert.assertEquals(0.2074999736353867,  optimum[1], 1e-6);
+        Assert.assertEquals(0.04268731682389561, optimizer.computeRMS(optimum), 1e-8);
+    }
+
+    private final double[][] circlePoints = new double[][] {
+        {-0.312967,  0.072366}, {-0.339248,  0.132965}, {-0.379780,  0.202724},
+        {-0.390426,  0.260487}, {-0.361212,  0.328325}, {-0.346039,  0.392619},
+        {-0.280579,  0.444306}, {-0.216035,  0.470009}, {-0.149127,  0.493832},
+        {-0.075133,  0.483271}, {-0.007759,  0.452680}, { 0.060071,  0.410235},
+        { 0.103037,  0.341076}, { 0.118438,  0.273884}, { 0.131293,  0.192201},
+        { 0.115869,  0.129797}, { 0.072223,  0.058396}, { 0.022884,  0.000718},
+        {-0.053355, -0.020405}, {-0.123584, -0.032451}, {-0.216248, -0.032862},
+        {-0.278592, -0.005008}, {-0.337655,  0.056658}, {-0.385899,  0.112526},
+        {-0.405517,  0.186957}, {-0.415374,  0.262071}, {-0.387482,  0.343398},
+        {-0.347322,  0.397943}, {-0.287623,  0.458425}, {-0.223502,  0.475513},
+        {-0.135352,  0.478186}, {-0.061221,  0.483371}, { 0.003711,  0.422737},
+        { 0.065054,  0.375830}, { 0.108108,  0.297099}, { 0.123882,  0.222850},
+        { 0.117729,  0.134382}, { 0.085195,  0.056820}, { 0.029800, -0.019138},
+        {-0.027520, -0.072374}, {-0.102268, -0.091555}, {-0.200299, -0.106578},
+        {-0.292731, -0.091473}, {-0.356288, -0.051108}, {-0.420561,  0.014926},
+        {-0.471036,  0.074716}, {-0.488638,  0.182508}, {-0.485990,  0.254068},
+        {-0.463943,  0.338438}, {-0.406453,  0.404704}, {-0.334287,  0.466119},
+        {-0.254244,  0.503188}, {-0.161548,  0.495769}, {-0.075733,  0.495560},
+        { 0.001375,  0.434937}, { 0.082787,  0.385806}, { 0.115490,  0.323807},
+        { 0.141089,  0.223450}, { 0.138693,  0.131703}, { 0.126415,  0.049174},
+        { 0.066518, -0.010217}, {-0.005184, -0.070647}, {-0.080985, -0.103635},
+        {-0.177377, -0.116887}, {-0.260628, -0.100258}, {-0.335756, -0.056251},
+        {-0.405195, -0.000895}, {-0.444937,  0.085456}, {-0.484357,  0.175597},
+        {-0.472453,  0.248681}, {-0.438580,  0.347463}, {-0.402304,  0.422428},
+        {-0.326777,  0.479438}, {-0.247797,  0.505581}, {-0.152676,  0.519380},
+        {-0.071754,  0.516264}, { 0.015942,  0.472802}, { 0.076608,  0.419077},
+        { 0.127673,  0.330264}, { 0.159951,  0.262150}, { 0.153530,  0.172681},
+        { 0.140653,  0.089229}, { 0.078666,  0.024981}, { 0.023807, -0.037022},
+        {-0.048837, -0.077056}, {-0.127729, -0.075338}, {-0.221271, -0.067526}
+    };
+
+    public void doTestStRD(final StatisticalReferenceDataset dataset,
+                           final double errParams,
+                           final double errParamsSd) {
+        final double[] w = new double[dataset.getNumObservations()];
+        Arrays.fill(w, 1);
+
+        final double[][] data = dataset.getData();
+        final double[] initial = dataset.getStartingPoint(0);
+        final StatisticalReferenceDataset.LeastSquaresProblem problem = dataset.getLeastSquaresProblem();
+
+        final T optimizer = createOptimizer()
+            .withMaxEvaluations(100)
+            .withMaxIterations(getMaxIterations())
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(data[1])
+            .withWeight(new DiagonalMatrix(w))
+            .withStartPoint(initial);
+
+        final double[] actual = optimizer.optimize().getPoint();
+        for (int i = 0; i < actual.length; i++) {
+            double expected = dataset.getParameter(i);
+            double delta = FastMath.abs(errParams * expected);
+            Assert.assertEquals(dataset.getName() + ", param #" + i,
+                                expected, actual[i], delta);
+        }
+    }
+
+    @Test
+    public void testKirby2() throws IOException {
+        doTestStRD(StatisticalReferenceDatasetFactory.createKirby2(), 1E-7, 1E-7);
+    }
+
+    @Test
+    public void testHahn1() throws IOException {
+        doTestStRD(StatisticalReferenceDatasetFactory.createHahn1(), 1E-7, 1E-4);
+    }
+
+    static class LinearProblem {
+        private final RealMatrix factors;
+        private final double[] target;
+
+        public LinearProblem(double[][] factors, double[] target) {
+            this.factors = new BlockRealMatrix(factors);
+            this.target  = target;
+        }
+
+        public double[] getTarget() {
+            return target;
+        }
+
+        public MultivariateVectorFunction getModelFunction() {
+            return new MultivariateVectorFunction() {
+                public double[] value(double[] params) {
+                    return factors.operate(params);
+                }
+            };
+        }
+
+        public MultivariateMatrixFunction getModelFunctionJacobian() {
+            return new MultivariateMatrixFunction() {
+                public double[][] value(double[] params) {
+                    return factors.getData();
+                }
+            };
+        }
+    }
+}

Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerAbstractTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerAbstractTest.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision

Added: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerTest.java?rev=1508481&view=auto
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerTest.java (added)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerTest.java Tue Jul 30 15:04:22 2013
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
+ * or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.apache.commons.math3.fitting.leastsquares;
+
+import java.io.IOException;
+import java.util.Arrays;
+import org.apache.commons.math3.optim.PointVectorValuePair;
+import org.apache.commons.math3.linear.DiagonalMatrix;
+import org.apache.commons.math3.util.FastMath;
+import org.junit.Test;
+import org.junit.Assert;
+/**
+ * The only features tested here are utility methods defined
+ * in {@link AbstractLeastSquaresOptimizer} that compute the
+ * chi-square and parameters standard-deviations.
+ */
+public class AbstractLeastSquaresOptimizerTest {
+    @Test
+    public void testComputeCost() throws IOException {
+        final StatisticalReferenceDataset dataset
+            = StatisticalReferenceDatasetFactory.createKirby2();
+        final double[] a = dataset.getParameters();
+        final double[] y = dataset.getData()[1];
+        final double[] w = new double[y.length];
+        Arrays.fill(w, 1d);
+
+        StatisticalReferenceDataset.LeastSquaresProblem problem
+            = dataset.getLeastSquaresProblem();
+
+        final LevenbergMarquardtOptimizer optim = LevenbergMarquardtOptimizer.create()
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(y)
+            .withWeight(new DiagonalMatrix(w))
+            .withStartPoint(a);
+
+        final double expected = dataset.getResidualSumOfSquares();
+        final double cost = optim.computeCost(optim.computeResiduals(optim.getModel().value(optim.getStart())));
+        final double actual = cost * cost;
+        Assert.assertEquals(dataset.getName(), expected, actual, 1e-11 * expected);
+    }
+
+    @Test
+    public void testComputeRMS() throws IOException {
+        final StatisticalReferenceDataset dataset
+            = StatisticalReferenceDatasetFactory.createKirby2();
+        final double[] a = dataset.getParameters();
+        final double[] y = dataset.getData()[1];
+        final double[] w = new double[y.length];
+        Arrays.fill(w, 1d);
+
+        StatisticalReferenceDataset.LeastSquaresProblem problem
+            = dataset.getLeastSquaresProblem();
+
+        final LevenbergMarquardtOptimizer optim = LevenbergMarquardtOptimizer.create()
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(y)
+            .withWeight(new DiagonalMatrix(w))
+            .withStartPoint(a);
+
+        final double expected = FastMath.sqrt(dataset.getResidualSumOfSquares() /
+                                              dataset.getNumObservations());
+        final double actual = optim.computeRMS(optim.getStart());
+        Assert.assertEquals(dataset.getName(), expected, actual, 1e-11 * expected);
+    }
+
+    @Test
+    public void testComputeSigma() throws IOException {
+        final StatisticalReferenceDataset dataset
+            = StatisticalReferenceDatasetFactory.createKirby2();
+        final double[] a = dataset.getParameters();
+        final double[] y = dataset.getData()[1];
+        final double[] w = new double[y.length];
+        Arrays.fill(w, 1d);
+
+        StatisticalReferenceDataset.LeastSquaresProblem problem
+            = dataset.getLeastSquaresProblem();
+
+        final LevenbergMarquardtOptimizer optim = LevenbergMarquardtOptimizer.create()
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(y)
+            .withWeight(new DiagonalMatrix(w))
+            .withStartPoint(a);
+
+        final double[] expected = dataset.getParametersStandardDeviations();
+
+        final double cost = optim.computeCost(optim.computeResiduals(optim.getModel().value(optim.getStart())));
+        final double[] sig = optim.computeSigma(optim.getStart(), 1e-14);
+        final int dof = y.length - a.length;
+        for (int i = 0; i < sig.length; i++) {
+            final double actual = FastMath.sqrt(cost * cost / dof) * sig[i];
+            Assert.assertEquals(dataset.getName() + ", parameter #" + i,
+                                expected[i], actual, 1e-6 * expected[i]);
+        }
+    }
+}

Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerTest.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision

Added: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerTestValidation.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerTestValidation.java?rev=1508481&view=auto
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerTestValidation.java (added)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerTestValidation.java Tue Jul 30 15:04:22 2013
@@ -0,0 +1,308 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
+ * or agreed to in writing, software distributed under the License is
+ * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.apache.commons.math3.fitting.leastsquares;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.ArrayList;
+import java.awt.geom.Point2D;
+import org.apache.commons.math3.optim.PointVectorValuePair;
+import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
+import org.apache.commons.math3.stat.descriptive.StatisticalSummary;
+import org.apache.commons.math3.linear.DiagonalMatrix;
+import org.apache.commons.math3.util.FastMath;
+import org.junit.Test;
+import org.junit.Assert;
+
+/**
+ * This class demonstrates the main functionality of the
+ * {@link AbstractLeastSquaresOptimizer}, common to the
+ * optimizer implementations in package
+ * {@link org.apache.commons.math3.fitting.leastsquares}.
+ * <br/>
+ * Not enabled by default, as the class name does not end with "Test".
+ * <br/>
+ * Invoke by running
+ * <pre><code>
+ *  mvn test -Dtest=AbstractLeastSquaresOptimizerTestValidation
+ * </code></pre>
+ * or by running
+ * <pre><code>
+ *  mvn test -Dtest=AbstractLeastSquaresOptimizerTestValidation -DargLine="-DmcRuns=1234 -server"
+ * </code></pre>
+ */
+public class AbstractLeastSquaresOptimizerTestValidation {
+    /** Number of runs. */
+    private static final int MONTE_CARLO_RUNS = Integer.parseInt(System.getProperty("mcRuns",
+                                                                                    "100"));
+
+    /**
+     * Using a Monte-Carlo procedure, this test checks the error estimations
+     * as provided by the square-root of the diagonal elements of the
+     * covariance matrix.
+     * <br/>
+     * The test generates sets of observations, each sampled from
+     * a Gaussian distribution.
+     * <br/>
+     * The optimization problem solved is defined in class
+     * {@link StraightLineProblem}.
+     * <br/>
+     * The output (on stdout) will be a table summarizing the distribution
+     * of parameters generated by the Monte-Carlo process and by the direct
+     * estimation provided by the diagonal elements of the covariance matrix.
+     */
+    @Test
+    public void testParametersErrorMonteCarloObservations() {
+        // Error on the observations.
+        final double yError = 15;
+
+        // True values of the parameters.
+        final double slope = 123.456;
+        final double offset = -98.765;
+
+        // Samples generator.
+        final RandomStraightLinePointGenerator lineGenerator
+            = new RandomStraightLinePointGenerator(slope, offset,
+                                                   yError,
+                                                   -1e3, 1e4,
+                                                   138577L);
+
+        // Number of observations.
+        final int numObs = 100; // XXX Should be a command-line option.
+        // number of parameters.
+        final int numParams = 2;
+
+        // Parameters found for each of Monte-Carlo run.
+        final SummaryStatistics[] paramsFoundByDirectSolution = new SummaryStatistics[numParams];
+        // Sigma estimations (square-root of the diagonal elements of the
+        // covariance matrix), for each Monte-Carlo run.
+        final SummaryStatistics[] sigmaEstimate = new SummaryStatistics[numParams];
+
+        // Initialize statistics accumulators.
+        for (int i = 0; i < numParams; i++) {
+            paramsFoundByDirectSolution[i] = new SummaryStatistics();
+            sigmaEstimate[i] = new SummaryStatistics();
+        }
+
+        final double[] init = { slope, offset };
+
+        // Monte-Carlo (generates many sets of observations).
+        final int mcRepeat = MONTE_CARLO_RUNS;
+        int mcCount = 0;
+        while (mcCount < mcRepeat) {
+            // Observations.
+            final Point2D.Double[] obs = lineGenerator.generate(numObs);
+
+            final StraightLineProblem problem = new StraightLineProblem(yError);
+            for (int i = 0; i < numObs; i++) {
+                final Point2D.Double p = obs[i];
+                problem.addPoint(p.x, p.y);
+            }
+
+            // Direct solution (using simple regression).
+            final double[] regress = problem.solve();
+
+            // Estimation of the standard deviation (diagonal elements of the
+            // covariance matrix).
+            // Dummy optimizer (to compute the covariance matrix).
+            final AbstractLeastSquaresOptimizer optim = LevenbergMarquardtOptimizer.create()
+                .withModelAndJacobian(problem.getModelFunction(),
+                                      problem.getModelFunctionJacobian())
+                .withTarget(problem.target())
+                .withWeight(new DiagonalMatrix(problem.weight()));
+
+            final double[] sigma = optim.computeSigma(init, 1e-14);
+
+            // Accumulate statistics.
+            for (int i = 0; i < numParams; i++) {
+                paramsFoundByDirectSolution[i].addValue(regress[i]);
+                sigmaEstimate[i].addValue(sigma[i]);
+            }
+
+            // Next Monte-Carlo.
+            ++mcCount;
+        }
+
+        // Print statistics.
+        final String line = "--------------------------------------------------------------";
+        System.out.println("                 True value       Mean        Std deviation");
+        for (int i = 0; i < numParams; i++) {
+            System.out.println(line);
+            System.out.println("Parameter #" + i);
+
+            StatisticalSummary s = paramsFoundByDirectSolution[i].getSummary();
+            System.out.printf("              %+.6e   %+.6e   %+.6e\n",
+                              init[i],
+                              s.getMean(),
+                              s.getStandardDeviation());
+
+            s = sigmaEstimate[i].getSummary();
+            System.out.printf("sigma: %+.6e (%+.6e)\n",
+                              s.getMean(),
+                              s.getStandardDeviation());
+        }
+        System.out.println(line);
+
+        // Check the error estimation.
+        for (int i = 0; i < numParams; i++) {
+            Assert.assertEquals(paramsFoundByDirectSolution[i].getSummary().getStandardDeviation(),
+                                sigmaEstimate[i].getSummary().getMean(),
+                                8e-2);
+        }
+    }
+
+    /**
+     * In this test, the set of observations is fixed.
+     * Using a Monte-Carlo procedure, it generates sets of parameters,
+     * and determine the parameter change that will result in the
+     * normalized chi-square becoming larger by one than the value from
+     * the best fit solution.
+     * <br/>
+     * The optimization problem solved is defined in class
+     * {@link StraightLineProblem}.
+     * <br/>
+     * The output (on stdout) will be a list of lines containing:
+     * <ul>
+     *  <li>slope of the straight line,</li>
+     *  <li>intercept of the straight line,</li>
+     *  <li>chi-square of the solution defined by the above two values.</li>
+     * </ul>
+     * The output is separated into two blocks (with a blank line between
+     * them); the first block will contain all parameter sets for which
+     * {@code chi2 < chi2_b + 1}
+     * and the second block, all sets for which
+     * {@code chi2 >= chi2_b + 1}
+     * where {@code chi2_b} is the lowest chi-square (corresponding to the
+     * best solution).
+     */
+    @Test
+    public void testParametersErrorMonteCarloParameters() {
+        // Error on the observations.
+        final double yError = 15;
+
+        // True values of the parameters.
+        final double slope = 123.456;
+        final double offset = -98.765;
+
+        // Samples generator.
+        final RandomStraightLinePointGenerator lineGenerator
+            = new RandomStraightLinePointGenerator(slope, offset,
+                                                   yError,
+                                                   -1e3, 1e4,
+                                                   13839013L);
+
+        // Number of observations.
+        final int numObs = 10;
+        // number of parameters.
+        final int numParams = 2;
+
+        // Create a single set of observations.
+        final Point2D.Double[] obs = lineGenerator.generate(numObs);
+
+        final StraightLineProblem problem = new StraightLineProblem(yError);
+        for (int i = 0; i < numObs; i++) {
+            final Point2D.Double p = obs[i];
+            problem.addPoint(p.x, p.y);
+        }
+
+        // Direct solution (using simple regression).
+        final double[] regress = problem.solve();
+
+        // Dummy optimizer (to compute the chi-square).
+        final AbstractLeastSquaresOptimizer optim = LevenbergMarquardtOptimizer.create()
+            .withModelAndJacobian(problem.getModelFunction(),
+                                  problem.getModelFunctionJacobian())
+            .withTarget(problem.target())
+            .withWeight(new DiagonalMatrix(problem.weight()));
+
+        final double[] init = { slope, offset };
+        // Get chi-square of the best parameters set for the given set of
+        // observations.
+        final double bestChi2N = getChi2N(optim, problem, regress);
+        final double[] sigma = optim.computeSigma(regress, 1e-14);
+
+        // Monte-Carlo (generates a grid of parameters).
+        final int mcRepeat = MONTE_CARLO_RUNS;
+        final int gridSize = (int) FastMath.sqrt(mcRepeat);
+
+        // Parameters found for each of Monte-Carlo run.
+        // Index 0 = slope
+        // Index 1 = offset
+        // Index 2 = normalized chi2
+        final List<double[]> paramsAndChi2 = new ArrayList<double[]>(gridSize * gridSize);
+
+        final double slopeRange = 10 * sigma[0];
+        final double offsetRange = 10 * sigma[1];
+        final double minSlope = slope - 0.5 * slopeRange;
+        final double minOffset = offset - 0.5 * offsetRange;
+        final double deltaSlope =  slopeRange/ gridSize;
+        final double deltaOffset = offsetRange / gridSize;
+        for (int i = 0; i < gridSize; i++) {
+            final double s = minSlope + i * deltaSlope;
+            for (int j = 0; j < gridSize; j++) {
+                final double o = minOffset + j * deltaOffset;
+                final double chi2N = getChi2N(optim, problem, new double[] {s, o});
+
+                paramsAndChi2.add(new double[] {s, o, chi2N});
+            }
+        }
+
+        // Output (for use with "gnuplot").
+
+        // Some info.
+
+        // For plotting separately sets of parameters that have a large chi2.
+        final double chi2NPlusOne = bestChi2N + 1;
+        int numLarger = 0;
+
+        final String lineFmt = "%+.10e %+.10e   %.8e\n";
+
+        // Point with smallest chi-square.
+        System.out.printf(lineFmt, regress[0], regress[1], bestChi2N);
+        System.out.println(); // Empty line.
+
+        // Points within the confidence interval.
+        for (double[] d : paramsAndChi2) {
+            if (d[2] <= chi2NPlusOne) {
+                System.out.printf(lineFmt, d[0], d[1], d[2]);
+            }
+        }
+        System.out.println(); // Empty line.
+
+        // Points outside the confidence interval.
+        for (double[] d : paramsAndChi2) {
+            if (d[2] > chi2NPlusOne) {
+                ++numLarger;
+                System.out.printf(lineFmt, d[0], d[1], d[2]);
+            }
+        }
+        System.out.println(); // Empty line.
+
+        System.out.println("# sigma=" + Arrays.toString(sigma));
+        System.out.println("# " + numLarger + " sets filtered out");
+    }
+
+    /**
+     * @return the normalized chi-square.
+     */
+    private double getChi2N(AbstractLeastSquaresOptimizer optim,
+                            StraightLineProblem problem,
+                            double[] params) {
+        final double[] t = problem.target();
+        final double[] w = problem.weight();
+        final double cost = optim.computeCost(optim.computeResiduals(optim.getModel().value(params)));
+        return cost * cost / (t.length - params.length);
+    }
+}
+

Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerTestValidation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/AbstractLeastSquaresOptimizerTestValidation.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision

Added: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/CircleProblem.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/CircleProblem.java?rev=1508481&view=auto
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/CircleProblem.java (added)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/CircleProblem.java Tue Jul 30 15:04:22 2013
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.fitting.leastsquares;
+
+import java.util.ArrayList;
+import org.apache.commons.math3.analysis.MultivariateVectorFunction;
+import org.apache.commons.math3.analysis.MultivariateMatrixFunction;
+import org.apache.commons.math3.util.MathUtils;
+import org.apache.commons.math3.util.FastMath;
+
+/**
+ * Class that models a circle.
+ * The parameters of problem are:
+ * <ul>
+ *  <li>the x-coordinate of the circle center,</li>
+ *  <li>the y-coordinate of the circle center,</li>
+ *  <li>the radius of the circle.</li>
+ * </ul>
+ * The model functions are:
+ * <ul>
+ *  <li>for each triplet (cx, cy, r), the (x, y) coordinates of a point on the
+ *   corresponding circle.</li>
+ * </ul>
+ */
+class CircleProblem {
+    /** Cloud of points assumed to be fitted by a circle. */
+    private final ArrayList<double[]> points;
+    /** Error on the x-coordinate of the points. */
+    private final double xSigma;
+    /** Error on the y-coordinate of the points. */
+    private final double ySigma;
+    /** Number of points on the circumference (when searching which
+        model point is closest to a given "observation". */
+    private final int resolution;
+
+    /**
+     * @param xError Assumed error for the x-coordinate of the circle points.
+     * @param yError Assumed error for the y-coordinate of the circle points.
+     * @param searchResolution Number of points to try when searching the one
+     * that is closest to a given "observed" point.
+     */
+    public CircleProblem(double xError,
+                         double yError,
+                         int searchResolution) {
+        points = new ArrayList<double[]>();
+        xSigma = xError;
+        ySigma = yError;
+        resolution = searchResolution;
+    }
+
+    /**
+     * @param xError Assumed error for the x-coordinate of the circle points.
+     * @param yError Assumed error for the y-coordinate of the circle points.
+     */
+    public CircleProblem(double xError,
+                         double yError) {
+        this(xError, yError, 500);
+    }
+
+    public void addPoint(double px, double py) {
+        points.add(new double[] { px, py });
+    }
+
+    public double[] target() {
+        final double[] t = new double[points.size() * 2];
+        for (int i = 0; i < points.size(); i++) {
+            final double[] p = points.get(i);
+            final int index = i * 2;
+            t[index] = p[0];
+            t[index + 1] = p[1];
+        }
+
+        return t;
+    }
+
+    public double[] weight() {
+        final double wX = 1 / (xSigma * xSigma);
+        final double wY = 1 / (ySigma * ySigma);
+        final double[] w = new double[points.size() * 2];
+        for (int i = 0; i < points.size(); i++) {
+            final int index = i * 2;
+            w[index] = wX;
+            w[index + 1] = wY;
+        }
+
+        return w;
+    }
+
+    public MultivariateVectorFunction getModelFunction() {
+        return new MultivariateVectorFunction() {
+            public double[] value(double[] params) {
+                final double cx = params[0];
+                final double cy = params[1];
+                final double r = params[2];
+
+                final double[] model = new double[points.size() * 2];
+
+                final double deltaTheta = MathUtils.TWO_PI / resolution;
+                for (int i = 0; i < points.size(); i++) {
+                    final double[] p = points.get(i);
+                    final double px = p[0];
+                    final double py = p[1];
+
+                    double bestX = 0;
+                    double bestY = 0;
+                    double dMin = Double.POSITIVE_INFINITY;
+
+                    // Find the angle for which the circle passes closest to the
+                    // current point (using a resolution of 100 points along the
+                    // circumference).
+                    for (double theta = 0; theta <= MathUtils.TWO_PI; theta += deltaTheta) {
+                        final double currentX = cx + r * FastMath.cos(theta);
+                        final double currentY = cy + r * FastMath.sin(theta);
+                        final double dX = currentX - px;
+                        final double dY = currentY - py;
+                        final double d = dX * dX + dY * dY;
+                        if (d < dMin) {
+                            dMin = d;
+                            bestX = currentX;
+                            bestY = currentY;
+                        }
+                    }
+
+                    final int index = i * 2;
+                    model[index] = bestX;
+                    model[index + 1] = bestY;
+                }
+
+                return model;
+            }
+        };
+    }
+
+    public MultivariateMatrixFunction getModelFunctionJacobian() {
+        return new MultivariateMatrixFunction() {
+            public double[][] value(double[] point) {
+                return jacobian(point);
+            }
+        };
+    }
+
+    private double[][] jacobian(double[] params) {
+        final double[][] jacobian = new double[points.size() * 2][3];
+
+        for (int i = 0; i < points.size(); i++) {
+            final int index = i * 2;
+            // Partial derivative wrt x-coordinate of center. 
+            jacobian[index][0] = 1;
+            jacobian[index + 1][0] = 0;
+            // Partial derivative wrt y-coordinate of center.
+            jacobian[index][1] = 0;
+            jacobian[index + 1][1] = 1;
+            // Partial derivative wrt radius.
+            final double[] p = points.get(i);
+            jacobian[index][2] = (p[0] - params[0]) / params[2];
+            jacobian[index + 1][2] = (p[1] - params[1]) / params[2];
+        }
+
+        return jacobian;
+    }
+}

Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/CircleProblem.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/CircleProblem.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision

Added: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/CircleVectorial.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/CircleVectorial.java?rev=1508481&view=auto
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/CircleVectorial.java (added)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/CircleVectorial.java Tue Jul 30 15:04:22 2013
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.fitting.leastsquares;
+
+import java.util.ArrayList;
+import org.apache.commons.math3.analysis.MultivariateVectorFunction;
+import org.apache.commons.math3.analysis.MultivariateMatrixFunction;
+import org.apache.commons.math3.geometry.euclidean.twod.Vector2D;
+
+/**
+ * Class used in the tests.
+ */
+class CircleVectorial {
+    private ArrayList<Vector2D> points;
+
+    public CircleVectorial() {
+        points  = new ArrayList<Vector2D>();
+    }
+
+    public void addPoint(double px, double py) {
+        points.add(new Vector2D(px, py));
+    }
+
+    public int getN() {
+        return points.size();
+    }
+
+    public double getRadius(Vector2D center) {
+        double r = 0;
+        for (Vector2D point : points) {
+            r += point.distance(center);
+        }
+        return r / points.size();
+    }
+
+    public MultivariateVectorFunction getModelFunction() {
+        return new MultivariateVectorFunction() {
+            public double[] value(double[] params) {
+                Vector2D center = new Vector2D(params[0], params[1]);
+                double radius = getRadius(center);
+                double[] residuals = new double[points.size()];
+                for (int i = 0; i < residuals.length; i++) {
+                    residuals[i] = points.get(i).distance(center) - radius;
+                }
+                
+                return residuals;
+            }
+        };
+    }
+
+    public MultivariateMatrixFunction getModelFunctionJacobian() {
+        return new MultivariateMatrixFunction() {
+            public double[][] value(double[] params) {
+                final int n = points.size();
+                final Vector2D center = new Vector2D(params[0], params[1]);
+
+                double dRdX = 0;
+                double dRdY = 0;
+                for (Vector2D pk : points) {
+                    double dk = pk.distance(center);
+                    dRdX += (center.getX() - pk.getX()) / dk;
+                    dRdY += (center.getY() - pk.getY()) / dk;
+                }
+                dRdX /= n;
+                dRdY /= n;
+
+                // Jacobian of the radius residuals.
+                double[][] jacobian = new double[n][2];
+                for (int i = 0; i < n; i++) {
+                    final Vector2D pi = points.get(i);
+                    final double di = pi.distance(center);
+                    jacobian[i][0] = (center.getX() - pi.getX()) / di - dRdX;
+                    jacobian[i][1] = (center.getY() - pi.getY()) / di - dRdY;
+                }
+
+                return jacobian;
+            }
+        };
+    }
+}

Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/CircleVectorial.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/fitting/leastsquares/CircleVectorial.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision