Skip to content

Commit

Permalink
Add algo enum
Browse files Browse the repository at this point in the history
This simplifies even further the API with an enum to choose the
algorithm instead of the 5 different functions for each algorithm:
```
enum prima_algorithm = {PRIMA_COBYLA, PRIMA_BOBYQA, ...}
int prima_minimize(int algorithm, prima_problem *problem, prima_options *options, prima_result *result);
```
  • Loading branch information
jschueller committed Nov 29, 2023
1 parent 34f886e commit de4d164
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 90 deletions.
2 changes: 1 addition & 1 deletion c/examples/bobyqa/bobyqa_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ int main(int argc, char * argv[])
options.rhoend= 1e-3;
options.maxfun = 200*n;
prima_result result;
const int rc = prima_bobyqa(&problem, &options, &result);
const int rc = prima_minimize(PRIMA_BOBYQA, &problem, &options, &result);
printf("x*={%g, %g} rc=%d msg='%s' evals=%d\n", result.x[0], result.x[1], rc, result.message, result.nf);
prima_free_problem(&problem);
prima_free_result(&result);
Expand Down
2 changes: 1 addition & 1 deletion c/examples/cobyla/cobyla_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ int main(int argc, char * argv[])
problem.xl = xl;
problem.xu = xu;
prima_result result;
const int rc = prima_cobyla(&problem, &options, &result);
const int rc = prima_minimize(PRIMA_COBYLA, &problem, &options, &result);
printf("x*={%g, %g} f*=%g cstrv=%g nlconstr=%g rc=%d msg='%s' evals=%d\n", result.x[0], result.x[1], result.f, result.cstrv, result.nlconstr[0], rc, result.message, result.nf);
prima_free_problem(&problem);
prima_free_result(&result);
Expand Down
2 changes: 1 addition & 1 deletion c/examples/lincoa/lincoa_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ int main(int argc, char * argv[])
problem.xl = xl;
problem.xu = xu;
prima_result result;
const int rc = prima_lincoa(&problem, &options, &result);
const int rc = prima_minimize(PRIMA_LINCOA, &problem, &options, &result);
printf("x*={%g, %g} f*=%g cstrv=%g rc=%d msg='%s' evals=%d\n", result.x[0], result.x[1], result.f, result.cstrv, rc, result.message, result.nf);
prima_free_problem(&problem);
prima_free_result(&result);
Expand Down
2 changes: 1 addition & 1 deletion c/examples/newuoa/newuoa_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ int main(int argc, char * argv[])
options.rhoend= 1e-3;
options.maxfun = 200*n;
prima_result result;
const int rc = prima_newuoa(&problem, &options, &result);
const int rc = prima_minimize(PRIMA_NEWUOA, &problem, &options, &result);
printf("x*={%g, %g} rc=%d msg='%s' evals=%d\n", result.x[0], result.x[1], rc, result.message, result.nf);
prima_free_problem(&problem);
prima_free_result(&result);
Expand Down
2 changes: 1 addition & 1 deletion c/examples/uobyqa/uobyqa_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ int main(int argc, char * argv[])
options.rhoend= 1e-3;
options.maxfun = 200*n;
prima_result result;
const int rc = prima_uobyqa(&problem, &options, &result);
const int rc = prima_minimize(PRIMA_UOBYQA, &problem, &options, &result);
printf("x*={%g, %g} rc=%d msg='%s' evals=%d\n", result.x[0], result.x[1], rc, result.message, result.nf);
prima_free_problem(&problem);
prima_free_result(&result);
Expand Down
28 changes: 15 additions & 13 deletions c/include/prima/prima.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,26 +202,28 @@ PRIMAC_API
int prima_free_result(prima_result * result);

/*
* Algorithm
*/
typedef enum
{
PRIMA_BOBYQA,
PRIMA_COBYLA,
PRIMA_LINCOA,
PRIMA_NEWUOA,
PRIMA_UOBYQA
} prima_algorithm;


/*
* algorithm : optimization algorithm (see prima_algorithm)
* problem : optimization problem (see prima_problem)
* options : optimization options (see prima_options)
* result : optimization result (see prima_result)
* return : see prima_rc enum for return codes
*/

PRIMAC_API
int prima_bobyqa(prima_problem *problem, prima_options *options, prima_result *result);

PRIMAC_API
int prima_newuoa(prima_problem *problem, prima_options *options, prima_result *result);

PRIMAC_API
int prima_uobyqa(prima_problem *problem, prima_options *options, prima_result *result);

PRIMAC_API
int prima_cobyla(prima_problem *problem, prima_options *options, prima_result *result);

