alpaqa 1.0.0a16
Nonconvex constrained optimization
Loading...
Searching...
No Matches
C++/FortranProblem/main.cpp

This example shows how to define optimization problems using Fortran routines.

This example shows how to define optimization problems using Fortran routines.

It solves a simple quadratic program of the form:

\[ \begin{aligned} & \underset{x}{\text{minimize}} && \tfrac12 \tp x Q x \\ & \text{subject to} && Ax \le b \\ \end{aligned} \]

Problem definition in Fortran

1module problem
2
3 use, intrinsic::iso_c_binding, only: c_double, c_ptrdiff_t
4 implicit none (type,external)
5
6 integer(c_ptrdiff_t), parameter :: n = 2
7 integer(c_ptrdiff_t), parameter :: m = 1
8 real(c_double) :: Q(n, n)
9 data q /3, -1, -1, 3/
10 real(c_double) :: A(m, n)
11 data a /2, 1/
12
13contains
14
15 ! Evaluate the cost, f(x)
16 pure real(c_double) function problem_eval_f(x) bind(C)
17 real(c_double), intent(in) :: x(n)
18
19 problem_eval_f = 0.5_c_double * dot_product(x, matmul(q, x))
20 end function
21
22 ! Evaluate the gradient of the cost, ∇f(x)
23 pure subroutine problem_eval_grad_f(x, grad_fx) bind(C)
24 real(c_double), intent(in) :: x(n)
25 real(c_double), intent(out) :: grad_fx(n)
26
27 grad_fx = matmul(q, x)
28 end subroutine
29
30 ! Evaluate the constraints, g(x)
31 pure subroutine problem_eval_g(x, gx) bind(C)
32 real(c_double), intent(in) :: x(n)
33 real(c_double), intent(out) :: gx(m)
34
35 gx = matmul(a, x)
36 end subroutine
37
38 ! Evaluate the matrix-vector product of the gradient of the constraints and
39 ! the vector y, ∇g(x) y
40 pure subroutine problem_eval_grad_g_prod(x, y, grad_gxy) bind(C)
41 real(c_double), intent(in) :: x(n)
42 real(c_double), intent(in) :: y(m)
43 real(c_double), intent(out) :: grad_gxy(n)
44
45 grad_gxy = matmul(transpose(a), y)
46 end subroutine
47
48 ! Get the number of variables of the problem
49 pure integer(c_ptrdiff_t) function problem_get_num_vars() bind(C)
50 problem_get_num_vars = n
51 end function
52
53 ! Get the number of constraints of the problem
54 pure integer(c_ptrdiff_t) function problem_get_num_constr() bind(C)
55 problem_get_num_constr = m
56 end function
57
58end module

Problem solution using alpaqa

4
5#include <iostream>
6
7// Double precision, same as in Fortran
9
10// External Fortran routines
11extern "C" {
12ptrdiff_t problem_get_num_vars(void);
13ptrdiff_t problem_get_num_constr(void);
14double problem_eval_f(const double *);
15void problem_eval_grad_f(const double *, double *);
16void problem_eval_g(const double *, double *);
17void problem_eval_grad_g_prod(const double *, const double *, double *);
18}
19
20// Problem specification by inheriting from alpaqa::Problem
21struct FortranProblem : alpaqa::BoxConstrProblem<config_t> {
22 using alpaqa::BoxConstrProblem<config_t>::BoxConstrProblem;
23
24 real_t eval_f(crvec x) const { return problem_eval_f(x.data()); }
25 void eval_grad_f(crvec x, rvec fx) const {
26 problem_eval_grad_f(x.data(), fx.data());
27 }
28 void eval_g(crvec x, rvec gx) const { problem_eval_g(x.data(), gx.data()); }
29 void eval_grad_g_prod(crvec x, crvec y, rvec grad_gxy) const {
30 problem_eval_grad_g_prod(x.data(), y.data(), grad_gxy.data());
31 }
32};
33
34int main() {
35 // Instantiate a problem
36 FortranProblem problem{problem_get_num_vars(), problem_get_num_constr()};
37 // Wrap the problem to count the function evaluations
38 auto counted_problem = alpaqa::problem_with_counters_ref(problem);
39
40 // Specify the bounds
41 vec b = vec::Constant(problem.m, -1);
42 problem.C.lowerbound = vec::Constant(problem.n, -alpaqa::inf<config_t>);
43 problem.C.upperbound = vec::Constant(problem.n, +alpaqa::inf<config_t>);
44 problem.D.lowerbound = vec::Constant(problem.m, -alpaqa::inf<config_t>);
45 problem.D.upperbound = b;
46
47 // Define the solvers to use
49 using InnerSolver = alpaqa::PANOCSolver<Direction>;
50 using OuterSolver = alpaqa::ALMSolver<InnerSolver>;
51
52 // Settings for the outer augmented Lagrangian method
53 OuterSolver::Params almparam;
54 almparam.tolerance = 1e-8; // tolerance
55 almparam.dual_tolerance = 1e-8;
56 almparam.penalty_update_factor = 10; // penalty update factor
57 almparam.max_iter = 20;
58 almparam.print_interval = 1;
59
60 // Settings for the inner PANOC solver
61 InnerSolver::Params panocparam;
62 panocparam.max_iter = 500;
63 panocparam.print_interval = 10;
64 // Settings for the L-BFGS algorithm used by PANOC
65 Direction::AcceleratorParams lbfgsparam;
66 lbfgsparam.memory = 2;
67
68 // Create an ALM solver using PANOC as inner solver
69 OuterSolver solver{
70 almparam, // params for outer solver
71 {panocparam, lbfgsparam}, // inner solver
72 };
73
74 // Initial guess
75 vec x(2);
76 x << 2, 2; // decision variables
77 vec y(1);
78 y << 1; // Lagrange multipliers
79
80 // Solve the problem
81 auto stats = solver(counted_problem, x, y);
82 // y and x have been overwritten by the solution
83
84 // Print the results
85 std::cout << '\n' << *counted_problem.evaluations << '\n';
86 std::cout << "status: " << stats.status << '\n'
87 << "solver: " << solver.get_name() << '\n'
88 << "f = " << problem.eval_f(x) << '\n'
89 << "inner iterations: " << stats.inner.iterations << '\n'
90 << "outer iterations: " << stats.outer_iterations << '\n'
91 << "ε = " << stats.ε << '\n'
92 << "δ = " << stats.δ << '\n'
93 << "elapsed time: "
94 << std::chrono::duration<double>{stats.elapsed_time}.count()
95 << " s" << '\n'
96 << "x = " << x.transpose() << '\n'
97 << "y = " << y.transpose() << '\n'
98 << "avg τ = " << (stats.inner.sum_τ / stats.inner.count_τ) << '\n'
99 << "L-BFGS rejected = " << stats.inner.lbfgs_rejected << '\n'
100 << "L-BFGS failures = " << stats.inner.lbfgs_failures << '\n'
101 << "Line search failures = " << stats.inner.linesearch_failures
102 << '\n'
103 << std::endl;
104}
int main(int argc, const char *argv[])
Augmented Lagrangian Method solver.
Definition alm.hpp:69
Implements common problem functions for minimization problems with box constraints.
PANOC solver for ALM.
Definition panoc.hpp:139
#define USING_ALPAQA_CONFIG(Conf)
Definition config.hpp:63
auto problem_with_counters_ref(Problem &p)
Wraps the given problem into a ProblemWithCounters and keeps track of how many times each function is...
constexpr const auto inf
Definition config.hpp:98
typename Conf::vec vec
Definition config.hpp:74
Double-precision double configuration.
Definition config.hpp:160