diff --git a/xbob/math/lp_interior_point.cpp b/xbob/math/lp_interior_point.cpp index 4d3424064e6cce6281a84d1cff4e3f3f22a6caf5..69432611b19f3e46ab4c2158070a916e2baf5cb7 100644 --- a/xbob/math/lp_interior_point.cpp +++ b/xbob/math/lp_interior_point.cpp @@ -14,6 +14,10 @@ #include <bob/math/LPInteriorPoint.h> #include <structmember.h> +/************************************************ + * Implementation of LPInteriorPoint base class * + ************************************************/ + PyDoc_STRVAR(s_lpinteriorpoint_str, XBOB_EXT_MODULE_PREFIX ".LPInteriorPoint"); PyDoc_STRVAR(s_lpinteriorpoint_doc, @@ -42,38 +46,19 @@ typedef struct { PyObject_HEAD /* Type-specific fields go here. */ - std::shared_ptr<bob::math::LPInteriorPoint> base; + bob::math::LPInteriorPoint* base; } PyBobMathLpInteriorPointObject; -static PyObject* PyBobMathLpInteriorPoint_new(PyTypeObject* type, PyObject*, PyObject*) { - - /* Allocates the python object itself */ - PyBobMathLpInteriorPointObject* self = (PyBobMathLpInteriorPointObject*)type->tp_alloc(type, 0); - - self->base.reset(); - - return reinterpret_cast<PyObject*>(self); - -} - static int PyBobMathLpInteriorPoint_init(PyBobMathLpInteriorPointObject* self, PyObject*, PyObject*) { PyErr_SetString(PyExc_NotImplementedError, "cannot initialize object of base type `LPInteriorPoint' - use one of the inherited classes"); - return -1; } -static void PyBobMathLpInteriorPoint_delete (PyBobMathLpInteriorPointObject* self) { - - self->base.reset(); - self->ob_type->tp_free((PyObject*)self); - -} - -PyDoc_STRVAR(s_M_str, "M"); +PyDoc_STRVAR(s_M_str, "m"); PyDoc_STRVAR(s_M_doc, "The first dimension of the problem/A matrix" ); @@ -105,7 +90,7 @@ static int PyBobMathLpInteriorPoint_setM (PyBobMathLpInteriorPointObject* self, } -PyDoc_STRVAR(s_N_str, "N"); +PyDoc_STRVAR(s_N_str, "n"); PyDoc_STRVAR(s_N_doc, "The second dimension of the problem/A matrix" ); @@ -168,7 +153,7 @@ static int PyBobMathLpInteriorPoint_setEpsilon (PyBobMathLpInteriorPointObject* } -PyDoc_STRVAR(s_lambda_str, "lambda"); +PyDoc_STRVAR(s_lambda_str, "lambda_"); PyDoc_STRVAR(s_lambda_doc, "The value of the lambda dual variable (read-only)" ); @@ -350,7 +335,7 @@ static PyObject* PyBobMathLpInteriorPoint_solve return 0; } - if (lambda->type_num != NPY_FLOAT64 || lambda->ndim != 1) { + if (lambda && (lambda->type_num != NPY_FLOAT64 || lambda->ndim != 1)) { PyErr_SetString(PyExc_TypeError, "Linear program solver only supports 64-bit floats 1D arrays for input vector `lambda'"); Py_DECREF(A); Py_DECREF(b); @@ -361,7 +346,7 @@ static PyObject* PyBobMathLpInteriorPoint_solve return 0; } - if (mu->type_num != NPY_FLOAT64 || mu->ndim != 1) { + if (mu && (mu->type_num != NPY_FLOAT64 || mu->ndim != 1)) { PyErr_SetString(PyExc_TypeError, "Linear program solver only supports 64-bit floats 1D arrays for input vector `mu'"); Py_DECREF(A); Py_DECREF(b); @@ -791,12 +776,10 @@ static PyObject* PyBobMathLpInteriorPoint_initialize_dual_lambda_mu PyBlitzArrayObject* A = 0; PyBlitzArrayObject* c = 0; - double theta = 0.; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O&d", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O&", kwlist, &PyBlitzArray_Converter, &A, - &PyBlitzArray_Converter, &c, - &theta + &PyBlitzArray_Converter, &c )) return 0; if (A->type_num != NPY_FLOAT64 || A->ndim != 2) { @@ -839,37 +822,37 @@ static PyMethodDef PyBobMathLpInteriorPoint_methods[] = { { s_reset_str, (PyCFunction)PyBobMathLpInteriorPoint_reset, - METH_NOARGS, + METH_VARARGS|METH_KEYWORDS, s_reset_doc }, { s_solve_str, (PyCFunction)PyBobMathLpInteriorPoint_solve, - METH_NOARGS, + METH_VARARGS|METH_KEYWORDS, s_solve_doc }, { s_is_feasible_str, (PyCFunction)PyBobMathLpInteriorPoint_is_feasible, - METH_NOARGS, + METH_VARARGS|METH_KEYWORDS, s_is_feasible_doc }, { s_is_in_v_str, (PyCFunction)PyBobMathLpInteriorPoint_is_in_v, - METH_NOARGS, + METH_VARARGS|METH_KEYWORDS, s_is_in_v_doc }, { s_is_in_v_s_str, (PyCFunction)PyBobMathLpInteriorPoint_is_in_v_s, - METH_NOARGS, + METH_VARARGS|METH_KEYWORDS, s_is_in_v_s_doc }, { s_initialize_dual_lambda_mu_str, (PyCFunction)PyBobMathLpInteriorPoint_initialize_dual_lambda_mu, - METH_NOARGS, + METH_VARARGS|METH_KEYWORDS, s_initialize_dual_lambda_mu_doc }, {0} /* Sentinel */ @@ -900,7 +883,7 @@ PyTypeObject PyBobMathLpInteriorPoint_Type = { s_lpinteriorpoint_str, /*tp_name*/ sizeof(PyBobMathLpInteriorPointObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ - (destructor)PyBobMathLpInteriorPoint_delete, /*tp_dealloc*/ + 0, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ @@ -933,7 +916,184 @@ PyTypeObject PyBobMathLpInteriorPoint_Type = { 0, /* tp_dictoffset */ (initproc)PyBobMathLpInteriorPoint_init, /* tp_init */ 0, /* tp_alloc */ - PyBobMathLpInteriorPoint_new, /* tp_new */ + 0, /* tp_new */ +}; + +/**************************************************** + * Implementation of LPInteriorPointShortstep class * + ****************************************************/ + +PyDoc_STRVAR(s_lpinteriorpointshortstep_str, XBOB_EXT_MODULE_PREFIX ".LPInteriorPointShortstep"); + +PyDoc_STRVAR(s_lpinteriorpointshortstep_doc, +"LPInteriorPointShortstep(M, N, theta, epsilon) -> new LPInteriorPointShortstep\n\ +\n\ +A Linear Program solver based on a short step interior point method.\n\ +\n\ +See :py:class:`LPInteriorPoint` for more details on the base class.\n\ +\n\ +Constructor parameters:\n\ +\n\ +M\n\ + (int) first dimension of the A matrix\n\ +\n\ +N\n\ + (int) second dimension of the A matrix\n\ +\n\ +theta\n\ + (float) theta The value defining the size of the V2 neighborhood\n\ +\n\ +epsilon\n\ + (float) The precision to determine whether an equality constraint\n\ + is fulfilled or not.\n\ +\n\ +"); + +/* Type definition for PyBobMathLpInteriorPointObject */ +typedef struct { + PyBobMathLpInteriorPointObject parent; + + /* Type-specific fields go here. */ + bob::math::LPInteriorPointShortstep* base; + +} PyBobMathLpInteriorPointShortstepObject; + +static int PyBobMathLpInteriorPointShortstep_init(PyBobMathLpInteriorPointShortstepObject* self, PyObject* args, PyObject* kwds) { + + /* Parses input arguments in a single shot */ + static const char* const_kwlist[] = {"M", "N", "theta", "epsilon", 0}; + static char** kwlist = const_cast<char**>(const_kwlist); + + Py_ssize_t M = 0; + Py_ssize_t N = 0; + double theta = 0.; + double epsilon = 0.; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "nndd", kwlist, + &M, &N, &theta, &epsilon)) return -1; + + self->base = new bob::math::LPInteriorPointShortstep(M, N, theta, epsilon); + if (!self->base) { + PyErr_SetString(PyExc_MemoryError, "could not allocate new LPInteriorPointShortstep object"); + return -1; + } + + self->parent.base = self->base; + + return 0; + +} + +static void PyBobMathLpInteriorPointShortstep_delete (PyBobMathLpInteriorPointShortstepObject* self) { + + delete self->base; + self->parent.base = 0; + self->base = 0; + self->parent.ob_type->tp_free((PyObject*)self); + +} + +PyDoc_STRVAR(s_theta_str, "theta"); +PyDoc_STRVAR(s_theta_doc, +"The value theta used to define a V2 neighborhood" +); + +static PyObject* PyBobMathLpInteriorPointShortstep_getTheta (PyBobMathLpInteriorPointShortstepObject* self, void* /*closure*/) { + return Py_BuildValue("d", self->base->getTheta()); +} + +static int PyBobMathLpInteriorPointShortstep_setTheta (PyBobMathLpInteriorPointShortstepObject* self, + PyObject* o, void* /*closure*/) { + + double e = PyFloat_AsDouble(o); + if (PyErr_Occurred()) return -1; + + try { + self->base->setTheta(e); + } + catch (std::exception& ex) { + PyErr_SetString(PyExc_RuntimeError, ex.what()); + return -1; + } + catch (...) { + PyErr_Format(PyExc_RuntimeError, "cannot reset `theta' of LPInteriorPointShortstep: unknown exception caught"); + return -1; + } + + return 0; + +} + +static PyGetSetDef PyBobMathLpInteriorPointShortstep_getseters[] = { + { + s_theta_str, + (getter)PyBobMathLpInteriorPointShortstep_getTheta, + (setter)PyBobMathLpInteriorPointShortstep_setTheta, + s_theta_doc, + 0 + }, + {0} /* Sentinel */ +}; + +static PyObject* PyBobMathLpInteriorPointShortstep_RichCompare +(PyBobMathLpInteriorPointShortstepObject* self, PyBobMathLpInteriorPointShortstepObject* other, int op) { + + switch (op) { + case Py_EQ: + if (*(self->base) == *(other->base)) Py_RETURN_TRUE; + Py_RETURN_FALSE; + break; + case Py_NE: + if (*(self->base) != *(other->base)) Py_RETURN_TRUE; + Py_RETURN_FALSE; + break; + default: + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + +} + +PyTypeObject PyBobMathLpInteriorPointShortstep_Type = { + PyObject_HEAD_INIT(0) + 0, /*ob_size*/ + s_lpinteriorpointshortstep_str, /*tp_name*/ + sizeof(PyBobMathLpInteriorPointShortstepObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)PyBobMathLpInteriorPointShortstep_delete, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + s_lpinteriorpointshortstep_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + (richcmpfunc)PyBobMathLpInteriorPointShortstep_RichCompare, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + PyBobMathLpInteriorPointShortstep_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)PyBobMathLpInteriorPointShortstep_init, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ }; /** @@ -947,9 +1107,6 @@ static bool is_in_vinf(bob::math::LPInteriorPointLongstep& op, void bind_math_lp_interiorpoint() { - .def(self == self) - .def(self != self) - class_<bob::math::LPInteriorPointShortstep, boost::shared_ptr<bob::math::LPInteriorPointShortstep>, bases<bob::math::LPInteriorPoint> >("LPInteriorPointShortstep", "A Linear Program solver based on a short step interior point method", init<const size_t, const size_t, const double, const double>((arg("self"), arg("M"), arg("N"), arg("theta"), arg("epsilon")), "Constructs a new LPInteriorPointShortstep solver")) .def(init<const bob::math::LPInteriorPointShortstep&>((arg("self"), arg("solver")), "Copy constructs a solver")) .def(self == self) diff --git a/xbob/math/lp_interior_point.h b/xbob/math/lp_interior_point.h index 4a32c732a4cf13e584b5957eded477742e88a5f8..bb4b75e6a70a221cf359f0e476e05a5b33dd55ae 100644 --- a/xbob/math/lp_interior_point.h +++ b/xbob/math/lp_interior_point.h @@ -8,3 +8,4 @@ #include <Python.h> extern PyTypeObject PyBobMathLpInteriorPoint_Type; +extern PyTypeObject PyBobMathLpInteriorPointShortstep_Type; diff --git a/xbob/math/main.cpp b/xbob/math/main.cpp index c2c62ce6badfa21b13ffb5783cc0676f42868af5..b89fdecb745d64beba563ebddfd446f4cfd81721 100644 --- a/xbob/math/main.cpp +++ b/xbob/math/main.cpp @@ -506,6 +506,9 @@ PyMODINIT_FUNC XBOB_EXT_ENTRY_NAME (void) { PyBobMathLpInteriorPoint_Type.tp_new = PyType_GenericNew; if (PyType_Ready(&PyBobMathLpInteriorPoint_Type) < 0) return; + PyBobMathLpInteriorPointShortstep_Type.tp_base = &PyBobMathLpInteriorPoint_Type; + if (PyType_Ready(&PyBobMathLpInteriorPointShortstep_Type) < 0) return; + PyObject* m = Py_InitModule3(XBOB_EXT_MODULE_NAME, module_methods, module_docstr); @@ -516,6 +519,9 @@ PyMODINIT_FUNC XBOB_EXT_ENTRY_NAME (void) { Py_INCREF(&PyBobMathLpInteriorPoint_Type); PyModule_AddObject(m, "LPInteriorPoint", (PyObject *)&PyBobMathLpInteriorPoint_Type); + Py_INCREF(&PyBobMathLpInteriorPointShortstep_Type); + PyModule_AddObject(m, "LPInteriorPointShortstep", (PyObject *)&PyBobMathLpInteriorPointShortstep_Type); + /* imports the NumPy C-API */ import_array(); diff --git a/xbob/math/test/test_LPInteriorPoint.py b/xbob/math/test/test_lp_interior_point.py similarity index 97% rename from xbob/math/test/test_LPInteriorPoint.py rename to xbob/math/test/test_lp_interior_point.py index 07e64c6039a672b803ce85932640b5749211d29b..840a650327d93b8e6c646ba850ed75be8890c05f 100644 --- a/xbob/math/test/test_LPInteriorPoint.py +++ b/xbob/math/test/test_lp_interior_point.py @@ -9,7 +9,7 @@ """ import os, sys -from xbob.math import LPInteriorPointShortstep, LPInteriorPointPredictorCorrector, LPInteriorPointLongstep +from xbob.math import LPInteriorPointShortstep #, LPInteriorPointPredictorCorrector, LPInteriorPointLongstep import numpy import nose.tools