#include "pounce.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct {
double p[3];
} ProblemData;
static bool eval_f(ipindex n, ipnumber *x, bool new_x,
ipnumber *obj, UserDataPtr user_data)
{
(void)new_x;
const ProblemData *d = (const ProblemData *)user_data;
double s = 0.0;
for (int j = 0; j < n; j++) {
double e = x[j] - d->p[j];
s += e * e;
}
*obj = 0.5 * s;
return true;
}
static bool eval_grad_f(ipindex n, ipnumber *x, bool new_x,
ipnumber *grad, UserDataPtr user_data)
{
(void)new_x;
const ProblemData *d = (const ProblemData *)user_data;
for (int j = 0; j < n; j++) grad[j] = x[j] - d->p[j];
return true;
}
static bool eval_g(ipindex n, ipnumber *x, bool new_x,
ipindex m, ipnumber *g, UserDataPtr user_data)
{
(void)new_x; (void)m; (void)user_data;
double s = 0.0;
for (int j = 0; j < n; j++) s += x[j];
g[0] = s;
return true;
}
static bool eval_jac_g(ipindex n, ipnumber *x, bool new_x,
ipindex m, ipindex nele_jac,
ipindex *irow, ipindex *jcol, ipnumber *values,
UserDataPtr user_data)
{
(void)x; (void)new_x; (void)m; (void)user_data;
if (irow != NULL && jcol != NULL) {
for (int j = 0; j < nele_jac; j++) {
irow[j] = 0;
jcol[j] = j;
}
}
if (values != NULL) {
for (int j = 0; j < nele_jac; j++) values[j] = 1.0;
}
return true;
}
static bool eval_h(ipindex n, ipnumber *x, bool new_x,
ipnumber obj_factor,
ipindex m, ipnumber *lambda, bool new_lambda,
ipindex nele_hess,
ipindex *irow, ipindex *jcol, ipnumber *values,
UserDataPtr user_data)
{
(void)x; (void)new_x; (void)m; (void)lambda; (void)new_lambda; (void)user_data;
if (irow != NULL && jcol != NULL) {
for (int j = 0; j < nele_hess; j++) {
irow[j] = j;
jcol[j] = j;
}
}
if (values != NULL) {
for (int j = 0; j < nele_hess; j++) values[j] = obj_factor;
}
return true;
}
static void print_step(int k, const double *p, const double *x,
int status, const IpoptBoundStatus *bounds,
const IpoptConsStatus *cons)
{
printf("step %d: p = (%6.3f, %6.3f, %6.3f) x = (%6.4f, %6.4f, %6.4f) "
"status = %d bounds = [%d,%d,%d] cons = [%d]\n",
k, p[0], p[1], p[2], x[0], x[1], x[2], status,
bounds[0], bounds[1], bounds[2], cons[0]);
}
int main(void)
{
const int n = 3, m = 1;
double x_l[3] = {0.0, 0.0, 0.0};
double x_u[3] = {1e20, 1e20, 1e20};
double g_l[1] = {1.0};
double g_u[1] = {1.0};
IpoptProblem prob = CreateIpoptProblem(
n, x_l, x_u,
m, g_l, g_u,
n,
n,
0,
eval_f, eval_g, eval_grad_f, eval_jac_g, eval_h
);
if (!prob) {
fprintf(stderr, "CreateIpoptProblem failed\n");
return 1;
}
AddIpoptStrOption(prob, "algorithm", "active-set-sqp");
AddIpoptIntOption(prob, "print_level", 0);
const double parameters[4][3] = {
{0.50, 0.40, -0.10},
{0.52, 0.39, -0.05},
{0.55, 0.37, 0.08},
{0.54, 0.38, 0.08},
};
ProblemData data;
double x[3] = {1.0 / 3, 1.0 / 3, 1.0 / 3};
double obj;
IpoptBoundStatus bounds[3];
IpoptConsStatus cons[1];
for (int k = 0; k < 4; k++) {
for (int j = 0; j < n; j++) data.p[j] = parameters[k][j];
int status;
if (k == 0) {
status = IpoptSolve(prob, x, NULL, &obj,
NULL, NULL, NULL, &data);
IpoptGetWorkingSet(prob, bounds, cons);
} else {
status = IpoptSolveWarmStart(
prob, x, NULL, &obj,
NULL, NULL, NULL,
bounds, cons,
bounds, cons,
&data
);
}
print_step(k, data.p, x, status, bounds, cons);
if (status != 0) {
fprintf(stderr, "solve failed at step %d (status %d)\n", k, status);
FreeIpoptProblem(prob);
return 1;
}
}
double s = 0.0;
for (int j = 0; j < n; j++) s += x[j];
if (fabs(s - 1.0) > 1e-6) {
fprintf(stderr, "sum(x) = %.9f != 1\n", s);
FreeIpoptProblem(prob);
return 1;
}
printf("all 4 solves succeeded; final sum(x) = %.9f\n", s);
FreeIpoptProblem(prob);
return 0;
}