| 587 | typename EXP2 |
| 588 | > |
| 589 | double find_max_box_constrained ( |
| 590 | search_strategy_type search_strategy, |
| 591 | stop_strategy_type stop_strategy, |
| 592 | const funct& f, |
| 593 | const funct_der& der, |
| 594 | T& x, |
| 595 | const matrix_exp<EXP1>& x_lower, |
| 596 | const matrix_exp<EXP2>& x_upper |
| 597 | ) |
| 598 | { |
| 599 | // make sure the requires clause is not violated |
| 600 | COMPILE_TIME_ASSERT(is_matrix<T>::value); |
| 601 | // The starting point (i.e. x) must be a column vector. |
| 602 | COMPILE_TIME_ASSERT(T::NC <= 1); |
| 603 | |
| 604 | DLIB_CASSERT ( |
| 605 | is_col_vector(x) && is_col_vector(x_lower) && is_col_vector(x_upper) && |
| 606 | x.size() == x_lower.size() && x.size() == x_upper.size(), |
| 607 | "\tdouble find_max_box_constrained()" |
| 608 | << "\n\t The inputs to this function must be equal length column vectors." |
| 609 | << "\n\t is_col_vector(x): " << is_col_vector(x) |
| 610 | << "\n\t is_col_vector(x_upper): " << is_col_vector(x_upper) |
| 611 | << "\n\t is_col_vector(x_upper): " << is_col_vector(x_upper) |
| 612 | << "\n\t x.size(): " << x.size() |
| 613 | << "\n\t x_lower.size(): " << x_lower.size() |
| 614 | << "\n\t x_upper.size(): " << x_upper.size() |
| 615 | ); |
| 616 | DLIB_ASSERT ( |
| 617 | min(x_upper-x_lower) >= 0, |
| 618 | "\tdouble find_max_box_constrained()" |
| 619 | << "\n\t You have to supply proper box constraints to this function." |
| 620 | << "\n\r min(x_upper-x_lower): " << min(x_upper-x_lower) |
| 621 | ); |
| 622 | |
| 623 | // This function is basically just a copy of find_min_box_constrained() but with - put |
| 624 | // in the right places to flip things around so that it ends up looking for the max |
| 625 | // rather than the min. |
| 626 | |
| 627 | T g, s; |
| 628 | double f_value = -f(x); |
| 629 | g = -der(x); |
| 630 | |
| 631 | if (!is_finite(f_value)) |
| 632 | throw error("The objective function generated non-finite outputs"); |
| 633 | if (!is_finite(g)) |
| 634 | throw error("The objective function generated non-finite outputs"); |
| 635 | |
| 636 | // gap_eps determines how close we have to get to a bound constraint before we |
| 637 | // start basically dropping it from the optimization and consider it to be an |
| 638 | // active constraint. |
| 639 | const double gap_eps = 1e-8; |
| 640 | |
| 641 | double last_alpha = 1; |
| 642 | while(stop_strategy.should_continue_search(x, f_value, g)) |
| 643 | { |
| 644 | s = search_strategy.get_next_direction(x, f_value, zero_bounded_variables(gap_eps, g, x, g, x_lower, x_upper)); |
| 645 | s = gap_step_assign_bounded_variables(gap_eps, s, x, g, x_lower, x_upper); |
| 646 | |