gurobipy.MNLExpr#
- class MNLExpr#
Gurobi matrix-friendly nonlinear expression object. An
MNLExpr
stores a dense array ofNLExpr
objects, and makes it possible to formulate a set of nonlinear constraints in Python using a single mathematical expression.You will generally build an
MNLExpr
by starting fromMVar
objects and applying Python operators, nonlinear functions, or a combination of both. AnMNLExpr
will only be created for matrix expressions that cannot be captured by anMLinExpr
orMQuadExpr
. Specifically, formulating a matrix expression where any element of the matrix is not a polynomial of degree at most 2 will result in anMNLExpr
.An
MNLExpr
object has ashape
representing its dimensions, asize
that counts the total number of elements, and anndim
that gives the number of dimensions. These properties lean on their counterparts in NumPy’sndarray
class.When working with
MLinExpr
objects, you need to make sure that the operands’ shapes are compatible. For matrix multiplication, we follow the rules of Python’s matrix multiplication operator: both operands need to have at least one dimension, and their inner dimensions must agree. For more information we refer you to Python’s documentation. Other binary operations such as addition and multiplication are straightforward to understand if both operands have the same shape: the operation is applied point wise on the matching indices. For operands that have different shapes, the arithmetic follows NumPy’s broadcasting rules. We refer you to the NumPy documentation for more information.The following example lists the object types and shapes of various expressions constructed from
MVar
objects:from gurobipy import nlfunc ... x = model.addMVar((3,), name="x") # MVar, shape (3,) y = model.addMVar((3, 3), name="y") # MVar, shape (3,3) z = model.addMVar((3, 3), name="z") # MVar, shape (3,3) expr1 = 2.0 * x # MLinExpr, shape (3,) expr2 = 2.0 * x * y # MQuadExpr, shape (3,3) expr3 = 2.0 * x * y * z # MNLExpr, shape (3,3) expr4 = x / y # MNLExpr, shape (3,3) expr5 = nlfunc.sin(x) # MNLExpr, shape (3,)
Nonlinear matrix expressions are used to build nonlinear matrix general constraints. They are typically temporary objects which are passed immediately to either
Model.addConstr
orModel.addGenConstrNL
to add a group of constraints to the model. Such constraints are always equality constraints with a resultant variable on the left side of the expression. In Python code these constraints can be added using either method. Using theMVar
objects from the previous example:# Add the constraint z_ij = sqrt(x_j + y_ij) for each (i, j) model.addConstr(z == nlfunc.sqrt(x + y)) # Add the constraint z_ij = x_j / y_ij for each (i, j) model.addGenConstrNL(z, x / y)
Nonlinear Inequality Constraints
It is not possible to use
<=
or>=
operators to specify nonlinear inequality constraints usingNLExpr
objects. However, you can formulate an equivalent constraint by creating a bounded resultant variable. For example, the following code constrains that \(log(x_i) \le 1\) for \(i \in {0, 1, 2, 3}\):x = model.addMVar((4,)) res = model.addMVar(x.shape, lb=-GRB.INFINITY, ub=1.0) model.addGenConstrNL(res, nlfunc.log(x))
More control over expression creation
If you want more control over the expression trees generated, you can explicitly opt in to the nonlinear world using the
nl
property ofMVar
objects. This is considered advanced usage. In the vast majority of cases, you do not need to consider how a nonlinear expression is represented internally.MVar.nl
returns anMNLExpr
object holding a matrix of expression trees, each of which represent a single variable. Any arithmetic operations involving that object will also result in anMNLExpr
:x = model.addMVar((2, 2)) # MVar, shape (2,2) expr1 = x + 1.0 # MLinExpr, shape (2,2) expr2 = x.nl # MNLExpr, shape (2,2) expr3 = x.nl + 1.0 # MNLExpr, shape (2,2)
The implications are subtle, but can have an impact on how a constraint is handled by the solver. For example, the following two constraints represent the same set of expressions \((x_i + y_i)^2\) but have a different internal representation in the solver:
x = model.addMVar((5,)) y = model.addMVar((5,)) z = model.addMVar((5,)) c1 = model.addGenConstrNL(z, (x - y) ** 2) c2 = model.addGenConstrNL(z, (x.nl - y.nl) ** 2)
Specifically, the first case captures quadratic expressions in expanded form \(x_i^2 - 2 x_i y_i + y_i^2\). The second case captures a nonlinear expression with \(x_i - y_i\) as a node in the expression tree which is explicitly squared.
Domain restrictions of operators
Some subtleties arise from certain arithmetic operators not being applicable to the whole domain that an operand may have (e.g., division by zero). Refer to the additional information for the divide operator and the power operator for all the details.
- property shape#
The shape of this expression.
- Returns:
A tuple of int
- property size#
The total number of elements in this expression.
- Returns:
An int
- property ndim#
The number of dimensions in this expression.
- Returns:
An int
- sum(axis=None)#
Sum the elements of this
MNLExpr
; returns anMNLExpr
object.- Parameters:
axis – An int, or
None
. Sum along the specified axis. If set toNone
, summation takes place along all axes of thisMNLExpr
.- Returns:
An
MNLExpr
representing the sum.
- item()#
For an
MNLExpr
that contains a single element, returns a copy of that element as anNLExpr
object. Calling this method on anMNLExpr
with more than one element will raise aValueError
.- Returns:
An
NLExpr
object