Python 在Gurobi中添加大小为n的二进制变量

Python 在Gurobi中添加大小为n的二进制变量,python,gurobi,Python,Gurobi,我试图在Gurobi(Python接口)中实现一个设施位置优化模型。我翻译这个模型有些困难。数学模型如下所示: 其中,dloc、floc是需求(客户)和设施(仓库)位置的(x,y)坐标。dloc数量是常数(即50),与floc相反,floc是决策变量:由解算器计算。此外,x、y坐标是介于0和100之间的浮点数 其中一个关键问题是我不知道如何添加facility变量,该变量的数目可以是0到n之间的任何一个 到目前为止,我的代码是: from gurobipy import * import nu

我试图在Gurobi(Python接口)中实现一个设施位置优化模型。我翻译这个模型有些困难。数学模型如下所示:

其中,dloc、floc是需求(客户)和设施(仓库)位置的(x,y)坐标。dloc数量是常数(即50),与floc相反,floc是决策变量:由解算器计算。此外,x、y坐标是介于0和100之间的浮点数

其中一个关键问题是我不知道如何添加facility变量,该变量的数目可以是0到n之间的任何一个

到目前为止,我的代码是:

from gurobipy import *
import numpy as np
import math


def distance(a, b):
    dx = a[0] - b[0]
    dy = a[1] - b[1]
    return math.sqrt(dx ** 2 + dy ** 2)

customer = np.random.uniform(0,100,[50,2])
print(customer)

m = Model()

n = m.addVar(lb=0.0, ub=GRB.INFINITY,vtype=GRB.INTEGER) #number of candidate facilities

facility={}
for j in range(n):
    facility[j] = m.addVar(vtype=GRB.BINARY, name="facility%d" % j) #certainly this is not correct, as an error is reported as 'Var' object cannot be interpreted as an integer

floc = ? 
因此,我尝试了另一种方法,手动设置固定数量的候选设施作为临时解决方案:

from gurobipy import *
import numpy as np
import math

customer = np.random.uniform(0,100,[50,2])
print(customer)

m = Model()

###Variable
dc={}
x={}
y={}
assign={}

for j in range(10):
    dc[j] = m.addVar(lb=0,ub=1,vtype=GRB.BINARY, name="DC%d" % j)
    x[j]= m.addVar(lb=0, ub=100, vtype=GRB.CONTINUOUS, name="x%d")
    y[j] = m.addVar(lb=0, ub=100, vtype=GRB.CONTINUOUS, name="y%d")
for i in range(len(customer)):

    for j in range(len(dc)):
        assign[(i,j)] = m.addVar(lb=0,ub=1,vtype=GRB.BINARY, name="Cu%d from DC%d" % (i,j))

###Constraint
for i in range(len(customer)):
    for j in range(len(dc)):
        m.addConstr(((customer[i][0] - x[j])*(customer[i][0] - x[j]) +\
                              (customer[i][1] - y[j])*(customer[i][1] - y[j])) <= 40*40 + 100*100*(1-assign[(i,j)]))

for i in range(len(customer)):
    m.addConstr(quicksum(assign[(i,j)] for j in range(len(dc))) == 1)

for i in range(len(customer)):
    for j in range(len(dc)):
        m.addConstr(assign[(i, j)] <= dc[j])

n=0
for j in dc:
    n=n+dc[j]

m.setObjective(n,GRB.MINIMIZE)

m.optimize()

print('\nOptimal Solution is: %g' % m.objVal)
for v in m.getVars():
    print('%s %g' % (v.varName, v.x))
