From da369863187bc63ef034d4d541e9c5304f23c588 Mon Sep 17 00:00:00 2001 From: Jerry James Date: Jul 31 2013 18:29:08 +0000 Subject: New glpk drops obsolete API; add -glpk patch to move to new API. --- diff --git a/python-cvxopt-glpk.patch b/python-cvxopt-glpk.patch new file mode 100644 index 0000000..6244044 --- /dev/null +++ b/python-cvxopt-glpk.patch @@ -0,0 +1,889 @@ +--- ./src/C/glpk.c.orig 2013-07-31 12:05:27.089955661 -0600 ++++ ./src/C/glpk.c 2013-07-31 12:13:40.702115730 -0600 +@@ -22,6 +22,8 @@ + #include "cvxopt.h" + #include "misc.h" + #include ++#include ++#include + + PyDoc_STRVAR(glpk__doc__, + "Interface to the simplex and mixed integer LP algorithms in GLPK.\n\n" +@@ -36,62 +38,15 @@ PyDoc_STRVAR(glpk__doc__, + + static PyObject *glpk_module; + +-typedef struct { +- char name[20]; +- int idx; +- char type; +-} param_tuple; +- +-static const param_tuple GLPK_PARAM_LIST[] = { +- {"LPX_K_MSGLEV", LPX_K_MSGLEV, 'i'}, +- {"LPX_K_SCALE", LPX_K_SCALE, 'i'}, +- {"LPX_K_DUAL", LPX_K_DUAL, 'i'}, +- {"LPX_K_PRICE", LPX_K_PRICE, 'i'}, +- {"LPX_K_RELAX", LPX_K_RELAX, 'f'}, +- {"LPX_K_TOLBND", LPX_K_TOLBND, 'f'}, +- {"LPX_K_TOLDJ", LPX_K_TOLDJ, 'f'}, +- {"LPX_K_TOLPIV", LPX_K_TOLPIV, 'f'}, +- {"LPX_K_ROUND", LPX_K_ROUND, 'i'}, +- {"LPX_K_OBJLL", LPX_K_OBJLL, 'f'}, +- {"LPX_K_OBJUL", LPX_K_OBJUL, 'f'}, +- {"LPX_K_ITLIM", LPX_K_ITLIM, 'i'}, +- {"LPX_K_ITCNT", LPX_K_ITCNT, 'i'}, +- {"LPX_K_TMLIM", LPX_K_TMLIM, 'f'}, +- {"LPX_K_OUTFRQ", LPX_K_OUTFRQ, 'i'}, +- {"LPX_K_OUTDLY", LPX_K_OUTDLY, 'f'}, +- {"LPX_K_BRANCH", LPX_K_BRANCH, 'i'}, +- {"LPX_K_BTRACK", LPX_K_BTRACK, 'i'}, +- {"LPX_K_TOLINT", LPX_K_TOLINT, 'f'}, +- {"LPX_K_TOLOBJ", LPX_K_TOLOBJ, 'f'}, +- {"LPX_K_MPSINFO", LPX_K_MPSINFO, 'i'}, +- {"LPX_K_MPSOBJ", LPX_K_MPSOBJ, 'i'}, +- {"LPX_K_MPSORIG", LPX_K_MPSORIG, 'i'}, +- {"LPX_K_MPSWIDE", LPX_K_MPSWIDE, 'i'}, +- {"LPX_K_MPSFREE", LPX_K_MPSFREE, 'i'}, +- {"LPX_K_MPSSKIP", LPX_K_MPSSKIP, 'i'}, +- {"LPX_K_LPTORIG", LPX_K_LPTORIG, 'i'}, +- {"LPX_K_PRESOL", LPX_K_PRESOL, 'i'}, +-}; /* 28 paramaters */ +- +- + #if PY_MAJOR_VERSION >= 3 +-static int get_param_idx(const char *str, int *idx, char *type) ++#define PYINT_CHECK(value) PyLong_Check(value) ++#define PYINT_AS_LONG(value) PyLong_AS_LONG(value) ++#define PYSTRING_FROMSTRING(str) PyUnicode_FromString(str) + #else +-static int get_param_idx(char *str, int *idx, char *type) ++#define PYINT_CHECK(value) PyInt_Check(value) ++#define PYINT_AS_LONG(value) PyInt_AS_LONG(value) ++#define PYSTRING_FROMSTRING(str) PyString_FromString(str) + #endif +-{ +- int i; +- +- for (i=0; i<28; i++) { +- if (!strcmp(GLPK_PARAM_LIST[i].name, str)) { +- *idx = GLPK_PARAM_LIST[i].idx; +- *type = GLPK_PARAM_LIST[i].type; +- return 1; +- } +- } +- return 0; +-} +- + + static char doc_simplex[] = + "Solves a linear program using GLPK.\n\n" +@@ -127,11 +82,12 @@ static PyObject *simplex(PyObject *self, + { + matrix *c, *h, *b=NULL, *x=NULL, *z=NULL, *y=NULL; + PyObject *G, *A=NULL, *t=NULL, *param, *key, *value; +- LPX *lp; +- int m, n, p, i, j, k, nnz, nnzmax, *rn=NULL, *cn=NULL, param_id; ++ glp_prob *lp; ++ glp_smcp smcp; ++ int m, n, p, i, j, k, nnz, nnzmax, *rn=NULL, *cn=NULL; + int_t pos=0; + double *a=NULL, val; +- char param_type, err_str[100]; ++ char err_str[100]; + #if PY_MAJOR_VERSION >= 3 + const char *keystr; + #else +@@ -183,18 +139,18 @@ static PyObject *simplex(PyObject *self, + return NULL; + } + +- lp = lpx_create_prob(); +- lpx_add_rows(lp, m+p); +- lpx_add_cols(lp, n); ++ lp = glp_create_prob(); ++ glp_add_rows(lp, m+p); ++ glp_add_cols(lp, n); + + for (i=0; i= 3 +- if ((PyUnicode_Check(key)) && +- get_param_idx(_PyUnicode_AsString(key), ¶m_id, +- ¶m_type)){ ++ if (PyUnicode_Check(key)){ + keystr = _PyUnicode_AsString(key); + #else +- if ((keystr = PyString_AsString(key)) && get_param_idx(keystr, +- ¶m_id, ¶m_type)){ +-#endif +- if (param_type == 'i'){ +-#if PY_MAJOR_VERSION >= 3 +- if (!PyLong_Check(value)){ +-#else +- if (!PyInt_Check(value)){ +-#endif +- sprintf(err_str, "invalid value for integer " +- "GLPK parameter: %-.20s", keystr); +- PyErr_SetString(PyExc_ValueError, err_str); +- lpx_delete_prob(lp); +- Py_DECREF(param); +- return NULL; +- } +- if (!strcmp("LPX_K_PRESOL", keystr) && +-#if PY_MAJOR_VERSION >= 3 +- PyLong_AS_LONG(value) != 1){ +-#else +- PyInt_AS_LONG(value) != 1){ ++ if ((keystr = PyString_AsString(key))){ + #endif ++ if (!strcmp("LPX_K_MSGLEV", keystr)){ ++ switch (PYINT_AS_LONG(value)){ ++ case 0: smcp.msg_lev = GLP_MSG_OFF; break; ++ case 1: smcp.msg_lev = GLP_MSG_ERR; break; ++ case 2: smcp.msg_lev = GLP_MSG_ON; break; ++ case 3: smcp.msg_lev = GLP_MSG_ALL; break; ++ default: goto error; ++ } ++ } else if (!strcmp("LPX_K_SCALE", keystr)){ ++ switch(PYINT_AS_LONG(value)){ ++ case 0: glp_unscale_prob(lp); break; ++ case 1: glp_scale_prob(lp, GLP_SF_EQ); break; ++ case 2: glp_scale_prob(lp, GLP_SF_GM); break; ++ case 3: glp_scale_prob(lp, GLP_SF_GM | GLP_SF_EQ); break; ++ default: goto error; ++ } ++ } else if (!strcmp("LPX_K_DUAL", keystr)){ ++ switch(PYINT_AS_LONG(value)){ ++ case 0: smcp.meth = GLP_PRIMAL; break; ++ case 1: smcp.meth = GLP_DUAL; break; ++ default: goto error; ++ } ++ } else if (!strcmp("LPX_K_PRICE", keystr)){ ++ switch(PYINT_AS_LONG(value)){ ++ case 0: smcp.pricing = GLP_PT_STD; break; ++ case 1: smcp.pricing = GLP_PT_PSE; break; ++ default: goto error; ++ } ++ } else if (!strcmp("LPX_K_RELAX", keystr)){ ++ double relax = PyFloat_AsDouble(value); ++ if (relax < 0.0 || relax > 1.0) ++ goto error; ++ smcp.r_test = (relax == 0.0) ? GLP_RT_STD : GLP_RT_HAR; ++ } else if (!strcmp("LPX_K_TOLBND", keystr)){ ++ smcp.tol_bnd = PyFloat_AsDouble(value); ++ if (smcp.tol_bnd < DBL_EPSILON || smcp.tol_bnd > 0.001) ++ goto error; ++ } else if (!strcmp("LPX_K_TOLDJ", keystr)){ ++ smcp.tol_dj = PyFloat_AsDouble(value); ++ if (smcp.tol_dj < DBL_EPSILON || smcp.tol_dj > 0.001) ++ goto error; ++ } else if (!strcmp("LPX_K_TOLPIV", keystr)){ ++ smcp.tol_piv = PyFloat_AsDouble(value); ++ if (smcp.tol_piv < DBL_EPSILON || smcp.tol_piv > 0.001) ++ goto error; ++ } else if (!strcmp("LPX_K_ROUND", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_OBJLL", keystr)){ ++ smcp.obj_ll = PyFloat_AsDouble(value); ++ } else if (!strcmp("LPX_K_OBJUL", keystr)){ ++ smcp.obj_ul = PyFloat_AsDouble(value); ++ } else if (!strcmp("LPX_K_ITLIM", keystr)){ ++ smcp.it_lim = PYINT_AS_LONG(value); ++ if (smcp.it_lim < 0) ++ smcp.it_lim = INT_MAX; ++ } else if (!strcmp("LPX_K_ITCNT", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_TMLIM", keystr)){ ++ smcp.tm_lim = (int)(PyFloat_AsDouble(value) * 1000.0); ++ if (smcp.tm_lim < 0) ++ smcp.tm_lim = INT_MAX; ++ } else if (!strcmp("LPX_K_OUTFRQ", keystr)){ ++ smcp.out_frq = PYINT_AS_LONG(value); ++ if (smcp.out_frq <= 0) ++ goto error; ++ } else if (!strcmp("LPX_K_OUTDLY", keystr)){ ++ smcp.out_dly = (int)(PyFloat_AsDouble(value) * 1000.0); ++ } else if (!strcmp("LPX_K_BRANCH", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_BTRACK", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_TOLINT", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_TOLOBJ", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_MPSINFO", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_MPSOBJ", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_MPSORIG", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_MPSWIDE", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_MPSFREE", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_MPSSKIP", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_LPTORIG", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_PRESOL", keystr)){ ++ if (PYINT_AS_LONG(value) != 1) + PyErr_Warn(PyExc_UserWarning, "ignoring value of " + "GLPK parameter 'LPX_K_PRESOL'"); ++ } else if (!strcmp("LPX_K_BINARIZE", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_USECUTS", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_BFTYPE", keystr)){ ++ glp_bfcp bfcp; ++ ++ glp_get_bfcp(lp, &bfcp); ++ switch(PYINT_AS_LONG(value)){ ++ case 1: bfcp.type = GLP_BF_FT; break; ++ case 2: bfcp.type = GLP_BF_BG; break; ++ case 3: bfcp.type = GLP_BF_GR; break; ++ default: goto error; + } +- else lpx_set_int_parm(lp, param_id, +-#if PY_MAJOR_VERSION >= 3 +- PyLong_AS_LONG(value)); +-#else +- PyInt_AS_LONG(value)); +-#endif +- } +- else { +-#if PY_MAJOR_VERSION >= 3 +- if (!PyLong_Check(value) && !PyFloat_Check(value)){ +-#else +- if (!PyInt_Check(value) && !PyFloat_Check(value)){ +-#endif +- sprintf(err_str, "invalid value for floating point " +- "GLPK parameter: %-.20s", keystr); +- PyErr_SetString(PyExc_ValueError, err_str); +- lpx_delete_prob(lp); +- Py_DECREF(param); +- return NULL; +- } +- lpx_set_real_parm(lp, param_id, +- PyFloat_AsDouble(value)); ++ glp_set_bfcp(lp, &bfcp); ++ } else if (!strcmp("LPX_K_MIPGAP", keystr)){ ++ /* Ignored */ ++ } else { ++ sprintf(err_str, "unknown GLPK parameter: %-.20s", keystr); ++ PyErr_SetString(PyExc_ValueError, err_str); ++ glp_delete_prob(lp); ++ Py_DECREF(param); ++ return NULL; + } ++ } + } +- lpx_set_int_parm(lp, LPX_K_PRESOL, 1); ++ smcp.presolve = GLP_ON; + Py_DECREF(param); + +- switch (lpx_simplex(lp)){ ++ switch (glp_simplex(lp, &smcp)){ + +- case LPX_E_OK: ++ case 0: + + x = (matrix *) Matrix_New(n,1,DOUBLE); + z = (matrix *) Matrix_New(m,1,DOUBLE); +@@ -329,71 +356,61 @@ static PyObject *simplex(PyObject *self, + Py_XDECREF(z); + Py_XDECREF(y); + Py_XDECREF(t); +- lpx_delete_prob(lp); ++ glp_delete_prob(lp); + return PyErr_NoMemory(); + } + +- PyTuple_SET_ITEM(t, 0, (PyObject *) +-#if PY_MAJOR_VERSION >= 3 +- PyUnicode_FromString("optimal")); +-#else +- PyString_FromString("optimal")); +-#endif ++ PyTuple_SET_ITEM(t, 0, (PyObject *)PYSTRING_FROMSTRING("optimal")); + + for (i=0; i= 3 +- PyUnicode_FromString("primal infeasible")); +-#else +- PyString_FromString("primal infeasible")); +-#endif ++ PYSTRING_FROMSTRING("primal infeasible")); + break; + +- case LPX_E_NODFS: ++ case GLP_ENODFS: + + PyTuple_SET_ITEM(t, 0, (PyObject *) +-#if PY_MAJOR_VERSION >= 3 +- PyUnicode_FromString("dual infeasible")); +-#else +- PyString_FromString("dual infeasible")); +-#endif ++ PYSTRING_FROMSTRING("dual infeasible")); + break; + + default: + + PyTuple_SET_ITEM(t, 0, (PyObject *) +-#if PY_MAJOR_VERSION >= 3 +- PyUnicode_FromString("unknown")); +-#else +- PyString_FromString("unknown")); +-#endif ++ PYSTRING_FROMSTRING("unknown")); + } + +- lpx_delete_prob(lp); ++ glp_delete_prob(lp); + + PyTuple_SET_ITEM(t, 1, Py_BuildValue("")); + PyTuple_SET_ITEM(t, 2, Py_BuildValue("")); + if (A) PyTuple_SET_ITEM(t, 3, Py_BuildValue("")); + + return (PyObject *) t; ++ ++error: ++ sprintf(err_str, "invalid value for GLPK parameter: %-.20s", keystr); ++ PyErr_SetString(PyExc_ValueError, err_str); ++ glp_delete_prob(lp); ++ Py_DECREF(param); ++ return NULL; + } + + +@@ -428,11 +445,12 @@ static PyObject *integer(PyObject *self, + matrix *c, *h, *b=NULL, *x=NULL; + PyObject *G, *A=NULL, *IntSet=NULL, *BinSet = NULL; + PyObject *t=NULL, *param, *key, *value; +- LPX *lp; +- int m, n, p, i, j, k, nnz, nnzmax, *rn=NULL, *cn=NULL, param_id; ++ glp_prob *lp; ++ glp_iocp iocp; ++ int m, n, p, i, j, k, nnz, nnzmax, *rn=NULL, *cn=NULL; + int_t pos=0; + double *a=NULL, val; +- char param_type, err_str[100]; ++ char err_str[100]; + #if PY_MAJOR_VERSION >= 3 + const char *keystr; + #else +@@ -490,18 +508,18 @@ static PyObject *integer(PyObject *self, + if ((BinSet) && (!PyAnySet_Check(BinSet))) + PY_ERR_TYPE("invalid binary index set"); + +- lp = lpx_create_prob(); +- lpx_add_rows(lp, m+p); +- lpx_add_cols(lp, n); ++ lp = glp_create_prob(); ++ glp_add_rows(lp, m+p); ++ glp_add_cols(lp, n); + + for (i=0; i= 3 +- if ((PyUnicode_Check(key)) && (keystr = PyUnicode_AS_DATA(key)) +- && get_param_idx(keystr, ¶m_id, ¶m_type)){ +-#else +- if ((keystr = PyString_AsString(key)) && get_param_idx(keystr, +- ¶m_id, ¶m_type)){ +-#endif +- if (param_type == 'i'){ +-#if PY_MAJOR_VERSION >= 3 +- if (!PyLong_Check(value)){ +-#else +- if (!PyInt_Check(value)){ +-#endif +- sprintf(err_str, "invalid value for integer " +- "GLPK parameter: %-.20s", keystr); +- PyErr_SetString(PyExc_ValueError, err_str); +- lpx_delete_prob(lp); +- Py_DECREF(param); +- return NULL; +- } +- if (!strcmp("LPX_K_PRESOL", keystr) && ++ glp_init_iocp(&iocp); ++ while (PyDict_Next(param, &pos, &key, &value)) { + #if PY_MAJOR_VERSION >= 3 +- PyLong_AS_LONG(value) != 1){ ++ if ((PyUnicode_Check(key)) && (keystr = PyUnicode_AS_DATA(key))){ + #else +- PyInt_AS_LONG(value) != 1){ ++ if ((keystr = PyString_AsString(key))){ + #endif ++ if (!strcmp("LPX_K_MSGLEV", keystr)){ ++ switch (PYINT_AS_LONG(value)){ ++ case 0: iocp.msg_lev = GLP_MSG_OFF; break; ++ case 1: iocp.msg_lev = GLP_MSG_ERR; break; ++ case 2: iocp.msg_lev = GLP_MSG_ON; break; ++ case 3: iocp.msg_lev = GLP_MSG_ALL; break; ++ default: goto error; ++ } ++ } else if (!strcmp("LPX_K_SCALE", keystr)){ ++ switch(PYINT_AS_LONG(value)){ ++ case 0: glp_unscale_prob(lp); break; ++ case 1: glp_scale_prob(lp, GLP_SF_EQ); break; ++ case 2: glp_scale_prob(lp, GLP_SF_GM); break; ++ case 3: glp_scale_prob(lp, GLP_SF_GM | GLP_SF_EQ); break; ++ default: goto error; ++ } ++ } else if (!strcmp("LPX_K_DUAL", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_PRICE", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_RELAX", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_TOLBND", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_TOLDJ", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_TOLPIV", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_ROUND", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_OBJLL", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_OBJUL", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_ITLIM", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_ITCNT", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_TMLIM", keystr)){ ++ iocp.tm_lim = (int)(PyFloat_AsDouble(value) * 1000.0); ++ if (iocp.tm_lim < 0) ++ iocp.tm_lim = INT_MAX; ++ } else if (!strcmp("LPX_K_OUTFRQ", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_OUTDLY", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_BRANCH", keystr)){ ++ switch(PYINT_AS_LONG(value)){ ++ case 0: iocp.br_tech = GLP_BR_FFV; break; ++ case 1: iocp.br_tech = GLP_BR_LFV; break; ++ case 2: iocp.br_tech = GLP_BR_DTH; break; ++ case 3: iocp.br_tech = GLP_BR_MFV; break; ++ default: goto error; ++ } ++ } else if (!strcmp("LPX_K_BTRACK", keystr)){ ++ switch(PYINT_AS_LONG(value)){ ++ case 0: iocp.bt_tech = GLP_BT_DFS; break; ++ case 1: iocp.bt_tech = GLP_BT_BFS; break; ++ case 2: iocp.bt_tech = GLP_BT_BPH; break; ++ case 3: iocp.bt_tech = GLP_BT_BLB; break; ++ default: goto error; ++ } ++ } else if (!strcmp("LPX_K_TOLINT", keystr)){ ++ iocp.tol_int = PyFloat_AsDouble(value); ++ if (iocp.tol_int < DBL_EPSILON || iocp.tol_int > 0.001) ++ goto error; ++ } else if (!strcmp("LPX_K_TOLOBJ", keystr)){ ++ iocp.tol_obj = PyFloat_AsDouble(value); ++ if (iocp.tol_obj < DBL_EPSILON || iocp.tol_obj > 0.001) ++ goto error; ++ } else if (!strcmp("LPX_K_MPSINFO", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_MPSOBJ", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_MPSORIG", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_MPSWIDE", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_MPSFREE", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_MPSSKIP", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_LPTORIG", keystr)){ ++ /* Ignored */ ++ } else if (!strcmp("LPX_K_PRESOL", keystr)){ ++ if (PYINT_AS_LONG(value) != 1) + PyErr_Warn(PyExc_UserWarning, "ignoring value of " + "GLPK parameter 'LPX_K_PRESOL'"); ++ } else if (!strcmp("LPX_K_BINARIZE", keystr)){ ++ iocp.binarize = (PYINT_AS_LONG(value) == 0) ? GLP_OFF : GLP_ON; ++ } else if (!strcmp("LPX_K_USECUTS", keystr)){ ++ int cuts = PYINT_AS_LONG(value); ++ if (cuts & ~0xFF) ++ goto error; ++ iocp.cov_cuts = (cuts & 1) ? GLP_ON : GLP_OFF; ++ iocp.clq_cuts = (cuts & 2) ? GLP_ON : GLP_OFF; ++ iocp.gmi_cuts = (cuts & 4) ? GLP_ON : GLP_OFF; ++ iocp.mir_cuts = (cuts & 8) ? GLP_ON : GLP_OFF; ++ } else if (!strcmp("LPX_K_BFTYPE", keystr)){ ++ glp_bfcp bfcp; ++ ++ glp_get_bfcp(lp, &bfcp); ++ switch(PYINT_AS_LONG(value)){ ++ case 1: bfcp.type = GLP_BF_FT; break; ++ case 2: bfcp.type = GLP_BF_BG; break; ++ case 3: bfcp.type = GLP_BF_GR; break; ++ default: goto error; + } +- else +-#if PY_MAJOR_VERSION >= 3 +- lpx_set_int_parm(lp, param_id, PyLong_AS_LONG(value)); +-#else +- lpx_set_int_parm(lp, param_id, PyInt_AS_LONG(value)); +-#endif +- } +- else { +-#if PY_MAJOR_VERSION >= 3 +- if (!PyLong_Check(value) && !PyFloat_Check(value)){ +-#else +- if (!PyInt_Check(value) && !PyFloat_Check(value)){ +-#endif +- sprintf(err_str, "invalid value for floating point " +- "GLPK parameter: %-.20s", keystr); +- PyErr_SetString(PyExc_ValueError, err_str); +- lpx_delete_prob(lp); +- Py_DECREF(param); +- return NULL; +- } +- lpx_set_real_parm(lp, param_id, +- PyFloat_AsDouble(value)); ++ glp_set_bfcp(lp, &bfcp); ++ } else if (!strcmp("LPX_K_MIPGAP", keystr)){ ++ iocp.mip_gap = PyFloat_AsDouble(value); ++ if (iocp.mip_gap < 0.0) ++ goto error; ++ } else { ++ sprintf(err_str, "unknown GLPK parameter: %-.20s", keystr); ++ PyErr_SetString(PyExc_ValueError, err_str); ++ glp_delete_prob(lp); ++ Py_DECREF(param); ++ return NULL; + } ++ } + } +- lpx_set_int_parm(lp, LPX_K_PRESOL, 1); ++ iocp.presolve = GLP_ON; + Py_DECREF(param); + + if (IntSet) { +@@ -628,22 +721,14 @@ static PyObject *integer(PyObject *self, + for (i=0; i= 3 +- if (!PyLong_Check(tmp)) { +-#else +- if (!PyInt_Check(tmp)) { +-#endif +- lpx_delete_prob(lp); ++ if (!PYINT_CHECK(tmp)) { ++ glp_delete_prob(lp); + Py_DECREF(iter); + PY_ERR_TYPE("non-integer element in I"); + } +-#if PY_MAJOR_VERSION >= 3 +- int k = PyLong_AS_LONG(tmp); +-#else +- int k = PyInt_AS_LONG(tmp); +-#endif ++ int k = PYINT_AS_LONG(tmp); + if ((k < 0) || (k >= n)) { +- lpx_delete_prob(lp); ++ glp_delete_prob(lp); + Py_DECREF(iter); + PY_ERR(PyExc_IndexError, "index element out of range in I"); + } +@@ -659,22 +744,14 @@ static PyObject *integer(PyObject *self, + for (i=0; i= 3 +- if (!PyLong_Check(tmp)) { +-#else +- if (!PyInt_Check(tmp)) { +-#endif +- lpx_delete_prob(lp); ++ if (!PYINT_CHECK(tmp)) { ++ glp_delete_prob(lp); + Py_DECREF(iter); + PY_ERR_TYPE("non-binary element in I"); + } +-#if PY_MAJOR_VERSION >= 3 +- int k = PyLong_AS_LONG(tmp); +-#else +- int k = PyInt_AS_LONG(tmp); +-#endif ++ int k = PYINT_AS_LONG(tmp); + if ((k < 0) || (k >= n)) { +- lpx_delete_prob(lp); ++ glp_delete_prob(lp); + Py_DECREF(iter); + PY_ERR(PyExc_IndexError, "index element out of range in B"); + } +@@ -686,117 +763,92 @@ static PyObject *integer(PyObject *self, + } + + ++ switch (glp_intopt(lp, &iocp)){ + +- switch (lpx_intopt(lp)){ +- +- case LPX_E_OK: ++ case 0: + + x = (matrix *) Matrix_New(n,1,DOUBLE); + if (!x) { + Py_XDECREF(t); +- lpx_delete_prob(lp); ++ glp_delete_prob(lp); + return PyErr_NoMemory(); + } +- PyTuple_SET_ITEM(t, 0, (PyObject *) +-#if PY_MAJOR_VERSION >= 3 +- PyUnicode_FromString("optimal")); +-#else +- PyString_FromString("optimal")); +-#endif ++ PyTuple_SET_ITEM(t, 0, (PyObject *)PYSTRING_FROMSTRING("optimal")); + + for (i=0; i= 3 +- PyUnicode_FromString("time limit exceeded")); +-#else +- PyString_FromString("time limit exceeded")); +-#endif ++ PYSTRING_FROMSTRING("time limit exceeded")); + + for (i=0; i= 3 +- PyUnicode_FromString("invalid MIP formulation")); +-#else +- PyString_FromString("invalid MIP formulation")); +-#endif ++ PYSTRING_FROMSTRING("invalid MIP formulation")); + break; + +- case LPX_E_NOPFS: ++ case GLP_ENOPFS: + PyTuple_SET_ITEM(t, 0, (PyObject *) +-#if PY_MAJOR_VERSION >= 3 +- PyUnicode_FromString("primal infeasible")); +-#else +- PyString_FromString("primal infeasible")); +-#endif ++ PYSTRING_FROMSTRING("primal infeasible")); + break; + +- case LPX_E_NODFS: ++ case GLP_ENODFS: + + PyTuple_SET_ITEM(t, 0, (PyObject *) +-#if PY_MAJOR_VERSION >= 3 +- PyUnicode_FromString("dual infeasible")); +-#else +- PyString_FromString("dual infeasible")); +-#endif ++ PYSTRING_FROMSTRING("dual infeasible")); + break; + +- case LPX_E_ITLIM: ++ case GLP_EITLIM: + + PyTuple_SET_ITEM(t, 0, (PyObject *) +-#if PY_MAJOR_VERSION >= 3 +- PyUnicode_FromString("maxiters exceeded")); +-#else +- PyString_FromString("maxiters exceeded")); +-#endif ++ PYSTRING_FROMSTRING("maxiters exceeded")); + break; + +- case LPX_E_SING: ++ case GLP_ESING: + + PyTuple_SET_ITEM(t, 0, (PyObject *) +-#if PY_MAJOR_VERSION >= 3 +- PyUnicode_FromString("singular or ill-conditioned basis")); +-#else +- PyString_FromString("singular or ill-conditioned basis")); +-#endif ++ PYSTRING_FROMSTRING("singular or ill-conditioned basis")); + break; + + + default: + + PyTuple_SET_ITEM(t, 0, (PyObject *) +-#if PY_MAJOR_VERSION >= 3 +- PyUnicode_FromString("unknown")); +-#else +- PyString_FromString("unknown")); +-#endif ++ PYSTRING_FROMSTRING("unknown")); + } + +- lpx_delete_prob(lp); ++ glp_delete_prob(lp); + + PyTuple_SET_ITEM(t, 1, Py_BuildValue("")); + return (PyObject *) t; ++ ++error: ++ sprintf(err_str, "invalid value for GLPK parameter: %-.20s", keystr); ++ PyErr_SetString(PyExc_ValueError, err_str); ++ glp_delete_prob(lp); ++ Py_DECREF(param); ++ return NULL; + } + + diff --git a/python-cvxopt.spec b/python-cvxopt.spec index 607859c..4e995c5 100644 --- a/python-cvxopt.spec +++ b/python-cvxopt.spec @@ -7,10 +7,12 @@ License: GPLv3+ URL: http://cvxopt.org/ Source0: https://github.com/cvxopt/cvxopt/archive/%{version}.tar.gz # Will submit patch0 to upstream ASAP -Patch0: python-cvxopt-fixglpkinclude.patch +Patch0: %{name}-fixglpkinclude.patch # Use the system suitesparse instead of building one, and ensure the ATLAS BLAS # library is used instead of the system BLAS. -Patch1: python-cvxopt-setup.patch +Patch1: %{name}-setup.patch +# Sent upstream 31 Jul 2013. Move from obsolete glpk API to new API. +Patch2: %{name}-glpk.patch BuildRequires: atlas-devel BuildRequires: DSDP-devel @@ -66,6 +68,7 @@ on the strengths of Python as a high-level programming language. %setup -q -n cvxopt-%{version} %patch0 %patch1 +%patch2 # Fix library path if [ %{__isa_bits} = "64" ]; then @@ -132,7 +135,7 @@ cp -a examples %{buildroot}%{_datadir}/%{name}/ %changelog * Tue Jul 30 2013 Jerry James - 1.1.6-2 -- Rebuild for new glpk +- New glpk drops obsolete API; add -glpk patch to move to new API - Fix Source0 URL * Tue May 28 2013 Jerry James - 1.1.6-1