HiGHS Backend

AUTHORS:

This backend uses the HiGHS optimization solver C API, which supports Linear Programming (LP), Quadratic Programming (QP), and Mixed Integer Programming (MIP).

HiGHS is available under the MIT License.

class sage.numerical.backends.highs_backend.HiGHSBackend[source]

Bases: GenericBackend

MIP Backend that uses the HiGHS solver via C API.

HiGHS is a high-performance solver for large-scale LP, QP, and MIP. This implementation uses the HiGHS C API directly for optimal performance and proper interrupt handling with sig_on/sig_off.

add_col(indices, coeffs)[source]

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: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
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
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> 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)[source]

Add a linear constraint.

INPUT:

  • coefficients – an iterable of pairs (i, v) where i is a variable index and v is a value

  • lower_bound – a lower bound, either a real value or None

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

  • name – optional name for this constraint

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.add_variables(5)
4
sage: p.add_linear_constraint([(0, 1), (1, 1)], None, 2.0)
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variables(Integer(5))
4
>>> p.add_linear_constraint([(Integer(0), Integer(1)), (Integer(1), Integer(1))], None, RealNumber('2.0'))
add_linear_constraints(number, lower_bound, upper_bound, names=None)[source]

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: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.add_variables(5)
4
sage: p.add_linear_constraints(5, None, 2)
sage: p.row_bounds(4)
(None, 2.0)
sage: p.add_linear_constraints(2, None, 2, names=['foo','bar'])
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variables(Integer(5))
4
>>> p.add_linear_constraints(Integer(5), None, Integer(2))
>>> p.row_bounds(Integer(4))
(None, 2.0)
>>> p.add_linear_constraints(Integer(2), None, Integer(2), names=['foo','bar'])
add_variable(lower_bound=0.0, upper_bound=None, binary=False, continuous=False, integer=False, obj=0.0, name=None)[source]

Add a variable.

This amounts to adding a new column to the matrix. By default, the variable is both positive, real and the coefficient in the objective function is 0.0.

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: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver = "HiGHS")
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
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver = "HiGHS")
>>> 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_variable_with_type(vtype, lower_bound=0.0, upper_bound=None, obj=0.0, name=None)[source]

Add a variable with type specified as an integer.

This amounts to adding a new column to the matrix. By default, the variable is positive and real, and the coefficient in the objective function is 0.0.

INPUT:

  • vtype – integer specifying the variable type:

    • 1 = Integer

    • 0 = Binary

    • -1 = Real (Continuous)

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

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

  • 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: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver = "HiGHS")
sage: p.ncols()
0
sage: p.add_variable_with_type(-1)    # Continuous variable
0
sage: p.is_variable_continuous(0)
True
sage: p.add_variable_with_type(0)     # Binary variable
1
sage: p.is_variable_binary(1)
True
sage: p.add_variable_with_type(1, lower_bound=-2.0)  # Integer variable
2
sage: p.is_variable_integer(2)
True
sage: p.add_variable_with_type(1, name='x', obj=1.0)
3
sage: p.col_name(3)
'x'
sage: p.objective_coefficient(3)
1.0
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver = "HiGHS")
>>> p.ncols()
0
>>> p.add_variable_with_type(-Integer(1))    # Continuous variable
0
>>> p.is_variable_continuous(Integer(0))
True
>>> p.add_variable_with_type(Integer(0))     # Binary variable
1
>>> p.is_variable_binary(Integer(1))
True
>>> p.add_variable_with_type(Integer(1), lower_bound=-RealNumber('2.0'))  # Integer variable
2
>>> p.is_variable_integer(Integer(2))
True
>>> p.add_variable_with_type(Integer(1), name='x', obj=RealNumber('1.0'))
3
>>> p.col_name(Integer(3))
'x'
>>> p.objective_coefficient(Integer(3))
1.0
add_variables(number, lower_bound=0.0, upper_bound=None, binary=False, continuous=False, integer=False, obj=0.0, names=None)[source]

Add number new variables.

This amounts to adding new columns to the matrix. By default, the variables are both positive, real and their coefficient in the objective function is 0.0.

