gurobipy.MNLExpr#

class MNLExpr#

Gurobi 矩阵友好的非线性表达式对象。一个 MNLExpr 存储了一个密集的 NLExpr 对象数组,并使得在 Python 中使用单个数学表达式来制定一组非线性约束成为可能。

通常,您会从MVar对象开始构建一个MNLExpr,并应用Python运算符、非线性函数或两者的组合。只有在矩阵表达式无法通过MLinExprMQuadExpr捕获时,才会创建MNLExpr。具体来说,如果矩阵的任何元素不是最多2次的多项式,则会导致生成MNLExpr

一个MNLExpr对象有一个表示其维度的shape,一个计算元素总数的size,以及一个给出维数的ndim。这些属性依赖于NumPy的ndarray类中的对应属性。

在使用MLinExpr对象时,您需要确保操作数的形状是兼容的。对于矩阵乘法,我们遵循Python的矩阵乘法运算符的规则:两个操作数都需要至少有一个维度,并且它们的内维度必须一致。更多信息请参考Python的文档。如果两个操作数具有相同的形状,其他二元操作(如加法和乘法)则很容易理解:操作是按点应用于匹配的索引上。对于具有不同形状的操作数,算术遵循NumPy的广播规则。更多信息请参考NumPy的文档。

以下示例列出了从MVar对象构建的各种表达式的对象类型和形状:

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,)

非线性矩阵表达式用于构建非线性矩阵的一般约束。它们通常是临时对象,立即传递给Model.addConstrModel.addGenConstrNL,以向模型添加一组约束。这些约束始终是等式约束,表达式的左侧有一个结果变量。在Python代码中,可以使用任一方法添加这些约束。使用上一个示例中的MVar对象:

# 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)

非线性不等式约束

无法使用<=>=运算符通过NLExpr对象指定非线性不等式约束。但是,您可以通过创建一个有界结果变量来制定等效的约束。例如,以下代码约束了\(log(x_i) \le 1\)对于\(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))

更多控制表达式创建

如果你想对生成的表达式树有更多的控制,你可以显式地选择进入非线性世界,使用nl属性,这是MVar对象的一个属性。这被认为是高级用法。在绝大多数情况下,你不需要考虑非线性表达式在内部是如何表示的。

MVar.nl 返回一个 MNLExpr 对象,该对象包含一个表达式树的矩阵,每个表达式树代表一个单独的变量。任何涉及该对象的算术操作也将产生一个 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)

影响是微妙的,但可能会影响求解器如何处理约束。例如,以下两个约束表示相同的表达式集 \((x_i + y_i)^2\),但在求解器中具有不同的内部表示:

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)

具体来说,第一种情况捕捉了展开形式的二次表达式 \(x_i^2 - 2 x_i y_i + y_i^2\)。第二种情况捕捉了一个非线性 表达式,其中\(x_i - y_i\)作为表达式树中的一个节点,并且 被显式地平方。

操作符的域限制

某些算术运算符可能不适用于操作数可能具有的整个域(例如,除以零),这会产生一些微妙的问题。有关所有详细信息,请参阅除法运算符幂运算符的附加信息。

property shape#

此表达式的形状。

Returns:

一个整数元组

property size#

此表达式中的元素总数。

Returns:

一个整数

property ndim#

此表达式中的维度数量。

Returns:

一个整数

sum(axis=None)#

求这个MNLExpr的元素之和;返回一个MNLExpr对象。

Parameters:

axis – 一个整数,或 None。沿指定轴求和。如果设置为 None,则沿此 MNLExpr 的所有轴进行求和。

Returns:

一个表示总和的MNLExpr

item()#

对于一个包含单个元素的MNLExpr,返回该元素的副本作为一个NLExpr对象。在一个包含多个元素的MNLExpr上调用此方法将会引发一个ValueError

Returns:

一个NLExpr对象