Throw exception when bounds are passed to an algorithm that does not
support them.


git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1442377 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Gilles Sadowski 2013-02-04 21:31:42 +00:00
parent 8204809676
commit 90e428ddac
7 changed files with 66 additions and 2 deletions

View File

@ -72,6 +72,7 @@ public enum LocalizedFormats implements Localizable {
CLOSEST_ORTHOGONAL_MATRIX_HAS_NEGATIVE_DETERMINANT("the closest orthogonal matrix has a negative determinant {0}"),
COLUMN_INDEX_OUT_OF_RANGE("column index {0} out of allowed range [{1}, {2}]"),
COLUMN_INDEX("column index ({0})"), /* keep */
CONSTRAINT("constraint"), /* keep */
CONTINUED_FRACTION_INFINITY_DIVERGENCE("Continued fraction convergents diverged to +/- infinity for value {0}"),
CONTINUED_FRACTION_NAN_DIVERGENCE("Continued fraction diverged to NaN for value {0}"),
CONTRACTION_CRITERIA_SMALLER_THAN_EXPANSION_FACTOR("contraction criteria ({0}) smaller than the expansion factor ({1}). This would lead to a never ending loop of expansion and contraction as a newly expanded internal storage array would immediately satisfy the criteria for contraction."),

View File

@ -19,6 +19,7 @@ package org.apache.commons.math3.optim.nonlinear.vector.jacobian;
import org.apache.commons.math3.exception.ConvergenceException;
import org.apache.commons.math3.exception.NullArgumentException;
import org.apache.commons.math3.exception.MathInternalError;
import org.apache.commons.math3.exception.MathUnsupportedOperationException;
import org.apache.commons.math3.exception.util.LocalizedFormats;
import org.apache.commons.math3.linear.ArrayRealVector;
import org.apache.commons.math3.linear.BlockRealMatrix;
@ -32,6 +33,11 @@ import org.apache.commons.math3.optim.PointVectorValuePair;
/**
* Gauss-Newton least-squares solver.
* <br/>
* Constraints are not supported: the call to
* {@link #optimize(OptimizationData[]) optimize} will throw
* {@link MathUnsupportedOperationException} if bounds are passed to it.
*
* <p>
* This class solve a least-square problem by solving the normal equations
* of the linearized problem at each iteration. Either LU decomposition or
@ -72,6 +78,8 @@ public class GaussNewtonOptimizer extends AbstractLeastSquaresOptimizer {
/** {@inheritDoc} */
@Override
public PointVectorValuePair doOptimize() {
checkParameters();
final ConvergenceChecker<PointVectorValuePair> checker
= getConvergenceChecker();
@ -159,4 +167,15 @@ public class GaussNewtonOptimizer extends AbstractLeastSquaresOptimizer {
// Must never happen.
throw new MathInternalError();
}
/**
* @throws MathUnsupportedOperationException if bounds were passed to the
* {@link #optimize(OptimizationData[]) optimize} method.
*/
private void checkParameters() {
if (getLowerBound() != null ||
getUpperBound() != null) {
throw new MathUnsupportedOperationException(LocalizedFormats.CONSTRAINT);
}
}
}

View File

@ -18,6 +18,7 @@ package org.apache.commons.math3.optim.nonlinear.vector.jacobian;
import java.util.Arrays;
import org.apache.commons.math3.exception.ConvergenceException;
import org.apache.commons.math3.exception.MathUnsupportedOperationException;
import org.apache.commons.math3.exception.util.LocalizedFormats;
import org.apache.commons.math3.optim.PointVectorValuePair;
import org.apache.commons.math3.optim.ConvergenceChecker;
@ -27,7 +28,12 @@ import org.apache.commons.math3.util.FastMath;
/**
* This class solves a least-squares problem using the Levenberg-Marquardt algorithm.
* This class solves a least-squares problem using the Levenberg-Marquardt
* algorithm.
* <br/>
* Constraints are not supported: the call to
* {@link #optimize(OptimizationData[]) optimize} will throw
* {@link MathUnsupportedOperationException} if bounds are passed to it.
*
* <p>This implementation <em>should</em> work even for over-determined systems
* (i.e. systems having more point than equations). Over-determined systems
@ -276,6 +282,8 @@ public class LevenbergMarquardtOptimizer
/** {@inheritDoc} */
@Override
protected PointVectorValuePair doOptimize() {
checkParameters();
final int nR = getTarget().length; // Number of observed data.
final double[] currentPoint = getStartPoint();
final int nC = currentPoint.length; // Number of parameters.
@ -936,4 +944,15 @@ public class LevenbergMarquardtOptimizer
}
}
}
/**
* @throws MathUnsupportedOperationException if bounds were passed to the
* {@link #optimize(OptimizationData[]) optimize} method.
*/
private void checkParameters() {
if (getLowerBound() != null ||
getUpperBound() != null) {
throw new MathUnsupportedOperationException(LocalizedFormats.CONSTRAINT);
}
}
}

