123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- import sys
- import copy
- import math
- from heapq import heappush, heappop
- from random import randint
- import matplotlib.pyplot as plt
- distances = []
- n = 0
- # returns hueristic value
- def heuristic(source, target, dist):
- #return 0
- for i in range(0, min(n * 2, n ** 2)):
- if (dist <= distances[i]):
- return 0
- return dist
- # returns weight(distance) between 2 vertices
- def weight(city1, city2):
- return math.sqrt((city1[1] - city2[1]) ** 2 + (city1[2] - city2[2]) ** 2)
- # returns if going to city i from curnode is okay
- def valid(curnode, cities, i):
- # can't revisit a city
- if (i in curnode[2]):
- return False
- # if curnode hasn't visited everything else and we are going to the gaol
- elif (len(curnode[2]) != (len(cities) - 1) and i == (len(cities) - 1)):
- return False
- else:
- return True
- # returns the count of child states. updates frontier
- def explore(curnode, frontier, cities):
- children = 0
-
- for i in range(1, len(cities)):
- # can we go here?
- if (valid(curnode, cities, i)):
- children += 1
- # add to frontier
- dist = weight(curnode[1], cities[i])
- metric = dist + heuristic(curnode[1], cities[i], dist)
- heappush(frontier, [curnode[0] + metric, cities[i], copy.deepcopy(curnode[2])])
-
- return children
- # A* solver for TSP
- def solve(frontier, cities):
- # number of child states
- newnodes = 0
- curnode = heappop(frontier)
-
- # while we are not on the goal node
- while (curnode[1] != cities[-1]):
- newnodes += explore(curnode, frontier, cities)
- curnode = heappop(frontier)
- curnode[2].append(cities.index(curnode[1]))
-
- return newnodes + 1
- def tsp(filename):
- # import map
- #prob = "instance_10.txt"
- prob = filename
- with open(prob) as file:
- prob = file.read().splitlines()
- n = int(prob[0])
- cities = prob[1:]
- counter = 0
- # convert to list of list of ints
- for l in cities:
- temp = l.split()
- temp[1] = int(temp[1])
- temp[2] = int(temp[2])
- temp.append(counter)
- counter += 1
- cities[cities.index(l)] = temp
-
- distances = []
-
- for i in range(0, len(cities) - 1):
- for j in range(i, len(cities)):
- dist = weight(cities[i], cities[j])
- distances.append(dist)
-
- distances.sort()
-
- # add in goal state
- cities.append(copy.deepcopy(cities[0]))
- cities[-1][0] = "Goal"
-
- # create frontier
- frontier = []
- # add start state, list of visited, and distancesofar to frontier
- heappush(frontier, [0, cities[0], [0]])
- result = solve(frontier, cities)
- print(result)
- return result
- def main():
- global distances
- global n
- plt.ioff()
- plt.switch_backend('agg')
- averages = []
-
- for i in range(1, 12):
- average = 0
- for j in range(1, 11):
- filepath = "tsp_problems/" + str(i) + "/instance_" + str(j) + ".txt"
- average += tsp(filepath)
-
- averages.append(average / 10.0)
-
- figure, axes = plt.subplots(1, 1, True)
- axes.semilogy(range(1, 12), averages, label='TSP Solver (Heuristic)')
- axes.legend()
- plt.xlabel("Number of Cities")
- plt.ylabel("Average Number of Nodes Generated in 10 Runs")
- plt.savefig("tsph.pdf")
-
- main()
|