001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.math.optimization.general;
019    
020    import java.io.Serializable;
021    import java.util.Arrays;
022    
023    import junit.framework.Test;
024    import junit.framework.TestCase;
025    import junit.framework.TestSuite;
026    
027    import org.apache.commons.math.FunctionEvaluationException;
028    import org.apache.commons.math.analysis.DifferentiableMultivariateVectorialFunction;
029    import org.apache.commons.math.analysis.MultivariateMatrixFunction;
030    import org.apache.commons.math.optimization.OptimizationException;
031    import org.apache.commons.math.optimization.VectorialPointValuePair;
032    
033    /**
034     * <p>Some of the unit tests are re-implementations of the MINPACK <a
035     * href="http://www.netlib.org/minpack/ex/file17">file17</a> and <a
036     * href="http://www.netlib.org/minpack/ex/file22">file22</a> test files. 
037     * The redistribution policy for MINPACK is available <a
038     * href="http://www.netlib.org/minpack/disclaimer">here</a>, for
039     * convenience, it is reproduced below.</p>
040    
041     * <table border="0" width="80%" cellpadding="10" align="center" bgcolor="#E0E0E0">
042     * <tr><td>
043     *    Minpack Copyright Notice (1999) University of Chicago.
044     *    All rights reserved
045     * </td></tr>
046     * <tr><td>
047     * Redistribution and use in source and binary forms, with or without
048     * modification, are permitted provided that the following conditions
049     * are met:
050     * <ol>
051     *  <li>Redistributions of source code must retain the above copyright
052     *      notice, this list of conditions and the following disclaimer.</li>
053     * <li>Redistributions in binary form must reproduce the above
054     *     copyright notice, this list of conditions and the following
055     *     disclaimer in the documentation and/or other materials provided
056     *     with the distribution.</li>
057     * <li>The end-user documentation included with the redistribution, if any,
058     *     must include the following acknowledgment:
059     *     <code>This product includes software developed by the University of
060     *           Chicago, as Operator of Argonne National Laboratory.</code>
061     *     Alternately, this acknowledgment may appear in the software itself,
062     *     if and wherever such third-party acknowledgments normally appear.</li>
063     * <li><strong>WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS"
064     *     WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE
065     *     UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND
066     *     THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR
067     *     IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES
068     *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE
069     *     OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY
070     *     OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR
071     *     USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF
072     *     THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4)
073     *     DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION
074     *     UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL
075     *     BE CORRECTED.</strong></li>
076     * <li><strong>LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT
077     *     HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF
078     *     ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT,
079     *     INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF
080     *     ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF
081     *     PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER
082     *     SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT
083     *     (INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE,
084     *     EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE
085     *     POSSIBILITY OF SUCH LOSS OR DAMAGES.</strong></li>
086     * <ol></td></tr>
087     * </table>
088    
089     * @author Argonne National Laboratory. MINPACK project. March 1980 (original fortran minpack tests)
090     * @author Burton S. Garbow (original fortran minpack tests)
091     * @author Kenneth E. Hillstrom (original fortran minpack tests)
092     * @author Jorge J. More (original fortran minpack tests)
093     * @author Luc Maisonobe (non-minpack tests and minpack tests Java translation)
094     */
095    public class MinpackTest extends TestCase {
096    
097      public MinpackTest(String name) {
098        super(name);
099      }
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    }