如何将Gurobi旅行推销员问题Python代码应用于我的数据

如何将Gurobi旅行推销员问题Python代码应用于我的数据,python,pandas,dictionary,traveling-salesman,gurobi,Python,Pandas,Dictionary,Traveling Salesman,Gurobi,我想在我的数据文件中使用来自Gurobi网站的示例旅行推销员问题Python代码。我正在努力处理数据的df,以便将其合并到Gurobi代码中。我对Python还是相当陌生的,最近刚被介绍给Gurobi 我从Gurobi网站上提取了TSP示例代码,并让它运行起来。该示例创建随机点并计算它们之间的距离,以说明TSP问题。我的电子表格中已经有了点和距离,它已作为df导入。在Python中,我似乎无法将df转换为代码使用的正确格式。似乎我需要将我的df转换为字典,其中包含每种可能的成对组合及其距离,但我

我想在我的数据文件中使用来自Gurobi网站的示例旅行推销员问题Python代码。我正在努力处理数据的df,以便将其合并到Gurobi代码中。我对Python还是相当陌生的,最近刚被介绍给Gurobi

我从Gurobi网站上提取了TSP示例代码,并让它运行起来。该示例创建随机点并计算它们之间的距离,以说明TSP问题。我的电子表格中已经有了点和距离,它已作为df导入。在Python中,我似乎无法将df转换为代码使用的正确格式。似乎我需要将我的df转换为字典,其中包含每种可能的成对组合及其距离,但我不知道一种简单的方法

下面是为示例创建虚拟数据的代码部分。我注释掉了我用一小部分数据模拟我的文件的部分

import math
import random
from gurobipy import *

# Euclidean distance between two points 

def distance(points, i, j): 
    dx = points[i][0] - points[j][0] 
    dy = points[i][1] - points[j][1] 
    return math.sqrt(dx*dx + dy*dy)

n=50

# Create n random points 

random.seed(1) 
points = [] 
for i in range(n): 
    points.append((random.randint(0,100),random.randint(0,100))) 

m = Model() 

# Create variables 

vars = {} 
for i in range(n): 
    for j in range(i+1): 
        vars[i,j] = m.addVar(obj=distance(points, i, j), vtype=GRB.BINARY, name='e'+str(i)+'_'+str(j)) 
        vars[j,i] = vars[i,j] 
    m.update()

#Attempting to incorporate my own data
#import pandas as pd
#data = [[0,20,15,8,6],[15,0,18,9,28],[24,23,0,13,13],[15,27,8,0,14],[8,17,24,15,0]]
#df = pd.DataFrame(data, columns=['P1','P2','P3','P4','P5'],index=['P1','P2','P3','P4','P5'])

我希望能够将我的数据的df与Gurobi-TSP-Python代码一起使用。提前感谢您的帮助。

我已经在上回答了这个问题。为方便起见,我在这里重新发布(并详述)答案:

addVars
不直接接受数据帧。如果数据帧
df
中有数据,可以执行以下操作:

n=df.shape[0]
dist = {(i,j) : df.iloc[i][j] for i in range(n) for j in range(n) if i != j}
假设距离矩阵是对称的。 例如,您可以从以下行中看到:

for i,j in vars.keys():
   vars[j,i] = vars[i,j] # edge in opposite direction
您需要删除这些,以使其与不对称矩阵一起工作

此外,应将阶数为2的约束替换为确保每个节点只有一条传入和传出边的约束。即更换

m.addConstrs(vars.sum(i,'*') == 2 for i in range(n))

对于惰性约束,需要确保添加了每条边的两个方向。添加惰性约束应如下所示:

        model.cbLazy(quicksum(model._vars[i,j] + model._vars[j,i]
                              for i,j in itertools.combinations(tour, 2))
                     <= len(tour)-1)
model.cbLazy(quicksum(model.\u vars[i,j]+model.\u vars[j,i]
对于itertools中的i,j.组合(tour,2))

注释掉的
数据
列表是一个成对的距离矩阵吗?它应该是对称的吗?它是一个5x5对称矩阵。我想用一个数据矩阵和古罗比TSP代码一起使用。但它甚至都不接近对称。是否有拼写错误?哎呀,那是一个拼写错误。它绝对是不对称的。有了这个数据,从P1到P2的距离是这与从P2到P1等等的情况不同。很抱歉造成混淆。翻阅我以前的帖子,发现我从来没有跟进过这篇文章。这个回复非常有用。我错误地解释了基本TSP代码的某些部分,这让我偏离了轨道。谢谢你的帮助!虽然我喜欢你的答案,但我觉得有些事情是错误的这里是错误的。首先,在惰性约束中的quicksum之前缺少一个gp。如果没有它,tsp.py将无法正常工作。此外,替换的2度约束似乎是错误的。正如我所想,I!=j,否则vars[I,I]=1假设dist[I,I]=0。当我执行你的建议时,我得到了一个0的obj值,而启发式实现给出了一些有意义的结果。你能重温一下这个公式吗?这对我会有很大的帮助:)我想,添加“m.addConstrs(vars.sum(I,I)==0表示范围(n)内的I”解决了这个问题。点头表示感谢!
        model.cbLazy(quicksum(model._vars[i,j] + model._vars[j,i]
                              for i,j in itertools.combinations(tour, 2))
                     <= len(tour)-1)