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