INPUT:

  • number – 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 continuous (default: True)

  • integer – True if the variable is integer (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: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver = "HiGHS")
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, obj=42.0, names=['a','b'])
6
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver = "HiGHS")
>>> p.ncols()
0
>>> p.add_variables(Integer(5))
4
>>> p.ncols()
5
>>> p.add_variables(Integer(2), lower_bound=-RealNumber('2.0'), integer=True, obj=RealNumber('42.0'), names=['a','b'])
6
best_known_objective_bound()[source]

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: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.add_variables(2)
1
sage: p.add_linear_constraint([(0, 1), (1, 1)], None, 2.0)
sage: p.set_objective([1, 1])
sage: p.solve()
0
sage: p.best_known_objective_bound()
2.0
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variables(Integer(2))
1
>>> p.add_linear_constraint([(Integer(0), Integer(1)), (Integer(1), Integer(1))], None, RealNumber('2.0'))
>>> p.set_objective([Integer(1), Integer(1)])
>>> p.solve()
0
>>> p.best_known_objective_bound()
2.0
col_bounds(index)[source]

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: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
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)
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> 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)[source]

Return the index-th column name.

INPUT:

  • index – integer; the column’s id

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.add_variable(name='x')
0
sage: p.col_name(0)
'x'
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variable(name='x')
0
>>> p.col_name(Integer(0))
'x'
get_col_dual(j)[source]

Return the dual value (reduced cost) of a variable.

The dual value is the reduced cost of a variable. The reduced cost is the amount by which the objective coefficient of a non-basic variable has to change to become a basic variable.

INPUT:

  • j – the index of the variable

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='HiGHS')
sage: p.add_variables(3)
2
sage: p.add_linear_constraint(list(zip([0, 1, 2], [8, 6, 1])), None, 48)
sage: p.add_linear_constraint(list(zip([0, 1, 2], [4, 2, 1.5])), None, 20)
sage: p.add_linear_constraint(list(zip([0, 1, 2], [2, 1.5, 0.5])), None, 8)
sage: p.set_objective([60, 30, 20])
sage: p.solve()
0
sage: p.get_col_dual(0)    # tol 1e-6
0.0
sage: p.get_col_dual(1)    # tol 1e-6
-5.0
sage: p.get_col_dual(2)    # tol 1e-6
0.0
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variables(Integer(3))
2
>>> p.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(8), Integer(6), Integer(1)])), None, Integer(48))
>>> p.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(4), Integer(2), RealNumber('1.5')])), None, Integer(20))
>>> p.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(2), RealNumber('1.5'), RealNumber('0.5')])), None, Integer(8))
>>> p.set_objective([Integer(60), Integer(30), Integer(20)])
>>> p.solve()
0
>>> p.get_col_dual(Integer(0))    # tol 1e-6
0.0
>>> p.get_col_dual(Integer(1))    # tol 1e-6
-5.0
>>> p.get_col_dual(Integer(2))    # tol 1e-6
0.0
get_col_stat(j)[source]

Retrieve the status of a variable.

INPUT:

  • j – the index of the variable

OUTPUT:

Current status assigned to the structural variable associated with the j-th column:

  • 0 kLower: non-basic variable at lower bound

  • 1 kBasic: basic variable

  • 2 kUpper: non-basic variable at upper bound

  • 3 kZero: non-basic free variable at zero

  • 4 kNonbasic: nonbasic (used for unbounded variables)

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: lp = get_solver(solver='HiGHS')
sage: lp.add_variables(3)
2
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [8, 6, 1])), None, 48)
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [4, 2, 1.5])), None, 20)
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [2, 1.5, 0.5])), None, 8)
sage: lp.set_objective([60, 30, 20])
sage: lp.solve()
0
sage: lp.get_col_stat(0)
1
sage: lp.get_col_stat(1)
0
sage: lp.get_col_stat(100)
Traceback (most recent call last):
...
ValueError: The variable's index j must satisfy 0 <= j < number_of_variables
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> lp = get_solver(solver='HiGHS')
>>> lp.add_variables(Integer(3))
2
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(8), Integer(6), Integer(1)])), None, Integer(48))
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(4), Integer(2), RealNumber('1.5')])), None, Integer(20))
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(2), RealNumber('1.5'), RealNumber('0.5')])), None, Integer(8))
>>> lp.set_objective([Integer(60), Integer(30), Integer(20)])
>>> lp.solve()
0
>>> lp.get_col_stat(Integer(0))
1
>>> lp.get_col_stat(Integer(1))
0
>>> lp.get_col_stat(Integer(100))
Traceback (most recent call last):
...
ValueError: The variable's index j must satisfy 0 <= j < number_of_variables
get_objective_value()[source]

