Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compatibility with optlang #1

Open
Midnighter opened this issue Oct 12, 2020 · 5 comments
Open

Compatibility with optlang #1

Midnighter opened this issue Oct 12, 2020 · 5 comments

Comments

@Midnighter
Copy link

Hi Lasse,
I was wondering if you ever tried to replace swiglpk in optlang with this package and if that worked, i.e., the optlang test suite passed, for example?

@DumData
Copy link

DumData commented Oct 15, 2020

I took a stab at it last night and which its extremely similar to the swiglpk interface its not (yet?) a drop in replacement.
The main issue I ran into (other than figuring out how to make tox work) was issues with variable types. E.g. GLPK expects a char array, but python3 by default returns a unicode string so I need to look into how swig deals with that.

@Midnighter
Copy link
Author

I see. I didn't mean to create work for you. Just wanted to know if you had tried. Thank you for checking it out 🙂

@cfblaeb
Copy link
Owner

cfblaeb commented Oct 18, 2020

Ok I did the work =)

I made no changes to the cffi_glpk interace.
I made a copy of the glpk_interface.py and test_glpk_interface.py and made a few changes:

Mainly C functions that take a "char *" cant, unlike with swig apparently, take a python3 string directly (but it should work with a python2 string). Instead it needs str.encode() to turn it into a byte array.
Likewise "char *" return values need to be converted with ffi.string which makes them byte arrays (aka a python2 string) which then needs to be str.decode() to become a python3 str.

A few places that passed a python "None" to a function needed to pass a ffi.NULL instead.
A few places where intArray or doubleArray or struct functions replaced with ffi.new()

4 function were, for unknown reasons, implemented in C in swiglpk. I reimplemented them in python
Those functions were:
get_col_primals(glp_prob *P)
get_col_duals(glp_prob *P)
get_row_primals(glp_prob *P)
get_row_duals(glp_prob *P)

Anyway after making those changes, it passed all tests and I then tried benchmarking by running the "slow tests". However the results were not exactly amazing. Number of replicates = 1 so this is absolutely not scientific but cffi was faster than swig and pypy+cffi was fastest but by so little that repeating the test might very well yield the opposite results:

py3.6 cffi 7730s
py3.6 swig 7863s
pypy3.6 cffi 7713s

@Midnighter
Copy link
Author

Wow, awesome! :)

I wouldn't necessarily expect any difference for the slow tests as those are mostly MIPs and so most of the time will be spent by the solver itself. It's actually more interesting to see the difference between swig and cffi at the Python/GLPK interface. For example, are there differences in time for creation of variables or retrieving of values (that's what those four functions are for), so a good implementation of those may be critical for scenarios where many fast problems are solved successively and where in the past moving the values into Python data structures was the bottleneck. It might also be worthwhile for optlang to create numpy arrays and let GLPK write to their memory directly, etc.

@cfblaeb
Copy link
Owner

cfblaeb commented Oct 19, 2020

If you give me a benchmarking script that tests those things then I will gladly run them and report the results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants