Skip to content

Commit

Permalink
Add tolerance options for simplex and mip
Browse files Browse the repository at this point in the history
  • Loading branch information
mckib2 committed Aug 17, 2020
1 parent a973664 commit 8936c37
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 11 deletions.
5 changes: 0 additions & 5 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,3 @@ Since the underlying API is quite simple and written in C and only C, `ctypes` i
GLPK is packaged but I may want to make it so the user can optionally specify where the installation is on a user's computer (i.e., path to the shared library) so GLPK is not packaged with `scikit-glpk` and/or scipy. `linprog` could then presumably route the problem to the GLPK backend instead of HiGHS or the existing native python solvers.

The `ctypes` wrapper is required for integrating GLPK into the Python runtime. Instead of using MPS files to communicate problems and reading solutions from files, `scipy.sparse.coo_matrix` and `numpy` arrays can be passed directly to the library. More information can be extracted from GLPK this way as well (For example, there is no way to get iteration count except by reading directly from the underlying structs. It is only ever printed to stdout, no other way to get it).

TODO
----

- Several GLPK solver options (notably tolerances) not wrapped yet
62 changes: 57 additions & 5 deletions glpk/_glpk.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,38 @@ def glpk(
- ``norelax`` : standard "textbook" ratio test
- ``flip`` : long-step ratio test
- tol_bnd : double
Tolerance used to check if the basic solution is primal
feasible. (Default: 1e-7).
- tol_dj : double
Tolerance used to check if the basic solution is dual
feasible. (Default: 1e-7).
- tol_piv : double
Tolerance used to choose eligble pivotal elements of
the simplex table. (Default: 1e-10).
- obj_ll : double
Lower limit of the objective function. If the objective
function reaches this limit and continues decreasing,
the solver terminates the search. Used in the dual simplex
only. (Default: -DBL_MAX -- the largest finite float64).
- obj_ul : double
Upper limit of the objective function. If the objective
function reaches this limit and continues increasing,
the solver terminates the search. Used in the dual simplex
only. (Default: +DBL_MAX -- the largest finite float64).
- presolve : bool
Use presolver (assumes ``scale=True`` and
``init_basis='adv'``. Default is ``True``.
- exact : bool
Use simplex method based on exact arithmetic.
Default is ``False``.
Default is ``False``. If ``True``, all other
``simplex_option`` fields are ignored.
ip_options : dict
Options specific to interior-pooint solver.
Expand Down Expand Up @@ -208,13 +233,31 @@ def glpk(
- ``clique`` : clique cuts
- ``all`` : generate all cuts above
- gap_tol : float
Relative mip gap tolerance.
- tol_int : float
Absolute tolerance used to check if optimal solution to the
current LP relaxation is integer feasible.
(Default: 1e-5).
- tol_obj : float
Relative tolerance used to check if the objective value in
optimal solution to the current LP relaxation is not better
than in the best known integer feasible solution.
(Default: 1e-7).
- mip_gap : float
Relative mip gap tolerance. If the relative mip gap for
currently known best integer feasiblesolution falls below
this tolerance, the solver terminates the search. This allows
obtaining suboptimal integer feasible solutions if solving the
problem to optimality takes too long time.
(Default: 0.0).
- bound : float
add inequality obj <= bound (minimization) or
obj >= bound (maximization) to integer feasibility
problem (assumes ``minisat=True``).
Notes
-----
In general, don't change tolerances without a detailed understanding
of their purposes.
'''

# Housekeeping
Expand Down Expand Up @@ -375,6 +418,13 @@ def glpk(
'norelax': GLPK.GLP_RT_STD,
'flip': GLPK.GLP_RT_FLIP,
}[simplex_options.get('ratio', 'relax')]
smcp.tol_bnd = simplex_options.get('tol_bnd', 1e-7)
smcp.tol_dj = simplex_options.get('tol_dj', 1e-7)
smcp.tol_piv = simplex_options.get('tol_piv', 1e-10)
if simplex_options.get('obj_ll', False):
smcp.obj_ll = simplex_options['obj_ll']
if simplex_options.get('obj_ul', False):
smcp.obj_ul = simplex_options['obj_ul']
smcp.it_lim = maxit
smcp.tm_lim = timeout
smcp.presolve = {
Expand Down Expand Up @@ -528,7 +578,9 @@ def glpk(
if 'clique' in cuts:
iocp.clq_cuts = GLPK.GLP_ON

iocp.mip_gap = mip_options.get('gap_tol', 0.0)
iocp.tol_int = mip_options.get('tol_int', 1e-5)
iocp.tol_obj = mip_options.get('tol_obj', 1e-7)
iocp.mip_gap = mip_options.get('mip_gap', 0.0)
iocp.tm_lim = timeout
iocp.presolve = {
True: GLPK.GLP_ON,
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def get_export_symbols(self, ext):

setup(
name='scikit-glpk',
version='0.2.0',
version='0.2.1',
author='Nicholas McKibben',
author_email='[email protected]',
url='https://github.com/mckib2/scikit-glpk',
Expand Down

0 comments on commit 8936c37

Please sign in to comment.