file_format | kernelspec | ||
---|---|---|---|
mystnb |
|
PyOptInterface supports the following types of constraints:
- Linear Constraint
- Quadratic Constraint
- Second-Order Cone Constraint
- Special Ordered Set (SOS) Constraint
:::{note}
Not all optimizers support all types of constraints. Please refer to the documentation of the optimizer you are using to see which types of constraints are supported. :::
import pyoptinterface as poi
from pyoptinterface import copt
model = copt.Model()
The sense of a constraint can be one of the following:
poi.Eq
: equalpoi.Leq
: less than or equalpoi.Geq
: greater than or equal
They are the abbreviations of poi.ConstraintSense.Equal
, poi.ConstraintSense.LessEqual
or poi.ConstraintSense.GreaterEqual
and can be used in the sense
argument of the constraint creation functions.
It is defined as:
It can be added to the model using the add_linear_constraint
method of the Model
class.
x = model.add_variable(name="x")
y = model.add_variable(name="y")
con = model.add_linear_constraint(2.0*x + 3.0*y, poi.Leq, 1.0)
add a linear constraint to the model
:param expr: the expression of the constraint
:param pyoptinterface.ConstraintSense sense: the sense of the constraint
:param float rhs: the right-hand side of the constraint
:param str name: the name of the constraint, optional
:return: the handle of the constraint
:::{note}
PyOptInterface provides project:#pyoptinterface.Eq, project:#pyoptinterface.Leq, and project:#pyoptinterface.Geq as alias of project:#pyoptinterface.ConstraintSense to represent the sense of the constraint with a shorter name. :::
Like the linear constraint, it is defined as:
It can be added to the model using the add_quadratic_constraint
method of the Model
class.
x = model.add_variable(name="x")
y = model.add_variable(name="y")
expr = x*x + 2.0*x*y + 4.0*y*y
con = model.add_quadratic_constraint(expr, poi.ConstraintSense.LessEqual, 1.0)
add a quadratic constraint to the model
:param expr: the expression of the constraint
:param pyoptinterface.ConstraintSense sense: the sense of the constraint, which can be `GreaterEqual`, `Equal`, or `LessEqual`
:param float rhs: the right-hand side of the constraint
:param str name: the name of the constraint, optional
:return: the handle of the constraint
It is defined as:
It can be added to the model using the add_second_order_cone_constraint
method of the Model
class.
N = 6
vars = [model.add_variable() for i in range(N)]
con = model.add_second_order_cone_constraint(vars)
There is another form of second-order cone constraint called as rotated second-order cone constraint, which is defined as:
add a second order cone constraint to the model
:param variables: the variables of the constraint, can be a list of variables
:param str name: the name of the constraint, optional
:param bool rotated: whether the constraint is a rotated second-order cone constraint, optional
:return: the handle of the constraint
It is defined as:
The dual form is:
Currently, only COPT(after 7.1.4), Mosek support exponential cone constraint. It can be added to the model using the add_exp_cone_constraint
method of the Model
class.
add a second order cone constraint to the model
:param variables: the variables of the constraint, can be a list of variables
:param str name: the name of the constraint, optional
:param bool dual: whether the constraint is dual form of exponential cone, optional
:return: the handle of the constraint
SOS constraints are used to model special structures in the optimization problem.
It contains two types: SOS1
and SOS2
, the details can be found in Wikipedia.
It can be added to the model using the add_sos_constraint
method of the Model
class.
N = 6
vars = [model.add_variable(domain=poi.VariableDomain.Binary) for i in range(N)]
con = model.add_sos_constraint(vars, poi.SOSType.SOS1)
add a special ordered set constraint to the model
:param variables: the variables of the constraint, can be a list of variables
:param pyoptinterface.SOSType sos_type: the type of the SOS constraint, which can be `SOS1` or `SOS2`
:param weights: the weights of the variables, optional, will be set to 1 if not provided
:type weights: list[float]
:return: the handle of the constraint
After a constraint is created, we can query or modify its attributes. The following table lists the standard constraint attributes:
:::{list-table} Standard constraint attributes :header-rows: 1 :widths: 20 20
-
- Attribute name
- Type
-
- Name
- str
-
- Primal
- float
-
- Dual
- float
-
- IIS
- bool :::
The most common attribute we will use is the Dual
attribute, which represents the dual multiplier of the constraint after optimization.
# get the dual multiplier of the constraint after optimization
dual = model.get_constraint_attribute(con, poi.ConstraintAttribute.Dual)
We can delete a constraint by calling the delete_constraint
method of the model:
model.delete_constraint(con)
After a constraint is deleted, it cannot be used in the model anymore, otherwise an exception will be raised.
We can query whether a constraint is active by calling the is_constraint_active
method of the
model:
is_active = model.is_constraint_active(con)
For linear and quadratic constraints, we can modify the right-hand side of a constraint by
calling the set_normalized_rhs
method of the model.
For linear constraints, we can modify the coefficients of the linear part of the constraint by
calling the set_normalized_coefficient
method of the model.
con = model.add_linear_constraint(x + y, poi.Leq, 1.0)
# modify the right-hand side of the constraint
model.set_normalized_rhs(con, 2.0)
# modify the coefficient of the linear part of the constraint
model.set_normalized_coefficient(con, x, 2.0)
In other modeling languages, we can create a constraint with a comparison operator, like:
model.addConsr(x + y <= 1)
This is quite convenient, so PyOptInterface now supports to create constraint with comparison operators <=
, ==
, >=
as a shortcut to create a linear or quadratic constraint.
model.add_linear_constraint(x + y <= 1)
model.add_linear_constraint(x <= y)
model.add_quadratic_constraint(x*x + y*y <= 1)
:::{note}
Creating constraint with comparison operator may cause performance issue especially the left-hand side and right-hand side of the constraint are complex expressions. PyOptInterface needs to create a new expression by subtracting the right-hand side from the left-hand side, which may be time-consuming.
If that becomes the bottleneck of performance, it is recommended to construct the left-hand side expression with ExprBuilder
and call add_linear_constraint
or add_quadratic_constraint
method to create constraints explicitly.
:::