Return the value of the objective function.

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.add_variables(2)
1
sage: p.add_linear_constraint([(0, 1), (1, 1)], None, 2.0)
sage: p.set_objective([1, 1])
sage: p.solve()
0
sage: p.get_objective_value()
2.0
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variables(Integer(2))
1
>>> p.add_linear_constraint([(Integer(0), Integer(1)), (Integer(1), Integer(1))], None, RealNumber('2.0'))
>>> p.set_objective([Integer(1), Integer(1)])
>>> p.solve()
0
>>> p.get_objective_value()
2.0
get_relative_objective_gap()[source]

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: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.add_variables(2)
1
sage: p.add_linear_constraint([(0, 1), (1, 1)], None, 2.0)
sage: p.set_objective([1, 1])
sage: p.solve()
0
sage: p.get_relative_objective_gap()
0.0
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variables(Integer(2))
1
>>> p.add_linear_constraint([(Integer(0), Integer(1)), (Integer(1), Integer(1))], None, RealNumber('2.0'))
>>> p.set_objective([Integer(1), Integer(1)])
>>> p.solve()
0
>>> p.get_relative_objective_gap()
0.0
get_row_dual(i)[source]

Return the dual value of a constraint.

The dual value of the i-th row is also the value of the i-th variable of the dual problem.

The dual value of a constraint is the shadow price of the constraint. The shadow price is the amount by which the objective value will change if the constraint’s bounds change by one unit under the precondition that the basis remains the same.

INPUT:

  • i – the index of the constraint

Note

Behaviour is undefined unless solve has been called before.

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: lp = get_solver(solver='HiGHS')
sage: lp.add_variables(3)
2
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [8, 6, 1])), None, 48)
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [4, 2, 1.5])), None, 20)
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [2, 1.5, 0.5])), None, 8)
sage: lp.set_objective([60, 30, 20])
sage: lp.solve()
0
sage: lp.get_row_dual(0)   # tol 1e-6
0.0
sage: lp.get_row_dual(1)   # tol 1e-6
10.0
sage: lp.get_row_dual(2)   # tol 1e-6
10.0
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> lp = get_solver(solver='HiGHS')
>>> lp.add_variables(Integer(3))
2
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(8), Integer(6), Integer(1)])), None, Integer(48))
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(4), Integer(2), RealNumber('1.5')])), None, Integer(20))
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(2), RealNumber('1.5'), RealNumber('0.5')])), None, Integer(8))
>>> lp.set_objective([Integer(60), Integer(30), Integer(20)])
>>> lp.solve()
0
>>> lp.get_row_dual(Integer(0))   # tol 1e-6
0.0
>>> lp.get_row_dual(Integer(1))   # tol 1e-6
10.0
>>> lp.get_row_dual(Integer(2))   # tol 1e-6
10.0
get_row_prim(i)[source]

Return the value of the auxiliary variable associated with i-th row.

Note

Behaviour is undefined unless solve has been called before.

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: lp = get_solver(solver='HiGHS')
sage: lp.add_variables(3)
2
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [8, 6, 1])), None, 48)
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [4, 2, 1.5])), None, 20)
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [2, 1.5, 0.5])), None, 8)
sage: lp.set_objective([60, 30, 20])
sage: lp.solve()
0
sage: lp.get_objective_value()
280.0
sage: lp.get_row_prim(0)
24.0
sage: lp.get_row_prim(1)
20.0
sage: lp.get_row_prim(2)
8.0
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> lp = get_solver(solver='HiGHS')
>>> lp.add_variables(Integer(3))
2
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(8), Integer(6), Integer(1)])), None, Integer(48))
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(4), Integer(2), RealNumber('1.5')])), None, Integer(20))
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(2), RealNumber('1.5'), RealNumber('0.5')])), None, Integer(8))
>>> lp.set_objective([Integer(60), Integer(30), Integer(20)])
>>> lp.solve()
0
>>> lp.get_objective_value()
280.0
>>> lp.get_row_prim(Integer(0))
24.0
>>> lp.get_row_prim(Integer(1))
20.0
>>> lp.get_row_prim(Integer(2))
8.0
get_row_stat(i)[source]

Retrieve the status of a constraint.

INPUT:

  • i – the index of the constraint

OUTPUT:

Current status assigned to the auxiliary variable associated with the i-th row:

  • 0 kLower: non-basic variable at lower bound

  • 1 kBasic: basic variable

  • 2 kUpper: non-basic variable at upper bound

  • 3 kZero: non-basic free variable at zero

  • 4 kNonbasic: nonbasic (used for unbounded variables)

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: lp = get_solver(solver='HiGHS')
sage: lp.add_variables(3)
2
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [8, 6, 1])), None, 48)
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [4, 2, 1.5])), None, 20)
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [2, 1.5, 0.5])), None, 8)
sage: lp.set_objective([60, 30, 20])
sage: lp.solve()
0
sage: lp.get_row_stat(0)  # doctest: +SKIP
2
sage: lp.get_row_stat(1)  # doctest: +SKIP
2
sage: lp.get_row_stat(-1)
Traceback (most recent call last):
...
ValueError: The constraint's index i must satisfy 0 <= i < number_of_constraints
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> lp = get_solver(solver='HiGHS')
>>> lp.add_variables(Integer(3))
2
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(8), Integer(6), Integer(1)])), None, Integer(48))
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(4), Integer(2), RealNumber('1.5')])), None, Integer(20))
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(2), RealNumber('1.5'), RealNumber('0.5')])), None, Integer(8))
>>> lp.set_objective([Integer(60), Integer(30), Integer(20)])
>>> lp.solve()
0
>>> lp.get_row_stat(Integer(0))  # doctest: +SKIP
2
>>> lp.get_row_stat(Integer(1))  # doctest: +SKIP
2
>>> lp.get_row_stat(-Integer(1))
Traceback (most recent call last):
...
ValueError: The constraint's index i must satisfy 0 <= i < number_of_constraints
get_variable_value(variable)[source]

Return the value of a variable given by the solver.

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.add_variables(2)
1
sage: p.add_linear_constraint([(0, 1), (1, 1)], None, 2.0)
sage: p.set_objective([1, 1])
sage: p.solve()
0
sage: p.get_variable_value(0)
2.0
sage: p.get_variable_value(1)
0.0
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variables(Integer(2))
1
>>> p.add_linear_constraint([(Integer(0), Integer(1)), (Integer(1), Integer(1))], None, RealNumber('2.0'))
>>> p.set_objective([Integer(1), Integer(1)])
>>> p.solve()
0
>>> p.get_variable_value(Integer(0))
2.0
>>> p.get_variable_value(Integer(1))
0.0
is_maximization()[source]

Test whether the problem is a maximization.

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.is_maximization()
True
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.is_maximization()
True
is_variable_binary(index)[source]

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='HiGHS')
sage: p.add_variable()
0
sage: p.is_variable_binary(0)
False
sage: p.add_variable(binary=True)
1
sage: p.is_variable_binary(1)
True
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variable()
0
>>> p.is_variable_binary(Integer(0))
False
>>> p.add_variable(binary=True)
1
>>> p.is_variable_binary(Integer(1))
True
is_variable_continuous(index)[source]

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='HiGHS')
sage: p.add_variable()
0
sage: p.is_variable_continuous(0)
True
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variable()
0
>>> p.is_variable_continuous(Integer(0))
True
is_variable_integer(index)[source]

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='HiGHS')
sage: p.add_variable()
0
sage: p.is_variable_integer(0)
False
sage: p.add_variable(integer=True)
1
sage: p.is_variable_integer(1)
True
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variable()
0
>>> p.is_variable_integer(Integer(0))
False
>>> p.add_variable(integer=True)
1
>>> p.is_variable_integer(Integer(1))
True
ncols()[source]

Return the number of columns/variables.

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.ncols()
0
sage: p.add_variables(2)
1
sage: p.ncols()
2
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.ncols()
0
>>> p.add_variables(Integer(2))
1
>>> p.ncols()
2
nrows()[source]

Return the number of rows/constraints.

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.nrows()
0
sage: p.add_variables(2)
1
sage: p.add_linear_constraint([(0, 1), (1, 1)], None, 2.0)
sage: p.nrows()
1
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.nrows()
0
>>> p.add_variables(Integer(2))
1
>>> p.add_linear_constraint([(Integer(0), Integer(1)), (Integer(1), Integer(1))], None, RealNumber('2.0'))
>>> p.nrows()
1
objective_coefficient(variable, coeff=None)[source]

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

INPUT:

  • variable – integer; the variable’s id

  • coeff – double; its coefficient or None for reading (default: None)

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver = "HiGHS")
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
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver = "HiGHS")
>>> 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
problem_name(name=None)[source]

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: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver = "HiGHS")
sage: p.problem_name("There once was a french fry")
sage: print(p.problem_name())
There once was a french fry
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver = "HiGHS")
>>> p.problem_name("There once was a french fry")
>>> print(p.problem_name())
There once was a french fry
remove_constraint(i)[source]

Remove a constraint from self.

INPUT:

  • i – index of the constraint to remove

EXAMPLES:

