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