// Copyright Maksym Zhelyenzyakov 2025-2026. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // https://www.boost.org/LICENSE_1_0.txt) #include "test_autodiff_reverse.hpp" #include "test_functions_for_optimization.hpp" #include #include #include namespace rdiff = boost::math::differentiation::reverse_mode; namespace bopt = boost::math::optimization; BOOST_AUTO_TEST_SUITE(basic_lbfgs) BOOST_AUTO_TEST_CASE_TEMPLATE(default_lbfgs_test, T, all_float_types) { constexpr size_t NITER = 10; constexpr size_t M = 10; const T eps = T{ 1e-8 }; RandomSample rng{ T(-10), T(10) }; std::array, 2> x; x[0] = rng.next(); x[1] = rng.next(); auto opt = bopt::make_lbfgs(&rosenbrock_saddle>, x, M); auto result = minimize(opt); for (auto& xi : x) { BOOST_REQUIRE_CLOSE(xi, T{ 1.0 }, eps); } } // Custom initialization policy that zeros out the parameters template struct zero_init_policy { void operator()(std::vector& x) const noexcept { std::fill(x.begin(), x.end(), RealType{ 0 }); } }; template struct analytic_objective_eval_pol { template RealType operator()(Objective&& objective, ArgumentContainer& x) { return objective(x); } }; template struct analytic_gradient_eval_pol { template void operator()(Objective&& obj_f, ArgumentContainer& x, FunctionEvaluationPolicy&& f_eval_pol, RealType& obj_v, std::vector& grad_container) { RealType v = f_eval_pol(obj_f, x); obj_v = v; grad_container.resize(x.size()); for (size_t i = 0; i < x.size(); ++i) { grad_container[i] = 2 * x[i]; } } }; // -- Test L-BFGS with custom initialization policy (zero_init_policy) BOOST_AUTO_TEST_CASE_TEMPLATE(custom_init_lbfgs_test, T, all_float_types) { constexpr size_t M = 8; const T eps = T{ 1e-6 }; RandomSample rng{ T(-5), T(5) }; std::array, 2> x; x[0] = rng.next(); x[1] = rng.next(); auto opt = bopt::make_lbfgs(&rosenbrock_saddle>, x, M, bopt::costant_initializer_rvar(0.0)); auto result = minimize(opt); for (auto& xi : x) { BOOST_REQUIRE_CLOSE(xi, T{ 1.0 }, eps); } } // // -- Test L-BFGS with analytic derivative policies // BOOST_AUTO_TEST_CASE_TEMPLATE(analytic_lbfgs_test, T, all_float_types) // { // constexpr size_t M = 10; // const T eps = T{ 1e-3 }; // RandomSample rng{ T(-5), T(5) }; // std::vector x(3); // for (auto& xi : x) // xi = rng.next(); // auto opt = bopt::make_lbfgs( // &quadratic>, // Objective // x, // Arguments // M, // History size // bopt::random_uniform_initializer_rvar{}, // Initialization // analytic_objective_eval_pol{}, // Function eval // analytic_gradient_eval_pol{} // Gradient eval // ); // // Run optimization (manual loop or minimize wrapper) // auto result = minimize(opt); // for (auto& xi : x) { // BOOST_REQUIRE_SMALL(xi, eps); // } // } // // -- Test L-BFGS with analytic policies and custom line search // // (strong_wolfe_line_search_policy) // BOOST_AUTO_TEST_CASE_TEMPLATE(analytic_lbfgs_strong_wolfe_test, // T, // all_float_types) // { // constexpr size_t M = 12; // const T eps = T{ 1e-4 }; // RandomSample rng{ T(-10), T(10) }; // std::vector x(5); // for (auto& xi : x) // xi = rng.next(); // auto opt = bopt::make_lbfgs( // &quadratic, // x, // M, // boost::math::optimization::random_uniform_initializer_rvar{}, // analytic_objective_eval_pol{}, // analytic_gradient_eval_pol{}, // boost::math::optimization::armijo_line_search_policy{}); // auto result = minimize(opt); // for (auto& xi : x) { // BOOST_REQUIRE_SMALL(xi, eps); // } // } // // -- Test L-BFGS with random init policy (demonstrates flexible // initialization) template struct random_init_policy // { // RandomSample rng{ RealType(-1), RealType(1) }; // void operator()(std::vector& x) const noexcept // { // for (auto& xi : x) // xi = rng.next(); // } // }; // BOOST_AUTO_TEST_CASE_TEMPLATE(random_init_lbfgs_test, T, all_float_types) // { // constexpr size_t M = 6; // const T eps = T{ 1e-4 }; // std::vector x(4); // random_init_policy{}(x); // Apply initialization manually // auto opt = bopt::make_lbfgs(&quadratic, // x, // M, // random_init_policy{}, // analytic_objective_eval_pol{}, // analytic_gradient_eval_pol{}); // auto result = minimize(opt); // for (auto& xi : x) { // BOOST_REQUIRE_SMALL(xi, eps); // } // } BOOST_AUTO_TEST_SUITE_END()