sage: p = MixedIntegerLinearProgram(solver='HiGHS')
sage: x, y = p['x'], p['y']
sage: p.add_constraint(2*x + 3*y <= 6)
sage: p.add_constraint(3*x + 2*y <= 6)
sage: p.add_constraint(x >= 0)
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
>>> from sage.all import *
>>> p = MixedIntegerLinearProgram(solver='HiGHS')
>>> x, y = p['x'], p['y']
>>> p.add_constraint(Integer(2)*x + Integer(3)*y <= Integer(6))
>>> p.add_constraint(Integer(3)*x + Integer(2)*y <= Integer(6))
>>> p.add_constraint(x >= Integer(0))
>>> 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

Removing fancy constraints does not make Sage crash:

sage: MixedIntegerLinearProgram(solver = "HiGHS").remove_constraint(-2)
Traceback (most recent call last):
...
ValueError: The constraint's index i must satisfy 0 <= i < number_of_constraints
[Python]
>>> from sage.all import *
>>> MixedIntegerLinearProgram(solver = "HiGHS").remove_constraint(-Integer(2))
Traceback (most recent call last):
...
ValueError: The constraint's index i must satisfy 0 <= i < number_of_constraints
remove_constraints(constraints)[source]

Remove several constraints.

INPUT:

  • constraints – an iterable containing the indices of the rows to remove

EXAMPLES:

sage: p = MixedIntegerLinearProgram(solver='HiGHS')
sage: x, y = p['x'], p['y']
sage: p.add_constraint(2*x + 3*y <= 6)
sage: p.add_constraint(3*x + 2*y <= 6)
sage: p.add_constraint(x >= 0)
sage: p.set_objective(x + y + 7)
sage: p.set_integer(x); p.set_integer(y)
sage: p.solve()
9.0
sage: p.remove_constraints([0])
sage: p.solve()
10.0
sage: p.get_values([x,y])
[-0.0, 3.0]
>>> from sage.all import *
>>> p = MixedIntegerLinearProgram(solver='HiGHS')
>>> x, y = p['x'], p['y']
>>> p.add_constraint(Integer(2)*x + Integer(3)*y <= Integer(6))
>>> p.add_constraint(Integer(3)*x + Integer(2)*y <= Integer(6))
>>> p.add_constraint(x >= Integer(0))
>>> p.set_objective(x + y + Integer(7))
>>> p.set_integer(x); p.set_integer(y)
>>> p.solve()
9.0
>>> p.remove_constraints([Integer(0)])
>>> p.solve()
10.0
>>> p.get_values([x,y])
[-0.0, 3.0]
row(index)[source]

Return the index-th constraint as a pair of lists.

INPUT:

  • index – index of the constraint

OUTPUT:

A pair (indices, coeffs) where indices lists the entries whose coefficient is nonzero, and to which coeffs associates their coefficient in the order of indices.

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.add_variables(5)
4
sage: p.add_linear_constraint(list(zip(range(5), range(5))), 2, 2)
sage: p.row(0)  # Note: zero coefficients are excluded in sparse format
([1, 2, 3, 4], [1.0, 2.0, 3.0, 4.0])
sage: p.row(1)
Traceback (most recent call last):
...
ValueError: invalid row index 1
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variables(Integer(5))
4
>>> p.add_linear_constraint(list(zip(range(Integer(5)), range(Integer(5)))), Integer(2), Integer(2))
>>> p.row(Integer(0))  # Note: zero coefficients are excluded in sparse format
([1, 2, 3, 4], [1.0, 2.0, 3.0, 4.0])
>>> p.row(Integer(1))
Traceback (most recent call last):
...
ValueError: invalid row index 1
row_bounds(index)[source]

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: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.add_variables(5)
4
sage: p.add_linear_constraint(list(zip(range(5), range(5))), 2, 2)
sage: p.row(0)  # Note: zero coefficients are excluded in sparse format
([1, 2, 3, 4], [1.0, 2.0, 3.0, 4.0])
sage: p.row_bounds(0)
(2.0, 2.0)
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variables(Integer(5))
4
>>> p.add_linear_constraint(list(zip(range(Integer(5)), range(Integer(5)))), Integer(2), Integer(2))
>>> p.row(Integer(0))  # Note: zero coefficients are excluded in sparse format
([1, 2, 3, 4], [1.0, 2.0, 3.0, 4.0])
>>> p.row_bounds(Integer(0))
(2.0, 2.0)
row_name(index)[source]

Return the index-th row name.

