tsp.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import sys
  2. import copy
  3. import math
  4. from heapq import heappush, heappop
  5. from random import randint
  6. import matplotlib.pyplot as plt
  7. distances = []
  8. n = 0
  9. # returns hueristic value
  10. def heuristic(source, target, dist):
  11. #return 0
  12. for i in range(0, min(n * 2, n ** 2)):
  13. if (dist <= distances[i]):
  14. return 0
  15. return dist
  16. # returns weight(distance) between 2 vertices
  17. def weight(city1, city2):
  18. return math.sqrt((city1[1] - city2[1]) ** 2 + (city1[2] - city2[2]) ** 2)
  19. # returns if going to city i from curnode is okay
  20. def valid(curnode, cities, i):
  21. # can't revisit a city
  22. if (i in curnode[2]):
  23. return False
  24. # if curnode hasn't visited everything else and we are going to the gaol
  25. elif (len(curnode[2]) != (len(cities) - 1) and i == (len(cities) - 1)):
  26. return False
  27. else:
  28. return True
  29. # returns the count of child states. updates frontier
  30. def explore(curnode, frontier, cities):
  31. children = 0
  32. for i in range(1, len(cities)):
  33. # can we go here?
  34. if (valid(curnode, cities, i)):
  35. children += 1
  36. # add to frontier
  37. dist = weight(curnode[1], cities[i])
  38. metric = dist + heuristic(curnode[1], cities[i], dist)
  39. heappush(frontier, [curnode[0] + metric, cities[i], copy.deepcopy(curnode[2])])
  40. return children
  41. # A* solver for TSP
  42. def solve(frontier, cities):
  43. # number of child states
  44. newnodes = 0
  45. curnode = heappop(frontier)
  46. # while we are not on the goal node
  47. while (curnode[1] != cities[-1]):
  48. newnodes += explore(curnode, frontier, cities)
  49. curnode = heappop(frontier)
  50. curnode[2].append(cities.index(curnode[1]))
  51. return newnodes + 1
  52. def tsp(filename):
  53. # import map
  54. #prob = "instance_10.txt"
  55. prob = filename
  56. with open(prob) as file:
  57. prob = file.read().splitlines()
  58. n = int(prob[0])
  59. cities = prob[1:]
  60. counter = 0
  61. # convert to list of list of ints
  62. for l in cities:
  63. temp = l.split()
  64. temp[1] = int(temp[1])
  65. temp[2] = int(temp[2])
  66. temp.append(counter)
  67. counter += 1
  68. cities[cities.index(l)] = temp
  69. distances = []
  70. for i in range(0, len(cities) - 1):
  71. for j in range(i, len(cities)):
  72. dist = weight(cities[i], cities[j])
  73. distances.append(dist)
  74. distances.sort()
  75. # add in goal state
  76. cities.append(copy.deepcopy(cities[0]))
  77. cities[-1][0] = "Goal"
  78. # create frontier
  79. frontier = []
  80. # add start state, list of visited, and distancesofar to frontier
  81. heappush(frontier, [0, cities[0], [0]])
  82. result = solve(frontier, cities)
  83. print(result)
  84. return result
  85. def main():
  86. global distances
  87. global n
  88. plt.ioff()
  89. plt.switch_backend('agg')
  90. averages = []
  91. for i in range(1, 12):
  92. average = 0
  93. for j in range(1, 11):
  94. filepath = "tsp_problems/" + str(i) + "/instance_" + str(j) + ".txt"
  95. average += tsp(filepath)
  96. averages.append(average / 10.0)
  97. figure, axes = plt.subplots(1, 1, True)
  98. axes.semilogy(range(1, 12), averages, label='TSP Solver (Heuristic)')
  99. axes.legend()
  100. plt.xlabel("Number of Cities")
  101. plt.ylabel("Average Number of Nodes Generated in 10 Runs")
  102. plt.savefig("tsph.pdf")
  103. main()