Skip to content

Commit

Permalink
Add prima_result
Browse files Browse the repository at this point in the history
  • Loading branch information
jschueller committed Oct 24, 2023
1 parent ca76de9 commit 870793e
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 89 deletions.
8 changes: 3 additions & 5 deletions c/examples/bobyqa/bobyqa_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,14 @@ int main(int argc, char * argv[])
(void)argv;
const int n = 2;
double x[2] = {0.0, 0.0};
double f = 0.0;

prima_options options;
prima_init_options(&options);
options.iprint = PRIMA_MSG_EXIT;
options.rhoend= 1e-3;
options.maxfun = 200*n;
int nf = 0;
const int rc = prima_bobyqa(&fun, n, x, &f, &nf, &options);
prima_result result;
const int rc = prima_bobyqa(&fun, n, x, &options, &result);
const char *msg = prima_get_rc_string(rc);
printf("x*={%g, %g} rc=%d msg='%s' evals=%d\n", x[0], x[1], rc, msg, nf);
printf("x*={%g, %g} rc=%d msg='%s' evals=%d\n", x[0], x[1], rc, msg, result.nf);
return (fabs(x[0]-3)>2e-2 || fabs(x[1]-2)>2e-2);
}
10 changes: 4 additions & 6 deletions c/examples/cobyla/cobyla_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ int main(int argc, char * argv[])
const int m_nlcon = 1;
const int n = 2;
double x[2] = {0.0, 0.0};
double f = 0.0;
double cstrv = 0.0;
double nlconstr[m_nlcon];
prima_options options;
prima_init_options(&options);
options.iprint = PRIMA_MSG_EXIT;
Expand All @@ -44,9 +41,10 @@ int main(int argc, char * argv[])
double xu[2] = {6.0, 6.0};
options.xl = xl;
options.xu = xu;
int nf = 0;
const int rc = prima_cobyla(&fun, n, x, &f, &cstrv, nlconstr, &nf, &options);
prima_result result;
const int rc = prima_cobyla(&fun, n, x, &options, &result);
const char *msg = prima_get_rc_string(rc);
printf("x*={%g, %g} f*=%g cstrv=%g nlconstr=%g rc=%d msg='%s' evals=%d\n", x[0], x[1], f, cstrv, nlconstr[0], rc, msg, nf);
printf("x*={%g, %g} f*=%g cstrv=%g nlconstr=%g rc=%d msg='%s' evals=%d\n", x[0], x[1], result.f, result.cstrv, result.nlconstr[0], rc, msg, result.nf);
prima_free_result(&result);
return (fabs(x[0]-3)>2e-2 || fabs(x[1]-2)>2e-2);
}
6 changes: 3 additions & 3 deletions c/examples/lincoa/lincoa_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ int main(int argc, char * argv[])
double xu[2] = {6.0, 6.0};
options.xl = xl;
options.xu = xu;
int nf = 0;
const int rc = prima_lincoa(&fun, n, x, &f, &cstrv, &nf, &options);
prima_result result;
const int rc = prima_lincoa(&fun, n, x, &options, &result);
const char *msg = prima_get_rc_string(rc);
printf("x*={%g, %g} f*=%g cstrv=%g rc=%d msg='%s' evals=%d\n", x[0], x[1], f, cstrv, rc, msg, nf);
printf("x*={%g, %g} f*=%g cstrv=%g rc=%d msg='%s' evals=%d\n", x[0], x[1], result.f, result.cstrv, rc, msg, result.nf);
return (fabs(x[0]-3)>2e-2 || fabs(x[1]-2)>2e-2);
}
7 changes: 3 additions & 4 deletions c/examples/newuoa/newuoa_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@ int main(int argc, char * argv[])
(void)argv;
const int n = 2;
double x[2] = {0.0, 0.0};
double f = 0.0;
prima_options options;
prima_init_options(&options);
options.iprint = PRIMA_MSG_EXIT;
options.rhoend= 1e-3;
options.maxfun = 200*n;
int nf = 0;
const int rc = prima_newuoa(&fun, n, x, &f, &nf, &options);
prima_result result;
const int rc = prima_newuoa(&fun, n, x, &options, &result);
const char *msg = prima_get_rc_string(rc);
printf("x*={%g, %g} rc=%d msg='%s' evals=%d\n", x[0], x[1], rc, msg, nf);
printf("x*={%g, %g} rc=%d msg='%s' evals=%d\n", x[0], x[1], rc, msg, result.nf);
return (fabs(x[0]-3)>2e-2 || fabs(x[1]-2)>2e-2);
}
7 changes: 3 additions & 4 deletions c/examples/uobyqa/uobyqa_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@ int main(int argc, char * argv[])
(void)argv;
const int n = 2;
double x[2] = {0.0, 0.0};
double f = 0.0;
prima_options options;
prima_init_options(&options);
options.iprint = PRIMA_MSG_EXIT;
options.rhoend= 1e-3;
options.maxfun = 200*n;
int nf = 0;
const int rc = prima_uobyqa(&fun, n, x, &f, &nf, &options);
prima_result result;
const int rc = prima_uobyqa(&fun, n, x, &options, &result);
const char *msg = prima_get_rc_string(rc);
printf("x*={%g, %g} rc=%d msg='%s' evals=%d\n", x[0], x[1], rc, msg, nf);
printf("x*={%g, %g} rc=%d msg='%s' evals=%d\n", x[0], x[1], rc, msg, result.nf);
return (fabs(x[0]-3)>2e-2 || fabs(x[1]-2)>2e-2);
}
49 changes: 31 additions & 18 deletions c/include/prima/prima.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,46 +135,59 @@ typedef struct {

} prima_options;


