Skip to content
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ The file "hs071.py" contains a toy optimization problem. If everything is OK, py

Pyipopt is a legitimate Python module, you can inspect it by using standard Python commands like "dir" or "help". All functions in pyipopt are documented in details.

**Hessian Estimation**: since Hessian estimation is usually tedious, Ipopt can solve problems without Hessian estimation. Pyipopt also supports this feature. The file "hs071.py" demonstrates the idea. If you provide the pyipopt.create function with an "eval_h" callback function as well as the "apply_new" callback function, Ipopt will delegate the Hessian matrix calculation to your function (otherwise Ipopt will approximate Hessian for you).
**Hessian Estimation**: since Hessian estimation is usually tedious, Ipopt can solve problems without Hessian estimation. Pyipopt also supports this feature. The file "hs071.py" demonstrates the idea. If you provide the pyipopt.create function with an "eval_h" callback function Ipopt will delegate the Hessian matrix calculation to your function (otherwise Ipopt will approximate Hessian for you).

Contributing
------------
Expand Down
81 changes: 2 additions & 79 deletions src/callback.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,27 +135,10 @@ eval_f(Index n, Number * x, Bool new_x, Number * obj_value, UserDataPtr data)
// import_array ();

import_array1(FALSE);
PyObject *arrayx =
PyArray_SimpleNewFromData(1, dims, PyArray_DOUBLE, (char *)x);
PyObject *arrayx = PyArray_SimpleNewFromData(1, dims, PyArray_DOUBLE, (char *)x);
if (!arrayx)
return FALSE;

if (new_x && myowndata->apply_new_python) {
/* Call the python function to applynew */
PyObject *arg1;
arg1 = Py_BuildValue("(O)", arrayx);
PyObject *tempresult = PyObject_CallObject(
myowndata->apply_new_python, arg1);
if (tempresult == NULL) {
logger("[Error] Python function apply_new returns NULL");
PyErr_Print();
Py_DECREF(arg1);
return FALSE;
}
Py_DECREF(arg1);
Py_DECREF(tempresult);
}

