1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package org.apache.commons.math3.optim.nonlinear.vector.jacobian;
19 
20 import java.util.Arrays;
21 
22 import org.apache.commons.math3.exception.TooManyEvaluationsException;
23 import org.apache.commons.math3.analysis.MultivariateVectorFunction;
24 import org.apache.commons.math3.analysis.MultivariateMatrixFunction;
25 import org.apache.commons.math3.optim.PointVectorValuePair;
26 import org.apache.commons.math3.optim.InitialGuess;
27 import org.apache.commons.math3.optim.MaxEval;
28 import org.apache.commons.math3.optim.nonlinear.vector.Target;
29 import org.apache.commons.math3.optim.nonlinear.vector.Weight;
30 import org.apache.commons.math3.optim.nonlinear.vector.ModelFunction;
31 import org.apache.commons.math3.optim.nonlinear.vector.ModelFunctionJacobian;
32 import org.apache.commons.math3.util.FastMath;
33 import org.junit.Assert;
34 import org.junit.Test;
35 
36 /**
37  * <p>Some of the unit tests are re-implementations of the MINPACK <a
38  * href="http://www.netlib.org/minpack/ex/file17">file17</a> and <a
39  * href="http://www.netlib.org/minpack/ex/file22">file22</a> test files.
40  * The redistribution policy for MINPACK is available <a
41  * href="http://www.netlib.org/minpack/disclaimer">here</a>, for
42  * convenience, it is reproduced below.</p>
43 
44  * <table border="0" width="80%" cellpadding="10" align="center" bgcolor="#E0E0E0">
45  * <tr><td>
46  *    Minpack Copyright Notice (1999) University of Chicago.
47  *    All rights reserved
48  * </td></tr>
49  * <tr><td>
50  * Redistribution and use in source and binary forms, with or without
51  * modification, are permitted provided that the following conditions
52  * are met:
53  * <ol>
54  *  <li>Redistributions of source code must retain the above copyright
55  *      notice, this list of conditions and the following disclaimer.</li>
56  * <li>Redistributions in binary form must reproduce the above
57  *     copyright notice, this list of conditions and the following
58  *     disclaimer in the documentation and/or other materials provided
59  *     with the distribution.</li>
60  * <li>The end-user documentation included with the redistribution, if any,
61  *     must include the following acknowledgment:
62  *     <code>This product includes software developed by the University of
63  *           Chicago, as Operator of Argonne National Laboratory.</code>
64  *     Alternately, this acknowledgment may appear in the software itself,
65  *     if and wherever such third-party acknowledgments normally appear.</li>
66  * <li><strong>WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS"
67  *     WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE
68  *     UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND
69  *     THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR
70  *     IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES
71  *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE
72  *     OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY
73  *     OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR
74  *     USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF
75  *     THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4)
76  *     DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION
77  *     UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL
78  *     BE CORRECTED.</strong></li>
79  * <li><strong>LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT
80  *     HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF
81  *     ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT,
82  *     INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF
83  *     ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF
84  *     PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER
85  *     SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT
86  *     (INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE,
87  *     EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE
88  *     POSSIBILITY OF SUCH LOSS OR DAMAGES.</strong></li>
89  * <ol></td></tr>
90  * </table>
91 
92  * @author Argonne National Laboratory. MINPACK project. March 1980 (original fortran minpack tests)
93  * @author Burton S. Garbow (original fortran minpack tests)
94  * @author Kenneth E. Hillstrom (original fortran minpack tests)
95  * @author Jorge J. More (original fortran minpack tests)
96  * @author Luc Maisonobe (non-minpack tests and minpack tests Java translation)
97  */
98 @Deprecated
99 public class MinpackTest {
100 
101     @Test
testMinpackLinearFullRank()102     public void testMinpackLinearFullRank() {
103         minpackTest(new LinearFullRankFunction(10, 5, 1.0,
104                                                5.0, 2.23606797749979), false);
105         minpackTest(new LinearFullRankFunction(50, 5, 1.0,
106                                                8.06225774829855, 6.70820393249937), false);
107     }
108 
109     @Test
testMinpackLinearRank1()110     public void testMinpackLinearRank1() {
111         minpackTest(new LinearRank1Function(10, 5, 1.0,
112                                             291.521868819476, 1.4638501094228), false);
113         minpackTest(new LinearRank1Function(50, 5, 1.0,
114                                             3101.60039334535, 3.48263016573496), false);
115     }
116 
117     @Test
testMinpackLinearRank1ZeroColsAndRows()118     public void testMinpackLinearRank1ZeroColsAndRows() {
119         minpackTest(new LinearRank1ZeroColsAndRowsFunction(10, 5, 1.0), false);
120         minpackTest(new LinearRank1ZeroColsAndRowsFunction(50, 5, 1.0), false);
121     }
122 
123     @Test
testMinpackRosenbrok()124     public void testMinpackRosenbrok() {
125         minpackTest(new RosenbrockFunction(new double[] { -1.2, 1.0 },
126                                            FastMath.sqrt(24.2)), false);
127         minpackTest(new RosenbrockFunction(new double[] { -12.0, 10.0 },
128                                            FastMath.sqrt(1795769.0)), false);
129         minpackTest(new RosenbrockFunction(new double[] { -120.0, 100.0 },
130                                            11.0 * FastMath.sqrt(169000121.0)), false);
131     }
132 
133     @Test
testMinpackHelicalValley()134     public void testMinpackHelicalValley() {
135         minpackTest(new HelicalValleyFunction(new double[] { -1.0, 0.0, 0.0 },
136                                               50.0), false);
137         minpackTest(new HelicalValleyFunction(new double[] { -10.0, 0.0, 0.0 },
138                                               102.95630140987), false);
139         minpackTest(new HelicalValleyFunction(new double[] { -100.0, 0.0, 0.0},
140                                               991.261822123701), false);
141     }
142 
143     @Test
testMinpackPowellSingular()144     public void testMinpackPowellSingular() {
145         minpackTest(new PowellSingularFunction(new double[] { 3.0, -1.0, 0.0, 1.0 },
146                                                14.6628782986152), false);
147         minpackTest(new PowellSingularFunction(new double[] { 30.0, -10.0, 0.0, 10.0 },
148                                                1270.9838708654), false);
149         minpackTest(new PowellSingularFunction(new double[] { 300.0, -100.0, 0.0, 100.0 },
150                                                126887.903284750), false);
151     }
152 
153     @Test
testMinpackFreudensteinRoth()154     public void testMinpackFreudensteinRoth() {
155         minpackTest(new FreudensteinRothFunction(new double[] { 0.5, -2.0 },
156                                                  20.0124960961895, 6.99887517584575,
157                                                  new double[] {
158                                                      11.4124844654993,
159                                                      -0.896827913731509
160                                                  }), false);
161         minpackTest(new FreudensteinRothFunction(new double[] { 5.0, -20.0 },
162                                                  12432.833948863, 6.9988751744895,
163                                                  new double[] {
164                                                      11.41300466147456,
165                                                      -0.896796038685959
166                                                  }), false);
167         minpackTest(new FreudensteinRothFunction(new double[] { 50.0, -200.0 },
168                                                  11426454.595762, 6.99887517242903,
169                                                  new double[] {
170                                                      11.412781785788564,
171                                                      -0.8968051074920405
172                                                  }), false);
173     }
174 
175     @Test
testMinpackBard()176     public void testMinpackBard() {
177         minpackTest(new BardFunction(1.0, 6.45613629515967, 0.0906359603390466,
178                                      new double[] {
179                                          0.0824105765758334,
180                                          1.1330366534715,
181                                          2.34369463894115
182                                      }), false);
183         minpackTest(new BardFunction(10.0, 36.1418531596785, 4.17476870138539,
184                                      new double[] {
185                                          0.840666673818329,
186                                          -158848033.259565,
187                                          -164378671.653535
188                                      }), false);
189         minpackTest(new BardFunction(100.0, 384.114678637399, 4.17476870135969,
190                                      new double[] {
191                                          0.840666673867645,
192                                          -158946167.205518,
193                                          -164464906.857771
194                                      }), false);
195     }
196 
197     @Test
testMinpackKowalikOsborne()198     public void testMinpackKowalikOsborne() {
199         minpackTest(new KowalikOsborneFunction(new double[] { 0.25, 0.39, 0.415, 0.39 },
200                                                0.0728915102882945,
201                                                0.017535837721129,
202                                                new double[] {
203                                                    0.192807810476249,
204                                                    0.191262653354071,
205                                                    0.123052801046931,
206                                                    0.136053221150517
207                                                }), false);
208         minpackTest(new KowalikOsborneFunction(new double[] { 2.5, 3.9, 4.15, 3.9 },
209                                                2.97937007555202,
210                                                0.032052192917937,
211                                                new double[] {
212                                                    728675.473768287,
213                                                    -14.0758803129393,
214                                                    -32977797.7841797,
215                                                    -20571594.1977912
216                                                }), false);
217         minpackTest(new KowalikOsborneFunction(new double[] { 25.0, 39.0, 41.5, 39.0 },
218                                                29.9590617016037,
219                                                0.0175364017658228,
220                                                new double[] {
221                                                    0.192948328597594,
222                                                    0.188053165007911,
223                                                    0.122430604321144,
224                                                    0.134575665392506
225                                                }), false);
226     }
227 
228     @Test
testMinpackMeyer()229     public void testMinpackMeyer() {
230         minpackTest(new MeyerFunction(new double[] { 0.02, 4000.0, 250.0 },
231                                       41153.4665543031, 9.37794514651874,
232                                       new double[] {
233                                           0.00560963647102661,
234                                           6181.34634628659,
235                                           345.223634624144
236                                       }), false);
237         minpackTest(new MeyerFunction(new double[] { 0.2, 40000.0, 2500.0 },
238                                       4168216.89130846, 792.917871779501,
239                                       new double[] {
240                                           1.42367074157994e-11,
241                                           33695.7133432541,
242                                           901.268527953801
243                                       }), true);
244     }
245 
246     @Test
testMinpackWatson()247     public void testMinpackWatson() {
248         minpackTest(new WatsonFunction(6, 0.0,
249                                        5.47722557505166, 0.0478295939097601,
250                                        new double[] {
251                                            -0.0157249615083782, 1.01243488232965,
252                                            -0.232991722387673,  1.26043101102818,
253                                            -1.51373031394421,   0.99299727291842
254                                        }), false);
255         minpackTest(new WatsonFunction(6, 10.0,
256                                        6433.12578950026, 0.0478295939096951,
257                                        new double[] {
258                                            -0.0157251901386677, 1.01243485860105,
259                                            -0.232991545843829,  1.26042932089163,
260                                            -1.51372776706575,   0.99299573426328
261                                        }), false);
262         minpackTest(new WatsonFunction(6, 100.0,
263                                        674256.040605213, 0.047829593911544,
264                                        new double[] {
265                                            -0.0157247019712586, 1.01243490925658,
266                                            -0.232991922761641,  1.26043292929555,
267                                            -1.51373320452707,   0.99299901922322
268                                        }), false);
269         minpackTest(new WatsonFunction(9, 0.0,
270                                        5.47722557505166, 0.00118311459212420,
271                                        new double[] {
272                                            -0.153070644166722e-4, 0.999789703934597,
273                                            0.0147639634910978,   0.146342330145992,
274                                            1.00082109454817,    -2.61773112070507,
275                                            4.10440313943354,    -3.14361226236241,
276                                            1.05262640378759
277                                        }), false);
278         minpackTest(new WatsonFunction(9, 10.0,
279                                        12088.127069307, 0.00118311459212513,
280                                        new double[] {
281                                            -0.153071334849279e-4, 0.999789703941234,
282                                            0.0147639629786217,   0.146342334818836,
283                                            1.00082107321386,    -2.61773107084722,
284                                            4.10440307655564,    -3.14361222178686,
285                                            1.05262639322589
286                                        }), false);
287         minpackTest(new WatsonFunction(9, 100.0,
288                                        1269109.29043834, 0.00118311459212384,
289                                        new double[] {
290                                            -0.153069523352176e-4, 0.999789703958371,
291                                            0.0147639625185392,   0.146342341096326,
292                                            1.00082104729164,    -2.61773101573645,
293                                            4.10440301427286,    -3.14361218602503,
294                                            1.05262638516774
295                                        }), false);
296         minpackTest(new WatsonFunction(12, 0.0,
297                                        5.47722557505166, 0.217310402535861e-4,
298                                        new double[] {
299                                            -0.660266001396382e-8, 1.00000164411833,
300                                            -0.000563932146980154, 0.347820540050756,
301                                            -0.156731500244233,    1.05281515825593,
302                                            -3.24727109519451,     7.2884347837505,
303                                            -10.271848098614,       9.07411353715783,
304                                            -4.54137541918194,     1.01201187975044
305                                        }), false);
306         minpackTest(new WatsonFunction(12, 10.0,
307                                        19220.7589790951, 0.217310402518509e-4,
308                                        new double[] {
309                                            -0.663710223017410e-8, 1.00000164411787,
310                                            -0.000563932208347327, 0.347820540486998,
311                                            -0.156731503955652,    1.05281517654573,
312                                            -3.2472711515214,      7.28843489430665,
313                                            -10.2718482369638,      9.07411364383733,
314                                            -4.54137546533666,     1.01201188830857
315                                        }), false);
316         minpackTest(new WatsonFunction(12, 100.0,
317                                        2018918.04462367, 0.217310402539845e-4,
318                                        new double[] {
319                                            -0.663806046485249e-8, 1.00000164411786,
320                                            -0.000563932210324959, 0.347820540503588,
321                                            -0.156731504091375,    1.05281517718031,
322                                            -3.24727115337025,     7.28843489775302,
323                                            -10.2718482410813,      9.07411364688464,
324                                            -4.54137546660822,     1.0120118885369
325                                        }), false);
326     }
327 
328     @Test
testMinpackBox3Dimensional()329     public void testMinpackBox3Dimensional() {
330         minpackTest(new Box3DimensionalFunction(10, new double[] { 0.0, 10.0, 20.0 },
331                                                 32.1115837449572), false);
332     }
333 
334     @Test
testMinpackJennrichSampson()335     public void testMinpackJennrichSampson() {
336         minpackTest(new JennrichSampsonFunction(10, new double[] { 0.3, 0.4 },
337                                                 64.5856498144943, 11.1517793413499,
338                                                 new double[] {
339 //                                                     0.2578330049, 0.257829976764542
340                                                     0.2578199266368004, 0.25782997676455244
341                                                 }), false);
342     }
343 
344     @Test
testMinpackBrownDennis()345     public void testMinpackBrownDennis() {
346         minpackTest(new BrownDennisFunction(20,
347                                             new double[] { 25.0, 5.0, -5.0, -1.0 },
348                                             2815.43839161816, 292.954288244866,
349                                             new double[] {
350                                                 -11.59125141003, 13.2024883984741,
351                                                 -0.403574643314272, 0.236736269844604
352                                             }), false);
353         minpackTest(new BrownDennisFunction(20,
354                                             new double[] { 250.0, 50.0, -50.0, -10.0 },
355                                             555073.354173069, 292.954270581415,
356                                             new double[] {
357                                                 -11.5959274272203, 13.2041866926242,
358                                                 -0.403417362841545, 0.236771143410386
359                                             }), false);
360         minpackTest(new BrownDennisFunction(20,
361                                             new double[] { 2500.0, 500.0, -500.0, -100.0 },
362                                             61211252.2338581, 292.954306151134,
363                                             new double[] {
364                                                 -11.5902596937374, 13.2020628854665,
365                                                 -0.403688070279258, 0.236665033746463
366                                             }), false);
367     }
368 
369     @Test
testMinpackChebyquad()370     public void testMinpackChebyquad() {
371         minpackTest(new ChebyquadFunction(1, 8, 1.0,
372                                           1.88623796907732, 1.88623796907732,
373                                           new double[] { 0.5 }), false);
374         minpackTest(new ChebyquadFunction(1, 8, 10.0,
375                                           5383344372.34005, 1.88424820499951,
376                                           new double[] { 0.9817314924684 }), false);
377         minpackTest(new ChebyquadFunction(1, 8, 100.0,
378                                           0.118088726698392e19, 1.88424820499347,
379                                           new double[] { 0.9817314852934 }), false);
380         minpackTest(new ChebyquadFunction(8, 8, 1.0,
381                                           0.196513862833975, 0.0593032355046727,
382                                           new double[] {
383                                               0.0431536648587336, 0.193091637843267,
384                                               0.266328593812698,  0.499999334628884,
385                                               0.500000665371116,  0.733671406187302,
386                                               0.806908362156733,  0.956846335141266
387                                           }), false);
388         minpackTest(new ChebyquadFunction(9, 9, 1.0,
389                                           0.16994993465202, 0.0,
390                                           new double[] {
391                                               0.0442053461357828, 0.199490672309881,
392                                               0.23561910847106,   0.416046907892598,
393                                               0.5,                0.583953092107402,
394                                               0.764380891528940,  0.800509327690119,
395                                               0.955794653864217
396                                           }), false);
397         minpackTest(new ChebyquadFunction(10, 10, 1.0,
398                                           0.183747831178711, 0.0806471004038253,
399                                           new double[] {
400                                               0.0596202671753563, 0.166708783805937,
401                                               0.239171018813509,  0.398885290346268,
402                                               0.398883667870681,  0.601116332129320,
403                                               0.60111470965373,   0.760828981186491,
404                                               0.833291216194063,  0.940379732824644
405                                           }), false);
406     }
407 
408     @Test
testMinpackBrownAlmostLinear()409     public void testMinpackBrownAlmostLinear() {
410         minpackTest(new BrownAlmostLinearFunction(10, 0.5,
411                                                   16.5302162063499, 0.0,
412                                                   new double[] {
413                                                       0.979430303349862, 0.979430303349862,
414                                                       0.979430303349862, 0.979430303349862,
415                                                       0.979430303349862, 0.979430303349862,
416                                                       0.979430303349862, 0.979430303349862,
417                                                       0.979430303349862, 1.20569696650138
418                                                   }), false);
419         minpackTest(new BrownAlmostLinearFunction(10, 5.0,
420                                                   9765624.00089211, 0.0,
421                                                   new double[] {
422                                                       0.979430303349865, 0.979430303349865,
423                                                       0.979430303349865, 0.979430303349865,
424                                                       0.979430303349865, 0.979430303349865,
425                                                       0.979430303349865, 0.979430303349865,
426                                                       0.979430303349865, 1.20569696650135
427                                                   }), false);
428         minpackTest(new BrownAlmostLinearFunction(10, 50.0,
429                                                   0.9765625e17, 0.0,
430                                                   new double[] {
431                                                       1.0, 1.0, 1.0, 1.0, 1.0,
432                                                       1.0, 1.0, 1.0, 1.0, 1.0
433                                                   }), false);
434         minpackTest(new BrownAlmostLinearFunction(30, 0.5,
435                                                   83.476044467848, 0.0,
436                                                   new double[] {
437                                                       0.997754216442807, 0.997754216442807,
438                                                       0.997754216442807, 0.997754216442807,
439                                                       0.997754216442807, 0.997754216442807,
440                                                       0.997754216442807, 0.997754216442807,
441                                                       0.997754216442807, 0.997754216442807,
442                                                       0.997754216442807, 0.997754216442807,
443                                                       0.997754216442807, 0.997754216442807,
444                                                       0.997754216442807, 0.997754216442807,
445                                                       0.997754216442807, 0.997754216442807,
446                                                       0.997754216442807, 0.997754216442807,
447                                                       0.997754216442807, 0.997754216442807,
448                                                       0.997754216442807, 0.997754216442807,
449                                                       0.997754216442807, 0.997754216442807,
450                                                       0.997754216442807, 0.997754216442807,
451                                                       0.997754216442807, 1.06737350671578
452                                                   }), false);
453         minpackTest(new BrownAlmostLinearFunction(40, 0.5,
454                                                   128.026364472323, 0.0,
455                                                   new double[] {
456                                                       1.00000000000002, 1.00000000000002,
457                                                       1.00000000000002, 1.00000000000002,
458                                                       1.00000000000002, 1.00000000000002,
459                                                       1.00000000000002, 1.00000000000002,
460                                                       1.00000000000002, 1.00000000000002,
461                                                       1.00000000000002, 1.00000000000002,
462                                                       1.00000000000002, 1.00000000000002,
463                                                       1.00000000000002, 1.00000000000002,
464                                                       1.00000000000002, 1.00000000000002,
465                                                       1.00000000000002, 1.00000000000002,
466                                                       1.00000000000002, 1.00000000000002,
467                                                       1.00000000000002, 1.00000000000002,
468                                                       1.00000000000002, 1.00000000000002,
469                                                       1.00000000000002, 1.00000000000002,
470                                                       1.00000000000002, 1.00000000000002,
471                                                       1.00000000000002, 1.00000000000002,
472                                                       1.00000000000002, 1.00000000000002,
473                                                       0.999999999999121
474                                                   }), false);
475     }
476 
477     @Test
testMinpackOsborne1()478     public void testMinpackOsborne1() {
479         minpackTest(new Osborne1Function(new double[] { 0.5, 1.5, -1.0, 0.01, 0.02, },
480                                          0.937564021037838, 0.00739249260904843,
481                                          new double[] {
482                                              0.375410049244025, 1.93584654543108,
483                                              -1.46468676748716, 0.0128675339110439,
484                                              0.0221227011813076
485                                          }), false);
486     }
487 
488     @Test
testMinpackOsborne2()489     public void testMinpackOsborne2() {
490         minpackTest(new Osborne2Function(new double[] {
491                     1.3, 0.65, 0.65, 0.7, 0.6,
492                     3.0, 5.0, 7.0, 2.0, 4.5, 5.5
493                 },
494                 1.44686540984712, 0.20034404483314,
495                 new double[] {
496                     1.30997663810096,  0.43155248076,
497                     0.633661261602859, 0.599428560991695,
498                     0.754179768272449, 0.904300082378518,
499                     1.36579949521007, 4.82373199748107,
500                     2.39868475104871, 4.56887554791452,
501                     5.67534206273052
502                 }), false);
503     }
504 
minpackTest(MinpackFunction function, boolean exceptionExpected)505     private void minpackTest(MinpackFunction function, boolean exceptionExpected) {
506         LevenbergMarquardtOptimizer optimizer
507             = new LevenbergMarquardtOptimizer(FastMath.sqrt(2.22044604926e-16),
508                                               FastMath.sqrt(2.22044604926e-16),
509                                               2.22044604926e-16);
510         try {
511             PointVectorValuePair optimum
512                 = optimizer.optimize(new MaxEval(400 * (function.getN() + 1)),
513                                      function.getModelFunction(),
514                                      function.getModelFunctionJacobian(),
515                                      new Target(function.getTarget()),
516                                      new Weight(function.getWeight()),
517                                      new InitialGuess(function.getStartPoint()));
518             Assert.assertFalse(exceptionExpected);
519             function.checkTheoreticalMinCost(optimizer.getRMS());
520             function.checkTheoreticalMinParams(optimum);
521         } catch (TooManyEvaluationsException e) {
522             Assert.assertTrue(exceptionExpected);
523         }
524     }
525 
526     private static abstract class MinpackFunction {
527         protected int      n;
528         protected int      m;
529         protected double[] startParams;
530         protected double   theoreticalMinCost;
531         protected double[] theoreticalMinParams;
532         protected double   costAccuracy;
533         protected double   paramsAccuracy;
534 
MinpackFunction(int m, double[] startParams, double theoreticalMinCost, double[] theoreticalMinParams)535         protected MinpackFunction(int m, double[] startParams,
536                                   double theoreticalMinCost,
537                                   double[] theoreticalMinParams) {
538             this.m = m;
539             this.n = startParams.length;
540             this.startParams          = startParams.clone();
541             this.theoreticalMinCost   = theoreticalMinCost;
542             this.theoreticalMinParams = theoreticalMinParams;
543             this.costAccuracy         = 1.0e-8;
544             this.paramsAccuracy       = 1.0e-5;
545         }
546 
buildArray(int n, double x)547         protected static double[] buildArray(int n, double x) {
548             double[] array = new double[n];
549             Arrays.fill(array, x);
550             return array;
551         }
552 
getTarget()553         public double[] getTarget() {
554             return buildArray(m, 0.0);
555         }
556 
getWeight()557         public double[] getWeight() {
558             return buildArray(m, 1.0);
559         }
560 
getStartPoint()561         public double[] getStartPoint() {
562             return startParams.clone();
563         }
564 
setCostAccuracy(double costAccuracy)565         protected void setCostAccuracy(double costAccuracy) {
566             this.costAccuracy = costAccuracy;
567         }
568 
setParamsAccuracy(double paramsAccuracy)569         protected void setParamsAccuracy(double paramsAccuracy) {
570             this.paramsAccuracy = paramsAccuracy;
571         }
572 
getN()573         public int getN() {
574             return startParams.length;
575         }
576 
checkTheoreticalMinCost(double rms)577         public void checkTheoreticalMinCost(double rms) {
578             double threshold = costAccuracy * (1.0 + theoreticalMinCost);
579             Assert.assertEquals(theoreticalMinCost, FastMath.sqrt(m) * rms, threshold);
580         }
581 
checkTheoreticalMinParams(PointVectorValuePair optimum)582         public void checkTheoreticalMinParams(PointVectorValuePair optimum) {
583             double[] params = optimum.getPointRef();
584             if (theoreticalMinParams != null) {
585                 for (int i = 0; i < theoreticalMinParams.length; ++i) {
586                     double mi = theoreticalMinParams[i];
587                     double vi = params[i];
588                     Assert.assertEquals(mi, vi, paramsAccuracy * (1.0 + FastMath.abs(mi)));
589                 }
590             }
591         }
592 
getModelFunction()593         public ModelFunction getModelFunction() {
594             return new ModelFunction(new MultivariateVectorFunction() {
595                     public double[] value(double[] point) {
596                         return computeValue(point);
597                     }
598                 });
599         }
600 
getModelFunctionJacobian()601         public ModelFunctionJacobian getModelFunctionJacobian() {
602             return new ModelFunctionJacobian(new MultivariateMatrixFunction() {
603                     public double[][] value(double[] point) {
604                         return computeJacobian(point);
605                     }
606                 });
607         }
608 
609         public abstract double[][] computeJacobian(double[] variables);
610         public abstract double[] computeValue(double[] variables);
611     }
612 
613     private static class LinearFullRankFunction extends MinpackFunction {
614         public LinearFullRankFunction(int m, int n, double x0,
615                                       double theoreticalStartCost,
616                                       double theoreticalMinCost) {
617             super(m, buildArray(n, x0), theoreticalMinCost,
618                   buildArray(n, -1.0));
619         }
620 
621         @Override
622         public double[][] computeJacobian(double[] variables) {
623             double t = 2.0 / m;
624             double[][] jacobian = new double[m][];
625             for (int i = 0; i < m; ++i) {
626                 jacobian[i] = new double[n];
627                 for (int j = 0; j < n; ++j) {
628                     jacobian[i][j] = (i == j) ? (1 - t) : -t;
629                 }
630             }
631             return jacobian;
632         }
633 
634         @Override
635         public double[] computeValue(double[] variables) {
636             double sum = 0;
637             for (int i = 0; i < n; ++i) {
638                 sum += variables[i];
639             }
640             double t  = 1 + 2 * sum / m;
641             double[] f = new double[m];
642             for (int i = 0; i < n; ++i) {
643                 f[i] = variables[i] - t;
644             }
645             Arrays.fill(f, n, m, -t);
646             return f;
647         }
648     }
649 
650     private static class LinearRank1Function extends MinpackFunction {
651         public LinearRank1Function(int m, int n, double x0,
652                                    double theoreticalStartCost,
653                                    double theoreticalMinCost) {
654             super(m, buildArray(n, x0), theoreticalMinCost, null);
655         }
656 
657         @Override
658         public double[][] computeJacobian(double[] variables) {
659             double[][] jacobian = new double[m][];
660             for (int i = 0; i < m; ++i) {
661                 jacobian[i] = new double[n];
662                 for (int j = 0; j < n; ++j) {
663                     jacobian[i][j] = (i + 1) * (j + 1);
664                 }
665             }
666             return jacobian;
667         }
668 
669         @Override
670         public double[] computeValue(double[] variables) {
671             double[] f = new double[m];
672             double sum = 0;
673             for (int i = 0; i < n; ++i) {
674                 sum += (i + 1) * variables[i];
675             }
676             for (int i = 0; i < m; ++i) {
677                 f[i] = (i + 1) * sum - 1;
678             }
679             return f;
680         }
681     }
682 
683     private static class LinearRank1ZeroColsAndRowsFunction extends MinpackFunction {
684         public LinearRank1ZeroColsAndRowsFunction(int m, int n, double x0) {
685             super(m, buildArray(n, x0),
686                   FastMath.sqrt((m * (m + 3) - 6) / (2.0 * (2 * m - 3))),
687                   null);
688         }
689 
690         @Override
691         public double[][] computeJacobian(double[] variables) {
692             double[][] jacobian = new double[m][];
693             for (int i = 0; i < m; ++i) {
694                 jacobian[i] = new double[n];
695                 jacobian[i][0] = 0;
696                 for (int j = 1; j < (n - 1); ++j) {
697                     if (i == 0) {
698                         jacobian[i][j] = 0;
699                     } else if (i != (m - 1)) {
700                         jacobian[i][j] = i * (j + 1);
701                     } else {
702                         jacobian[i][j] = 0;
703                     }
704                 }
705                 jacobian[i][n - 1] = 0;
706             }
707             return jacobian;
708         }
709 
710         @Override
711         public double[] computeValue(double[] variables) {
712             double[] f = new double[m];
713             double sum = 0;
714             for (int i = 1; i < (n - 1); ++i) {
715                 sum += (i + 1) * variables[i];
716             }
717             for (int i = 0; i < (m - 1); ++i) {
718                 f[i] = i * sum - 1;
719             }
720             f[m - 1] = -1;
721             return f;
722         }
723     }
724 
725     private static class RosenbrockFunction extends MinpackFunction {
726         public RosenbrockFunction(double[] startParams, double theoreticalStartCost) {
727             super(2, startParams, 0.0, buildArray(2, 1.0));
728         }
729 
730         @Override
731         public double[][] computeJacobian(double[] variables) {
732             double x1 = variables[0];
733             return new double[][] { { -20 * x1, 10 }, { -1, 0 } };
734         }
735 
736         @Override
737         public double[] computeValue(double[] variables) {
738             double x1 = variables[0];
739             double x2 = variables[1];
740             return new double[] { 10 * (x2 - x1 * x1), 1 - x1 };
741         }
742     }
743 
744     private static class HelicalValleyFunction extends MinpackFunction {
745         public HelicalValleyFunction(double[] startParams,
746                                      double theoreticalStartCost) {
747             super(3, startParams, 0.0, new double[] { 1.0, 0.0, 0.0 });
748         }
749 
750         @Override
751         public double[][] computeJacobian(double[] variables) {
752             double x1 = variables[0];
753             double x2 = variables[1];
754             double tmpSquare = x1 * x1 + x2 * x2;
755             double tmp1 = twoPi * tmpSquare;
756             double tmp2 = FastMath.sqrt(tmpSquare);
757             return new double[][] {
758                 {  100 * x2 / tmp1, -100 * x1 / tmp1, 10 },
759                 { 10 * x1 / tmp2, 10 * x2 / tmp2, 0 },
760                 { 0, 0, 1 }
761             };
762         }
763 
764         @Override
765         public double[] computeValue(double[] variables) {
766             double x1 = variables[0];
767             double x2 = variables[1];
768             double x3 = variables[2];
769             double tmp1;
770             if (x1 == 0) {
771                 tmp1 = (x2 >= 0) ? 0.25 : -0.25;
772             } else {
773                 tmp1 = FastMath.atan(x2 / x1) / twoPi;
774                 if (x1 < 0) {
775                     tmp1 += 0.5;
776                 }
777             }
778             double tmp2 = FastMath.sqrt(x1 * x1 + x2 * x2);
779             return new double[] {
780                 10.0 * (x3 - 10 * tmp1),
781                 10.0 * (tmp2 - 1),
782                 x3
783             };
784         }
785 
786         private static final double twoPi = 2.0 * FastMath.PI;
787     }
788 
789     private static class PowellSingularFunction extends MinpackFunction {
790         public PowellSingularFunction(double[] startParams,
791                                       double theoreticalStartCost) {
792             super(4, startParams, 0.0, buildArray(4, 0.0));
793         }
794 
795         @Override
796         public double[][] computeJacobian(double[] variables) {
797             double x1 = variables[0];
798             double x2 = variables[1];
799             double x3 = variables[2];
800             double x4 = variables[3];
801             return new double[][] {
802                 { 1, 10, 0, 0 },
803                 { 0, 0, sqrt5, -sqrt5 },
804                 { 0, 2 * (x2 - 2 * x3), -4 * (x2 - 2 * x3), 0 },
805                 { 2 * sqrt10 * (x1 - x4), 0, 0, -2 * sqrt10 * (x1 - x4) }
806             };
807         }
808 
809         @Override
810         public double[] computeValue(double[] variables) {
811             double x1 = variables[0];
812             double x2 = variables[1];
813             double x3 = variables[2];
814             double x4 = variables[3];
815             return new double[] {
816                 x1 + 10 * x2,
817                 sqrt5 * (x3 - x4),
818                 (x2 - 2 * x3) * (x2 - 2 * x3),
819                 sqrt10 * (x1 - x4) * (x1 - x4)
820             };
821         }
822 
823         private static final double sqrt5  = FastMath.sqrt( 5.0);
824         private static final double sqrt10 = FastMath.sqrt(10.0);
825   }
826 
827     private static class FreudensteinRothFunction extends MinpackFunction {
828         public FreudensteinRothFunction(double[] startParams,
829                                         double theoreticalStartCost,
830                                         double theoreticalMinCost,
831                                         double[] theoreticalMinParams) {
832             super(2, startParams, theoreticalMinCost,
833                   theoreticalMinParams);
834         }
835 
836         @Override
837         public double[][] computeJacobian(double[] variables) {
838             double x2 = variables[1];
839             return new double[][] {
840                 { 1, x2 * (10 - 3 * x2) -  2 },
841                 { 1, x2 * ( 2 + 3 * x2) - 14, }
842             };
843         }
844 
845         @Override
846         public double[] computeValue(double[] variables) {
847             double x1 = variables[0];
848             double x2 = variables[1];
849             return new double[] {
850                 -13.0 + x1 + ((5.0 - x2) * x2 -  2.0) * x2,
851                 -29.0 + x1 + ((1.0 + x2) * x2 - 14.0) * x2
852             };
853         }
854     }
855 
856     private static class BardFunction extends MinpackFunction {
857         public BardFunction(double x0,
858                             double theoreticalStartCost,
859                             double theoreticalMinCost,
860                             double[] theoreticalMinParams) {
861             super(15, buildArray(3, x0), theoreticalMinCost,
862                   theoreticalMinParams);
863         }
864 
865         @Override
866         public double[][] computeJacobian(double[] variables) {
867             double   x2 = variables[1];
868             double   x3 = variables[2];
869             double[][] jacobian = new double[m][];
870             for (int i = 0; i < m; ++i) {
871                 double tmp1 = i  + 1;
872                 double tmp2 = 15 - i;
873                 double tmp3 = (i <= 7) ? tmp1 : tmp2;
874                 double tmp4 = x2 * tmp2 + x3 * tmp3;
875                 tmp4 *= tmp4;
876                 jacobian[i] = new double[] { -1, tmp1 * tmp2 / tmp4, tmp1 * tmp3 / tmp4 };
877             }
878             return jacobian;
879         }
880 
881         @Override
882         public double[] computeValue(double[] variables) {
883             double   x1 = variables[0];
884             double   x2 = variables[1];
885             double   x3 = variables[2];
886             double[] f = new double[m];
887             for (int i = 0; i < m; ++i) {
888                 double tmp1 = i + 1;
889                 double tmp2 = 15 - i;
890                 double tmp3 = (i <= 7) ? tmp1 : tmp2;
891                 f[i] = y[i] - (x1 + tmp1 / (x2 * tmp2 + x3 * tmp3));
892             }
893             return f;
894         }
895 
896         private static final double[] y = {
897             0.14, 0.18, 0.22, 0.25, 0.29,
898             0.32, 0.35, 0.39, 0.37, 0.58,
899             0.73, 0.96, 1.34, 2.10, 4.39
900         };
901     }
902 
903     private static class KowalikOsborneFunction extends MinpackFunction {
904         public KowalikOsborneFunction(double[] startParams,
905                                       double theoreticalStartCost,
906                                       double theoreticalMinCost,
907                                       double[] theoreticalMinParams) {
908             super(11, startParams, theoreticalMinCost,
909                   theoreticalMinParams);
910             if (theoreticalStartCost > 20.0) {
911                 setCostAccuracy(2.0e-4);
912                 setParamsAccuracy(5.0e-3);
913             }
914         }
915 
916         @Override
917         public double[][] computeJacobian(double[] variables) {
918             double   x1 = variables[0];
919             double   x2 = variables[1];
920             double   x3 = variables[2];
921             double   x4 = variables[3];
922             double[][] jacobian = new double[m][];
923             for (int i = 0; i < m; ++i) {
924                 double tmp = v[i] * (v[i] + x3) + x4;
925                 double j1  = -v[i] * (v[i] + x2) / tmp;
926                 double j2  = -v[i] * x1 / tmp;
927                 double j3  = j1 * j2;
928                 double j4  = j3 / v[i];
929                 jacobian[i] = new double[] { j1, j2, j3, j4 };
930             }
931             return jacobian;
932         }
933 
934         @Override
935         public double[] computeValue(double[] variables) {
936             double x1 = variables[0];
937             double x2 = variables[1];
938             double x3 = variables[2];
939             double x4 = variables[3];
940             double[] f = new double[m];
941             for (int i = 0; i < m; ++i) {
942                 f[i] = y[i] - x1 * (v[i] * (v[i] + x2)) / (v[i] * (v[i] + x3) + x4);
943             }
944             return f;
945         }
946 
947         private static final double[] v = {
948             4.0, 2.0, 1.0, 0.5, 0.25, 0.167, 0.125, 0.1, 0.0833, 0.0714, 0.0625
949         };
950 
951         private static final double[] y = {
952             0.1957, 0.1947, 0.1735, 0.1600, 0.0844, 0.0627,
953             0.0456, 0.0342, 0.0323, 0.0235, 0.0246
954         };
955     }
956 
957     private static class MeyerFunction extends MinpackFunction {
958         public MeyerFunction(double[] startParams,
959                              double theoreticalStartCost,
960                              double theoreticalMinCost,
961                              double[] theoreticalMinParams) {
962             super(16, startParams, theoreticalMinCost,
963                   theoreticalMinParams);
964             if (theoreticalStartCost > 1.0e6) {
965                 setCostAccuracy(7.0e-3);
966                 setParamsAccuracy(2.0e-2);
967             }
968         }
969 
970         @Override
971         public double[][] computeJacobian(double[] variables) {
972             double   x1 = variables[0];
973             double   x2 = variables[1];
974             double   x3 = variables[2];
975             double[][] jacobian = new double[m][];
976             for (int i = 0; i < m; ++i) {
977                 double temp = 5.0 * (i + 1) + 45.0 + x3;
978                 double tmp1 = x2 / temp;
979                 double tmp2 = FastMath.exp(tmp1);
980                 double tmp3 = x1 * tmp2 / temp;
981                 jacobian[i] = new double[] { tmp2, tmp3, -tmp1 * tmp3 };
982             }
983             return jacobian;
984         }
985 
986         @Override
987         public double[] computeValue(double[] variables) {
988             double x1 = variables[0];
989             double x2 = variables[1];
990             double x3 = variables[2];
991             double[] f = new double[m];
992             for (int i = 0; i < m; ++i) {
993                 f[i] = x1 * FastMath.exp(x2 / (5.0 * (i + 1) + 45.0 + x3)) - y[i];
994             }
995             return f;
996         }
997 
998         private static final double[] y = {
999             34780.0, 28610.0, 23650.0, 19630.0,
1000             16370.0, 13720.0, 11540.0,  9744.0,
1001             8261.0,  7030.0,  6005.0,  5147.0,
1002             4427.0,  3820.0,  3307.0,  2872.0
1003         };
1004     }
1005 
1006     private static class WatsonFunction extends MinpackFunction {
1007         public WatsonFunction(int n, double x0,
1008                               double theoreticalStartCost,
1009                               double theoreticalMinCost,
1010                               double[] theoreticalMinParams) {
1011             super(31, buildArray(n, x0), theoreticalMinCost,
1012                   theoreticalMinParams);
1013         }
1014 
1015         @Override
1016         public double[][] computeJacobian(double[] variables) {
1017             double[][] jacobian = new double[m][];
1018 
1019             for (int i = 0; i < (m - 2); ++i) {
1020                 double div = (i + 1) / 29.0;
1021                 double s2  = 0.0;
1022                 double dx  = 1.0;
1023                 for (int j = 0; j < n; ++j) {
1024                     s2 += dx * variables[j];
1025                     dx *= div;
1026                 }
1027                 double temp= 2 * div * s2;
1028                 dx = 1.0 / div;
1029                 jacobian[i] = new double[n];
1030                 for (int j = 0; j < n; ++j) {
1031                     jacobian[i][j] = dx * (j - temp);
1032                     dx *= div;
1033                 }
1034             }
1035 
1036             jacobian[m - 2]    = new double[n];
1037             jacobian[m - 2][0] = 1;
1038 
1039             jacobian[m - 1]   = new double[n];
1040             jacobian[m - 1][0]= -2 * variables[0];
1041             jacobian[m - 1][1]= 1;
1042 
1043             return jacobian;
1044         }
1045 
1046         @Override
1047         public double[] computeValue(double[] variables) {
1048             double[] f = new double[m];
1049             for (int i = 0; i < (m - 2); ++i) {
1050                 double div = (i + 1) / 29.0;
1051                 double s1 = 0;
1052                 double dx = 1;
1053                 for (int j = 1; j < n; ++j) {
1054                     s1 += j * dx * variables[j];
1055                     dx *= div;
1056                 }
1057                 double s2 = 0;
1058                 dx = 1;
1059                 for (int j = 0; j < n; ++j) {
1060                     s2 += dx * variables[j];
1061                     dx *= div;
1062                 }
1063                 f[i] = s1 - s2 * s2 - 1;
1064             }
1065 
1066             double x1 = variables[0];
1067             double x2 = variables[1];
1068             f[m - 2] = x1;
1069             f[m - 1] = x2 - x1 * x1 - 1;
1070 
1071             return f;
1072         }
1073     }
1074 
1075     private static class Box3DimensionalFunction extends MinpackFunction {
1076         public Box3DimensionalFunction(int m, double[] startParams,
1077                                        double theoreticalStartCost) {
1078             super(m, startParams, 0.0,
1079                   new double[] { 1.0, 10.0, 1.0 });
1080         }
1081 
1082         @Override
1083         public double[][] computeJacobian(double[] variables) {
1084             double   x1 = variables[0];
1085             double   x2 = variables[1];
1086             double[][] jacobian = new double[m][];
1087             for (int i = 0; i < m; ++i) {
1088                 double tmp = (i + 1) / 10.0;
1089                 jacobian[i] = new double[] {
1090                     -tmp * FastMath.exp(-tmp * x1),
1091                     tmp * FastMath.exp(-tmp * x2),
1092                     FastMath.exp(-i - 1) - FastMath.exp(-tmp)
1093                 };
1094             }
1095             return jacobian;
1096         }
1097 
1098         @Override
1099         public double[] computeValue(double[] variables) {
1100             double x1 = variables[0];
1101             double x2 = variables[1];
1102             double x3 = variables[2];
1103             double[] f = new double[m];
1104             for (int i = 0; i < m; ++i) {
1105                 double tmp = (i + 1) / 10.0;
1106                 f[i] = FastMath.exp(-tmp * x1) - FastMath.exp(-tmp * x2)
1107                     + (FastMath.exp(-i - 1) - FastMath.exp(-tmp)) * x3;
1108             }
1109             return f;
1110         }
1111     }
1112 
1113     private static class JennrichSampsonFunction extends MinpackFunction {
1114         public JennrichSampsonFunction(int m, double[] startParams,
1115                                        double theoreticalStartCost,
1116                                        double theoreticalMinCost,
1117                                        double[] theoreticalMinParams) {
1118             super(m, startParams, theoreticalMinCost,
1119                   theoreticalMinParams);
1120         }
1121 
1122         @Override
1123         public double[][] computeJacobian(double[] variables) {
1124             double   x1 = variables[0];
1125             double   x2 = variables[1];
1126             double[][] jacobian = new double[m][];
1127             for (int i = 0; i < m; ++i) {
1128                 double t = i + 1;
1129                 jacobian[i] = new double[] { -t * FastMath.exp(t * x1), -t * FastMath.exp(t * x2) };
1130             }
1131             return jacobian;
1132         }
1133 
1134         @Override
1135         public double[] computeValue(double[] variables) {
1136             double x1 = variables[0];
1137             double x2 = variables[1];
1138             double[] f = new double[m];
1139             for (int i = 0; i < m; ++i) {
1140                 double temp = i + 1;
1141                 f[i] = 2 + 2 * temp - FastMath.exp(temp * x1) - FastMath.exp(temp * x2);
1142             }
1143             return f;
1144         }
1145     }
1146 
1147     private static class BrownDennisFunction extends MinpackFunction {
1148         public BrownDennisFunction(int m, double[] startParams,
1149                                    double theoreticalStartCost,
1150                                    double theoreticalMinCost,
1151                                    double[] theoreticalMinParams) {
1152             super(m, startParams, theoreticalMinCost,
1153                 theoreticalMinParams);
1154             setCostAccuracy(2.5e-8);
1155         }
1156 
1157         @Override
1158         public double[][] computeJacobian(double[] variables) {
1159             double   x1 = variables[0];
1160             double   x2 = variables[1];
1161             double   x3 = variables[2];
1162             double   x4 = variables[3];
1163             double[][] jacobian = new double[m][];
1164             for (int i = 0; i < m; ++i) {
1165                 double temp = (i + 1) / 5.0;
1166                 double ti   = FastMath.sin(temp);
1167                 double tmp1 = x1 + temp * x2 - FastMath.exp(temp);
1168                 double tmp2 = x3 + ti   * x4 - FastMath.cos(temp);
1169                 jacobian[i] = new double[] {
1170                     2 * tmp1, 2 * temp * tmp1, 2 * tmp2, 2 * ti * tmp2
1171                 };
1172             }
1173             return jacobian;
1174         }
1175 
1176         @Override
1177         public double[] computeValue(double[] variables) {
1178             double x1 = variables[0];
1179             double x2 = variables[1];
1180             double x3 = variables[2];
1181             double x4 = variables[3];
1182             double[] f = new double[m];
1183             for (int i = 0; i < m; ++i) {
1184                 double temp = (i + 1) / 5.0;
1185                 double tmp1 = x1 + temp * x2 - FastMath.exp(temp);
1186                 double tmp2 = x3 + FastMath.sin(temp) * x4 - FastMath.cos(temp);
1187                 f[i] = tmp1 * tmp1 + tmp2 * tmp2;
1188             }
1189             return f;
1190         }
1191     }
1192 
1193     private static class ChebyquadFunction extends MinpackFunction {
1194         private static double[] buildChebyquadArray(int n, double factor) {
1195             double[] array = new double[n];
1196             double inv = factor / (n + 1);
1197             for (int i = 0; i < n; ++i) {
1198                 array[i] = (i + 1) * inv;
1199             }
1200             return array;
1201         }
1202 
1203         public ChebyquadFunction(int n, int m, double factor,
1204                                  double theoreticalStartCost,
1205                                  double theoreticalMinCost,
1206                                  double[] theoreticalMinParams) {
1207             super(m, buildChebyquadArray(n, factor), theoreticalMinCost,
1208                   theoreticalMinParams);
1209         }
1210 
1211         @Override
1212         public double[][] computeJacobian(double[] variables) {
1213             double[][] jacobian = new double[m][];
1214             for (int i = 0; i < m; ++i) {
1215                 jacobian[i] = new double[n];
1216             }
1217 
1218             double dx = 1.0 / n;
1219             for (int j = 0; j < n; ++j) {
1220                 double tmp1 = 1;
1221                 double tmp2 = 2 * variables[j] - 1;
1222                 double temp = 2 * tmp2;
1223                 double tmp3 = 0;
1224                 double tmp4 = 2;
1225                 for (int i = 0; i < m; ++i) {
1226                     jacobian[i][j] = dx * tmp4;
1227                     double ti = 4 * tmp2 + temp * tmp4 - tmp3;
1228                     tmp3 = tmp4;
1229                     tmp4 = ti;
1230                     ti   = temp * tmp2 - tmp1;
1231                     tmp1 = tmp2;
1232                     tmp2 = ti;
1233                 }
1234             }
1235 
1236             return jacobian;
1237         }
1238 
1239         @Override
1240         public double[] computeValue(double[] variables) {
1241             double[] f = new double[m];
1242 
1243             for (int j = 0; j < n; ++j) {
1244                 double tmp1 = 1;
1245                 double tmp2 = 2 * variables[j] - 1;
1246                 double temp = 2 * tmp2;
1247                 for (int i = 0; i < m; ++i) {
1248                     f[i] += tmp2;
1249                     double ti = temp * tmp2 - tmp1;
1250                     tmp1 = tmp2;
1251                     tmp2 = ti;
1252                 }
1253             }
1254 
1255             double dx = 1.0 / n;
1256             boolean iev = false;
1257             for (int i = 0; i < m; ++i) {
1258                 f[i] *= dx;
1259                 if (iev) {
1260                     f[i] += 1.0 / (i * (i + 2));
1261                 }
1262                 iev = ! iev;
1263             }
1264 
1265             return f;
1266         }
1267     }
1268 
1269     private static class BrownAlmostLinearFunction extends MinpackFunction {
1270         public BrownAlmostLinearFunction(int m, double factor,
1271                                          double theoreticalStartCost,
1272                                          double theoreticalMinCost,
1273                                          double[] theoreticalMinParams) {
1274             super(m, buildArray(m, factor), theoreticalMinCost,
1275                   theoreticalMinParams);
1276         }
1277 
1278         @Override
1279         public double[][] computeJacobian(double[] variables) {
1280             double[][] jacobian = new double[m][];
1281             for (int i = 0; i < m; ++i) {
1282                 jacobian[i] = new double[n];
1283             }
1284 
1285             double prod = 1;
1286             for (int j = 0; j < n; ++j) {
1287                 prod *= variables[j];
1288                 for (int i = 0; i < n; ++i) {
1289                     jacobian[i][j] = 1;
1290                 }
1291                 jacobian[j][j] = 2;
1292             }
1293 
1294             for (int j = 0; j < n; ++j) {
1295                 double temp = variables[j];
1296                 if (temp == 0) {
1297                     temp = 1;
1298                     prod = 1;
1299                     for (int k = 0; k < n; ++k) {
1300                         if (k != j) {
1301                             prod *= variables[k];
1302                         }
1303                     }
1304                 }
1305                 jacobian[n - 1][j] = prod / temp;
1306             }
1307 
1308             return jacobian;
1309         }
1310 
1311         @Override
1312         public double[] computeValue(double[] variables) {
1313             double[] f = new double[m];
1314             double sum  = -(n + 1);
1315             double prod = 1;
1316             for (int j = 0; j < n; ++j) {
1317                 sum  += variables[j];
1318                 prod *= variables[j];
1319             }
1320             for (int i = 0; i < n; ++i) {
1321                 f[i] = variables[i] + sum;
1322             }
1323             f[n - 1] = prod - 1;
1324             return f;
1325         }
1326     }
1327 
1328     private static class Osborne1Function extends MinpackFunction {
1329         public Osborne1Function(double[] startParams,
1330                                 double theoreticalStartCost,
1331                                 double theoreticalMinCost,
1332                                 double[] theoreticalMinParams) {
1333             super(33, startParams, theoreticalMinCost,
1334                   theoreticalMinParams);
1335         }
1336 
1337         @Override
1338         public double[][] computeJacobian(double[] variables) {
1339             double   x2 = variables[1];
1340             double   x3 = variables[2];
1341             double   x4 = variables[3];
1342             double   x5 = variables[4];
1343             double[][] jacobian = new double[m][];
1344             for (int i = 0; i < m; ++i) {
1345                 double temp = 10.0 * i;
1346                 double tmp1 = FastMath.exp(-temp * x4);
1347                 double tmp2 = FastMath.exp(-temp * x5);
1348                 jacobian[i] = new double[] {
1349                     -1, -tmp1, -tmp2, temp * x2 * tmp1, temp * x3 * tmp2
1350                 };
1351             }
1352             return jacobian;
1353         }
1354 
1355         @Override
1356         public double[] computeValue(double[] variables) {
1357             double x1 = variables[0];
1358             double x2 = variables[1];
1359             double x3 = variables[2];
1360             double x4 = variables[3];
1361             double x5 = variables[4];
1362             double[] f = new double[m];
1363             for (int i = 0; i < m; ++i) {
1364                 double temp = 10.0 * i;
1365                 double tmp1 = FastMath.exp(-temp * x4);
1366                 double tmp2 = FastMath.exp(-temp * x5);
1367                 f[i] = y[i] - (x1 + x2 * tmp1 + x3 * tmp2);
1368             }
1369             return f;
1370         }
1371 
1372         private static final double[] y = {
1373             0.844, 0.908, 0.932, 0.936, 0.925, 0.908, 0.881, 0.850, 0.818, 0.784, 0.751,
1374             0.718, 0.685, 0.658, 0.628, 0.603, 0.580, 0.558, 0.538, 0.522, 0.506, 0.490,
1375             0.478, 0.467, 0.457, 0.448, 0.438, 0.431, 0.424, 0.420, 0.414, 0.411, 0.406
1376         };
1377     }
1378 
1379     private static class Osborne2Function extends MinpackFunction {
1380         public Osborne2Function(double[] startParams,
1381                                 double theoreticalStartCost,
1382                                 double theoreticalMinCost,
1383                                 double[] theoreticalMinParams) {
1384             super(65, startParams, theoreticalMinCost,
1385                   theoreticalMinParams);
1386         }
1387 
1388         @Override
1389         public double[][] computeJacobian(double[] variables) {
1390             double   x01 = variables[0];
1391             double   x02 = variables[1];
1392             double   x03 = variables[2];
1393             double   x04 = variables[3];
1394             double   x05 = variables[4];
1395             double   x06 = variables[5];
1396             double   x07 = variables[6];
1397             double   x08 = variables[7];
1398             double   x09 = variables[8];
1399             double   x10 = variables[9];
1400             double   x11 = variables[10];
1401             double[][] jacobian = new double[m][];
1402             for (int i = 0; i < m; ++i) {
1403                 double temp = i / 10.0;
1404                 double tmp1 = FastMath.exp(-x05 * temp);
1405                 double tmp2 = FastMath.exp(-x06 * (temp - x09) * (temp - x09));
1406                 double tmp3 = FastMath.exp(-x07 * (temp - x10) * (temp - x10));
1407                 double tmp4 = FastMath.exp(-x08 * (temp - x11) * (temp - x11));
1408                 jacobian[i] = new double[] {
1409                     -tmp1,
1410                     -tmp2,
1411                     -tmp3,
1412                     -tmp4,
1413                     temp * x01 * tmp1,
1414                     x02 * (temp - x09) * (temp - x09) * tmp2,
1415                     x03 * (temp - x10) * (temp - x10) * tmp3,
1416                     x04 * (temp - x11) * (temp - x11) * tmp4,
1417                     -2 * x02 * x06 * (temp - x09) * tmp2,
1418                     -2 * x03 * x07 * (temp - x10) * tmp3,
1419                     -2 * x04 * x08 * (temp - x11) * tmp4
1420                 };
1421             }
1422             return jacobian;
1423         }
1424 
1425         @Override
1426         public double[] computeValue(double[] variables) {
1427             double x01 = variables[0];
1428             double x02 = variables[1];
1429             double x03 = variables[2];
1430             double x04 = variables[3];
1431             double x05 = variables[4];
1432             double x06 = variables[5];
1433             double x07 = variables[6];
1434             double x08 = variables[7];
1435             double x09 = variables[8];
1436             double x10 = variables[9];
1437             double x11 = variables[10];
1438             double[] f = new double[m];
1439             for (int i = 0; i < m; ++i) {
1440                 double temp = i / 10.0;
1441                 double tmp1 = FastMath.exp(-x05 * temp);
1442                 double tmp2 = FastMath.exp(-x06 * (temp - x09) * (temp - x09));
1443                 double tmp3 = FastMath.exp(-x07 * (temp - x10) * (temp - x10));
1444                 double tmp4 = FastMath.exp(-x08 * (temp - x11) * (temp - x11));
1445                 f[i] = y[i] - (x01 * tmp1 + x02 * tmp2 + x03 * tmp3 + x04 * tmp4);
1446             }
1447             return f;
1448         }
1449 
1450         private static final double[] y = {
1451             1.366, 1.191, 1.112, 1.013, 0.991,
1452             0.885, 0.831, 0.847, 0.786, 0.725,
1453             0.746, 0.679, 0.608, 0.655, 0.616,
1454             0.606, 0.602, 0.626, 0.651, 0.724,
1455             0.649, 0.649, 0.694, 0.644, 0.624,
1456             0.661, 0.612, 0.558, 0.533, 0.495,
1457             0.500, 0.423, 0.395, 0.375, 0.372,
1458             0.391, 0.396, 0.405, 0.428, 0.429,
1459             0.523, 0.562, 0.607, 0.653, 0.672,
1460             0.708, 0.633, 0.668, 0.645, 0.632,
1461             0.591, 0.559, 0.597, 0.625, 0.739,
1462             0.710, 0.729, 0.720, 0.636, 0.581,
1463             0.428, 0.292, 0.162, 0.098, 0.054
1464         };
1465     }
1466 }
1467