2016-10-06 1 views
1

Python 및 PuLP 라이브러리를 사용하여 선형 프로그래밍 모델을 작성하여 TSP (Traveling Salesman Problem)를 해결하는 방법은 무엇입니까? 위키Python에서 여행 세일즈맨을위한 선형 프로그래밍 모델 정의

, 목적 함수와 제약

enter image description here

문제입니다 것은 저는 여기에 붙어 오전 내 부분적인 시도이다.

  1. 코드를 정의하는 방법을 알지 못하므로 코드의 최종 제약 조건을 포함하지 않았습니다. 나는 U 변수와이 제약은 현재 모델에 대한 해결,

  2. 또한 용액에 서브 사이클을 방지하기위한 것입니다 생각은 '내가 할 수있는 ... 그런 확실히 잘못 1.0 동일되고 x0_0x1_1 등의 의사 결정 변수를 제공합니다 이것이 내가

    if i == j: 
         upperBound = 0 
    
  3. 있었다하더라도 그렇게

파이썬 코드

import pulp 

def get_dist(tsp): 
    with open(tsp, 'rb') as tspfile: 
     r = csv.reader(tspfile, delimiter='\t') 
     d = [row for row in r] 

    d = d[1:] # skip header row 
    locs = set([r[0] for r in d]) | set([r[1] for r in d]) 
    loc_map = {l:i for i, l in enumerate(locs)} 
    idx_map = {i:l for i, l in enumerate(locs)} 
    dist = [(loc_map[r[0]], loc_map[r[1]], r[2]) for r in d] 
    return dist, idx_map 


def dist_from_coords(dist, n): 
    points = [] 
    for i in range(n): 
     points.append([0] * n) 
    for i, j, v in dist: 
     points[i][j] = points[j][i] = float(v) 
    return points 


def find_tour(): 
    tsp_file = '/Users/test/' + 'my-waypoints-dist-dur.tsv' 
    coords, idx_map = get_dist(tsp_file) 
    n = len(idx_map) 
    dist = dist_from_coords(coords, n) 


    # Define the problem 
    m = pulp.LpProblem('TSP', pulp.LpMinimize) 


    # Create variables 
    # x[i,j] is 1 if edge i->j is on the optimal tour, and 0 otherwise 
    # Also forbid loops 
    x = {} 
    for i in range(n): 
     for j in range(n): 
      lowerBound = 0 
      upperBound = 1 

      # Forbid loops 
      if i == j: 
       upperBound = 0 
       # print i,i 

      x[i,j] = pulp.LpVariable('x' + str(i) + '_' + str(j), lowerBound, upperBound, pulp.LpBinary) 
      # x[j,i] = x[i,j] 


    # Define the objective function to minimize 
    m += pulp.lpSum([dist[i][j] * x[i,j] for i in range(n) for j in range(n)]) 


    # Add degree-2 constraint 
    for i in range(n): 
     m += pulp.lpSum([x[i,j] for j in range(n)]) == 2 


    # Solve and display results 
    status = m.solve() 
    print pulp.LpStatus[status] 
    for i in range(n): 
     for j in range(n): 
      if pulp.value(x[i,j]) >0: 
       print str(i) + '_' + str(j) + ': ' + str(pulp.value(x[i,j])) 

find_tour() 
이유 t 알아낼

내 - 중간 지점 - 거리 - dur.tsv

데이터 파일 can be found here.

결과

0_0: 1.0 
0_5: 1.0 
1_1: 1.0 
1_15: 1.0 
2_2: 1.0 
2_39: 1.0 
3_3: 1.0 
3_26: 1.0 
4_4: 1.0 
4_42: 1.0 
5_5: 1.0 
5_33: 1.0 
6_6: 1.0 
6_31: 1.0 
7_7: 1.0 
7_38: 1.0 
8_8: 1.0 
8_24: 1.0 
9_9: 1.0 
9_26: 1.0 
10_4: 1.0 
10_10: 1.0 
11_11: 1.0 
11_12: 1.0 
12_11: 1.0 
12_12: 1.0 
13_13: 1.0 
13_17: 1.0 
14_14: 1.0 
14_18: 1.0 
15_1: 1.0 
15_15: 1.0 
16_3: 1.0 
16_16: 1.0 
17_13: 1.0 
17_17: 1.0 
18_14: 1.0 
18_18: 1.0 
19_19: 1.0 
19_20: 1.0 
20_4: 1.0 
20_20: 1.0 
21_21: 1.0 
21_25: 1.0 
22_22: 1.0 
22_27: 1.0 
23_21: 1.0 
23_23: 1.0 
24_8: 1.0 
24_24: 1.0 
25_21: 1.0 
25_25: 1.0 
26_26: 1.0 
26_43: 1.0 
27_27: 1.0 
27_38: 1.0 
28_28: 1.0 
28_47: 1.0 
29_29: 1.0 
29_31: 1.0 
30_30: 1.0 
30_34: 1.0 
31_29: 1.0 
31_31: 1.0 
32_25: 1.0 
32_32: 1.0 
33_28: 1.0 
33_33: 1.0 
34_30: 1.0 
34_34: 1.0 
35_35: 1.0 
35_42: 1.0 
36_36: 1.0 
36_47: 1.0 
37_36: 1.0 
37_37: 1.0 
38_27: 1.0 
38_38: 1.0 
39_39: 1.0 
39_44: 1.0 
40_40: 1.0 
40_43: 1.0 
41_41: 1.0 
41_45: 1.0 
42_4: 1.0 
42_42: 1.0 
43_26: 1.0 
43_43: 1.0 
44_39: 1.0 
44_44: 1.0 
45_15: 1.0 
45_45: 1.0 
46_40: 1.0 
46_46: 1.0 
47_28: 1.0 
47_47: 1.0 