PyObject *arglist;
if (user_data != NULL) {
arglist = Py_BuildValue("(OO)", arrayx, (PyObject *) user_data);
Expand Down Expand Up @@ -218,21 +201,6 @@ eval_grad_f(Index n, Number * x, Bool new_x, Number * grad_f, UserDataPtr data)
if (!arrayx)
return FALSE;

if (new_x && myowndata->apply_new_python) {
/* Call the python function to applynew */
PyObject *arg1 = Py_BuildValue("(O)", arrayx);
PyObject *tempresult = PyObject_CallObject(
myowndata->apply_new_python, arg1);
if (tempresult == NULL) {
logger("[Error] Python function apply_new returns NULL");
PyErr_Print();
Py_DECREF(arg1);
return FALSE;
}
Py_DECREF(arg1);
Py_DECREF(tempresult);
}

PyObject *arglist;
if (user_data != NULL)
arglist = Py_BuildValue("(OO)", arrayx, (PyObject *) user_data);
Expand Down Expand Up @@ -296,21 +264,6 @@ eval_g(Index n, Number * x, Bool new_x, Index m, Number * g, UserDataPtr data)
if (!arrayx)
return FALSE;

if (new_x && myowndata->apply_new_python) {
/* Call the python function to applynew */
PyObject *arg1 = Py_BuildValue("(O)", arrayx);
PyObject *tempresult = PyObject_CallObject(
myowndata->apply_new_python, arg1);
if (tempresult == NULL) {
logger("[Error] Python function apply_new returns NULL");
PyErr_Print();
Py_DECREF(arg1);
return FALSE;
}
Py_DECREF(arg1);
Py_DECREF(tempresult);
}

PyObject *arglist;
if (user_data != NULL)
arglist = Py_BuildValue("(OO)", arrayx, (PyObject *) user_data);
Expand Down Expand Up @@ -420,27 +373,11 @@ eval_jac_g(Index n, Number * x, Bool new_x,
Py_CLEAR(arglist);
//logger("[Callback:R] eval_jac_g(1)");
} else {
PyObject *arrayx =
PyArray_SimpleNewFromData(1, dims, PyArray_DOUBLE,
(char *)x);
PyObject *arrayx = PyArray_SimpleNewFromData(1, dims, PyArray_DOUBLE,(char *)x);

if (!arrayx)
return FALSE;

if (new_x && myowndata->apply_new_python) {
/* Call the python function to applynew */
PyObject *arg1 = Py_BuildValue("(O)", arrayx);
PyObject *tempresult =
PyObject_CallObject(myowndata->apply_new_python,
arg1);
if (tempresult == NULL) {
logger("[Error] Python function apply_new returns NULL");
Py_DECREF(arg1);
return FALSE;
}
Py_DECREF(arg1);
Py_DECREF(tempresult);
}
PyObject *arglist;
if (user_data != NULL)
arglist = Py_BuildValue("(OOO)",
Expand Down Expand Up @@ -586,20 +523,6 @@ eval_h(Index n, Number * x, Bool new_x, Number obj_factor,
if (!arrayx)
return FALSE;

if (new_x && myowndata->apply_new_python) {
/* Call the python function to applynew */
PyObject *arg1 = Py_BuildValue("(O)", arrayx);
PyObject *tempresult = PyObject_CallObject(
myowndata->apply_new_python, arg1);
if (tempresult == NULL) {
logger("[Error] Python function apply_new returns NULL");
PyErr_Print();
Py_DECREF(arg1);
return FALSE;
}
Py_DECREF(arg1);
Py_DECREF(tempresult);
}
dims2[0] = m;
PyObject *lagrangex = PyArray_SimpleNewFromData(
1, dims2, PyArray_DOUBLE, (char *)lambda);
Expand Down
1 change: 0 additions & 1 deletion src/hook.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ typedef struct {
PyObject *eval_g_python;
PyObject *eval_jac_g_python;
PyObject *eval_h_python;
PyObject *apply_new_python;
PyObject *eval_intermediate_callback_python;
PyObject *userdata;
} DispatchData;
Expand Down
22 changes: 2 additions & 20 deletions src/pyipoptcoremodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,6 @@ static PyObject *create(PyObject * obj, PyObject * args)
PyObject *g = NULL;
PyObject *jacg = NULL;
PyObject *h = NULL;
PyObject *applynew = NULL;

DispatchData myowndata;

Expand Down Expand Up @@ -333,18 +332,17 @@ static PyObject *create(PyObject * obj, PyObject * args)
myowndata.eval_g_python = NULL;
myowndata.eval_jac_g_python = NULL;
myowndata.eval_h_python = NULL;
myowndata.apply_new_python = NULL;
myowndata.userdata = NULL;

/* "O!", &PyArray_Type &a_x */
if (!PyArg_ParseTuple(args, "iO!O!iO!O!iiOOOO|OO:pyipoptcreate",
if (!PyArg_ParseTuple(args, "iO!O!iO!O!iiOOOO|O:pyipoptcreate",
&n, &PyArray_Type, &xL,
&PyArray_Type, &xU,
&m,
&PyArray_Type, &gL,
&PyArray_Type, &gU,
&nele_jac, &nele_hess,
&f, &gradf, &g, &jacg, &h, &applynew)) {
&f, &gradf, &g, &jacg, &h)) {
retval = NULL;
SAFE_FREE(x_L);
SAFE_FREE(x_U);
Expand Down Expand Up @@ -386,20 +384,6 @@ static PyObject *create(PyObject * obj, PyObject * args)
logger("[PyIPOPT] Ipopt will use Hessian approximation.\n");
}

if (applynew != NULL) {
if (PyCallable_Check(applynew)) {
myowndata.apply_new_python = applynew;
} else {
PyErr_SetString(PyExc_TypeError,
"Need a callable object for function applynew.");
retval = NULL;
SAFE_FREE(x_L);
SAFE_FREE(x_U);
SAFE_FREE(g_L);
SAFE_FREE(g_U);
return retval;
}
}
if (m < 0 || n < 0) {
PyErr_SetString(PyExc_TypeError, "m or n can't be negative");
retval = NULL;
Expand Down Expand Up @@ -445,7 +429,6 @@ static PyObject *create(PyObject * obj, PyObject * args)
Py_XINCREF(g);
Py_XINCREF(jacg);
Py_XINCREF(h);
Py_XINCREF(applynew);

/* create the Ipopt Problem */

Expand Down Expand Up @@ -708,7 +691,6 @@ PyObject *close_model(PyObject * self, PyObject * args)
Py_XDECREF(dp->eval_g_python);
Py_XDECREF(dp->eval_jac_g_python);
Py_XDECREF(dp->eval_h_python);
Py_XDECREF(dp->apply_new_python);

FreeIpoptProblem(obj->nlp);
obj->nlp = NULL;
Expand Down