Control: retitle python-cvxopt: glpk component doesn't work anymore
Control: severity -1 important
Control: tags -1 -moreinfo +confirmed +fixed-upstream +patch

I traced back the problem to release 4.53 of glpk [1], in February 2014.
According to policy 8.6.2, there should have been a SONAME bump to 37 in
order to have a smooth transition.

Anyway, looking at the upstream source, references to lpx_create_prob
have been changed to glp_create_prob in version 1.1.7 [2], but the
commit is not atomic and in fact huge.

Attached is a patch that replaces glpk-4.49.diff. It upgrades
src/C/glpk.c and only that from version 1.1.4 to version 1.1.7, from
upstream.

It sure resolves the import, but I don't know how to properly test it.

Julien: Can you provide a small test?


[1]
https://anonscm.debian.org/cgit/debian-science/packages/glpk.git/commit/?id=3f635b63468815873c9c33dd497dea8240d607fa

[2] commit f3ca94fb997979a54b913f95b816132f7fd44820 on
https://github.com/cvxopt/cvxopt/

-- 
Nirgal
Description: Bring glpk component to version 1.1.7
 glpk ABI has changed and some symbols are no longer available.
 .
 That patch is the complete diff between version 1.1.4 and 1.1.7, but limited to the src/C/glpk.c file.
Author: Martin Andersen <martin.skovgaard.ander...@gmail.com>
Origin: upstream
Bug-Debian: https://bugs.debian.org/780251
Forwarded: not-needed
Reviewed-By: Jean-Michel Nirgal Vourgère <jmv_...@nirgal.com>
Last-Update: 2015-03-11

