From 291ced2b46e6686435ea0a75576014b9a432cec9 Mon Sep 17 00:00:00 2001 From: Nickolai Belakovski Date: Tue, 30 Apr 2024 21:24:53 -0400 Subject: [PATCH] Refactor prima_is_success to accept options.ctol This is in reference to https://github.com/libprima/prima/issues/195 --- c/cobyla_c.f90 | 6 ++---- c/include/prima/prima.h | 2 +- c/lincoa_c.f90 | 6 ++---- c/prima.c | 8 ++++---- python/_prima.cpp | 7 ++++--- 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/c/cobyla_c.f90 b/c/cobyla_c.f90 index e0ac273e01..36db0414e0 100644 --- a/c/cobyla_c.f90 +++ b/c/cobyla_c.f90 @@ -71,6 +71,7 @@ subroutine cobyla_c(m_nlcon, cobjcon_ptr, data_ptr, n, x, f, cstrv, nlconstr, m_ real(RP) :: beq_loc(m_eq) real(RP) :: bineq_loc(m_ineq) real(RP) :: cstrv_loc +real(RP) :: ctol_loc real(RP) :: f_loc real(RP) :: ftarget_loc real(RP) :: nlconstr_loc(m_nlcon) @@ -79,7 +80,6 @@ subroutine cobyla_c(m_nlcon, cobjcon_ptr, data_ptr, n, x, f, cstrv, nlconstr, m_ real(RP), allocatable :: nlconstr0_loc(:) real(RP), allocatable :: rhobeg_loc real(RP), allocatable :: rhoend_loc -real(RP), allocatable :: ctol_loc real(RP), allocatable :: xl_loc(:) real(RP), allocatable :: xu_loc(:) @@ -131,9 +131,7 @@ subroutine cobyla_c(m_nlcon, cobjcon_ptr, data_ptr, n, x, f, cstrv, nlconstr, m_ maxfun_loc = int(maxfun, kind(maxfun_loc)) end if iprint_loc = int(iprint, kind(iprint_loc)) -if (.not. is_nan(ctol)) then - ctol_loc = real(ctol, kind(ctol_loc)) -end if +ctol_loc = real(ctol, kind(ctol_loc)) ! Call the Fortran code if (c_associated(callback_ptr)) then diff --git a/c/include/prima/prima.h b/c/include/prima/prima.h index 9893108747..00c68c6f8c 100644 --- a/c/include/prima/prima.h +++ b/c/include/prima/prima.h @@ -300,7 +300,7 @@ prima_rc_t prima_minimize(const prima_algorithm_t algorithm, const prima_problem // Function to check if PRIMA returned normally or ran into abnormal conditions PRIMAC_API -bool prima_is_success(const prima_result_t result); +bool prima_is_success(const prima_result_t result, const prima_options_t options); #ifdef __cplusplus } diff --git a/c/lincoa_c.f90 b/c/lincoa_c.f90 index cb399bfef2..40864846d4 100644 --- a/c/lincoa_c.f90 +++ b/c/lincoa_c.f90 @@ -68,12 +68,12 @@ subroutine lincoa_c(cobj_ptr, data_ptr, n, x, f, cstrv, m_ineq, Aineq, bineq, m_ real(RP) :: beq_loc(m_eq) real(RP) :: bineq_loc(m_ineq) real(RP) :: cstrv_loc +real(RP) :: ctol_loc real(RP) :: f_loc real(RP) :: ftarget_loc real(RP) :: x_loc(n) real(RP), allocatable :: rhobeg_loc real(RP), allocatable :: rhoend_loc -real(RP), allocatable :: ctol_loc real(RP), allocatable :: xl_loc(:) real(RP), allocatable :: xu_loc(:) @@ -120,9 +120,7 @@ subroutine lincoa_c(cobj_ptr, data_ptr, n, x, f, cstrv, m_ineq, Aineq, bineq, m_ npt_loc = int(npt, kind(npt_loc)) end if iprint_loc = int(iprint, kind(iprint_loc)) -if (.not. is_nan(ctol)) then - ctol_loc = real(ctol, kind(ctol_loc)) -end if +ctol_loc = real(ctol, kind(ctol_loc)) ! Call the Fortran code if (c_associated(callback_ptr)) then diff --git a/c/prima.c b/c/prima.c index 5d380971c1..b91d3c7556 100644 --- a/c/prima.c +++ b/c/prima.c @@ -57,7 +57,7 @@ prima_rc_t prima_init_options(prima_options_t *const options) options->rhoend = NAN; // Will be interpreted by Fortran as not present options->iprint = PRIMA_MSG_NONE; options->ftarget = -INFINITY; - options->ctol = NAN; // Will be interpreted by Fortran as not present + options->ctol = sqrt(DBL_EPSILON); return PRIMA_RC_DFT; } @@ -268,8 +268,8 @@ prima_rc_t prima_minimize(const prima_algorithm_t algorithm, const prima_problem return info; } -bool prima_is_success(const prima_result_t result) +bool prima_is_success(const prima_result_t result, const prima_options_t options) { - return (result.status == PRIMA_SMALL_TR_RADIUS || - result.status == PRIMA_FTARGET_ACHIEVED) && (result.cstrv <= sqrt(DBL_EPSILON)); + return ((result.status == PRIMA_SMALL_TR_RADIUS && result.cstrv <= options.ctol) || + (result.status == PRIMA_FTARGET_ACHIEVED)); } diff --git a/python/_prima.cpp b/python/_prima.cpp index 98794b453d..a27b701150 100644 --- a/python/_prima.cpp +++ b/python/_prima.cpp @@ -30,9 +30,10 @@ class SelfCleaningPyObject { struct PRIMAResult { // Construct PRIMAResult from prima_result_t - PRIMAResult(const prima_result_t& result, const int num_vars, const int num_constraints, const std::string method) : + PRIMAResult(const prima_result_t& result, const int num_vars, const int num_constraints, const std::string method + const prima_options_t& options) : x(num_vars, result.x), - success(prima_is_success(result)), + success(prima_is_success(result, options)), status(result.status), message(result.message), fun(result.f), @@ -325,7 +326,7 @@ PYBIND11_MODULE(_prima, m) { // Initialize the result, call the function, convert the return type, and return it. prima_result_t result; const prima_rc_t rc = prima_minimize(algorithm, problem, options, &result); - PRIMAResult result_copy(result, py_x0.size(), problem.m_nlcon, method.cast()); + PRIMAResult result_copy(result, py_x0.size(), problem.m_nlcon, method.cast(), options); prima_free_result(&result); return result_copy; }, "fun"_a, "x0"_a, "args"_a=py::tuple(), "method"_a=py::none(),