Skip to content

Commit

Permalink
Improvements to GLPK configuration for MIPs (#231)
Browse files Browse the repository at this point in the history
* enable more parameters in interface

* remove optimality
  • Loading branch information
cdiener authored Mar 27, 2021
1 parent 03e2c19 commit 2848776
Showing 1 changed file with 20 additions and 14 deletions.
34 changes: 20 additions & 14 deletions src/optlang/glpk_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@


"""
Interface for the GNU Linear Programming Kit (GLPK)
Interface for the GNU Linear Programming Kit (GLPK).
Wraps the GLPK solver by subclassing and extending :class:`Model`,
:class:`Variable`, and :class:`Constraint` from :mod:`interface`.
Expand All @@ -26,16 +26,13 @@
"""
import logging

import os
import six

from optlang.util import inheritdocstring, TemporaryFilename
from optlang.expression_parsing import parse_optimization_expression
from optlang import interface
from optlang import symbolics

log = logging.getLogger(__name__)

from swiglpk import glp_find_col, glp_get_col_prim, glp_get_col_dual, GLP_CV, GLP_IV, GLP_BV, GLP_UNDEF, GLP_FEAS, \
GLP_INFEAS, GLP_NOFEAS, GLP_OPT, GLP_UNBND, \
glp_set_col_kind, glp_find_row, glp_get_row_prim, glp_get_row_dual, glp_get_obj_val, glp_set_obj_dir, glp_init_smcp, \
Expand All @@ -46,10 +43,9 @@
glp_set_col_name, intArray, glp_del_cols, glp_add_rows, glp_set_row_name, doubleArray, glp_write_lp, glp_write_prob, \
glp_set_mat_row, glp_set_col_bnds, glp_set_row_bnds, GLP_FR, GLP_UP, GLP_LO, GLP_FX, GLP_DB, glp_del_rows, \
glp_get_mat_row, glp_get_row_ub, glp_get_row_type, glp_get_row_lb, glp_get_row_name, glp_get_obj_coef, \
glp_get_obj_dir, glp_scale_prob, GLP_SF_AUTO, glp_get_num_int, glp_get_num_bin, glp_mip_col_val, \
glp_get_obj_dir, glp_scale_prob, GLP_SF_AUTO, glp_get_num_int, glp_mip_col_val, \
glp_mip_obj_val, glp_mip_status, GLP_ETMLIM, glp_adv_basis, glp_read_lp, glp_mip_row_val, \
get_col_primals, get_col_duals, get_row_primals, get_row_duals, glp_delete_prob

get_col_primals, get_col_duals, get_row_primals, get_row_duals


_GLPK_STATUS_TO_STATUS = {
Expand All @@ -71,6 +67,8 @@
[(val, key) for key, val in six.iteritems(_GLPK_VTYPE_TO_VTYPE)]
)

log = logging.getLogger(__name__)


def _glpk_validate_id(name):
if name is None:
Expand Down Expand Up @@ -152,7 +150,6 @@ def name(self, value):
glp_set_col_name(self.problem.problem, glp_find_col(self.problem.problem, old_name), str(value))



@six.add_metaclass(inheritdocstring)
class Constraint(interface.Constraint):
_INDICATOR_CONSTRAINT_SUPPORT = False
Expand Down Expand Up @@ -376,7 +373,6 @@ def get_linear_coefficients(self, variables):
raise Exception("Can't get coefficients from solver if objective is not in a model")



@six.add_metaclass(inheritdocstring)
class Configuration(interface.MathematicalProgrammingConfiguration):
def __init__(self, presolve="auto", verbosity=0, timeout=None, *args, **kwargs):
Expand Down Expand Up @@ -414,7 +410,7 @@ def __setstate__(self, state):

def _set_presolve(self, value):
self._smcp.presolve = {False: GLP_OFF, True: GLP_ON, "auto": GLP_OFF}[value]
self._iocp.presolve = {False: GLP_OFF, True: GLP_ON, "auto": GLP_OFF}[value]
self._iocp.presolve = {False: GLP_OFF, True: GLP_ON, "auto": GLP_ON}[value]

def _set_verbosity(self, value):
if value == 0:
Expand Down Expand Up @@ -453,10 +449,17 @@ def _get_feasibility(self):
def _set_feasibility(self, value):
return setattr(self._smcp, "tol_bnd", value)

def _get_integrality(self):
return getattr(self._iocp, "tol_int")

def _set_integrality(self, value):
return setattr(self._iocp, "tol_int", value)

def _tolerance_functions(self):
return {
"feasibility": (self._get_feasibility, self._set_feasibility)
}
"feasibility": (self._get_feasibility, self._set_feasibility),
"integrality": (self._get_integrality, self._set_integrality)
}

@property
def presolve(self):
Expand Down Expand Up @@ -599,14 +602,17 @@ def __setstate__(self, repr_dict):
if code != 0:
with open(tmp_file_name) as tmp_file:
invalid_problem = tmp_file.read()
raise Exception("The GLPK file " + tmp_file_name + " does not seem to contain a valid GLPK problem:\n\n" + invalid_problem)
raise Exception("The GLPK file " + tmp_file_name +
" does not seem to contain a valid GLPK problem:\n\n" +
invalid_problem)
self.__init__(problem=problem)
self.configuration = Configuration.clone(repr_dict['config'], problem=self)
if repr_dict['glpk_status'] == 'optimal':
self.optimize() # since the start is an optimal solution, nothing will happen here

# def __del__(self): # To make sure that the glpk problem is deleted when this is garbage collected
# Gotcha: When objects with a __del__ method are part of a referencing cycle, the entire cycle is never automatically garbage collected
# Gotcha: When objects with a __del__ method are part of a referencing cycle, the entire
# cycle is never automatically garbage collected
# glp_delete_prob(self.problem)

@property
Expand Down

0 comments on commit 2848776

Please sign in to comment.