117int main(
int argc,
const char *argv[])
try {
119 SetConsoleOutputCP(CP_UTF8);
128 std::span args{argv,
static_cast<size_t>(argc)};
129 Options opts{argc - 2, argv + 2};
132 std::ostream &os = std::cout;
138 os <<
"Loading problem " << prob_path << std::endl;
139 auto problem =
load_problem(prob_type, prob_path.parent_path(),
140 prob_path.filename(), opts);
141 os <<
"Loaded problem " << problem.path.stem().string() <<
" from "
142 << problem.path <<
"\nnvar: " << problem.problem.get_num_variables()
143 <<
"\nncon: " << problem.problem.get_num_constraints()
144 <<
"\nProvided functions:\n";
149 auto has_opt = [&opts](std::string_view o) {
150 auto o_it = std::ranges::find(opts.
options(), o);
151 if (o_it == opts.
options().end())
153 auto index =
static_cast<size_t>(o_it - opts.
options().begin());
154 ++opts.
used()[index];
158 .print_full = has_opt(
"--full-print"),
159 .hessians = !has_opt(
"--no-hessians"),
160 .scale_perturbations = 1e-2,
165 auto seed =
static_cast<unsigned int>(std::time(
nullptr));
170 auto used = opts.
used();
171 auto unused_opt = std::ranges::find(used, 0);
172 auto unused_idx =
static_cast<size_t>(unused_opt - used.begin());
173 if (unused_opt != used.end())
174 throw std::invalid_argument(
"Unused option: " +
175 std::string(opts.
options()[unused_idx]));
180}
catch (std::exception &e) {
181 std::cerr <<
"Error: " << guanaqo::demangled_typename(
typeid(e)) <<
":\n "
182 << e.what() << std::endl;
277 auto &te_problem = lproblem.
problem;
282 auto n = te_problem.get_num_variables(),
283 m = te_problem.get_num_constraints();
285 std::srand(
static_cast<unsigned int>(std::time(
nullptr)));
286 vec Σ = 1.5 * vec::Random(m).array() + 2;
288 vec x = x0 + sc * vec::Random(n);
289 vec v = 5e-6 * sc * vec::Random(n);
293 auto print_compare = [&log, &opts](
const auto &other,
const auto &ref) {
295 (ref - other).reshaped().template lpNorm<Eigen::Infinity>();
297 abs_err / ref.reshaped().template lpNorm<Eigen::Infinity>();
298 log <<
" abs error = " << alpaqa::float_to_str(abs_err) <<
'\n';
299 log <<
" rel error = " << alpaqa::float_to_str(rel_err) <<
'\n';
305 auto print_compare_scal = [&log, &opts](
const auto &fd,
const auto &ad) {
306 auto abs_err = std::abs(fd - ad);
307 auto rel_err = abs_err / std::abs(fd);
308 log <<
" abs error = " << alpaqa::float_to_str(abs_err) <<
'\n';
309 log <<
" rel error = " << alpaqa::float_to_str(rel_err) <<
'\n';
311 log <<
" (1) = " << alpaqa::float_to_str(fd) <<
'\n';
312 log <<
" (2) = " << alpaqa::float_to_str(ad) <<
'\n' << std::endl;
316 auto f = [&](crvec x) {
return te_problem.eval_objective(x); };
317 log <<
"Gradient verification: ∇f(x) (grad_f compared to finite "
318 "differences of f)\n";
321 te_problem.eval_objective_gradient(x, grad_f);
322 print_compare(grad_f, fd_grad_f);
324 if (te_problem.provides_eval_objective_and_gradient()) {
325 log <<
"Gradient verification: ∇f(x) (f_grad_f compared to grad_f)\n";
327 auto f2 = te_problem.eval_objective_and_gradient(x, f_grad_f);
328 print_compare(f_grad_f, grad_f);
329 log <<
"Function verification: f(x) (f_grad_f compared to f)\n";
330 print_compare_scal(f2, fx);
333 log <<
"Gradient verification: ∇L(x) (grad_L compared to finite "
334 "differences of f + yᵀg)\n";
335 auto L = [&](crvec x) {
336 te_problem.eval_constraints(x, gx);
337 return te_problem.eval_objective(x) + gx.dot(y);
341 te_problem.eval_lagrangian_gradient(x, y, grad_L, wn);
342 print_compare(grad_L, fd_grad_L);
344 log <<
"Gradient verification: ∇ψ(x) (grad_ψ compared to finite "
345 "differences of ψ)\n";
346 auto ψ = [&](crvec x) {
347 return te_problem.eval_augmented_lagrangian(x, y, Σ, wm);
351 te_problem.eval_augmented_lagrangian_gradient(x, y, Σ, grad_ψ, wn, wm);
352 print_compare(grad_ψ, fd_grad_ψ);
354 log <<
"Gradient verification: ∇ψ(x) (grad_ψ compared to reference "
355 "implementation based on g, ∇f, ∇g)\n";
356 vec grad_ψ_default(n);
358 te_problem, x, y, Σ, grad_ψ_default, wn, wm);
359 print_compare(grad_ψ, grad_ψ_default);
360 log <<
"Function verification: ψ(x) (ψ compared to reference "
361 "implementation based on f, g)\n";
362 print_compare_scal(ψx, ψ_default);
364 if (te_problem.provides_eval_augmented_lagrangian_and_gradient()) {
365 log <<
"Gradient verification: ∇ψ(x) (grad_ψ compared to ψ_grad_ψ)\n";
367 real_t ψ2 = te_problem.eval_augmented_lagrangian_and_gradient(
368 x, y, Σ, ψ_grad_ψ, wn, wm);
369 print_compare(grad_ψ, ψ_grad_ψ);
370 log <<
"Function verification: ψ(x) (ψ compared to ψ_grad_ψ)\n";
371 print_compare_scal(ψx, ψ2);
374 if (te_problem.provides_eval_lagrangian_hessian_product()) {
375 log <<
"Hessian product verification: ∇²L(x) (hess_L_prod compared to "
376 "finite differences of grad_L)\n";
379 te_problem.eval_lagrangian_gradient(xv, y, grad_Lv, wn);
380 vec fd_hess_Lv = grad_Lv - grad_L;
382 te_problem.eval_lagrangian_hessian_product(x, y, 1, v, hess_Lv);
383 print_compare(hess_Lv, fd_hess_Lv);
386 if (te_problem.provides_eval_augmented_lagrangian_hessian_product()) {
387 log <<
"Hessian product verification: ∇²ψ(x) (hess_ψ_prod compared to "
388 "finite differences of grad_ψ)\n";
391 te_problem.eval_augmented_lagrangian_gradient(xv, y, Σ, grad_ψv, wn,
393 vec fd_hess_ψv = grad_ψv - grad_ψ;
395 te_problem.eval_augmented_lagrangian_hessian_product(x, y, Σ, 1, v,
397 print_compare(hess_ψv, fd_hess_ψv);
400 if (opts.
hessians && te_problem.provides_eval_lagrangian_hessian()) {
401 log <<
"Hessian verification: ∇²L(x) (hess_L compared to finite "
402 "differences of grad_L)\n";
403 auto sp = te_problem.get_lagrangian_hessian_sparsity();
405 auto eval_h = [&](rvec v) {
406 te_problem.eval_lagrangian_hessian(x, y, 1., v);
408 auto hess_L = cvt.
eval(eval_h);
410 [&](crvec x, rvec g) {
411 te_problem.eval_lagrangian_gradient(x, y, g, wn);
414 print_compare(hess_L, fd_hess_L);
418 te_problem.provides_eval_augmented_lagrangian_hessian()) {
419 log <<
"Hessian verification: ∇²ψ(x) (hess_ψ compared to finite "
420 "differences of grad_ψ)\\n";
421 auto sp = te_problem.get_augmented_lagrangian_hessian_sparsity();
423 auto eval_h = [&](rvec v) {
424 te_problem.eval_augmented_lagrangian_hessian(x, y, Σ, 1., v);
426 auto hess_ψ = cvt.
eval(eval_h);
428 [&](crvec x, rvec g) {
429 te_problem.eval_augmented_lagrangian_gradient(x, y, Σ, g, wn,
433 print_compare(hess_ψ, fd_hess_ψ);