Logging Backend - Numerical Optimization

Skip to content
Back to top
View this page
Edit this page

# Logging Backend

It records, for debugging and unit testing purposes, all calls to backend methods in one of three ways.

See `LoggingBackendFactory` for more information.

class sage.numerical.backends.logging_backend.LoggingBackend(backend, printing=True, doctest=None, test_method=None, base_ring=None)

  Bases: `GenericBackend`

  See `LoggingBackendFactory` for documentation.

  EXAMPLES:

  Sage

      sage: import sage.numerical.backends.logging_backend
      sage: from sage.numerical.backends.logging_backend import LoggingBackend
      sage: from sage.numerical.backends.generic_backend import get_solver
      sage: b = get_solver(solver = "GLPK")
      sage: lb = LoggingBackend(backend=b)
      sage: lb.add_variable(obj=42, name='Helloooooo')
      # p.add_variable(obj=42, name='Helloooooo')
      # result: 0
      0
      sage: lb.add_variable(obj=1789)
      # p.add_variable(obj=1789)
      # result: 1
      1

  Python

      >>> from sage.all import *
      >>> import sage.numerical.backends.logging_backend
      >>> from sage.numerical.backends.logging_backend import LoggingBackend
      >>> from sage.numerical.backends.generic_backend import get_solver
      >>> b = get_solver(solver = "GLPK")
      >>> lb = LoggingBackend(backend=b)
      >>> lb.add_variable(obj=Integer(42), name='Helloooooo')
      # p.add_variable(obj=42, name='Helloooooo')
      # result: 0
      0
      >>> lb.add_variable(obj=Integer(1789))
      # p.add_variable(obj=1789)
      # result: 1
      1

  add_col(indices, coeffs)

    Add a column.

    INPUT:

    - `indices` – list of integers; this list contains the indices of the constraints in which the variable’s coefficient is nonzero

    - `coeffs` – list of real values; associates a coefficient to the variable in each of the constraints in which it appears. Namely, the i-th entry of `coeffs` corresponds to the coefficient of the variable in the constraint represented by the i-th entry in `indices`.

    Note

    `indices` and `coeffs` are expected to be of the same length.

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.ncols()
        0
        sage: p.nrows()
        0
        sage: p.add_linear_constraints(5, 0, None)
        sage: p.add_col(list(range(5)), list(range(5)))
        sage: p.nrows()
        5

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.ncols()
        0
        >>> p.nrows()
        0
        >>> p.add_linear_constraints(Integer(5), Integer(0), None)
        >>> p.add_col(list(range(Integer(5))), list(range(Integer(5))))
        >>> p.nrows()
        5

  add_linear_constraint(coefficients, lower_bound, upper_bound, name=None)

    Add a linear constraint.

    INPUT:

    - `coefficients` – an iterable of pairs `(i, v)`. In each pair, `i` is a variable index (integer) and `v` is a value (element of `base_ring()`).

    - `lower_bound` – element of `base_ring()` or `None`; the lower bound

    - `upper_bound` – element of `base_ring()` or `None`; the upper bound

    - `name` – string or `None`; optional name for this row

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_variables(5)
        4
        sage: p.add_linear_constraint( zip(range(5), range(5)), 2.0, 2.0)
        sage: p.row(0)
        ([0, 1, 2, 3, 4], [0.0, 1.0, 2.0, 3.0, 4.0])
        sage: p.row_bounds(0)
        (2.0, 2.0)
        sage: p.add_linear_constraint( zip(range(5), range(5)), 1.0, 1.0, name='foo')
        sage: p.row_name(1)
        'foo'

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_variables(Integer(5))
        4
        >>> p.add_linear_constraint( zip(range(Integer(5)), range(Integer(5))), RealNumber('2.0'), RealNumber('2.0'))
        >>> p.row(Integer(0))
        ([0, 1, 2, 3, 4], [0.0, 1.0, 2.0, 3.0, 4.0])
        >>> p.row_bounds(Integer(0))
        (2.0, 2.0)
        >>> p.add_linear_constraint( zip(range(Integer(5)), range(Integer(5))), RealNumber('1.0'), RealNumber('1.0'), name='foo')
        >>> p.row_name(Integer(1))
        'foo'

  add_linear_constraint_vector(degree, coefficients, lower_bound, upper_bound, name=None)

    Add a vector-valued linear constraint.

    Note

    This is the generic implementation, which will split the vector-valued constraint into components and add these individually. Backends are encouraged to replace it with their own optimized implementation.

    INPUT:

    - `degree` – integer; the vector degree, that is, the number of new scalar constraints

    - `coefficients` – an iterable of pairs `(i, v)`. In each pair, `i` is a variable index (integer) and `v` is a vector (real and of length `degree`).

    - `lower_bound` – either a vector or `None`; the component-wise lower bound

    - `upper_bound` – either a vector or `None`; the component-wise upper bound

    - `name` – string or `None`; an optional name for all new rows

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: coeffs = ([0, vector([1, 2])], [1, vector([2, 3])])
        sage: upper = vector([5, 5])
        sage: lower = vector([0, 0])
        sage: p.add_variables(2)
        1
        sage: p.add_linear_constraint_vector(2, coeffs, lower, upper, 'foo')

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> coeffs = ([Integer(0), vector([Integer(1), Integer(2)])], [Integer(1), vector([Integer(2), Integer(3)])])
        >>> upper = vector([Integer(5), Integer(5)])
        >>> lower = vector([Integer(0), Integer(0)])
        >>> p.add_variables(Integer(2))
        1
        >>> p.add_linear_constraint_vector(Integer(2), coeffs, lower, upper, 'foo')

  add_linear_constraints(number, lower_bound, upper_bound, names=None)

    Add `'number` linear constraints.

    INPUT:

    - `number` – integer; the number of constraints to add

    - `lower_bound` – a lower bound, either a real value or `None`

    - `upper_bound` – an upper bound, either a real value or `None`

    - `names` – an optional list of names (default: `None`)

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_variables(5)
        5
        sage: p.add_linear_constraints(5, None, 2)
        sage: p.row(4)
        ([], [])
        sage: p.row_bounds(4)
        (None, 2.0)

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_variables(Integer(5))
        5
        >>> p.add_linear_constraints(Integer(5), None, Integer(2))
        >>> p.row(Integer(4))
        ([], [])
        >>> p.row_bounds(Integer(4))
        (None, 2.0)

  add_variable(*args, **kwdargs)

    Add a variable.

    This amounts to adding a new column to the matrix. By default, the variable is both positive and real.

    INPUT:

    - `lower_bound` – the lower bound of the variable (default: 0)

    - `upper_bound` – the upper bound of the variable (default: `None`)

    - `binary` – `True` if the variable is binary (default: `False`)

    - `continuous` – `True` if the variable is continuous (default: `True`)

    - `integer` – `True` if the variable is integral (default: `False`)

    - `obj` – (optional) coefficient of this variable in the objective function (default: 0.0)

    - `name` – an optional name for the newly added variable (default: `None`)

    OUTPUT: the index of the newly created variable

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.ncols()
        0
        sage: p.add_variable()
        0
        sage: p.ncols()
        1
        sage: p.add_variable(binary=True)
        1
        sage: p.add_variable(lower_bound=-2.0, integer=True)
        2
        sage: p.add_variable(continuous=True, integer=True)
        Traceback (most recent call last):
        ...
        ValueError: ...
        sage: p.add_variable(name='x', obj=1.0)
        3
        sage: p.col_name(3)
        'x'
        sage: p.objective_coefficient(3)
        1.0

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.ncols()
        0
        >>> p.add_variable()
        0
        >>> p.ncols()
        1
        >>> p.add_variable(binary=True)
        1
        >>> p.add_variable(lower_bound=-RealNumber('2.0'), integer=True)
        2
        >>> p.add_variable(continuous=True, integer=True)
        Traceback (most recent call last):
        ...
        ValueError: ...
        >>> p.add_variable(name='x', obj=RealNumber('1.0'))
        3
        >>> p.col_name(Integer(3))
        'x'
        >>> p.objective_coefficient(Integer(3))
        1.0

  add_variables(*args, **kwdargs)

    Add `n` variables.

    This amounts to adding new columns to the matrix. By default, the variables are both nonnegative and real.

    INPUT:

    - `n` – the number of new variables (must be > 0)

    - `lower_bound` – the lower bound of the variable (default: 0)

    - `upper_bound` – the upper bound of the variable (default: `None`)

    - `binary` – `True` if the variable is binary (default: `False`)

    - `continuous` – `True` if the variable is binary (default: `True`)

    - `integer` – `True` if the variable is binary (default: `False`)

    - `obj` – coefficient of all variables in the objective function (default: 0.0)

    - `names` – list of names (default: `None`)

    OUTPUT: the index of the variable created last

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.ncols()
        0
        sage: p.add_variables(5)
        4
        sage: p.ncols()
        5
        sage: p.add_variables(2, lower_bound=-2.0, integer=True, names=['a','b'])
        6

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.ncols()
        0
        >>> p.add_variables(Integer(5))
        4
        >>> p.ncols()
        5
        >>> p.add_variables(Integer(2), lower_bound=-RealNumber('2.0'), integer=True, names=['a','b'])
        6

  base_ring()

    Return the base ring.

    The backend’s base ring can be overridden. It is best to run the tests with GLPK and override the base ring to `QQ`. Then default input to backend methods, prepared by `MixedIntegerLinearProgram`, depends on the base ring. This way input will be rational and so suitable for both exact and inexact methods; whereas output will be float and will thus trigger `assertAlmostEqual()` tests.

    EXAMPLES:

    Sage

        sage: import sage.numerical.backends.logging_backend
        sage: from sage.numerical.backends.logging_backend import LoggingBackend
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: b = get_solver(solver = "GLPK")
        sage: lb = LoggingBackend(backend=b)
        sage: lb.base_ring()
        Real Double Field
        sage: from sage.rings.rational_field import QQ
        sage: lb = LoggingBackend(backend=b, base_ring=QQ)
        sage: lb.base_ring()
        Rational Field

    Python

        >>> from sage.all import *
        >>> import sage.numerical.backends.logging_backend
        >>> from sage.numerical.backends.logging_backend import LoggingBackend
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> b = get_solver(solver = "GLPK")
        >>> lb = LoggingBackend(backend=b)
        >>> lb.base_ring()
        Real Double Field
        >>> from sage.rings.rational_field import QQ
        >>> lb = LoggingBackend(backend=b, base_ring=QQ)
        >>> lb.base_ring()
        Rational Field

  best_known_objective_bound()

    Return the value of the currently best known bound.

    This method returns the current best upper (resp. lower) bound on the optimal value of the objective function in a maximization (resp. minimization) problem. It is equal to the output of `get_objective_value()` if the MILP found an optimal solution, but it can differ if it was interrupted manually or after a time limit (cf `solver_parameter()`).

    Note

    Has no meaning unless `solve` has been called before.

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: p = MixedIntegerLinearProgram(solver="Nonexistent_LP_solver")
        sage: b = p.new_variable(binary=True)
        sage: for u,v in graphs.CycleGraph(5).edges(labels=False):
        ....:     p.add_constraint(b[u]+b[v]<=1)
        sage: p.set_objective(p.sum(b[x] for x in range(5)))
        sage: p.solve()
        2.0
        sage: pb = p.get_backend()
        sage: pb.get_objective_value()
        2.0
        sage: pb.best_known_objective_bound()
        2.0

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> p = MixedIntegerLinearProgram(solver="Nonexistent_LP_solver")
        >>> b = p.new_variable(binary=True)
        >>> for u,v in graphs.CycleGraph(Integer(5)).edges(labels=False):
        ...     p.add_constraint(b[u]+b[v]<=Integer(1))
        >>> p.set_objective(p.sum(b[x] for x in range(Integer(5))))
        >>> p.solve()
        2.0
        >>> pb = p.get_backend()
        >>> pb.get_objective_value()
        2.0
        >>> pb.best_known_objective_bound()
        2.0

  category()
  col_bounds(index)

    Return the bounds of a specific variable.

    INPUT:

    - `index` – integer; the variable’s id

    OUTPUT:

    A pair `(lower_bound, upper_bound)`. Each of them can be set to `None` if the variable is not bounded in the corresponding direction, and is a real value otherwise.

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_variable()
        0
        sage: p.col_bounds(0)
        (0.0, None)
        sage: p.variable_upper_bound(0, 5)
        sage: p.col_bounds(0)
        (0.0, 5.0)

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_variable()
        0
        >>> p.col_bounds(Integer(0))
        (0.0, None)
        >>> p.variable_upper_bound(Integer(0), Integer(5))
        >>> p.col_bounds(Integer(0))
        (0.0, 5.0)

  col_name(index)

    Return the `index`-th column name.

    INPUT:

    - `index` – integer; the column id

    - `name` – (`char *`) its name; when set to `NULL` (default), the method returns the current name

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_variable(name="I am a variable")
        1
        sage: p.col_name(0)
        'I am a variable'

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_variable(name="I am a variable")
        1
        >>> p.col_name(Integer(0))
        'I am a variable'

  copy()

    Return a copy of `self`.

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = MixedIntegerLinearProgram(solver="Nonexistent_LP_solver")
        sage: b = p.new_variable()
        sage: p.add_constraint(b[1] + b[2] <= 6)
        sage: p.set_objective(b[1] + b[2])
        sage: copy(p).solve()
        6.0

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = MixedIntegerLinearProgram(solver="Nonexistent_LP_solver")
        >>> b = p.new_variable()
        >>> p.add_constraint(b[Integer(1)] + b[Integer(2)] <= Integer(6))
        >>> p.set_objective(b[Integer(1)] + b[Integer(2)])
        >>> copy(p).solve()
        6.0

  dump(filename, compress=True)

    Same as self.save(filename, compress)

  dumps(compress=True)

    Dump `self` to a string `s`, which can later be reconstituted as `self` using `loads(s)`.

    There is an optional boolean argument `compress` which defaults to `True`.

    EXAMPLES:

    Sage

        sage: from sage.misc.persist import comp
        sage: O = SageObject()
        sage: p_comp = O.dumps()
        sage: p_uncomp = O.dumps(compress=False)
        sage: comp.decompress(p_comp) == p_uncomp
        True
        sage: import pickletools
        sage: pickletools.dis(p_uncomp)
            0: \x80 PROTO      2
            2: c    GLOBAL     'sage.structure.sage_object SageObject'
           41: q    BINPUT     ...
           43: )    EMPTY_TUPLE
           44: \x81 NEWOBJ
           45: q    BINPUT     ...
           47: .    STOP
        highest protocol among opcodes = 2

    Python

        >>> from sage.all import *
        >>> from sage.misc.persist import comp
        >>> O = SageObject()
        >>> p_comp = O.dumps()
        >>> p_uncomp = O.dumps(compress=False)
        >>> comp.decompress(p_comp) == p_uncomp
        True
        >>> import pickletools
        >>> pickletools.dis(p_uncomp)
            0: \x80 PROTO      2
            2: c    GLOBAL     'sage.structure.sage_object SageObject'
           41: q    BINPUT     ...
           43: )    EMPTY_TUPLE
           44: \x81 NEWOBJ
           45: q    BINPUT     ...
           47: .    STOP
        highest protocol among opcodes = 2

  get_custom_name()

    Return the custom name of this object, or `None` if it is not renamed.

    EXAMPLES:

    Sage

        sage: P.<x> = QQ[]
        sage: P.get_custom_name() is None
        True
        sage: P.rename('A polynomial ring')
        sage: P.get_custom_name()
        'A polynomial ring'
        sage: P.reset_name()
        sage: P.get_custom_name() is None
        True

    Python

        >>> from sage.all import *
        >>> P = QQ['x']; (x,) = P._first_ngens(1)
        >>> P.get_custom_name() is None
        True
        >>> P.rename('A polynomial ring')
        >>> P.get_custom_name()
        'A polynomial ring'
        >>> P.reset_name()
        >>> P.get_custom_name() is None
        True

  get_objective_value()

    Return the value of the objective function.

    Note

    Behavior is undefined unless `solve` has been called before.

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_variables(2)
        1
        sage: p.add_linear_constraint([(0,1), (1,2)], None, 3)
        sage: p.set_objective([2, 5])
        sage: p.solve()
        0
        sage: p.get_objective_value()
        7.5
        sage: p.get_variable_value(0)
        0.0
        sage: p.get_variable_value(1)
        1.5

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_variables(Integer(2))
        1
        >>> p.add_linear_constraint([(Integer(0),Integer(1)), (Integer(1),Integer(2))], None, Integer(3))
        >>> p.set_objective([Integer(2), Integer(5)])
        >>> p.solve()
        0
        >>> p.get_objective_value()
        7.5
        >>> p.get_variable_value(Integer(0))
        0.0
        >>> p.get_variable_value(Integer(1))
        1.5

  get_relative_objective_gap()

    Return the relative objective gap of the best known solution.

    For a minimization problem, this value is computed by \((\texttt{bestinteger} - \texttt{bestobjective}) / (1e-10 + |\texttt{bestobjective}|)\), where `bestinteger` is the value returned by `get_objective_value()` and `bestobjective` is the value returned by `best_known_objective_bound()`. For a maximization problem, the value is computed by \((\texttt{bestobjective} - \texttt{bestinteger}) / (1e-10 + |\texttt{bestobjective}|)\).

    Note

    Has no meaning unless `solve` has been called before.

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: p = MixedIntegerLinearProgram(solver="Nonexistent_LP_solver")
        sage: b = p.new_variable(binary=True)
        sage: for u,v in graphs.CycleGraph(5).edges(labels=False):
        ....:     p.add_constraint(b[u]+b[v]<=1)
        sage: p.set_objective(p.sum(b[x] for x in range(5)))
        sage: p.solve()
        2.0
        sage: pb = p.get_backend()
        sage: pb.get_objective_value()
        2.0
        sage: pb.get_relative_objective_gap()
        0.0

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> p = MixedIntegerLinearProgram(solver="Nonexistent_LP_solver")
        >>> b = p.new_variable(binary=True)
        >>> for u,v in graphs.CycleGraph(Integer(5)).edges(labels=False):
        ...     p.add_constraint(b[u]+b[v]<=Integer(1))
        >>> p.set_objective(p.sum(b[x] for x in range(Integer(5))))
        >>> p.solve()
        2.0
        >>> pb = p.get_backend()
        >>> pb.get_objective_value()
        2.0
        >>> pb.get_relative_objective_gap()
        0.0

  get_variable_value(variable)

    Return the value of a variable given by the solver.

    Note

    Behavior is undefined unless `solve` has been called before.

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_variables(2)
        1
        sage: p.add_linear_constraint([(0,1), (1, 2)], None, 3)
        sage: p.set_objective([2, 5])
        sage: p.solve()
        0
        sage: p.get_objective_value()
        7.5
        sage: p.get_variable_value(0)
        0.0
        sage: p.get_variable_value(1)
        1.5

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_variables(Integer(2))
        1
        >>> p.add_linear_constraint([(Integer(0),Integer(1)), (Integer(1), Integer(2))], None, Integer(3))
        >>> p.set_objective([Integer(2), Integer(5)])
        >>> p.solve()
        0
        >>> p.get_objective_value()
        7.5
        >>> p.get_variable_value(Integer(0))
        0.0
        >>> p.get_variable_value(Integer(1))
        1.5

  is_maximization(*args, **kwdargs)

    Test whether the problem is a maximization

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.is_maximization()
        True
        sage: p.set_sense(-1)
        sage: p.is_maximization()
        False

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.is_maximization()
        True
        >>> p.set_sense(-Integer(1))
        >>> p.is_maximization()
        False

  is_slack_variable_basic(*args, **kwdargs)

    Test whether the slack variable of the given row is basic.

    This assumes that the problem has been solved with the simplex method and a basis is available. Otherwise an exception will be raised.

    INPUT:

    - `index` – integer; the variable’s id

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: p = MixedIntegerLinearProgram(maximization=True,
        ....:                               solver="Nonexistent_LP_solver")
        sage: x = p.new_variable(nonnegative=True)
        sage: p.add_constraint(-x[0] + x[1] <= 2)
        sage: p.add_constraint(8 * x[0] + 2 * x[1] <= 17)
        sage: p.set_objective(5.5 * x[0] - 3 * x[1])
        sage: b = p.get_backend()
        sage: # Backend-specific commands to instruct solver to use simplex method here
        sage: b.solve()
        0
        sage: b.is_slack_variable_basic(0)
        True
        sage: b.is_slack_variable_basic(1)
        False

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> p = MixedIntegerLinearProgram(maximization=True,
        ...                               solver="Nonexistent_LP_solver")
        >>> x = p.new_variable(nonnegative=True)
        >>> p.add_constraint(-x[Integer(0)] + x[Integer(1)] <= Integer(2))
        >>> p.add_constraint(Integer(8) * x[Integer(0)] + Integer(2) * x[Integer(1)] <= Integer(17))
        >>> p.set_objective(RealNumber('5.5') * x[Integer(0)] - Integer(3) * x[Integer(1)])
        >>> b = p.get_backend()
        >>> # Backend-specific commands to instruct solver to use simplex method here
        >>> b.solve()
        0
        >>> b.is_slack_variable_basic(Integer(0))
        True
        >>> b.is_slack_variable_basic(Integer(1))
        False

  is_slack_variable_nonbasic_at_lower_bound(*args, **kwdargs)

    Test whether the given variable is nonbasic at lower bound.

    This assumes that the problem has been solved with the simplex method and a basis is available. Otherwise an exception will be raised.

    INPUT:

    - `index` – integer; the variable’s id

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: p = MixedIntegerLinearProgram(maximization=True,
        ....:                               solver="Nonexistent_LP_solver")
        sage: x = p.new_variable(nonnegative=True)
        sage: p.add_constraint(-x[0] + x[1] <= 2)
        sage: p.add_constraint(8 * x[0] + 2 * x[1] <= 17)
        sage: p.set_objective(5.5 * x[0] - 3 * x[1])
        sage: b = p.get_backend()
        sage: # Backend-specific commands to instruct solver to use simplex method here
        sage: b.solve()
        0
        sage: b.is_slack_variable_nonbasic_at_lower_bound(0)
        False
        sage: b.is_slack_variable_nonbasic_at_lower_bound(1)
        True

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> p = MixedIntegerLinearProgram(maximization=True,
        ...                               solver="Nonexistent_LP_solver")
        >>> x = p.new_variable(nonnegative=True)
        >>> p.add_constraint(-x[Integer(0)] + x[Integer(1)] <= Integer(2))
        >>> p.add_constraint(Integer(8) * x[Integer(0)] + Integer(2) * x[Integer(1)] <= Integer(17))
        >>> p.set_objective(RealNumber('5.5') * x[Integer(0)] - Integer(3) * x[Integer(1)])
        >>> b = p.get_backend()
        >>> # Backend-specific commands to instruct solver to use simplex method here
        >>> b.solve()
        0
        >>> b.is_slack_variable_nonbasic_at_lower_bound(Integer(0))
        False
        >>> b.is_slack_variable_nonbasic_at_lower_bound(Integer(1))
        True

  is_variable_basic(*args, **kwdargs)

    Test whether the given variable is basic.

    This assumes that the problem has been solved with the simplex method and a basis is available. Otherwise an exception will be raised.

    INPUT:

    - `index` – integer; the variable’s id

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: p = MixedIntegerLinearProgram(maximization=True,
        ....:                               solver="Nonexistent_LP_solver")
        sage: x = p.new_variable(nonnegative=True)
        sage: p.add_constraint(-x[0] + x[1] <= 2)
        sage: p.add_constraint(8 * x[0] + 2 * x[1] <= 17)
        sage: p.set_objective(5.5 * x[0] - 3 * x[1])
        sage: b = p.get_backend()
        sage: # Backend-specific commands to instruct solver to use simplex method here
        sage: b.solve()
        0
        sage: b.is_variable_basic(0)
        True
        sage: b.is_variable_basic(1)
        False

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> p = MixedIntegerLinearProgram(maximization=True,
        ...                               solver="Nonexistent_LP_solver")
        >>> x = p.new_variable(nonnegative=True)
        >>> p.add_constraint(-x[Integer(0)] + x[Integer(1)] <= Integer(2))
        >>> p.add_constraint(Integer(8) * x[Integer(0)] + Integer(2) * x[Integer(1)] <= Integer(17))
        >>> p.set_objective(RealNumber('5.5') * x[Integer(0)] - Integer(3) * x[Integer(1)])
        >>> b = p.get_backend()
        >>> # Backend-specific commands to instruct solver to use simplex method here
        >>> b.solve()
        0
        >>> b.is_variable_basic(Integer(0))
        True
        >>> b.is_variable_basic(Integer(1))
        False

  is_variable_binary(*args, **kwdargs)

    Test whether the given variable is of binary type.

    INPUT:

    - `index` – integer; the variable’s id

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.ncols()
        0
        sage: p.add_variable()
        0
        sage: p.set_variable_type(0,0)
        sage: p.is_variable_binary(0)
        True

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.ncols()
        0
        >>> p.add_variable()
        0
        >>> p.set_variable_type(Integer(0),Integer(0))
        >>> p.is_variable_binary(Integer(0))
        True

  is_variable_continuous(*args, **kwdargs)

    Test whether the given variable is of continuous/real type.

    INPUT:

    - `index` – integer; the variable’s id

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.ncols()
        0
        sage: p.add_variable()
        0
        sage: p.is_variable_continuous(0)
        True
        sage: p.set_variable_type(0,1)
        sage: p.is_variable_continuous(0)
        False

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.ncols()
        0
        >>> p.add_variable()
        0
        >>> p.is_variable_continuous(Integer(0))
        True
        >>> p.set_variable_type(Integer(0),Integer(1))
        >>> p.is_variable_continuous(Integer(0))
        False

  is_variable_integer(*args, **kwdargs)

    Test whether the given variable is of integer type.

    INPUT:

    - `index` – integer; the variable’s id

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.ncols()
        0
        sage: p.add_variable()
        0
        sage: p.set_variable_type(0,1)
        sage: p.is_variable_integer(0)
        True

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.ncols()
        0
        >>> p.add_variable()
        0
        >>> p.set_variable_type(Integer(0),Integer(1))
        >>> p.is_variable_integer(Integer(0))
        True

  is_variable_nonbasic_at_lower_bound(*args, **kwdargs)

    Test whether the given variable is nonbasic at lower bound.

    This assumes that the problem has been solved with the simplex method and a basis is available. Otherwise an exception will be raised.

    INPUT:

    - `index` – integer; the variable’s id

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: p = MixedIntegerLinearProgram(maximization=True,
        ....:                               solver="Nonexistent_LP_solver")
        sage: x = p.new_variable(nonnegative=True)
        sage: p.add_constraint(-x[0] + x[1] <= 2)
        sage: p.add_constraint(8 * x[0] + 2 * x[1] <= 17)
        sage: p.set_objective(5.5 * x[0] - 3 * x[1])
        sage: b = p.get_backend()
        sage: # Backend-specific commands to instruct solver to use simplex method here
        sage: b.solve()
        0
        sage: b.is_variable_nonbasic_at_lower_bound(0)
        False
        sage: b.is_variable_nonbasic_at_lower_bound(1)
        True

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> p = MixedIntegerLinearProgram(maximization=True,
        ...                               solver="Nonexistent_LP_solver")
        >>> x = p.new_variable(nonnegative=True)
        >>> p.add_constraint(-x[Integer(0)] + x[Integer(1)] <= Integer(2))
        >>> p.add_constraint(Integer(8) * x[Integer(0)] + Integer(2) * x[Integer(1)] <= Integer(17))
        >>> p.set_objective(RealNumber('5.5') * x[Integer(0)] - Integer(3) * x[Integer(1)])
        >>> b = p.get_backend()
        >>> # Backend-specific commands to instruct solver to use simplex method here
        >>> b.solve()
        0
        >>> b.is_variable_nonbasic_at_lower_bound(Integer(0))
        False
        >>> b.is_variable_nonbasic_at_lower_bound(Integer(1))
        True

  ncols(*args, **kwdargs)

    Return the number of columns/variables.

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.ncols()
        0
        sage: p.add_variables(2)
        1
        sage: p.ncols()
        2

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.ncols()
        0
        >>> p.add_variables(Integer(2))
        1
        >>> p.ncols()
        2

  nrows(*args, **kwdargs)

    Return the number of rows/constraints.

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.nrows()
        0
        sage: p.add_linear_constraints(2, 2.0, None)
        sage: p.nrows()
        2

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.nrows()
        0
        >>> p.add_linear_constraints(Integer(2), RealNumber('2.0'), None)
        >>> p.nrows()
        2

  objective_coefficient(variable, coeff=None)

    Set or get the coefficient of a variable in the objective function

    INPUT:

    - `variable` – integer; the variable’s id

    - `coeff` – double; its coefficient

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_variable()
        0
        sage: p.objective_coefficient(0)
        0.0
        sage: p.objective_coefficient(0,2)
        sage: p.objective_coefficient(0)
        2.0

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_variable()
        0
        >>> p.objective_coefficient(Integer(0))
        0.0
        >>> p.objective_coefficient(Integer(0),Integer(2))
        >>> p.objective_coefficient(Integer(0))
        2.0

  objective_constant_term(d=None)

    Set or get the constant term in the objective function.

    INPUT:

    - `d` – double; its coefficient. If `None` (default), return the current value.

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.objective_constant_term()
        0.0
        sage: p.objective_constant_term(42)
        sage: p.objective_constant_term()
        42.0

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.objective_constant_term()
        0.0
        >>> p.objective_constant_term(Integer(42))
        >>> p.objective_constant_term()
        42.0

  parent()

    Return the type of `self` to support the coercion framework.

    EXAMPLES:

    Sage

        sage: t = log(sqrt(2) - 1) + log(sqrt(2) + 1); t                            # needs sage.symbolic
        log(sqrt(2) + 1) + log(sqrt(2) - 1)
        sage: u = t.maxima_methods()                                                # needs sage.symbolic
        sage: u.parent()                                                            # needs sage.symbolic
        <class 'sage.symbolic.maxima_wrapper.MaximaWrapper'>

    Python

        >>> from sage.all import *
        >>> t = log(sqrt(Integer(2)) - Integer(1)) + log(sqrt(Integer(2)) + Integer(1)); t                            # needs sage.symbolic
        log(sqrt(2) + 1) + log(sqrt(2) - 1)
        >>> u = t.maxima_methods()                                                # needs sage.symbolic
        >>> u.parent()                                                            # needs sage.symbolic
        <class 'sage.symbolic.maxima_wrapper.MaximaWrapper'>

  problem_name(name=None)

    Return or define the problem’s name.

    INPUT:

    - `name` – string; the problem’s name. When set to `None` (default), the method returns the problem’s name.

    EXAMPLES:

    Sage

        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")   # optional - Nonexistent_LP_solver
        sage: p.problem_name("There once was a french fry") # optional - Nonexistent_LP_solver
        sage: print(p.problem_name())                       # optional - Nonexistent_LP_solver
        There once was a french fry

    Python

        >>> from sage.all import *
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")   # optional - Nonexistent_LP_solver
        >>> p.problem_name("There once was a french fry") # optional - Nonexistent_LP_solver
        >>> print(p.problem_name())                       # optional - Nonexistent_LP_solver
        There once was a french fry

  remove_constraint(i)

    Remove a constraint.

    INPUT:

    - `i` – index of the constraint to remove

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: p = MixedIntegerLinearProgram(solver="Nonexistent_LP_solver")
        sage: v = p.new_variable(nonnegative=True)
        sage: x,y = v[0], v[1]
        sage: p.add_constraint(2*x + 3*y, max=6)
        sage: p.add_constraint(3*x + 2*y, max=6)
        sage: p.set_objective(x + y + 7)
        sage: p.set_integer(x); p.set_integer(y)
        sage: p.solve()
        9.0
        sage: p.remove_constraint(0)
        sage: p.solve()
        10.0
        sage: p.get_values([x,y])
        [0.0, 3.0]

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> p = MixedIntegerLinearProgram(solver="Nonexistent_LP_solver")
        >>> v = p.new_variable(nonnegative=True)
        >>> x,y = v[Integer(0)], v[Integer(1)]
        >>> p.add_constraint(Integer(2)*x + Integer(3)*y, max=Integer(6))
        >>> p.add_constraint(Integer(3)*x + Integer(2)*y, max=Integer(6))
        >>> p.set_objective(x + y + Integer(7))
        >>> p.set_integer(x); p.set_integer(y)
        >>> p.solve()
        9.0
        >>> p.remove_constraint(Integer(0))
        >>> p.solve()
        10.0
        >>> p.get_values([x,y])
        [0.0, 3.0]

  remove_constraints(constraints)

    Remove several constraints.

    INPUT:

    - `constraints` – an iterable containing the indices of the rows to remove

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_variables(2)
        1
        sage: p.add_linear_constraint([(0, 2), (1, 3)], None, 6)
        sage: p.add_linear_constraint([(0, 3), (1, 2)], None, 6)
        sage: p.remove_constraints([0, 1])

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_variables(Integer(2))
        1
        >>> p.add_linear_constraint([(Integer(0), Integer(2)), (Integer(1), Integer(3))], None, Integer(6))
        >>> p.add_linear_constraint([(Integer(0), Integer(3)), (Integer(1), Integer(2))], None, Integer(6))
        >>> p.remove_constraints([Integer(0), Integer(1)])

  rename(x=None)

    Change `self` so it prints as x, where x is a string.

    If x is `None`, the existing custom name is removed.

    Note

    This is only supported for Python classes that derive from SageObject.

    EXAMPLES:

    Sage

        sage: x = PolynomialRing(QQ, 'x', sparse=True).gen()
        sage: g = x^3 + x - 5
        sage: g
        x^3 + x - 5
        sage: g.rename('a polynomial')
        sage: g
        a polynomial
        sage: g + x
        x^3 + 2*x - 5
        sage: h = g^100
        sage: str(h)[:20]
        'x^300 + 100*x^298 - '
        sage: h.rename('x^300 + ...')
        sage: h
        x^300 + ...
        sage: g.rename(None)
        sage: g
        x^3 + x - 5

    Python

        >>> from sage.all import *
        >>> x = PolynomialRing(QQ, 'x', sparse=True).gen()
        >>> g = x**Integer(3) + x - Integer(5)
        >>> g
        x^3 + x - 5
        >>> g.rename('a polynomial')
        >>> g
        a polynomial
        >>> g + x
        x^3 + 2*x - 5
        >>> h = g**Integer(100)
        >>> str(h)[:Integer(20)]
        'x^300 + 100*x^298 - '
        >>> h.rename('x^300 + ...')
        >>> h
        x^300 + ...
        >>> g.rename(None)
        >>> g
        x^3 + x - 5

    Real numbers are not Python classes, so rename is not supported:

    Sage

        sage: a = 3.14
        sage: type(a)                                                               # needs sage.rings.real_mpfr
        <... 'sage.rings.real_mpfr.RealLiteral'>
        sage: a.rename('pi')                                                        # needs sage.rings.real_mpfr
        Traceback (most recent call last):
        ...
        NotImplementedError: object does not support renaming: 3.14000000000000

    [Python]

        >>> from sage.all import *
        >>> a = RealNumber('3.14')
        >>> type(a)                                                               # needs sage.rings.real_mpfr
        <... 'sage.rings.real_mpfr.RealLiteral'>
        >>> a.rename('pi')                                                        # needs sage.rings.real_mpfr
        Traceback (most recent call last):
        ...
        NotImplementedError: object does not support renaming: 3.14000000000000

    Note

    The reason C-extension types are not supported by default is if they were then every single one would have to carry around an extra attribute, which would be slower and waste a lot of memory.

    To support them for a specific class, add a `cdef public _SageObject__custom_name` attribute.

  reset_name()

    Remove the custom name of an object.

    EXAMPLES:

    Sage

        sage: P.<x> = QQ[]
        sage: P
        Univariate Polynomial Ring in x over Rational Field
        sage: P.rename('A polynomial ring')
        sage: P
        A polynomial ring
        sage: P.reset_name()
        sage: P
        Univariate Polynomial Ring in x over Rational Field

    Python

        >>> from sage.all import *
        >>> P = QQ['x']; (x,) = P._first_ngens(1)
        >>> P
        Univariate Polynomial Ring in x over Rational Field
        >>> P.rename('A polynomial ring')
        >>> P
        A polynomial ring
        >>> P.reset_name()
        >>> P
        Univariate Polynomial Ring in x over Rational Field

  row(i)

    Return a row.

    INPUT:

    - `index` – integer; the constraint’s id

    OUTPUT:

    A pair `(indices, coeffs)` where `indices` lists the entries whose coefficient is nonzero, and to which `coeffs` associates their coefficient on the model of the `add_linear_constraint` method.

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_variables(5)
        4
        sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2)
        sage: p.row(0)
        ([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0]) ## FIXME: Why backwards?
        sage: p.row_bounds(0)
        (2.0, 2.0)

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_variables(Integer(5))
        4
        >>> p.add_linear_constraint(zip(range(Integer(5)), range(Integer(5))), Integer(2), Integer(2))
        >>> p.row(Integer(0))
        ([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0]) ## FIXME: Why backwards?
        >>> p.row_bounds(Integer(0))
        (2.0, 2.0)

  row_bounds(index)

    Return the bounds of a specific constraint.

    INPUT:

    - `index` – integer; the constraint’s id

    OUTPUT:

    A pair `(lower_bound, upper_bound)`. Each of them can be set to `None` if the constraint is not bounded in the corresponding direction, and is a real value otherwise.

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_variables(5)
        4
        sage: p.add_linear_constraint(list(range(5)), list(range(5)), 2, 2)
        sage: p.row(0)
        ([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0]) ## FIXME: Why backwards?
        sage: p.row_bounds(0)
        (2.0, 2.0)

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_variables(Integer(5))
        4
        >>> p.add_linear_constraint(list(range(Integer(5))), list(range(Integer(5))), Integer(2), Integer(2))
        >>> p.row(Integer(0))
        ([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0]) ## FIXME: Why backwards?
        >>> p.row_bounds(Integer(0))
        (2.0, 2.0)

  row_name(index)

    Return the `index`-th row name.

    INPUT:

    - `index` – integer; the row’s id

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_linear_constraints(1, 2, None, names=['Empty constraint 1'])
        sage: p.row_name(0)
        'Empty constraint 1'

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_linear_constraints(Integer(1), Integer(2), None, names=['Empty constraint 1'])
        >>> p.row_name(Integer(0))
        'Empty constraint 1'

  save(filename=None, compress=True)

    Save `self` to the given filename.

    EXAMPLES:

    Sage

        sage: # needs sage.symbolic
        sage: x = SR.var("x")
        sage: f = x^3 + 5
        sage: from tempfile import NamedTemporaryFile
        sage: with NamedTemporaryFile(suffix='.sobj') as t:
        ....:     f.save(t.name)
        ....:     load(t.name)
        x^3 + 5

    Python

        >>> from sage.all import *
        >>> # needs sage.symbolic
        >>> x = SR.var("x")
        >>> f = x**Integer(3) + Integer(5)
        >>> from tempfile import NamedTemporaryFile
        >>> with NamedTemporaryFile(suffix='.sobj') as t:
        ...     f.save(t.name)
        ...     load(t.name)
        x^3 + 5

  set_objective(coeff, d=0.0)

    Set the objective function.

    INPUT:

    - `coeff` – list of real values, whose i-th element is the coefficient of the i-th variable in the objective function

    - `d` – double; the constant term in the linear function (set to \(0\) by default)

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_variables(5)
        4
        sage: p.set_objective([1, 1, 2, 1, 3])
        sage: [p.objective_coefficient(x) for x in range(5)]
        [1.0, 1.0, 2.0, 1.0, 3.0]

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_variables(Integer(5))
        4
        >>> p.set_objective([Integer(1), Integer(1), Integer(2), Integer(1), Integer(3)])
        >>> [p.objective_coefficient(x) for x in range(Integer(5))]
        [1.0, 1.0, 2.0, 1.0, 3.0]

    Constants in the objective function are respected:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: p = MixedIntegerLinearProgram(solver='Nonexistent_LP_solver')
        sage: x,y = p[0], p[1]
        sage: p.add_constraint(2*x + 3*y, max=6)
        sage: p.add_constraint(3*x + 2*y, max=6)
        sage: p.set_objective(x + y + 7)
        sage: p.set_integer(x); p.set_integer(y)
        sage: p.solve()
        9.0

    [Python]

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> p = MixedIntegerLinearProgram(solver='Nonexistent_LP_solver')
        >>> x,y = p[Integer(0)], p[Integer(1)]
        >>> p.add_constraint(Integer(2)*x + Integer(3)*y, max=Integer(6))
        >>> p.add_constraint(Integer(3)*x + Integer(2)*y, max=Integer(6))
        >>> p.set_objective(x + y + Integer(7))
        >>> p.set_integer(x); p.set_integer(y)
        >>> p.solve()
        9.0

  set_sense(sense)

    Set the direction (maximization/minimization).

    INPUT:

    - `sense` – integer:

      > - +1 => Maximization

      > - -1 => Minimization

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.is_maximization()
        True
        sage: p.set_sense(-1)
        sage: p.is_maximization()
        False

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.is_maximization()
        True
        >>> p.set_sense(-Integer(1))
        >>> p.is_maximization()
        False

  set_variable_type(variable, vtype)

    Set the type of a variable.

    INPUT:

    - `variable` – integer; the variable’s id

    - `vtype` – integer:

      - \(1\) Integer

      - \(0\) Binary

      - \(-1\) Continuous

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.ncols()
        0
        sage: p.add_variable()
        0
        sage: p.set_variable_type(0,1)
        sage: p.is_variable_integer(0)
        True

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.ncols()
        0
        >>> p.add_variable()
        0
        >>> p.set_variable_type(Integer(0),Integer(1))
        >>> p.is_variable_integer(Integer(0))
        True

  set_verbosity(level)

    Set the log (verbosity) level.

    INPUT:

    - `level` – integer; from 0 (no verbosity) to 3

    EXAMPLES:

    Sage

        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")  # optional - Nonexistent_LP_solver
        sage: p.set_verbosity(2)                                # optional - Nonexistent_LP_solver

    Python

        >>> from sage.all import *
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")  # optional - Nonexistent_LP_solver
        >>> p.set_verbosity(Integer(2))                                # optional - Nonexistent_LP_solver

  solve(*args, **kwdargs)

    Solve the problem.

    Note

    This method raises `MIPSolverException` exceptions when the solution cannot be computed for any reason (none exists, or the LP solver was not able to find it, etc…)

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_linear_constraints(5, 0, None)
        sage: p.add_col(list(range(5)), list(range(5)))
        sage: p.solve()
        0
        sage: p.objective_coefficient(0,1)
        sage: p.solve()
        Traceback (most recent call last):
        ...
        MIPSolverException: ...

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_linear_constraints(Integer(5), Integer(0), None)
        >>> p.add_col(list(range(Integer(5))), list(range(Integer(5))))
        >>> p.solve()
        0
        >>> p.objective_coefficient(Integer(0),Integer(1))
        >>> p.solve()
        Traceback (most recent call last):
        ...
        MIPSolverException: ...

  solver_parameter(name, value=None)

    Return or define a solver parameter.

    INPUT:

    - `name` – string; the parameter

    - `value` – the parameter’s value if it is to be defined, or `None` (default) to obtain its current value

    Note

    The list of available parameters is available at `solver_parameter()`.

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.solver_parameter("timelimit")
        sage: p.solver_parameter("timelimit", 60)
        sage: p.solver_parameter("timelimit")

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.solver_parameter("timelimit")
        >>> p.solver_parameter("timelimit", Integer(60))
        >>> p.solver_parameter("timelimit")

  variable_lower_bound(index, value=False)

    Return or define the lower bound on a variable.

    INPUT:

    - `index` – integer; the variable’s id

    - `value` – real value, or `None` to mean that the variable has not lower bound. When set to `False` (default), the method returns the current value.

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_variable()
        0
        sage: p.col_bounds(0)
        (0.0, None)
        sage: p.variable_lower_bound(0, 5)
        sage: p.col_bounds(0)
        (5.0, None)

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_variable()
        0
        >>> p.col_bounds(Integer(0))
        (0.0, None)
        >>> p.variable_lower_bound(Integer(0), Integer(5))
        >>> p.col_bounds(Integer(0))
        (5.0, None)

  variable_upper_bound(index, value=False)

    Return or define the upper bound on a variable.

    INPUT:

    - `index` – integer; the variable’s id

    - `value` – real value, or `None` to mean that the variable has not upper bound. When set to `False` (default), the method returns the current value.

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_variable()
        0
        sage: p.col_bounds(0)
        (0.0, None)
        sage: p.variable_upper_bound(0, 5)
        sage: p.col_bounds(0)
        (0.0, 5.0)

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_variable()
        0
        >>> p.col_bounds(Integer(0))
        (0.0, None)
        >>> p.variable_upper_bound(Integer(0), Integer(5))
        >>> p.col_bounds(Integer(0))
        (0.0, 5.0)

  write_lp(name)

    Write the problem to a `.lp` file.

    INPUT:

    - `filename` – string

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_variables(2)
        2
        sage: p.add_linear_constraint([(0, 1], (1, 2)], None, 3)
        sage: p.set_objective([2, 5])
        sage: from tempfile import NamedTemporaryFile
        sage: with NamedTemporaryFile(suffix='.lp') as f:
        ....:     p.write_lp(f.name)

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_variables(Integer(2))
        2
        >>> p.add_linear_constraint([(Integer(0), Integer(1)], (Integer(1), Integer(2))], None, Integer(3))
        >>> p.set_objective([Integer(2), Integer(5)])
        >>> from tempfile import NamedTemporaryFile
        >>> with NamedTemporaryFile(suffix='.lp') as f:
        ...     p.write_lp(f.name)

  write_mps(name, modern)

    Write the problem to a `.mps` file.

    INPUT:

    - `filename` – string

    EXAMPLES:

    Sage

        sage: # optional - nonexistent_lp_solver
        sage: from sage.numerical.backends.generic_backend import get_solver
        sage: p = get_solver(solver="Nonexistent_LP_solver")
        sage: p.add_variables(2)
        2
        sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3)
        sage: p.set_objective([2, 5])
        sage: from tempfile import NamedTemporaryFile
        sage: with NamedTemporaryFile(suffix='.lp') as f:
        ....:     p.write_lp(f.name)

    Python

        >>> from sage.all import *
        >>> # optional - nonexistent_lp_solver
        >>> from sage.numerical.backends.generic_backend import get_solver
        >>> p = get_solver(solver="Nonexistent_LP_solver")
        >>> p.add_variables(Integer(2))
        2
        >>> p.add_linear_constraint([(Integer(0), Integer(1)), (Integer(1), Integer(2))], None, Integer(3))
        >>> p.set_objective([Integer(2), Integer(5)])
        >>> from tempfile import NamedTemporaryFile
        >>> with NamedTemporaryFile(suffix='.lp') as f:
        ...     p.write_lp(f.name)

