Path: blob/master/sage/numerical/backends/glpk_backend.pyx
4079 views
"""1GLPK Backend23AUTHORS:45- Nathann Cohen (2010-10): initial implementation6- John Perry (2012-01): glp_simplex preprocessing7- John Perry and Raniere Gaia Silva (2012-03): solver parameters8"""910##############################################################################11# Copyright (C) 2010 Nathann Cohen <[email protected]>12# Distributed under the terms of the GNU General Public License (GPL)13# The full text of the GPL is available at:14# http://www.gnu.org/licenses/15##############################################################################1617from sage.numerical.mip import MIPSolverException1819include "../../ext/interrupt.pxi"2021cdef class GLPKBackend(GenericBackend):2223def __cinit__(self, maximization = True):24"""25Constructor2627EXAMPLE::2829sage: p = MixedIntegerLinearProgram(solver="GLPK")30"""31self.lp = glp_create_prob()32self.simplex_or_intopt = glp_intopt_only33self.smcp = <c_glp_smcp* > sage_malloc(sizeof(c_glp_smcp))34glp_init_smcp(self.smcp)35self.iocp = <c_glp_iocp* > sage_malloc(sizeof(c_glp_iocp))36glp_init_iocp(self.iocp)37self.iocp.presolve = GLP_ON38self.set_verbosity(0)39self.obj_constant_term = 0.04041if maximization:42self.set_sense(+1)43else:44self.set_sense(-1)4546cpdef int add_variable(self, lower_bound=0.0, upper_bound=None, binary=False, continuous=False, integer=False, obj=0.0, name=None) except -1:47"""48Add a variable.4950This amounts to adding a new column to the matrix. By default,51the variable is both positive, real and the coefficient in the52objective function is 0.0.5354INPUT:5556- ``lower_bound`` - the lower bound of the variable (default: 0)5758- ``upper_bound`` - the upper bound of the variable (default: ``None``)5960- ``binary`` - ``True`` if the variable is binary (default: ``False``).6162- ``continuous`` - ``True`` if the variable is binary (default: ``True``).6364- ``integer`` - ``True`` if the variable is binary (default: ``False``).6566- ``obj`` - (optional) coefficient of this variable in the objective function (default: 0.0)6768- ``name`` - an optional name for the newly added variable (default: ``None``).6970OUTPUT: The index of the newly created variable7172EXAMPLE::7374sage: from sage.numerical.backends.generic_backend import get_solver75sage: p = get_solver(solver = "GLPK")76sage: p.ncols()77078sage: p.add_variable()79080sage: p.ncols()81182sage: p.add_variable(binary=True)83184sage: p.add_variable(lower_bound=-2.0, integer=True)85286sage: p.add_variable(continuous=True, integer=True)87Traceback (most recent call last):88...89ValueError: ...90sage: p.add_variable(name='x',obj=1.0)91392sage: p.col_name(3)93'x'94sage: p.objective_coefficient(3)951.096"""97cdef int vtype = int(bool(binary)) + int(bool(continuous)) + int(bool(integer))98if vtype == 0:99continuous = True100elif vtype != 1:101raise ValueError("Exactly one parameter of 'binary', 'integer' and 'continuous' must be 'True'.")102103glp_add_cols(self.lp, 1)104cdef int n_var = glp_get_num_cols(self.lp)105106self.variable_lower_bound(n_var - 1, lower_bound)107self.variable_upper_bound(n_var - 1, upper_bound)108109if continuous:110glp_set_col_kind(self.lp, n_var, GLP_CV)111elif binary:112glp_set_col_kind(self.lp, n_var, GLP_BV)113elif integer:114glp_set_col_kind(self.lp, n_var, GLP_IV)115116if name is not None:117glp_set_col_name(self.lp, n_var, name)118119if obj:120self.objective_coefficient(n_var - 1, obj)121122return n_var - 1123124cpdef int add_variables(self, int number, lower_bound=0.0, upper_bound=None, binary=False, continuous=False, integer=False, obj=0.0, names=None) except -1:125"""126Add ``number`` new variables.127128This amounts to adding new columns to the matrix. By default,129the variables are both positive, real and theor coefficient in130the objective function is 0.0.131132INPUT:133134- ``n`` - the number of new variables (must be > 0)135136- ``lower_bound`` - the lower bound of the variable (default: 0)137138- ``upper_bound`` - the upper bound of the variable (default: ``None``)139140- ``binary`` - ``True`` if the variable is binary (default: ``False``).141142- ``continuous`` - ``True`` if the variable is binary (default: ``True``).143144- ``integer`` - ``True`` if the variable is binary (default: ``False``).145146- ``obj`` - (optional) coefficient of all variables in the objective function (default: 0.0)147148- ``names`` - optional list of names (default: ``None``)149150OUTPUT: The index of the variable created last.151152EXAMPLE::153154sage: from sage.numerical.backends.generic_backend import get_solver155sage: p = get_solver(solver = "GLPK")156sage: p.ncols()1570158sage: p.add_variables(5)1594160sage: p.ncols()1615162sage: p.add_variables(2, lower_bound=-2.0, integer=True, names=['a','b'])1636164"""165cdef int vtype = int(bool(binary)) + int(bool(continuous)) + int(bool(integer))166if vtype == 0:167continuous = True168elif vtype != 1:169raise ValueError("Exactly one parameter of 'binary', 'integer' and 'continuous' must be 'True'.")170171glp_add_cols(self.lp, number)172173cdef int n_var174n_var = glp_get_num_cols(self.lp)175176cdef int i177178for 0<= i < number:179self.variable_lower_bound(n_var - i - 1, lower_bound)180self.variable_upper_bound(n_var - i - 1, upper_bound)181if continuous:182glp_set_col_kind(self.lp, n_var - i, GLP_CV)183elif binary:184glp_set_col_kind(self.lp, n_var - i, GLP_BV)185elif integer:186glp_set_col_kind(self.lp, n_var - i, GLP_IV)187188if obj:189self.objective_coefficient(n_var - i - 1, obj)190191if names is not None:192glp_set_col_name(self.lp, n_var, names[number - i - 1])193194return n_var - 1195196cpdef set_variable_type(self, int variable, int vtype):197"""198Set the type of a variable199200INPUT:201202- ``variable`` (integer) -- the variable's id203204- ``vtype`` (integer) :205206* 1 Integer207* 0 Binary208* -1 Real209210EXAMPLE::211212sage: from sage.numerical.backends.generic_backend import get_solver213sage: p = get_solver(solver = "GLPK")214sage: p.ncols()2150216sage: p.add_variable()2170218sage: p.set_variable_type(0,1)219sage: p.is_variable_integer(0)220True221"""222223if vtype==1:224glp_set_col_kind(self.lp, variable+1, GLP_IV)225226elif vtype==0:227glp_set_col_kind(self.lp, variable+1, GLP_BV)228229else:230glp_set_col_kind(self.lp, variable+1, GLP_CV)231232cpdef set_sense(self, int sense):233"""234Set the direction (maximization/minimization).235236INPUT:237238- ``sense`` (integer) :239240* +1 => Maximization241* -1 => Minimization242243EXAMPLE::244245sage: from sage.numerical.backends.generic_backend import get_solver246sage: p = get_solver(solver = "GLPK")247sage: p.is_maximization()248True249sage: p.set_sense(-1)250sage: p.is_maximization()251False252"""253if sense == 1:254glp_set_obj_dir(self.lp, GLP_MAX)255else:256glp_set_obj_dir(self.lp, GLP_MIN)257258cpdef objective_coefficient(self, int variable, coeff=None):259"""260Set or get the coefficient of a variable in the objective function261262INPUT:263264- ``variable`` (integer) -- the variable's id265266- ``coeff`` (double) -- its coefficient or ``None`` for267reading (default: ``None``)268269EXAMPLE::270271sage: from sage.numerical.backends.generic_backend import get_solver272sage: p = get_solver(solver = "GLPK")273sage: p.add_variable()2740275sage: p.objective_coefficient(0)2760.0277sage: p.objective_coefficient(0,2)278sage: p.objective_coefficient(0)2792.0280"""281if coeff is None:282return glp_get_obj_coef(self.lp, variable + 1)283else:284glp_set_obj_coef(self.lp, variable + 1, coeff)285286cpdef problem_name(self, char * name = NULL):287"""288Return or define the problem's name289290INPUT:291292- ``name`` (``char *``) -- the problem's name. When set to293``NULL`` (default), the method returns the problem's name.294295EXAMPLE::296297sage: from sage.numerical.backends.generic_backend import get_solver298sage: p = get_solver(solver = "GLPK")299sage: p.problem_name("There once was a french fry")300sage: print p.problem_name()301There once was a french fry302"""303cdef char * n304305if name == NULL:306n = <char *> glp_get_prob_name(self.lp)307if n == NULL:308return ""309else:310return n311312else:313glp_set_prob_name(self.lp, name)314315cpdef set_objective(self, list coeff, double d = 0.0):316"""317Set the objective function.318319INPUT:320321- ``coeff`` - a list of real values, whose ith element is the322coefficient of the ith variable in the objective function.323324- ``d`` (double) -- the constant term in the linear function (set to `0` by default)325326EXAMPLE::327328sage: from sage.numerical.backends.generic_backend import get_solver329sage: p = get_solver(solver = "GLPK")330sage: p.add_variables(5)3314332sage: p.set_objective([1, 1, 2, 1, 3])333sage: map(lambda x :p.objective_coefficient(x), range(5))334[1.0, 1.0, 2.0, 1.0, 3.0]335"""336cdef int i337338for i,v in enumerate(coeff):339glp_set_obj_coef(self.lp, i+1, v)340341glp_set_obj_coef(self.lp, 0, d)342343self.obj_constant_term = d344345cpdef set_verbosity(self, int level):346"""347Set the verbosity level348349INPUT:350351- ``level`` (integer) -- From 0 (no verbosity) to 3.352353EXAMPLE::354355sage: from sage.numerical.backends.generic_backend import get_solver356sage: p = get_solver(solver = "GLPK")357sage: p.set_verbosity(2)358359"""360if level == 0:361self.iocp.msg_lev = GLP_MSG_OFF362self.smcp.msg_lev = GLP_MSG_OFF363elif level == 1:364self.iocp.msg_lev = GLP_MSG_ERR365self.smcp.msg_lev = GLP_MSG_ERR366elif level == 2:367self.iocp.msg_lev = GLP_MSG_ON368self.smcp.msg_lev = GLP_MSG_ON369else:370self.iocp.msg_lev = GLP_MSG_ALL371self.smcp.msg_lev = GLP_MSG_ALL372373cpdef remove_constraint(self, int i):374r"""375Remove a constraint from self.376377INPUT:378379- ``i`` -- index of the constraint to remove380381EXAMPLE::382383sage: p = MixedIntegerLinearProgram(solver='GLPK')384sage: x,y = p[0], p[1]385sage: p.add_constraint(2*x + 3*y, max = 6)386sage: p.add_constraint(3*x + 2*y, max = 6)387sage: p.set_objective(x + y + 7)388sage: p.set_integer(x); p.set_integer(y)389sage: p.solve()3909.0391sage: p.remove_constraint(0)392sage: p.solve()39310.0394395Removing fancy constraints does not make Sage crash::396397sage: MixedIntegerLinearProgram(solver = "GLPK").remove_constraint(-2)398Traceback (most recent call last):399...400ValueError: The constraint's index i must satisfy 0 <= i < number_of_constraints401"""402cdef int rows[2]403404if i < 0 or i >= glp_get_num_rows(self.lp):405raise ValueError("The constraint's index i must satisfy 0 <= i < number_of_constraints")406407rows[1] = i + 1408glp_del_rows(self.lp, 1, rows)409glp_std_basis(self.lp)410411cpdef remove_constraints(self, constraints):412r"""413Remove several constraints.414415INPUT:416417- ``constraints`` -- an iterable containing the indices of the rows to remove.418419EXAMPLE::420421sage: p = MixedIntegerLinearProgram(solver='GLPK')422sage: x,y = p[0], p[1]423sage: p.add_constraint(2*x + 3*y, max = 6)424sage: p.add_constraint(3*x + 2*y, max = 6)425sage: p.set_objective(x + y + 7)426sage: p.set_integer(x); p.set_integer(y)427sage: p.solve()4289.0429sage: p.remove_constraints([1])430sage: p.solve()43110.0432sage: p.get_values([x,y])433[3.0, 0.0]434435TESTS:436437Removing fancy constraints does not make Sage crash::438439sage: MixedIntegerLinearProgram(solver= "GLPK").remove_constraints([0, -2])440Traceback (most recent call last):441...442ValueError: The constraint's index i must satisfy 0 <= i < number_of_constraints443"""444cdef int i, c445cdef int m = len(constraints)446cdef int * rows = <int *>sage_malloc((m + 1) * sizeof(int *))447cdef int nrows = glp_get_num_rows(self.lp)448449for i in xrange(m):450451c = constraints[i]452if c < 0 or c >= nrows:453sage_free(rows)454raise ValueError("The constraint's index i must satisfy 0 <= i < number_of_constraints")455456rows[i+1] = c + 1457458glp_del_rows(self.lp, m, rows)459sage_free(rows)460glp_std_basis(self.lp)461462cpdef add_linear_constraint(self, coefficients, lower_bound, upper_bound, name=None):463"""464Add a linear constraint.465466INPUT:467468- ``coefficients`` an iterable with ``(c,v)`` pairs where ``c``469is a variable index (integer) and ``v`` is a value (real470value).471472- ``lower_bound`` - a lower bound, either a real value or ``None``473474- ``upper_bound`` - an upper bound, either a real value or ``None``475476- ``name`` - an optional name for this row (default: ``None``)477478EXAMPLE::479480sage: from sage.numerical.backends.generic_backend import get_solver481sage: p = get_solver(solver = "GLPK")482sage: p.add_variables(5)4834484sage: p.add_linear_constraint( zip(range(5), range(5)), 2.0, 2.0)485sage: p.row(0)486([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0])487sage: p.row_bounds(0)488(2.0, 2.0)489sage: p.add_linear_constraint( zip(range(5), range(5)), 1.0, 1.0, name='foo')490sage: p.row_name(1)491'foo'492"""493if lower_bound is None and upper_bound is None:494raise ValueError("At least one of 'upper_bound' or 'lower_bound' must be set.")495496glp_add_rows(self.lp, 1)497cdef int n = glp_get_num_rows(self.lp)498499cdef int * row_i500cdef double * row_values501502row_i = <int *> sage_malloc((len(coefficients)+1) * sizeof(int))503row_values = <double *> sage_malloc((len(coefficients)+1) * sizeof(double))504505for i,(c,v) in enumerate(coefficients):506row_i[i+1] = c+1507row_values[i+1] = v508509glp_set_mat_row(self.lp, n, len(coefficients), row_i, row_values)510511if upper_bound is not None and lower_bound is None:512glp_set_row_bnds(self.lp, n, GLP_UP, upper_bound, upper_bound)513elif lower_bound is not None and upper_bound is None:514glp_set_row_bnds(self.lp, n, GLP_LO, lower_bound, lower_bound)515elif upper_bound is not None and lower_bound is not None:516if lower_bound == upper_bound:517glp_set_row_bnds(self.lp, n, GLP_FX, lower_bound, upper_bound)518else:519glp_set_row_bnds(self.lp, n, GLP_DB, lower_bound, upper_bound)520521if name is not None:522glp_set_row_name(self.lp, n, name)523524sage_free(row_i)525sage_free(row_values)526527cpdef add_linear_constraints(self, int number, lower_bound, upper_bound, names=None):528"""529Add ``'number`` linear constraints.530531INPUT:532533- ``number`` (integer) -- the number of constraints to add.534535- ``lower_bound`` - a lower bound, either a real value or ``None``536537- ``upper_bound`` - an upper bound, either a real value or ``None``538539- ``names`` - an optional list of names (default: ``None``)540541EXAMPLE::542543sage: from sage.numerical.backends.generic_backend import get_solver544sage: p = get_solver(solver = "GLPK")545sage: p.add_variables(5)5464547sage: p.add_linear_constraints(5, None, 2)548sage: p.row(4)549([], [])550sage: p.row_bounds(4)551(None, 2.0)552sage: p.add_linear_constraints(2, None, 2, names=['foo','bar'])553"""554if lower_bound is None and upper_bound is None:555raise ValueError("At least one of 'upper_bound' or 'lower_bound' must be set.")556557glp_add_rows(self.lp, number)558cdef int n = glp_get_num_rows(self.lp)559560cdef int i561for 0<= i < number:562if upper_bound is not None and lower_bound is None:563glp_set_row_bnds(self.lp, n-i, GLP_UP, upper_bound, upper_bound)564elif lower_bound is not None and upper_bound is None:565glp_set_row_bnds(self.lp, n-i, GLP_LO, lower_bound, lower_bound)566elif upper_bound is not None and lower_bound is not None:567if lower_bound == upper_bound:568glp_set_row_bnds(self.lp, n-i, GLP_FX, lower_bound, upper_bound)569else:570glp_set_row_bnds(self.lp, n-i, GLP_DB, lower_bound, upper_bound)571if names is not None:572glp_set_row_name(self.lp, n-i, names[number-i-1])573574cpdef row(self, int index):575r"""576Return a row577578INPUT:579580- ``index`` (integer) -- the constraint's id.581582OUTPUT:583584A pair ``(indices, coeffs)`` where ``indices`` lists the585entries whose coefficient is nonzero, and to which ``coeffs``586associates their coefficient on the model of the587``add_linear_constraint`` method.588589EXAMPLE::590591sage: from sage.numerical.backends.generic_backend import get_solver592sage: p = get_solver(solver = "GLPK")593sage: p.add_variables(5)5944595sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2)596sage: p.row(0)597([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0])598sage: p.row_bounds(0)599(2.0, 2.0)600"""601cdef int n = glp_get_num_cols(self.lp)602cdef int * c_indices = <int*> sage_malloc((n+1)*sizeof(int))603cdef double * c_values = <double*> sage_malloc((n+1)*sizeof(double))604cdef list indices = []605cdef list values = []606cdef int i,j607608i = glp_get_mat_row(self.lp, index + 1, c_indices, c_values)609for 0 < j <= i:610indices.append(c_indices[j]-1)611values.append(c_values[j])612613sage_free(c_indices)614sage_free(c_values)615616return (indices, values)617618cpdef row_bounds(self, int index):619"""620Return the bounds of a specific constraint.621622INPUT:623624- ``index`` (integer) -- the constraint's id.625626OUTPUT:627628A pair ``(lower_bound, upper_bound)``. Each of them can be set629to ``None`` if the constraint is not bounded in the630corresponding direction, and is a real value otherwise.631632EXAMPLE::633634sage: from sage.numerical.backends.generic_backend import get_solver635sage: p = get_solver(solver = "GLPK")636sage: p.add_variables(5)6374638sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2)639sage: p.row(0)640([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0])641sage: p.row_bounds(0)642(2.0, 2.0)643"""644cdef double ub645cdef double lb646647ub = glp_get_row_ub(self.lp, index + 1)648lb = glp_get_row_lb(self.lp, index +1)649650return (651(lb if lb != -DBL_MAX else None),652(ub if ub != +DBL_MAX else None)653)654655cpdef col_bounds(self, int index):656"""657Return the bounds of a specific variable.658659INPUT:660661- ``index`` (integer) -- the variable's id.662663OUTPUT:664665A pair ``(lower_bound, upper_bound)``. Each of them can be set666to ``None`` if the variable is not bounded in the667corresponding direction, and is a real value otherwise.668669EXAMPLE::670671sage: from sage.numerical.backends.generic_backend import get_solver672sage: p = get_solver(solver = "GLPK")673sage: p.add_variable()6740675sage: p.col_bounds(0)676(0.0, None)677sage: p.variable_upper_bound(0, 5)678sage: p.col_bounds(0)679(0.0, 5.0)680"""681682cdef double ub683cdef double lb684685ub = glp_get_col_ub(self.lp, index +1)686lb = glp_get_col_lb(self.lp, index +1)687688return (689(lb if lb != -DBL_MAX else None),690(ub if ub != +DBL_MAX else None)691)692693cpdef add_col(self, list indices, list coeffs):694"""695Add a column.696697INPUT:698699- ``indices`` (list of integers) -- this list constains the700indices of the constraints in which the variable's701coefficient is nonzero702703- ``coeffs`` (list of real values) -- associates a coefficient704to the variable in each of the constraints in which it705appears. Namely, the ith entry of ``coeffs`` corresponds to706the coefficient of the variable in the constraint707represented by the ith entry in ``indices``.708709.. NOTE::710711``indices`` and ``coeffs`` are expected to be of the same712length.713714EXAMPLE::715716sage: from sage.numerical.backends.generic_backend import get_solver717sage: p = get_solver(solver = "GLPK")718sage: p.ncols()7190720sage: p.nrows()7210722sage: p.add_linear_constraints(5, 0, None)723sage: p.add_col(range(5), range(5))724sage: p.nrows()7255726"""727728glp_add_cols(self.lp, 1)729cdef int n = glp_get_num_cols(self.lp)730731cdef int * col_i732cdef double * col_values733734col_i = <int *> sage_malloc((len(indices)+1) * sizeof(int))735col_values = <double *> sage_malloc((len(indices)+1) * sizeof(double))736737for i,v in enumerate(indices):738col_i[i+1] = v+1739for i,v in enumerate(coeffs):740col_values[i+1] = v741742glp_set_mat_col(self.lp, n, len(indices), col_i, col_values)743glp_set_col_bnds(self.lp, n, GLP_LO, 0,0)744745746cpdef int solve(self) except -1:747"""748Solve the problem.749750.. NOTE::751752This method raises ``MIPSolverException`` exceptions when753the solution can not be computed for any reason (none754exists, or the LP solver was not able to find it, etc...)755756EXAMPLE::757758sage: from sage.numerical.backends.generic_backend import get_solver759sage: p = get_solver(solver = "GLPK")760sage: p.add_linear_constraints(5, 0, None)761sage: p.add_col(range(5), range(5))762sage: p.solve()7630764sage: p.objective_coefficient(0,1)765sage: p.solve()766Traceback (most recent call last):767...768MIPSolverException: ...769770.. WARNING::771772Sage uses GLPK's ``glp_intopt`` to find solutions.773This routine sometimes FAILS CATASTROPHICALLY774when given a system it cannot solve. (Ticket #12309.)775Here, "catastrophic" can mean either "infinite loop" or776segmentation fault. Upstream considers this behavior777"essentially innate" to their design, and suggests778preprocessing it with ``glpk_simplex`` first.779Thus, if you suspect that your system is infeasible,780set the ``preprocessing`` option first.781782EXAMPLE::783784sage: lp = MixedIntegerLinearProgram(solver = "GLPK")785sage: lp.add_constraint( lp[1] +lp[2] -2.0 *lp[3] , max =-1.0)786sage: lp.add_constraint( lp[0] -4.0/3 *lp[1] +1.0/3 *lp[2] , max =-1.0/3)787sage: lp.add_constraint( lp[0] +0.5 *lp[1] -0.5 *lp[2] +0.25 *lp[3] , max =-0.25)788sage: lp.solve()7890.0790sage: lp.add_constraint( lp[0] +4.0 *lp[1] -lp[2] +lp[3] , max =-1.0)791sage: lp.solve()792Traceback (most recent call last):793...794RuntimeError: GLPK : Signal sent, try preprocessing option795sage: lp.solver_parameter("simplex_or_intopt", "simplex_then_intopt")796sage: lp.solve()797Traceback (most recent call last):798...799MIPSolverException: 'GLPK : Simplex cannot find a feasible solution'800801The user can ask sage to solve via ``simplex`` or ``intopt``.802The default solver is ``intopt``, so we get integer solutions.803804sage: lp = MixedIntegerLinearProgram(solver = 'GLPK', maximization = False)805sage: x, y = lp[0], lp[1]806sage: lp.add_constraint(-2*x + y <= 1)807sage: lp.add_constraint(x - y <= 1)808sage: lp.add_constraint(x + y >= 2)809sage: lp.set_objective(x + y)810sage: lp.set_integer(x)811sage: lp.set_integer(y)812sage: lp.solve()8132.0814sage: lp.get_values([x, y])815[1.0, 1.0]816817If we switch to ``simplex``, we get continuous solutions.818819sage: lp.solver_parameter("simplex_or_intopt", "simplex_only") # use simplex only820sage: lp.solve()8212.0822sage: lp.get_values([x, y])823[1.5, 0.5]824"""825826cdef int status827if self.simplex_or_intopt == glp_simplex_only or self.simplex_or_intopt == glp_simplex_then_intopt:828status = glp_simplex(self.lp, self.smcp)829status = glp_get_prim_stat(self.lp)830if status == GLP_OPT or status == GLP_FEAS:831pass832elif status == GLP_UNDEF or status == GLP_NOFEAS:833raise MIPSolverException("GLPK : Simplex cannot find a feasible solution")834835if self.simplex_or_intopt != glp_simplex_only:836sig_str('GLPK : Signal sent, try preprocessing option')837status = glp_intopt(self.lp, self.iocp)838sig_off()839# this is necessary to catch errors when certain options are enabled, e.g. tm_lim840if status == GLP_ETMLIM: raise MIPSolverException("GLPK : The time limit was reached")841elif status == GLP_EITLIM: raise MIPSolverException("GLPK : The iteration limit was reached")842843status = glp_mip_status(self.lp)844if status == GLP_OPT:845pass846elif status == GLP_UNDEF:847raise MIPSolverException("GLPK : Solution is undefined")848elif status == GLP_FEAS:849raise MIPSolverException("GLPK : Feasible solution found, while optimality has not been proven")850elif status == GLP_INFEAS:851raise MIPSolverException("GLPK : Solution is infeasible")852elif status == GLP_UNBND:853raise MIPSolverException("GLPK : Problem has unbounded solution")854elif status == GLP_NOFEAS:855raise MIPSolverException("GLPK : There is no feasible integer solution to this Linear Program")856857return 0858859cpdef double get_objective_value(self):860"""861Returns the value of the objective function.862863.. NOTE::864865Behaviour is undefined unless ``solve`` has been called before.866867EXAMPLE::868869sage: from sage.numerical.backends.generic_backend import get_solver870sage: p = get_solver(solver = "GLPK")871sage: p.add_variables(2)8721873sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)874sage: p.set_objective([2, 5])875sage: p.solve()8760877sage: p.get_objective_value()8787.5879sage: p.get_variable_value(0)8800.0881sage: p.get_variable_value(1)8821.5883"""884if self.simplex_or_intopt != glp_simplex_only:885return glp_mip_obj_val(self.lp)886else:887return glp_get_obj_val(self.lp)888889cpdef double get_variable_value(self, int variable):890"""891Returns the value of a variable given by the solver.892893.. NOTE::894895Behaviour is undefined unless ``solve`` has been called before.896897EXAMPLE::898899sage: from sage.numerical.backends.generic_backend import get_solver900sage: p = get_solver(solver = "GLPK")901sage: p.add_variables(2)9021903sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)904sage: p.set_objective([2, 5])905sage: p.solve()9060907sage: p.get_objective_value()9087.5909sage: p.get_variable_value(0)9100.0911sage: p.get_variable_value(1)9121.5913"""914if self.simplex_or_intopt != glp_simplex_only:915return glp_mip_col_val(self.lp, variable+1)916else:917return glp_get_col_prim(self.lp, variable+1)918919cpdef int ncols(self):920"""921Return the number of columns/variables.922923EXAMPLE::924925sage: from sage.numerical.backends.generic_backend import get_solver926sage: p = get_solver(solver = "GLPK")927sage: p.ncols()9280929sage: p.add_variables(2)9301931sage: p.ncols()9322933"""934return glp_get_num_cols(self.lp)935936cpdef int nrows(self):937"""938Return the number of rows/constraints.939940EXAMPLE::941942sage: from sage.numerical.backends.generic_backend import get_solver943sage: p = get_solver(solver = "GLPK")944sage: p.nrows()9450946sage: p.add_linear_constraints(2, 2, None)947sage: p.nrows()9482949"""950951return glp_get_num_rows(self.lp)952953cpdef col_name(self, int index):954"""955Return the ``index`` th col name956957INPUT:958959- ``index`` (integer) -- the col's id960961EXAMPLE::962963sage: from sage.numerical.backends.generic_backend import get_solver964sage: p = get_solver(solver = "GLPK")965sage: p.add_variable(name='I am a variable')9660967sage: p.col_name(0)968'I am a variable'969"""970cdef char * s971972glp_create_index(self.lp)973s = <char*> glp_get_col_name(self.lp, index + 1)974975if s != NULL:976return s977else:978return ""979980cpdef row_name(self, int index):981"""982Return the ``index`` th row name983984INPUT:985986- ``index`` (integer) -- the row's id987988EXAMPLE::989990sage: from sage.numerical.backends.generic_backend import get_solver991sage: p = get_solver(solver = "GLPK")992sage: p.add_linear_constraints(1, 2, None, names=['Empty constraint 1'])993sage: p.row_name(0)994'Empty constraint 1'995"""996cdef char * s997998glp_create_index(self.lp)999s = <char*> glp_get_row_name(self.lp, index + 1)10001001if s != NULL:1002return s1003else:1004return ""10051006cpdef bint is_variable_binary(self, int index):1007"""1008Test whether the given variable is of binary type.10091010INPUT:10111012- ``index`` (integer) -- the variable's id10131014EXAMPLE::10151016sage: from sage.numerical.backends.generic_backend import get_solver1017sage: p = get_solver(solver = "GLPK")1018sage: p.ncols()101901020sage: p.add_variable()102101022sage: p.set_variable_type(0,0)1023sage: p.is_variable_binary(0)1024True10251026"""1027return glp_get_col_kind(self.lp, index + 1) == GLP_BV10281029cpdef bint is_variable_integer(self, int index):1030"""1031Test whether the given variable is of integer type.10321033INPUT:10341035- ``index`` (integer) -- the variable's id10361037EXAMPLE::10381039sage: from sage.numerical.backends.generic_backend import get_solver1040sage: p = get_solver(solver = "GLPK")1041sage: p.ncols()104201043sage: p.add_variable()104401045sage: p.set_variable_type(0,1)1046sage: p.is_variable_integer(0)1047True1048"""1049return glp_get_col_kind(self.lp, index + 1) == GLP_IV10501051cpdef bint is_variable_continuous(self, int index):1052"""1053Test whether the given variable is of continuous/real type.10541055INPUT:10561057- ``index`` (integer) -- the variable's id10581059EXAMPLE::10601061sage: from sage.numerical.backends.generic_backend import get_solver1062sage: p = get_solver(solver = "GLPK")1063sage: p.ncols()106401065sage: p.add_variable()106601067sage: p.is_variable_continuous(0)1068True1069sage: p.set_variable_type(0,1)1070sage: p.is_variable_continuous(0)1071False10721073"""1074return glp_get_col_kind(self.lp, index + 1) == GLP_CV10751076cpdef bint is_maximization(self):1077"""1078Test whether the problem is a maximization10791080EXAMPLE::10811082sage: from sage.numerical.backends.generic_backend import get_solver1083sage: p = get_solver(solver = "GLPK")1084sage: p.is_maximization()1085True1086sage: p.set_sense(-1)1087sage: p.is_maximization()1088False1089"""10901091return glp_get_obj_dir(self.lp) == GLP_MAX10921093cpdef variable_upper_bound(self, int index, value = False):1094"""1095Return or define the upper bound on a variable10961097INPUT:10981099- ``index`` (integer) -- the variable's id11001101- ``value`` -- real value, or ``None`` to mean that the1102variable has not upper bound. When set to ``False``1103(default), the method returns the current value.11041105EXAMPLE::11061107sage: from sage.numerical.backends.generic_backend import get_solver1108sage: p = get_solver(solver = "GLPK")1109sage: p.add_variable()111001111sage: p.col_bounds(0)1112(0.0, None)1113sage: p.variable_upper_bound(0, 5)1114sage: p.col_bounds(0)1115(0.0, 5.0)1116"""1117cdef double x1118cdef double min11191120if value == False:1121x = glp_get_col_ub(self.lp, index +1)1122if x == DBL_MAX:1123return None1124else:1125return x11261127else:1128min = glp_get_col_lb(self.lp, index + 1)11291130if value is None and min == -DBL_MAX:1131glp_set_col_bnds(self.lp, index + 1, GLP_FR, 0, 0)11321133elif value is None:1134glp_set_col_bnds(self.lp, index + 1, GLP_LO, min, 0)11351136elif min == -DBL_MAX:1137glp_set_col_bnds(self.lp, index + 1, GLP_UP, 0, value)11381139elif min == value:1140glp_set_col_bnds(self.lp, index + 1, GLP_FX, value, value)11411142else:1143glp_set_col_bnds(self.lp, index + 1, GLP_DB, min, value)114411451146cpdef variable_lower_bound(self, int index, value = False):1147"""1148Return or define the lower bound on a variable11491150INPUT:11511152- ``index`` (integer) -- the variable's id11531154- ``value`` -- real value, or ``None`` to mean that the1155variable has not lower bound. When set to ``False``1156(default), the method returns the current value.11571158EXAMPLE::11591160sage: from sage.numerical.backends.generic_backend import get_solver1161sage: p = get_solver(solver = "GLPK")1162sage: p.add_variable()116301164sage: p.col_bounds(0)1165(0.0, None)1166sage: p.variable_lower_bound(0, 5)1167sage: p.col_bounds(0)1168(5.0, None)1169"""1170cdef double x1171cdef double max11721173if value == False:1174x = glp_get_col_lb(self.lp, index +1)1175if x == -DBL_MAX:1176return None1177else:1178return x1179else:1180max = glp_get_col_ub(self.lp, index + 1)11811182if value is None and max == DBL_MAX:1183glp_set_col_bnds(self.lp, index + 1, GLP_FR, 0.0, 0.0)11841185elif value is None:1186glp_set_col_bnds(self.lp, index + 1, GLP_UP, 0.0, max)11871188elif max == DBL_MAX:1189glp_set_col_bnds(self.lp, index + 1, GLP_LO, value, 0.0)11901191elif max == value:1192glp_set_col_bnds(self.lp, index + 1, GLP_FX, value, value)11931194else:1195glp_set_col_bnds(self.lp, index + 1, GLP_DB, value, max)11961197cpdef write_lp(self, char * filename):1198"""1199Write the problem to a .lp file12001201INPUT:12021203- ``filename`` (string)12041205EXAMPLE::12061207sage: from sage.numerical.backends.generic_backend import get_solver1208sage: p = get_solver(solver = "GLPK")1209sage: p.add_variables(2)121011211sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)1212sage: p.set_objective([2, 5])1213sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")1214"""1215glp_write_lp(self.lp, NULL, filename)12161217cpdef write_mps(self, char * filename, int modern):1218"""1219Write the problem to a .mps file12201221INPUT:12221223- ``filename`` (string)12241225EXAMPLE::12261227sage: from sage.numerical.backends.generic_backend import get_solver1228sage: p = get_solver(solver = "GLPK")1229sage: p.add_variables(2)123011231sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)1232sage: p.set_objective([2, 5])1233sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")1234"""1235glp_write_mps(self.lp, modern, NULL, filename)12361237cpdef GLPKBackend copy(self):1238"""1239Returns a copy of self.12401241EXAMPLE::12421243sage: from sage.numerical.backends.generic_backend import get_solver1244sage: p = MixedIntegerLinearProgram(solver = "GLPK")1245sage: b = p.new_variable()1246sage: p.add_constraint(b[1] + b[2] <= 6)1247sage: p.set_objective(b[1] + b[2])1248sage: copy(p).solve()12496.01250"""1251cdef GLPKBackend p = GLPKBackend(maximization = (1 if self.is_maximization() else -1))1252p.simplex_or_intopt = self.simplex_or_intopt1253p.iocp.tm_lim = self.iocp.tm_lim1254glp_copy_prob(p.lp, self.lp, 1)1255return p125612571258cpdef solver_parameter(self, name, value = None):1259"""1260Return or define a solver parameter12611262INPUT:12631264- ``name`` (string) -- the parameter12651266- ``value`` -- the parameter's value if it is to be defined,1267or ``None`` (default) to obtain its current value.12681269You can supply the name of a parameter and its value using either a1270string or a ``glp_`` constant (which are defined as Cython variables of1271this module).12721273In most cases, you can use the same name for a parameter as that given1274in the GLPK documentation, which is available by downloading GLPK from1275<http://www.gnu.org/software/glpk/>. The exceptions relate to parameters1276common to both methods; these require you to append ``_simplex`` or1277``_intopt`` to the name to resolve ambiguity, since the interface allows1278access to both.12791280We have also provided more meaningful names, to assist readability.12811282Parameter **names** are specified in lower case.1283To use a constant instead of a string, prepend ``glp_`` to the name.1284For example, both ``glp_gmi_cuts`` or ``"gmi_cuts"`` control whether1285to solve using Gomory cuts.12861287Parameter **values** are specificed as strings in upper case,1288or as constants in lower case. For example, both ``glp_on`` and ``"GLP_ON"``1289specify the same thing.12901291Naturally, you can use ``True`` and ``False`` in cases where ``glp_on`` and ``glp_off``1292would be used.12931294A list of parameter names, with their possible values:12951296**General-purpose parameters:**12971298.. list-table::1299:widths: 30 7013001301* - ``timelimit``13021303- specify the time limit IN SECONDS. This affects both simplex1304and intopt.13051306* - ``timelimit_simplex`` and ``timelimit_intopt``13071308- specify the time limit IN MILLISECONDS. (This is glpk's1309default.)13101311* - ``simplex_or_intopt``13121313- whether to use the ``simplex`` or ``intopt`` routines in1314GLPK. This is controlled by using ``glp_simplex_only``,1315``glp_intopt_only``, and ``glp_simplex_then_intopt``. The latter1316is useful to deal with a problem in GLPK where problems with no1317solution hang when using integer optimization; if you specify1318``glp_simplex_then_intopt``, sage will try simplex first, then1319perform integer optimization only if a solution of the LP1320relaxation exists.13211322* - ``verbosity_intopt`` and ``verbosity_simplex``13231324- one of ``GLP_MSG_OFF``, ``GLP_MSG_ERR``, ``GLP_MSG_ON``, or1325``GLP_MSG_ALL``. The default is ``GLP_MSG_OFF``.13261327* - ``output_frequency_intopt`` and ``output_frequency_simplex``13281329- the output frequency, in milliseconds. Default is 5000.13301331* - ``output_delay_intopt`` and ``output_delay_simplex``13321333- the output delay, in milliseconds, regarding the use of the1334simplex method on the LP relaxation. Default is 10000.133513361337**intopt-specific parameters:**13381339.. list-table::1340:widths: 30 7013411342* - ``branching``1343- - ``GLP_BR_FFV`` first fractional variable1344- ``GLP_BR_LFV`` last fractional variable1345- ``GLP_BR_MFV`` most fractional variable1346- ``GLP_BR_DTH`` Driebeck-Tomlin heuristic (default)1347- ``GLP_BR_PCH`` hybrid pseudocost heuristic13481349* - ``backtracking``1350- - ``GLP_BT_DFS`` depth first search1351- ``GLP_BT_BFS`` breadth first search1352- ``GLP_BT_BLB`` best local bound (default)1353- ``GLP_BT_BPH`` best projection heuristic13541355* - ``preprocessing``1356- - ``GLP_PP_NONE``1357- ``GLP_PP_ROOT`` preprocessing only at root level1358- ``GLP_PP_ALL`` (default)135913601361* - ``feasibility_pump``13621363- ``GLP_ON`` or ``GLP_OFF`` (default)13641365* - ``gomory_cuts``13661367- ``GLP_ON`` or ``GLP_OFF`` (default)13681369* - ``mixed_int_rounding_cuts``13701371- ``GLP_ON`` or ``GLP_OFF`` (default)13721373* - ``mixed_cover_cuts``13741375- ``GLP_ON`` or ``GLP_OFF`` (default)13761377* - ``clique_cuts``13781379- ``GLP_ON`` or ``GLP_OFF`` (default)13801381* - ``absolute_tolerance``13821383- (double) used to check if optimal solution to LP relaxation is1384integer feasible. GLPK manual advises, "do not change... without1385detailed understanding of its purpose."13861387* - ``relative_tolerance``13881389- (double) used to check if objective value in LP relaxation is not1390better than best known integer solution. GLPK manual advises, "do1391not change... without detailed understanding of its purpose."13921393* - ``mip_gap_tolerance``13941395- (double) relative mip gap tolerance. Default is 0.0.13961397* - ``presolve_intopt``13981399- ``GLP_ON`` (default) or ``GLP_OFF``.14001401* - ``binarize``14021403- ``GLP_ON`` or ``GLP_OFF`` (default)140414051406**simplex-specific parameters:**14071408.. list-table::1409:widths: 30 7014101411* - ``primal_v_dual``14121413- - ``GLP_PRIMAL`` (default)1414- ``GLP_DUAL``1415- ``GLP_DUALP``14161417* - ``pricing``14181419- - ``GLP_PT_STD`` standard (textbook)1420- ``GLP_PT_PSE`` projected steepest edge (default)14211422* - ``ratio_test``14231424- - ``GLP_RT_STD`` standard (textbook)1425- ``GLP_RT_HAR`` Harris' two-pass ratio test (default)14261427* - ``tolerance_primal``14281429- (double) tolerance used to check if basic solution is primal1430feasible. GLPK manual advises, "do not change... without1431detailed understanding of its purpose."14321433* - ``tolerance_dual``14341435- (double) tolerance used to check if basic solution is dual1436feasible. GLPK manual advises, "do not change... without1437detailed understanding of its purpose."14381439* - ``tolerance_pivot``14401441- (double) tolerance used to choose pivot. GLPK manual advises,1442"do not change... without detailed understanding of its1443purpose."14441445* - ``obj_lower_limit``14461447- (double) lower limit of the objective function. The default is1448``-DBL_MAX``.14491450* - ``obj_upper_limit``14511452- (double) upper limit of the objective function. The default is1453``DBL_MAX``.14541455* - ``iteration_limit``14561457- (int) iteration limit of the simplex algorithn. The default is1458``INT_MAX``.14591460* - ``presolve_simplex``14611462- ``GLP_ON`` or ``GLP_OFF`` (default).14631464.. NOTE::14651466The coverage for GLPK's control parameters for simplex and integer optimization1467is nearly complete. The only thing lacking is a wrapper for callback routines.14681469To date, no attempt has been made to expose the interior point methods.14701471EXAMPLE::14721473sage: from sage.numerical.backends.generic_backend import get_solver1474sage: p = get_solver(solver = "GLPK")1475sage: p.solver_parameter("timelimit", 60)1476sage: p.solver_parameter("timelimit")147760.014781479- Don't forget the difference between ``timelimit`` and ``timelimit_intopt``14801481::14821483sage: p.solver_parameter("timelimit_intopt")14846000014851486If you don't care for an integer answer, you can ask for an lp1487relaxation instead. The default solver performs integer optimization,1488but you can switch to the standard simplex algorithm through the1489``glp_simplex_or_intopt`` parameter.14901491EXAMPLE::14921493sage: lp = MixedIntegerLinearProgram(solver = 'GLPK', maximization = False)1494sage: x, y = lp[0], lp[1]1495sage: lp.add_constraint(-2*x + y <= 1)1496sage: lp.add_constraint(x - y <= 1)1497sage: lp.add_constraint(x + y >= 2)1498sage: lp.set_integer(x); lp.set_integer(y)1499sage: lp.set_objective(x + y)1500sage: lp.solve()15012.01502sage: lp.get_values([x,y])1503[1.0, 1.0]1504sage: import sage.numerical.backends.glpk_backend as backend1505sage: lp.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)1506sage: lp.solve()15072.01508sage: lp.get_values([x,y])1509[1.5, 0.5]15101511You can get glpk to spout all sorts of information at you.1512The default is to turn this off, but sometimes (debugging) it's very useful::15131514sage: lp.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_then_intopt)1515sage: lp.solver_parameter(backend.glp_mir_cuts, backend.glp_on)1516sage: lp.solver_parameter(backend.glp_msg_lev_intopt, backend.glp_msg_all)1517sage: lp.solver_parameter(backend.glp_mir_cuts)1518115191520If you actually try to solve ``lp``, you will get a lot of detailed information.1521"""15221523if type(name) == str:1524if name == "out_frq" or name == "out_dly" or name == "tm_lim" or name == "msg_lev":1525raise ValueError("To set parameter " + name + " you must specify the solver. Append either _simplex or _intopt.")1526name = solver_parameter_names_dict[name]15271528if type(value) == str: value = solver_parameter_values[value]15291530if name == timelimit_intopt:1531if value == None: return self.iocp.tm_lim1532else: self.iocp.tm_lim = value15331534if name == timelimit_seconds:1535if value == None: return self.iocp.tm_lim / 1000.01536else:1537self.iocp.tm_lim = value * 1000.01538self.smcp.tm_lim = value * 1000.015391540elif name == timelimit_simplex:1541if value == None: return self.smcp.tm_lim1542else: self.smcp.tm_lim = value15431544elif name == simplex_or_intopt:1545if value == None: return self.simplex_or_intopt1546if not value in (simplex_only,intopt_only,simplex_then_intopt):1547raise MIPSolverException, "GLPK: invalid value for simplex_or_intopt; see documentation"1548self.simplex_or_intopt = value15491550elif name == msg_lev_simplex:1551if value == None: return self.smcp.msg_lev1552else: self.smcp.msg_lev = value15531554elif name == msg_lev_intopt:1555if value == None: return self.iocp.msg_lev1556else: self.iocp.msg_lev = value15571558elif name == br_tech:1559if value == None: return self.iocp.br_tech1560else: self.iocp.br_tech = value15611562elif name == bt_tech:1563if value == None: return self.iocp.bt_tech1564else: self.iocp.bt_tech = value15651566elif name == pp_tech:1567if value == None: return self.iocp.pp_tech1568else: self.iocp.pp_tech = value15691570elif name == fp_heur:1571if value == None: return self.iocp.fp_heur1572else:1573if value == True: value = GLP_ON1574elif value == False: value = GLP_OFF1575self.iocp.fp_heur = value15761577elif name == gmi_cuts:1578if value == None: return self.iocp.gmi_cuts1579else:1580if value == True: value = GLP_ON1581elif value == False: value = GLP_OFF1582self.iocp.gmi_cuts = value15831584elif name == mir_cuts:1585if value == None: return self.iocp.mir_cuts1586else:1587if value == True: value = GLP_ON1588elif value == False: value = GLP_OFF1589self.iocp.mir_cuts = value15901591elif name == cov_cuts:1592if value == None: return self.iocp.cov_cuts1593else:1594if value == True: value = GLP_ON1595elif value == False: value = GLP_OFF1596self.iocp.cov_cuts = value15971598elif name == clq_cuts:1599if value == None: return self.iocp.clq_cuts1600else:1601if value == True: value = GLP_ON1602elif value == False: value = GLP_OFF1603self.iocp.clq_cuts = value16041605elif name == tol_int:1606if value == None: return self.iocp.tol_int1607else: self.iocp.tol_int = value16081609elif name == tol_obj:1610if value == None: return self.iocp.tol_obj1611else: self.iocp.tol_obj = value16121613elif name == mip_gap:1614if value == None: return self.iocp.mip_gap1615else: self.iocp.mip_gap = value16161617elif name == tm_lim_intopt:1618if value == None: return self.iocp.tm_lim1619else: self.iocp.tm_lim = value16201621elif name == out_frq_intopt:1622if value == None: return self.iocp.out_frq1623else: self.iocp.out_frq = value16241625elif name == out_dly_intopt:1626if value == None: return self.iocp.out_dly1627else: self.iocp.out_dly = value16281629elif name == presolve_intopt:1630if value == None: return self.iocp.presolve1631else:1632if value == True: value = GLP_ON1633elif value == False: value = GLP_OFF1634self.iocp.presolve = value16351636elif name == binarize:1637if value == None: return self.iocp.binarize1638else:1639if value == True: value = GLP_ON1640elif value == False: value = GLP_OFF1641self.iocp.binarize = value16421643elif name == msg_lev_simplex:1644if value == None: return self.smcp.msg_lev1645else: self.smcp.msg_lev = value16461647elif name == meth:1648if value == None: return self.smcp.meth1649else: self.smcp.meth = value16501651elif name == pricing:1652if value == None: return self.smcp.pricing1653else: self.smcp.pricing = value16541655elif name == r_test:1656if value == None: return self.smcp.r_test1657else: self.smcp.r_test = value16581659elif name == tol_bnd:1660if value == None: return self.smcp.tol_bnd1661else: self.smcp.tol_bnd = value16621663elif name == tol_dj:1664if value == None: return self.smcp.tol_dj1665else: self.smcp.tol_dj = value16661667elif name == tol_piv:1668if value == None: return self.smcp.tol_piv1669else: self.smcp.tol_piv = value16701671elif name == obj_ll:1672if value == None: return self.smcp.obj_ll1673else: self.smcp.obj_ll = value16741675elif name == obj_ul:1676if value == None: return self.smcp.obj_ul1677else: self.smcp.obj_ul = value16781679elif name == it_lim:1680if value == None: return self.smcp.it_lim1681else: self.smcp.it_lim = value16821683elif name == tm_lim_simplex:1684if value == None: return self.smcp.tm_lim1685else: self.smcp.tm_lim = value16861687elif name == out_frq_simplex:1688if value == None: return self.smcp.out_frq1689else: self.smcp.out_frq = value16901691elif name == out_dly_simplex:1692if value == None: return self.smcp.out_dly1693else: self.smcp.out_dly = value16941695elif name == presolve_simplex:1696if value == None: return self.smcp.presolve1697else:1698if value == True: value = GLP_ON1699elif value == False: value = GLP_OFF1700self.smcp.presolve = value17011702else:1703raise ValueError("This parameter is not available.")17041705def __dealloc__(self):1706"""1707Destructor1708"""1709glp_delete_prob(self.lp)1710sage_free(self.iocp)1711sage_free(self.smcp)17121713# parameter names17141715cdef enum solver_parameter_names:1716timelimit_seconds, timelimit_simplex, timelimit_intopt, simplex_or_intopt, msg_lev_simplex,1717msg_lev_intopt, br_tech, bt_tech, pp_tech, fp_heur, gmi_cuts,1718mir_cuts, cov_cuts, clq_cuts, tol_int, tol_obj, mip_gap,1719tm_lim_intopt, out_frq_intopt, out_dly_intopt, presolve_intopt,1720binarize, meth, pricing, r_test, tol_bnd, tol_dj, tol_piv, obj_ll,1721obj_ul, it_lim, tm_lim_simplex, out_frq_simplex, out_dly_simplex,1722presolve_simplex17231724glp_tm_lim_simplex = timelimit_simplex1725glp_tm_lim_intopt = timelimit_intopt1726glp_simplex_or_intopt = simplex_or_intopt1727glp_msg_lev_intopt = glp_verbosity_intopt = msg_lev_intopt1728glp_msg_lev_simplex = glp_verbosity_simplex = msg_lev_simplex1729glp_br_tech = glp_branching = br_tech1730glp_bt_tech = glp_backtracking = bt_tech1731glp_pp_tech = glp_preprocessing = pp_tech1732glp_fp_heur = glp_feasibility_pump = fp_heur1733glp_gmi_cuts = glp_gomory_cuts = gmi_cuts1734glp_mir_cuts = glp_mixed_int_rounding_cuts = mir_cuts1735glp_cov_cuts = glp_mixed_cover_cuts = cov_cuts1736glp_clq_cuts = glp_clique_cuts = clq_cuts1737glp_tol_int = glp_absolute_tolerance = tol_int1738glp_tol_obj = glp_relative_tolerance = tol_obj1739glp_mip_gap = glp_mip_gap_tolerance = mip_gap1740glp_out_frq_intopt = glp_output_frequency_intopt = out_frq_intopt1741glp_out_dly_intopt = glp_output_delay_intopt = out_dly_intopt1742glp_presolve_intopt = presolve_intopt1743glp_binarize = binarize1744glp_meth = glp_primal_v_dual = meth1745glp_pricing = pricing1746glp_r_test = glp_ratio_test = r_test1747glp_tol_bnd = glp_tolerance_primal = tol_bnd1748glp_tol_dj = glp_tolerance_dual = tol_dj1749glp_tol_piv = glp_tolerance_pivot = tol_piv1750glp_obj_ll = glp_obj_lower_limit = obj_ll1751glp_obj_ul = glp_obj_upper_limit = obj_ul1752glp_it_lim = glp_iteration_limit = it_lim1753glp_out_frq_simplex = glp_output_frequency_intopt = out_frq_simplex1754glp_out_dly_simplex = glp_output_delay_simplex = out_dly_simplex1755glp_presolve_simplex = presolve_simplex17561757solver_parameter_names_dict = {1758'timelimit': timelimit_seconds,1759'timelimit_intopt': timelimit_intopt,1760'tm_lim_intopt': timelimit_intopt,1761'timelimit_simplex': timelimit_simplex,1762'tm_lim_simplex': timelimit_simplex,1763'simplex_or_intopt': simplex_or_intopt,1764'msg_lev_simplex': msg_lev_simplex, 'verbosity_simplex': msg_lev_simplex,1765'msg_lev_intopt': msg_lev_intopt, 'verbosity_intopt': msg_lev_intopt,1766'br_tech': br_tech, 'branching': br_tech,1767'bt_tech': bt_tech, 'backtracking': bt_tech,1768'pp_tech': pp_tech, 'preprocessing': pp_tech,1769'fp_heur': fp_heur, 'feasibility_pump': fp_heur,1770'gmi_cuts': gmi_cuts, 'gomory_cuts': gmi_cuts,1771'mir_cuts': mir_cuts, 'mixed_int_rounding_cuts': mir_cuts,1772'cov_cuts': cov_cuts, 'mixed_cover_cuts': cov_cuts,1773'clq_cuts': clq_cuts, 'clique_cuts': clq_cuts,1774'tol_int': tol_int, 'absolute_tolerance': tol_int,1775'tol_obj': tol_obj, 'relative_tolerance': tol_obj,1776'mip_gap': mip_gap, 'mip_gap_tolerance': mip_gap,1777'out_frq_intopt': out_frq_intopt, 'output_frequency_intopt': out_frq_intopt,1778'out_dly_intopt': out_dly_intopt, 'output_delay_intopt': out_dly_intopt,1779'presolve_intopt': presolve_intopt, 'binarize': binarize,1780'meth': meth, 'primal_v_dual': meth,1781'pricing': pricing,1782'r_test': r_test, 'ratio_test': r_test,1783'tol_bnd': tol_bnd, 'tolerance_primal': tol_bnd,1784'tol_dj': tol_dj, 'tolerance_dual': tol_dj,1785'tol_piv': tol_piv, 'tolerance_pivot': tol_piv,1786'obj_ll': obj_ll, 'obj_lower_limit': obj_ll,1787'obj_ul': obj_ul, 'obj_upper_limit': obj_ul,1788'it_lim': it_lim, 'iteration_limit': it_lim,1789'out_frq_simplex': out_frq_simplex, 'output_frequency_intopt': out_frq_simplex,1790'out_dly_simplex': out_dly_simplex, 'output_delay_simplex': out_dly_simplex,1791'presolve_simplex': presolve_simplex1792}17931794# parameter values17951796glp_msg_off = GLP_MSG_OFF1797glp_msg_on = GLP_MSG_ON1798glp_msg_err = GLP_MSG_ERR1799glp_msg_all = GLP_MSG_ALL1800glp_msg_dbg = GLP_MSG_DBG18011802glp_primal = GLP_PRIMAL1803glp_dual = GLP_DUAL1804glp_dualp = GLP_DUALP18051806glp_pt_std = GLP_PT_STD1807glp_pt_pse = GLP_PT_PSE18081809glp_rt_std = GLP_RT_STD1810glp_rt_har = GLP_RT_HAR18111812dbl_max = DBL_MAX1813int_max = INT_MAX18141815glp_on = GLP_ON1816glp_off = GLP_OFF18171818glp_br_ffv = GLP_BR_FFV1819glp_br_lfv = GLP_BR_LFV1820glp_br_mfv = GLP_BR_MFV1821glp_br_dth = GLP_BR_DTH1822glp_br_pch = GLP_BR_PCH18231824glp_bt_dfs = GLP_BT_DFS1825glp_bt_bfs = GLP_BT_BFS1826glp_bt_blb = GLP_BT_BLB1827glp_bt_bph = GLP_BT_BPH18281829glp_pp_none = GLP_PP_NONE1830glp_pp_root = GLP_PP_ROOT1831glp_pp_all = GLP_PP_ALL18321833glp_max = GLP_MAX1834glp_min = GLP_MIN1835glp_up = GLP_UP1836glp_fr = GLP_FR1837glp_db = GLP_DB1838glp_fx = GLP_FX1839glp_lo = GLP_LO1840glp_cv = GLP_CV1841glp_iv = GLP_IV1842glp_bv = GLP_BV1843glp_mps_deck = GLP_MPS_DECK1844glp_mps_file = GLP_MPS_FILE18451846glp_undef = GLP_UNDEF1847glp_opt = GLP_OPT1848glp_feas = GLP_FEAS1849glp_nofeas = GLP_NOFEAS18501851cdef enum more_parameter_values:1852simplex_only, simplex_then_intopt, intopt_only18531854glp_simplex_only = simplex_only1855glp_simplex_then_intopt = simplex_then_intopt1856glp_intopt_only = intopt_only18571858# dictionaries for those who prefer to use strings18591860solver_parameter_values = {18611862'simplex_only': simplex_only,1863'simplex_then_intopt': simplex_then_intopt,1864'intopt_only': intopt_only,18651866'GLP_MSG_OFF' : GLP_MSG_OFF,1867'GLP_MSG_ON' : GLP_MSG_ON,1868'GLP_MSG_ERR' : GLP_MSG_ERR,1869'GLP_MSG_ALL' : GLP_MSG_ALL,1870'GLP_MSG_DBG' : GLP_MSG_DBG,18711872'GLP_PRIMAL' : GLP_PRIMAL,1873'GLP_DUAL' : GLP_DUAL,1874'GLP_DUALP' : GLP_DUALP,18751876'GLP_PT_STD' : GLP_PT_STD,1877'GLP_PT_PSE' : GLP_PT_PSE,18781879'GLP_RT_STD' : GLP_RT_STD,1880'GLP_RT_HAR' : GLP_RT_HAR,18811882'DBL_MAX' : DBL_MAX,1883'INT_MAX' : INT_MAX,18841885'GLP_ON' : GLP_ON,1886'GLP_OFF' : GLP_OFF,18871888'GLP_BR_FFV' : GLP_BR_FFV,1889'GLP_BR_LFV' : GLP_BR_LFV,1890'GLP_BR_MFV' : GLP_BR_MFV,1891'GLP_BR_DTH' : GLP_BR_DTH,1892'GLP_BR_PCH' : GLP_BR_PCH,18931894'GLP_BT_DFS' : GLP_BT_DFS,1895'GLP_BT_BFS' : GLP_BT_BFS,1896'GLP_BT_BLB' : GLP_BT_BLB,1897'GLP_BT_BPH' : GLP_BT_BPH,18981899'GLP_PP_NONE' : GLP_PP_NONE,1900'GLP_PP_ROOT' : GLP_PP_ROOT,1901'GLP_PP_ALL' : GLP_PP_ALL,19021903'GLP_MAX' : GLP_MAX,1904'GLP_MIN' : GLP_MIN,1905'GLP_UP' : GLP_UP,1906'GLP_FR' : GLP_FR,1907'GLP_DB' : GLP_DB,1908'GLP_FX' : GLP_FX,1909'GLP_LO' : GLP_LO,1910'GLP_CV' : GLP_CV,1911'GLP_IV' : GLP_IV,1912'GLP_BV' : GLP_BV,1913'GLP_MPS_DECK' : GLP_MPS_DECK,1914'GLP_MPS_FILE' : GLP_MPS_FILE,19151916'GLP_UNDEF' : GLP_UNDEF,1917'GLP_OPT' : GLP_OPT,1918'GLP_FEAS' : GLP_FEAS,1919'GLP_NOFEAS' : GLP_NOFEAS19201921}192219231924