19using namespace std::string_literals;
 
   22void throw_error(std::string_view s, 
int code) {
 
   26void throw_if_error(std::string_view s, 
int code) {
 
   30void log_if_error(std::string_view s, 
int code) {
 
   32        std::cerr << s << 
" (" << code << 
")\n";
 
   35auto checked(F &&func, std::string_view msg) {
 
   36    return [msg, func{std::forward<F>(func)}]<
class... Args>(
 
   37               Args &&...args) 
mutable {
 
   39        std::forward<F>(func)(&status, std::forward<Args>(args)...);
 
   40        throw_if_error(msg, status);
 
   44std::shared_ptr<void> load_lib(
const char *so_filename) {
 
   47    void *h = ::dlopen(so_filename, RTLD_LOCAL | RTLD_NOW);
 
   48    if (
auto *err = ::dlerror())
 
   49        throw std::runtime_error(err);
 
   50    return std::shared_ptr<void>{h, &::dlclose};
 
   66                         [func{std::forward<F>(func)}](
void *) { func(); }};
 
   73    auto load() -> F::signature_t * {
 
   77    template <
class F, 
class... Args>
 
   78    decltype(
auto) 
call(Args &&...args) {
 
   79        return load<F>()(std::forward<Args>(args)...);
 
   84        auto fptr_close = load<cutest::fortran_close>();
 
   85        call<cutest::fortran_open>(&
funit, outsdif_fname, &status);
 
   86        throw_if_error(
"Failed to open "s + outsdif_fname, status);
 
   89            fptr_close(&
funit, &status);
 
   90            log_if_error(
"Failed to close OUTSDIF.d file", status);
 
   95        auto fptr_cterminate = load<cutest::cterminate>();
 
   96        return cleanup([fptr_cterminate] {
 
   98            fptr_cterminate(&status);
 
   99            log_if_error(
"Failed to call cutest_cterminate", status);
 
  114        throw_if_error(
"Failed to call cutest_cdimen", status);
 
  152        call<cutest::csetup>(
 
  156            linear.data(), &e_order, &l_order, &v_order);
 
  157        throw_if_error(
"Failed to call cutest_csetup", status);
 
  162            throw std::runtime_error(
 
  163                "Unconstrained CUTEst problems are currently unsupported");
 
  175            .
cfn    = load<cutest::cfn>(),
 
  176            .cofg   = load<cutest::cofg>(),
 
  177            .ccfg   = load<cutest::ccfg>(),
 
  178            .clfg   = load<cutest::clfg>(),
 
  179            .cjprod = load<cutest::cjprod>(),
 
  180            .ccifg  = load<cutest::ccifg>(),
 
  181            .cigr   = load<cutest::cigr>(),
 
  182            .cdimsj = load<cutest::cdimsj>(),
 
  183            .csjp   = load<cutest::csjp>(),
 
  184            .ccfsg  = load<cutest::ccfsg>(),
 
  185            .cdh    = load<cutest::cdh>(),
 
  186            .cdimsh = load<cutest::cdimsh>(),
 
  187            .cshp   = load<cutest::cshp>(),
 
  188            .csh    = load<cutest::csh>(),
 
  189            .chprod = load<cutest::chprod>(),
 
  196        call<cutest::probname>(&status, name.data());
 
  197        throw_if_error(
"Failed to call CUTEST_probname", status);
 
  198        if (
auto last = name.find_last_not_of(
' '); last != name.npos)
 
  199            name.resize(last + 1);
 
  206            call<cutest::creport>(&status, calls, time);
 
  207            throw_if_error(
"Failed to call CUTEST_creport", status);
 
  209            call<cutest::ureport>(&status, calls, time);
 
  210            throw_if_error(
"Failed to call CUTEST_ureport", status);
 
  217        auto res = 
reinterpret_cast<T *
>(::dlsym(
so_handle.get(), name));
 
  218        if (
const char *error = dlerror())
 
  219            throw std::runtime_error(error);
 
  245    impl = std::make_unique<CUTEstLoader>(so_fname, outsdif_fname);
 
  246    resize(
static_cast<length_t>(impl->nvar),
 
  250    impl->setup_problem(x0, y0, C, D);
 
  251    name = impl->get_name();
 
  257CUTEstProblem &CUTEstProblem::operator=(CUTEstProblem &&) noexcept = default;
 
  258CUTEstProblem::~CUTEstProblem()                                    = default;
 
  263    impl->get_report(calls, time);
 
  264    const bool constr = impl->ncon > 0;
 
  267            .
objective            = 
static_cast<unsigned>(calls[0]),
 
  268            .objective_grad       = 
static_cast<unsigned>(calls[1]),
 
  269            .objective_hess       = 
static_cast<unsigned>(calls[2]),
 
  270            .hessian_times_vector = 
static_cast<unsigned>(calls[3]),
 
  271            .constraints      = constr ? 
static_cast<unsigned>(calls[4]) : 0,
 
  272            .constraints_grad = constr ? 
static_cast<unsigned>(calls[5]) : 0,
 
  273            .constraints_hess = constr ? 
static_cast<unsigned>(calls[6]) : 0,
 
  275        .time_setup = time[0],
 
  281    assert(x.size() == 
static_cast<length_t>(impl->nvar));
 
  284    checked(impl->funcs.cofg, 
"eval_f: CUTEST_cofg")(&impl->nvar, x.data(), &f,
 
  290    assert(grad_fx.size() == 
static_cast<length_t>(
impl->nvar));
 
  293    checked(
impl->funcs.cofg, 
"eval_grad_f: CUTEST_cofg")(
 
  294        &
impl->nvar, x.data(), &f, grad_fx.data(), &grad);
 
  301    checked(
impl->funcs.ccfg, 
"eval_g: CUTEST_ccfg")(
 
  302        &
impl->nvar, &
impl->ncon, x.data(), gx.data(), &jtrans, &zero, &zero,
 
  308    assert(grad_gxy.size() == 
static_cast<length_t>(
impl->nvar));
 
  312    checked(
impl->funcs.cjprod, 
"eval_grad_g_prod: CUTEST_cjprod")(
 
  313        &
impl->nvar, &
impl->ncon, &gotj, &jtrans, x.data(), y.data(), &lvector,
 
  314        grad_gxy.data(), &lresult);
 
  319                               rvec J_values)
 const {
 
  321    if (J_values.size() > 0) {
 
  329            assert(outer_ptr.size() == 
static_cast<length_t>(
impl->nvar + 1));
 
  332            checked(
impl->funcs.ccfsg, 
"eval_jac_g: CUTEST_ccfsg")(
 
  335            auto t0  = std::chrono::steady_clock::now();
 
  337            auto t1  = std::chrono::steady_clock::now();
 
  338            std::cout << 
"Permutation of J took: " 
  339                      << std::chrono::duration<double>{t1 - t0}.count() * 1e6
 
  344            assert(J_values.size() == 
static_cast<length_t>(
impl->nvar) *
 
  347            checked(
impl->funcs.ccfg, 
"eval_jac_g: CUTEST_ccfg")(
 
  348                &
impl->nvar, &
impl->ncon, x.data(), 
impl->work.data(), &jtrans,
 
  349                &
impl->ncon, &
impl->nvar, J_values.data(), &grad);
 
  356        assert(outer_ptr.size() == 
static_cast<length_t>(
impl->nvar + 1));
 
  358        checked(
impl->funcs.csjp, 
"eval_jac_g: CUTEST_csjp")(
 
  362        util::convert_triplets_to_ccs<config_t>(
J_row, 
J_col, inner_idx,
 
  370        checked(
impl->funcs.cdimsj,
 
  371                "get_jac_g_num_nonzeros: CUTEST_cdimsj")(&
nnz_J);
 
  383    assert(grad_gi.size() == 
static_cast<length_t>(
impl->nvar));
 
  385    checked(
impl->funcs.cigr, 
"eval_grad_gi: CUTEST_cigr")(
 
  386        &
impl->nvar, &iprob, x.data(), grad_gi.data());
 
  394    const auto *mult = y.data();
 
  397        mult       = 
impl->work.data();
 
  400    checked(
impl->funcs.chprod, 
"eval_hess_L_prod: CUTEST_chprod")(
 
  401        &
impl->nvar, &
impl->ncon, &goth, x.data(), mult,
 
  402        const_cast<real_t *
>(v.data()), Hv.data());
 
  413    auto &&ζ = 
impl->work.topRows(
impl->ncon);
 
  414    auto &&ŷ = 
impl->work2.topRows(
impl->ncon);
 
  417    ζ += Σ.asDiagonal().inverse() * y;
 
  421    ŷ.array() *= Σ.array();
 
  430    auto &&Jv            = 
impl->work2.topRows(
impl->ncon);
 
  434    checked(
impl->funcs.cjprod, 
"eval_hess_ψ_prod: CUTEST_cjprod-1")(
 
  435        &
impl->nvar, &
impl->ncon, &gotj, &jtrans, x.data(), v.data(), &lvector,
 
  436        Jv.data(), &lresult);
 
  438    Jv.array() *= ζ.array();
 
  440    std::swap(lvector, lresult);
 
  442    auto &&JΣJv   = 
impl->work.topRows(
impl->nvar);
 
  443    checked(
impl->funcs.cjprod, 
"eval_hess_ψ_prod: CUTEST_cjprod-2")(
 
  444        &
impl->nvar, &
impl->ncon, &gotj, &jtrans, x.data(), Jv.data(), &lvector,
 
  445        JΣJv.data(), &lresult);
 
  450                                rvec H_values)
 const {
 
  452    if (H_values.size() > 0) {
 
  455        const auto *mult = y.data();
 
  458            mult       = 
impl->work.data();
 
  466            assert(outer_ptr.size() == 
static_cast<length_t>(
impl->nvar + 1));
 
  468            checked(
impl->funcs.csh, 
"eval_hess_L: CUTEST_csh")(
 
  471            auto t0  = std::chrono::steady_clock::now();
 
  473            auto t1  = std::chrono::steady_clock::now();
 
  474            std::cout << 
"Permutation of H took: " 
  475                      << std::chrono::duration<double>{t1 - t0}.count() * 1e6
 
  480            assert(H_values.size() == 
static_cast<length_t>(
impl->nvar) *
 
  482            checked(
impl->funcs.cdh, 
"eval_hess_L: CUTEST_cdh")(
 
  493        assert(outer_ptr.size() == 
static_cast<length_t>(
impl->nvar + 1));
 
  495        checked(
impl->funcs.cshp, 
"eval_hess_L: CUTEST_cshp")(
 
  499        util::convert_triplets_to_ccs<config_t>(
H_row, 
H_col, inner_idx,
 
  507        checked(
impl->funcs.cdimsh,
 
  508                "get_hess_L_num_nonzeros: CUTEST_cdimsh")(&
nnz_H);
 
  518    assert(x.size() == 
static_cast<length_t>(impl->nvar));
 
  519    assert(grad_fx.size() == 
static_cast<length_t>(impl->nvar));
 
  522    checked(impl->funcs.cofg, 
"eval_f_grad_f: CUTEST_cofg")(
 
  523        &impl->nvar, x.data(), &f, grad_fx.data(), &grad);
 
  527    assert(x.size() == 
static_cast<length_t>(impl->nvar));
 
  528    assert(g.size() == 
static_cast<length_t>(impl->ncon));
 
  530    checked(impl->funcs.cfn, 
"eval_f_g: CUTEST_cfn")(&impl->nvar, &impl->ncon,
 
  531                                                     x.data(), &f, g.data());
 
  537    assert(grad_L.size() == 
static_cast<length_t>(
impl->nvar));
 
  540    checked(
impl->funcs.clfg, 
"eval_f_g: CUTEST_clfg")(
 
  541        &
impl->nvar, &
impl->ncon, x.data(), y.data(), &L, grad_L.data(), &grad);
 
  546    os << 
"CUTEst problem: " << 
name << 
"\r\n\n" 
  547       << 
"Number of variables:   " << 
n << 
"\r\n" 
  548       << 
"Number of constraints: " << 
m << 
"\r\n\n" 
  549       << 
"Objective function evaluations:            "  
  551       << 
"Objective function gradient evaluations:   "  
  553       << 
"Objective function Hessian evaluations:    "  
  555       << 
"Hessian times vector products:             "  
  558        os << 
"Constraint function evaluations:           "  
  560           << 
"Constraint function gradients evaluations: "  
  562           << 
"Constraint function Hessian evaluations:   "  
  565    return os << 
"Setup time:       " << r.
time_setup << 
"s\r\n" 
  566              << 
"Time since setup: " << r.
time << 
"s";
 
Implements common problem functions for minimization problems with box constraints.
 
void eval_proj_diff_g(crvec z, rvec p) const
 
length_t m
Number of constraints, dimension of g(x) and z.
 
length_t n
Number of decision variables, dimension of x.
 
Box D
Other constraints, .
 
cleanup_t cutest_terminate
Responsible for calling CUTEST_xterminate.
 
cutest::ccifg::signature_t * ccifg
 
cutest::cigr::signature_t * cigr
 
cutest::cfn::signature_t * cfn
 
integer ncon
Number of constraints.
 
cutest::ccfsg::signature_t * ccfsg
 
std::shared_ptr< void > cleanup_t
 
cutest::csjp::signature_t * csjp
 
cleanup_t cleanup_outsdif
Responsible for closing the OUTSDIF.d file.
 
cutest::cdimsh::signature_t * cdimsh
 
CUTEstLoader(const char *so_fname, const char *outsdif_fname)
 
integer iout
Fortran Unit Number for standard output.
 
cutest::cdimsj::signature_t * cdimsj
 
integer funit
Fortran Unit Number for OUTSDIF.d file.
 
decltype(auto) call(Args &&...args)
 
cutest::csh::signature_t * csh
 
cutest::clfg::signature_t * clfg
 
cleanup_t load_outsdif(const char *outsdif_fname)
 
cutest::cofg::signature_t * cofg
 
cleanup_t cleanup(F &&func)
 
integer nvar
Number of decision variabls.
 
T * dlfun(const char *name)
 
std::shared_ptr< void > so_handle
dlopen handle to shared library
 
cutest::cjprod::signature_t * cjprod
 
cutest::cdh::signature_t * cdh
 
Eigen::VectorX< logical > logical_vec
Pointers to loaded problem functions.
 
cutest::chprod::signature_t * chprod
 
void setup_problem(rvec x0, rvec y0, Box &C, Box &D)
 
logical_vec equatn
whether the constraint is an equality
 
cutest::cshp::signature_t * cshp
 
auto load() -> F::signature_t *
 
void get_report(double *calls, double *time)
 
cutest::ccfg::signature_t * ccfg
 
logical_vec linear
whether the constraint is linear
 
integer io_buffer
Fortran Unit Number for internal IO.
 
Wrapper for CUTEst problems loaded from an external shared library.
 
void eval_grad_gi(crvec x, index_t i, rvec grad_gi) const
 
Calls calls
Function call counters.
 
unsigned constraints_grad
Number of calls to the constraint gradients.
 
real_t eval_f_g(crvec x, rvec g) const
 
double time_setup
CPU time (in seconds) for CUTEST_csetup.
 
CUTEstProblem(const char *so_fname, const char *outsdif_fname, bool sparse=false)
Load a CUTEst problem from the given shared library and OUTSDIF.d file.
 
unsigned objective
Number of calls to the objective function.
 
void eval_grad_L(crvec x, crvec y, rvec grad_L, rvec work_n) const
 
Eigen::VectorX< int > J_row
 
Eigen::VectorX< int > J_col
 
Eigen::VectorX< int > H_col
 
void eval_hess_L(crvec x, crvec y, real_t scale, rindexvec inner_idx, rindexvec outer_ptr, rvec H_values) const
 
unsigned constraints
Number of calls to the constraint functions.
 
std::string name
Problem name.
 
util::copyable_unique_ptr< class CUTEstLoader > impl
 
real_t eval_f_grad_f(crvec x, rvec grad_fx) const
 
double time
CPU time (in seconds) since the end of CUTEST_csetup.
 
void eval_grad_g_prod(crvec x, crvec y, rvec grad_gxy) const
 
void eval_hess_L_prod(crvec x, crvec y, real_t scale, crvec v, rvec Hv) const
 
Eigen::VectorX< int > H_row
 
void eval_grad_f(crvec x, rvec grad_fx) const
 
real_t eval_f(crvec x) const
 
void eval_g(crvec x, rvec gx) const
 
unsigned objective_hess
Number of calls to the objective Hessian.
 
length_t get_jac_g_num_nonzeros() const
 
std::ostream & format_report(std::ostream &os, const Report &r) const
 
unsigned constraints_hess
Number of calls to the constraint Hessians.
 
CUTEstProblem & operator=(const CUTEstProblem &)
 
void eval_jac_g(crvec x, rindexvec inner_idx, rindexvec outer_ptr, rvec J_values) const
 
unsigned objective_grad
Number of calls to the objective gradient.
 
void eval_hess_ψ_prod(crvec x, crvec y, crvec Σ, real_t scale, crvec v, rvec Hv) const
 
length_t get_hess_L_num_nonzeros() const
 
The report generated by CUTEst.
 
#define USING_ALPAQA_CONFIG(Conf)
 
constexpr size_t fstring_len
 
typename Conf::real_t real_t
 
typename Conf::rindexvec rindexvec
 
typename Conf::index_t index_t
 
typename Conf::length_t length_t
 
typename Conf::crvec crvec