// 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) #ifndef BOOST_MATH_OPTIMIZATION_GRADIENT_DESCENT_HPP #define BOOST_MATH_OPTIMIZATION_GRADIENT_DESCENT_HPP #include #include #include namespace boost { namespace math { namespace optimization { template struct gradient_descent_update_policy { RealType lr_; gradient_descent_update_policy(RealType lr) : lr_(lr) {}; template::value>::type> void operator()(ArgumentType& x, RealType& g) { x.get_value() -= lr_ * g; } template::value, int>::type = 0> void operator()(ArgumentType& x, RealType& g) const { x -= lr_ * g; } }; /** * @brief> Gradient Descent Optimizer. * * This class implements a gradient descent optimization strategy using the * policies provided for initialization, objective evaluation, and gradient * computation. It inherits from `abstract_optimizer`, which provides the * general optimization framework. * * @tparam> ArgumentContainer Type of the parameter container (e.g. * std::vector). * @tparam> RealType Floating-point type * @tparam> Objective Objective function type (functor or callable). * @tparam> InitializationPolicy Policy controlling initialization of * differentiable variables. * @tparam> ObjectiveEvalPolicy Policy defining how the objective is evaluated. * @tparam> GradEvalPolicy Policy defining how the gradient is computed. */ template class gradient_descent : public abstract_optimizer, gradient_descent> { using base_opt = abstract_optimizer, gradient_descent>; public: using base_opt::base_opt; /** * @brief Perform one optimization step. * * defaults to a regular update inside abstract optimizer * x -= lr * grad(f) */ void step() { this->step_impl(); } }; /** * @brief Create a gradient descent optimizer with default reverse-mode autodiff policies. * * make_gradient_descent(objective, x) * constructs gradient descent with objective function, and parameters x * * learning rate set to 0.01 by default * * initialization strategy : use specified, gradient tape taken care of by * optimizer * function eval policy : rvar function eval policy, to be used with * boost::math::differentiation::reverse_mode::rvar * * gradient eval policy : rvar gradient evaluation policy * * gradient descent update policy : * basically x -= lr * grad(f); * * make_gradient_descent(objective, x, lr) * custom learning rate */ template auto make_gradient_descent(Objective&& obj, ArgumentContainer& x, RealType lr = RealType{ 0.01 }) { return gradient_descent, tape_initializer_rvar, reverse_mode_function_eval_policy, reverse_mode_gradient_evaluation_policy>( std::forward(obj), x, tape_initializer_rvar{}, reverse_mode_function_eval_policy{}, reverse_mode_gradient_evaluation_policy{}, gradient_descent_update_policy(lr)); } template auto make_gradient_descent(Objective&& obj, ArgumentContainer& x, RealType lr, InitializationPolicy&& ip) { return gradient_descent, InitializationPolicy, reverse_mode_function_eval_policy, reverse_mode_gradient_evaluation_policy>( std::forward(obj), x, std::forward(ip), reverse_mode_function_eval_policy{}, reverse_mode_gradient_evaluation_policy{}, gradient_descent_update_policy(lr)); } template auto make_gradient_descent(Objective&& obj, ArgumentContainer& x, RealType& lr, InitializationPolicy&& ip, ObjectiveEvalPolicy&& oep, GradEvalPolicy&& gep) { return gradient_descent, InitializationPolicy, ObjectiveEvalPolicy, GradEvalPolicy>( std::forward(obj), x, std::forward(ip), std::forward(oep), std::forward(gep), gradient_descent_update_policy{ lr }); } } // namespace optimization } // namespace math } // namespace boost #endif