View File

@ -44,6 +44,7 @@ CLASS_DOESNT_IMPLEMENT_COMPARABLE = la classe ({0}) n''implante pas l''interface
CLOSEST_ORTHOGONAL_MATRIX_HAS_NEGATIVE_DETERMINANT = la matrice orthogonale la plus proche a un d\u00e9terminant n\u00e9gatif {0}
COLUMN_INDEX_OUT_OF_RANGE = l''index de colonne {0} est hors du domaine autoris\u00e9 [{1}, {2}]
COLUMN_INDEX = index de colonne ({0})
CONSTRAINT = contrainte
CONTINUED_FRACTION_INFINITY_DIVERGENCE = Divergence de fraction continue \u00e0 l''infini pour la valeur {0}
CONTINUED_FRACTION_NAN_DIVERGENCE = Divergence de fraction continue \u00e0 NaN pour la valeur {0}
CONTRACTION_CRITERIA_SMALLER_THAN_EXPANSION_FACTOR = crit\u00e8re de contraction ({0}) inf\u00e9rieur au facteur d''extension ({1}). Ceci induit une boucle infinie d''extensions/contractions car tout tableau de stockage fra\u00eechement \u00e9tendu respecte imm\u00e9diatement le crit\u00e8re de contraction.

View File

@ -30,7 +30,7 @@ public class LocalizedFormatsTest {
@Test
public void testMessageNumber() {
Assert.assertEquals(312, LocalizedFormats.values().length);
Assert.assertEquals(313, LocalizedFormats.values().length);
}
@Test

View File

@ -20,9 +20,11 @@ package org.apache.commons.math3.optim.nonlinear.vector.jacobian;
import java.io.IOException;
import org.apache.commons.math3.exception.ConvergenceException;
import org.apache.commons.math3.exception.TooManyEvaluationsException;
import org.apache.commons.math3.exception.MathUnsupportedOperationException;
import org.apache.commons.math3.optim.SimpleVectorValueChecker;
import org.apache.commons.math3.optim.InitialGuess;
import org.apache.commons.math3.optim.MaxEval;
import org.apache.commons.math3.optim.SimpleBounds;
import org.apache.commons.math3.optim.nonlinear.vector.Target;
import org.apache.commons.math3.optim.nonlinear.vector.Weight;
import org.apache.commons.math3.optim.nonlinear.vector.ModelFunction;
@ -99,6 +101,16 @@ public class GaussNewtonOptimizerTest
return new GaussNewtonOptimizer(new SimpleVectorValueChecker(1.0e-6, 1.0e-6));
}
@Test(expected=MathUnsupportedOperationException.class)
public void testConstraintsUnsupported() {
createOptimizer().optimize(new MaxEval(100),
new Target(new double[] { 2 }),
new Weight(new double[] { 1 }),
new InitialGuess(new double[] { 1, 2 }),
new SimpleBounds(new double[] { -10, 0 },
new double[] { 20, 30 }));
}
@Override
@Test(expected = ConvergenceException.class)
public void testMoreEstimatedParametersSimple() {

View File

@ -23,6 +23,7 @@ import java.util.List;
import org.apache.commons.math3.optim.PointVectorValuePair;
import org.apache.commons.math3.optim.InitialGuess;
import org.apache.commons.math3.optim.MaxEval;
import org.apache.commons.math3.optim.SimpleBounds;
import org.apache.commons.math3.optim.nonlinear.vector.Target;
import org.apache.commons.math3.optim.nonlinear.vector.Weight;
import org.apache.commons.math3.optim.nonlinear.vector.ModelFunction;
@ -32,6 +33,7 @@ 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.TooManyEvaluationsException;
import org.apache.commons.math3.exception.MathUnsupportedOperationException;
import org.apache.commons.math3.geometry.euclidean.twod.Vector2D;
import org.apache.commons.math3.linear.SingularMatrixException;
import org.apache.commons.math3.util.FastMath;
@ -109,6 +111,16 @@ public class LevenbergMarquardtOptimizerTest
return new LevenbergMarquardtOptimizer();
}
@Test(expected=MathUnsupportedOperationException.class)
public void testConstraintsUnsupported() {
createOptimizer().optimize(new MaxEval(100),
new Target(new double[] { 2 }),
new Weight(new double[] { 1 }),
new InitialGuess(new double[] { 1, 2 }),
new SimpleBounds(new double[] { -10, 0 },
new double[] { 20, 30 }));
}
@Override
@Test(expected=SingularMatrixException.class)
public void testNonInvertible() {