sage.numerical.backends.logging_backend.LoggingBackendFactory(solver=None, printing=True, doctest_file=None, test_method_file=None, test_method=None, base_ring=Rational Field)

  Factory that constructs a `LoggingBackend` for debugging and testing.

  An instance of it can be passed as the solver argument of `sage.numerical.backends.generic_backend.get_solver()` and `MixedIntegerLinearProgram`.

  EXAMPLES:

  Assume that we have the following function that does some computation using `MixedIntegerLinearProgram` (or MIP backend methods), and suppose we have observed that it works with the GLPK backend, but not with the COIN backend:

  Sage

      sage: def compute_something(solver='GLPK'):
      ....:     from sage.numerical.mip import MIPSolverException
      ....:     mip = MixedIntegerLinearProgram(solver=solver)
      ....:     lb = mip.get_backend()
      ....:     lb.add_variable(obj=42, name='Helloooooo')
      ....:     lb.add_variable(obj=1789)
      ....:     try:
      ....:         lb.solve()
      ....:     except MIPSolverException:
      ....:         return 4711
      ....:     else:
      ....:         return 91

  Python

      >>> from sage.all import *
      >>> def compute_something(solver='GLPK'):
      ...     from sage.numerical.mip import MIPSolverException
      ...     mip = MixedIntegerLinearProgram(solver=solver)
      ...     lb = mip.get_backend()
      ...     lb.add_variable(obj=Integer(42), name='Helloooooo')
      ...     lb.add_variable(obj=Integer(1789))
      ...     try:
      ...         lb.solve()
      ...     except MIPSolverException:
      ...         return Integer(4711)
      ...     else:
      ...         return Integer(91)

  We can investigate what the backend methods are doing by running a `LoggingBackend` in its in-terminal logging mode:

  Sage

      sage: import sage.numerical.backends.logging_backend
      sage: from sage.numerical.backends.logging_backend import LoggingBackendFactory
      sage: compute_something(solver = LoggingBackendFactory(solver='GLPK'))
      # p = get_solver(solver='GLPK')
      # p.add_variable(obj=42, name='Helloooooo')
      # result: 0
      # p.add_variable(obj=1789)
      # result: 1
      # p.solve()
      # exception: GLPK: The LP (relaxation) problem has no dual feasible solution
      4711

  [Python]

      >>> from sage.all import *
      >>> import sage.numerical.backends.logging_backend
      >>> from sage.numerical.backends.logging_backend import LoggingBackendFactory
      >>> compute_something(solver = LoggingBackendFactory(solver='GLPK'))
      # p = get_solver(solver='GLPK')
      # p.add_variable(obj=42, name='Helloooooo')
      # result: 0
      # p.add_variable(obj=1789)
      # result: 1
      # p.solve()
      # exception: GLPK: The LP (relaxation) problem has no dual feasible solution
      4711

  By replacing ‘GLPK’ by ‘COIN’ above, we can then compare the two logs and see where they differ.

  Imagine that we have now fixed the bug in the COIN backend, and we want to add a doctest that documents this fact. We do not want to call `compute_something` in the doctest, but rather just have a sequence of calls to backend methods.

  We can have the doctest autogenerated by running a `LoggingBackend` in its doctest-writing mode:

  Sage

      sage: fname = tmp_filename()
      sage: compute_something(solver = LoggingBackendFactory(solver='GLPK', printing=False,
      ....:                                                  doctest_file=fname))
      4711
      sage: with open(fname) as f:
      ....:     for line in f.readlines(): _ = sys.stdout.write('|{}'.format(line))
      |        sage: p = get_solver(solver='GLPK')
      |        sage: p.add_variable(obj=42, name='Helloooooo')
      |        0
      |        sage: p.add_variable(obj=1789)
      |        1
      |        sage: p.solve()
      |        Traceback (most recent call last):
      |        ...
      |        MIPSolverException: GLPK: The LP (relaxation) problem has no dual feasible solution

  Python

      >>> from sage.all import *
      >>> fname = tmp_filename()
      >>> compute_something(solver = LoggingBackendFactory(solver='GLPK', printing=False,
      ...                                                  doctest_file=fname))
      4711
      >>> with open(fname) as f:
      ...     for line in f.readlines(): _ = sys.stdout.write('|{}'.format(line))
      |        sage: p = get_solver(solver='GLPK')
      |        sage: p.add_variable(obj=42, name='Helloooooo')
      |        0
      |        sage: p.add_variable(obj=1789)
      |        1
      |        sage: p.solve()
      |        Traceback (most recent call last):
      |        ...
      |        MIPSolverException: GLPK: The LP (relaxation) problem has no dual feasible solution

  We then copy from the generated file and paste into the source code of the COIN backend.

  If this test seems valuable enough that all backends should be tested against it, we should create a test method instead of a docstring.

  We can have the test method autogenerated by running a `LoggingBackend` in its test-method-writing mode:

  Sage

      sage: fname = tmp_filename()
      sage: compute_something(solver= LoggingBackendFactory(solver='GLPK', printing=False,
      ....:                                                 test_method_file=fname,
      ....:                                                 test_method='something'))
      4711
      sage: with open(fname) as f:
      ....:     for line in f.readlines(): _ = sys.stdout.write('|{}'.format(line))
      |
      |    @classmethod
      |    def _test_something(cls, tester=None, **options):
      |        ...
      |        Run tests on ...
      |
      |        TESTS::
      |
      |            sage: from sage.numerical.backends.generic_backend import GenericBackend
      |            sage: p = GenericBackend()
      |            sage: p._test_something()
      |            Traceback (most recent call last):
      |            ...
      |            NotImplementedError
      |        ...
      |        p = cls()                         # fresh instance of the backend
      |        if tester is None:
      |            tester = p._tester(**options)
      |        tester.assertEqual(p.add_variable(obj=42, name='Helloooooo'), 0)
      |        tester.assertEqual(p.add_variable(obj=1789), 1)
      |        with tester.assertRaises(MIPSolverException) as cm:
      |            p.solve()

  [Python]

      >>> from sage.all import *
      >>> fname = tmp_filename()
      >>> compute_something(solver= LoggingBackendFactory(solver='GLPK', printing=False,
      ...                                                 test_method_file=fname,
      ...                                                 test_method='something'))
      4711
      >>> with open(fname) as f:
      ...     for line in f.readlines(): _ = sys.stdout.write('|{}'.format(line))
      |
      |    @classmethod
      |    def _test_something(cls, tester=None, **options):
      |        ...
      |        Run tests on ...
      |
      |        TESTS::
      |
      |            sage: from sage.numerical.backends.generic_backend import GenericBackend
      |            sage: p = GenericBackend()
      |            sage: p._test_something()
      |            Traceback (most recent call last):
      |            ...
      |            NotImplementedError
      |        ...
      |        p = cls()                         # fresh instance of the backend
      |        if tester is None:
      |            tester = p._tester(**options)
      |        tester.assertEqual(p.add_variable(obj=42, name='Helloooooo'), 0)
      |        tester.assertEqual(p.add_variable(obj=1789), 1)
      |        with tester.assertRaises(MIPSolverException) as cm:
      |            p.solve()

  We then copy from the generated file and paste into the source code of the generic backend, where all test methods are defined.

  If `test_method_file` is not provided, a default output file name will be computed from `test_method`.