Index: cvxopt-1.1.4/src/C/glpk.c
===================================================================
--- cvxopt-1.1.4.orig/src/C/glpk.c
+++ cvxopt-1.1.4/src/C/glpk.c
@@ -1,8 +1,9 @@
 /*
+ * Copyright 2012-2014 M. Andersen and L. Vandenberghe.
  * Copyright 2010-2011 L. Vandenberghe.
  * Copyright 2004-2009 J. Dahl and L. Vandenberghe.
  *
- * This file is part of CVXOPT version 1.1.4.
+ * This file is part of CVXOPT version 1.1.7.
  *
  * CVXOPT is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,76 +21,36 @@
 
 #include "cvxopt.h"
 #include "misc.h"
-#include "glpk.h"
+#include <glpk.h>
+#include <float.h>
+#include <limits.h>
 
 PyDoc_STRVAR(glpk__doc__,
     "Interface to the simplex and mixed integer LP algorithms in GLPK.\n\n"
     "The GLPK control parameters have the default values listed in \n"
-    "the GLPK documentation, except for 'LPX_K_PRESOL', which is set\n"
-    "to 1 and cannot be modified.  The other parameters can be\n"
-    "modified by making an entry in the dictionary glpk.options.\n"
-    "For example, the command glpk.options['LPX_K_MSGLEV'] = 0 turns\n"
-    "off the printed output during execution of glpk.simplex().\n"
-    "See the documentation at www.gnu.org/software/glpk/glpk.html for\n"
-    "the list of GLPK control parameters and their default values.");
+    "the GLPK documentation (section 2.8.1 for the simplex solver and \n"
+    "section 2.10.5 for the MILP solver).  The control  parameters can \n"
+    "be modified by making an entry in the dictionary glpk.options.\n"
+    "For example, glpk.options['msg_lev'] = 'GLP_MSG_OFF' turns off the \n"
+    "printed output will be turned off during execution of glpk.lp().\n"  
+    "Setting glpk.options['it_lim'] = 10 sets the simplex iteration \n"
+    "limit to 10.  Unrecognized entries in glpk.options are ignored.");
 
 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)
-#else
-static int get_param_idx(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)
+#define PYSTRING_CHECK(a) PyUnicode_Check(a)
+#define PYSTRING_COMPARE(a,b) PyUnicode_CompareWithASCIIString(a, b)
+#else
+#define PYINT_CHECK(value) PyInt_Check(value)
+#define PYINT_AS_LONG(value) PyInt_AS_LONG(value)
+#define PYSTRING_FROMSTRING(str) PyString_FromString(str)
+#define PYSTRING_CHECK(a) PyString_Check(a)
+#define PYSTRING_COMPARE(a,b) strcmp(PyString_AsString(a), b)
 #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[] =
@@ -97,13 +58,13 @@ static char doc_simplex[] =
     "(status, x, z, y) = lp(c, G, h, A, b)\n"
     "(status, x, z) = lp(c, G, h)\n\n"
     "PURPOSE\n"
-    "(status, x, z, y) = lp(c, G, h, A, b) solves the pair\n"
-    "of primal and dual LPs\n\n"
+    "(status, x, z, y) = lp(c, G, h, A, b) solves the pair of primal and\n"
+    "dual LPs\n\n"
     "    minimize    c'*x            maximize    -h'*z + b'*y\n"
     "    subject to  G*x <= h        subject to  G'*z + A'*y + c = 0\n"
     "                A*x = b                     z >= 0.\n\n"
-    "(status, x, z) = lp(c, G, h) solves the pair of primal\n"
-    "and dual LPs\n\n"
+    "(status, x, z) = lp(c, G, h) solves the pair of primal and dual LPs"
+    "\n\n"
     "    minimize    c'*x            maximize    -h'*z \n"
     "    subject to  G*x <= h        subject to  G'*z + c = 0\n"
     "                                            z >= 0.\n\n"
@@ -112,7 +73,7 @@ static char doc_simplex[] =
     "G            mxn dense or sparse 'd' matrix with m>=1\n\n"
     "h            mx1 dense 'd' matrix\n\n"
     "A            pxn dense or sparse 'd' matrix with p>=0\n\n"
-    "b            px1 dnese 'd' matrix\n\n"
+    "b            px1 dense 'd' matrix\n\n"
     "status       'optimal', 'primal infeasible', 'dual infeasible' \n"
     "             or 'unknown'\n\n"
     "x            if status is 'optimal', a primal optimal solution;\n"
@@ -121,21 +82,15 @@ static char doc_simplex[] =
     "             None otherwise";
 
 
-static PyObject *simplex(PyObject *self, PyObject *args,
-    PyObject *kwrds)
+static PyObject *simplex(PyObject *self, PyObject *args, PyObject *kwrds)
 {
     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]; 
-#if PY_MAJOR_VERSION >= 3
-    const char *keystr;
-#else
-    char *keystr;
-#endif
     char *kwlist[] = {"c", "G", "h", "A", "b", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|OO", kwlist, &c,
@@ -182,18 +137,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<n; i++){
-        lpx_set_obj_coef(lp, i+1, MAT_BUFD(c)[i]);
-        lpx_set_col_bnds(lp, i+1, LPX_FR, 0.0, 0.0);
+        glp_set_obj_coef(lp, i+1, MAT_BUFD(c)[i]);
+        glp_set_col_bnds(lp, i+1, GLP_FR, 0.0, 0.0);
     }
     for (i=0; i<m; i++)
-        lpx_set_row_bnds(lp, i+1, LPX_UP, 0.0, MAT_BUFD(h)[i]);
+        glp_set_row_bnds(lp, i+1, GLP_UP, 0.0, MAT_BUFD(h)[i]);
     for (i=0; i<p; i++)
-        lpx_set_row_bnds(lp, i+m+1, LPX_FX, MAT_BUFD(b)[i],
+        glp_set_row_bnds(lp, i+m+1, GLP_FX, MAT_BUFD(b)[i],
             MAT_BUFD(b)[i]);
 
     nnzmax = (SpMatrix_Check(G) ? SP_NNZ(G) : m*n ) +
@@ -202,7 +157,8 @@ static PyObject *simplex(PyObject *self,
     rn = (int *) calloc(nnzmax+1, sizeof(int));
     cn = (int *) calloc(nnzmax+1, sizeof(int));
     if (!a || !rn || !cn){
-        free(a);  free(rn);  free(cn);  lpx_delete_prob(lp);
+        free(a);  free(rn);  free(cn);  
+        glp_delete_prob(lp);
         return PyErr_NoMemory();
     }
 
@@ -241,153 +197,229 @@ static PyObject *simplex(PyObject *self,
             nnz++;
         }
 
-    lpx_load_matrix(lp, nnz, rn, cn, a);
+    glp_load_matrix(lp, nnz, rn, cn, a);
     free(rn);  free(cn);  free(a);
 
     if (!(t = PyTuple_New(A ? 4 : 3))){
-        lpx_delete_prob(lp);
+        glp_delete_prob(lp);
         return PyErr_NoMemory();
     }
 
     if (!(param = PyObject_GetAttrString(glpk_module, "options"))
         || !PyDict_Check(param)){
-            lpx_delete_prob(lp);
+            glp_delete_prob(lp);
             PyErr_SetString(PyExc_AttributeError,
                 "missing glpk.options dictionary");
             return NULL;
     }
 
+    glp_init_smcp(&smcp);
+
     while (PyDict_Next(param, &pos, &key, &value))
-#if PY_MAJOR_VERSION >= 3
-        if ((PyUnicode_Check(key)) && 
-            get_param_idx(_PyUnicode_AsString(key), &param_id, 
-            &param_type)){
-            keystr = _PyUnicode_AsString(key);
-#else
-        if ((keystr = PyString_AsString(key)) && get_param_idx(keystr,
-            &param_id, &param_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){
-#endif
-                    PyErr_Warn(PyExc_UserWarning, "ignoring value of "
-                        "GLPK parameter 'LPX_K_PRESOL'");
+        if (PYSTRING_CHECK(key)){
+            if (!PYSTRING_COMPARE(key, "msg_lev"))
+                if (PYSTRING_CHECK(value)){
+                    if (!PYSTRING_COMPARE(value, "GLP_MSG_OFF"))
+                        smcp.msg_lev = GLP_MSG_OFF;
+                    else if (!PYSTRING_COMPARE(value, "GLP_MSG_ERR")) 
+                        smcp.msg_lev = GLP_MSG_ERR;
+                    else if (!PYSTRING_COMPARE(value, "GLP_MSG_ON")) 
+                        smcp.msg_lev = GLP_MSG_ON;
+                    else if (!PYSTRING_COMPARE(value, "GLP_MSG_ALL")) 
+                        smcp.msg_lev = GLP_MSG_ALL;
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['msg_lev'] with default value", 
+                            1);
                 }
-                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));
-	    }
-    }
-    lpx_set_int_parm(lp, LPX_K_PRESOL, 1);
-    Py_DECREF(param);
-
-    switch (lpx_simplex(lp)){
-
-        case LPX_E_OK:
-
-            x = (matrix *) Matrix_New(n,1,DOUBLE);
-            z = (matrix *) Matrix_New(m,1,DOUBLE);
-            if (A) y = (matrix *) Matrix_New(p,1,DOUBLE);
-            if (!x || !z || (A && !y)){
-                Py_XDECREF(x);
-                Py_XDECREF(z);
-                Py_XDECREF(y);
-                Py_XDECREF(t);
-                lpx_delete_prob(lp);
-                return PyErr_NoMemory();
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['msg_lev'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "meth")) 
+                if (PYSTRING_CHECK(value)){
+                    if (!PYSTRING_COMPARE(value, "GLP_PRIMAL"))
+                        smcp.meth = GLP_PRIMAL;
+                    else if (!PYSTRING_COMPARE(value, "GLP_DUAL")) 
+                        smcp.meth = GLP_DUAL;
+                    else if (!PYSTRING_COMPARE(value, "GLP_DUALP")) 
+                        smcp.meth = GLP_DUALP;
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['meth'] with default value", 1);
+                }
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['meth'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "pricing"))
+                if (PYSTRING_CHECK(value)){
+                    if (!PYSTRING_COMPARE(value, "GLP_PT_STD"))
+                        smcp.pricing = GLP_PT_STD;
+                    else if (!PYSTRING_COMPARE(value, "GLP_PT_PSE")) 
+                        smcp.pricing = GLP_PT_PSE;
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['pricing'] with default value",
+                            1);
+                }
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['pricing'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "r_test"))
+                if (PYSTRING_CHECK(value)){
+                    if (!PYSTRING_COMPARE(value, "GLP_RT_STD"))
+                        smcp.r_test = GLP_RT_STD;
+                    else if (!PYSTRING_COMPARE(value, "GLP_RT_HAR")) 
+                        smcp.r_test = GLP_RT_HAR;
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['r_test'] with default value",
+                            1);
+                }
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['r_test'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "tol_bnd"))
+                if (PyFloat_Check(value))
+                    smcp.tol_bnd = PyFloat_AsDouble(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['tol_bnd'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "tol_dj"))
+                if (PyFloat_Check(value))
+                    smcp.tol_dj = PyFloat_AsDouble(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['tol_dj'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "tol_piv")) 
+                if (PyFloat_Check(value))
+                    smcp.tol_piv = PyFloat_AsDouble(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['tol_piv'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "obj_ll"))
+                if (PyFloat_Check(value))
+                    smcp.obj_ll = PyFloat_AsDouble(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['obj_ll'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "obj_ul"))
+                if (PyFloat_Check(value))
+                    smcp.obj_ul = PyFloat_AsDouble(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['obj_ul'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "it_lim"))
+                if (PYINT_CHECK(value)) 
+                    smcp.it_lim = PYINT_AS_LONG(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['it_lim'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "tm_lim"))
+                if (PYINT_CHECK(value)) 
+                    smcp.tm_lim = PYINT_AS_LONG(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['tm_lim'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "out_frq"))
+                if (PYINT_CHECK(value)) 
+                    smcp.out_frq = PYINT_AS_LONG(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['out_frq'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "out_dly"))
+                if (PYINT_CHECK(value)) 
+                    smcp.out_dly = PYINT_AS_LONG(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['out_dly'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "presolve")){
+                if (PYSTRING_CHECK(value)) {
+                    if (!PYSTRING_COMPARE(value, "GLP_ON"))
+                        smcp.presolve = GLP_ON;
+                    else if (!PYSTRING_COMPARE(value, "GLP_OFF")) 
+                        smcp.presolve = GLP_OFF;
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['presolve'] with default value",
+                            1);
+                }
+                else 
+                    PyErr_WarnEx(NULL, "replacing "
+                        "glpk.options['presolve'] with default value", 1);
             }
+        }    
 
-            PyTuple_SET_ITEM(t, 0, (PyObject *)
-#if PY_MAJOR_VERSION >= 3
-                PyUnicode_FromString("optimal"));
-#else
-                PyString_FromString("optimal"));
-#endif
-
-            for (i=0; i<n; i++)
-                MAT_BUFD(x)[i] = lpx_get_col_prim(lp, i+1);
-            PyTuple_SET_ITEM(t, 1, (PyObject *) x);
+    Py_DECREF(param);
 
-            for (i=0; i<m; i++)
-                MAT_BUFD(z)[i] = -lpx_get_row_dual(lp, i+1);
-            PyTuple_SET_ITEM(t, 2, (PyObject *) z);
+    switch (glp_simplex(lp, &smcp)){
 
-            if (A){
-                for (i=0; i<p; i++)
-                    MAT_BUFD(y)[i] = -lpx_get_row_dual(lp, m+i+1);
-                PyTuple_SET_ITEM(t, 3, (PyObject *) y);
+        case 0:
+            switch(glp_get_status(lp)){
+                case GLP_OPT:
+                    x = (matrix *) Matrix_New(n,1,DOUBLE);
+                    z = (matrix *) Matrix_New(m,1,DOUBLE);
+                    if (A) y = (matrix *) Matrix_New(p,1,DOUBLE);
+                    if (!x || !z || (A && !y)){
+                        Py_XDECREF(x);
+                        Py_XDECREF(z);
+                        Py_XDECREF(y);
+                        Py_XDECREF(t);
+                        glp_delete_prob(lp);
+                        return PyErr_NoMemory();
+                    }
+
+                    PyTuple_SET_ITEM(t, 0, (PyObject *)
+                        PYSTRING_FROMSTRING("optimal"));
+
+                    for (i=0; i<n; i++)
+                        MAT_BUFD(x)[i] = glp_get_col_prim(lp, i+1);
+                    PyTuple_SET_ITEM(t, 1, (PyObject *) x);
+
+                    for (i=0; i<m; i++)
+                        MAT_BUFD(z)[i] = -glp_get_row_dual(lp, i+1);
+                    PyTuple_SET_ITEM(t, 2, (PyObject *) z);
+
+                    if (A){
+                        for (i=0; i<p; i++)
+                            MAT_BUFD(y)[i] = -glp_get_row_dual(lp, m+i+1);
+                        PyTuple_SET_ITEM(t, 3, (PyObject *) y);
+                    }
+                    glp_delete_prob(lp);
+                    return (PyObject *) t;
+                    break;
+
+                case GLP_NOFEAS:
+                    PyTuple_SET_ITEM(t, 0, (PyObject *)
+                        PYSTRING_FROMSTRING("primal infeasible"));
+                    break;
+
+                case GLP_UNBND:
+                    PyTuple_SET_ITEM(t, 0, (PyObject *)
+                        PYSTRING_FROMSTRING("dual infeasible"));
+                    break;
+
+                default: 
+                    PyTuple_SET_ITEM(t, 0, (PyObject *)
+                        PYSTRING_FROMSTRING("unknown"));
             }
+            break;
 
-            lpx_delete_prob(lp);
-            return (PyObject *) t;
-
-        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;
 
         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(""));
@@ -405,21 +437,25 @@ static char doc_integer[] =
     "    minimize    c'*x\n"
     "    subject to  G*x <= h\n"
     "                A*x = b\n"
-    "                x[I] are all integer\n"
-    "                x[B] are all binary\n\n"
+    "                x[k] is integer for k in I\n"
+    "                x[k] is binary for k in B\n\n"
     "ARGUMENTS\n"
     "c            nx1 dense 'd' matrix with n>=1\n\n"
     "G            mxn dense or sparse 'd' matrix with m>=1\n\n"
     "h            mx1 dense 'd' matrix\n\n"
     "A            pxn dense or sparse 'd' matrix with p>=0\n\n"
     "b            px1 dense 'd' matrix\n\n"
-    "I            set with indices of integer variables\n\n"
-    "B            set with indices of binary variables\n\n"
-    "status       'optimal', 'primal infeasible', 'dual infeasible', \n"
-    "             'invalid MIP formulation', 'maxiters exceeded', \n"
-    "             'time limit exceeded', 'unknown'\n\n"
-    "x            an optimal solution if status is 'optimal';\n"
-    "             None otherwise";
+    "I            set of indices of integer variables\n\n"
+    "B            set of indices of binary variables\n\n"
+    "status       if status is 'optimal', 'feasible', or 'undefined',\n"
+    "             a value of x is returned and the status string \n"
+    "             gives the status of x.  Other possible values of "
+    "             status are:  'invalid formulation', \n"
+    "             'infeasible problem', 'LP relaxation is primal \n"
+    "             infeasible', 'LP relaxation is dual infeasible', \n"
+    "             'unknown'.\n\n"
+    "x            a (sub-)optimal solution if status is 'optimal', \n"
+    "             'feasible', or 'undefined'.  None otherwise";
 
 static PyObject *integer(PyObject *self, PyObject *args,
     PyObject *kwrds)
@@ -427,16 +463,11 @@ 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, info, status;
     int_t pos=0;
     double *a=NULL, val;
-    char param_type, err_str[100]; 
-#if PY_MAJOR_VERSION >= 3
-    const char *keystr;
-#else
-    char *keystr;
-#endif
     char *kwlist[] = {"c", "G", "h", "A", "b", "I", "B", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwrds, "OOO|OOOO", kwlist, &c,
@@ -484,23 +515,23 @@ static PyObject *integer(PyObject *self,
     }
 
     if ((IntSet) && (!PyAnySet_Check(IntSet)))
-      PY_ERR_TYPE("invalid integer index set");
+        PY_ERR_TYPE("invalid integer index set");
 
     if ((BinSet) && (!PyAnySet_Check(BinSet)))
-      PY_ERR_TYPE("invalid binary index set");
+        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<n; i++){
-        lpx_set_obj_coef(lp, i+1, MAT_BUFD(c)[i]);
-        lpx_set_col_bnds(lp, i+1, LPX_FR, 0.0, 0.0);
+        glp_set_obj_coef(lp, i+1, MAT_BUFD(c)[i]);
+        glp_set_col_bnds(lp, i+1, GLP_FR, 0.0, 0.0);
     }
     for (i=0; i<m; i++)
-        lpx_set_row_bnds(lp, i+1, LPX_UP, 0.0, MAT_BUFD(h)[i]);
+        glp_set_row_bnds(lp, i+1, GLP_UP, 0.0, MAT_BUFD(h)[i]);
     for (i=0; i<p; i++)
-        lpx_set_row_bnds(lp, i+m+1, LPX_FX, MAT_BUFD(b)[i],
+        glp_set_row_bnds(lp, i+m+1, GLP_FX, MAT_BUFD(b)[i],
             MAT_BUFD(b)[i]);
 
     nnzmax = (SpMatrix_Check(G) ? SP_NNZ(G) : m*n ) +
@@ -509,7 +540,7 @@ static PyObject *integer(PyObject *self,
     rn = (int *) calloc(nnzmax+1, sizeof(int));
     cn = (int *) calloc(nnzmax+1, sizeof(int));
     if (!a || !rn || !cn){
-        free(a);  free(rn);  free(cn);  lpx_delete_prob(lp);
+        free(a);  free(rn);  free(cn);  glp_delete_prob(lp);
         return PyErr_NoMemory();
     }
 
@@ -548,232 +579,399 @@ static PyObject *integer(PyObject *self,
             nnz++;
         }
 
-    lpx_load_matrix(lp, nnz, rn, cn, a);
+    glp_load_matrix(lp, nnz, rn, cn, a);
     free(rn);  free(cn);  free(a);
 
     if (!(t = PyTuple_New(2))) {
-        lpx_delete_prob(lp);
+        glp_delete_prob(lp);
         return PyErr_NoMemory();
     }
 
     if (!(param = PyObject_GetAttrString(glpk_module, "options"))
         || !PyDict_Check(param)){
-            lpx_delete_prob(lp);
+            glp_delete_prob(lp);
             PyErr_SetString(PyExc_AttributeError,
                 "missing glpk.options dictionary");
             return NULL;
     }
 
+    glp_init_iocp(&iocp);
+
     while (PyDict_Next(param, &pos, &key, &value))
-#if PY_MAJOR_VERSION >= 3
-        if ((PyUnicode_Check(key)) && (keystr = PyUnicode_AS_DATA(key)) 
-            && get_param_idx(keystr, &param_id, &param_type)){
-#else
-        if ((keystr = PyString_AsString(key)) && get_param_idx(keystr,
-            &param_id, &param_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){
-#endif
-                    PyErr_Warn(PyExc_UserWarning, "ignoring value of "
-                        "GLPK parameter 'LPX_K_PRESOL'");
+        if (PYSTRING_CHECK(key)){
+            if (!PYSTRING_COMPARE(key, "msg_lev"))
+                if (PYSTRING_CHECK(value)){
+                    if (!PYSTRING_COMPARE(value, "GLP_MSG_OFF"))
+                        iocp.msg_lev = GLP_MSG_OFF;
+                    else if (!PYSTRING_COMPARE(value, "GLP_MSG_ERR")) 
+                        iocp.msg_lev = GLP_MSG_ERR;
+                    else if (!PYSTRING_COMPARE(value, "GLP_MSG_ON")) 
+                        iocp.msg_lev = GLP_MSG_ON;
+                    else if (!PYSTRING_COMPARE(value, "GLP_MSG_ALL")) 
+                        iocp.msg_lev = GLP_MSG_ALL;
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['msg_lev'] with default value", 
+                            1);
                 }
                 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)){
+                    PyErr_WarnEx(NULL, "replacing glpk.options['msg_lev'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "br_tech")) 
+                if (PYSTRING_CHECK(value)){
+                    if (!PYSTRING_COMPARE(value, "GLP_BR_FFV"))
+                        iocp.br_tech= GLP_BR_FFV;
+                    else if (!PYSTRING_COMPARE(value, "GLP_BR_LFV")) 
+                        iocp.br_tech = GLP_BR_LFV;
+                    else if (!PYSTRING_COMPARE(value, "GLP_BR_MFV")) 
+                        iocp.br_tech = GLP_BR_MFV;
+                    else if (!PYSTRING_COMPARE(value, "GLP_BR_DTH")) 
+                        iocp.br_tech = GLP_BR_DTH;
+                    else if (!PYSTRING_COMPARE(value, "GLP_BR_PCH")) 
+                        iocp.br_tech = GLP_BR_PCH;
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['br_tech'] with default value", 
+                             1);
+                }
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['br_tech'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "bt_tech"))
+                if (PYSTRING_CHECK(value)){
+                    if (!PYSTRING_COMPARE(value, "GLP_BT_DFS"))
+                        iocp.bt_tech = GLP_BT_DFS;
+                    else if (!PYSTRING_COMPARE(value, "GLP_BT_BFS")) 
+                        iocp.bt_tech = GLP_BT_BFS;
+                    else if (!PYSTRING_COMPARE(value, "GLP_BT_BLB")) 
+                        iocp.bt_tech = GLP_BT_BLB;
+                    else if (!PYSTRING_COMPARE(value, "GLP_BT_BPH")) 
+                        iocp.bt_tech = GLP_BT_BPH;
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['bt_tech'] with default value",
+                            1);
+                }
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['bt_tech'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "pp_tech"))
+                if (PYSTRING_CHECK(value)){
+                    if (!PYSTRING_COMPARE(value, "GLP_PP_NONE"))
+                        iocp.pp_tech = GLP_PP_NONE;
+                    else if (!PYSTRING_COMPARE(value, "GLP_PP_ROOT")) 
+                        iocp.pp_tech = GLP_PP_ROOT;
+                    else if (!PYSTRING_COMPARE(value, "GLP_PP_ALL")) 
+                        iocp.pp_tech = GLP_PP_ALL;
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['pp_tech'] with default value",
+                            1);
+                }
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['pp_tech'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "fp_heur"))
+                if (PYSTRING_CHECK(value)){
+                    if (!PYSTRING_COMPARE(value, "GLP_ON"))
+                        iocp.fp_heur = GLP_ON;
+                    else if (!PYSTRING_COMPARE(value, "GLP_OFF")) 
+                        iocp.fp_heur = GLP_OFF;
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['fp_heur'] with default value",
+                            1);
+                }
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['fp_heur'] "
+                        "with default value", 1);
+#if 0
+            else if (!PYSTRING_COMPARE(key, "ps_heur"))
+                if (PYSTRING_CHECK(value)){
+                    if (!PYSTRING_COMPARE(value, "GLP_ON"))
+                        iocp.ps_heur = GLP_ON;
+                    else if (!PYSTRING_COMPARE(value, "GLP_OFF")) 
+                        iocp.ps_heur = GLP_OFF;
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['ps_heur'] with default value",
+                            1);
+                }
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['ps_heur'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "ps_tm_lim"))
+                if (PYINT_CHECK(value)) 
+                    iocp.ps_tm_lim = PYINT_AS_LONG(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing "
+                        "glpk.options['ps_tm_lim'] with default value", 1);
 #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));
-	    }
-    }
-    lpx_set_int_parm(lp, LPX_K_PRESOL, 1);
+            else if (!PYSTRING_COMPARE(key, "gmi_cuts"))
+                if (PYSTRING_CHECK(value)){
+                    if (!PYSTRING_COMPARE(value, "GLP_ON"))
+                        iocp.gmi_cuts = GLP_ON;
+                    else if (!PYSTRING_COMPARE(value, "GLP_OFF")) 
+                        iocp.gmi_cuts = GLP_OFF;
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['gmi_cuts'] with default value",
+                            1);
+                }
+                else 
+                    PyErr_WarnEx(NULL, "replacing "
+                        "glpk.options['gmi_cuts'] with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "mir_cuts"))
+                if (PYSTRING_CHECK(value)){
+                    if (!PYSTRING_COMPARE(value, "GLP_ON"))
+                        iocp.mir_cuts = GLP_ON;
+                    else if (!PYSTRING_COMPARE(value, "GLP_OFF")) 
+                        iocp.mir_cuts = GLP_OFF;
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['mir_cuts'] with default value",
+                            1);
+                }
+                else 
+                    PyErr_WarnEx(NULL, "replacing "
+                        "glpk.options['mir_cuts'] with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "cov_cuts"))
+                if (PYSTRING_CHECK(value)){
+                    if (!PYSTRING_COMPARE(value, "GLP_ON"))
+                        iocp.cov_cuts = GLP_ON;
+                    else if (!PYSTRING_COMPARE(value, "GLP_OFF")) 
+                        iocp.cov_cuts = GLP_OFF;
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['cov_cuts'] with default value",
+                            1);
+                }
+                else 
+                    PyErr_WarnEx(NULL, "replacing "
+                        "glpk.options['cov_cuts'] with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "clq_cuts"))
+                if (PYSTRING_CHECK(value)){
+                    if (!PYSTRING_COMPARE(value, "GLP_ON"))
+                        iocp.clq_cuts = GLP_ON;
+                    else if (!PYSTRING_COMPARE(value, "GLP_OFF")) 
+                        iocp.clq_cuts = GLP_OFF;
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['clq_cuts'] with default value",
+                            1);
+                }
+                else 
+                    PyErr_WarnEx(NULL, "replacing "
+                        "glpk.options['clq_cuts'] with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "tol_int"))
+                if (PyFloat_Check(value))
+                    iocp.tol_int = PyFloat_AsDouble(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['tol_int'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "tol_obj"))
+                if (PyFloat_Check(value))
+                    iocp.tol_obj = PyFloat_AsDouble(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['tol_obj'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "mip_gap"))
+                if (PyFloat_Check(value))
+                    iocp.mip_gap = PyFloat_AsDouble(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['mip_gap'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "tm_lim"))
+                if (PYINT_CHECK(value)) 
+                    iocp.tm_lim = PYINT_AS_LONG(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['tm_lim'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "out_frq"))
+                if (PYINT_CHECK(value)) 
+                    iocp.out_frq = PYINT_AS_LONG(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['out_frq'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "out_dly"))
+                if (PYINT_CHECK(value)) 
+                    iocp.out_dly = PYINT_AS_LONG(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['out_dly'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "glp_tree"))
+                PyErr_WarnEx(NULL, "replacing glpk.options['glp_tree'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "cb_info"))
+                PyErr_WarnEx(NULL, "replacing glpk.options['cb_info'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "cb_size"))
+                if (PYINT_CHECK(value)) 
+                    iocp.cb_size = PYINT_AS_LONG(value);
+                else 
+                    PyErr_WarnEx(NULL, "replacing glpk.options['cb_size'] "
+                        "with default value", 1);
+            else if (!PYSTRING_COMPARE(key, "presolve"))
+                if (PYSTRING_CHECK(value)) {
+                    if (!PYSTRING_COMPARE(value, "GLP_ON"))
+                        iocp.presolve = GLP_ON;
+                    else if (!PYSTRING_COMPARE(value, "GLP_OFF")){
+                        iocp.presolve = GLP_ON;
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['presolve'] with GLP_ON", 1);
+                    }
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['presolve'] with GLP_ON", 1);
+                }
+                else 
+                    PyErr_WarnEx(NULL, "replacing "
+                        "glpk.options['presolve'] with GLP_ON", 1);
+            else if (!PYSTRING_COMPARE(key, "binarize")) {
+                if (PYSTRING_CHECK(value)) {
+                    if (!PYSTRING_COMPARE(value, "GLP_ON"))
+                        iocp.binarize = GLP_ON;
+                    else if (!PYSTRING_COMPARE(value, "GLP_OFF")) 
+                        iocp.binarize = GLP_OFF;
+                    else 
+                        PyErr_WarnEx(NULL, "replacing "
+                            "glpk.options['binarize'] with default "
+                            "value", 1);
+                }
+                else 
+                    PyErr_WarnEx(NULL, "replacing "
+                        "glpk.options['binarize'] with default value", 1);
+            }
+        }
+
     Py_DECREF(param);
+    iocp.presolve = GLP_ON;
 
     if (IntSet) {
-      PyObject *iter = PySequence_Fast(IntSet, "Critical error: not sequence");
-
-      for (i=0; i<PySet_GET_SIZE(IntSet); i++) {
-
-	PyObject *tmp = PySequence_Fast_GET_ITEM(iter, i);
-#if PY_MAJOR_VERSION >= 3
-	if (!PyLong_Check(tmp)) {
-#else
-	if (!PyInt_Check(tmp)) {
-#endif
-	  lpx_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
-	if ((k < 0) || (k >= n)) {
-	  lpx_delete_prob(lp);
-	  Py_DECREF(iter);
-	  PY_ERR(PyExc_IndexError, "index element out of range in I");
-	}
-	glp_set_col_kind(lp, k+1, GLP_IV);
-      }
-
-      Py_DECREF(iter);
+        PyObject *iter = PySequence_Fast(IntSet, 
+            "Critical error: not sequence");
+        for (i=0; i<PySet_GET_SIZE(IntSet); i++) {
+            PyObject *tmp = PySequence_Fast_GET_ITEM(iter, i);
+            if (!PYINT_CHECK(tmp)) {
+                glp_delete_prob(lp);
+                Py_DECREF(iter);
+                PY_ERR_TYPE("non-integer element in I");
+            }
+            int k = PYINT_AS_LONG(tmp);
+            if ((k < 0) || (k >= n)) {
+                 glp_delete_prob(lp);
+                 Py_DECREF(iter);
+                 PY_ERR(PyExc_IndexError, "index element out of range "
+                     "in I");
+            }
+            glp_set_col_kind(lp, k+1, GLP_IV);
+        }
+        Py_DECREF(iter);
     }
 
-    if (BinSet) {
-      PyObject *iter = PySequence_Fast(BinSet, "Critical error: not sequence");
-
-      for (i=0; i<PySet_GET_SIZE(BinSet); i++) {
-
-	PyObject *tmp = PySequence_Fast_GET_ITEM(iter, i);
-#if PY_MAJOR_VERSION >= 3
-	if (!PyLong_Check(tmp)) {
-#else
-	if (!PyInt_Check(tmp)) {
-#endif
-	  lpx_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
-	if ((k < 0) || (k >= n)) {
-	  lpx_delete_prob(lp);
-	  Py_DECREF(iter);
-	  PY_ERR(PyExc_IndexError, "index element out of range in B");
-	}
-	glp_set_col_kind(lp, k+1, GLP_BV);
-      }
-
-      Py_DECREF(iter);
-
+    if (BinSet){
+        PyObject *iter = PySequence_Fast(BinSet, 
+            "Critical error: not sequence");
+        for (i=0; i<PySet_GET_SIZE(BinSet); i++) {
+            PyObject *tmp = PySequence_Fast_GET_ITEM(iter, i);
+            if (!PYINT_CHECK(tmp)) {
+                glp_delete_prob(lp);
+                Py_DECREF(iter);
+                PY_ERR_TYPE("non-binary element in I");
+            }
+            int k = PYINT_AS_LONG(tmp);
+            if ((k < 0) || (k >= n)) {
+                glp_delete_prob(lp);
+                Py_DECREF(iter);
+                PY_ERR(PyExc_IndexError, 
+                    "index element out of range in B");
+	    }
+	    glp_set_col_kind(lp, k+1, GLP_BV);
+        }
+        Py_DECREF(iter);
     }
 
+    info = glp_intopt(lp, &iocp);
+    status = glp_mip_status(lp);
 
+    switch (info){
 
-    switch (lpx_intopt(lp)){
-
-        case LPX_E_OK:
-
-            x = (matrix *) Matrix_New(n,1,DOUBLE);
-            if (!x) {
-                Py_XDECREF(t);
-                lpx_delete_prob(lp);
-                return PyErr_NoMemory();
+        case 0:
+        case GLP_EMIPGAP:
+        case GLP_ETMLIM:
+            switch(status){
+                case GLP_OPT:     /* x is optimal */
+                case GLP_FEAS:    /* x is integer feasible */
+                case GLP_UNDEF:   /* x is undefined */
+                    x = (matrix *) Matrix_New(n,1,DOUBLE);
+                    if (!x) {
+                        Py_XDECREF(t);
+                        glp_delete_prob(lp);
+                        return PyErr_NoMemory();
+                    }
+                    if (status == GLP_OPT)
+                        PyTuple_SET_ITEM(t, 0, 
+                            (PyObject *) PYSTRING_FROMSTRING("optimal"));
+                    else if (status == GLP_FEAS)
+                        PyTuple_SET_ITEM(t, 0, 
+                           (PyObject *)PYSTRING_FROMSTRING("feasible"));
+                    else 
+                        PyTuple_SET_ITEM(t, 0, 
+                           (PyObject *)PYSTRING_FROMSTRING("undefined"));
+                    for (i=0; i<n; i++)
+                        MAT_BUFD(x)[i] = glp_mip_col_val(lp, i+1);
+                    PyTuple_SET_ITEM(t, 1, (PyObject *) x);
+                    glp_delete_prob(lp);
+                    return (PyObject *) t;
+                    break;
+
+                case GLP_NOFEAS:
+                    PyTuple_SET_ITEM(t, 0, (PyObject *)
+                        PYSTRING_FROMSTRING("infeasible problem"));
+                    PyTuple_SET_ITEM(t, 1, Py_BuildValue(""));
+                    break;
+
+                default: 
+                    PyTuple_SET_ITEM(t, 1, Py_BuildValue(""));
+                    PyTuple_SET_ITEM(t, 0, (PyObject *)
+                        PYSTRING_FROMSTRING("unknown"));
             }
