SHOW:
|
|
- or go back to the newest paste.
1 | ##############################################<START OF PROGRAM>############################################## | |
2 | def setUpCanvas(root): # These are the REQUIRED magic lines to enter graphics mode. | |
3 | root.title("THE TRAVELING SALESMAN PROBLEM by (your name here).") | |
4 | canvas = Canvas(root, width = root.winfo_screenwidth(), height = root.winfo_screenheight(), bg = 'black') | |
5 | canvas.pack(expand = YES, fill = BOTH) | |
6 | return canvas | |
7 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
8 | ||
9 | def script(x, y, msg = '', kolor = 'WHITE'): | |
10 | canvas.create_text(x, y, text = msg, fill = kolor, font = ('Helvetica', 10, 'bold')) | |
11 | #---------------------------------------------------------------------------------Traveling Salesman Problem- | |
12 | ||
13 | def plot(city): # Plots 5x5 "points" on video screen | |
14 | x = city[1]+5; y = city[2]+5 # The +5 is to push away from the side bars. | |
15 | if city[0] == -1: | |
16 | kolor = 'WHITE' | |
17 | else: kolor = 'YELLOW' | |
18 | canvas.create_rectangle(x-2, y-2, x+2, y+2, width = 1, fill = kolor) | |
19 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
20 | ||
21 | def line(city1, city2, kolor = 'RED'): | |
22 | canvas.create_line(city1[1]+5, city1[2]+5, city2[1]+5, city2[2]+5, width = 1, fill = kolor) | |
23 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
24 | ||
25 | def displayDataInConsole(AlgorithmResults, baseCity, city): | |
26 | print('===<Traveling Salesman Path Statistics>===') | |
27 | print (' algorithm path length ') | |
28 | for element in AlgorithmResults: | |
29 | print ('---%-20s'%element[0], int(element[2])) | |
30 | city.sort() | |
31 | baseCity.sort() | |
32 | if city == baseCity: | |
33 | print("---Data verified as unchanged.") | |
34 | else: | |
35 | print ('ERROR: City data has been corrupted!') | |
36 | print(' Run time =', round(clock()-START_TIME, 2), ' seconds.') | |
37 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
38 | ||
39 | def printCity(city): # Used for debugging. | |
40 | count = 0 | |
41 | for (id,x,y) in city: | |
42 | print( '%3d: id =%2d, (%5d, %5d)'%(count,id, int(x), int(y))) | |
43 | count += 1 | |
44 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
45 | ||
46 | def displayPathOnScreen(city, statistics): | |
47 | #=---Normalize data | |
48 | (minX, maxX, minY, maxY, meanX, meanY, medianX, medianY, size, m, b) = statistics | |
49 | canvas.delete('all') | |
50 | cityNorm, (p,q,r,s) = normalizeCityDataToFitScreen(city[:], statistics) | |
51 | ||
52 | #---Plot points and lines | |
53 | cityNorm.append(cityNorm[0]) | |
54 | plot(cityNorm[0]) | |
55 | for n in range(1, len(cityNorm)): | |
56 | plot(cityNorm[n]) | |
57 | line(cityNorm[n], cityNorm[n-1]) | |
58 | script(650, 20, 'path length = ' + str(pathLength(city))) | |
59 | canvas.create_rectangle(530,10, 770, 30, width = 1, outline = 'WHITE') | |
60 | canvas.update() | |
61 | root.mainloop() # Required for graphics. | |
62 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
63 | ||
64 | def normalizeCityDataToFitScreen(city, statistics): | |
65 | """ Coordinates are all assumed to be non-negative.""" | |
66 | (minX, maxX, minY, maxY, meanX, meanY, medianX, medianY, size, m, b) = statistics | |
67 | newCity = [] | |
68 | ||
69 | #---Step 1a. Shift city points to the x- and y-axes. | |
70 | for (id, x,y) in city: | |
71 | newCity.append ( (id, x-minX, y-minY)) | |
72 | ||
73 | #---Step 1b. Shift line-of-best-fit to the x- and y-axes. | |
74 | (x0,y0) = (maxX-minX, m*maxX+b - minY) # = x-intercept of line-of-best-fit. | |
75 | (x1,y1) = (minX-minX, m*minX+b - minY) # = y-intercept of line-of-best-fit. | |
76 | ||
77 | ||
78 | #---Step 1c. Shift max-values to x- and y-axes. | |
79 | maxX = maxX-minX | |
80 | maxY = maxY-minY | |
81 | ||
82 | #---Step 2a. # Re-scale city points to fit the screen. | |
83 | cityNorm = [] | |
84 | for (id, x, y) in newCity: | |
85 | cityNorm.append ((id, x*SCREEN_WIDTH/maxX, y*SCREEN_HEIGHT/maxY)) | |
86 | ||
87 | #---Step 2b. # Re-scale the x-axis and y-axis intercepts for the line-of-best-fit. | |
88 | (x0,y0) = x0/maxX*SCREEN_WIDTH, y0/maxY*SCREEN_HEIGHT # a point on the x-axis | |
89 | (x1,y1) = x1/maxX*SCREEN_WIDTH, y1/maxY*SCREEN_HEIGHT # a point on the y-axis | |
90 | ||
91 | return cityNorm, (x1,y1,x0,y0) # = the adjusted city xy-values and 2 points on the line-of-best-fit. | |
92 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
93 | ||
94 | def readDataFromFileAndAppendId(fileName): | |
95 | file1 = open(fileName, 'r') | |
96 | fileLength = int(file1.readline()) # removes heading | |
97 | city = [] | |
98 | for elt in range(fileLength): | |
99 | x, y = file1.readline().split() | |
100 | city.append( [0, float(x), float(y)] ) # A place for an id (0, here) is appended. | |
101 | file1.close() | |
102 | return city | |
103 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
104 | ||
105 | def getFileLength(fileName): | |
106 | file1 = open(fileName, 'r') | |
107 | fileLength = int(file1.readline()) # removes heading | |
108 | return fileLength | |
109 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
110 | ||
111 | def pathLength(city): | |
112 | totalPath = 0 | |
113 | for n in range(1, len(city)): | |
114 | totalPath += dist( city[n-1], city[n] ) | |
115 | totalPath += dist( city[n], city[0] ) | |
116 | return int(totalPath) | |
117 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
118 | ||
119 | def dataStatistics(city): | |
120 | xValues = [] | |
121 | yValues = [] | |
122 | size = len(city) | |
123 | for (id, x,y) in city: | |
124 | xValues.append(x) | |
125 | yValues.append(y) | |
126 | minX = min(xValues) | |
127 | maxX = max(xValues) | |
128 | minY = min(yValues) | |
129 | maxY = max(yValues) | |
130 | ||
131 | assert (minX >= 0 or maxX >= 0 or minY >= 0 or maxY >= 0) | |
132 | ||
133 | meanX = sum(xValues)/size | |
134 | meanY = sum(yValues)/size | |
135 | medianX = city[len(city)//2][0] | |
136 | medianY = city[len(city)//2][1] | |
137 | ||
138 | #---Derive the line of best fit: y = mx+b | |
139 | xyDiff = 0 | |
140 | xDiffSqr = 0 | |
141 | for (id, x,y) in city: | |
142 | xyDiff += (meanX - x)*(meanY - y) | |
143 | xDiffSqr+= (meanX - x)**2 | |
144 | ||
145 | m = xyDiff/xDiffSqr | |
146 | b = meanY - m*meanX | |
147 | ||
148 | return minX, maxX, minY, maxY, meanX, meanY, medianX, medianY, size, m, b | |
149 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
150 | ||
151 | def dist(cityA, cityB): | |
152 | return hypot(cityA[1]-cityB[1], cityA[2] - cityB[2]) | |
153 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
154 | ||
155 | def chunks(l, n): | |
156 | n = max(1, n) | |
157 | l.pop() | |
158 | return [l[i:i + n] for i in range(0, len(l), n)] | |
159 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
160 | ||
161 | def printToFile(distances, myfile): | |
162 | for item in distances: | |
163 | myfile.write("%s\n" % item) | |
164 | myfile.write("\n") | |
165 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
166 | ||
167 | def myAlgorithm(distances,city,fileLength): | |
168 | for x in range(len(city)): | |
169 | for y in range(len(city)): | |
170 | if x+y+1<len(city): | |
171 | distances.append(dist(city[x],city[x+y+1])) | |
172 | elif city[x] !=city[(x+y)%(fileLength-1)]: | |
173 | distances.append(dist(city[x],city[(x+y)%(fileLength-1)])) | |
174 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
175 | ||
176 | def ySort(city): | |
177 | for item in city: | |
178 | item[1],item[2]=item[2],item[1] | |
179 | city.sort() | |
180 | for item in city: | |
181 | item[1],item[2]=item[2],item[1] | |
182 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
183 | ||
184 | def xSort(city): | |
185 | city.sort() | |
186 | #====================================<GLOBAL CONSTANTS and GLOBAL IMPORTS>========Traveling Salesman Problem== | |
187 | ||
188 | from tkinter import Tk, Canvas, YES, BOTH | |
189 | from operator import itemgetter | |
190 | from itertools import permutations | |
191 | from copy import deepcopy | |
192 | from random import shuffle | |
193 | from time import clock | |
194 | from math import hypot | |
195 | from operator import itemgetter | |
196 | from collections import OrderedDict | |
197 | root = Tk() | |
198 | canvas = setUpCanvas(root) | |
199 | START_TIME = clock() | |
200 | SCREEN_WIDTH = root.winfo_screenwidth() //5*5 - 15 # adjusted to exclude task bars on my PC. | |
201 | SCREEN_HEIGHT = root.winfo_screenheight()//5*5 - 90 # adjusted to exclude task bars on my PC. | |
202 | fileName = "tsp0038.txt" # My file name will be different from yours | |
203 | #==================================================< MAIN >=======================Traveling Salesman Problem== | |
204 | ||
205 | def main(): | |
206 | #---0. Read in data, append an id to every pair, and store results in a variable called "city". | |
207 | ||
208 | fileLength = getFileLength(fileName) | |
209 | city = readDataFromFileAndAppendId(fileName) | |
210 | ||
211 | #---1. Extract statistics. | |
212 | ||
213 | statistics = (minX, maxX, minY, maxY, meanX, meanY, medianX, medianY, size, m, b) = dataStatistics(city) | |
214 | ||
215 | #---2. Create a random path. | |
216 | ||
217 | shuffle(city) | |
218 | ||
219 | #---3. Sort on y-coordinate and connect sequentially by y. | |
220 | ||
221 | ySort(city) | |
222 | ||
223 | #---4. Sort on x-coordinate and connect sequentially by x. | |
224 | ||
225 | xSort(city) | |
226 | ||
227 | #---5. Greedy Algorithm | |
228 | - | #---5. Your algorithm(s). Can you do better than the sorting algorithms above? |
228 | + | |
229 | for x in range(len(city)-1): | |
230 | print(x) | |
231 | if x==0: | |
232 | z.append(city[x]) | |
233 | temp=dist(city[x],city[x+1]) | |
234 | for y in range(len(city)-1): | |
235 | if dist(city[x],city[y+1])<temp: | |
236 | z.append(city[y+1]) | |
237 | break | |
238 | city=z | |
239 | - | print(temp) |
239 | + | |
240 | - | print(len(z)) |
240 | + | |
241 | - | print(len(city)) |
241 | + | |
242 | #---------------------------------------------------------------------------------Traveling Salesman Problem-- | |
243 | if __name__ == '__main__': main() | |
244 | ###############################################<END OF PROGRAM>############################################### |