3

So I am creating a Docker container with python 3.6 runtime. I need a UX64 version of lp_solver (http://lpsolve.sourceforge.net/5.5/index.htm) for python. The one linked is python 2.7. I have found the following: https://github.com/chandu-atina/lp_solve_python_3x but it does not work either. Tried both approaches. I have really no idea how to get this lp_solver to work on Ubuntu Python 3.6. Is there something like the following: https://www.lfd.uci.edu/~gohlke/pythonlibs/#lp_solve but for Ubuntu?

Also found this, which worked: https://anaconda.org/snorfalorpagus/lpsolve but I cannot import lpsolve. (here is the question linked for importing lpsolve: Conda installation of lpsolve)

EDIT 1:

Here are the steps that I take:

mkdir -p /tmp/lp_solve && cd /tmp/lp_solve

wget -O ./lp_solve.tar.gz http://sourceforge.net/projects/lpsolve/files/lpsolve/5.5.2.0/lp_solve_5.5.2.0_source.tar.gz/download

tar -xf lp_solve.tar.gz

DOWNLOAD THE REPO FROM GITHUB  (https://github.com/chandu-atina/lp_solve_python_3x )

mkdir -p /tmp/lp_solve/lp_solve_5.5/extra/

//Creates Python directory! Just make sure that origin is extra/Python

cp -R extra/Python_that_is_downloaded  /tmp/lp_solve/lp_solve_5.5/extra/ 

cd /tmp/lp_solve/lp_solve_5.5/lpsolve55

chmod a+x ccc

sh ccc

on sh ccc I get tons of syntax errors in .h files. Here:

user@user-box:/tmp/lp_solve/lp_solve_5.5/lpsolve55$ sh ccc
/tmp/platform.c:3:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
 main(){printf("ux%d", (int) (sizeof(void *)*8));}
 ^
In file included from ../lp_MDO.c:22:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_crash.c:21:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_lib.c:41:0:
../lp_lib.h:63:0: warning: "isnan" redefined
 # define isnan(x) FALSE
 ^
In file included from ../lp_lib.c:27:0:
/usr/include/math.h:292:0: note: this is the location of the previous definition
 #  define isnan(x) __builtin_isnan (x)
 ^
In file included from ../lp_wlp.c:6:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_matrix.c:3:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_mipbb.c:30:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_MPS.c:5:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_params.c:6:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_presolve.c:36:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_price.c:3:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_pricePSE.c:3:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_scale.c:3:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_simplex.c:27:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_SOS.c:3:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_utils.c:4:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
ar: lp_MDO.o: No such file or directory
In file included from ../lp_MDO.c:22:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_crash.c:21:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_lib.c:41:0:
../lp_lib.h:63:0: warning: "isnan" redefined
 # define isnan(x) FALSE
 ^
In file included from ../lp_lib.c:27:0:
/usr/include/math.h:292:0: note: this is the location of the previous definition
 #  define isnan(x) __builtin_isnan (x)
 ^
In file included from ../lp_wlp.c:6:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_matrix.c:3:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_mipbb.c:30:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_MPS.c:5:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_params.c:6:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_presolve.c:36:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_price.c:3:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_pricePSE.c:3:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_scale.c:3:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_simplex.c:27:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_SOS.c:3:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
In file included from ../lp_utils.c:4:0:
../shared/commonlib.h:88:24: error: expected identifier or ‘(’ before numeric constant
   #define FALSE        0
                        ^
cc: error: lp_MDO.o: No such file or directory
cc: error: lp_crash.o: No such file or directory
cc: error: lp_wlp.o: No such file or directory
cc: error: lp_matrix.o: No such file or directory
cc: error: lp_mipbb.o: No such file or directory
cc: error: lp_MPS.o: No such file or directory
cc: error: lp_params.o: No such file or directory
cc: error: lp_presolve.o: No such file or directory
cc: error: lp_price.o: No such file or directory
cc: error: lp_pricePSE.o: No such file or directory
cc: error: lp_scale.o: No such file or directory
cc: error: lp_simplex.o: No such file or directory
cc: error: lp_SOS.o: No such file or directory
cc: error: lp_utils.o: No such file or directory

sorry for the snippet, when I enclose in code, it gives me the errors here.

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
Naz
  • 2,012
  • 1
  • 21
  • 45
  • this works in my Docker O_o. But there is still a linking issue to the file in ux64 (that is created during sh ccc) – Naz Feb 13 '18 at 14:47
  • To get `import lp_solve` to work, I had to manually symlink `liblpsolve55.so` into a directory listed in `PYTHONPATH` (such as `site-packages`). – unutbu Feb 13 '18 at 15:31
  • how did you do it? I have this error now: >>> from lpsolve55 import * Traceback (most recent call last): File "", line 1, in ImportError: liblpsolve55.so: cannot open shared object file: No such file or directory – Naz Feb 13 '18 at 15:58
  • made it work by adding this to my Dockerfile: ENV LD_LIBRARY_PATH /usr/local/lib:/usr/lib/lp_solve/lp_solve_5.5:/usr/lib/lp_solve/lp_solve_5.5/lpsolve55/bin/ux64 – Naz Feb 13 '18 at 16:05
  • still interested in how you made it work – Naz Feb 13 '18 at 16:05
  • When I ran `python setup.py install`, it reported that `lp_solve.py` was copied into into my virtualenv `site-packages` directory. When I tried to `import lp_solve`, I got the same error: `ImportError: liblpsolve55.so: cannot open shared object file: No such file or directory`. So I symlinked `lp_solve_5.5/lpsolve55/bin/ux64/liblpsolve55.so` to `site-packages`: `ln -s /path/to/liblpsolve55.so /path/to/site-packages`. Then `import lp_solve` worked. – unutbu Feb 13 '18 at 16:15
  • For others reading this, please note that my way is **not** the correct way to solve the problem. Setting the `LD_LIBRARY_PATH` to point to the `ux64` directory (or whatever directory contains `liblpsolve55.so`) is correct. See [this page](http://lpsolve.sourceforge.net/5.5/Python.htm) (search for "cannot open shared object file") for more information. – unutbu Feb 13 '18 at 17:19
  • What about physically moving all the files to site packages? – Naz Feb 13 '18 at 17:30
  • I don't think that works -- or at least not perfectly. Symlinking `liblpsolve55.so` to `site-packages` only sort-of worked. I had to `import liblpsolve55`, which emitted an error (so I thought this was just a misstep), but I later found out that only then does `import lp_solve` work. So I think my barbarian way of making this work is incorrect. I removed the symlink, set `LD_LIBRARY_PATH` in my ~/.profile, logged out, logged back in, and then `import lp_solved` worked smoothly. – unutbu Feb 13 '18 at 18:03

1 Answers1

7

How I got lpsolve working with python 3.5.3 on raspbian:

Install from repository

apt-get install lp-solve # for shared object file (liblpsolve55.so)
apt-get install liblpsolve55-dev # for header files (e.g. lp_lib.h)

Get Python source code from sourceforge (https://sourceforge.net/projects/lpsolve/files/lpsolve/5.5.2.5/lp_solve_5.5.2.5_Python_source.tar.gz/download).

Extract the tar file

tar -xzf lp_solve_5.5.2.5_Python_source.tar.gz
cd lp_solve_5.5/extra/Python

Start the installation by running

bash build.sh

The source files had some non-python3 related issues in my case.

  1. lp_lib.h could not be found. Solved by adding '/usr/include/lpsolve' to the include_dirs in setup.py
  2. multiple defined error for functions defined in hash.c. Solved by removing the "hash.c" file from the files to be compiled and linked in setup.py.
  3. Undefined reference symamd. Solved by adding "colamd" to the libraries in setup.py

Python3 related issues:

  1. print ... has changed to print(...). Updated in setup.py
  2. PyString has changed to PyUnicode/PyBytes and PyInt to PyLong (https://docs.python.org/3/howto/cporting.html). Updated in pythonmod.c
  3. Init module function changed (https://docs.python.org/2.3/whatsnew/node20.html, Difference between PyMODINIT_FUNC and PyModule_Create and https://docs.python.org/3/c-api/module.html). Updated in pythonmod.c

setup.py diff

14c14
< print 'numpy: ' + NUMPY
---
> print('numpy: ' + NUMPY)
30c30
<               ["lpsolve.c", "hash.c", "pythonmod.c"],
---
>               ["lpsolve.c", "pythonmod.c"],
32c32
<                                 include_dirs=['../..', NUMPYPATH],
---
>                                 include_dirs=['../..', NUMPYPATH, '/usr/include/lpsolve'],
34c34
<               libraries = ["lpsolve55"])
---
>               libraries = ["lpsolve55", "colamd"])

pythonmod.c diff

35a36
> static char lpsolve_name[] = "lpsolve";
43a45,48
> static PyModuleDef lpsolve_module = { .m_base = PyModuleDef_HEAD_INIT,
> .m_name = lpsolve_name,
> .m_doc = lpsolve_doc,
> .m_methods = lpsolve_methods };
47,48c52,53
< DL_EXPORT(void)
<     initlpsolve55(void)
---
> PyMODINIT_FUNC
> PyInit_lpsolve55(void)
53c58
<     m = Py_InitModule("lpsolve55", lpsolve_methods);
---
>     m = PyModule_Create(&lpsolve_module);
85,212c90,217
<     PyDict_SetItemString(d, "LE", PyInt_FromLong(LE));
...
<     PyDict_SetItemString(d, "FULL", PyInt_FromLong(FULL));
---
>     PyDict_SetItemString(d, "LE", PyLong_FromLong(LE));
...
>     PyDict_SetItemString(d, "FULL", PyLong_FromLong(FULL));
213a219,220
> 
>     return m;
771c778
<            (PyString_AsStringAndSize(item, &ptr, &size1) != 0) ||
---
>            (PyBytes_AsStringAndSize(item, &ptr, &size1) != 0) ||
799c806
<         if (PyString_Check(vector)) {
---
>         if (PyUnicode_Check(vector)) {
824c831
<           if ((item == NULL) || (!PyString_Check(item))) {
---
>           if ((item == NULL) || (!PyUnicode_Check(item))) {
832c839
<               if ((PyString_AsStringAndSize(item, &ptr, &size1) != 0) ||
---
>               if ((PyBytes_AsStringAndSize(item, &ptr, &size1) != 0) ||
1028c1035
<                 setlhs(lpsolvecaller, element, PyString_FromString(*str));
---
>                 setlhs(lpsolvecaller, element, PyUnicode_FromString(*str));
1035c1042
<                   MyPyArray_SET_ITEM(PyObject1, i, PyString_FromString(*(str++)));
---
>                   MyPyArray_SET_ITEM(PyObject1, i, PyUnicode_FromString(*(str++)));

Verify that the install works as indicated in the documentation of lpsolve (http://lpsolve.sourceforge.net/5.5/Python.htm#Installation)

>>> from lpsolve55 import *
>>> lpsolve()