Solver dictionaries

backends.abstract_backend_dictionary

class sage_numerical_interactive_mip.backends.abstract_backend_dictionary.LPAbstractBackendDictionary(backend)

Bases: LPAbstractDictionary

Construct an abstract dictionary for an LP problem from a backend.

INPUT:

  • backend – the backend that the dictionary is constructed from

OUTPUT: a backend dictionary for an LP problem

EXAMPLES:

One needs an instance of MixedIntegerLinearProgram to initialize this class:

sage: from sage_numerical_interactive_mip.backends.abstract_backend_dictionary import LPAbstractBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True)
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: d = LPAbstractBackendDictionary(b)
sage: d
LP problem dictionary (use ... details)
__eq__(other)

Check if two LP problem dictionaries have the same reference.

INPUT:

  • other – anything

OUTPUT:

  • True if other is an LPDictionary with its reference the same as self, False otherwise.

TESTS:

Setting up the problem:

sage: from sage_numerical_interactive_mip.backends.abstract_backend_dictionary import LPAbstractBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: d = LPAbstractBackendDictionary(b)

Test when two problems have the same reference:

sage: d2 = d
sage: d2 == d
True

Test when two problems have the same construction:

sage: d3 = LPAbstractBackendDictionary(copy(p).get_backend())
sage: d3 == d
False
__hash__ = None
__init__(backend)

Initialize internal fields for entering and leaving variables.

TESTS:

sage: from sage_numerical_interactive_mip import *
sage: A = ([1, 1], [3, 1])
sage: b = (1000, 1500)
sage: c = (10, 5)
sage: P = InteractiveLPProblemStandardForm(A, b, c)
sage: D = P.initial_dictionary()    # indirect doctest
static _format_(name='', symbol='x', infix='_', index='0')

Returns a proper name for a given parameter.

INPUT:

- ``name`` -- (defualt: '') the original name of the variable

-symbol – (defualt: ‘x’) the symbol for the new name

-infix – (default: ‘_’) the character separate the symbol and its index for the new name

-index – (default: ‘0’) the index following the infix for the new name

TESTS:

If a name is given, then returns the name itself:

sage: from sage_numerical_interactive_mip.backends.abstract_backend_dictionary import LPAbstractBackendDictionary
sage: LPAbstractBackendDictionary._format_('Name')
'Name'

However, if the name given is in the form ‘symbol[index]’, then it will be converted to ‘symbol+infix+index’ i.e. ‘symbol_index’ by default:

sage: LPAbstractBackendDictionary._format_('x[3]')
'x_3'
sage: LPAbstractBackendDictionary._format_('x[2]', infix='~')
'x~2'

If no name is given, then a newly create name will be returned in the form of ‘symbol+infix+index’:

sage: LPAbstractBackendDictionary._format_(symbol='w', index='7')
'w_7'
_load_new_variable_(index, name, auxiliary=True)

Load a new variable to buffer.

INPUT:

  • index – the index of the new variable

  • name – the name of the new variable

  • auxiliary – (default: True) if true, the symbol of the new variable will be ‘w’, ‘x’ otherwise.

EXAMPLE:

sage: from sage_numerical_interactive_mip.backends.abstract_backend_dictionary import LPAbstractBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: b.solve()
0
sage: d = LPAbstractBackendDictionary(b)
sage: d._x
(x_0, x_1, w_0, w_1)
_nonbasic_coef_to_problem_coef_(nonbasic_coef, constant)

Returns coefficients of nonbasic variables rewritten in terms of problem variables.

INPUT:

  • nonbasic_coef – a list of nonbasic coefficients for the new row

  • constant – a number of the constant term for the new row

OUTPUT:

  • coef_pairs – a list of tuples that indicate problem variable

indices and coefficients

  • constant – the re-calculated row bound

EXAMPLE:

sage: from sage_numerical_interactive_mip.backends.glpk_backend_dictionary import LPGLPKBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: import sage.numerical.backends.glpk_backend as backend
sage: b.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
sage: b.solve()
0
sage: d = LPGLPKBackendDictionary(b)
sage: nonbasic_coef = [3, 4, 5, 6]
sage: constant = 11
sage: pairs, const = d._nonbasic_coef_to_problem_coef_(nonbasic_coef, constant)
sage: pairs
[(0, -29.0), (1, -11.0)]
sage: const
-63.0
dictionary()

Return a regular LP dictionary matching self.

OUTPUT: an LP dictionary

EXAMPLES:

sage: from sage_numerical_interactive_mip.backends.glpk_backend_dictionary import LPGLPKBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: import sage.numerical.backends.glpk_backend as backend
sage: b.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
sage: b.solve()
0
sage: d = LPGLPKBackendDictionary(b)
sage: view(d.dictionary()) # not tested

Zeta is used as default problem name, and it can be changed:

sage: b.problem_name("beta")
sage: view(d.dictionary()) # not tested
get_backend()

Return the backend used to create the dictionary.

