gurobipy.NLExpr#

class NLExpr#

Gurobi nonlinear expression object. An NLExpr stores an expression tree, and makes it possible to formulate nonlinear programming (NLP) and mixed integer nonlinear programming (MINLP) models in Python using symbolic math.

You will generally build nonlinear expressions by starting from Var objects and applying Python operators, nonlinear functions, or a combination of both. In general, an NLExpr will only be created for expressions that cannot be captured by a LinExpr or QuadExpr. Specifically, formulating an expression which is not a polynomial of degree at most 2 will result in an NLExpr.

The following example lists the object types of various expressions constructed from Var objects:

from gurobipy import nlfunc

...

x = model.addVar(name="x")  # Var
y = model.addVar(name="y")  # Var
z = model.addVar(name="z")  # Var

expr1 = 2.0 * x             # LinExpr
expr2 = 2.0 * x * y         # QuadExpr
expr3 = 2.0 * x * y * z     # NLExpr
expr4 = x / y               # NLExpr
expr5 = nlfunc.sin(x)       # NLExpr

Nonlinear expressions are used to build nonlinear general constraints. They are typically temporary objects which are passed immediately to either Model.addConstr or Model.addGenConstrNL to add a constraint 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:

model.addConstr(z == nlfunc.sqrt(x + y))
model.addGenConstrNL(z, x / y)

Nonlinear Inequality Constraints

It is not possible to use <= or >= operators to specify nonlinear inequality constraints using NLExpr objects. However, you can formulate an equivalent constraint by creating a bounded resultant variable. For example, the following code constrains that \(log(x) \le 1\):

x = model.addVar()
res = model.addVar(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 ‘opt-in’ to the nonlinear world using the .nl property of Var and MVar 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.

The .nl property returns an NLExpr object representing its object. Any arithmetic operations involving that object will also result in an NLExpr:

x = model.addVar()  # Var
expr1 = x + 1.0     # LinExpr
expr2 = x.nl        # NLExpr
expr3 = x.nl + 1.0  # NLExpr

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 expression \((x + y)^2\) but have a different internal representation in the solver:

c1 = model.addGenConstrNL(z, (x - y) ** 2)
c2 = model.addGenConstrNL(z, (x.nl - y.nl) ** 2)

Specifically, the first case captures a quadratic expression in expanded form \(x^2 - 2xy + y^2\). The second case captures a nonlinear expression with \(x - y\) 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.

copy()#

Returns a copy of this nonlinear expression

Returns:

A new NLExpr object