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