Skip to content

Commit

Permalink
Working on MIP wrappers
Browse files Browse the repository at this point in the history
  • Loading branch information
mckib2 committed May 18, 2020
1 parent 00e0080 commit 8b07c0a
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 5 deletions.
26 changes: 24 additions & 2 deletions glpk/_glpk.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from scipy.sparse import coo_matrix
from scipy.optimize import OptimizeWarning, OptimizeResult

from ._glpk_defines import GLPK, glp_smcp, glp_iptcp, glp_bfcp
from ._glpk_defines import GLPK, glp_smcp, glp_iptcp, glp_bfcp, glp_iocp

def glpk(
c,
Expand Down Expand Up @@ -48,7 +48,7 @@ def glpk(
- ``up`` : double
If the entry is ``None``, then ``type=GLP_FX`` and ``ub==lb==0``.
solver : { 'simplex', 'interior' }
solver : { 'simplex', 'interior', 'mip' }
Use simplex (LP/MIP) or interior point method (LP only).
Default is ``simplex``.
sense : { 'GLP_MIN', 'GLP_MAX' }
Expand Down Expand Up @@ -414,6 +414,28 @@ def glpk(
# We shouldn't be reading this field... But we will anyways
res.nit = prob.contents.it_cnt

elif solver == 'mip':

# Make a control structure
iocp = glp_iocp()
_lib.glp_init_iocp(ctypes.byref(iocp))

# Set options
iocp.msg_lev = message_level*disp
iocp.br_tech = {
'first': GLPK.GLP_BR_FFV,
'last': GLPK.GLP_BR_LFV,
'mostf': GLPK.GLP_BR_MFV,
'drtom': GLPK.GLP_BR_DTH,
'pcost': GLPK.GLP_BR_PCH,
}[ip_options.get('branch', 'drtom')]
iocp.bt_tech = {
'dfs': GLPK.GLP_BT_DFS,
'bfs': GLPK.GLP_BT_BFS,
'bestp': GLPK.GLP_BT_BPH,
'bestb': GLPK.GLP_BT_BLB,
}[ip_options.get('backtrack', 'bestb')]

else:
raise ValueError('"%s" is not a recognized solver.' % solver)

Expand Down
61 changes: 59 additions & 2 deletions glpk/_glpk_defines.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class glp_mpscp(ctypes.Structure):
class glp_bfcp(ctypes.Structure):
_fields_ = [
('msg_lev', ctypes.c_int), # (not used)
('type', ctypes.c_int), # factorization type:
('type', ctypes.c_int), # factorization type
('lu_size', ctypes.c_int), # (not used)
('piv_tol', ctypes.c_double), # sgf_piv_tol
('piv_lim', ctypes.c_int), # sgf_piv_lim
Expand All @@ -55,6 +55,43 @@ class glp_bfcp(ctypes.Structure):
('foo_bar', ctypes.c_double*38), # (reserved)
]

# integer optimizer control parameters
class glp_tree(ctypes.Structure):
_fields_ = []
class glp_iocp(ctypes.Structure):
_fields_ = [
('msg_lev', ctypes.c_int), # message level (see glp_smcp)
('br_tech', ctypes.c_int), # branching technique
('bt_tech', ctypes.c_int), # backtracking technique:
('tol_int', ctypes.c_double), # mip.tol_int
('tol_obj', ctypes.c_double), # mip.tol_obj
('tm_lim', ctypes.c_int), # mip.tm_lim (milliseconds)
('out_frq', ctypes.c_int), # mip.out_frq (milliseconds)
('out_dly', ctypes.c_int), # mip.out_dly (milliseconds)
#void (*cb_func)(glp_tree *T, void *info); # mip.cb_func
('cb_func', ctypes.CFUNCTYPE(None, ctypes.POINTER(glp_tree), ctypes.c_void_p)),
('cb_info', ctypes.c_void_p), # mip.cb_info
('cb_size', ctypes.c_int), # mip.cb_size
('pp_tech', ctypes.c_int), # preprocessing technique:
('mip_gap', ctypes.c_double), # relative MIP gap tolerance
('mir_cuts', ctypes.c_int), # MIR cuts (GLP_ON/GLP_OFF)
('gmi_cuts', ctypes.c_int), # Gomory's cuts (GLP_ON/GLP_OFF)
('cov_cuts', ctypes.c_int), # cover cuts (GLP_ON/GLP_OFF)
('clq_cuts', ctypes.c_int), # clique cuts (GLP_ON/GLP_OFF)
('presolve', ctypes.c_int), # enable/disable using MIP presolver
('binarize', ctypes.c_int), # try to binarize integer variables
('fp_heur', ctypes.c_int), # feasibility pump heuristic
('ps_heur', ctypes.c_int), # proximity search heuristic
('ps_tm_lim', ctypes.c_int), # proxy time limit, milliseconds
('sr_heur', ctypes.c_int), # simple rounding heuristic
('use_sol', ctypes.c_int), # use existing solution
('save_sol', ctypes.c_char_p), # filename to save every new solution
('alien', ctypes.c_int), # use alien solver
('flip', ctypes.c_int), # use long-step dual simplex; not documented--should not be used
('foo_bar', ctypes.c_double*23), # (reserved)
]


# LP problem structure
class glp_prob(ctypes.Structure):
class DMP(ctypes.Structure):
Expand Down Expand Up @@ -100,7 +137,6 @@ class BFD(ctypes.Structure):
('mip_obj', ctypes.c_double),
]


class GLPK:

INT_MAX = ctypes.c_uint(-1).value // 2
Expand Down Expand Up @@ -224,6 +260,24 @@ class GLPK:
GLP_BF_BG = 2 # 0x02 # Schur compl. + Bartels-Golub
GLP_BF_GR = 3 # 0x03 # Schur compl. + Givens rotation

# Branching techniques
GLP_BR_FFV = 1 # first fractional variable
GLP_BR_LFV = 2 # last fractional variable
GLP_BR_MFV = 3 # most fractional variable
GLP_BR_DTH = 4 # heuristic by Driebeck and Tomlin
GLP_BR_PCH = 5 # hybrid pseudocost heuristic

# Backtracking technique
GLP_BT_DFS = 1 # depth first search
GLP_BT_BFS = 2 # breadth first search
GLP_BT_BLB = 3 # best local bound
GLP_BT_BPH = 4 # best projection heuristic

# MIP preprocessing
GLP_PP_NONE = 0 # disable preprocessing
GLP_PP_ROOT = 1 # preprocessing only on root level
GLP_PP_ALL = 2 # preprocessing on all levels

def __init__(self, libpath):

# Load the shared library;
Expand Down Expand Up @@ -413,6 +467,9 @@ def __init__(self, libpath):
_lib.glp_init_iptcp.restype = ctypes.c_int
_lib.glp_init_iptcp.argtypes = [ctypes.POINTER(glp_iptcp)]

_lib.glp_init_iocp.restype = None
_lib.glp_init_iocp.argtypes = [ctypes.POINTER(glp_iocp)]

# Simplex drivers
_lib.glp_simplex.restype = ctypes.c_int
_lib.glp_simplex.argtypes = [ctypes.POINTER(glp_prob), ctypes.POINTER(glp_smcp)]
Expand Down
2 changes: 1 addition & 1 deletion test.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
message_level=GLPK.GLP_MSG_OFF,
maxit=100,
timeout=10,
solver='interior',
solver='mip',
basis_fac='btf+cbg',
simplex_options={
'init_basis': 'adv',
Expand Down

0 comments on commit 8b07c0a

Please sign in to comment.