/* Initialize option data */
PRIMAC_API
int prima_init_options(prima_options * options);


typedef struct {
// objective value
double f;

// number of objective function calls
int nf;

// constraint violation (cobyla & lincoa)
double cstrv;

// non-linear constraint values, of size m_nlcon (cobyla only)
double *nlconstr;

// whether prima had to allocate nlconstr0 (private, do not use)
int _allocated_nlconstr;

} prima_result;


PRIMAC_API
int prima_free_result(prima_result * result);

/*
* calfun : function to minimize (see prima_obj)
* calcfc : function to minimize and constraints (see prima_objcon)
* n : number of variables (>=0)
* x : on input, initial estimate
* on output, the solution
* f : objective value (output)
* nf : number of objective function calls (output)
* options : optimization options (see prima_options)
* calcfc : function to minimize and constraints (see prima_objcon)
* cstrv : constraint violation (output)
* nlconstr : non-linear constraint values of size m_nlcon (output)
*
* result : optimization results (see prima_result)
* return : see prima_rc enum for return codes
*/

PRIMAC_API
int prima_bobyqa(const prima_obj calfun, const int n, double x[], double *f,
int *nf, prima_options * options);
int prima_bobyqa(const prima_obj calfun, const int n, double x[], prima_options * options, prima_result * result);

PRIMAC_API
int prima_newuoa(const prima_obj calfun, const int n, double x[], double *f,
int *nf, prima_options * options);
int prima_newuoa(const prima_obj calfun, const int n, double x[], prima_options * options, prima_result * result);

PRIMAC_API
int prima_uobyqa(const prima_obj calfun, const int n, double x[], double *f,
int *nf, prima_options * options);
int prima_uobyqa(const prima_obj calfun, const int n, double x[], prima_options * options, prima_result * result);

PRIMAC_API
int prima_cobyla(const prima_objcon calcfc, const int n, double x[], double *f,
double *cstrv, double nlconstr[],
int *nf, prima_options * options);
int prima_cobyla(const prima_objcon calcfc, const int n, double x[], prima_options * options, prima_result * result);

PRIMAC_API
int prima_lincoa(const prima_obj calfun, const int n, double x[], double *f,
double *cstrv,
int *nf, prima_options * options);
int prima_lincoa(const prima_obj calfun, const int n, double x[], prima_options * options, prima_result * result);

#ifdef __cplusplus
}
Expand Down
76 changes: 53 additions & 23 deletions c/prima.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,43 @@ void prima_free_options(prima_options * opt)
}
}

int prima_init_result(prima_result * result)
{
result->f = 0.0;
result->nf = 0;
result->cstrv = 0.0;
result->nlconstr = NULL;
result->_allocated_nlconstr = 0;
return 0;
}

