Я не вижу проблем в вашем определении для 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.
Теперь мы можем создать переменные и сохранить их в 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, а floc
- это tupledict.
Установка целевой функции и вызов m.optimize()
# 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)
дает мне оптимальное решение n = 3.