PRIMAC_API
int prima_lincoa(prima_problem *problem, prima_options *options, prima_result *result);
int prima_minimize(prima_algorithm algorithm, prima_problem *problem, prima_options *options, prima_result *result);

#ifdef __cplusplus
}
Expand Down
94 changes: 34 additions & 60 deletions c/prima.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,16 @@ int prima_free_result(prima_result *result)
}

/* these functions just call the fortran compatibility layer and return the status code */
int prima_cobyla(prima_problem *problem, prima_options *options, prima_result *result)
int prima_minimize(prima_algorithm algorithm, prima_problem *problem, prima_options *options, prima_result *result)
{
int info = prima_check_problem(problem, options, 1, 1);
int alloc_bounds = (algorithm == PRIMA_COBYLA) || (algorithm == PRIMA_BOBYQA) || (algorithm == PRIMA_LINCOA);
int use_constr = (algorithm == PRIMA_COBYLA);

int info = prima_check_problem(problem, options, alloc_bounds, use_constr);
if (info == 0)
info = prima_init_result(result, problem);
if (info == 0)

if ((info == 0) && use_constr)
{
// reuse or (re)allocate nlconstr
if (result->_m_nlcon != problem->m_nlcon)
Expand All @@ -177,7 +181,8 @@ int prima_cobyla(prima_problem *problem, prima_options *options, prima_result *r
result->_m_nlcon = problem->m_nlcon;
}
}
if (info == 0)

if ((info == 0) && use_constr)
{
// evaluate f0, nlconstr0 if either one is not provided
if (problem->f0 == NAN || !problem->nlconstr0)
Expand All @@ -192,69 +197,38 @@ int prima_cobyla(prima_problem *problem, prima_options *options, prima_result *r
problem->calcfc(result->x, &(problem->f0), problem->nlconstr0, options->data);
}
}
if (info == 0)
{
cobyla_c(problem->m_nlcon, problem->calcfc, options->data, problem->n, result->x, &(result->f), &(result->cstrv), result->nlconstr,
problem->m_ineq, problem->Aineq, problem->bineq, problem->m_eq, problem->Aeq, problem->beq,
problem->xl, problem->xu, problem->f0, problem->nlconstr0, &(result->nf), options->rhobeg, options->rhoend, options->ftarget, options->maxfun, options->iprint, &info);
result->status = info;
result->message = prima_get_rc_string(info);
}
return info;
}

int prima_bobyqa(prima_problem *problem, prima_options *options, prima_result *result)
{
int info = prima_check_problem(problem, options, 1, 0);
if (info == 0)
info = prima_init_result(result, problem);
if (info == 0)
{
bobyqa_c(problem->calfun, options->data, problem->n, result->x, &(result->f), problem->xl, problem->xu, &(result->nf), options->rhobeg, options->rhoend, options->ftarget, options->maxfun, options->npt, options->iprint, &info);
result->status = info;
result->message = prima_get_rc_string(info);
}
return info;
}

