10 #include <string_view>
12 using namespace std::string_literals;
17 throw std::runtime_error(s +
" (" + std::to_string(code) +
")");
27 so_handle = dlopen(so_fname, RTLD_LAZY);
29 throw std::runtime_error(
"Failed to open "s + so_fname);
33 auto fptr_open = dlfun<decltype(FORTRAN_open)>(
"fortran_open_");
34 fptr_open(&funit, outsdif_fname, &ierr);
36 throw std::runtime_error(
"Failed to open "s + outsdif_fname);
40 auto fptr_cdimen = dlfun<decltype(CUTEST_cdimen)>(
"cutest_cdimen_");
41 fptr_cdimen(&status, &funit, &nvar, &ncon);
42 throw_if_error(
"Failed to call cutest_cdimen", status);
60 dlfun<decltype(CUTEST_csetup)>(
"cutest_cint_csetup_");
61 fptr_csetup(&status, &funit, &iout, &io_buffer, &nvar, &ncon,
62 x.data(), x_l.data(), x_u.data(),
y.data(), c_l.data(),
63 c_u.data(), (logical *)equatn.data(),
64 (logical *)linear.data(), &e_order, &l_order, &v_order);
65 throw_if_error(
"Failed to call cutest_csetup", status);
69 auto fptr_usetup = dlfun<decltype(CUTEST_usetup)>(
"cutest_usetup_");
70 fptr_usetup(&status, &funit, &iout, &io_buffer, &nvar,
x.data(),
71 x_l.data(), x_u.data());
72 throw_if_error(
"Failed to call cutest_usetup", status);
75 work.resize(std::max(nvar, ncon));
78 ? dlfun<void>(
"cutest_cfn_")
79 : dlfun<void>(
"cutest_ufn_");
80 eval_obj_grad_p = ncon > 0
81 ? dlfun<void>(
"cutest_cint_cofg_")
82 : dlfun<void>(
"cutest_ugr_");
83 eval_constr_p = ncon > 0
86 eval_constr_grad_prod_p = ncon > 0
87 ? dlfun<void>(
"cutest_cint_cjprod_")
89 eval_constr_i_grad_p = ncon > 0
90 ? dlfun<void>(
"cutest_cint_ccifg_")
92 eval_lagr_hess_prod_p = ncon > 0
93 ? dlfun<void>(
"cutest_cint_chprod_")
94 : dlfun<void>(
"cutest_cint_uhprod_");
95 eval_lagr_hess_p = ncon > 0
96 ? dlfun<void>(
"cutest_cdh_")
97 : dlfun<void>(
"cutest_udh_");
101 static inline constexpr
auto call_as(
void *funp) {
106 assert(
x.size() == nvar);
110 call_as<decltype(CUTEST_cfn)>(eval_obj_p)(&status, &nvar, &ncon,
111 x.data(), &
f, work.data());
112 throw_if_error(
"Failed to call cutest_cfn", status);
117 assert(
x.size() == nvar);
121 call_as<decltype(CUTEST_ufn)>(eval_obj_p)(&status, &nvar,
x.data(), &
f);
122 throw_if_error(
"Failed to call cutest_ufn", status);
127 assert(
x.size() == nvar);
128 assert(
grad_f.size() == nvar);
132 call_as<decltype(CUTEST_cofg)>(eval_obj_grad_p)(
133 &status, &nvar,
x.data(), work.data(),
grad_f.data(), &grad);
134 throw_if_error(
"Failed to call cutest_cfn", status);
138 assert(
x.size() == nvar);
139 assert(
grad_f.size() == nvar);
142 call_as<decltype(CUTEST_ugr)>(eval_obj_grad_p)(&status, &nvar,
x.data(),
144 throw_if_error(
"Failed to call cutest_ugr", status);
148 assert(
x.size() == nvar);
149 assert(
g.size() == ncon);
153 call_as<decltype(CUTEST_cfn)>(eval_constr_p)(
154 &status, &nvar, &ncon,
x.data(), work.data(),
g.data());
155 throw_if_error(
"Failed to call cutest_cfn", status);
160 assert(
x.size() == nvar);
161 assert(
v.size() == ncon);
162 assert(grad_g_v.size() == nvar);
168 logical gotJ =
false;
169 logical jtrans =
true;
170 call_as<decltype(CUTEST_cjprod)>(eval_constr_grad_prod_p)(
171 &status, &nvar, &ncon, &gotJ, &jtrans,
x.data(),
v.data(), &ncon,
172 grad_g_v.data(), &nvar);
173 throw_if_error(
"Failed to call cutest_cjprod", status);
178 assert(
x.size() == nvar);
179 assert(
grad_gi.size() == nvar);
185 integer icon = i + 1;
187 assert(icon <= ncon);
190 call_as<decltype(CUTEST_ccifg)>(eval_constr_i_grad_p)(
191 &status, &nvar, &icon,
x.data(), &ci,
grad_gi.data(), &grad);
192 throw_if_error(
"Failed to call cutest_ccifg", status);
197 assert(
x.size() == nvar);
198 assert(
y.size() == ncon);
199 assert(
v.rows() == nvar);
200 assert(Hv.rows() == nvar);
202 logical gotH =
false;
204 call_as<decltype(CUTEST_uhprod)>(eval_lagr_hess_prod_p)(
205 &status, &nvar, &gotH,
x.data(),
v.data(), Hv.data());
206 throw_if_error(
"Failed to call cutest_uhprod", status);
208 call_as<decltype(CUTEST_chprod)>(eval_lagr_hess_prod_p)(
209 &status, &nvar, &ncon, &gotH,
x.data(),
y.data(),
212 throw_if_error(
"Failed to call cutest_chprod", status);
217 assert(
x.size() == nvar);
218 assert(
y.size() == ncon);
219 assert(
H.rows() >= nvar);
220 assert(
H.cols() >= nvar);
222 integer ldH =
H.rows();
224 call_as<decltype(CUTEST_udh)>(eval_lagr_hess_p)(
225 &status, &nvar,
x.data(), &ldH,
H.data());
226 throw_if_error(
"Failed to call cutest_udh", status);
228 call_as<decltype(CUTEST_cdh)>(eval_lagr_hess_p)(
229 &status, &nvar, &ncon,
x.data(),
y.data(), &ldH,
H.data());
230 throw_if_error(
"Failed to call cutest_cdh", status);
235 return std::count_if(x_l.data(), x_l.data() + nvar,
237 std::count_if(x_u.data(), x_u.data() + nvar,
245 dlfun<decltype(CUTEST_probname)>(
"cutest_probname_")(&status,
247 throw_if_error(
"Failed to call cutest_probname", status);
248 auto nspace = std::find_if(
name.rbegin(),
name.rend(),
249 [](
char c) { return c !=
' '; });
257 ncon > 0 ? dlfun<decltype(CUTEST_creport)>(
"cutest_creport_")
258 : dlfun<decltype(CUTEST_ureport)>(
"cutest_ureport_");
259 fptr_report(&status, calls, time);
267 auto fptr_cterminate =
268 dlfun<decltype(CUTEST_cterminate)>(
"cutest_cterminate_");
269 fptr_cterminate(&status);
270 throw_if_error(
"Failed to call cutest_cterminate", status);
273 auto fptr_uterminate =
274 dlfun<decltype(CUTEST_uterminate)>(
"cutest_uterminate_");
275 fptr_uterminate(&status);
276 throw_if_error(
"Failed to call cutest_uterminate", status);
281 auto fptr_close = dlfun<decltype(FORTRAN_close)>(
"fortran_close_");
282 fptr_close(&funit, &ierr);
283 throw_if_error(
"Failed to close OUTSDIF.d file", ierr);
293 auto res = (T *)dlsym(so_handle,
name);
294 if (
const char *error = dlerror(); error)
295 throw std::runtime_error(error);
299 void *so_handle =
nullptr;
303 integer io_buffer = 11;
319 void *eval_obj_p =
nullptr;
320 void *eval_obj_grad_p =
nullptr;
321 void *eval_constr_p =
nullptr;
322 void *eval_constr_grad_prod_p =
nullptr;
323 void *eval_constr_i_grad_p =
nullptr;
324 void *eval_lagr_hess_prod_p =
nullptr;
325 void *eval_lagr_hess_p =
nullptr;
329 implementation = std::make_unique<CUTEstLoader>(so_fname, outsdif_fname);
330 auto *
l = implementation.get();
331 name =
l->get_name();
332 number_box_constraints =
l->count_box_constraints();
335 problem.C.lowerbound = std::move(
l->x_l);
336 problem.C.upperbound = std::move(
l->x_u);
337 problem.D.lowerbound = std::move(
l->c_l);
338 problem.D.upperbound = std::move(
l->c_u);
339 using namespace std::placeholders;
358 x0 = std::move(
l->x);
359 y0 = std::move(
l->y);
363 const std::string &outsdif_fname)
374 using stat_t = decltype(r.
status);
379 r.
calls.objective = calls[0];
380 r.
calls.objective_grad = calls[1];
381 r.
calls.objective_hess = calls[2];
382 r.
calls.hessian_times_vector = calls[3];
394 case Status::Success:
return "Success";
395 case Status::AllocationError:
return "AllocationError";
396 case Status::ArrayBoundError:
return "ArrayBoundError";
397 case Status::EvaluationError:
return "EvaluationError";
399 throw std::out_of_range(
400 "invalid value for pa::CUTEstProblem::Report::Status");
408 os <<
"CUTEst problem: " << r.
name <<
"\r\n\n"
409 <<
"Number of variables: " << r.
nvar <<
"\r\n"
410 <<
"Number of constraints: " << r.
ncon <<
"\r\n\n"
411 <<
"Status: " << r.
status <<
" (" << +r.
status <<
")\r\n\n"
412 <<
"Objective function evaluations: " << r.
calls.objective
414 <<
"Objective function gradient evaluations: "
415 << r.
calls.objective_grad <<
"\r\n"
416 <<
"Objective function Hessian evaluations: "
417 << r.
calls.objective_hess <<
"\r\n"
418 <<
"Hessian times vector products: "
419 << r.
calls.objective_hess <<
"\r\n\n";
421 os <<
"Constraint function evaluations: "
422 << r.
calls.constraints <<
"\r\n"
423 <<
"Constraint function gradients evaluations: "
424 << r.
calls.constraints_grad <<
"\r\n"
425 <<
"Constraint function Hessian evaluations: "
426 << r.
calls.constraints_hess <<
"\r\n\n";
428 return os <<
"Setup time: " << r.
time_setup <<
"s\r\n"
429 <<
"Time since setup: " << r.
time <<
"s";