Path: blob/master/src/sage/numerical/backends/generic_backend.pyx
8815 views
r"""1Generic Backend for LP solvers23This class only lists the methods that should be defined by any4interface with a LP Solver. All these methods immediately raise5``NotImplementedError`` exceptions when called, and are obviously6meant to be replaced by the solver-specific method. This file can also7be used as a template to create a new interface : one would only need8to replace the occurences of ``"Nonexistent_LP_solver"`` by the9solver's name, and replace ``GenericBackend`` by10``SolverName(GenericBackend)`` so that the new solver extends this11class.1213AUTHORS:1415- Nathann Cohen (2010-10): initial implementation16- Risan (2012-02) : extension for PPL backend1718"""1920##############################################################################21# Copyright (C) 2010 Nathann Cohen <[email protected]>22# Distributed under the terms of the GNU General Public License (GPL)23# The full text of the GPL is available at:24# http://www.gnu.org/licenses/25##############################################################################262728cdef class GenericBackend:2930cpdef base_ring(self):31from sage.rings.all import RDF32return RDF3334cpdef zero(self):35return self.base_ring()(0)3637cpdef int add_variable(self, lower_bound=None, upper_bound=None, binary=False, continuous=True, integer=False, obj=None, name=None) except -1:38"""39Add a variable.4041This amounts to adding a new column to the matrix. By default,42the variable is both positive and real.4344INPUT:4546- ``lower_bound`` - the lower bound of the variable (default: 0)4748- ``upper_bound`` - the upper bound of the variable (default: ``None``)4950- ``binary`` - ``True`` if the variable is binary (default: ``False``).5152- ``continuous`` - ``True`` if the variable is binary (default: ``True``).5354- ``integer`` - ``True`` if the variable is binary (default: ``False``).5556- ``obj`` - (optional) coefficient of this variable in the objective function (default: 0.0)5758- ``name`` - an optional name for the newly added variable (default: ``None``).5960OUTPUT: The index of the newly created variable6162EXAMPLE::6364sage: from sage.numerical.backends.generic_backend import get_solver65sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver66sage: p.ncols() # optional - Nonexistent_LP_solver67068sage: p.add_variable() # optional - Nonexistent_LP_solver69070sage: p.ncols() # optional - Nonexistent_LP_solver71172sage: p.add_variable(binary=True) # optional - Nonexistent_LP_solver73174sage: p.add_variable(lower_bound=-2.0, integer=True) # optional - Nonexistent_LP_solver75276sage: p.add_variable(continuous=True, integer=True) # optional - Nonexistent_LP_solver77Traceback (most recent call last):78...79ValueError: ...80sage: p.add_variable(name='x',obj=1.0) # optional - Nonexistent_LP_solver81382sage: p.col_name(3) # optional - Nonexistent_LP_solver83'x'84sage: p.objective_coefficient(3) # optional - Nonexistent_LP_solver851.086"""87raise NotImplementedError()8889cpdef int add_variables(self, int n, lower_bound=None, upper_bound=None, binary=False, continuous=True, integer=False, obj=None, names=None) except -1:90"""91Add ``n`` variables.9293This amounts to adding new columns to the matrix. By default,94the variables are both positive and real.9596INPUT:9798- ``n`` - the number of new variables (must be > 0)99100- ``lower_bound`` - the lower bound of the variable (default: 0)101102- ``upper_bound`` - the upper bound of the variable (default: ``None``)103104- ``binary`` - ``True`` if the variable is binary (default: ``False``).105106- ``continuous`` - ``True`` if the variable is binary (default: ``True``).107108- ``integer`` - ``True`` if the variable is binary (default: ``False``).109110- ``obj`` - (optional) coefficient of all variables in the objective function (default: 0.0)111112- ``names`` - optional list of names (default: ``None``)113114OUTPUT: The index of the variable created last.115116EXAMPLE::117118sage: from sage.numerical.backends.generic_backend import get_solver119sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver120sage: p.ncols() # optional - Nonexistent_LP_solver1210122sage: p.add_variables(5) # optional - Nonexistent_LP_solver1234124sage: p.ncols() # optional - Nonexistent_LP_solver1255126sage: p.add_variables(2, lower_bound=-2.0, integer=True, names=['a','b']) # optional - Nonexistent_LP_solver1276128"""129raise NotImplementedError()130131cpdef set_variable_type(self, int variable, int vtype):132"""133Set the type of a variable134135INPUT:136137- ``variable`` (integer) -- the variable's id138139- ``vtype`` (integer) :140141* 1 Integer142* 0 Binary143* -1 Continuous144145EXAMPLE::146147sage: from sage.numerical.backends.generic_backend import get_solver148sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver149sage: p.ncols() # optional - Nonexistent_LP_solver1500151sage: p.add_variable() # optional - Nonexistent_LP_solver1521153sage: p.set_variable_type(0,1) # optional - Nonexistent_LP_solver154sage: p.is_variable_integer(0) # optional - Nonexistent_LP_solver155True156"""157raise NotImplementedError()158159cpdef set_sense(self, int sense):160"""161Set the direction (maximization/minimization).162163INPUT:164165- ``sense`` (integer) :166167* +1 => Maximization168* -1 => Minimization169170EXAMPLE::171172sage: from sage.numerical.backends.generic_backend import get_solver173sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver174sage: p.is_maximization() # optional - Nonexistent_LP_solver175True176sage: p.set_sense(-1) # optional - Nonexistent_LP_solver177sage: p.is_maximization() # optional - Nonexistent_LP_solver178False179"""180raise NotImplementedError()181182cpdef objective_coefficient(self, int variable, coeff=None):183"""184Set or get the coefficient of a variable in the objective185function186187INPUT:188189- ``variable`` (integer) -- the variable's id190191- ``coeff`` (double) -- its coefficient192193EXAMPLE::194195sage: from sage.numerical.backends.generic_backend import get_solver196sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver197sage: p.add_variable() # optional - Nonexistent_LP_solver1981199sage: p.objective_coefficient(0) # optional - Nonexistent_LP_solver2000.0201sage: p.objective_coefficient(0,2) # optional - Nonexistent_LP_solver202sage: p.objective_coefficient(0) # optional - Nonexistent_LP_solver2032.0204"""205raise NotImplementedError()206207cpdef set_objective(self, list coeff, d = 0.0):208"""209Set the objective function.210211INPUT:212213- ``coeff`` -- a list of real values, whose ith element is the214coefficient of the ith variable in the objective function.215216- ``d`` (double) -- the constant term in the linear function (set to `0` by default)217218EXAMPLE::219220sage: from sage.numerical.backends.generic_backend import get_solver221sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver222sage: p.add_variables(5) # optional - Nonexistent_LP_solver2235224sage: p.set_objective([1, 1, 2, 1, 3]) # optional - Nonexistent_LP_solver225sage: map(lambda x :p.objective_coefficient(x), range(5)) # optional - Nonexistent_LP_solver226[1.0, 1.0, 2.0, 1.0, 3.0]227228Constants in the objective function are respected::229230sage: p = MixedIntegerLinearProgram(solver='Nonexistent_LP_solver') # optional - Nonexistent_LP_solver231sage: x,y = p[0], p[1] # optional - Nonexistent_LP_solver232sage: p.add_constraint(2*x + 3*y, max = 6) # optional - Nonexistent_LP_solver233sage: p.add_constraint(3*x + 2*y, max = 6) # optional - Nonexistent_LP_solver234sage: p.set_objective(x + y + 7) # optional - Nonexistent_LP_solver235sage: p.set_integer(x); p.set_integer(y) # optional - Nonexistent_LP_solver236sage: p.solve() # optional - Nonexistent_LP_solver2379.0238"""239raise NotImplementedError()240241cpdef set_verbosity(self, int level):242"""243Set the log (verbosity) level244245INPUT:246247- ``level`` (integer) -- From 0 (no verbosity) to 3.248249EXAMPLE::250251sage: from sage.numerical.backends.generic_backend import get_solver252sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver253sage: p.set_verbosity(2) # optional - Nonexistent_LP_solver254"""255raise NotImplementedError()256257cpdef remove_constraint(self, int i):258r"""259Remove a constraint.260261INPUT::262263- ``i`` -- index of the constraint to remove.264265EXAMPLE::266267sage: from sage.numerical.backends.generic_backend import get_solver268sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver269sage: p.add_constraint(p[0] + p[1], max = 10) # optional - Nonexistent_LP_solver270sage: p.remove_constraint(0) # optional - Nonexistent_LP_solver271"""272raise NotImplementedError()273274cpdef remove_constraints(self, constraints):275r"""276Remove several constraints.277278INPUT:279280- ``constraints`` -- an iterable containing the indices of the rows to remove.281282EXAMPLE::283284sage: from sage.numerical.backends.generic_backend import get_solver285sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver286sage: p.add_constraint(p[0] + p[1], max = 10) # optional - Nonexistent_LP_solver287sage: p.remove_constraints([0]) # optional - Nonexistent_LP_solver288"""289if type(constraints) == int: self.remove_constraint(constraints)290291cdef int last = self.nrows() + 1292293for c in sorted(constraints, reverse=True):294if c != last:295self.remove_constraint(c)296last = c297298cpdef add_linear_constraint(self, coefficients, lower_bound, upper_bound, name=None):299"""300Add a linear constraint.301302INPUT:303304- ``coefficients`` an iterable with ``(c,v)`` pairs where ``c``305is a variable index (integer) and ``v`` is a value (real306value).307308- ``lower_bound`` - a lower bound, either a real value or ``None``309310- ``upper_bound`` - an upper bound, either a real value or ``None``311312- ``name`` - an optional name for this row (default: ``None``)313314EXAMPLE::315316sage: from sage.numerical.backends.generic_backend import get_solver317sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver318sage: p.add_variables(5) # optional - Nonexistent_LP_solver3194320sage: p.add_linear_constraint(zip(range(5), range(5)), 2.0, 2.0) # optional - Nonexistent_LP_solver321sage: p.row(0) # optional - Nonexistent_LP_solver322([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0]) # optional - Nonexistent_LP_solver323sage: p.row_bounds(0) # optional - Nonexistent_LP_solver324(2.0, 2.0)325sage: p.add_linear_constraint( zip(range(5), range(5)), 1.0, 1.0, name='foo') # optional - Nonexistent_LP_solver326sage: p.row_name(-1) # optional - Nonexistent_LP_solver327"foo"328"""329raise NotImplementedError()330331cpdef add_col(self, list indices, list coeffs):332"""333Add a column.334335INPUT:336337- ``indices`` (list of integers) -- this list constains the338indices of the constraints in which the variable's339coefficient is nonzero340341- ``coeffs`` (list of real values) -- associates a coefficient342to the variable in each of the constraints in which it343appears. Namely, the ith entry of ``coeffs`` corresponds to344the coefficient of the variable in the constraint345represented by the ith entry in ``indices``.346347.. NOTE::348349``indices`` and ``coeffs`` are expected to be of the same350length.351352EXAMPLE::353354sage: from sage.numerical.backends.generic_backend import get_solver355sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver356sage: p.ncols() # optional - Nonexistent_LP_solver3570358sage: p.nrows() # optional - Nonexistent_LP_solver3590360sage: p.add_linear_constraints(5, 0, None) # optional - Nonexistent_LP_solver361sage: p.add_col(range(5), range(5)) # optional - Nonexistent_LP_solver362sage: p.nrows() # optional - Nonexistent_LP_solver3635364"""365raise NotImplementedError()366367cpdef add_linear_constraints(self, int number, lower_bound, upper_bound, names=None):368"""369Add constraints.370371INPUT:372373- ``number`` (integer) -- the number of constraints to add.374375- ``lower_bound`` - a lower bound, either a real value or ``None``376377- ``upper_bound`` - an upper bound, either a real value or ``None``378379- ``names`` - an optional list of names (default: ``None``)380381EXAMPLE::382383sage: from sage.numerical.backends.generic_backend import get_solver384sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver385sage: p.add_variables(5) # optional - Nonexistent_LP_solver3865387sage: p.add_linear_constraints(5, None, 2) # optional - Nonexistent_LP_solver388sage: p.row(4) # optional - Nonexistent_LP_solver389([], [])390sage: p.row_bounds(4) # optional - Nonexistent_LP_solver391(None, 2.0)392"""393raise NotImplementedError()394395cpdef int solve(self) except -1:396"""397Solve the problem.398399.. NOTE::400401This method raises ``MIPSolverException`` exceptions when402the solution can not be computed for any reason (none403exists, or the LP solver was not able to find it, etc...)404405EXAMPLE::406407sage: from sage.numerical.backends.generic_backend import get_solver408sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver409sage: p.add_linear_constraints(5, 0, None) # optional - Nonexistent_LP_solver410sage: p.add_col(range(5), range(5)) # optional - Nonexistent_LP_solver411sage: p.solve() # optional - Nonexistent_LP_solver4120413sage: p.objective_coefficient(0,1) # optional - Nonexistent_LP_solver414sage: p.solve() # optional - Nonexistent_LP_solver415Traceback (most recent call last):416...417MIPSolverException: ...418"""419raise NotImplementedError()420421cpdef get_objective_value(self):422"""423Return the value of the objective function.424425.. NOTE::426427Behaviour is undefined unless ``solve`` has been called before.428429EXAMPLE::430431sage: from sage.numerical.backends.generic_backend import get_solver432sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver433sage: p.add_variables(2) # optional - Nonexistent_LP_solver4342435sage: p.add_linear_constraint([(0,1), (1,2)], None, 3) # optional - Nonexistent_LP_solver436sage: p.set_objective([2, 5]) # optional - Nonexistent_LP_solver437sage: p.solve() # optional - Nonexistent_LP_solver4380439sage: p.get_objective_value() # optional - Nonexistent_LP_solver4407.5441sage: p.get_variable_value(0) # optional - Nonexistent_LP_solver4420.0443sage: p.get_variable_value(1) # optional - Nonexistent_LP_solver4441.5445"""446447raise NotImplementedError()448449cpdef get_variable_value(self, int variable):450"""451Return the value of a variable given by the solver.452453.. NOTE::454455Behaviour is undefined unless ``solve`` has been called before.456457EXAMPLE::458459sage: from sage.numerical.backends.generic_backend import get_solver460sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver461sage: p.add_variables(2) # optional - Nonexistent_LP_solver4622463sage: p.add_linear_constraint([(0,1), (1, 2)], None, 3) # optional - Nonexistent_LP_solver464sage: p.set_objective([2, 5]) # optional - Nonexistent_LP_solver465sage: p.solve() # optional - Nonexistent_LP_solver4660467sage: p.get_objective_value() # optional - Nonexistent_LP_solver4687.5469sage: p.get_variable_value(0) # optional - Nonexistent_LP_solver4700.0471sage: p.get_variable_value(1) # optional - Nonexistent_LP_solver4721.5473"""474475raise NotImplementedError()476477cpdef int ncols(self):478"""479Return the number of columns/variables.480481EXAMPLE::482483sage: from sage.numerical.backends.generic_backend import get_solver484sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver485sage: p.ncols() # optional - Nonexistent_LP_solver4860487sage: p.add_variables(2) # optional - Nonexistent_LP_solver4882489sage: p.ncols() # optional - Nonexistent_LP_solver4902491"""492493raise NotImplementedError()494495cpdef int nrows(self):496"""497Return the number of rows/constraints.498499EXAMPLE::500501sage: from sage.numerical.backends.generic_backend import get_solver502sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver503sage: p.nrows() # optional - Nonexistent_LP_solver5040505sage: p.add_linear_constraints(2, 2.0, None) # optional - Nonexistent_LP_solver506sage: p.nrows() # optional - Nonexistent_LP_solver5072508"""509510raise NotImplementedError()511512cpdef bint is_maximization(self):513"""514Test whether the problem is a maximization515516EXAMPLE::517518sage: from sage.numerical.backends.generic_backend import get_solver519sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver520sage: p.is_maximization() # optional - Nonexistent_LP_solver521True522sage: p.set_sense(-1) # optional - Nonexistent_LP_solver523sage: p.is_maximization() # optional - Nonexistent_LP_solver524False525"""526raise NotImplementedError()527528cpdef problem_name(self, char * name = NULL):529"""530Return or define the problem's name531532INPUT:533534- ``name`` (``char *``) -- the problem's name. When set to535``NULL`` (default), the method returns the problem's name.536537EXAMPLE::538539sage: from sage.numerical.backends.generic_backend import get_solver540sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver541sage: p.problem_name("There once was a french fry") # optional - Nonexistent_LP_solver542sage: print p.get_problem_name() # optional - Nonexistent_LP_solver543There once was a french fry544"""545546raise NotImplementedError()547548cpdef write_lp(self, char * name):549"""550Write the problem to a .lp file551552INPUT:553554- ``filename`` (string)555556EXAMPLE::557558sage: from sage.numerical.backends.generic_backend import get_solver559sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver560sage: p.add_variables(2) # optional - Nonexistent_LP_solver5612562sage: p.add_linear_constraint([(0, 1], (1, 2)], None, 3) # optional - Nonexistent_LP_solver563sage: p.set_objective([2, 5]) # optional - Nonexistent_LP_solver564sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp")) # optional - Nonexistent_LP_solver565"""566raise NotImplementedError()567568cpdef write_mps(self, char * name, int modern):569"""570Write the problem to a .mps file571572INPUT:573574- ``filename`` (string)575576EXAMPLE::577578sage: from sage.numerical.backends.generic_backend import get_solver579sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver580sage: p.add_variables(2) # optional - Nonexistent_LP_solver5812582sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3) # optional - Nonexistent_LP_solver583sage: p.set_objective([2, 5]) # optional - Nonexistent_LP_solver584sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp")) # optional - Nonexistent_LP_solver585"""586raise NotImplementedError()587588cpdef row(self, int i):589"""590Return a row591592INPUT:593594- ``index`` (integer) -- the constraint's id.595596OUTPUT:597598A pair ``(indices, coeffs)`` where ``indices`` lists the599entries whose coefficient is nonzero, and to which ``coeffs``600associates their coefficient on the model of the601``add_linear_constraint`` method.602603EXAMPLE::604605sage: from sage.numerical.backends.generic_backend import get_solver606sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver607sage: p.add_variables(5) # optional - Nonexistent_LP_solver6085609sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2) # optional - Nonexistent_LP_solver610sage: p.row(0) # optional - Nonexistent_LP_solver611([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0])612sage: p.row_bounds(0) # optional - Nonexistent_LP_solver613(2.0, 2.0)614"""615raise NotImplementedError()616617cpdef row_bounds(self, int index):618"""619Return the bounds of a specific constraint.620621INPUT:622623- ``index`` (integer) -- the constraint's id.624625OUTPUT:626627A pair ``(lower_bound, upper_bound)``. Each of them can be set628to ``None`` if the constraint is not bounded in the629corresponding direction, and is a real value otherwise.630631EXAMPLE::632633sage: from sage.numerical.backends.generic_backend import get_solver634sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver635sage: p.add_variables(5) # optional - Nonexistent_LP_solver6365637sage: p.add_linear_constraint(range(5), range(5), 2, 2) # optional - Nonexistent_LP_solver638sage: p.row(0) # optional - Nonexistent_LP_solver639([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0])640sage: p.row_bounds(0) # optional - Nonexistent_LP_solver641(2.0, 2.0)642"""643raise NotImplementedError()644645cpdef col_bounds(self, int index):646"""647Return the bounds of a specific variable.648649INPUT:650651- ``index`` (integer) -- the variable's id.652653OUTPUT:654655A pair ``(lower_bound, upper_bound)``. Each of them can be set656to ``None`` if the variable is not bounded in the657corresponding direction, and is a real value otherwise.658659EXAMPLE::660661sage: from sage.numerical.backends.generic_backend import get_solver662sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver663sage: p.add_variable() # optional - Nonexistent_LP_solver6641665sage: p.col_bounds(0) # optional - Nonexistent_LP_solver666(0.0, None)667sage: p.variable_upper_bound(0, 5) # optional - Nonexistent_LP_solver668sage: p.col_bounds(0) # optional - Nonexistent_LP_solver669(0.0, 5.0)670"""671raise NotImplementedError()672673cpdef bint is_variable_binary(self, int index):674"""675Test whether the given variable is of binary type.676677INPUT:678679- ``index`` (integer) -- the variable's id680681EXAMPLE::682683sage: from sage.numerical.backends.generic_backend import get_solver684sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver685sage: p.ncols() # optional - Nonexistent_LP_solver6860687sage: p.add_variable() # optional - Nonexistent_LP_solver6881689sage: p.set_variable_type(0,0) # optional - Nonexistent_LP_solver690sage: p.is_variable_binary(0) # optional - Nonexistent_LP_solver691True692693"""694raise NotImplementedError()695696cpdef bint is_variable_integer(self, int index):697"""698Test whether the given variable is of integer type.699700INPUT:701702- ``index`` (integer) -- the variable's id703704EXAMPLE::705706sage: from sage.numerical.backends.generic_backend import get_solver707sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver708sage: p.ncols() # optional - Nonexistent_LP_solver7090710sage: p.add_variable() # optional - Nonexistent_LP_solver7111712sage: p.set_variable_type(0,1) # optional - Nonexistent_LP_solver713sage: p.is_variable_integer(0) # optional - Nonexistent_LP_solver714True715"""716raise NotImplementedError()717718cpdef bint is_variable_continuous(self, int index):719"""720Test whether the given variable is of continuous/real type.721722INPUT:723724- ``index`` (integer) -- the variable's id725726EXAMPLE::727728sage: from sage.numerical.backends.generic_backend import get_solver729sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver730sage: p.ncols() # optional - Nonexistent_LP_solver7310732sage: p.add_variable() # optional - Nonexistent_LP_solver7331734sage: p.is_variable_continuous(0) # optional - Nonexistent_LP_solver735True736sage: p.set_variable_type(0,1) # optional - Nonexistent_LP_solver737sage: p.is_variable_continuous(0) # optional - Nonexistent_LP_solver738False739740"""741raise NotImplementedError()742743cpdef row_name(self, int index):744"""745Return the ``index`` th row name746747INPUT:748749- ``index`` (integer) -- the row's id750751EXAMPLE::752753sage: from sage.numerical.backends.generic_backend import get_solver754sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver755sage: p.add_linear_constraints(1, 2, None, name="Empty constraint 1") # optional - Nonexistent_LP_solver756sage: p.row_name(0) # optional - Nonexistent_LP_solver757'Empty constraint 1'758759"""760raise NotImplementedError()761762cpdef col_name(self, int index):763"""764Return the ``index`` th col name765766INPUT:767768- ``index`` (integer) -- the col's id769770- ``name`` (``char *``) -- its name. When set to ``NULL``771(default), the method returns the current name.772773EXAMPLE::774775sage: from sage.numerical.backends.generic_backend import get_solver776sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver777sage: p.add_variable(name="I am a variable") # optional - Nonexistent_LP_solver7781779sage: p.col_name(0) # optional - Nonexistent_LP_solver780'I am a variable'781"""782raise NotImplementedError()783784cpdef variable_upper_bound(self, int index, value = None):785"""786Return or define the upper bound on a variable787788INPUT:789790- ``index`` (integer) -- the variable's id791792- ``value`` -- real value, or ``None`` to mean that the793variable has not upper bound. When set to ``None``794(default), the method returns the current value.795796EXAMPLE::797798sage: from sage.numerical.backends.generic_backend import get_solver799sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver800sage: p.add_variable() # optional - Nonexistent_LP_solver8011802sage: p.col_bounds(0) # optional - Nonexistent_LP_solver803(0.0, None)804sage: p.variable_upper_bound(0, 5) # optional - Nonexistent_LP_solver805sage: p.col_bounds(0) # optional - Nonexistent_LP_solver806(0.0, 5.0)807"""808raise NotImplementedError()809810cpdef variable_lower_bound(self, int index, value = None):811"""812Return or define the lower bound on a variable813814INPUT:815816- ``index`` (integer) -- the variable's id817818- ``value`` -- real value, or ``None`` to mean that the819variable has not lower bound. When set to ``None``820(default), the method returns the current value.821822EXAMPLE::823824sage: from sage.numerical.backends.generic_backend import get_solver825sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver826sage: p.add_variable() # optional - Nonexistent_LP_solver8271828sage: p.col_bounds(0) # optional - Nonexistent_LP_solver829(0.0, None)830sage: p.variable_lower_bound(0, 5) # optional - Nonexistent_LP_solver831sage: p.col_bounds(0) # optional - Nonexistent_LP_solver832(5.0, None)833"""834raise NotImplementedError()835836cpdef solver_parameter(self, name, value = None):837"""838Return or define a solver parameter839840INPUT:841842- ``name`` (string) -- the parameter843844- ``value`` -- the parameter's value if it is to be defined,845or ``None`` (default) to obtain its current value.846847.. NOTE::848849The list of available parameters is available at850:meth:`~sage.numerical.mip.MixedIntegerLinearProgram.solver_parameter`.851852EXAMPLE::853854sage: from sage.numerical.backends.generic_backend import get_solver855sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver856sage: p.solver_parameter("timelimit") # optional - Nonexistent_LP_solver857sage: p.solver_parameter("timelimit", 60) # optional - Nonexistent_LP_solver858sage: p.solver_parameter("timelimit") # optional - Nonexistent_LP_solver859"""860raise NotImplementedError()861862863864default_solver = None865866def default_mip_solver(solver = None):867"""868Returns/Sets the default MILP Solver used by Sage869870INPUT:871872- ``solver`` -- defines the solver to use:873874- GLPK (``solver="GLPK"``). See the `GLPK875<http://www.gnu.org/software/glpk/>`_ web site.876877- COIN Branch and Cut (``solver="Coin"``). See the `COIN-OR878<http://www.coin-or.org>`_ web site.879880- CPLEX (``solver="CPLEX"``). See the881`CPLEX <http://www.ilog.com/products/cplex/>`_ web site.882883- Gurobi (``solver="Gurobi"``). See the `Gurobi884<http://www.gurobi.com/>`_ web site.885886``solver`` should then be equal to one of ``"GLPK"``,887``"Coin"``, ``"CPLEX"``, or ``"Gurobi"``.888889- If ``solver=None`` (default), the current default solver's name is890returned.891892OUTPUT:893894This function returns the current default solver's name if ``solver = None``895(default). Otherwise, it sets the default solver to the one given. If this896solver does not exist, or is not available, a ``ValueError`` exception is897raised.898899EXAMPLE::900901sage: former_solver = default_mip_solver()902sage: default_mip_solver("GLPK")903sage: default_mip_solver()904'Glpk'905sage: default_mip_solver("Yeahhhhhhhhhhh")906Traceback (most recent call last):907...908ValueError: 'solver' should be set to 'GLPK', 'Coin', 'CPLEX', 'Gurobi' or None.909sage: default_mip_solver(former_solver)910"""911global default_solver912913if solver is None:914915if default_solver is not None:916return default_solver917918else:919for s in ["Cplex", "Gurobi", "Coin", "Glpk"]:920try:921default_mip_solver(s)922return s923except ValueError:924pass925926solver = solver.capitalize()927928if solver == "Cplex":929try:930from sage.numerical.backends.cplex_backend import CPLEXBackend931default_solver = solver932except ImportError:933raise ValueError("CPLEX is not available. Please refer to the documentation to install it.")934935elif solver == "Coin":936try:937from sage.numerical.backends.coin_backend import CoinBackend938default_solver = solver939except ImportError:940raise ValueError("COIN is not available. Please refer to the documentation to install it.")941942elif solver == "Gurobi":943try:944from sage.numerical.backends.gurobi_backend import GurobiBackend945default_solver = solver946except ImportError:947raise ValueError("Gurobi is not available. Please refer to the documentation to install it.")948949elif solver == "Glpk":950default_solver = solver951952else:953raise ValueError("'solver' should be set to 'GLPK', 'Coin', 'CPLEX', 'Gurobi' or None.")954955cpdef GenericBackend get_solver(constraint_generation = False, solver = None):956"""957Return a solver according to the given preferences958959INPUT:960961- ``solver`` -- 4 solvers should be available through this class:962963- GLPK (``solver="GLPK"``). See the `GLPK964<http://www.gnu.org/software/glpk/>`_ web site.965966- COIN Branch and Cut (``solver="Coin"``). See the `COIN-OR967<http://www.coin-or.org>`_ web site.968969- CPLEX (``solver="CPLEX"``). See the970`CPLEX <http://www.ilog.com/products/cplex/>`_ web site.971972- Gurobi (``solver="Gurobi"``). See the `Gurobi973<http://www.gurobi.com/>`_ web site.974975- PPL (``solver="PPL"``). See the `PPL976<http://bugseng.com/products/ppl>`_ web site.977978``solver`` should then be equal to one of ``"GLPK"``, ``"Coin"``,979``"CPLEX"``, ``"Gurobi"``, ``"PPL"``, or ``None``. If ``solver=None`` (default),980the default solver is used (see ``default_mip_solver`` method.981982- ``constraint_generation`` (boolean) -- whether the solver983returned is to be used for constraint/variable generation. As984the interface with Coin does not support constraint/variable985generation, setting ``constraint_generation`` to ``False``986ensures that the backend to Coin is not returned when ``solver =987None``. This is set to ``False`` by default.988989.. SEEALSO::990991- :func:`default_mip_solver` -- Returns/Sets the default MIP solver.992993EXAMPLE::994995sage: from sage.numerical.backends.generic_backend import get_solver996sage: p = get_solver()997"""998if solver is None:999solver = default_mip_solver()10001001# We do not want to use Coin for constraint_generation. It just does not1002# work1003if solver == "Coin" and constraint_generation:1004solver = "Glpk"10051006else:1007solver = solver.capitalize()10081009if solver == "Coin":1010from sage.numerical.backends.coin_backend import CoinBackend1011return CoinBackend()10121013elif solver == "Glpk":1014from sage.numerical.backends.glpk_backend import GLPKBackend1015return GLPKBackend()10161017elif solver == "Cplex":1018from sage.numerical.backends.cplex_backend import CPLEXBackend1019return CPLEXBackend()10201021elif solver == "Gurobi":1022from sage.numerical.backends.gurobi_backend import GurobiBackend1023return GurobiBackend()10241025elif solver == "Ppl":1026from sage.numerical.backends.ppl_backend import PPLBackend1027return PPLBackend()10281029else:1030raise ValueError("'solver' should be set to 'GLPK', 'Coin', 'CPLEX', 'Gurobi', 'PPL' or None (in which case the default one is used).")103110321033