【gurobi】解释gurobi中quicksum和addTerms函数的作用,及举例说明其用法

本文详细比较了Gurobi中的quicksum()和addTerms()函数在构建线性表达式上的作用与用法,指出quicksum()适用于快速求和,addTerms()用于逐项添加,同时给出了实际优化建模中的代码示例.
摘要由CSDN通过智能技术生成

在 Gurobi 中,quicksum()addTerms() 函数都用于构建线性表达式,但它们的使用场景略有不同。下面我将解释它们的作用及用法,并提供示例说明。

1. quicksum() 函数:

  • 作用:用于快速构建对多个变量的求和的线性表达式。
  • 用法:quicksum(expr_list),其中 expr_list 是一个变量和系数的列表或生成器表达式。
  • 示例:
import gurobipy as gp
from gurobipy import GRB

# 创建一个新的模型
model = gp.Model()

# 添加变量
x = model.addVars(5, vtype=GRB.CONTINUOUS, name="x")

# 构建线性表达式:x[0] + x[1] + x[2] + x[3] + x[4]
expr = gp.quicksum(x[i] for i in range(5))

# 输出线性表达式
print(expr)

2. addTerms() 函数:

  • 作用:用于向线性表达式中添加一个或多个项。
  • 用法:addTerms(coefficients, variables, constant=None),其中 coefficients 是项的系数,variables 是对应的变量,constant 是常数项。
  • 示例:
import gurobipy as gp
from gurobipy import GRB

# 创建一个新的模型
model = gp.Model()

# 添加变量
x = model.addVars(5, vtype=GRB.CONTINUOUS, name="x")

# 创建一个空的线性表达式
expr = gp.LinExpr()

# 向线性表达式中添加项:2*x[0] + 3*x[1] + 4*x[2] + 5*x[3] + 6*x[4]
expr.addTerms([2, 3, 4, 5, 6], x)

# 输出线性表达式
print(expr)

总的来说,quicksum() 函数适用于快速构建对多个变量的求和的线性表达式,而 addTerms() 函数则适用于向线性表达式中逐项添加项。根据具体的情况,你可以选择使用其中的一个函数来构建线性表达式。


代码示例:

# 约束
for i in range(1, data.nodeNum - 1):
    expr = LinExpr(0)
    for j in range(data.nodeNum):
        if i != j:
            for k in range(data.vehicleNum):
                if i != 0 and i != data.nodeNum - 1:
                    expr.addTerms(1, X[i][j][k])
    model.addConstr(expr == 1)

这段代码是在使用Python的优化建模库来创建约束条件。具体来说,它是在使用线性表达式(Linear Expression)来设置一个约束条件,确保对于每个节点 i(排除起点和终点),有且仅有一个车辆从该节点出发。

下面是代码的逐行解释:

  1. for i in range(1, data.nodeNum - 1)::遍历节点编号,从第二个节点到倒数第二个节点(排除起点和终点)。

  2. expr = LinExpr(0):创建一个新的线性表达式,初始值为0。这个表达式将用来表示约束条件。

  3. for j in range(data.nodeNum)::遍历所有节点,包括起点和终点。

  4. if i != j::确保节点 i 和 j 不相等,即不考虑从节点 i 到节点 i 的情况。

  5. for k in range(data.vehicleNum)::遍历所有车辆编号。

  6. if i != 0 and i != data.nodeNum - 1::检查节点 i 是否为起点或终点之一,如果不是则执行以下操作。

  7. expr.addTerms(1, X[i][j][k]):将变量 X[i][j][k](表示车辆 k 从节点 i 出发到节点 j 的路径是否被选择)的系数设置为1,并添加到线性表达式 expr 中。

  8. model.addConstr(expr == 1):将刚刚创建的线性表达式 expr 加入到优化模型中作为一个约束条件,要求该表达式的结果等于1,即确保对于节点 i,有且仅有一个车辆从该节点出发。

这段代码的作用是确保每个节点(除了起点和终点)只有一个车辆从该节点出发,从而满足路径规划问题的约束条件。

在这段代码中,expr = LinExpr(0)是在第一层循环下面而不是在循环之前初始化的原因是因为每次循环需要创建一个新的线性表达式,以确保每个约束条件都是独立的。如果将 expr = LinExpr(0) 放在循环之前,那么在每次迭代时,都会在同一个线性表达式对象上累加系数,而不是创建新的表达式,这将导致约束条件叠加在一起,而不是独立地添加到模型中。

通过在每次循环迭代中创建一个新的线性表达式对象,可以确保每个约束条件都是独立的,不会互相影响。因此,将 expr = LinExpr(0) 放在第一层循环内部是为了确保每个节点 i 对应的约束条件都有自己独立的线性表达式对象。

以下是使用quicksum函数重写的代码:

for i in range(1, data.nodeNum - 1):
    expr = quicksum(X[i][j][k] for j in range(data.nodeNum) if i != j for k in range(data.vehicleNum) if i != 0 and i != data.nodeNum - 1)
    model.addConstr(expr == 1)

这段代码与之前的代码实现相同的功能,但使用了quicksum函数来计算表达式中的求和部分。quicksum函数是优化库中的一个函数,用于快速求解迭代求和。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
当优化问题比较复杂时,可以采用 Gurobi 的 Algebraic Modeling Language (AML) 来编写优化模型,这种方法更加高效、简洁,可以使代码更易于维护和修改。下面以一个线性规划问题为例,说明如何使用 AML 编写优化模型。 假设有如下的线性规划问题: $$ \begin{aligned} &\min_{x,y} \quad -x+y \\ &s.t. \quad x+y \leq 2 \\ & \quad \quad x-y \leq 1 \\ & \quad \quad 0 \leq x \leq 1 \\ & \quad \quad y \geq 0 \end{aligned} $$ 使用 AML 编写优化模型的代码如下: ```matlab model = gurobiModel('LP'); % 添加变量 x = model.addVar(0, 1, -1, 'C', 'x'); y = model.addVar(0, Inf, 1, 'C', 'y'); % 添加约束 model.addConstr(x + y <= 2, 'c1'); model.addConstr(x - y <= 1, 'c2'); % 设置优化目标 model.setObjective(x - y, 'minimize'); % 求解模型 model.optimize(); % 获取结果 x_value = model.getVarByName('x').x; y_value = model.getVarByName('y').x; ``` 其,第一行代码创建了一个名为 'LP' 的 Gurobi 模型,然后使用 `model.addVar()` 函数添加了两个变量 x 和 y,分别表示问题的决策变量。接着,使用 `model.addConstr()` 函数添加了两个约束,分别表示问题的两个限制条件。最后,使用 `model.setObjective()` 函数设置了优化目标,即问题的目标函数。之后,使用 `model.optimize()` 函数进行求解,最后使用 `model.getVarByName()` 函数获取变量的取值。 需要注意的是,使用 AML 编写优化模型需要对 Gurobi 的语法和函数有一定的了解,但是一旦掌握了这种方法,编写起来会更加简洁、高效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喝凉白开都长肉的大胖子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值