int prima_newuoa(prima_problem *problem, prima_options *options, prima_result *result)
{
int info = prima_check_problem(problem, options, 0, 0);
if (info == 0)
info = prima_init_result(result, problem);
if (info == 0)
{
newuoa_c(problem->calfun, options->data, problem->n, result->x, &(result->f), &(result->nf), options->rhobeg, options->rhoend, options->ftarget, options->maxfun, options->npt, options->iprint, &info);
result->status = info;
result->message = prima_get_rc_string(info);
}
return info;
}
switch (algorithm)
{
case PRIMA_BOBYQA:
bobyqa_c(problem->calfun, options->data, problem->n, result->x, &(result->f), problem->xl, problem->xu, &(result->nf), options->rhobeg, options->rhoend, options->ftarget, options->maxfun, options->npt, options->iprint, &info);
break;

int prima_uobyqa(prima_problem *problem, prima_options *options, prima_result *result)
{
int info = prima_check_problem(problem, options, 0, 0);
if (info == 0)
info = prima_init_result(result, problem);
if (info == 0)
{
uobyqa_c(problem->calfun, options->data, problem->n, result->x, &(result->f), &(result->nf), options->rhobeg, options->rhoend, options->ftarget, options->maxfun, options->iprint, &info);
result->status = info;
result->message = prima_get_rc_string(info);
}
return info;
}
case PRIMA_COBYLA:
cobyla_c(problem->m_nlcon, problem->calcfc, options->data, problem->n, result->x, &(result->f), &(result->cstrv), result->nlconstr,
problem->m_ineq, problem->Aineq, problem->bineq, problem->m_eq, problem->Aeq, problem->beq,
problem->xl, problem->xu, problem->f0, problem->nlconstr0, &(result->nf), options->rhobeg, options->rhoend, options->ftarget, options->maxfun, options->iprint, &info);
break;

int prima_lincoa(prima_problem *problem, prima_options *options, prima_result *result)
{
int info = prima_check_problem(problem, options, 1, 0);
if (info == 0)
info = prima_init_result(result, problem);
if (info == 0)
{
lincoa_c(problem->calfun, options->data, problem->n, result->x, &(result->f), &(result->cstrv),
case PRIMA_LINCOA:
lincoa_c(problem->calfun, options->data, problem->n, result->x, &(result->f), &(result->cstrv),
problem->m_ineq, problem->Aineq, problem->bineq, problem->m_eq, problem->Aeq, problem->beq,
problem->xl, problem->xu, &(result->nf), options->rhobeg, options->rhoend, options->ftarget, options->maxfun, options->npt, options->iprint, &info);
break;

case PRIMA_NEWUOA:
newuoa_c(problem->calfun, options->data, problem->n, result->x, &(result->f), &(result->nf), options->rhobeg, options->rhoend, options->ftarget, options->maxfun, options->npt, options->iprint, &info);
break;

case PRIMA_UOBYQA:
uobyqa_c(problem->calfun, options->data, problem->n, result->x, &(result->f), &(result->nf), options->rhobeg, options->rhoend, options->ftarget, options->maxfun, options->iprint, &info);
break;

default:
return PRIMA_INVALID_INPUT;
}
result->status = info;
result->message = prima_get_rc_string(info);
}
Expand Down
13 changes: 7 additions & 6 deletions c/tests/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,33 +91,34 @@ int main(int argc, char * argv[])
problem.xl = xl;
problem.xu = xu;
prima_result result;
int rc = 0;
int algorithm = 0;
if(strcmp(algo, "bobyqa") == 0)
{
rc = prima_bobyqa(&problem, &options, &result);
algorithm = PRIMA_BOBYQA;
}
else if(strcmp(algo, "cobyla") == 0)
{
algorithm = PRIMA_COBYLA;
problem.m_nlcon = M_NLCON;
rc = prima_cobyla(&problem, &options, &result);
}
else if(strcmp(algo, "lincoa") == 0)
{
rc = prima_lincoa(&problem, &options, &result);
algorithm = PRIMA_LINCOA;
}
else if(strcmp(algo, "newuoa") == 0)
{
rc = prima_newuoa(&problem, &options, &result);
algorithm = PRIMA_NEWUOA;
}
else if(strcmp(algo, "uobyqa") == 0)
{
rc = prima_uobyqa(&problem, &options, &result);
algorithm = PRIMA_UOBYQA;
}
else
{
printf("incorrect algo\n");
return 1;
}
int rc = prima_minimize(algorithm, &problem, &options, &result);
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, result.message, result.nf);
prima_free_problem(&problem);
prima_free_result(&result);
Expand Down
13 changes: 7 additions & 6 deletions c/tests/stress.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,41 +109,42 @@ int main(int argc, char * argv[])
xl[i] = -1.0;
xu[i] = 1.0;
}
int algorithm = 0;
prima_result result;
if(strcmp(algo, "bobyqa") == 0)
{
algorithm = PRIMA_BOBYQA;
problem.n = 1600;
rc = prima_bobyqa(&problem, &options, &result);
}
else if(strcmp(algo, "cobyla") == 0)
{
algorithm = PRIMA_COBYLA;
problem.n = 800;
problem.m_nlcon = M_NLCON;
problem.m_ineq = 600;
rc = prima_cobyla(&problem, &options, &result);
}
else if(strcmp(algo, "lincoa") == 0)
{
algorithm = PRIMA_LINCOA;
problem.n = 1000;
problem.m_ineq = 1000;
rc = prima_lincoa(&problem, &options, &result);
}
else if(strcmp(algo, "newuoa") == 0)
{
algorithm = PRIMA_NEWUOA;
problem.n = 1600;
rc = prima_newuoa(&problem, &options, &result);
}
else if(strcmp(algo, "uobyqa") == 0)
{
algorithm = PRIMA_UOBYQA;
problem.n = 100;
rc = prima_uobyqa(&problem, &options, &result);
}
else
{
printf("incorrect algo\n");
return 1;
}

rc = prima_minimize(algorithm, &problem, &options, &result);
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, result.message, result.nf);
prima_free_problem(&problem);
prima_free_result(&result);
Expand Down

0 comments on commit de4d164

Please sign in to comment.