001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.math.optimization;
019    
020    import static org.junit.Assert.assertEquals;
021    import static org.junit.Assert.assertTrue;
022    import static org.junit.Assert.fail;
023    
024    import java.io.Serializable;
025    
026    import org.apache.commons.math.FunctionEvaluationException;
027    import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
028    import org.apache.commons.math.analysis.MultivariateMatrixFunction;
029    import org.apache.commons.math.linear.BlockRealMatrix;
030    import org.apache.commons.math.linear.RealMatrix;
031    import org.apache.commons.math.optimization.general.GaussNewtonOptimizer;
032    import org.apache.commons.math.random.GaussianRandomGenerator;
033    import org.apache.commons.math.random.JDKRandomGenerator;
034    import org.apache.commons.math.random.RandomVectorGenerator;
035    import org.apache.commons.math.random.UncorrelatedRandomVectorGenerator;
036    import org.junit.Test;
037    
038    /**
039     * <p>Some of the unit tests are re-implementations of the MINPACK <a
040     * href="http://www.netlib.org/minpack/ex/file17">file17</a> and <a
041     * href="http://www.netlib.org/minpack/ex/file22">file22</a> test files. 
042     * The redistribution policy for MINPACK is available <a
043     * href="http://www.netlib.org/minpack/disclaimer">here</a>, for
044     * convenience, it is reproduced below.</p>
045    
046     * <table border="0" width="80%" cellpadding="10" align="center" bgcolor="#E0E0E0">
047     * <tr><td>
048     *    Minpack Copyright Notice (1999) University of Chicago.
049     *    All rights reserved
050     * </td></tr>
051     * <tr><td>
052     * Redistribution and use in source and binary forms, with or without
053     * modification, are permitted provided that the following conditions
054     * are met:
055     * <ol>
056     *  <li>Redistributions of source code must retain the above copyright
057     *      notice, this list of conditions and the following disclaimer.</li>
058     * <li>Redistributions in binary form must reproduce the above
059     *     copyright notice, this list of conditions and the following
060     *     disclaimer in the documentation and/or other materials provided
061     *     with the distribution.</li>
062     * <li>The end-user documentation included with the redistribution, if any,
063     *     must include the following acknowledgment:
064     *     <code>This product includes software developed by the University of
065     *           Chicago, as Operator of Argonne National Laboratory.</code>
066     *     Alternately, this acknowledgment may appear in the software itself,
067     *     if and wherever such third-party acknowledgments normally appear.</li>
068     * <li><strong>WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS"
069     *     WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE
070     *     UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND
071     *     THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR
072     *     IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES
073     *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE
074     *     OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY
075     *     OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR
076     *     USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF
077     *     THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4)
078     *     DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION
079     *     UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL
080     *     BE CORRECTED.</strong></li>
081     * <li><strong>LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT
082     *     HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF
083     *     ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT,
084     *     INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF
085     *     ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF
086     *     PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER
087     *     SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT
088     *     (INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE,
089     *     EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE
090     *     POSSIBILITY OF SUCH LOSS OR DAMAGES.</strong></li>
091     * <ol></td></tr>
092     * </table>
093    
094     * @author Argonne National Laboratory. MINPACK project. March 1980 (original fortran minpack tests)
095     * @author Burton S. Garbow (original fortran minpack tests)
096     * @author Kenneth E. Hillstrom (original fortran minpack tests)
097     * @author Jorge J. More (original fortran minpack tests)
098     * @author Luc Maisonobe (non-minpack tests and minpack tests Java translation)
099     */
100    public class MultiStartDifferentiableMultivariateVectorialOptimizerTest {
101    
102        @Test
103        public void testTrivial() throws FunctionEvaluationException, OptimizationException {
104            LinearProblem problem =
105                new LinearProblem(new double[][] { { 2 } }, new double[] { 3 });
106            DifferentiableMultivariateVectorialOptimizer underlyingOptimizer =
107                new GaussNewtonOptimizer(true);
108            JDKRandomGenerator g = new JDKRandomGenerator();
109            g.setSeed(16069223052l);
110            RandomVectorGenerator generator =
111                new UncorrelatedRandomVectorGenerator(1, new GaussianRandomGenerator(g));
112            MultiStartDifferentiableMultivariateVectorialOptimizer optimizer =
113                new MultiStartDifferentiableMultivariateVectorialOptimizer(underlyingOptimizer,
114                                                                           10, generator);
115            optimizer.setMaxIterations(100);
116            optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
117    
118            // no optima before first optimization attempt
119            try {
120                optimizer.getOptima();
121                fail("an exception should have been thrown");
122            } catch (IllegalStateException ise) {
123                // expected
124            }
125            VectorialPointValuePair optimum =
126                optimizer.optimize(problem, problem.target, new double[] { 1 }, new double[] { 0 });
127            assertEquals(1.5, optimum.getPoint()[0], 1.0e-10);
128            assertEquals(3.0, optimum.getValue()[0], 1.0e-10);
129            VectorialPointValuePair[] optima = optimizer.getOptima();
130            assertEquals(10, optima.length);
131            for (int i = 0; i < optima.length; ++i) {
132                assertEquals(1.5, optima[i].getPoint()[0], 1.0e-10);
133                assertEquals(3.0, optima[i].getValue()[0], 1.0e-10);
134            }
135            assertTrue(optimizer.getEvaluations() > 20);
136            assertTrue(optimizer.getEvaluations() < 50);
137            assertTrue(optimizer.getIterations() > 20);
138            assertTrue(optimizer.getIterations() < 50);
139            assertTrue(optimizer.getJacobianEvaluations() > 20);
140            assertTrue(optimizer.getJacobianEvaluations() < 50);
141            assertEquals(100, optimizer.getMaxIterations());
142        }
143    
144        @Test(expected = OptimizationException.class)
145        public void testNoOptimum() throws FunctionEvaluationException, OptimizationException {
146            DifferentiableMultivariateVectorialOptimizer underlyingOptimizer =
147                new GaussNewtonOptimizer(true);
148            JDKRandomGenerator g = new JDKRandomGenerator();
149            g.setSeed(12373523445l);
150            RandomVectorGenerator generator =
151                new UncorrelatedRandomVectorGenerator(1, new GaussianRandomGenerator(g));
152            MultiStartDifferentiableMultivariateVectorialOptimizer optimizer =
153                new MultiStartDifferentiableMultivariateVectorialOptimizer(underlyingOptimizer,
154                                                                           10, generator);
155            optimizer.setMaxIterations(100);
156            optimizer.setConvergenceChecker(new SimpleVectorialValueChecker(1.0e-6, 1.0e-6));
157            optimizer.optimize(new DifferentiableMultivariateVectorialFunction() {
158                    public MultivariateMatrixFunction jacobian() {
159                        return null;
160                    }
161                    public double[] value(double[] point) throws FunctionEvaluationException {
162                        throw new FunctionEvaluationException(point[0]);
163                    }
164                }, new double[] { 2 }, new double[] { 1 }, new double[] { 0 });
165        }
166    
167        private static class LinearProblem implements DifferentiableMultivariateVectorialFunction, Serializable {
168    
169            private static final long serialVersionUID = -8804268799379350190L;
170            final RealMatrix factors;
171            final double[] target;
172            public LinearProblem(double[][] factors, double[] target) {
173                this.factors = new BlockRealMatrix(factors);
174                this.target  = target;
175            }
176    
177            public double[] value(double[] variables) {
178                return factors.operate(variables);
179            }
180    
181            public MultivariateMatrixFunction jacobian() {
182                return new MultivariateMatrixFunction() {
183                    private static final long serialVersionUID = -8387467946663627585L;
184                    public double[][] value(double[] point) {
185                        return factors.getData();
186                    }
187                };
188            }
189    
190        }
191    
192    }