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

Python: Add many constraints more efficiently #1020

Open
meyer89 opened this issue Jan 18, 2019 · 17 comments
Open

Python: Add many constraints more efficiently #1020

meyer89 opened this issue Jan 18, 2019 · 17 comments
Assignees
Labels
Feature Request Missing Feature/Wrapper Lang: Python Python wrapper issue Solver: Linear Solver Related to all Linear Solver (GLOP, BOP, CBC etc...)
Milestone

Comments

@meyer89
Copy link

meyer89 commented Jan 18, 2019

I use or-tools in Python for a model with many constraints and came across some limitations in the SWIG interface. It takes much longer creating the model than solving it.

I created an extended interface with Cython, which allows the creation of many constraints in a fraction of the previous time. However, I struggle a bit on how to integrate the Cython-Extension with ortools.

Arguments of MakeMatrixConstraint:

  • solver: The ortools.linear_solver.pywraplp.Solver instance
  • coefficients: double[:,:]/np.ndarray
  • lin_expr: list with entry for each column containing anything which implements GetCoeffs()
  • lb: double[:]/np.ndarray
  • ub: double[:]/np.ndarray

Right now only dense matrices are supported, but scipy.csr_matrix could be also supported with an identical interface. However, that would add an dependency.

I have the Cython source file "ortools/linear_solver/python/matrix_constraints.pyx" and the header file "ortools/linear_solver/python/swigpyobject.h" for Pointer extraction from SWIG. I can build and run this with "python3 setup_extension.py build_ext --inplace" after "make python" and test it, but it should be either a separate package or maybe integrated into the standard ortools package.

You can find the mentioned files attached to this issue as patch file:
matrix_constraints.zip
It is a proof-of-concept and could be improved by using a C-Structure for the LinExpr. Right now there is still a Python call in each loop.

To give you an impression here is the runtime of the naive implementation in Python:

created Test problem with 500 vars
init_mat took 9.53 ms
add_expr took 8.09 ms
add_constraints took **6301.57 ms**

And the much faster version with MakeMatrixConstraint in Cython:

created Test problem with 500 vars
init_mat took 4.69 ms
add_expr took 6.21 ms
add_constraints took **86.67 ms**

The result of ExportModelAsLpFormat() is confirmed to be identical.

Any hint how to proceed on this issue is highly appreciated.

@lperron
Copy link
Collaborator

lperron commented Jan 19, 2019

Thanks for the proposal.
We know we need to have a look.

@meyer89
Copy link
Author

meyer89 commented Jan 21, 2019

I just realized that I attached an empty file by accident. My proof of concept is attached to this comment now:
matrix_constraints.zip

@Mizux Mizux added Feature Request Missing Feature/Wrapper Lang: Python Python wrapper issue Solver: Linear Solver Related to all Linear Solver (GLOP, BOP, CBC etc...) labels Jan 23, 2019
@meyer89
Copy link
Author

meyer89 commented Mar 22, 2019

Time is passing on and so knowledge increases. I created a small wrapper in my free time, which works fine on Linux. On Windows the linking to the ortools library does not work.

pip install ortools cython numpy
pip install https://github.com/meyer89/orwrap/archive/master.zip

ref: https://github.com/meyer89/orwrap

Afterwards you can see the speedup with the following small test:

 python -m timeit -n 100 -s "import numpy as np; from orwrap.test.test_matrix_constraints import create_solver_fast as create; coef = np.tril(np.ones((100, 100))); lb = np.zeros(100); ub = np.zeros(100);" "create(coef, lb, ub)"

 python -m timeit -n 100 -s "import numpy as np; from orwrap.test.test_matrix_constraints import create_solver_slow as create; coef = np.tril(np.ones((100, 100))); lb = np.zeros(100); ub = np.zeros(100);" "create(coef, lb, ub)"

Right now I still don't know where this should go and I see multiple options:

  • Integrate the feature into the ortools package
  • Keep the package separate and add other community-provided functionality around ortools
  • Leave this repository as a proof-of-concept how cython can be used to improve execution speed
@MartiMayo
Copy link

Any update on this issue? It would be a strong performance enhancer for the LP Solver

@lperron
Copy link
Collaborator

lperron commented Jun 17, 2020 via email

@meyer89
Copy link
Author

meyer89 commented Jun 17, 2020

I totally understand your hesitation to support cython, as it might really complicate building and testing ortools for different architectures and platforms. However, it seems like the easiest way to build a fast interface between Python and ortools backend.

The published code works fine since one year in productive software. The effort made the difference between "way too slow" and "blazing fast" and was definitely worth it.

My hope is that the code is useful for the community, as I benefit so much from the good contributions here and elsewhere. I would like to see it integrated into ortools and willing to improve the quality until it can be merged, but of course the feature must be wanted.

@programsfallapart
Copy link

@meyer89 Hi, could you please give me your email adress? I would like to ask you some questions :)

@meyer89
Copy link
Author

meyer89 commented Sep 14, 2020

You can ask any question under this issue, so these answered for everybody. You could also leave me your email adress and I can contact you.

@Mizux Mizux added this to the v8.3 milestone Feb 12, 2021
@Mizux Mizux self-assigned this Feb 12, 2021
@Mizux Mizux modified the milestones: v9.0, v9.1 Mar 22, 2021
@Mizux Mizux modified the milestones: v9.1, v9.2 Aug 9, 2021
@Mizux Mizux modified the milestones: v9.2, v9.3 Oct 5, 2021
@Mizux Mizux modified the milestones: v9.3, v10.0 Feb 11, 2022
@ssmofidi
Copy link

ssmofidi commented Apr 26, 2022

I am dealing with the same issue. building constraints takes a lot of time for large problems. Looking for ways to create constraints through matrices and/or arrays systematically. Has there been any enhancement since the last time?

lperron added a commit that referenced this issue Apr 30, 2022
…rt simple_max_flow/simple_min_cost_flow to the fast API, fix #321, #1020, #2390
@Mizux
Copy link
Collaborator

Mizux commented May 2, 2022

FYI:

  1. LinearSolver MPsolver is not longer actively in development, but we continue the maintenance, support
  2. MPSolver should be replaced with math_opt or model_builder as better alternative but currently both are still in early stage
  3. We are moving from SWIG to pybind11 for Python wrappers (which provide support for numpy array)
  4. math_opt currently doesn't provide a python pybind11 support
@andreas-schwab andreas-schwab mentioned this issue Jun 4, 2022
@leeek
Copy link

leeek commented Sep 12, 2022

Is it possible to create constraints in a vectorized manner for CP-SAT in Python?

@lperron
Copy link
Collaborator

lperron commented Sep 12, 2022 via email

@ion-elgreco
Copy link

How is this still not available? Having to call solver.add is very suboptimal.

@lperron
Copy link
Collaborator

lperron commented Oct 4, 2023 via email

@lperron
Copy link
Collaborator

lperron commented Jan 16, 2024

How is this still not available? Having to call solver.add is very suboptimal.

you can send me a PR that implements it.

@ion-elgreco
Copy link

@lperron I don't code in C++, only python and Rust. Also it wouldn't be worthwhile to spend time on it for me since I don't use or-tools often enough :)

@lperron
Copy link
Collaborator

lperron commented Jan 16, 2024 via email

@Mizux Mizux modified the milestones: v10.0, Backlog Apr 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Request Missing Feature/Wrapper Lang: Python Python wrapper issue Solver: Linear Solver Related to all Linear Solver (GLOP, BOP, CBC etc...)
8 participants