OUTPUT: the corresponding backend associated with self

EXAMPLES:

sage: from sage_numerical_interactive_mip.backends.abstract_backend_dictionary import LPAbstractBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: b.solve()
0
sage: d = LPAbstractBackendDictionary(b)
sage: d.get_backend()
<...GLPKBackend...>
objective_value()

Return the value of the objective value.

OUTPUT: a number

EXAMPLES:

sage: from sage_numerical_interactive_mip.backends.abstract_backend_dictionary import LPAbstractBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: b.solve()
0
sage: d = LPAbstractBackendDictionary(b)
sage: d.objective_value()
14.08

backends.glpk_backend_dictionary

class sage_numerical_interactive_mip.backends.glpk_backend_dictionary.LPGLPKBackendDictionary(backend)

Bases: LPAbstractBackendDictionary

Construct a dictionary for an LP problem from an backend.

INPUT:

  • backend – the backend where the dictionary is constructed from

OUTPUT: a backend dictionary for an LP problem

EXAMPLES:

One needs an instance of GLPKBackend to initialize this class:

sage: from sage_numerical_interactive_mip.backends.glpk_backend_dictionary import LPGLPKBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: d = LPGLPKBackendDictionary(b)
sage: d
LP problem dictionary (use ... details)
__init__(backend)

See LPGLPKBackendDictionary for documentation.

TESTS:

sage: from sage_numerical_interactive_mip.backends.glpk_backend_dictionary import LPGLPKBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: d = LPGLPKBackendDictionary(b)
sage: TestSuite(d).run(skip=['_test_pickling'])

An exception will be raised if the problem is not in standard form i.e. with <= constraints and >= 0 variable bounds:

sage: from sage_numerical_interactive_mip.backends.glpk_backend_dictionary import LPGLPKBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(8 * x[0] + 2 * x[1], min=17)
sage: p.set_objective(5.5 * x[0] + 2.1 * x[1])
sage: b = p.get_backend()
sage: d = LPGLPKBackendDictionary(b)
Traceback (most recent call last):
...
ValueError: Problem constraints not in standard form.
add_row(nonbasic_coef, constant, slack_variable, integer_slack_variable=False)

Update a dictionary with an additional row based on a given dictionary.

INPUT:

  • nonbasic_coef– a list of nonbasic coefficients for the new row

  • constant– a number of the constant term for the new row

  • slack_variable– a string of the name for the new slack variable

  • integer_slack_variable– (default: False) a boolean value indicating if the new slack variable is integer or not.

EXAMPLES:

sage: from sage_numerical_interactive_mip.backends.glpk_backend_dictionary import LPGLPKBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(x[0] + x[1] - 7*x[2] + x[3] <= 22)
sage: p.add_constraint(x[1] + 2*x[2] - x[3] <= 13)
sage: p.add_constraint(5*x[0] + x[2] <= 11)
sage: p.set_objective(2*x[0] + 3*x[1] + 4*x[2] + 13*x[3])
sage: b = p.get_backend()
sage: import sage.numerical.backends.glpk_backend as backend
sage: b.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
sage: b.solve()
0
sage: d = LPGLPKBackendDictionary(b)
sage: d.basic_variables()
(x_2, x_3, w_1)
sage: d.nonbasic_variables()
(x_0, x_1, w_0, w_2)
sage: d.objective_coefficients()
(-486.0, -10.0, -13.0, -95.0)
sage: d.add_row(range(3,7), 2, 'z_0')
sage: d.objective_coefficients()
(-486.0, -10.0, -13.0, -95.0)
sage: d.basic_variables()
(x_2, x_3, w_1, z_0)
sage: d.leave(d.basic_variables()[3])
sage: d.leaving_coefficients()
(3.0, 4.0, 5.0, 6.0)
sage: b.solve()
0
sage: d.basic_variables()
(x_2, x_3, w_1, z_0)
sage: d.nonbasic_variables()
(x_0, x_1, w_0, w_2)

Variables have 0 as their coefficient will not show up in the tableau:

sage: d.add_row(range(-2, 2), 5, 'z_1')
sage: d.get_backend().row(4)
([2, 1, 0], [-1.0, -1.0, -7.0])
basic_variables()

Return the basic variables of self.

OUTPUT: a vector

EXAMPLES:

Setting up the problem:

sage: from sage_numerical_interactive_mip.backends.glpk_backend_dictionary import LPGLPKBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: import sage.numerical.backends.glpk_backend as backend
sage: b.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
sage: b.solve()
0

Use function in LPGLPKBackendDictionary:

sage: d = LPGLPKBackendDictionary(b)

Use function in InteractiveLPProblem:

sage: lp, basis = p.interactive_lp_problem()
sage: lpd = lp.dictionary(*basis)

Compare results:

sage: d.basic_variables()
(x_0, x_1)
sage: lpd.basic_variables()
(x_0, x_1)
column_coefficients(v)

Return coefficients of a nonbasic variable.