从gurobipy导入*
将numpy作为np导入
输入数学
客户=np.随机统一(0100[50,2])
打印(客户)
m=模型()
###变数
dc={}
x={}
y={}
赋值={}
对于范围(10)内的j:
dc[j]=m.addVar(lb=0,ub=1,vtype=GRB.BINARY,name=“dc%d”%j)
x[j]=m.addVar(lb=0,ub=100,vtype=GRB.CONTINUOUS,name=“x%d”)
y[j]=m.addVar(lb=0,ub=100,vtype=GRB.CONTINUOUS,name=“y%d”)
对于范围内的i(len(客户)):
对于范围内的j(len(dc)):
赋值[(i,j)]=m.addVar(lb=0,ub=1,vtype=GRB.BINARY,name=“Cu%d from DC%d”%(i,j))
###约束
对于范围内的i(len(客户)):
对于范围内的j(len(dc)):
m、 addConstr(((客户[i][0]-x[j])*(客户[i][0]-x[j])+\

(customer[i][1]-y[j])*(customer[i][1]-y[j])我认为您对
n
的定义没有问题。尽管如此,我重新编写了您的代码,使其不那么冗长,更容易理解。首先,我们创建给定的集合和常量:

from gurobipy import Model, GRB, quicksum
import numpy as np

m = Model()

demo_coords = np.random.uniform(0, 100, size=(50, 2)) # Just for demonstration

# Sets and Constants
demand = [f"i{k}" for k in range(1, 51)]
facilities = [ f"facility{k}" for k in range(1, 11) ]
dloc = {fac : demo_coords[i] for i, fac in enumerate(demand)}
maxdist = 40
M = 10e6
请注意,
dloc
是一个字典,因此
dloc[i]
将为您提供坐标 对于需求点i,
dloc[i][0]
是x坐标,
dloc[i][1]
是 y坐标

现在我们可以创建变量并将其存储在:

使用,可以将约束编写为

# Constraints
m.addConstrs(((dloc[i][0] - floc[j, 0]) * (dloc[i][0] - floc[j, 0]) \
    + (dloc[i][1] - floc[j, 1])*(dloc[i][1] - floc[j, 1]) \
    <= maxdist**2 + M * (1 - assign[i, j]) \
    for i in demand for j in facilities), name="distance")

m.addConstrs((quicksum(assign[i, j] for j in facilities) == 1\
              for i in demand), name="assignDemand")

m.addConstrs((assign[i, j] <= isopen[j] for i in demand for j in facilities),\
name="closed")

m.addConstr(n == quicksum(isopen[j] for j in facilities), name="numFacilities")

# zip is needed to iterate over all pairs of consecutive facilites
m.addConstrs((isopen[j] >= isopen[jp1] \
    for j, jp1 in zip(facilities, facilities[1:])), name="order")

为我提供了最佳解决方案n=3。

事实上,我不知道需要打开多少个设施。使用不同的数据集,可能需要打开10多个设施。我们是否总是必须手动为设施变量定义一个(大)数字?您所说的“设施变量”是什么意思?开放设施的数量n?独立于数据集,在这个模型中,
n
不能超过设施的数量,因为numFacilites约束。我的意思是候选设施数不胜数,因为这是一个连续的设施位置问题。这里我设置了设施变量“dc{}”作为10,这意味着最多只能有10个开放设施。但在实际情况中,根据数据,可能需要超过10个开放设施才能获得解决方案。根据您的模型,候选设施是作为一个集合给出的,因此不是无数的。假设候选设施集合是无数的:在e设施需要为每个需求点打开。为了满足您的需求,您可以创建两个集合,使候选设施集合和需求点集合具有相同的大小。根据需求点的数量,在这种情况下,由于二进制变量的数量,模型将难以解算。如果我设置候选位置变量如果与需求点的大小相同,它会显著增加计算时间吗?那么对于这种连续的设施位置问题,特别是当所需的设施数量难以估计时,您的建议是什么?
# Constraints
m.addConstrs(((dloc[i][0] - floc[j, 0]) * (dloc[i][0] - floc[j, 0]) \
    + (dloc[i][1] - floc[j, 1])*(dloc[i][1] - floc[j, 1]) \
    <= maxdist**2 + M * (1 - assign[i, j]) \
    for i in demand for j in facilities), name="distance")

m.addConstrs((quicksum(assign[i, j] for j in facilities) == 1\
              for i in demand), name="assignDemand")

m.addConstrs((assign[i, j] <= isopen[j] for i in demand for j in facilities),\
name="closed")

m.addConstr(n == quicksum(isopen[j] for j in facilities), name="numFacilities")

# zip is needed to iterate over all pairs of consecutive facilites
m.addConstrs((isopen[j] >= isopen[jp1] \
    for j, jp1 in zip(facilities, facilities[1:])), name="order")
# Objective
m.setObjective(n, sense=GRB.MINIMIZE)

m.optimize()

if m.status == GRB.OPTIMAL:
    print(f"Optimal Solution is: {m.objVal}")
    print("--------------")
    for var in m.getVars():
        print(var.varName, var.X)