INPUT:

  • index – integer; the row’s id

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.add_linear_constraint([], 2, 2, name='foo')
sage: p.row_name(0)
'foo'
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_linear_constraint([], Integer(2), Integer(2), name='foo')
>>> p.row_name(Integer(0))
'foo'
set_col_stat(j, stat)[source]

Set the status of a variable.

INPUT:

  • j – the index of the variable

  • stat – the status to set to:

    • 0 kLower: non-basic variable at lower bound

    • 1 kBasic: basic variable

    • 2 kUpper: non-basic variable at upper bound

    • 3 kZero: non-basic free variable at zero

    • 4 kNonbasic: nonbasic (used for unbounded variables)

Note

HiGHS may reject invalid basis configurations. Setting arbitrary status values may result in the basis being rejected and the original basis being preserved.

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: lp = get_solver(solver='HiGHS')
sage: lp.add_variables(3)
2
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [8, 6, 1])), None, 48)
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [4, 2, 1.5])), None, 20)
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [2, 1.5, 0.5])), None, 8)
sage: lp.set_objective([60, 30, 20])
sage: lp.solve()
0
sage: lp.get_col_stat(0)
1
sage: lp.set_col_stat(0, 2)
sage: lp.get_col_stat(0)
2
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> lp = get_solver(solver='HiGHS')
>>> lp.add_variables(Integer(3))
2
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(8), Integer(6), Integer(1)])), None, Integer(48))
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(4), Integer(2), RealNumber('1.5')])), None, Integer(20))
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(2), RealNumber('1.5'), RealNumber('0.5')])), None, Integer(8))
>>> lp.set_objective([Integer(60), Integer(30), Integer(20)])
>>> lp.solve()
0
>>> lp.get_col_stat(Integer(0))
1
>>> lp.set_col_stat(Integer(0), Integer(2))
>>> lp.get_col_stat(Integer(0))
2
set_objective(coeff, d=0.0)[source]

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 – constant term in objective function (default: 0.0)

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.add_variables(5)
4
sage: p.set_objective([1, 1, 2, 1, 3])
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variables(Integer(5))
4
>>> p.set_objective([Integer(1), Integer(1), Integer(2), Integer(1), Integer(3)])
set_row_stat(i, stat)[source]

Set the status of a constraint.

INPUT:

  • i – the index of the constraint

  • stat – the status to set to:

    • 0 kLower: non-basic variable at lower bound

    • 1 kBasic: basic variable

    • 2 kUpper: non-basic variable at upper bound

    • 3 kZero: non-basic free variable at zero

    • 4 kNonbasic: nonbasic (used for unbounded variables)

Note

HiGHS may reject invalid basis configurations. Setting arbitrary status values may result in the basis being rejected and the original basis being preserved.

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: lp = get_solver(solver='HiGHS')
sage: lp.add_variables(3)
2
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [8, 6, 1])), None, 48)
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [4, 2, 1.5])), None, 20)
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [2, 1.5, 0.5])), None, 8)
sage: lp.set_objective([60, 30, 20])
sage: lp.solve()
0
sage: lp.get_row_stat(0)
1
sage: lp.set_col_stat(0, 2)
sage: lp.get_col_stat(0)
2
sage: lp.set_row_stat(0, 3)
sage: lp.get_row_stat(0)
3
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> lp = get_solver(solver='HiGHS')
>>> lp.add_variables(Integer(3))
2
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(8), Integer(6), Integer(1)])), None, Integer(48))
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(4), Integer(2), RealNumber('1.5')])), None, Integer(20))
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(2), RealNumber('1.5'), RealNumber('0.5')])), None, Integer(8))
>>> lp.set_objective([Integer(60), Integer(30), Integer(20)])
>>> lp.solve()
0
>>> lp.get_row_stat(Integer(0))
1
>>> lp.set_col_stat(Integer(0), Integer(2))
>>> lp.get_col_stat(Integer(0))
2
>>> lp.set_row_stat(Integer(0), Integer(3))
>>> lp.get_row_stat(Integer(0))
3
set_sense(sense)[source]

Set the direction (maximization/minimization).

INPUT:

  • sense – +1 for maximization; any other integer for minimization

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.is_maximization()
True
sage: p.set_sense(-1)
sage: p.is_maximization()
False
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.is_maximization()
True
>>> p.set_sense(-Integer(1))
>>> p.is_maximization()
False
set_variable_type(variable, vtype)[source]

Set the type of a variable.

