我正在解决奖品收集TSP并生成削减以消除次要路线的方法。我想生成削减以消除断开的子循环(切削能力= 0),然后,如果没有,则生成“最小切削”切削(0 <切削能力<1)。 问题在于,即使在某些时候,即使子循环的剪切容量小于1,该程序也不会在根节点上添加更多剪切。
有什么办法解决这个问题?
预先感谢
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
from gurobipy import *
def ins_run(n, alpha, t=0):
np.random.seed(t)
depot = n + 1
nodos = [i + 1 for i in range(depot)]
pos = dict(zip([i for i in nodos],list(map(tuple,np.random.random([n, 2]) * 5))))
pos[depot] = pos[1]
c_cam = {(i, j): np.sqrt((pos[i][0] - pos[j][0]) ** 2 + (pos[i][1] - pos[j][1]) ** 2)
for i in nodos for j in nodos if i != j}
c_drone = {e: alpha * c_cam[e] for e in c_cam} # Velocidad del drone
return pos, c_cam, c_drone
def delta_out(arcos, i):
aux = list()
for e in arcos:
if e[0] == i:
aux.append(e)
return aux
def delta_in(arcos, i):
aux = list()
for e in arcos:
if e[1] == i:
aux.append(e)
return aux
def delta_out_S(arcos, S):
aux = list()
for i in S:
for e in delta_out(arcos, i):
if e[1] not in S:
aux.append(e)
return aux
def run_DisconnectedCycle(G, nodos, capacity, peso):
# Los arcos con valor no nulo tienen capacidad 1 y se determinan todos los subciclos desconectados
G.remove_edges_from(list(G.edges))
edges = list()
for (i, j) in capacity:
if capacity[i, j] > 1e-8:
edges.append((i, j))
G.add_edges_from(edges)
st_list = list(nx.simple_cycles(G))
subtour_list = list()
for i in st_list:
if 1 not in i:
peso_subtour = {j: peso[j] for j in i}
subtour_list.append((i, max(peso_subtour, key=peso_subtour.get)))
return subtour_list
def run_MinCut(G, nodos, capacity, peso):
# Para todo j != depot, se hace min-cut. Sobre todos, se elige el subtour mas violado, junto al peso respectivo (gamma)
G.remove_edges_from(list(G.edges))
G.add_edges_from(capacity)
for (i, j) in capacity:
G[i][j]['capacity'] = capacity[i, j]
subtour_list = list()
subtour = None
for j in nodos:
if j != 1:
(cap, (S, S_c)) = nx.minimum_cut(G, 1, j)
if cap - peso[j] < 0:
subtour_list.append((cap - peso[j], j, S_c))
if subtour_list:
subtour = min(subtour_list, key=lambda x: x[0])
return subtour
if __name__ == '__main__':
def PCTSP_CB(m, where):
def get_sol(model):
x_sol = list()
for e in index_2:
arco_x = model.cbGetSolution([x[e]])
if arco_x[0] > 0.5:
x_sol.append(e)
return x_sol
if where == GRB.Callback.MIPSOL:
x_recurso = {e: 0 for e in index_2}
x_sol = get_sol(m)
for e in x_sol:
x_recurso[e] = 1
# SEC en solucion entera
G = nx.DiGraph(x_sol)
subtour_list = list(nx.simple_cycles(G))
for i in subtour_list:
if 1 in i:
subtour_list.remove(i)
break
for subtour in subtour_list:
m.cbLazy(quicksum(x[e] for e in delta_out_S(index_2, subtour)) >= gamma[subtour[0]])
cuts.SEC_int += 1
elif where == GRB.Callback.MIPNODE:
depth = m.cbGet(GRB.Callback.MIPNODE_NODCNT)
if depth == 0:
x_rec = m.cbGetNodeRel(x)
gamma_rec = m.cbGetNodeRel(gamma)
st_DisconnectedCycle = run_DisconnectedCycle(graph.G, nodos, x_rec, gamma_rec)
st_MinCut = run_MinCut(graph.G, nodos, x_rec, gamma_rec)
if st_DisconnectedCycle:
for subtour in st_DisconnectedCycle:
m.cbLazy(quicksum(x[e] for e in delta_out_S(index_2, subtour[0])) >= gamma[subtour[1]])
cuts.SEC_frac_DC += 1
else:
# Si no hay subciclos desconectados, se agrega un Min-Cut
if st_MinCut:
m.cbLazy(quicksum(x[e] for e in delta_out_S(index_2, st_MinCut[2])) >= gamma[st_MinCut[1]])
cuts.SEC_frac_MC += 1
class Graph():
def __init__(self):
self.G = nx.DiGraph()
self.S_track = list()
class Cuts():
def __init__(self):
self.SEC_frac_DC = 0
self.SEC_frac_MC = 0
self.SEC_int = 0
# Data
n = 30
seed = 11
alpha = 0.5
pos, c, d = ins_run(n, alpha, seed)
depot = n + 1
nodos = [i + 1 for i in range(depot)]
index_2 = [(i, j) for i in nodos for j in nodos if i != j]
graph = Graph()
cuts = Cuts()
model = Model()
# model.Params.OutputFlag = 0
model.Params.LazyConstraints = 1
x = model.addVars(index_2, vtype=GRB.BINARY, name='x')
gamma = model.addVars(nodos, vtype=GRB.CONTINUOUS, ub=1, name='z')
model.addConstrs(quicksum(x[e] for e in delta_in(index_2, i)) == gamma[i] for i in nodos)
model.addConstrs(quicksum(x[e] for e in delta_out(index_2, i)) == gamma[i] for i in nodos)
model.addConstr(x[depot, 1] == 1)
model.addConstr(x[1, depot] == 0)
model.addConstr(gamma[1] == 1)
model.addConstr(gamma[depot] == 1)
model.addConstrs(x[e] <= quicksum(x[r] for r in delta_in(index_2, depot) if r[0] <= e[1]) for e in delta_out(index_2, 1))
model.addConstr(quicksum(gamma[i] for i in nodos) >= round((len(nodos) - 1) / 2 + 0.1) + 1)
obj = quicksum(x[e] * c[e] for e in index_2)
model.setObjective(obj, GRB.MINIMIZE)
model.optimize(PCTSP_CB)
print(cuts.SEC_frac_DC, cuts.SEC_frac_MC)