我正在尝试使用python中的PuLP包实现最短路径问题的ILP公式。输入是使用NetworkX包生成的图形。
import networkx as nx
import pulp
import random
import matplotlib.pyplot as plt
g = nx.to_directed(nx.barabasi_albert_graph(20, 2))
# nx.draw(g, with_labels=True)
# plt.show()
source = 0
target = 13
dict_d = {}
for i, j in g.edges:
dict_d[i, j] = dict_d[j, i] = round(random.uniform(1.0, 20.0), 2)
nx.set_edge_attributes(g, dict_d, 'delay')
# instantiate
prob = pulp.LpProblem("Shortest Path Problem", pulp.LpMinimize)
cost = nx.get_edge_attributes(g, 'delay')
# binary variable to state a link is chosen or not
var_dict = {}
for (i, j) in g.edges:
x = pulp.LpVariable("x_(%s_%s)" % (i,j), cat=pulp.LpBinary)
var_dict[i, j] = x
# objective function
prob += pulp.lpSum([cost[i, j] * var_dict[i, j] for i, j in g.edges]), "Total Hop Count"
# constraints
for node in g.nodes:
if node == source:
prob += pulp.lpSum([var_dict[i, k] for i, k in g.edges if k == node]) - \
pulp.lpSum([var_dict[k, j] for k, j in g.edges if k == node]) == 1
elif node == target:
prob += pulp.lpSum([var_dict[i, k] for i, k in g.edges if k == node]) - \
pulp.lpSum([var_dict[k, j] for k, j in g.edges if k == node]) == -1
else:
prob += pulp.lpSum([var_dict[i, k] for i, k in g.edges if k == node]) - \
pulp.lpSum([var_dict[k, j] for k, j in g.edges if k == node]) == 0
# solve
prob.solve(pulp.GUROBI_CMD(msg=0))
print(pulp.LpStatus[prob.status])
print(pulp.value(prob.objective))
print("The shortest path is ")
for link in g.edges:
if var_dict[link].value() == 1.0:
print(link, end=" ")
如果我使用无向图,则流量约束守恒不起作用,因为图中不存在反向边缘。
prob += pulp.lpSum([var_dict[i, k] for i, k in g.edges if k == node]) - \
pulp.lpSum([var_dict[k, j] for k, j in g.edges if k == node]) == 1
另一方面,在使用有向图时,反向边的指标变量取值,导致输出
The shortest path is (1, 2) (2, 0) (13, 1)
当输出应为(0,2)(2,1)(1,13)
时所以我的问题是双管齐下的:
答案 0 :(得分:2)
如果我使用无向图,则流量约束的守恒确实如此 由于图中没有反向边缘,因此无法正常工作。
事实并非如此:我使用prob.writeLP('eyes.lp')
检查余额约束,似乎存在反向边缘。
另一方面,在使用有向图时,指标 反向边的变量取值,导致输出
The shortest path is (1, 2) (2, 0) (13, 1)
当输出应为(0,2)(2,1)(1,13)
时
这里的问题是源和目标约束的符号被翻转:注意你的解决方案从目标到源而不是从源到目标。如果您更改了标志,它将正常工作:
# constraints
for node in g.nodes:
rhs = 0
if node == source:
rhs = -1
elif node == target:
rhs = 1
prob += pulp.lpSum([var_dict[i, k] for i, k in g.edges if k == node]) - \
pulp.lpSum([var_dict[k, j] for k, j in g.edges if k == node]) == rhs
是否有更好的代表性的LP配方 完全避免这个问题的最短路径问题?
LP配方是正确的。
如果失败了,如何获得有意义的路径作为输出?停止反向 弧度取决于价值?从我的输出中以某种方式获取路径 现在开始?
修复标志应使其有效。