INPUT:

  • v – a nonbasic variable of self, can be given as a string, an actual variable, or an integer interpreted as the index of a variable

OUTPUT: a vector

EXAMPLES:

sage: from sage_numerical_interactive_mip.backends.glpk_backend_dictionary import LPGLPKBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(x[0] + x[1] - 7*x[2] + x[3] <= 22)
sage: p.add_constraint(x[1] + 2*x[2] - x[3] <= 13)
sage: p.add_constraint(5*x[0] + x[2] <= 11)
sage: p.set_objective(2*x[0] + 3*x[1] + 4*x[2] + 13*x[3])
sage: b = p.get_backend()
sage: import sage.numerical.backends.glpk_backend as backend
sage: b.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
sage: b.solve()
0
sage: d = LPGLPKBackendDictionary(b)
sage: vars = d.nonbasic_variables()
sage: vars
(x_0, x_1, w_0, w_2)
sage: d.enter(vars[0])
sage: d.entering_coefficients()   # indirect doctest
(5.0, 36.0, 26.0)
sage: d.enter(vars[1])
sage: d.entering_coefficients()   # indirect doctest
(0.0, 1.0, 2.0)
constant_terms()

Return the constant terms of relations of self.

OUTPUT:

  • a vector.

EXAMPLES:

sage: from sage_numerical_interactive_mip.backends.glpk_backend_dictionary import LPGLPKBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: import sage.numerical.backends.glpk_backend as backend
sage: b.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
sage: b.solve()
0
sage: d = LPGLPKBackendDictionary(b)
sage: d.constant_terms()
(1.3, 3.3)
nonbasic_variables()

Return non-basic variables of self.

OUTPUT: a vector

EXAMPLES:

Setting up the problem:

sage: from sage_numerical_interactive_mip.backends.glpk_backend_dictionary import LPGLPKBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: import sage.numerical.backends.glpk_backend as backend
sage: b.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
sage: b.solve()
0

Use function in LPGLPKBackendDictionary:

sage: d = LPGLPKBackendDictionary(b)

Use function in InteractiveLPProblem:

sage: lp, basis = p.interactive_lp_problem()
sage: lpd = lp.dictionary(*basis)

Compare results:

sage: d.nonbasic_variables()
(w_0, w_1)
sage: lpd.nonbasic_variables()
(w_0, w_1)
objective_coefficients()

Return coefficients of the objective of self.

OUTPUT: a vector

EXAMPLES:

Setting up the problem:

sage: from sage_numerical_interactive_mip.backends.glpk_backend_dictionary import LPGLPKBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: import sage.numerical.backends.glpk_backend as backend
sage: b.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
sage: b.solve()
0

Use function in LPGLPKBackendDictionary:

sage: d = LPGLPKBackendDictionary(b)

Use function in InteractiveLPProblem:

sage: lp, basis = p.interactive_lp_problem()
sage: lpd = lp.dictionary(*basis)

Compare results:

sage: d.objective_coefficients()   # rel tol 1e-9
(-0.58, -0.76)
sage: lpd.objective_coefficients() # rel tol 1e-9
(-0.58, -0.76)
objective_name()

Return the objective name of self.

OUTPUT: a symbolic expression

row_coefficients(v)

Return coefficients of the basic variable v.

These are the coefficients with which nonbasic variables are subtracted in the relation for v.

INPUT:

  • v – a basic variable of self, can be given as a string, an actual variable, or an integer interpreted as the index of a variable

OUTPUT: a vector

EXAMPLES:

sage: from sage_numerical_interactive_mip.backends.glpk_backend_dictionary import LPGLPKBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(x[0] + x[1] - 7*x[2] + x[3] <= 22)
sage: p.add_constraint(x[1] + 2*x[2] - x[3] <= 13)
sage: p.add_constraint(5*x[0] + x[2] <= 11)
sage: p.set_objective(2*x[0] + 3*x[1] + 4*x[2] + 13*x[3])
sage: b = p.get_backend()
sage: import sage.numerical.backends.glpk_backend as backend
sage: b.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
sage: b.solve()
0
sage: d = LPGLPKBackendDictionary(b)
sage: vars = d.basic_variables()
sage: vars
(x_2, x_3, w_1)
sage: d.leave(vars[0])
sage: d.leaving_coefficients()   # indirect doctest
(5.0, 0.0, 0.0, 1.0)
sage: d.leave(vars[1])
sage: d.leaving_coefficients()   # indirect doctest
(36.0, 1.0, 1.0, 7.0)
update()

Update self using previously set entering and leaving variables.

EXAMPLES:

sage: from sage_numerical_interactive_mip.backends.glpk_backend_dictionary import LPGLPKBackendDictionary
sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(x[0] + x[1] - 7*x[2] + x[3] <= 22)
sage: p.add_constraint(x[1] + 2*x[2] - x[3] <= 13)
sage: p.add_constraint(5*x[0] + x[2] <= 11)
sage: p.set_objective(2*x[0] + 3*x[1] + 4*x[2] + 13*x[3])
sage: b = p.get_backend()
sage: import sage.numerical.backends.glpk_backend as backend
sage: b.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
sage: b.solve()
0
sage: d = LPGLPKBackendDictionary(b)
sage: d.objective_value()
1331.0
sage: d.nonbasic_variables()
(x_0, x_1, w_0, w_2)
sage: d.enter(d.nonbasic_variables()[0])
sage: d.basic_variables()
(x_2, x_3, w_1)
sage: d.leave(d.basic_variables()[0])
sage: d.objective_value()
1331.0
sage: d.update()
sage: d.basic_variables()
(x_0, x_3, w_1)
sage: d.nonbasic_variables()
(x_1, x_2, w_0, w_2)
sage: d.objective_value()
261.8

TESTS:

An error will be raised if the pivot selected is zero:

sage: from sage_numerical_interactive_mip.backends.glpk_backend_dictionary import LPGLPKBackendDictionary
sage: p = MixedIntegerLinearProgram(maximization=True, solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(x[0] + x[1] - 7*x[2] + x[3] <= 22)
sage: p.add_constraint(x[1] + 2*x[2] - x[3] <= 13)
sage: p.add_constraint(5*x[0] + x[2] <= 11)
sage: p.set_objective(2*x[0] + 3*x[1] + 4*x[2] + 13*x[3])
sage: b = p.get_backend()
sage: import sage.numerical.backends.glpk_backend as backend
sage: b.solver_parameter(backend.glp_simplex_or_intopt, backend.glp_simplex_only)
sage: b.solve()
0
sage: d = LPGLPKBackendDictionary(b)
sage: d.leave(d.basic_variables()[0])
sage: d.leaving_coefficients()
(5.0, 0.0, 0.0, 1.0)
sage: d.enter(d.nonbasic_variables()[1])
sage: d.leave(d.basic_variables()[0])
sage: d.update()
Traceback (most recent call last):
...
ValueError: incompatible choice of entering and leaving variables

backends.coin_backend_dictionary

class sage_numerical_interactive_mip.backends.coin_backend_dictionary.LPCoinBackendDictionary(backend)

Bases: LPAbstractBackendDictionary

Construct a dictionary for an LP problem from an backend.

INPUT:

  • backend – the backend that the dictionary is constructed from

OUTPUT: a backend dictionary for an LP problem

EXAMPLES:

One needs an instance of CoinBackend to initialize this class:

sage: from sage_numerical_interactive_mip.backends.coin_backend_dictionary import LPCoinBackendDictionary
sage: p = MixedIntegerLinearProgram(maximization=True, solver="Coin")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: d = LPCoinBackendDictionary(b)
sage: d
LP problem dictionary (use ... details)
__init__(backend)

See LPCoinBackendDictionary for documentation.

TESTS:

sage: from sage_numerical_interactive_mip.backends.coin_backend_dictionary import LPCoinBackendDictionary
sage: p = MixedIntegerLinearProgram(maximization=True, solver="Coin")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: d = LPCoinBackendDictionary(b)
sage: TestSuite(d).run(skip=['_test_pickling'])

An exception will be raised if the problem is not in standard form i.e. with <= constraints and >= 0 variable bounds:

sage: from sage_numerical_interactive_mip.backends.coin_backend_dictionary import LPCoinBackendDictionary
sage: p = MixedIntegerLinearProgram(maximization=True, solver="Coin")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(8 * x[0] + 2 * x[1], min=17)
sage: p.set_objective(5.5 * x[0] + 2.1 * x[1])
sage: b = p.get_backend()
sage: d = LPCoinBackendDictionary(b)
Traceback (most recent call last):
...
ValueError: Problem constraints not in standard form.
add_row(nonbasic_coef, constant, slack_variable, integer_slack_variable=False)

Update a dictionary with an additional row based on a given dictionary.

INPUT:

  • nonbasic_coef– a list of nonbasic coefficients for the new row

  • constant– a number of the constant term for the new row

  • slack_variable– a string of the name for the new slack variable

  • integer_slack_variable– (default: False) a boolean value indicating if the new slack variable is integer or not.

EXAMPLES:

sage: from sage_numerical_interactive_mip.backends.coin_backend_dictionary import LPCoinBackendDictionary
sage: p = MixedIntegerLinearProgram(maximization=True, solver="Coin")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(x[0] + x[1] - 7*x[2] + x[3] <= 22)
sage: p.add_constraint(x[1] + 2*x[2] - x[3] <= 13)
sage: p.add_constraint(5*x[0] + x[2] <= 11)
sage: p.set_objective(2*x[0] + 3*x[1] + 4*x[2] + 13*x[3])
sage: b = p.get_backend()
sage: b.solve()
0
sage: d = LPCoinBackendDictionary(b)
sage: d.basic_variables()
(x_2, x_3, w_1)
sage: d.nonbasic_variables()
(x_0, x_1, w_0, w_2)
sage: d.objective_coefficients()
(-486.0, -10.0, -13.0, -95.0)
sage: d.add_row(range(3,7), 2, 'z_0')
sage: d.objective_coefficients()
(-486.0, -10.0, -13.0, -95.0)
sage: d.basic_variables()
(x_2, x_3, w_1, z_0)
sage: d.leave(d.basic_variables()[3])
sage: d.leaving_coefficients()
(3.0, 4.0, 5.0, 6.0)
sage: b.solve()
0
sage: d.basic_variables()
(x_2, x_3, w_1, z_0)
sage: d.nonbasic_variables()
(x_0, x_1, w_0, w_2)

Variables have 0 as their coefficient will not show up in the tableau:

sage: d.add_row(range(-2, 2), 5, ‘z_1’) sage: d.get_backend().row(4) ([0, 1, 2], [-7.0, -1.0, -1.0])

basic_variables()

Return the basic variables of self.

OUTPUT: a vector

EXAMPLES:

sage: from sage_numerical_interactive_mip.backends.coin_backend_dictionary import LPCoinBackendDictionary
sage: p = MixedIntegerLinearProgram(maximization=True, solver="Coin")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: b.solve()
0
sage: d = LPCoinBackendDictionary(b)
sage: d.basic_variables()
(x_0, x_1)
column_coefficients(v)

Return coefficients of a nonbasic variable.

INPUT:

  • v – a nonbasic variable of self, can be given as a string, an actual variable, or an integer interpreted as the index of a variable

OUTPUT: a vector

EXAMPLES:

sage: from sage_numerical_interactive_mip.backends.coin_backend_dictionary import LPCoinBackendDictionary
sage: p = MixedIntegerLinearProgram(maximization=True, solver="Coin")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(x[0] + x[1] - 7*x[2] + x[3] <= 22)
sage: p.add_constraint(x[1] + 2*x[2] - x[3] <= 13)
sage: p.add_constraint(5*x[0] + x[2] <= 11)
sage: p.set_objective(2*x[0] + 3*x[1] + 4*x[2] + 13*x[3])
sage: b = p.get_backend()
sage: b.solve()
0
sage: d = LPCoinBackendDictionary(b)
sage: vars = d.nonbasic_variables()
sage: vars
(x_0, x_1, w_0, w_2)
sage: d.enter(vars[0])
sage: d.entering_coefficients()   # indirect doctest
(36.0, 26.0, 5.0)
sage: d.enter(vars[1])
sage: d.entering_coefficients()   # indirect doctest
(1.0, 2.0, 0.0)
constant_terms()

Return the constant terms of relations of self.

OUTPUT: a vector.

EXAMPLES:

sage: from sage_numerical_interactive_mip.backends.coin_backend_dictionary import LPCoinBackendDictionary
sage: p = MixedIntegerLinearProgram(maximization=True, solver="Coin")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: b.solve()
0
sage: d = LPCoinBackendDictionary(b)
sage: d.constant_terms()
(1.3, 3.3)
nonbasic_variables()

Return non-basic variables of self.

OUTPUT: a vector

EXAMPLES:

sage: from sage_numerical_interactive_mip.backends.coin_backend_dictionary import LPCoinBackendDictionary
sage: p = MixedIntegerLinearProgram(maximization=True, solver="Coin")
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] + 2.1 * x[1])
sage: b = p.get_backend()
sage: b.solve()
0
sage: d = LPCoinBackendDictionary(b)
sage: d.nonbasic_variables()
(w_0, w_1)
objective_coefficients()