... 

업데이트 코드 마지막으로 제약하지 하나의 제약 조건 입니다

import csv 
import pulp 


def get_dist(tsp): 
    with open(tsp, 'rb') as tspfile: 
     r = csv.reader(tspfile, delimiter='\t') 
     d = [row for row in r] 

    d = d[1:] # skip header row 
    locs = set([r[0] for r in d]) | set([r[1] for r in d]) 
    loc_map = {l:i for i, l in enumerate(locs)} 
    idx_map = {i:l for i, l in enumerate(locs)} 
    dist = [(loc_map[r[0]], loc_map[r[1]], r[2]) for r in d] 
    return dist, idx_map 


def dist_from_coords(dist, n): 
    points = [] 
    for i in range(n): 
     points.append([0] * n) 
    for i, j, v in dist: 
     points[i][j] = points[j][i] = float(v) 
    return points 


def find_tour(): 
    tsp_file = '/Users/test/' + 'my-waypoints-dist-dur.tsv' 
    coords, idx_map = get_dist(tsp_file) 
    n = len(idx_map) 
    dist = dist_from_coords(coords, n) 


    # Define the problem 
    m = pulp.LpProblem('TSP', pulp.LpMinimize) 


    # Create variables 
    # x[i,j] is 1 if edge i->j is on the optimal tour, and 0 otherwise 
    # Also forbid loops 
    x = {} 
    for i in range(n+1): 
     for j in range(n+1): 
      lowerBound = 0 
      upperBound = 1 

      # Forbid loops 
      if i == j: 
       upperBound = 0 
       # print i,i 

      # Create the decision variable and First constraint 
      x[i,j] = pulp.LpVariable('x' + str(i) + '_' + str(j), lowerBound, upperBound, pulp.LpBinary) 
      # x[j,i] = x[i,j] 


    # Define the objective function to minimize 
    m += pulp.lpSum([dist[i][j] * x[i,j] for i in range(1,n+1) for j in range(1,n+1)]) 


    # Add degree-2 constraint (3rd and 4th) 
    for i in range(1,n+1): 
     m += pulp.lpSum([x[i,j] for j in range(1,n+1)]) == 2 


    # Add the last (5th) constraint (prevents subtours) 
    u = [] 
    for i in range(1, n+1): 
     u.append(pulp.LpVariable('u_' + str(i), cat='Integer')) 
    for i in range(1, n-1): 
     for j in range(i+1, n+1): 
      m += pulp.lpSum([ u[i] - u[j] + n*x[i,j]]) <= n-1 


    # status = m.solve() 
    # print pulp.LpStatus[status] 
    # for i in range(n): 
    # for j in range(n): 
    #  if pulp.value(x[i,j]) >0: 
    #   print str(i) + '_' + str(j) + ': ' + str(pulp.value(x[i,j])) 

find_tour() 
+0

어떤 문제 : 먼저 cat='Integer' 인수 LpVariable에 전달, 정수로 u_i 변수를 선언해야하지만

for i in range(n-1): for j in range(i+1, n): m += pulp.lpSum([ u[i] - u[j] + n*x[i,j]]) <= n-1 

코드를 가지고 있습니까? – kindall

+0

@kindall 최종 제약 조건을 정의하는 방법을 모르기 때문에 최종 제약 조건을 포함하지 않았습니다. 또한, 현재 모델에 대한 해결은'x1_1'과 같은 의사 결정 변수가'1.0'과 같아서 틀린 것입니다 ... 왜 그런지 모르겠습니다. – Nyxynyx

+0

@kindall 문제를 명확히하기 위해 질문을 업데이트하고 잘못된 결과를 현재 코드에 포함 시켰습니다. – Nyxynyx

답변

0

. 당신은 그 조건을 만족하는 인덱스 i, j의 각 쌍에 대해 하나 개의 제약 조건을 추가해야합니다 :

u = [] 
for i in range(n): 
    u.append(pulp.LpVariable('u_' + str(i), cat='Integer')) 
+0

감사합니다. 귀하의 제안을 검토하고 있습니다. 현재 코드가 지금까지 괜찮은 것 같습니까? 'x0_0','x1_1' 등이 '0.0' 대신에 '1.0'의 값을 가지게 된 이유는 마지막 제약이 없기 때문입니까? – Nyxynyx

+0

@Nyxynyx 마지막 제약 조건은 문제에 절대적으로 중요합니다. 그것이 없으면 문제는 * 정수 * 선형 문제가 아니며 단지 선형 문제이므로 TSP를 의미있는 방식으로 표현할 수 없습니다 (TSP는 다항식 시간으로 풀 수 없으며 "좋은 방법"으로 근사 할 수 없음을 기억하십시오) "다항식 시간에서, 따라서 다항식 시간에 항상 풀릴 수있는 모든 비 정수 선형 프로그래밍 문제는 그것을 표현할 수 없거나 좋은 근사를 나타낼 수 없습니다. – Bakuriu

+0

마지막 제약 조건에 대한 코드를 동화 시키려고 할 때 현재 코드에 적용 해 보았습니다 만, 그 결과는 이상하게 보입니다. 변수'x [i, j]''i == j '에 대해서'1.0'의 값을 얻었습니다. – Nyxynyx