-            PyTuple_SET_ITEM(t, 0, (PyObject *)
-#if PY_MAJOR_VERSION >= 3
-                PyUnicode_FromString("optimal"));
-#else
-                PyString_FromString("optimal"));
-#endif
-
-            for (i=0; i<n; i++)
-                MAT_BUFD(x)[i] = lpx_mip_col_val(lp, i+1);
-            PyTuple_SET_ITEM(t, 1, (PyObject *) x);
-
-            lpx_delete_prob(lp);
-            return (PyObject *) t;
+            break;
 
-        case LPX_E_FAULT:
-            PyTuple_SET_ITEM(t, 0, (PyObject *)
-#if PY_MAJOR_VERSION >= 3
-                PyUnicode_FromString("invalid MIP formulation"));
-#else
-                PyString_FromString("invalid MIP formulation"));
-#endif
+#if 0
+        case GLP_EBADB:
 
-	case LPX_E_NOPFS:
-            PyTuple_SET_ITEM(t, 0, (PyObject *)
-#if PY_MAJOR_VERSION >= 3
-                PyUnicode_FromString("primal infeasible"));
-#else
-                PyString_FromString("primal infeasible"));
+        case GLP_ECOND:
 #endif
 
-	case LPX_E_NODFS:
-
+        case GLP_EBOUND:
             PyTuple_SET_ITEM(t, 0, (PyObject *)
-#if PY_MAJOR_VERSION >= 3
-                PyUnicode_FromString("dual infeasible"));
-#else
-                PyString_FromString("dual infeasible"));
-#endif
-
-        case LPX_E_ITLIM:
+                PYSTRING_FROMSTRING("invalid MIP formulation"));
+            break;
 
+        case GLP_ENOPFS:
             PyTuple_SET_ITEM(t, 0, (PyObject *)
-#if PY_MAJOR_VERSION >= 3
-                PyUnicode_FromString("maxiters exceeded"));
-#else
-                PyString_FromString("maxiters exceeded"));
-#endif
-
-        case LPX_E_TMLIM:
+                PYSTRING_FROMSTRING("LP relaxation is primal infeasible"));
+            break;
 
+	case GLP_ENODFS:
             PyTuple_SET_ITEM(t, 0, (PyObject *)
-#if PY_MAJOR_VERSION >= 3
-                PyUnicode_FromString("time limit exceeded"));
-#else
-                PyString_FromString("time limit exceeded"));
-#endif
-
-	case LPX_E_SING:
+                PYSTRING_FROMSTRING("LP relaxation is dual infeasible"));
+            break;
 
+	case GLP_EFAIL:
             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("solver failure"));
+            break;
 
+        case GLP_EROOT: /* only occurs if presolver is off */
+        case GLP_ESTOP: /* only occurs when advanced interface is used */
         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;
 }

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to