INPUT:

  • variable – integer; the variable’s id

  • vtype – integer:

    • 1 = Integer

    • 0 = Binary

    • -1 = Real (Continuous)

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.add_variable()
0
sage: p.is_variable_continuous(0)
True
sage: p.set_variable_type(0, 1)
sage: p.is_variable_integer(0)
True
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variable()
0
>>> p.is_variable_continuous(Integer(0))
True
>>> p.set_variable_type(Integer(0), Integer(1))
>>> p.is_variable_integer(Integer(0))
True
set_verbosity(level)[source]

Set the log (verbosity) level.

INPUT:

  • level – integer; from 0 (no verbosity) to 1

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.set_verbosity(0)
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.set_verbosity(Integer(0))
solve()[source]

Solve the problem.

Sage uses HiGHS’s implementation of the branch-and-cut algorithm to solve mixed-integer linear programs. HiGHS automatically selects the most appropriate algorithm based on the problem type.

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:

sage: lp = MixedIntegerLinearProgram(solver = 'HiGHS', maximization = False)
sage: x, y = lp[0], lp[1]
sage: lp.add_constraint(-2*x + y <= 1)
sage: lp.add_constraint(x - y <= 1)
sage: lp.add_constraint(x + y >= 2)
sage: lp.set_objective(x + y)
sage: lp.set_integer(x)
sage: lp.set_integer(y)
sage: lp.solve()
2.0
sage: lp.get_values([x, y])
[1.0, 1.0]
>>> from sage.all import *
>>> lp = MixedIntegerLinearProgram(solver = 'HiGHS', maximization = False)
>>> x, y = lp[Integer(0)], lp[Integer(1)]
>>> lp.add_constraint(-Integer(2)*x + y <= Integer(1))
>>> lp.add_constraint(x - y <= Integer(1))
>>> lp.add_constraint(x + y >= Integer(2))
>>> lp.set_objective(x + y)
>>> lp.set_integer(x)
>>> lp.set_integer(y)
>>> lp.solve()
2.0
>>> lp.get_values([x, y])
[1.0, 1.0]
solver_parameter(name, value=None)[source]

Return or define a solver parameter.

INPUT:

  • name – string; the parameter name

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

HiGHS solver parameters can be set using their option names as documented in the HiGHS documentation: https://ergo-code.github.io/HiGHS/dev/options/definitions/

Common parameters include:

  • time_limit – maximum time in seconds (double)

  • mip_rel_gap – relative MIP gap tolerance (double)

  • mip_abs_gap – absolute MIP gap tolerance (double)

  • threads – number of threads to use (int)

  • presolve – presolve option: “off”, “choose”, or “on”

  • solver – solver to use: “choose”, “simplex”, “ipm”, or “pdlp” (requires CUDA)

  • parallel – parallel option: “off”, “choose”, or “on”

  • log_to_console – whether to log to console: True or False

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.solver_parameter("time_limit", 60)
sage: p.solver_parameter("time_limit")
60.0
sage: p.solver_parameter("threads", 2)
sage: p.solver_parameter("threads")
2
sage: p.solver_parameter("presolve", "on")
sage: p.solver_parameter("presolve")
'on'
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.solver_parameter("time_limit", Integer(60))
>>> p.solver_parameter("time_limit")
60.0
>>> p.solver_parameter("threads", Integer(2))
>>> p.solver_parameter("threads")
2
>>> p.solver_parameter("presolve", "on")
>>> p.solver_parameter("presolve")
'on'

You can also use boolean values for options:

sage: p.solver_parameter("log_to_console", False)
sage: p.solver_parameter("log_to_console")
False
[Python]
>>> from sage.all import *
>>> p.solver_parameter("log_to_console", False)
>>> p.solver_parameter("log_to_console")
False

Float parameters like MIP gap tolerance work correctly:

sage: p.solver_parameter("mip_rel_gap", 0.05)
sage: p.solver_parameter("mip_rel_gap")
0.05
>>> from sage.all import *
>>> p.solver_parameter("mip_rel_gap", RealNumber('0.05'))
>>> p.solver_parameter("mip_rel_gap")
0.05
variable_lower_bound(index, value=False)[source]

Set or get the lower bound of a variable.

INPUT:

  • index – the variable’s id

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

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.add_variable()
0
sage: p.variable_lower_bound(0)
0.0
sage: p.variable_lower_bound(0, -10.0)
sage: p.variable_lower_bound(0)
-10.0
sage: p.variable_lower_bound(0, None)
sage: p.variable_lower_bound(0) is None
True
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variable()
0
>>> p.variable_lower_bound(Integer(0))
0.0
>>> p.variable_lower_bound(Integer(0), -RealNumber('10.0'))
>>> p.variable_lower_bound(Integer(0))
-10.0
>>> p.variable_lower_bound(Integer(0), None)
>>> p.variable_lower_bound(Integer(0)) is None
True
variable_upper_bound(index, value=False)[source]

