Hide navigation sidebar
Hide table of contents sidebar
Back to top
Toggle table of contents sidebar

# gurobipy.MNLExpr

class MNLExpr

  Gurobi matrix-friendly nonlinear expression object. An `MNLExpr` stores a dense array of `NLExpr` 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 from `MVar` objects and applying Python operators, nonlinear functions, or a combination of both. An `MNLExpr` will only be created for matrix expressions that cannot be captured by an `MLinExpr` or `MQuadExpr`. Specifically, formulating a matrix expression where any element of the matrix is not a polynomial of degree at most 2 will result in an `MNLExpr`.

  An `MNLExpr` object has a `shape` representing its dimensions, a `size` that counts the total number of elements, and an `ndim` that gives the number of dimensions. These properties lean on their counterparts in NumPy’s `ndarray` 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` or `Model.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 the `MVar` 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 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_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 of `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.

  `MVar.nl` returns an `MNLExpr` object holding a matrix of expression trees, each of which represent a single variable. Any arithmetic operations involving that object will also result in an `MNLExpr`:

      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 an `MNLExpr` object.

    Parameters:

      axis – An int, or `None`. Sum along the specified axis. If set to `None`, summation takes place along all axes of this `MNLExpr`.

    Returns:

      An `MNLExpr` representing the sum.

  item()

    For an `MNLExpr` that contains a single element, returns a copy of that element as an `NLExpr` object. Calling this method on an `MNLExpr` with more than one element will raise a `ValueError`.

    Returns:

      An `NLExpr` object

Help and Feedback

Press `/` or click to search this documentation | Gurobi website | Gurobi community forum
Go to other Gurobi documentation | Gurobi download | Contact support