1 // Copyright (C) 2008  Davis E. King (davis@dlib.net)
2 // License: Boost Software License   See LICENSE.txt for the full license.
3 
4 
5 #include "optimization_test_functions.h"
6 #include <dlib/optimization.h>
7 #include <dlib/statistics.h>
8 #include <sstream>
9 #include <string>
10 #include <cstdlib>
11 #include <ctime>
12 #include <vector>
13 #include "../stl_checked.h"
14 #include "../array.h"
15 #include "../rand.h"
16 
17 #include "tester.h"
18 
19 
20 namespace
21 {
22 
23     using namespace test;
24     using namespace dlib;
25     using namespace std;
26 
27     logger dlog("test.optimization");
28 
29 // ----------------------------------------------------------------------------------------
30 
approx_equal(double a,double b)31     bool approx_equal (
32         double a,
33         double b
34     )
35     {
36         return std::abs(a - b) < 100*std::numeric_limits<double>::epsilon();
37     }
38 
39 // ----------------------------------------------------------------------------------------
40 
41     long total_count = 0;
42 
43 
44     template <typename T>
apq(const T & x)45     double apq ( const T& x)
46     {
47         DLIB_ASSERT(x.nr() > 1 && x.nc() == 1,"");
48         COMPILE_TIME_ASSERT(is_matrix<T>::value);
49         double temp = 0;
50         for (long r = 0; r < x.nr(); ++r)
51         {
52             temp += (r+1)*x(r)*x(r);
53         }
54 
55         ++total_count;
56 
57         return temp + 1/100.0*(x(0) + x(x.nr()-1))*(x(0) + x(x.nr()-1));
58     }
59 
60     template <typename T>
der_apq(const T & x)61     T der_apq ( const T& x)
62     {
63         DLIB_ASSERT(x.nr() > 1 && x.nc() == 1,"");
64         COMPILE_TIME_ASSERT(is_matrix<T>::value);
65         T temp(x.nr());
66         for (long r = 0; r < x.nr(); ++r)
67         {
68             temp(r) = 2*(r+1)*x(r) ;
69         }
70 
71         temp(0) += 1/50.0*(x(0) + x(x.nr()-1));
72         temp(x.nr()-1) += 1/50.0*(x(0) + x(x.nr()-1));
73 
74         ++total_count;
75 
76         return temp;
77     }
78 
79 // ----------------------------------------------------------------------------------------
80 
81     // Rosenbrock's function.  minimum at (1,1)
rosen(const matrix<double,2,1> & x)82     double rosen ( const matrix<double,2,1>& x)
83     {
84         ++total_count;
85         return 100*pow(x(1) - x(0)*x(0),2) + pow(1 - x(0),2);
86     }
87 
der_rosen(const matrix<double,2,1> & x)88     matrix<double,2,1> der_rosen ( const matrix<double,2,1>& x)
89     {
90         ++total_count;
91         matrix<double,2,1> res;
92         res(0) = -400*x(0)*(x(1)-x(0)*x(0)) - 2*(1-x(0));
93         res(1) = 200*(x(1)-x(0)*x(0));
94         return res;
95     }
96 
97 // ----------------------------------------------------------------------------------------
98 
99     // negative of Rosenbrock's function.  minimum at (1,1)
neg_rosen(const matrix<double,2,1> & x)100     double neg_rosen ( const matrix<double,2,1>& x)
101     {
102         ++total_count;
103         return -(100*pow(x(1) - x(0)*x(0),2) + pow(1 - x(0),2));
104     }
105 
der_neg_rosen(const matrix<double,2,1> & x)106     matrix<double,2,1> der_neg_rosen ( const matrix<double,2,1>& x)
107     {
108         ++total_count;
109         matrix<double,2,1> res;
110         res(0) = -400*x(0)*(x(1)-x(0)*x(0)) - 2*(1-x(0));
111         res(1) = 200*(x(1)-x(0)*x(0));
112         return -res;
113     }
114 
115 // ----------------------------------------------------------------------------------------
116 
simple(const matrix<double,2,1> & x)117     double simple ( const matrix<double,2,1>& x)
118     {
119         ++total_count;
120         return 10*x(0)*x(0) + x(1)*x(1);
121     }
122 
der_simple(const matrix<double,2,1> & x)123     matrix<double,2,1> der_simple ( const matrix<double,2,1>& x)
124     {
125         ++total_count;
126         matrix<double,2,1> res;
127         res(0) = 20*x(0);
128         res(1) = 2*x(1);
129         return res;
130     }
131 
132 // ----------------------------------------------------------------------------------------
133 
powell(const matrix<double,4,1> & x)134     double powell ( const matrix<double,4,1>& x)
135     {
136         ++total_count;
137         return pow(x(0) + 10*x(1),2) +
138             pow(std::sqrt(5.0)*(x(2) - x(3)),2) +
139             pow((x(1) - 2*x(2))*(x(1) - 2*x(2)),2) +
140             pow(std::sqrt(10.0)*(x(0) - x(3))*(x(0) - x(3)),2);
141     }
142 
143 // ----------------------------------------------------------------------------------------
144 
145 // a simple function with a minimum at zero
single_variable_function(double x)146     double single_variable_function ( double x)
147     {
148         ++total_count;
149         return 3*x*x + 5;
150     }
151 
152 // ----------------------------------------------------------------------------------------
153 // ----------------------------------------------------------------------------------------
154 // ----------------------------------------------------------------------------------------
155 
test_apq(const matrix<double,0,1> p)156     void test_apq (
157         const matrix<double,0,1> p
158     )
159     {
160         typedef matrix<double,0,1> T;
161         const double eps = 1e-12;
162         const double minf = -10;
163         matrix<double,0,1> x(p.nr()), opt(p.nr());
164         set_all_elements(opt, 0);
165         double val = 0;
166 
167         if (p.size() < 20)
168             dlog << LINFO << "testing with apq and the start point: " << trans(p);
169         else
170             dlog << LINFO << "testing with apq and a big vector with " << p.size() << " components.";
171 
172         // don't use bfgs on really large vectors
173         if (p.size() < 20)
174         {
175             total_count = 0;
176             x = p;
177             val = find_min(bfgs_search_strategy(),
178                      objective_delta_stop_strategy(eps),
179                      wrap_function(apq<T>), wrap_function(der_apq<T>), x, minf);
180             DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
181             DLIB_TEST(approx_equal(val , apq(x)));
182             dlog << LINFO << "find_min() bgfs: got apq in " << total_count;
183 
184             total_count = 0;
185             x = p;
186             find_min(bfgs_search_strategy(),
187                      gradient_norm_stop_strategy(),
188                      wrap_function(apq<T>), wrap_function(der_apq<T>), x, minf);
189             DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
190             dlog << LINFO << "find_min() bgfs(gn): got apq in " << total_count;
191         }
192 
193 
194         if (p.size() < 100)
195         {
196             total_count = 0;
197             x = p;
198             val=find_min_bobyqa(wrap_function(apq<T>), x, 2*x.size()+1,
199                             uniform_matrix<double>(x.size(),1,-1e100),
200                             uniform_matrix<double>(x.size(),1,1e100),
201                             (max(abs(x))+1)/10,
202                             1e-6,
203                             10000);
204             DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
205             DLIB_TEST(approx_equal(val , apq(x)));
206             dlog << LINFO << "find_min_bobyqa(): got apq in " << total_count;
207         }
208 
209         total_count = 0;
210         x = p;
211         val=find_min(lbfgs_search_strategy(10),
212                  objective_delta_stop_strategy(eps),
213                  wrap_function(apq<T>), wrap_function(der_apq<T>), x, minf);
214         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
215         DLIB_TEST(approx_equal(val , apq(x)));
216         dlog << LINFO << "find_min() lbgfs-10: got apq in " << total_count;
217 
218 
219         total_count = 0;
220         x = p;
221         val=find_min(lbfgs_search_strategy(1),
222                  objective_delta_stop_strategy(eps),
223                  wrap_function(apq<T>), wrap_function(der_apq<T>), x, minf);
224         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
225         DLIB_TEST(approx_equal(val , apq(x)));
226         dlog << LINFO << "find_min() lbgfs-1: got apq in " << total_count;
227 
228 
229         total_count = 0;
230         x = p;
231         val=find_min(cg_search_strategy(),
232                  objective_delta_stop_strategy(eps),
233                  wrap_function(apq<T>), wrap_function(der_apq<T>), x, minf);
234         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
235         DLIB_TEST(approx_equal(val , apq(x)));
236         dlog << LINFO << "find_min() cg: got apq in " << total_count;
237 
238 
239         // don't do approximate derivative tests if the input point is really long
240         if (p.size() < 20)
241         {
242             total_count = 0;
243             x = p;
244             val=find_min(bfgs_search_strategy(),
245                      objective_delta_stop_strategy(eps),
246                      wrap_function(apq<T>), derivative(wrap_function(apq<T>)), x, minf);
247             DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
248             DLIB_TEST(approx_equal(val , apq(x)));
249             dlog << LINFO << "find_min() bfgs: got apq/noder in " << total_count;
250 
251 
252             total_count = 0;
253             x = p;
254             val=find_min(cg_search_strategy(),
255                      objective_delta_stop_strategy(eps),
256                      wrap_function(apq<T>), derivative(wrap_function(apq<T>)), x, minf);
257             DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
258             DLIB_TEST(approx_equal(val , apq(x)));
259             dlog << LINFO << "find_min() cg: got apq/noder in " << total_count;
260 
261 
262             total_count = 0;
263             x = p;
264             val=find_min_using_approximate_derivatives(bfgs_search_strategy(),
265                                                    objective_delta_stop_strategy(eps),
266                                                    wrap_function(apq<T>), x, minf);
267             DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
268             DLIB_TEST(approx_equal(val , apq(x)));
269             dlog << LINFO << "find_min() bfgs: got apq/noder2 in " << total_count;
270 
271 
272             total_count = 0;
273             x = p;
274             val=find_min_using_approximate_derivatives(lbfgs_search_strategy(10),
275                                                    objective_delta_stop_strategy(eps),
276                                                    wrap_function(apq<T>), x, minf);
277             DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
278             dlog << LINFO << "find_min() lbfgs-10: got apq/noder2 in " << total_count;
279 
280 
281             total_count = 0;
282             x = p;
283             val=find_min_using_approximate_derivatives(cg_search_strategy(),
284                                                    objective_delta_stop_strategy(eps),
285                                                    wrap_function(apq<T>), x, minf);
286             DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
287             DLIB_TEST(approx_equal(val , apq(x)));
288             dlog << LINFO << "find_min() cg: got apq/noder2 in " << total_count;
289         }
290     }
291 
test_powell(const matrix<double,4,1> p)292     void test_powell (
293         const matrix<double,4,1> p
294     )
295     {
296         const double eps = 1e-15;
297         const double minf = -1;
298         matrix<double,4,1> x, opt;
299         opt(0) = 0;
300         opt(1) = 0;
301         opt(2) = 0;
302         opt(3) = 0;
303 
304         double val = 0;
305 
306         dlog << LINFO << "testing with powell and the start point: " << trans(p);
307 
308         /*
309         total_count = 0;
310         x = p;
311         val=find_min(bfgs_search_strategy(),
312                  objective_delta_stop_strategy(eps),
313                  powell, derivative(powell,1e-8), x, minf);
314         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-2),opt-x);
315         DLIB_TEST(approx_equal(val , powell(x)));
316         dlog << LINFO << "find_min() bfgs: got powell/noder in " << total_count;
317 
318 
319         total_count = 0;
320         x = p;
321         val=find_min(cg_search_strategy(),
322                  objective_delta_stop_strategy(eps),
323                  powell, derivative(powell,1e-9), x, minf);
324         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-2),opt-x);
325         DLIB_TEST(approx_equal(val , powell(x)));
326         dlog << LINFO << "find_min() cg: got powell/noder in " << total_count;
327         */
328 
329         total_count = 0;
330         x = p;
331         val=find_min_using_approximate_derivatives(bfgs_search_strategy(),
332                                                objective_delta_stop_strategy(eps),
333                                                powell, x, minf, 1e-10);
334         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-1),opt-x);
335         DLIB_TEST(approx_equal(val , powell(x)));
336         dlog << LINFO << "find_min() bfgs: got powell/noder2 in " << total_count;
337 
338 
339         total_count = 0;
340         x = p;
341         val=find_min_using_approximate_derivatives(lbfgs_search_strategy(4),
342                                                objective_delta_stop_strategy(eps),
343                                                powell, x, minf, 1e-10);
344         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-1),opt-x);
345         DLIB_TEST(approx_equal(val , powell(x)));
346         dlog << LINFO << "find_min() lbfgs-4: got powell/noder2 in " << total_count;
347 
348 
349         total_count = 0;
350         x = p;
351         val=find_min_using_approximate_derivatives(lbfgs_search_strategy(4),
352                                                gradient_norm_stop_strategy(),
353                                                powell, x, minf, 1e-10);
354         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-1),opt-x);
355         DLIB_TEST(approx_equal(val , powell(x)));
356         dlog << LINFO << "find_min() lbfgs-4(gn): got powell/noder2 in " << total_count;
357 
358 
359         total_count = 0;
360         x = p;
361         val=find_min_using_approximate_derivatives(cg_search_strategy(),
362                                                objective_delta_stop_strategy(eps),
363                                                powell, x, minf, 1e-10);
364         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-1),opt-x);
365         DLIB_TEST(approx_equal(val , powell(x)));
366         dlog << LINFO << "find_min() cg: got powell/noder2 in " << total_count;
367 
368 
369         total_count = 0;
370         x = p;
371         val=find_min_bobyqa(powell, x, 2*x.size()+1,
372                         uniform_matrix<double>(x.size(),1,-1e100),
373                         uniform_matrix<double>(x.size(),1,1e100),
374                         (max(abs(x))+1)/10,
375                         1e-8,
376                         10000);
377         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-3),opt-x);
378         DLIB_TEST(approx_equal(val , powell(x)));
379         dlog << LINFO << "find_min_bobyqa(): got powell in " << total_count;
380 
381     }
382 
383 
384 
test_simple(const matrix<double,2,1> p)385     void test_simple (
386         const matrix<double,2,1> p
387     )
388     {
389         const double eps = 1e-12;
390         const double minf = -10000;
391         matrix<double,2,1> x, opt;
392         opt(0) = 0;
393         opt(1) = 0;
394         double val = 0;
395 
396         dlog << LINFO << "testing with simple and the start point: " << trans(p);
397 
398         total_count = 0;
399         x = p;
400         val=find_min(bfgs_search_strategy(),
401                  objective_delta_stop_strategy(eps),
402                  simple, der_simple, x, minf);
403         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
404         DLIB_TEST(approx_equal(val , simple(x)));
405         dlog << LINFO << "find_min() bfgs: got simple in " << total_count;
406 
407 
408         total_count = 0;
409         x = p;
410         val=find_min(bfgs_search_strategy(),
411                  gradient_norm_stop_strategy(),
412                  simple, der_simple, x, minf);
413         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
414         DLIB_TEST(approx_equal(val , simple(x)));
415         dlog << LINFO << "find_min() bfgs(gn): got simple in " << total_count;
416 
417 
418         total_count = 0;
419         x = p;
420         val=find_min(lbfgs_search_strategy(3),
421                  objective_delta_stop_strategy(eps),
422                  simple, der_simple, x, minf);
423         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
424         DLIB_TEST(approx_equal(val , simple(x)));
425         dlog << LINFO << "find_min() lbfgs-3: got simple in " << total_count;
426 
427 
428         total_count = 0;
429         x = p;
430         val=find_min(cg_search_strategy(),
431                  objective_delta_stop_strategy(eps),
432                  simple, der_simple, x, minf);
433         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
434         DLIB_TEST(approx_equal(val , simple(x)));
435         dlog << LINFO << "find_min() cg: got simple in " << total_count;
436 
437 
438 
439         total_count = 0;
440         x = p;
441         val=find_min(bfgs_search_strategy(),
442                  objective_delta_stop_strategy(eps),
443                  simple, derivative(simple), x, minf);
444         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
445         DLIB_TEST(approx_equal(val , simple(x)));
446         dlog << LINFO << "find_min() bfgs: got simple/noder in " << total_count;
447 
448 
449         total_count = 0;
450         x = p;
451         val=find_min(lbfgs_search_strategy(8),
452                  objective_delta_stop_strategy(eps),
453                  simple, derivative(simple), x, minf);
454         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
455         DLIB_TEST(approx_equal(val , simple(x)));
456         dlog << LINFO << "find_min() lbfgs-8: got simple/noder in " << total_count;
457 
458 
459         total_count = 0;
460         x = p;
461         val=find_min(cg_search_strategy(),
462                  objective_delta_stop_strategy(eps),
463                  simple, derivative(simple), x, minf);
464         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
465         DLIB_TEST(approx_equal(val , simple(x)));
466         dlog << LINFO << "find_min() cg: got simple/noder in " << total_count;
467 
468 
469 
470         total_count = 0;
471         x = p;
472         val=find_min_using_approximate_derivatives(bfgs_search_strategy(),
473                                                objective_delta_stop_strategy(eps),
474                                                simple, x, minf);
475         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
476         DLIB_TEST(approx_equal(val , simple(x)));
477         dlog << LINFO << "find_min() bfgs: got simple/noder2 in " << total_count;
478 
479 
480         total_count = 0;
481         x = p;
482         val=find_min_using_approximate_derivatives(lbfgs_search_strategy(6),
483                                                objective_delta_stop_strategy(eps),
484                                                simple, x, minf);
485         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
486         DLIB_TEST(approx_equal(val , simple(x)));
487         dlog << LINFO << "find_min() lbfgs-6: got simple/noder2 in " << total_count;
488 
489 
490         total_count = 0;
491         x = p;
492         val=find_min_using_approximate_derivatives(cg_search_strategy(),
493                                                objective_delta_stop_strategy(eps),
494                                                simple, x, minf);
495         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
496         DLIB_TEST(approx_equal(val , simple(x)));
497         dlog << LINFO << "find_min() cg: got simple/noder2 in " << total_count;
498 
499 
500         total_count = 0;
501         x = p;
502         val=find_min_bobyqa(simple, x, 2*x.size()+1,
503                         uniform_matrix<double>(x.size(),1,-1e100),
504                         uniform_matrix<double>(x.size(),1,1e100),
505                         (max(abs(x))+1)/10,
506                         1e-6,
507                         10000);
508         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
509         DLIB_TEST(approx_equal(val , simple(x)));
510         dlog << LINFO << "find_min_bobyqa(): got simple in " << total_count;
511 
512     }
513 
514 
test_rosen(const matrix<double,2,1> p)515     void test_rosen (
516         const matrix<double,2,1> p
517     )
518     {
519         const double eps = 1e-15;
520         const double minf = -10;
521         matrix<double,2,1> x, opt;
522         opt(0) = 1;
523         opt(1) = 1;
524 
525         double val = 0;
526 
527         dlog << LINFO << "testing with rosen and the start point: " << trans(p);
528 
529         total_count = 0;
530         x = p;
531         val=find_min(bfgs_search_strategy(),
532                  objective_delta_stop_strategy(eps),
533                  rosen, der_rosen, x, minf);
534         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-7),opt-x);
535         DLIB_TEST(approx_equal(val , rosen(x)));
536         dlog << LINFO << "find_min() bfgs: got rosen in " << total_count;
537 
538 
539         total_count = 0;
540         x = p;
541         val=find_min(bfgs_search_strategy(),
542                  gradient_norm_stop_strategy(),
543                  rosen, der_rosen, x, minf);
544         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-7),opt-x);
545         DLIB_TEST(approx_equal(val , rosen(x)));
546         dlog << LINFO << "find_min() bfgs(gn): got rosen in " << total_count;
547 
548 
549         total_count = 0;
550         x = p;
551         val=find_min(lbfgs_search_strategy(20),
552                  objective_delta_stop_strategy(eps),
553                  rosen, der_rosen, x, minf);
554         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-7),opt-x);
555         DLIB_TEST(approx_equal(val , rosen(x)));
556         dlog << LINFO << "find_min() lbfgs-20: got rosen in " << total_count;
557 
558 
559         total_count = 0;
560         x = p;
561         val=find_min(cg_search_strategy(),
562                  objective_delta_stop_strategy(eps),
563                  rosen, der_rosen, x, minf);
564         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-7),opt-x);
565         DLIB_TEST(approx_equal(val , rosen(x)));
566         dlog << LINFO << "find_min() cg: got rosen in " << total_count;
567 
568 
569 
570         total_count = 0;
571         x = p;
572         val=find_min(bfgs_search_strategy(),
573                  objective_delta_stop_strategy(eps),
574                  rosen, derivative(rosen,1e-5), x, minf);
575         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-4),opt-x);
576         DLIB_TEST(approx_equal(val , rosen(x)));
577         dlog << LINFO << "find_min() bfgs: got rosen/noder in " << total_count;
578 
579 
580         total_count = 0;
581         x = p;
582         val=find_min(lbfgs_search_strategy(5),
583                  objective_delta_stop_strategy(eps),
584                  rosen, derivative(rosen,1e-5), x, minf);
585         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-4),opt-x);
586         DLIB_TEST(approx_equal(val , rosen(x)));
587         dlog << LINFO << "find_min() lbfgs-5: got rosen/noder in " << total_count;
588 
589 
590         total_count = 0;
591         x = p;
592         val=find_min(cg_search_strategy(),
593                  objective_delta_stop_strategy(eps),
594                  rosen, derivative(rosen,1e-5), x, minf);
595         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-4),opt-x);
596         DLIB_TEST(approx_equal(val , rosen(x)));
597         dlog << LINFO << "find_min() cg: got rosen/noder in " << total_count;
598 
599 
600         total_count = 0;
601         x = p;
602         val=find_min_using_approximate_derivatives(cg_search_strategy(),
603                                                objective_delta_stop_strategy(eps),
604                                                rosen, x, minf);
605         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-4),opt-x);
606         DLIB_TEST(approx_equal(val , rosen(x)));
607         dlog << LINFO << "find_min() cg: got rosen/noder2 in " << total_count;
608 
609 
610         if (max(abs(p)) < 1000)
611         {
612             total_count = 0;
613             x = p;
614             val=find_min_bobyqa(rosen, x, 2*x.size()+1,
615                             uniform_matrix<double>(x.size(),1,-1e100),
616                             uniform_matrix<double>(x.size(),1,1e100),
617                             (max(abs(x))+1)/10,
618                             1e-6,
619                             10000);
620             DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
621             DLIB_TEST(approx_equal(val , rosen(x)));
622             dlog << LINFO << "find_min_bobyqa(): got rosen in " << total_count;
623         }
624     }
625 
626 
test_neg_rosen(const matrix<double,2,1> p)627     void test_neg_rosen (
628         const matrix<double,2,1> p
629     )
630     {
631         const double eps = 1e-15;
632         const double maxf = 10;
633         matrix<double,2,1> x, opt;
634         opt(0) = 1;
635         opt(1) = 1;
636 
637         double val = 0;
638 
639         dlog << LINFO << "testing with neg_rosen and the start point: " << trans(p);
640 
641         total_count = 0;
642         x = p;
643         val=find_max(
644             bfgs_search_strategy(),
645             objective_delta_stop_strategy(eps), neg_rosen, der_neg_rosen, x, maxf);
646         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-7),opt-x);
647         DLIB_TEST(approx_equal(val , neg_rosen(x)));
648         dlog << LINFO << "find_max() bfgs: got neg_rosen in " << total_count;
649 
650         total_count = 0;
651         x = p;
652         val=find_max(
653             lbfgs_search_strategy(5),
654             objective_delta_stop_strategy(eps), neg_rosen, der_neg_rosen, x, maxf);
655         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-7),opt-x);
656         DLIB_TEST(approx_equal(val , neg_rosen(x)));
657         dlog << LINFO << "find_max() lbfgs-5: got neg_rosen in " << total_count;
658 
659         total_count = 0;
660         x = p;
661         val=find_max(
662             lbfgs_search_strategy(5),
663             objective_delta_stop_strategy(eps), neg_rosen, derivative(neg_rosen), x, maxf);
664         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-7),opt-x);
665         DLIB_TEST(approx_equal(val , neg_rosen(x)));
666         dlog << LINFO << "find_max() lbfgs-5: got neg_rosen/noder in " << total_count;
667 
668 
669         total_count = 0;
670         x = p;
671         val=find_max_using_approximate_derivatives(
672             cg_search_strategy(),
673             objective_delta_stop_strategy(eps), neg_rosen, x, maxf);
674         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-7),opt-x);
675         DLIB_TEST(approx_equal(val , neg_rosen(x)));
676         dlog << LINFO << "find_max() cg: got neg_rosen/noder2 in " << total_count;
677 
678 
679         total_count = 0;
680         x = p;
681         val=find_max_bobyqa(neg_rosen, x, 2*x.size()+1,
682                         uniform_matrix<double>(x.size(),1,-1e100),
683                         uniform_matrix<double>(x.size(),1,1e100),
684                         (max(abs(x))+1)/10,
685                         1e-6,
686                         10000);
687         DLIB_TEST_MSG(dlib::equal(x,opt, 1e-5),opt-x);
688         DLIB_TEST(approx_equal(val , neg_rosen(x)));
689         dlog << LINFO << "find_max_bobyqa(): got neg_rosen in " << total_count;
690     }
691 
692 // ----------------------------------------------------------------------------------------
693 
test_single_variable_function(const double p)694     void test_single_variable_function (
695         const double p
696     )
697     {
698         const double eps = 1e-7;
699 
700 
701         dlog << LINFO << "testing with single_variable_function and the start point: " << p;
702         double out, x;
703 
704         total_count = 0;
705         x = p;
706         out = find_min_single_variable(single_variable_function, x, -1e100, 1e100, eps, 1000);
707         DLIB_TEST_MSG(std::abs(out-5) < 1e-6, out-5);
708         DLIB_TEST_MSG(std::abs(x) < 1e-6, x);
709         dlog << LINFO << "find_min_single_variable(): got single_variable_function in " << total_count;
710 
711 
712         total_count = 0;
713         x = p;
714         out = -find_max_single_variable(negate_function(single_variable_function), x, -1e100, 1e100, eps, 1000);
715         DLIB_TEST_MSG(std::abs(out-5) < 1e-6, out-5);
716         DLIB_TEST_MSG(std::abs(x) < 1e-6, x);
717         dlog << LINFO << "find_max_single_variable(): got single_variable_function in " << total_count;
718 
719 
720         if (p > 0)
721         {
722             total_count = 0;
723             x = p;
724             out = find_min_single_variable(single_variable_function, x, -1e-4, 1e100, eps, 1000);
725             DLIB_TEST_MSG(std::abs(out-5) < 1e-6, out-5);
726             DLIB_TEST_MSG(std::abs(x) < 1e-6, x);
727             dlog << LINFO << "find_min_single_variable(): got single_variable_function in " << total_count;
728 
729 
730             if (p > 3)
731             {
732                 total_count = 0;
733                 x = p;
734                 out = -find_max_single_variable(negate_function(single_variable_function), x, 3, 1e100, eps, 1000);
735                 DLIB_TEST_MSG(std::abs(out - (3*3*3+5)) < 1e-6, out-(3*3*3+5));
736                 DLIB_TEST_MSG(std::abs(x-3) < 1e-6, x);
737                 dlog << LINFO << "find_max_single_variable(): got single_variable_function in " << total_count;
738             }
739         }
740 
741         if (p < 0)
742         {
743             total_count = 0;
744             x = p;
745             out = find_min_single_variable(single_variable_function, x, -1e100, 1e-4, eps, 1000);
746             DLIB_TEST_MSG(std::abs(out-5) < 1e-6, out-5);
747             DLIB_TEST_MSG(std::abs(x) < 1e-6, x);
748             dlog << LINFO << "find_min_single_variable(): got single_variable_function in " << total_count;
749 
750             if (p < -3)
751             {
752                 total_count = 0;
753                 x = p;
754                 out = find_min_single_variable(single_variable_function, x, -1e100, -3, eps, 1000);
755                 DLIB_TEST_MSG(std::abs(out - (3*3*3+5)) < 1e-6, out-(3*3*3+5));
756                 DLIB_TEST_MSG(std::abs(x+3) < 1e-6, x);
757                 dlog << LINFO << "find_min_single_variable(): got single_variable_function in " << total_count;
758             }
759         }
760 
761     }
762 
763 // ----------------------------------------------------------------------------------------
764 
optimization_test()765     void optimization_test (
766     )
767     /*!
768         ensures
769             - runs tests on the optimization stuff compliance with the specs
770     !*/
771     {
772         matrix<double,0,1> p;
773 
774         print_spinner();
775 
776         p.set_size(2);
777 
778         // test with single_variable_function
779         test_single_variable_function(0);
780         test_single_variable_function(1);
781         test_single_variable_function(-10);
782         test_single_variable_function(-100);
783         test_single_variable_function(900.53);
784 
785         // test with the rosen function
786         p(0) = 9;
787         p(1) = -4.9;
788         test_rosen(p);
789         test_neg_rosen(p);
790 
791         p(0) = 0;
792         p(1) = 0;
793         test_rosen(p);
794 
795         p(0) = 5323;
796         p(1) = 98248;
797         test_rosen(p);
798 
799         // test with the simple function
800         p(0) = 1;
801         p(1) = 1;
802         test_simple(p);
803 
804         p(0) = 0.5;
805         p(1) = -9;
806         test_simple(p);
807 
808         p(0) = 645;
809         p(1) = 839485;
810         test_simple(p);
811 
812         print_spinner();
813 
814         // test with the apq function
815         p.set_size(5);
816 
817         p(0) = 1;
818         p(1) = 1;
819         p(2) = 1;
820         p(3) = 1;
821         p(4) = 1;
822         test_apq(p);
823 
824         p(0) = 1;
825         p(1) = 2;
826         p(2) = 3;
827         p(3) = 4;
828         p(4) = 5;
829         test_apq(p);
830 
831         p(0) = 1;
832         p(1) = 2;
833         p(2) = -3;
834         p(3) = 4;
835         p(4) = 5;
836         test_apq(p);
837 
838         print_spinner();
839 
840         p(0) = 1;
841         p(1) = 2324;
842         p(2) = -3;
843         p(3) = 4;
844         p(4) = 534534;
845         test_apq(p);
846 
847         p.set_size(10);
848         p(0) = 1;
849         p(1) = 2;
850         p(2) = -3;
851         p(3) = 4;
852         p(4) = 5;
853         p(5) = 1;
854         p(6) = 2;
855         p(7) = -3;
856         p(8) = 4;
857         p(9) = 5;
858         test_apq(p);
859 
860         // test apq with a big vector
861         p.set_size(500);
862         dlib::rand rnd;
863         for (long i = 0; i < p.size(); ++i)
864         {
865             p(i) = rnd.get_random_double()*20 - 10;
866         }
867         test_apq(p);
868 
869         print_spinner();
870 
871         // test with the powell function
872         p.set_size(4);
873 
874         p(0) = 3;
875         p(1) = -1;
876         p(2) = 0;
877         p(3) = 1;
878         test_powell(p);
879 
880         {
881             matrix<double,2,1> m;
882             m(0) = -0.43;
883             m(1) = 0.919;
884             DLIB_TEST(dlib::equal(der_rosen(m) , derivative(rosen)(m),1e-5));
885 
886             DLIB_TEST_MSG(std::abs(derivative(make_line_search_function(rosen,m,m))(0) -
887                                   make_line_search_function(derivative(rosen),m,m)(0)) < 1e-5,"");
888             DLIB_TEST_MSG(std::abs(derivative(make_line_search_function(rosen,m,m))(1) -
889                                   make_line_search_function(derivative(rosen),m,m)(1)) < 1e-5,"");
890 
891             DLIB_TEST_MSG(std::abs(derivative(make_line_search_function(rosen,m,m))(0) -
892                                   make_line_search_function(der_rosen,m,m)(0)) < 1e-5,"");
893             DLIB_TEST_MSG(std::abs(derivative(make_line_search_function(rosen,m,m))(1) -
894                                   make_line_search_function(der_rosen,m,m)(1)) < 1e-5,"");
895         }
896         {
897             matrix<double,2,1> m;
898             m(0) = 1;
899             m(1) = 2;
900             DLIB_TEST(dlib::equal(der_rosen(m) , derivative(rosen)(m),1e-5));
901 
902             DLIB_TEST_MSG(std::abs(derivative(make_line_search_function(rosen,m,m))(0) -
903                                   make_line_search_function(derivative(rosen),m,m)(0)) < 1e-5,"");
904             DLIB_TEST_MSG(std::abs(derivative(make_line_search_function(rosen,m,m))(1) -
905                                   make_line_search_function(derivative(rosen),m,m)(1)) < 1e-5,"");
906 
907             DLIB_TEST_MSG(std::abs(derivative(make_line_search_function(rosen,m,m))(0) -
908                                   make_line_search_function(der_rosen,m,m)(0)) < 1e-5,"");
909             DLIB_TEST_MSG(std::abs(derivative(make_line_search_function(rosen,m,m))(1) -
910                                   make_line_search_function(der_rosen,m,m)(1)) < 1e-5,"");
911         }
912 
913         {
914             matrix<double,2,1> m;
915             m = 1,2;
916             DLIB_TEST(std::abs(neg_rosen(m) - negate_function(rosen)(m) ) < 1e-16);
917         }
918 
919     }
920 
921     template <typename der_funct, typename T>
unconstrained_gradient_magnitude(const der_funct & grad,const T & x,const T & lower,const T & upper)922     double unconstrained_gradient_magnitude (
923         const der_funct& grad,
924         const T& x,
925         const T& lower,
926         const T& upper
927     )
928     {
929         T g = grad(x);
930 
931         double unorm = 0;
932 
933         for (long i = 0; i < g.size(); ++i)
934         {
935             if (lower(i) < x(i) && x(i) < upper(i))
936                 unorm += g(i)*g(i);
937             else if (x(i) == lower(i) && g(i) < 0)
938                 unorm += g(i)*g(i);
939             else if (x(i) == upper(i) && g(i) > 0)
940                 unorm += g(i)*g(i);
941         }
942 
943         return unorm;
944     }
945 
946     template <typename der_funct, typename T>
unconstrained_gradient_magnitude_neg_funct(const der_funct & grad,const T & x,const T & lower,const T & upper)947     double unconstrained_gradient_magnitude_neg_funct (
948         const der_funct& grad,
949         const T& x,
950         const T& lower,
951         const T& upper
952     )
953     {
954         T g = grad(x);
955 
956         double unorm = 0;
957 
958         for (long i = 0; i < g.size(); ++i)
959         {
960             if (lower(i) < x(i) && x(i) < upper(i))
961                 unorm += g(i)*g(i);
962             else if (x(i) == lower(i) && g(i) > 0)
963                 unorm += g(i)*g(i);
964             else if (x(i) == upper(i) && g(i) < 0)
965                 unorm += g(i)*g(i);
966         }
967 
968         return unorm;
969     }
970 
971     template <typename search_strategy_type>
test_bound_solver_neg_rosen(dlib::rand & rnd,search_strategy_type search_strategy)972     double test_bound_solver_neg_rosen (dlib::rand& rnd, search_strategy_type search_strategy)
973     {
974         using namespace dlib::test_functions;
975         print_spinner();
976         matrix<double,2,1> starting_point, lower, upper, x;
977 
978 
979         // pick random bounds
980         lower = rnd.get_random_gaussian()+1, rnd.get_random_gaussian()+1;
981         upper = rnd.get_random_gaussian()+1, rnd.get_random_gaussian()+1;
982         while (upper(0) < lower(0)) upper(0) = rnd.get_random_gaussian()+1;
983         while (upper(1) < lower(1)) upper(1) = rnd.get_random_gaussian()+1;
984 
985         starting_point = rnd.get_random_double()*(upper(0)-lower(0))+lower(0),
986                        rnd.get_random_double()*(upper(1)-lower(1))+lower(1);
987 
988         dlog << LINFO << "lower: "<< trans(lower);
989         dlog << LINFO << "upper: "<< trans(upper);
990         dlog << LINFO << "starting: "<< trans(starting_point);
991 
992         x = starting_point;
993         double val = find_max_box_constrained(
994             search_strategy,
995             objective_delta_stop_strategy(1e-16, 500),
996             neg_rosen, der_neg_rosen, x,
997             lower,
998             upper
999         );
1000 
1001         DLIB_TEST_MSG(std::abs(val - neg_rosen(x)) < 1e-11, std::abs(val - neg_rosen(x)));
1002         dlog << LINFO << "neg_rosen solution:\n" << x;
1003 
1004         dlog << LINFO << "neg_rosen gradient: "<< trans(der_neg_rosen(x));
1005         const double gradient_residual = unconstrained_gradient_magnitude_neg_funct(der_neg_rosen, x, lower, upper);
1006         dlog << LINFO << "gradient_residual: "<< gradient_residual;
1007 
1008         return gradient_residual;
1009     }
1010 
1011     template <typename search_strategy_type>
test_bound_solver_rosen(dlib::rand & rnd,search_strategy_type search_strategy)1012     double test_bound_solver_rosen (dlib::rand& rnd, search_strategy_type search_strategy)
1013     {
1014         using namespace dlib::test_functions;
1015         print_spinner();
1016         matrix<double,2,1> starting_point, lower, upper, x;
1017 
1018 
1019         // pick random bounds and sometimes put the upper bound at zero so we can have
1020         // a test where the optimal value has a bound active at 0 so make sure this case
1021         // works properly.
1022         if (rnd.get_random_double() > 0.2)
1023         {
1024             lower = rnd.get_random_gaussian()+1, rnd.get_random_gaussian()+1;
1025             upper = rnd.get_random_gaussian()+1, rnd.get_random_gaussian()+1;
1026             while (upper(0) < lower(0)) upper(0) = rnd.get_random_gaussian()+1;
1027             while (upper(1) < lower(1)) upper(1) = rnd.get_random_gaussian()+1;
1028         }
1029         else
1030         {
1031             upper = 0,0;
1032             if (rnd.get_random_double() > 0.5)
1033                 upper(0) = -rnd.get_random_double();
1034             if (rnd.get_random_double() > 0.5)
1035                 upper(1) = -rnd.get_random_double();
1036 
1037             lower = rnd.get_random_double()+1, rnd.get_random_double()+1;
1038             lower = upper - lower;
1039         }
1040         const bool pick_uniform_bounds = rnd.get_random_double() > 0.9;
1041         if (pick_uniform_bounds)
1042         {
1043             double x = rnd.get_random_gaussian()*2;
1044             double y = rnd.get_random_gaussian()*2;
1045             lower = min(x,y);
1046             upper = max(x,y);
1047         }
1048 
1049         starting_point = rnd.get_random_double()*(upper(0)-lower(0))+lower(0),
1050                        rnd.get_random_double()*(upper(1)-lower(1))+lower(1);
1051 
1052         dlog << LINFO << "lower: "<< trans(lower);
1053         dlog << LINFO << "upper: "<< trans(upper);
1054         dlog << LINFO << "starting: "<< trans(starting_point);
1055 
1056         x = starting_point;
1057         double val;
1058         if (!pick_uniform_bounds)
1059         {
1060             val = find_min_box_constrained(
1061                 search_strategy,
1062                 objective_delta_stop_strategy(1e-16, 500),
1063                 rosen, der_rosen, x,
1064                 lower,
1065                 upper
1066             );
1067         }
1068         else
1069         {
1070             val = find_min_box_constrained(
1071                 search_strategy,
1072                 objective_delta_stop_strategy(1e-16, 500),
1073                 rosen, der_rosen, x,
1074                 lower(0),
1075                 upper(0)
1076             );
1077         }
1078 
1079 
1080         DLIB_TEST_MSG(std::abs(val - rosen(x)) < 1e-11, std::abs(val - rosen(x)));
1081         dlog << LINFO << "rosen solution:\n" << x;
1082 
1083         dlog << LINFO << "rosen gradient: "<< trans(der_rosen(x));
1084         const double gradient_residual = unconstrained_gradient_magnitude(der_rosen, x, lower, upper);
1085         dlog << LINFO << "gradient_residual: "<< gradient_residual;
1086 
1087         return gradient_residual;
1088     }
1089 
1090     template <typename search_strategy_type>
test_bound_solver_brown(dlib::rand & rnd,search_strategy_type search_strategy)1091     double test_bound_solver_brown (dlib::rand& rnd, search_strategy_type search_strategy)
1092     {
1093         using namespace dlib::test_functions;
1094         print_spinner();
1095         matrix<double,4,1> starting_point(4), lower(4), upper(4), x;
1096 
1097         const matrix<double,0,1> solution = brown_solution();
1098 
1099         // pick random bounds
1100         lower = rnd.get_random_gaussian(), rnd.get_random_gaussian(), rnd.get_random_gaussian(), rnd.get_random_gaussian();
1101         lower = lower*10 + solution;
1102         upper = rnd.get_random_gaussian(), rnd.get_random_gaussian(), rnd.get_random_gaussian(), rnd.get_random_gaussian();
1103         upper = upper*10 + solution;
1104         for (int i = 0; i < lower.size(); ++i)
1105         {
1106             if (upper(i) < lower(i))
1107                 swap(upper(i),lower(i));
1108         }
1109 
1110         starting_point = rnd.get_random_double()*(upper(0)-lower(0))+lower(0),
1111                        rnd.get_random_double()*(upper(1)-lower(1))+lower(1),
1112                        rnd.get_random_double()*(upper(2)-lower(2))+lower(2),
1113                        rnd.get_random_double()*(upper(3)-lower(3))+lower(3);
1114 
1115         dlog << LINFO << "lower: "<< trans(lower);
1116         dlog << LINFO << "upper: "<< trans(upper);
1117         dlog << LINFO << "starting: "<< trans(starting_point);
1118 
1119         // The contract for find_min_box_constrained() says we always call obj() before der().  So
1120         // these lambdas verify that this is so.
1121         dlib::matrix<double,0,1> last_x;
1122         auto obj = [&](const dlib::matrix<double,0,1> &x) { last_x = x; return brown(x); };
1123         auto der = [&](const dlib::matrix<double,0,1> &x) {
1124             // check that obj(x) was called before der(x).
1125             DLIB_TEST_MSG(max(abs(x - last_x)) == 0, max(abs(x - last_x)));
1126             return brown_derivative(x);
1127         };
1128 
1129         x = starting_point;
1130         double val = find_min_box_constrained(
1131             search_strategy,
1132             objective_delta_stop_strategy(1e-16, 500),
1133             obj, der, x,
1134             lower,
1135             upper
1136         );
1137 
1138         DLIB_TEST(std::abs(val - brown(x)) < 1e-14);
1139         dlog << LINFO << "brown solution:\n" << x;
1140         return unconstrained_gradient_magnitude(brown_derivative, x, lower, upper);
1141     }
1142 
1143     template <typename search_strategy_type>
test_box_constrained_optimizers(search_strategy_type search_strategy)1144     void test_box_constrained_optimizers(search_strategy_type search_strategy)
1145     {
1146         dlib::rand rnd;
1147         running_stats<double> rs;
1148 
1149         dlog << LINFO << "test find_min_box_constrained() on rosen";
1150         for (int i = 0; i < 10000; ++i)
1151             rs.add(test_bound_solver_rosen(rnd, search_strategy));
1152         dlog << LINFO << "mean rosen gradient: " << rs.mean();
1153         dlog << LINFO << "max rosen gradient:  " << rs.max();
1154         DLIB_TEST(rs.mean() < 1e-12);
1155         DLIB_TEST(rs.max() < 1e-9);
1156 
1157         dlog << LINFO << "test find_min_box_constrained() on brown";
1158         rs.clear();
1159         for (int i = 0; i < 1000; ++i)
1160             rs.add(test_bound_solver_brown(rnd, search_strategy));
1161         dlog << LINFO << "mean brown gradient: " << rs.mean();
1162         dlog << LINFO << "max brown gradient:  " << rs.max();
1163         dlog << LINFO << "min brown gradient:  " << rs.min();
1164         DLIB_TEST(rs.mean() < 4e-5);
1165         DLIB_TEST_MSG(rs.max() < 3e-2, rs.max());
1166         DLIB_TEST(rs.min() < 1e-10);
1167 
1168         dlog << LINFO << "test find_max_box_constrained() on neg_rosen";
1169         rs.clear();
1170         for (int i = 0; i < 1000; ++i)
1171             rs.add(test_bound_solver_neg_rosen(rnd, search_strategy));
1172         dlog << LINFO << "mean neg_rosen gradient: " << rs.mean();
1173         dlog << LINFO << "max neg_rosen gradient:  " << rs.max();
1174         DLIB_TEST(rs.mean() < 1e-12);
1175         DLIB_TEST(rs.max() < 1e-9);
1176 
1177     }
1178 
test_poly_min_extract_2nd()1179     void test_poly_min_extract_2nd()
1180     {
1181         double off;
1182 
1183         off = 0.0; DLIB_TEST(std::abs( poly_min_extrap(off*off, -2*off, (1-off)*(1-off)) - off) < 1e-13);
1184         off = 0.1; DLIB_TEST(std::abs( poly_min_extrap(off*off, -2*off, (1-off)*(1-off)) - off) < 1e-13);
1185         off = 0.2; DLIB_TEST(std::abs( poly_min_extrap(off*off, -2*off, (1-off)*(1-off)) - off) < 1e-13);
1186         off = 0.3; DLIB_TEST(std::abs( poly_min_extrap(off*off, -2*off, (1-off)*(1-off)) - off) < 1e-13);
1187         off = 0.4; DLIB_TEST(std::abs( poly_min_extrap(off*off, -2*off, (1-off)*(1-off)) - off) < 1e-13);
1188         off = 0.5; DLIB_TEST(std::abs( poly_min_extrap(off*off, -2*off, (1-off)*(1-off)) - off) < 1e-13);
1189         off = 0.6; DLIB_TEST(std::abs( poly_min_extrap(off*off, -2*off, (1-off)*(1-off)) - off) < 1e-13);
1190         off = 0.8; DLIB_TEST(std::abs( poly_min_extrap(off*off, -2*off, (1-off)*(1-off)) - off) < 1e-13);
1191         off = 0.9; DLIB_TEST(std::abs( poly_min_extrap(off*off, -2*off, (1-off)*(1-off)) - off) < 1e-13);
1192         off = 1.0; DLIB_TEST(std::abs( poly_min_extrap(off*off, -2*off, (1-off)*(1-off)) - off) < 1e-13);
1193     }
1194 
test_solve_trust_region_subproblem_bounded()1195     void test_solve_trust_region_subproblem_bounded()
1196     {
1197         print_spinner();
1198         matrix<double> H(2,2);
1199         H = 1, 0,
1200         0, 1;
1201         matrix<double,0,1> g, lower, upper, p, true_p;
1202         g = {0, 0};
1203 
1204         double radius = 0.5;
1205         lower = {0.5, 0};
1206         upper = {10, 10};
1207 
1208 
1209         solve_trust_region_subproblem_bounded(H,g, radius, p,  0.001, 500, lower, upper);
1210         true_p = { 0.5, 0};
1211         DLIB_TEST_MSG(length(p-true_p) < 1e-12, p);
1212 
1213     }
1214 
1215 // ----------------------------------------------------------------------------------------
1216 
test_find_min_single_variable()1217     void test_find_min_single_variable()
1218     {
1219         auto f = [](double x) { return (x-0.2)*(x-0.2); };
1220         double x = 0.8;
1221         try
1222         {
1223             find_min_single_variable(f, x, 0, 1, 1e-9);
1224             DLIB_TEST(std::abs(x-0.2) < 1e-7);
1225         }
1226         catch(optimize_single_variable_failure&)
1227         {
1228             DLIB_TEST(false);
1229         }
1230     }
1231 
1232 // ----------------------------------------------------------------------------------------
1233 
1234     class optimization_tester : public tester
1235     {
1236     public:
optimization_tester()1237         optimization_tester (
1238         ) :
1239             tester ("test_optimization",
1240                     "Runs tests on the optimization component.")
1241         {}
1242 
perform_test()1243         void perform_test (
1244         )
1245         {
1246             dlog << LINFO << "test_box_constrained_optimizers(bfgs_search_strategy())";
1247             test_box_constrained_optimizers(bfgs_search_strategy());
1248             dlog << LINFO << "test_box_constrained_optimizers(lbfgs_search_strategy(5))";
1249             test_box_constrained_optimizers(lbfgs_search_strategy(5));
1250             test_poly_min_extract_2nd();
1251             optimization_test();
1252             test_solve_trust_region_subproblem_bounded();
1253             test_find_min_single_variable();
1254         }
1255     } a;
1256 
1257 }
1258 
1259 
1260