Loading README.md +22 −20 Original line number Diff line number Diff line Loading @@ -41,25 +41,30 @@ There are three steps to use gradient-descent-cpp: ```cpp #include <gdcpp.h> // Implement an objective functor. struct Paraboloid struct Ackley { double operator()(const Eigen::VectorXd &xval, Eigen::VectorXd &gradient) static double pi() { return 3.141592653589; } Ackley() { } double operator()(const Eigen::VectorXd &xval, Eigen::VectorXd &) const { // compute gradient explicitly // if gradient calculation is omitted, then the optimizer uses // finite differences to approximate the gradient numerically gradient.resize(2); gradient(0) = 2 * xval(0); gradient(1) = 2 * xval(1); return xval(0) * xval(0) + xval(1) * xval(1); assert(xval.size() == 2); double x = xval(0); double y = xval(1); // Calculate ackley function, but no gradient. Let gradien be estimated // numerically. return -20.0 * std::exp(-0.2 * std::sqrt(0.5 * (x * x + y * y))) - std::exp(0.5 * (std::cos(2 * pi() * x) + std::cos(2 * pi() * y))) + std::exp(1) + 20.0; } }; int main() { // Create optimizer object with Paraboloid functor as objective. // Create optimizer object with Ackley functor as objective. // // You can specify a StepSize functor as template parameter. // There are ConstantStepSize, LimitedChangeStep, BarzilaiBorweinStep and Loading @@ -70,12 +75,12 @@ int main() // You can additionally specify a FiniteDifferences functor as template // parameter. There are Forward-, Backward- and CentralDifferences // available. (Default is CentralDifferences) gdc::GradientDescent<double, Paraboloid, gdc::ConstantStepSize<double, Paraboloid>> optimizer; gdc::GradientDescent<double, Ackley, gdc::WolfeLineSearch<double, Ackley>> optimizer; // Set number of iterations as stop criterion. // Set it to 0 or negative for infinite iterations (default is 0). optimizer.setMaxIterations(100); optimizer.setMaxIterations(200); // Set the minimum length of the gradient. // The optimizer stops minimizing if the gradient length falls below this Loading @@ -87,12 +92,9 @@ int main() // value (default is 1e-9). optimizer.setMinStepLength(1e-6); // Set the the parametrized StepSize functor used for the step calculation. optimizer.setStepSize(gdc::ConstantStepSize<double, Paraboloid>(0.8)); // Set the momentum rate used for the step calculation (default is 0.0). // Defines how much momentum is kept from previous iterations. optimizer.setMomentum(0.1); optimizer.setMomentum(0.4); // Turn verbosity on, so the optimizer prints status updates after each // iteration. Loading @@ -100,7 +102,7 @@ int main() // Set initial guess. Eigen::VectorXd initialGuess(2); initialGuess << 2, 2; initialGuess << -2.7, 2.2; // Start the optimization auto result = optimizer.minimize(initialGuess); Loading examples/CMakeLists.txt +1 −0 Original line number Diff line number Diff line Loading @@ -4,3 +4,4 @@ # Created On: 13 Jul 2019 add_executable(paraboloid "paraboloid.cpp") add_executable(ackley "ackley.cpp") examples/ackley.cpp 0 → 100644 +79 −0 Original line number Diff line number Diff line #include <gdcpp.h> struct Ackley { static double pi() { return 3.141592653589; } Ackley() { } double operator()(const Eigen::VectorXd &xval, Eigen::VectorXd &) const { assert(xval.size() == 2); double x = xval(0); double y = xval(1); // Calculate ackley function, but no gradient. Let gradien be estimated // numerically. return -20.0 * std::exp(-0.2 * std::sqrt(0.5 * (x * x + y * y))) - std::exp(0.5 * (std::cos(2 * pi() * x) + std::cos(2 * pi() * y))) + std::exp(1) + 20.0; } }; int main() { // Create optimizer object with Ackley functor as objective. // // You can specify a StepSize functor as template parameter. // There are ConstantStepSize, LimitedChangeStep, BarzilaiBorweinStep and // WolfeLineSearch available. (Default is BarzilaiBorweinStep) // // You can additionally specify a Callback functor as template parameter. // // You can additionally specify a FiniteDifferences functor as template // parameter. There are Forward-, Backward- and CentralDifferences // available. (Default is CentralDifferences) gdc::GradientDescent<double, Ackley, gdc::WolfeLineSearch<double, Ackley>> optimizer; // Set number of iterations as stop criterion. // Set it to 0 or negative for infinite iterations (default is 0). optimizer.setMaxIterations(200); // Set the minimum length of the gradient. // The optimizer stops minimizing if the gradient length falls below this // value (default is 1e-9). optimizer.setMinGradientLength(1e-6); // Set the minimum length of the step. // The optimizer stops minimizing if the step length falls below this // value (default is 1e-9). optimizer.setMinStepLength(1e-6); // Set the momentum rate used for the step calculation (default is 0.0). // Defines how much momentum is kept from previous iterations. optimizer.setMomentum(0.4); // Turn verbosity on, so the optimizer prints status updates after each // iteration. optimizer.setVerbose(true); // Set initial guess. Eigen::VectorXd initialGuess(2); initialGuess << -2.7, 2.2; // Start the optimization auto result = optimizer.minimize(initialGuess); std::cout << "Done! Converged: " << (result.converged ? "true" : "false") << " Iterations: " << result.iterations << std::endl; // do something with final function value std::cout << "Final fval: " << result.fval << std::endl; // do something with final x-value std::cout << "Final xval: " << result.xval.transpose() << std::endl; return 0; } include/gdcpp.h +1 −1 Original line number Diff line number Diff line Loading @@ -489,7 +489,7 @@ namespace gdc Scalar fval = evaluateObjective(xval, gradient); Scalar gradientLen = gradient.norm(); Scalar stepSize = stepSize_(xval, fval, gradient); Vector step = stepSize * gradient; Vector step = (1 - momentum_) * stepSize * gradient; Scalar stepLen = step.norm(); Index iterations = 0; Loading Loading
README.md +22 −20 Original line number Diff line number Diff line Loading @@ -41,25 +41,30 @@ There are three steps to use gradient-descent-cpp: ```cpp #include <gdcpp.h> // Implement an objective functor. struct Paraboloid struct Ackley { double operator()(const Eigen::VectorXd &xval, Eigen::VectorXd &gradient) static double pi() { return 3.141592653589; } Ackley() { } double operator()(const Eigen::VectorXd &xval, Eigen::VectorXd &) const { // compute gradient explicitly // if gradient calculation is omitted, then the optimizer uses // finite differences to approximate the gradient numerically gradient.resize(2); gradient(0) = 2 * xval(0); gradient(1) = 2 * xval(1); return xval(0) * xval(0) + xval(1) * xval(1); assert(xval.size() == 2); double x = xval(0); double y = xval(1); // Calculate ackley function, but no gradient. Let gradien be estimated // numerically. return -20.0 * std::exp(-0.2 * std::sqrt(0.5 * (x * x + y * y))) - std::exp(0.5 * (std::cos(2 * pi() * x) + std::cos(2 * pi() * y))) + std::exp(1) + 20.0; } }; int main() { // Create optimizer object with Paraboloid functor as objective. // Create optimizer object with Ackley functor as objective. // // You can specify a StepSize functor as template parameter. // There are ConstantStepSize, LimitedChangeStep, BarzilaiBorweinStep and Loading @@ -70,12 +75,12 @@ int main() // You can additionally specify a FiniteDifferences functor as template // parameter. There are Forward-, Backward- and CentralDifferences // available. (Default is CentralDifferences) gdc::GradientDescent<double, Paraboloid, gdc::ConstantStepSize<double, Paraboloid>> optimizer; gdc::GradientDescent<double, Ackley, gdc::WolfeLineSearch<double, Ackley>> optimizer; // Set number of iterations as stop criterion. // Set it to 0 or negative for infinite iterations (default is 0). optimizer.setMaxIterations(100); optimizer.setMaxIterations(200); // Set the minimum length of the gradient. // The optimizer stops minimizing if the gradient length falls below this Loading @@ -87,12 +92,9 @@ int main() // value (default is 1e-9). optimizer.setMinStepLength(1e-6); // Set the the parametrized StepSize functor used for the step calculation. optimizer.setStepSize(gdc::ConstantStepSize<double, Paraboloid>(0.8)); // Set the momentum rate used for the step calculation (default is 0.0). // Defines how much momentum is kept from previous iterations. optimizer.setMomentum(0.1); optimizer.setMomentum(0.4); // Turn verbosity on, so the optimizer prints status updates after each // iteration. Loading @@ -100,7 +102,7 @@ int main() // Set initial guess. Eigen::VectorXd initialGuess(2); initialGuess << 2, 2; initialGuess << -2.7, 2.2; // Start the optimization auto result = optimizer.minimize(initialGuess); Loading
examples/CMakeLists.txt +1 −0 Original line number Diff line number Diff line Loading @@ -4,3 +4,4 @@ # Created On: 13 Jul 2019 add_executable(paraboloid "paraboloid.cpp") add_executable(ackley "ackley.cpp")
examples/ackley.cpp 0 → 100644 +79 −0 Original line number Diff line number Diff line #include <gdcpp.h> struct Ackley { static double pi() { return 3.141592653589; } Ackley() { } double operator()(const Eigen::VectorXd &xval, Eigen::VectorXd &) const { assert(xval.size() == 2); double x = xval(0); double y = xval(1); // Calculate ackley function, but no gradient. Let gradien be estimated // numerically. return -20.0 * std::exp(-0.2 * std::sqrt(0.5 * (x * x + y * y))) - std::exp(0.5 * (std::cos(2 * pi() * x) + std::cos(2 * pi() * y))) + std::exp(1) + 20.0; } }; int main() { // Create optimizer object with Ackley functor as objective. // // You can specify a StepSize functor as template parameter. // There are ConstantStepSize, LimitedChangeStep, BarzilaiBorweinStep and // WolfeLineSearch available. (Default is BarzilaiBorweinStep) // // You can additionally specify a Callback functor as template parameter. // // You can additionally specify a FiniteDifferences functor as template // parameter. There are Forward-, Backward- and CentralDifferences // available. (Default is CentralDifferences) gdc::GradientDescent<double, Ackley, gdc::WolfeLineSearch<double, Ackley>> optimizer; // Set number of iterations as stop criterion. // Set it to 0 or negative for infinite iterations (default is 0). optimizer.setMaxIterations(200); // Set the minimum length of the gradient. // The optimizer stops minimizing if the gradient length falls below this // value (default is 1e-9). optimizer.setMinGradientLength(1e-6); // Set the minimum length of the step. // The optimizer stops minimizing if the step length falls below this // value (default is 1e-9). optimizer.setMinStepLength(1e-6); // Set the momentum rate used for the step calculation (default is 0.0). // Defines how much momentum is kept from previous iterations. optimizer.setMomentum(0.4); // Turn verbosity on, so the optimizer prints status updates after each // iteration. optimizer.setVerbose(true); // Set initial guess. Eigen::VectorXd initialGuess(2); initialGuess << -2.7, 2.2; // Start the optimization auto result = optimizer.minimize(initialGuess); std::cout << "Done! Converged: " << (result.converged ? "true" : "false") << " Iterations: " << result.iterations << std::endl; // do something with final function value std::cout << "Final fval: " << result.fval << std::endl; // do something with final x-value std::cout << "Final xval: " << result.xval.transpose() << std::endl; return 0; }
include/gdcpp.h +1 −1 Original line number Diff line number Diff line Loading @@ -489,7 +489,7 @@ namespace gdc Scalar fval = evaluateObjective(xval, gradient); Scalar gradientLen = gradient.norm(); Scalar stepSize = stepSize_(xval, fval, gradient); Vector step = stepSize * gradient; Vector step = (1 - momentum_) * stepSize * gradient; Scalar stepLen = step.norm(); Index iterations = 0; Loading