Skip to content

Commit

Permalink
Merge pull request #180 from nbelakovski/always_init_result
Browse files Browse the repository at this point in the history
Always initialize the result.
  • Loading branch information
zaikunzhang authored Mar 25, 2024
2 parents 890d46d + 6460871 commit 19cf6b5
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 30 deletions.
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;
}

0 comments on commit 19cf6b5

Please sign in to comment.