int prima_free_result(prima_result * result)
{
if (result)
{
if (result->_allocated_nlconstr)
{
free(result->nlconstr);
result->nlconstr = NULL;
result->_allocated_nlconstr = 0;
}
}
return 0;
}

/* these functions just call the fortran compatibility layer and return the status code */
int prima_cobyla(const prima_objcon calcfc, const int n, double x[], double *f,
double *cstrv, double nlconstr[],
int *nf, prima_options * opt)
int prima_cobyla(const prima_objcon calcfc, const int n, double x[], prima_options * opt, prima_result * result)
{
int info = prima_check_options(opt, n, 1);
if (info == 0)
if ((info == 0) && result)
{
prima_init_result(result);
// allocate nlconstr
result->nlconstr = (double*)calloc(opt->m_nlcon, sizeof(double));
if (!result->nlconstr)
return PRIMA_MEMORY_ALLOCATION_FAILS;
result->_allocated_nlconstr = 1;

// evaluate f0, nlconstr0 if either one is not provided
if (opt->f0 == NAN || !opt->nlconstr0)
{
Expand All @@ -130,59 +159,60 @@ int prima_cobyla(const prima_objcon calcfc, const int n, double x[], double *f,
}
calcfc(x, &(opt->f0), opt->nlconstr0, opt->data);
}
cobyla_c(opt->m_nlcon, calcfc, opt->data, n, x, f, cstrv, nlconstr,
cobyla_c(opt->m_nlcon, calcfc, opt->data, n, x, &(result->f), &(result->cstrv), result->nlconstr,
opt->m_ineq, opt->Aineq, opt->bineq, opt->m_eq, opt->Aeq, opt->beq,
opt->xl, opt->xu, opt->f0, opt->nlconstr0, nf, opt->rhobeg, opt->rhoend, opt->ftarget, opt->maxfun, opt->iprint, &info);
opt->xl, opt->xu, opt->f0, opt->nlconstr0, &(result->nf), opt->rhobeg, opt->rhoend, opt->ftarget, opt->maxfun, opt->iprint, &info);
prima_free_options(opt);
}
return info;
}

int prima_bobyqa(const prima_obj calfun, const int n, double x[], double *f,
int *nf, prima_options * opt)
int prima_bobyqa(const prima_obj calfun, const int n, double x[], prima_options * opt, prima_result * result)
{
int info = prima_check_options(opt, n, 1);
if (info == 0)
if ((info == 0) && result)
{
bobyqa_c(calfun, opt->data, n, x, f, opt->xl, opt->xu, nf, opt->rhobeg, opt->rhoend, opt->ftarget, opt->maxfun, opt->npt < 0 ? 2*n+1 : opt->npt, opt->iprint, &info);
prima_init_result(result);
bobyqa_c(calfun, opt->data, n, x, &(result->f), opt->xl, opt->xu, &(result->nf), opt->rhobeg, opt->rhoend, opt->ftarget, opt->maxfun, opt->npt, opt->iprint, &info);

prima_free_options(opt);
}
return info;
}

int prima_newuoa(const prima_obj calfun, const int n, double x[], double *f,
int *nf, prima_options * opt)
int prima_newuoa(const prima_obj calfun, const int n, double x[], prima_options * opt, prima_result * result)
{
int info = prima_check_options(opt, n, 0);
if (info == 0)
if ((info == 0) && result)
{
newuoa_c(calfun, opt->data, n, x, f, nf, opt->rhobeg, opt->rhoend, opt->ftarget, opt->maxfun, opt->npt < 0 ? 2*n+1 : opt->npt, opt->iprint, &info);
prima_init_result(result);
newuoa_c(calfun, opt->data, n, x, &(result->f), &(result->nf), opt->rhobeg, opt->rhoend, opt->ftarget, opt->maxfun, opt->npt, opt->iprint, &info);
prima_free_options(opt);
}
return info;
}

