Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always initialize the result. #180

Merged
merged 2 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions c/include/prima/prima.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,9 @@ int prima_init_options(prima_options_t *const options);


// Structure to hold the result
// prima_minimize will allocate the memory for x and nlconstr (if needed),
// and as such the user is expected to free the memory using prima_free_result
// once they are done using the contents of the result (or have saved the contents).
typedef struct {

// x: returned point
Expand Down Expand Up @@ -277,11 +280,14 @@ int prima_free_result(prima_result_t *const result);


/*
* The function that does the minimization using a PRIMA solver
* algorithm : optimization algorithm (see prima_algorithm)
* problem : optimization problem (see prima_problem)
* options : optimization options (see prima_options)
* result : optimization result (see prima_result)
* The function that does the minimization using a PRIMA solver.
* After using (or saving) the result, the user is expected to call
* prima_free_result, regardless of the return value of prima_minimize,
* in order to avoid memory leaks.
* algorithm : optimization algorithm (see prima_algorithm_t)
* problem : optimization problem (see prima_problem_t)
* options : optimization options (see prima_options_t)
* result : optimization result (see prima_result_t)
* return : see prima_rc_t enum for return codes
*/
PRIMAC_API
Expand Down
53 changes: 28 additions & 25 deletions c/prima.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,32 +93,12 @@ int prima_init_result(prima_result_t *const result, const prima_problem_t proble

memset(result, 0, sizeof(prima_result_t));

// x: returned point
result->x = (double*)malloc(problem.n * sizeof(double));
if (!result->x)
return PRIMA_MEMORY_ALLOCATION_FAILS;
for (int i = 0; i < problem.n; i++)
result->x[i] = problem.x0[i];

// f: objective function value at the returned point
result->f = NAN;

// cstrv: constraint violation at the returned point (COBYLA and LINCOA only)
result->cstrv = NAN;

// nlconstr: nonlinear constraint values at the returned point, of size m_nlcon (COBYLA only)
if (problem.m_nlcon <= 0)
result->nlconstr = NULL;
else {
result->nlconstr = (double*)malloc(problem.m_nlcon * sizeof(double));
if (!result->nlconstr) {
free(result->x);
return PRIMA_MEMORY_ALLOCATION_FAILS;
}
for (int i = 0; i < problem.m_nlcon; i++)
result->nlconstr[i] = NAN;
}

// nf: number of function evaluations
result->nf = INT_MIN;

Expand All @@ -128,6 +108,22 @@ int prima_init_result(prima_result_t *const result, const prima_problem_t proble
// message: exit message
result->message = NULL;

// x: returned point
result->x = (double*)malloc(problem.n * sizeof(double));
if (!result->x)
return PRIMA_MEMORY_ALLOCATION_FAILS;
for (int i = 0; i < problem.n; i++)
result->x[i] = NAN;

// nlconstr: nonlinear constraint values at the returned point, of size m_nlcon (COBYLA only)
result->nlconstr = (double*)malloc(problem.m_nlcon * sizeof(double));
if (!result->nlconstr) {
free(result->x);
return PRIMA_MEMORY_ALLOCATION_FAILS;
}
for (int i = 0; i < problem.m_nlcon; i++)
result->nlconstr[i] = NAN;

return 0;
}

Expand Down Expand Up @@ -238,12 +234,19 @@ int prima_minimize(const prima_algorithm_t algorithm, const prima_problem_t prob
{
int use_constr = (algorithm == PRIMA_COBYLA);

int info = prima_check_problem(problem, use_constr, algorithm);
int info = prima_init_result(result, problem);

if (info == 0)
info = prima_init_result(result, problem);
info = prima_check_problem(problem, use_constr, algorithm);

if (info == 0) {
// We copy x0 into result->x only after prima_check_problem has succeeded,
// so that if prima_check_problem failed, result->x will not contained a
// seemingly valid value.
for (int i = 0; i < problem.n; i++) {
result->x[i] = problem.x0[i];
}

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, options.callback, &info);
Expand Down Expand Up @@ -275,10 +278,10 @@ int prima_minimize(const prima_algorithm_t algorithm, const prima_problem_t prob
default:
return PRIMA_INVALID_INPUT;
}

result->status = info;
result->message = prima_get_rc_string(info);
}

result->status = info;
result->message = prima_get_rc_string(info);

return info;
}
Loading