Set or get the upper bound of a variable.

INPUT:

  • index – the variable’s id

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

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.add_variable()
0
sage: p.variable_upper_bound(0)
sage: p.variable_upper_bound(0, 10.0)
sage: p.variable_upper_bound(0)
10.0
sage: p.variable_upper_bound(0, None)
sage: p.variable_upper_bound(0) is None
True
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variable()
0
>>> p.variable_upper_bound(Integer(0))
>>> p.variable_upper_bound(Integer(0), RealNumber('10.0'))
>>> p.variable_upper_bound(Integer(0))
10.0
>>> p.variable_upper_bound(Integer(0), None)
>>> p.variable_upper_bound(Integer(0)) is None
True
warm_up()[source]

Warm up the basis using current statuses assigned to rows and cols.

This method attempts to validate and use the currently set basis. In HiGHS, setting a basis automatically attempts to factorize it, so this method checks if the current basis is valid.

OUTPUT:

The warming up status:

  • 0 – the operation has been successfully performed

  • -1 – the basis is invalid or could not be factorized

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: lp = get_solver(solver = "HiGHS")
sage: lp.add_variables(3)
2
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [8, 6, 1])), None, 48)
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [4, 2, 1.5])), None, 20)
sage: lp.add_linear_constraint(list(zip([0, 1, 2], [2, 1.5, 0.5])), None, 8)
sage: lp.set_objective([60, 30, 20])
sage: lp.solve()
0
sage: lp.get_objective_value()
280.0
sage: lp.set_row_stat(0, 3)
sage: lp.set_col_stat(1, 1)
sage: lp.warm_up()
0
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> lp = get_solver(solver = "HiGHS")
>>> lp.add_variables(Integer(3))
2
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(8), Integer(6), Integer(1)])), None, Integer(48))
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(4), Integer(2), RealNumber('1.5')])), None, Integer(20))
>>> lp.add_linear_constraint(list(zip([Integer(0), Integer(1), Integer(2)], [Integer(2), RealNumber('1.5'), RealNumber('0.5')])), None, Integer(8))
>>> lp.set_objective([Integer(60), Integer(30), Integer(20)])
>>> lp.solve()
0
>>> lp.get_objective_value()
280.0
>>> lp.set_row_stat(Integer(0), Integer(3))
>>> lp.set_col_stat(Integer(1), Integer(1))
>>> lp.warm_up()
0
write_lp(filename)[source]

Write the problem to a .lp file.

INPUT:

  • filename – string; the file name

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.add_variables(2)
1
sage: p.add_linear_constraint([(0, 1), (1, 1)], None, 2.0)
sage: import tempfile
sage: with tempfile.NamedTemporaryFile(suffix='.lp') as f:
....:     p.write_lp(f.name)
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variables(Integer(2))
1
>>> p.add_linear_constraint([(Integer(0), Integer(1)), (Integer(1), Integer(1))], None, RealNumber('2.0'))
>>> import tempfile
>>> with tempfile.NamedTemporaryFile(suffix='.lp') as f:
...     p.write_lp(f.name)
write_mps(filename, modern)[source]

Write the problem to a .mps file.

INPUT:

  • filename – string; the file name

  • modern – integer; whether to use modern MPS format (ignored for HiGHS)

Note

HiGHS determines the output format from the filename extension. The modern flag is accepted for API compatibility but ignored.

EXAMPLES:

sage: from sage.numerical.backends.generic_backend import get_solver
sage: p = get_solver(solver='HiGHS')
sage: p.add_variables(2)
1
sage: p.add_linear_constraint([(0, 1), (1, 1)], None, 2.0)
sage: import tempfile
sage: with tempfile.NamedTemporaryFile(suffix='.mps') as f:
....:     p.write_mps(f.name, 1)
>>> from sage.all import *
>>> from sage.numerical.backends.generic_backend import get_solver
>>> p = get_solver(solver='HiGHS')
>>> p.add_variables(Integer(2))
1
>>> p.add_linear_constraint([(Integer(0), Integer(1)), (Integer(1), Integer(1))], None, RealNumber('2.0'))
>>> import tempfile
>>> with tempfile.NamedTemporaryFile(suffix='.mps') as f:
...     p.write_mps(f.name, Integer(1))