int prima_uobyqa(const prima_obj calfun, const int n, double x[], double *f,
int *nf, prima_options * opt)
int prima_uobyqa(const prima_obj calfun, const int n, double x[], prima_options * opt, prima_result * result)
{
int info = prima_check_options(opt, n, 0);
if (info == 0)
if ((info == 0) && result)
{
uobyqa_c(calfun, opt->data, n, x, f, nf, opt->rhobeg, opt->rhoend, opt->ftarget, opt->maxfun, opt->iprint, &info);
prima_init_result(result);
uobyqa_c(calfun, opt->data, n, x, &(result->f), &(result->nf), opt->rhobeg, opt->rhoend, opt->ftarget, opt->maxfun, opt->iprint, &info);
prima_free_options(opt);
}
return info;
}

int prima_lincoa(const prima_obj calfun, const int n, double x[], double *f, double *cstrv,
int *nf, prima_options * opt)
int prima_lincoa(const prima_obj calfun, const int n, double x[], prima_options * opt, prima_result * result)
{
int info = prima_check_options(opt, n, 1);
if (info == 0)
if ((info == 0) && result)
{
lincoa_c(calfun, opt->data, n, x, f, cstrv,
prima_init_result(result);
lincoa_c(calfun, opt->data, n, x, &(result->f), &(result->cstrv),
opt->m_ineq, opt->Aineq, opt->bineq, opt->m_eq, opt->Aeq, opt->beq,
opt->xl, opt->xu, nf, opt->rhobeg, opt->rhoend, opt->ftarget, opt->maxfun, opt->npt < 0 ? 2*n+1 : opt->npt, opt->iprint, &info);
opt->xl, opt->xu, &(result->nf), opt->rhobeg, opt->rhoend, opt->ftarget, opt->maxfun, opt->npt, opt->iprint, &info);
prima_free_options(opt);
}
return info;
Expand Down
20 changes: 8 additions & 12 deletions c/tests/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,6 @@ int main(int argc, char * argv[])
double x[] = {0, 0};
double xl[] = {-6.0, -6.0};
double xu[] = {6.0, 6.0};
double f = 0.0;
double cstrv = 0.0;
double nlconstr[m_nlcon];
for (int j = 0; j < m_nlcon; ++ j)
nlconstr[j] = 0.0;
prima_options options;
prima_init_options(&options);
options.iprint = PRIMA_MSG_RHO;
Expand All @@ -90,28 +85,28 @@ int main(int argc, char * argv[])
options.bineq = bineq;
options.xl = xl;
options.xu = xu;
int nf = 0;
prima_result result;
int rc = 0;
if(strcmp(algo, "bobyqa") == 0)
{
rc = prima_bobyqa(&fun, n, x, &f, &nf, &options);
rc = prima_bobyqa(&fun, n, x, &options, &result);
}
else if(strcmp(algo, "cobyla") == 0)
{
options.m_nlcon = m_nlcon;
rc = prima_cobyla(&fun_con, n, x, &f, &cstrv, nlconstr, &nf, &options);
rc = prima_cobyla(&fun_con, n, x, &options, &result);
}
else if(strcmp(algo, "lincoa") == 0)
{
rc = prima_lincoa(&fun, n, x, &f, &cstrv, &nf, &options);
rc = prima_lincoa(&fun, n, x, &options, &result);
}
else if(strcmp(algo, "newuoa") == 0)
{
rc = prima_newuoa(&fun, n, x, &f, &nf, &options);
rc = prima_newuoa(&fun, n, x, &options, &result);
}
else if(strcmp(algo, "uobyqa") == 0)
{
rc = prima_uobyqa(&fun, n, x, &f, &nf, &options);
rc = prima_uobyqa(&fun, n, x, &options, &result);
}
else
{
Expand All @@ -120,6 +115,7 @@ int main(int argc, char * argv[])
}
const char *msg = prima_get_rc_string(rc);

printf("f*=%g cstrv=%g nlconstr=%g rc=%d msg='%s' evals=%d\n", f, cstrv, nlconstr[0], rc, msg, nf);
printf("f*=%g cstrv=%g nlconstr=%g rc=%d msg='%s' evals=%d\n", result.f, result.cstrv, result.nlconstr ? result.nlconstr[0] : 0.0, rc, msg, result.nf);
prima_free_result(&result);
return (fabs(x[0]-3)>2e-2 || fabs(x[1]-2)>2e-2);
}
Loading

0 comments on commit 870793e

Please sign in to comment.