Return coefficients of the objective of self.

OUTPUT: a vector

EXAMPLES:

sage: from sage_numerical_interactive_mip.backends.coin_backend_dictionary import LPCoinBackendDictionary
sage: p = MixedIntegerLinearProgram(maximization=True, solver="Coin")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(x[0] + x[1] - 7*x[2] + x[3] <= 22)
sage: p.add_constraint(x[1] + 2*x[2] - x[3] <= 13)
sage: p.add_constraint(5*x[0] + x[2] <= 11)
sage: p.set_objective(2*x[0] + 3*x[1] + 4*x[2] + 13*x[3])
sage: b = p.get_backend()
sage: b.solve()
0
sage: d = LPCoinBackendDictionary(b)
sage: d.objective_coefficients()
(-486.0, -10.0, -13.0, -95.0)
objective_name()

Return the objective name of self.

OUTPUT: a symbolic expression

row_coefficients(v)

Return coefficients of the basic variable v.

These are the coefficients with which nonbasic variables are subtracted in the relation for v.

INPUT:

  • v – a basic variable of self, can be given as a string, an actual variable, or an integer interpreted as the index of a variable

OUTPUT: a vector

EXAMPLES:

sage: from sage_numerical_interactive_mip.backends.coin_backend_dictionary import LPCoinBackendDictionary
sage: p = MixedIntegerLinearProgram(maximization=True, solver="Coin")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(x[0] + x[1] - 7*x[2] + x[3] <= 22)
sage: p.add_constraint(x[1] + 2*x[2] - x[3] <= 13)
sage: p.add_constraint(5*x[0] + x[2] <= 11)
sage: p.set_objective(2*x[0] + 3*x[1] + 4*x[2] + 13*x[3])
sage: b = p.get_backend()
sage: b.solve()
0
sage: d = LPCoinBackendDictionary(b)
sage: vars = d.basic_variables()
sage: vars
(x_2, x_3, w_1)
sage: d.leave(vars[0])
sage: d.leaving_coefficients()   # indirect doctest
(5.0, 0.0, 0.0, 1.0)
sage: d.leave(vars[1])
sage: d.leaving_coefficients()   # indirect doctest
(36.0, 1.0, 1.0, 7.0)
update()

