PPL Backend¶
AUTHORS:
Risan (2012-02): initial implementation
Jeroen Demeyer (2014-08-04) allow rational coefficients for constraints and objective function (trac ticket #16755)
- class sage.numerical.backends.ppl_backend.PPLBackend¶
Bases:
sage.numerical.backends.generic_backend.GenericBackend
MIP Backend that uses the exact MIP solver from the Parma Polyhedra Library.
- 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 nonzerocoeffs
(list of real values) – associates a coefficient to the variable in each of the constraints in which it appears. Namely, the ith entry ofcoeffs
corresponds to the coefficient of the variable in the constraint represented by the ith entry inindices
.
Note
indices
andcoeffs
are expected to be of the same length.EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") 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
- add_linear_constraint(coefficients, lower_bound, upper_bound, name=None)¶
Add a linear constraint.
INPUT:
coefficients
– an iterable with(c,v)
pairs wherec
is a variable index (integer) andv
is a value (real value).lower_bound
– a lower bound, either a real value orNone
upper_bound
– an upper bound, either a real value orNone
name
– an optional name for this row (default:None
)
EXAMPLES:
sage: p = MixedIntegerLinearProgram(solver="PPL") sage: x = p.new_variable(nonnegative=True) sage: p.add_constraint(x[0]/2 + x[1]/3 <= 2/5) sage: p.set_objective(x[1]) sage: p.solve() 6/5 sage: p.add_constraint(x[0] - x[1] >= 1/10) sage: p.solve() 21/50 sage: p.set_max(x[0], 1/2) sage: p.set_min(x[1], 3/8) sage: p.solve() 2/5 sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.add_variables(5) 4 sage: p.add_linear_constraint(zip(range(5), range(5)), 2.0, 2.0) sage: p.row(0) ([1, 2, 3, 4], [1, 2, 3, 4]) sage: p.row_bounds(0) (2.00000000000000, 2.00000000000000) sage: p.add_linear_constraint( zip(range(5), range(5)), 1.0, 1.0, name='foo') sage: p.row_name(-1) 'foo'
- add_linear_constraints(number, lower_bound, upper_bound, names=None)¶
Add constraints.
INPUT:
number
(integer) – the number of constraints to add.lower_bound
– a lower bound, either a real value orNone
upper_bound
– an upper bound, either a real value orNone
names
– an optional list of names (default:None
)
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.add_variables(5) 4 sage: p.add_linear_constraints(5, None, 2) sage: p.row(4) ([], []) sage: p.row_bounds(4) (None, 2)
- add_variable(lower_bound=0, upper_bound=None, binary=False, continuous=False, integer=False, obj=0, name=None)¶
Add a variable.
This amounts to adding a new column to the matrix. By default, the variable is both positive and real.
It has not been implemented for selecting the variable type yet.
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 binary (default:True
).integer
–True
if the variable is binary (default:False
).obj
– (optional) coefficient of this variable in the objective function (default: 0)name
– an optional name for the newly added variable (default:None
).
OUTPUT: The index of the newly created variable
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.ncols() 0 sage: p.add_variable() 0 sage: p.ncols() 1 sage: p.add_variable(lower_bound=-2) 1 sage: p.add_variable(name='x',obj=2/3) 2 sage: p.col_name(2) 'x' sage: p.objective_coefficient(2) 2/3 sage: p.add_variable(integer=True) 3
- add_variables(n, lower_bound=0, upper_bound=None, binary=False, continuous=True, integer=False, obj=0, names=None)¶
Add
n
variables.This amounts to adding new columns to the matrix. By default, the variables are both positive and real.
It has not been implemented for selecting the variable type yet.
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
– (optional) coefficient of all variables in the objective function (default: 0)names
– optional list of names (default:None
)
OUTPUT: The index of the variable created last.
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.ncols() 0 sage: p.add_variables(5) 4 sage: p.ncols() 5 sage: p.add_variables(2, lower_bound=-2.0, obj=42.0, names=['a','b']) 6
- base_ring()¶
- 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 toNone
if the variable is not bounded in the corresponding direction, and is a real value otherwise.EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.add_variable() 0 sage: p.col_bounds(0) (0, None) sage: p.variable_upper_bound(0, 5) sage: p.col_bounds(0) (0, 5)
- col_name(index)¶
Return the
index
th col nameINPUT:
index
(integer) – the col’s idname
(char *
) – its name. When set toNULL
(default), the method returns the current name.
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.add_variable(name="I am a variable") 0 sage: p.col_name(0) 'I am a variable'
- get_objective_value()¶
Return the exact value of the objective function.
Note
Behaviour is undefined unless
solve
has been called before.EXAMPLES:
sage: p = MixedIntegerLinearProgram(solver="PPL") sage: x = p.new_variable(nonnegative=True) sage: p.add_constraint(5/13*x[0] + x[1]/2 == 8/7) sage: p.set_objective(5/13*x[0] + x[1]/2) sage: p.solve() 8/7 sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") 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() 15/2 sage: p.get_variable_value(0) 0 sage: p.get_variable_value(1) 3/2
- get_variable_value(variable)¶
Return the value of a variable given by the solver.
Note
Behaviour is undefined unless
solve
has been called before.EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") 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() 15/2 sage: p.get_variable_value(0) 0 sage: p.get_variable_value(1) 3/2
- init_mip()¶
Converting the matrix form of the MIP Problem to PPL MIP_Problem.
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver="PPL") sage: p.base_ring() Rational Field sage: type(p.zero()) <type 'sage.rings.rational.Rational'> sage: p.init_mip()
- is_maximization()¶
Test whether the problem is a maximization
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.is_maximization() True sage: p.set_sense(-1) sage: p.is_maximization() False
- is_variable_binary(index)¶
Test whether the given variable is of binary type.
INPUT:
index
(integer) – the variable’s id
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.ncols() 0 sage: p.add_variable() 0 sage: p.is_variable_binary(0) False
- is_variable_continuous(index)¶
Test whether the given variable is of continuous/real type.
INPUT:
index
(integer) – the variable’s id
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.ncols() 0 sage: p.add_variable() 0 sage: p.is_variable_continuous(0) True
- is_variable_integer(index)¶
Test whether the given variable is of integer type.
INPUT:
index
(integer) – the variable’s id
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.ncols() 0 sage: p.add_variable() 0 sage: p.is_variable_integer(0) False
- ncols()¶
Return the number of columns/variables.
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.ncols() 0 sage: p.add_variables(2) 1 sage: p.ncols() 2
- nrows()¶
Return the number of rows/constraints.
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.nrows() 0 sage: p.add_linear_constraints(2, 2.0, None) sage: 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 idcoeff
(integer) – its coefficient
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.add_variable() 0 sage: p.objective_coefficient(0) 0 sage: p.objective_coefficient(0,2) sage: p.objective_coefficient(0) 2
- problem_name(name=None)¶
Return or define the problem’s name
INPUT:
name
(str
) – the problem’s name. When set toNone
(default), the method returns the problem’s name.
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.problem_name("There once was a french fry") sage: print(p.problem_name()) There once was a french fry
- row(i)¶
Return a row
INPUT:
index
(integer) – the constraint’s id.
OUTPUT:
A pair
(indices, coeffs)
whereindices
lists the entries whose coefficient is nonzero, and to whichcoeffs
associates their coefficient on the model of theadd_linear_constraint
method.EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.add_variables(5) 4 sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2) sage: p.row(0) ([1, 2, 3, 4], [1, 2, 3, 4]) sage: p.row_bounds(0) (2, 2)
- 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 toNone
if the constraint is not bounded in the corresponding direction, and is a real value otherwise.EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.add_variables(5) 4 sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2) sage: p.row(0) ([1, 2, 3, 4], [1, 2, 3, 4]) sage: p.row_bounds(0) (2, 2)
- row_name(index)¶
Return the
index
th row nameINPUT:
index
(integer) – the row’s id
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.add_linear_constraints(1, 2, None, names=["Empty constraint 1"]) sage: p.row_name(0) 'Empty constraint 1'
- set_objective(coeff, d=0)¶
Set the objective function.
INPUT:
coeff
– a list of real values, whose ith element is the coefficient of the ith variable in the objective function.
EXAMPLES:
sage: p = MixedIntegerLinearProgram(solver="PPL") sage: x = p.new_variable(nonnegative=True) sage: p.add_constraint(x[0]*5 + x[1]/11 <= 6) sage: p.set_objective(x[0]) sage: p.solve() 6/5 sage: p.set_objective(x[0]/2 + 1) sage: p.show() Maximization: 1/2 x_0 + 1 Constraints: constraint_0: 5 x_0 + 1/11 x_1 <= 6 Variables: x_0 is a continuous variable (min=0, max=+oo) x_1 is a continuous variable (min=0, max=+oo) sage: p.solve() 8/5 sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") 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, 1, 2, 1, 3]
- set_sense(sense)¶
Set the direction (maximization/minimization).
INPUT:
sense
(integer) :+1 => Maximization
-1 => Minimization
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.is_maximization() True sage: p.set_sense(-1) sage: p.is_maximization() False
- set_variable_type(variable, vtype)¶
Set the type of a variable.
INPUT:
variable
(integer) – the variable’s idvtype
(integer) :1 Integer
0 Binary
- -1
Continuous
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.add_variables(5) 4 sage: p.set_variable_type(0,1) sage: p.is_variable_integer(0) True sage: p.set_variable_type(3,0) sage: p.is_variable_integer(3) or p.is_variable_binary(3) True sage: p.col_bounds(3) # tol 1e-6 (0, 1) sage: p.set_variable_type(3, -1) sage: p.is_variable_continuous(3) True
- set_verbosity(level)¶
Set the log (verbosity) level. Not Implemented.
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.set_verbosity(0)
- solve()¶
Solve the problem.
Note
This method raises
MIPSolverException
exceptions when the solution cannot be computed for any reason (none exists, or the solver was not able to find it, etc…)EXAMPLES:
A linear optimization problem:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.add_linear_constraints(5, 0, None) sage: p.add_col(list(range(5)), list(range(5))) sage: p.solve() 0
An unbounded problem:
sage: p.objective_coefficient(0,1) sage: p.solve() Traceback (most recent call last): ... MIPSolverException: ...
An integer optimization problem:
sage: p = MixedIntegerLinearProgram(solver='PPL') sage: x = p.new_variable(integer=True, nonnegative=True) sage: p.add_constraint(2*x[0] + 3*x[1], max = 6) sage: p.add_constraint(3*x[0] + 2*x[1], max = 6) sage: p.set_objective(x[0] + x[1] + 7) sage: p.solve() 9
- variable_lower_bound(index, value=False)¶
Return or define the lower bound on a variable
INPUT:
index
(integer) – the variable’s idvalue
– real value, orNone
to mean that the variable has not lower bound. When set toNone
(default), the method returns the current value.
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.add_variable() 0 sage: p.col_bounds(0) (0, None) sage: p.variable_lower_bound(0, 5) sage: p.col_bounds(0) (5, None) sage: p.variable_lower_bound(0, None) sage: p.col_bounds(0) (None, None)
- variable_upper_bound(index, value=False)¶
Return or define the upper bound on a variable
INPUT:
index
(integer) – the variable’s idvalue
– real value, orNone
to mean that the variable has not upper bound. When set toNone
(default), the method returns the current value.
EXAMPLES:
sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "PPL") sage: p.add_variable() 0 sage: p.col_bounds(0) (0, None) sage: p.variable_upper_bound(0, 5) sage: p.col_bounds(0) (0, 5) sage: p.variable_upper_bound(0, None) sage: p.col_bounds(0) (0, None)
- zero()¶