我正打算在Gurobi(Python界面)中实现设施位置优化模型。我很难翻译模型。数学模型如下所示:
其中dloc,floc是需求(客户)和设施(仓库)位置的(x,y)坐标。 dloc量是常数(即50),与作为决策变量的floc相反:这些量是由求解器计算的。同样,x,y坐标是0到100之间的浮点数。
关键问题之一是我不知道如何添加便利设施变量,其数量可以在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))
任何人都可以在Gurobi中演示该模型的翻译,这将有很大的帮助。
答案 0 :(得分:1)
我认为您对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]
将为您提供坐标
对于需求点然后dloc[i][0]
是x坐标,dloc[i][1]
是x坐标
y坐标。
现在,我们可以创建变量并将其存储在gurobi tubledict中:
# Variables
floc = m.addVars(facilities, 2, name="floc")
isopen = m.addVars(facilities, vtype=GRB.BINARY, name="isopen")
assign = m.addVars(demand, facilities, vtype=GRB.BINARY, name="assign")
n = m.addVar(vtype=GRB.INTEGER, name="n")
m.update()
使用m.addConstrs(),约束可以写为
# 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")
请注意,虽然在距离约束中写floc[j, 0]
并不是问题,但是您不能写dloc[i, 0]
,因为dloc
是python字典,而{{1 }}是元组。
设置目标函数并调用floc
m.optimize()
给我最优解n = 3。