Update self using previously set entering and leaving variables.

EXAMPLES:

sage: from sage_numerical_interactive_mip.backends.coin_backend_dictionary import LPCoinBackendDictionary
sage: p = MixedIntegerLinearProgram(maximization=True, solver="Coin")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(x[0] + x[1] - 7*x[2] + x[3] <= 22)
sage: p.add_constraint(x[1] + 2*x[2] - x[3] <= 13)
sage: p.add_constraint(5*x[0] + x[2] <= 11)
sage: p.set_objective(2*x[0] + 3*x[1] + 4*x[2] + 13*x[3])
sage: b = p.get_backend()
sage: b.solve()
0
sage: d = LPCoinBackendDictionary(b)
sage: d.objective_value()
1331.0
sage: d.nonbasic_variables()
(x_0, x_1, w_0, w_2)
sage: d.enter(d.nonbasic_variables()[0])
sage: d.basic_variables()
(x_2, x_3, w_1)
sage: d.leave(d.basic_variables()[0])
sage: d.objective_value()
1331.0
sage: d.update()
sage: d.basic_variables()
(x_0, x_3, w_1)
sage: d.nonbasic_variables()
(x_1, x_2, w_0, w_2)
sage: d.objective_value() # rel tol 1e-9
261.8

TESTS:

An error will be raised if the pivot selected is zero:

sage: from sage_numerical_interactive_mip.backends.coin_backend_dictionary import LPCoinBackendDictionary
sage: p = MixedIntegerLinearProgram(maximization=True, solver="Coin")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(x[0] + x[1] - 7*x[2] + x[3] <= 22)
sage: p.add_constraint(x[1] + 2*x[2] - x[3] <= 13)
sage: p.add_constraint(5*x[0] + x[2] <= 11)
sage: p.set_objective(2*x[0] + 3*x[1] + 4*x[2] + 13*x[3])
sage: b = p.get_backend()
sage: b.solve()
0
sage: d = LPCoinBackendDictionary(b)
sage: d.leave(d.basic_variables()[0])
sage: d.leaving_coefficients()
(5.0, 0.0, 0.0, 1.0)
sage: d.enter(d.nonbasic_variables()[1])
sage: d.leave(d.basic_variables()[0])
sage: d.update()
Traceback (most recent call last):
...
ValueError: incompatible choice of entering and leaving variables

clean_dictionary

Interactive Simplex Method floating-point helper class

This module provides a “clean” dictionary view on a dictionary with floating-point numbers. Cleaning means to change almost-zeros to exact zeros, allowing the Interactive Simplex Method to recognize primal and dual feasibility and to avoid pivoting on zero pivot elements. By extension, it also changes almost-integers to exact integers, for the benefit of mixed-integer programming.

class sage_numerical_interactive_mip.clean_dictionary.LPCleanDictionary(dictionary, epsilon=1e-09)

Bases: LPAbstractDictionary

Construct a clean dictionary for an LP problem from a dictionary.

INPUT:

  • dictionary – the dictionary to be cleaned

  • epsilon – (default: 1e-9) the tolerance of the cleaning process

OUTPUT: a dictionary for an LP problem

EXAMPLES:

One needs an instance inherited from LPAbstractDictionary to initialize this class:

Setting up a backend dictionary as the input:

sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: p = MixedIntegerLinearProgram(names=['m'], solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(-x[0] + x[1] <= 2)
sage: p.add_constraint(0.001 * x[0] + 0.0005 * x[1] <= 0.0000003)
sage: p.set_objective(-5.5 * x[0] + -2.1 * x[1])
sage: lp, basis = p.interactive_lp_problem()
sage: d = lp.dictionary(*basis)
sage: view(d)  # not tested

Create the clean dictionary using the backend dictionary:

sage: from sage_numerical_interactive_mip.clean_dictionary import LPCleanDictionary
sage: clean = LPCleanDictionary(d, epsilon=1e-5)
sage: TestSuite(clean).run(skip=['_test_not_implemented_methods',
....:                            '_test_pickling'])
sage: clean
LP problem dictionary (use ... details)
sage: view(clean.dictionary())  # not tested
__init__(dictionary, epsilon=1e-09)

See LPGLPKBackendDictionary for documentation.

TESTS:

sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: from sage_numerical_interactive_mip.clean_dictionary import LPCleanDictionary
sage: p = MixedIntegerLinearProgram(names=['m'], solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(-x[0] + x[1] <= 2)
sage: p.add_constraint(0.001 * x[0] + 0.00056 * x[1] <= 0.0000003)
sage: p.set_objective(-5.5 * x[0] + -2.1 * x[1])
sage: lp, basis = p.interactive_lp_problem()
sage: d = lp.dictionary(*basis)
sage: view(d)  # not tested
sage: clean = LPCleanDictionary(d, epsilon=1e-5)
sage: clean
LP problem dictionary (use ... details)
sage: view(clean.dictionary())  # not tested
_round_(var)

Round a number based on the epsilon.

INPUT:

  • var – the variable to be rounded

EXAMPLES:

sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: from sage_numerical_interactive_mip.clean_dictionary import LPCleanDictionary
sage: p = MixedIntegerLinearProgram(names=['m'], solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(-x[0] + x[1] <= 2)
sage: lp, basis = p.interactive_lp_problem()
sage: d = lp.dictionary(*basis)
sage: clean = LPCleanDictionary(d, epsilon=1e-4)
sage: clean._round_(0.1)
0.100000000000000
sage: clean._round_(0.00001)
0
_round_all_(iterable)

Round all element in an iterable.

INPUT:

  • iterable – the list to tranverse through

EXAMPLES:

sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: from sage_numerical_interactive_mip.clean_dictionary import LPCleanDictionary
sage: p = MixedIntegerLinearProgram(names=['m'], solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(-x[0] + x[1] <= 2)
sage: lp, basis = p.interactive_lp_problem()
sage: d = lp.dictionary(*basis)
sage: clean = LPCleanDictionary(d, epsilon=1e-4)
sage: l = [0.01, 0.000001]
sage: clean._round_all_(l)
(0.0100000000000000, 0.000000000000000)
basic_variables()

Return the basic variables of the associated dictionary.

OUTPUT: a vector

EXAMPLES:

sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: from sage_numerical_interactive_mip.clean_dictionary import LPCleanDictionary
sage: p = MixedIntegerLinearProgram(names=['m'], solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(-x[0] + x[1] <= 2)
sage: p.add_constraint(0.001 * x[0] + 0.0005 * x[1] <= 0.0000003)
sage: p.set_objective(-5.5 * x[0] + -2.1 * x[1])
sage: lp, basis = p.interactive_lp_problem()
sage: d = lp.dictionary(*basis)
sage: clean = LPCleanDictionary(d, epsilon=1e-4)
sage: clean.basic_variables()
(w_0, w_1)
constant_terms()

Return the constant terms of relations of self.

OUTPUT: a vector.

EXAMPLES:

sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: from sage_numerical_interactive_mip.clean_dictionary import LPCleanDictionary
sage: p = MixedIntegerLinearProgram(names=['m'], solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(-x[0] + x[1] <= 2)
sage: p.add_constraint(0.001 * x[0] + 0.0005 * x[1] <= 0.0000003)
sage: p.set_objective(-5.5 * x[0] + -2.1 * x[1])
sage: lp, basis = p.interactive_lp_problem()
sage: d = lp.dictionary(*basis)
sage: clean = LPCleanDictionary(d, epsilon=1e-4)
sage: d.constant_terms()
(2.0, 3e-07)
sage: clean.constant_terms()
(2, 0)
dictionary()

Return a cleaned regular LP dictionary of the associated dictionary.

OUTPUT: an LP dictionary

EXAMPLES:

sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: from sage_numerical_interactive_mip.clean_dictionary import LPCleanDictionary
sage: p = MixedIntegerLinearProgram(names=['m'], solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(-x[0] + x[1] <= 2)
sage: p.add_constraint(0.001 * x[0] + 0.0005 * x[1] <= 0.0000003)
sage: p.set_objective(-5.5 * x[0] + -2.1 * x[1])
sage: lp, basis = p.interactive_lp_problem()
sage: d = lp.dictionary(*basis)
sage: clean = LPCleanDictionary(d, epsilon=1e-4)
sage: clean_dict = clean.dictionary()
sage: view(clean_dict)  #not tested
enter(v)

Set v as the entering variable for the associated dictionary.

INPUT:

  • v – a basic variable of the associated dictionary, can be given as a string, an actual variable, or an integer interpreted as the index of a variable

EXAMPLES:

sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: from sage_numerical_interactive_mip.clean_dictionary import LPCleanDictionary
sage: p = MixedIntegerLinearProgram(names=['m'], solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(-x[0] + x[1] <= 2)
sage: p.add_constraint(0.001 * x[0] + 0.0005 * x[1] <= 0.0000003)
sage: p.set_objective(-5.5 * x[0] + -2.1 * x[1])
sage: lp, basis = p.interactive_lp_problem()
sage: d = lp.dictionary(*basis)
sage: clean = LPCleanDictionary(d, epsilon=1e-4)
sage: clean.nonbasic_variables()
(m_0, m_1)
sage: clean.enter(clean.nonbasic_variables()[0])
sage: d._entering
m_0
leave(v)

Set v as the leaving variable for the associated dictionary.

INPUT:

  • v – a basic variable of the associated dictionary, can be given as a string, an actual variable, or an integer interpreted as the index of a variable

EXAMPLES:

sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: from sage_numerical_interactive_mip.clean_dictionary import LPCleanDictionary
sage: p = MixedIntegerLinearProgram(names=['m'], solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(-x[0] + x[1] <= 2)
sage: p.add_constraint(0.001 * x[0] + 0.0005 * x[1] <= 0.0000003)
sage: p.set_objective(-5.5 * x[0] + -2.1 * x[1])
sage: lp, basis = p.interactive_lp_problem()
sage: d = lp.dictionary(*basis)
sage: clean = LPCleanDictionary(d, epsilon=1e-4)
sage: clean.basic_variables()
(w_0, w_1)
sage: clean.leave(clean.basic_variables()[0])
sage: d.leaving()
w_0
nonbasic_variables()

Return the non-basic variables of the associated dictionary.

OUTPUT: a vector

EXAMPLES:

sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: from sage_numerical_interactive_mip.clean_dictionary import LPCleanDictionary
sage: p = MixedIntegerLinearProgram(names=['m'], solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(-x[0] + x[1] <= 2)
sage: p.add_constraint(0.001 * x[0] + 0.0005 * x[1] <= 0.0000003)
sage: p.set_objective(-5.5 * x[0] + -2.1 * x[1])
sage: lp, basis = p.interactive_lp_problem()
sage: d = lp.dictionary(*basis)
sage: clean = LPCleanDictionary(d, epsilon=1e-4)
sage: clean.nonbasic_variables()
(m_0, m_1)
objective_coefficients()

Return coefficients of the objective of self.

OUTPUT: a vector

EXAMPLES:

sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: from sage_numerical_interactive_mip.clean_dictionary import LPCleanDictionary
sage: p = MixedIntegerLinearProgram(names=['m'], solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(-x[0] + x[1] <= 2)
sage: p.add_constraint(0.001 * x[0] + 0.0005 * x[1] <= 0.0000003)
sage: p.set_objective(-5.5 * x[0] + -2.1 * x[1])
sage: lp, basis = p.interactive_lp_problem()
sage: d = lp.dictionary(*basis)
sage: clean = LPCleanDictionary(d, epsilon=1e-4)
sage: clean.objective_coefficients()
(-5.5, -2.1)
objective_name()

Return the objective name of self.

OUTPUT: a symbolic expression

EXAMPLES:

sage: from sage_numerical_interactive_mip import *
sage: A = ([1, 1], [3, 1])
sage: b = (1000, 1500)
sage: c = (10, 5)
sage: P = InteractiveLPProblemStandardForm(A, b, c)
sage: D = P.initial_dictionary()
sage: D.objective_name()
z
objective_value()

Return the value of the objective value.

OUTPUT: a number

EXAMPLES:

sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: from sage_numerical_interactive_mip.clean_dictionary import LPCleanDictionary
sage: p = MixedIntegerLinearProgram(names=['m'], solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(-x[0] + x[1] <= 2)
sage: p.add_constraint(0.001 * x[0] + 0.0005 * x[1] <= 0.0000003)
sage: p.set_objective(-5.5 * x[0] + -2.1 * x[1])
sage: lp, basis = p.interactive_lp_problem()
sage: d = lp.dictionary(*basis)
sage: clean = LPCleanDictionary(d, epsilon=1e-4)
sage: clean.objective_value()
0
row_coefficients(v)

Return the coefficients of a basic variable

INPUT:

  • v – a basic variable of self, can be given as a string, an actual variable, or an integer interpreted as the index of a variable

OUTPUT: a vector of coefficients of a basic variable

EXAMPLES:

sage: from sage.numerical.mip import MixedIntegerLinearProgram
sage: from sage_numerical_interactive_mip.clean_dictionary import LPCleanDictionary
sage: p = MixedIntegerLinearProgram(names=['m'], solver="GLPK")
sage: x = p.new_variable(nonnegative=True)
sage: p.add_constraint(-x[0] + x[1] <= 2)
sage: p.add_constraint(0.001 * x[0] + 0.0005 * x[1] <= 0.0000003)
sage: p.set_objective(-5.5 * x[0] + -2.1 * x[1])
sage: lp, basis = p.interactive_lp_problem()
sage: d = lp.dictionary(*basis)
sage: clean = LPCleanDictionary(d, epsilon=1e-4)
sage: clean.row_coefficients(clean.basic_variables()[0])
(-1, 1)