| 571 | |
| 572 | template <typename funct> |
| 573 | double find_min_single_variable ( |
| 574 | const funct& f, |
| 575 | double& starting_point, |
| 576 | const double begin = -1e200, |
| 577 | const double end = 1e200, |
| 578 | const double eps = 1e-3, |
| 579 | const long max_iter = 100, |
| 580 | const double initial_search_radius = 1 |
| 581 | ) |
| 582 | { |
| 583 | DLIB_CASSERT( eps > 0 && |
| 584 | max_iter > 1 && |
| 585 | begin <= starting_point && starting_point <= end && |
| 586 | initial_search_radius > 0, |
| 587 | "eps: " << eps |
| 588 | << "\n max_iter: "<< max_iter |
| 589 | << "\n begin: "<< begin |
| 590 | << "\n end: "<< end |
| 591 | << "\n starting_point: "<< starting_point |
| 592 | << "\n initial_search_radius: "<< initial_search_radius |
| 593 | ); |
| 594 | |
| 595 | double search_radius = initial_search_radius; |
| 596 | |
| 597 | double p1=0, p2=0, p3=0, f1=0, f2=0, f3=0; |
| 598 | long f_evals = 1; |
| 599 | |
| 600 | if (begin == end) |
| 601 | { |
| 602 | return f(starting_point); |
| 603 | } |
| 604 | |
| 605 | using std::abs; |
| 606 | using std::min; |
| 607 | using std::max; |
| 608 | |
| 609 | // find three bracketing points such that f1 > f2 < f3. Do this by generating a sequence |
| 610 | // of points expanding away from 0. Also note that, in the following code, it is always the |
| 611 | // case that p1 < p2 < p3. |
| 612 | |
| 613 | |
| 614 | |
| 615 | // The first thing we do is get a starting set of 3 points that are inside the [begin,end] bounds |
| 616 | p1 = max(starting_point-search_radius, begin); |
| 617 | p3 = min(starting_point+search_radius, end); |
| 618 | f1 = f(p1); |
| 619 | f3 = f(p3); |
| 620 | |
| 621 | if (starting_point == p1 || starting_point == p3) |
| 622 | { |
| 623 | p2 = (p1+p3)/2; |
| 624 | f2 = f(p2); |
| 625 | } |
| 626 | else |
| 627 | { |
| 628 | p2 = starting_point; |
| 629 | f2 = f(starting_point); |
| 630 | } |