├── requirements.txt ├── report ├── report.pdf ├── slides.pdf ├── img │ ├── italy.png │ ├── uruguay.png │ └── finnish_som.png ├── slides.org └── report.org ├── diagrams └── uruguay.gif ├── src ├── distance.py ├── neuron.py ├── plot.py ├── io_helper.py └── main.py ├── README.org ├── LICENSE ├── .gitignore └── assets ├── qa194.tsp └── uy734.tsp /requirements.txt: -------------------------------------------------------------------------------- 1 | matplotlib==2.1.0 2 | pandas==0.20.3 3 | numpy==1.14.0 4 | -------------------------------------------------------------------------------- /report/report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCEChain/SOM/HEAD/report/report.pdf -------------------------------------------------------------------------------- /report/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCEChain/SOM/HEAD/report/slides.pdf -------------------------------------------------------------------------------- /diagrams/uruguay.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCEChain/SOM/HEAD/diagrams/uruguay.gif -------------------------------------------------------------------------------- /report/img/italy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCEChain/SOM/HEAD/report/img/italy.png -------------------------------------------------------------------------------- /report/img/uruguay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCEChain/SOM/HEAD/report/img/uruguay.png -------------------------------------------------------------------------------- /report/img/finnish_som.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCEChain/SOM/HEAD/report/img/finnish_som.png -------------------------------------------------------------------------------- /src/distance.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | def select_closest(candidates, origin): 4 | """Return the index of the closest candidate to a given point.""" 5 | return euclidean_distance(candidates, origin).argmin() 6 | 7 | def euclidean_distance(a, b): 8 | """Return the array of distances of two numpy arrays of points.""" 9 | return np.linalg.norm(a - b, axis=1) 10 | 11 | def route_distance(cities): 12 | """Return the cost of traversing a route of cities in a certain order.""" 13 | points = cities[['x', 'y']] 14 | distances = euclidean_distance(points, np.roll(points, 1, axis=0)) 15 | return np.sum(distances) 16 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Solving the Traveling Salesman Problem using Self-Organizing Maps 2 | #+AUTHOR: Diego Vicente Martín 3 | #+EMAIL: mail@diego.codes 4 | 5 | This repository contains an implementation of a Self Organizing Map that can be 6 | used to find sub-optimal solutions for the Traveling Salesman Problem. The 7 | 8 | 9 | #+BEGIN_SRC sh 10 | pip install requirements.txt 11 | #+END_SRC 12 | 13 | To run the code, simply execute: 14 | 15 | #+BEGIN_SRC sh 16 | cd som-tsp 17 | python src/main.py assets/.tsp 18 | #+END_SRC 19 | 20 | The images generated will be stored in the =diagrams= folder. Using a tool like 21 | =convert=, you can easily generate an animation like the one in this file by 22 | running: 23 | 24 | #+BEGIN_SRC sh 25 | convert -delay 10 -loop 0 *.png animation.gif 26 | #+END_SRC 27 | 28 | This code is licensed under MIT License, so feel free to modify and/or use it 29 | in your projects. If you have any doubts, feel free to contact me or contribute 30 | to this repository by creating an issue. 31 | 32 | ----- 33 | 34 | 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Diego Vicente 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/neuron.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from distance import select_closest 4 | 5 | def generate_network(size): 6 | """ 7 | Generate a neuron network of a given size. 8 | 9 | Return a vector of two dimensional points in the interval [0,1]. 10 | """ 11 | return np.random.rand(size, 2) 12 | 13 | def get_neighborhood(center, radix, domain): 14 | """Get the range gaussian of given radix around a center index.""" 15 | 16 | # Impose an upper bound on the radix to prevent NaN and blocks 17 | if radix < 1: 18 | radix = 1 19 | 20 | # Compute the circular network distance to the center 21 | deltas = np.absolute(center - np.arange(domain)) 22 | distances = np.minimum(deltas, domain - deltas) 23 | 24 | # Compute Gaussian distribution around the given center 25 | return np.exp(-(distances*distances) / (2*(radix*radix))) 26 | 27 | def get_route(cities, network): 28 | """Return the route computed by a network.""" 29 | cities['winner'] = cities[['x', 'y']].apply( 30 | lambda c: select_closest(network, c), 31 | axis=1, raw=True) 32 | 33 | return cities.sort_values('winner').index 34 | -------------------------------------------------------------------------------- /src/plot.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import matplotlib as mpl 3 | 4 | def plot_network(cities, neurons, name='diagram.png', ax=None): 5 | """Plot a graphical representation of the problem""" 6 | mpl.rcParams['agg.path.chunksize'] = 10000 7 | 8 | if not ax: 9 | fig = plt.figure(figsize=(5, 5), frameon = False) 10 | axis = fig.add_axes([0,0,1,1]) 11 | 12 | axis.set_aspect('equal', adjustable='datalim') 13 | plt.axis('off') 14 | 15 | axis.scatter(cities['x'], cities['y'], color='red', s=4) 16 | axis.plot(neurons[:,0], neurons[:,1], 'r.', ls='-', color='#0063ba', markersize=2) 17 | 18 | plt.savefig(name, bbox_inches='tight', pad_inches=0, dpi=200) 19 | plt.close() 20 | 21 | else: 22 | ax.scatter(cities['x'], cities['y'], color='red', s=4) 23 | ax.plot(neurons[:,0], neurons[:,1], 'r.', ls='-', color='#0063ba', markersize=2) 24 | return ax 25 | 26 | def plot_route(cities, route, name='diagram.png', ax=None): 27 | """Plot a graphical representation of the route obtained""" 28 | mpl.rcParams['agg.path.chunksize'] = 10000 29 | 30 | if not ax: 31 | fig = plt.figure(figsize=(5, 5), frameon = False) 32 | axis = fig.add_axes([0,0,1,1]) 33 | 34 | axis.set_aspect('equal', adjustable='datalim') 35 | plt.axis('off') 36 | 37 | axis.scatter(cities['x'], cities['y'], color='red', s=4) 38 | route = cities.reindex(route) 39 | route.loc[route.shape[0]] = route.iloc[0] 40 | axis.plot(route['x'], route['y'], color='purple', linewidth=1) 41 | 42 | plt.savefig(name, bbox_inches='tight', pad_inches=0, dpi=200) 43 | plt.close() 44 | 45 | else: 46 | ax.scatter(cities['x'], cities['y'], color='red', s=4) 47 | route = cities.reindex(route) 48 | route.loc[route.shape[0]] = route.iloc[0] 49 | ax.plot(route['x'], route['y'], color='purple', linewidth=1) 50 | return ax 51 | -------------------------------------------------------------------------------- /src/io_helper.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | def read_tsp(filename): 5 | """ 6 | Read a file in .tsp format into a pandas DataFrame 7 | 8 | The .tsp files can be found in the TSPLIB project. Currently, the library 9 | only considers the possibility of a 2D map. 10 | """ 11 | with open(filename) as f: 12 | node_coord_start = None 13 | dimension = None 14 | lines = f.readlines() 15 | 16 | # Obtain the information about the .tsp 17 | i = 0 18 | while not dimension or not node_coord_start: 19 | line = lines[i] 20 | if line.startswith('DIMENSION :'): 21 | dimension = int(line.split()[-1]) 22 | if line.startswith('NODE_COORD_SECTION'): 23 | node_coord_start = i 24 | i = i+1 25 | 26 | print('Problem with {} cities read.'.format(dimension)) 27 | 28 | f.seek(0) 29 | 30 | # Read a data frame out of the file descriptor 31 | cities = pd.read_csv( 32 | f, 33 | skiprows=node_coord_start + 1, 34 | sep=' ', 35 | names=['city', 'y', 'x'], 36 | dtype={'city': str, 'x': np.float64, 'y': np.float64}, 37 | header=None, 38 | nrows=dimension 39 | ) 40 | 41 | # cities.set_index('city', inplace=True) 42 | 43 | return cities 44 | 45 | def normalize(points): 46 | """ 47 | Return the normalized version of a given vector of points. 48 | 49 | For a given array of n-dimensions, normalize each dimension by removing the 50 | initial offset and normalizing the points in a proportional interval: [0,1] 51 | on y, maintining the original ratio on x. 52 | """ 53 | ratio = (points.x.max() - points.x.min()) / (points.y.max() - points.y.min()), 1 54 | ratio = np.array(ratio) / max(ratio) 55 | norm = points.apply(lambda c: (c - c.min()) / (c.max() - c.min())) 56 | return norm.apply(lambda p: ratio * p, axis=1) 57 | -------------------------------------------------------------------------------- /src/main.py: -------------------------------------------------------------------------------- 1 | from sys import argv 2 | 3 | import numpy as np 4 | 5 | from io_helper import read_tsp, normalize 6 | from neuron import generate_network, get_neighborhood, get_route 7 | from distance import select_closest, euclidean_distance, route_distance 8 | from plot import plot_network, plot_route 9 | 10 | def main(): 11 | if len(argv) != 2: 12 | print("Correct use: python src/main.py .tsp") 13 | return -1 14 | 15 | problem = read_tsp(argv[1]) 16 | 17 | route = som(problem, 100000) 18 | 19 | problem = problem.reindex(route) 20 | 21 | distance = route_distance(problem) 22 | 23 | print('Route found of length {}'.format(distance)) 24 | 25 | 26 | def som(problem, iterations, learning_rate=0.8): 27 | """Solve the TSP using a Self-Organizing Map.""" 28 | 29 | # Obtain the normalized set of cities (w/ coord in [0,1]) 30 | cities = problem.copy() 31 | 32 | cities[['x', 'y']] = normalize(cities[['x', 'y']]) 33 | 34 | # The population size is 8 times the number of cities 35 | n = cities.shape[0] * 8 36 | 37 | # Generate an adequate network of neurons: 38 | network = generate_network(n) 39 | print('Network of {} neurons created. Starting the iterations:'.format(n)) 40 | 41 | for i in range(iterations): 42 | if not i % 100: 43 | print('\t> Iteration {}/{}'.format(i, iterations), end="\r") 44 | # Choose a random city 45 | city = cities.sample(1)[['x', 'y']].values 46 | winner_idx = select_closest(network, city) 47 | # Generate a filter that applies changes to the winner's gaussian 48 | gaussian = get_neighborhood(winner_idx, n//10, network.shape[0]) 49 | # Update the network's weights (closer to the city) 50 | network += gaussian[:,np.newaxis] * learning_rate * (city - network) 51 | # Decay the variables 52 | learning_rate = learning_rate * 0.99997 53 | n = n * 0.9997 54 | 55 | # Check for plotting interval 56 | if not i % 1000: 57 | plot_network(cities, network, name='diagrams/{:05d}.png'.format(i)) 58 | 59 | # Check if any parameter has completely decayed. 60 | if n < 1: 61 | print('Radius has completely decayed, finishing execution', 62 | 'at {} iterations'.format(i)) 63 | break 64 | if learning_rate < 0.001: 65 | print('Learning rate has completely decayed, finishing execution', 66 | 'at {} iterations'.format(i)) 67 | break 68 | else: 69 | print('Completed {} iterations.'.format(iterations)) 70 | 71 | plot_network(cities, network, name='diagrams/final.png') 72 | 73 | route = get_route(cities, network) 74 | plot_route(cities, route, 'diagrams/route.png') 75 | return route 76 | 77 | if __name__ == '__main__': 78 | main() 79 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/macos,emacs,python 3 | 4 | ### Emacs ### 5 | # -*- mode: gitignore; -*- 6 | *~ 7 | \#*\# 8 | /.emacs.desktop 9 | /.emacs.desktop.lock 10 | *.elc 11 | auto-save-list 12 | tramp 13 | .\#* 14 | 15 | # Org-mode 16 | .org-id-locations 17 | *_archive 18 | 19 | # flymake-mode 20 | *_flymake.* 21 | 22 | # eshell files 23 | /eshell/history 24 | /eshell/lastdir 25 | 26 | # elpa packages 27 | /elpa/ 28 | 29 | # reftex files 30 | *.rel 31 | 32 | # AUCTeX auto folder 33 | /auto/ 34 | 35 | # cask packages 36 | .cask/ 37 | dist/ 38 | 39 | # Flycheck 40 | flycheck_*.el 41 | 42 | # server auth directory 43 | /server/ 44 | 45 | # projectiles files 46 | .projectile 47 | projectile-bookmarks.eld 48 | 49 | # directory configuration 50 | .dir-locals.el 51 | 52 | # saveplace 53 | places 54 | 55 | # url cache 56 | url/cache/ 57 | 58 | # cedet 59 | ede-projects.el 60 | 61 | # smex 62 | smex-items 63 | 64 | # company-statistics 65 | company-statistics-cache.el 66 | 67 | # anaconda-mode 68 | anaconda-mode/ 69 | 70 | ### macOS ### 71 | *.DS_Store 72 | .AppleDouble 73 | .LSOverride 74 | 75 | # Icon must end with two \r 76 | Icon 77 | 78 | # Thumbnails 79 | ._* 80 | 81 | # Files that might appear in the root of a volume 82 | .DocumentRevisions-V100 83 | .fseventsd 84 | .Spotlight-V100 85 | .TemporaryItems 86 | .Trashes 87 | .VolumeIcon.icns 88 | .com.apple.timemachine.donotpresent 89 | 90 | # Directories potentially created on remote AFP share 91 | .AppleDB 92 | .AppleDesktop 93 | Network Trash Folder 94 | Temporary Items 95 | .apdisk 96 | 97 | ### Python ### 98 | # Byte-compiled / optimized / DLL files 99 | __pycache__/ 100 | *.py[cod] 101 | *$py.class 102 | 103 | # C extensions 104 | *.so 105 | 106 | # Distribution / packaging 107 | .Python 108 | build/ 109 | develop-eggs/ 110 | downloads/ 111 | eggs/ 112 | .eggs/ 113 | lib/ 114 | lib64/ 115 | parts/ 116 | sdist/ 117 | var/ 118 | wheels/ 119 | *.egg-info/ 120 | .installed.cfg 121 | *.egg 122 | 123 | # PyInstaller 124 | # Usually these files are written by a python script from a template 125 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 126 | *.manifest 127 | *.spec 128 | 129 | # Installer logs 130 | pip-log.txt 131 | pip-delete-this-directory.txt 132 | 133 | # Unit test / coverage reports 134 | htmlcov/ 135 | .tox/ 136 | .coverage 137 | .coverage.* 138 | .cache 139 | nosetests.xml 140 | coverage.xml 141 | *.cover 142 | .hypothesis/ 143 | 144 | # Translations 145 | *.mo 146 | *.pot 147 | 148 | # Django stuff: 149 | *.log 150 | local_settings.py 151 | 152 | # Flask stuff: 153 | instance/ 154 | .webassets-cache 155 | 156 | # Scrapy stuff: 157 | .scrapy 158 | 159 | # Sphinx documentation 160 | docs/_build/ 161 | 162 | # PyBuilder 163 | target/ 164 | 165 | # Jupyter Notebook 166 | .ipynb_checkpoints 167 | 168 | # pyenv 169 | .python-version 170 | 171 | # celery beat schedule file 172 | celerybeat-schedule 173 | 174 | # SageMath parsed files 175 | *.sage.py 176 | 177 | # Environments 178 | .env 179 | .venv 180 | env/ 181 | venv/ 182 | ENV/ 183 | env.bak/ 184 | venv.bak/ 185 | 186 | # Spyder project settings 187 | .spyderproject 188 | .spyproject 189 | 190 | # Rope project settings 191 | .ropeproject 192 | 193 | # mkdocs documentation 194 | /site 195 | 196 | # mypy 197 | .mypy_cache/ 198 | 199 | # End of https://www.gitignore.io/api/macos,emacs,python 200 | -------------------------------------------------------------------------------- /report/slides.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Self-Organizing Maps para resolver Traveling Salesman Problem 2 | #+AUTHOR: Diego Vicente Martín (=100317150@alumnos.uc3m.es=) 3 | #+EMAIL: 100317150@alumnos.uc3m.es 4 | #+DATE: 15 de enero, 2018 5 | #+STARTUP: beamer 6 | #+OPTIONS: H:2 7 | #+LaTeX_CLASS: beamer 8 | #+BEAMER_FRAME_LEVEL: 2 9 | #+LANGUAGE: es 10 | #+LaTeX_HEADER: \usepackage[export]{adjustbox}[2011/08/13] 11 | #+LaTeX_HEADER: \usepackage[spanish]{babel} 12 | 13 | * Resumen del artículo original 14 | 15 | ** Introducción 16 | 17 | - *Self-organizing maps*: estudiados por cite:kohonen-1998-maps 18 | - Técnica de organización y visualización inspirada en ANNs. 19 | - Simula un modelo dado a través de una regresión en una red. 20 | - Se /auto-organiza/ para poner cerca entre sí nodos que representan partes 21 | similares. 22 | 23 | #+ATTR_LATEX: :width 0.8\textwidth 24 | [[./img/finnish_som.png]] 25 | 26 | ** Regresión al modelo 27 | 28 | - Las neuronas del SOM se organizan espacialmente para juntar nodos similares. 29 | - La regresión se realiza elemento por elemento del modelo: 30 | 31 | \[ 32 | n_{t+1} = n_{t} + h(w_{e}) \cdot \Delta(e, n_{t}) 33 | \] 34 | 35 | - \(n_{i}\) :: neurona en el momento \(i\). 36 | - \(w_{e}\) :: neurona ganadora del elemento. 37 | - \(h(n)\) :: factor de vecindario de una neurona \(n\). 38 | - \(\Delta(x, y)\) :: vector de distancia entre \(x\) e \(y\) 39 | 40 | ** Definiendo conceptos 41 | 42 | - La elección del *ganador* se define por similitud: 43 | - El ejemplo más cercano usando la distancia euclídea. 44 | - Las dos distribuciones con mayor correlación. 45 | - Elemento de mayor heurística. 46 | 47 | - El vecindario actúa como un filtro de convolución. 48 | - Un filtro de suavizado (normalmente Gaussiano). 49 | - Se encarga de actualizar zonas concretas del mapa. 50 | 51 | ** Otras cosas a tener en cuenta 52 | 53 | - La conectividad de la red puede cambiar 54 | - No solo una red rectangular, sino hexagonal, octogonal... 55 | 56 | - El modelo no siempre converge si los parámetros no son correctos. 57 | 58 | - Si se usa como un LVQ, se pueden aplicar regiones de Voronoi. 59 | 60 | * Modificando SOM para resolver TSP 61 | 62 | ** Usando SOM para resolver TSP 63 | 64 | - Si usamos una conectividad 2 (1D) en el mapa, la red es un anillo. 65 | - Las neuronas intentarán reducir la distancia con su sucesor y predecesor. 66 | - Aún así, se aplicará una regresión al modelo. 67 | 68 | - Usando un mapa para resolver un TSP en 2D: 69 | - Similitud: distancia euclídea. 70 | - Conectividad de una dimensión (circular). 71 | - Vecindario: filtro Gaussiano de 1D. 72 | 73 | ** Otras modificaciones 74 | 75 | - El mapa no siempre converge, hace falta una forma de equilibrar la 76 | exploración y la explotación del modelo. 77 | - Solución: introducción factor de aprendizaje (\alpha) y descuentos en el factor de 78 | aprendizaje y el tamaño del vecindario. 79 | - Reducir el factor de aprendizaje permite forzar la convergencia. 80 | - Reducir el vecindario fuerza la exploración primero para luego explotar 81 | zonas más locales. 82 | 83 | \[ 84 | n_{t+1} = n_{t} + \alpha_{t} \cdot g(w_{e}, h_{t}) \cdot \Delta(e, n_{t}) 85 | \] 86 | 87 | 88 | \[ 89 | \alpha_{t+1} = \gamma_{\alpha} \cdot \alpha_{t} , \ \ h_{t+1} = \gamma_{h} \cdot h_{t} 90 | \] 91 | 92 | * Implementación y evaluación 93 | 94 | ** Implementación 95 | 96 | - Python 3 y =numpy= para la vectorización de operaciones en el mapa. 97 | - Parámetros configurables, valores elegidos por defecto basados en 98 | cite:brocki-2010-somtsp: 99 | - Tamaño de la red: 8 veces el número de ciudades. 100 | - \alpha = 0.8, \gamma_{\alpha} = 0.99997 101 | - h = número de ciudades, \gamma_{h}= 0.9997 102 | 103 | ** Evaluación 104 | 105 | - Métricas: 106 | - Calidad de la solución en función de la óptima. 107 | - Tiempo consumido hasta devolver una solución. 108 | 109 | ** Resultados 110 | 111 | - Pruebas del mapa en 3 países: 112 | - Qatar, con 194 ciudades. 113 | - Uruguay, con 734 ciudades. 114 | - Filandia, con 10639 ciudades. 115 | - Italia, con 16862 ciudades. 116 | 117 | | Instancia | Iteraciones | Tiempo (s) | Longitud | Calidad | 118 | |-----------+-------------+------------+-----------+---------| 119 | | Qatar | 14690 | 14.3 | 10233.89 | 9.4% | 120 | | Uruguay | 17351 | 23.4 | 85072.35 | 7.5% | 121 | | Finlandia | 37833 | 284.0 | 636580.27 | 22.3% | 122 | | Italia | 39368 | 401.1 | 723212.87 | 29.7% | 123 | 124 | ** Visualización: Uruguay 125 | 126 | #+ATTR_LATEX: :width 1.2\textwidth,center 127 | [[./img/uruguay.png]] 128 | 129 | 130 | ** Visualización: Italia 131 | 132 | #+ATTR_LATEX: :width 1.2\textwidth,center 133 | [[./img/italy.png]] 134 | 135 | * Conclusiones 136 | 137 | ** Conclusiones 138 | 139 | - SOM es una técnica muy interesante que ofrece buenos resultados 140 | - Potente herramiento para la visualización 141 | - Aplicar SOM al TSP resulta en una técnica muy sensible a los parámetros. 142 | - Es posible encontrar una ruta subóptima en menos de 25 segundos para más de 143 | 700 ciudades. 144 | 145 | ** Referencias 146 | 147 | bibliography:~/Dropbox/org/bibliography/main.bib 148 | bibliographystyle:apalike 149 | -------------------------------------------------------------------------------- /assets/qa194.tsp: -------------------------------------------------------------------------------- 1 | NAME : qa194 2 | COMMENT : 194 locations in Qatar 3 | COMMENT : Derived from National Imagery and Mapping Agency data 4 | TYPE : TSP 5 | DIMENSION : 194 6 | EDGE_WEIGHT_TYPE : EUC_2D 7 | NODE_COORD_SECTION 8 | 1 24748.3333 50840.0000 9 | 2 24758.8889 51211.9444 10 | 3 24827.2222 51394.7222 11 | 4 24904.4444 51175.0000 12 | 5 24996.1111 51548.8889 13 | 6 25010.0000 51039.4444 14 | 7 25030.8333 51275.2778 15 | 8 25067.7778 51077.5000 16 | 9 25100.0000 51516.6667 17 | 10 25103.3333 51521.6667 18 | 11 25121.9444 51218.3333 19 | 12 25150.8333 51537.7778 20 | 13 25158.3333 51163.6111 21 | 14 25162.2222 51220.8333 22 | 15 25167.7778 51606.9444 23 | 16 25168.8889 51086.3889 24 | 17 25173.8889 51269.4444 25 | 18 25210.8333 51394.1667 26 | 19 25211.3889 51619.1667 27 | 20 25214.1667 50807.2222 28 | 21 25214.4444 51378.8889 29 | 22 25223.3333 51451.6667 30 | 23 25224.1667 51174.4444 31 | 24 25233.3333 51333.3333 32 | 25 25234.1667 51203.0556 33 | 26 25235.5556 51330.0000 34 | 27 25235.5556 51495.5556 35 | 28 25242.7778 51428.8889 36 | 29 25243.0556 51452.5000 37 | 30 25252.5000 51559.1667 38 | 31 25253.8889 51535.2778 39 | 32 25253.8889 51549.7222 40 | 33 25256.9444 51398.8889 41 | 34 25263.6111 51516.3889 42 | 35 25265.8333 51545.2778 43 | 36 25266.6667 50969.1667 44 | 37 25266.6667 51483.3333 45 | 38 25270.5556 51532.7778 46 | 39 25270.8333 51505.8333 47 | 40 25270.8333 51523.0556 48 | 41 25275.8333 51533.6111 49 | 42 25277.2222 51547.7778 50 | 43 25278.3333 51525.5556 51 | 44 25278.3333 51541.3889 52 | 45 25279.1667 51445.5556 53 | 46 25281.1111 51535.0000 54 | 47 25281.3889 51512.5000 55 | 48 25283.3333 51533.3333 56 | 49 25283.6111 51546.6667 57 | 50 25284.7222 51555.2778 58 | 51 25286.1111 51504.1667 59 | 52 25286.1111 51534.1667 60 | 53 25286.6667 51533.3333 61 | 54 25287.5000 51537.7778 62 | 55 25288.0556 51546.6667 63 | 56 25290.8333 51528.3333 64 | 57 25291.9444 51424.4444 65 | 58 25292.5000 51520.8333 66 | 59 25298.6111 51001.6667 67 | 60 25300.8333 51394.4444 68 | 61 25306.9444 51507.7778 69 | 62 25311.9444 51003.0556 70 | 63 25313.8889 50883.3333 71 | 64 25315.2778 51438.6111 72 | 65 25316.6667 50766.6667 73 | 66 25320.5556 51495.5556 74 | 67 25322.5000 51507.7778 75 | 68 25325.2778 51470.0000 76 | 69 25326.6667 51350.2778 77 | 70 25337.5000 51425.0000 78 | 71 25339.1667 51173.3333 79 | 72 25340.5556 51293.6111 80 | 73 25341.9444 51507.5000 81 | 74 25358.8889 51333.6111 82 | 75 25363.6111 51281.1111 83 | 76 25368.6111 51226.3889 84 | 77 25374.4444 51436.6667 85 | 78 25377.7778 51294.7222 86 | 79 25396.9444 51422.5000 87 | 80 25400.0000 51183.3333 88 | 81 25400.0000 51425.0000 89 | 82 25404.7222 51073.0556 90 | 83 25416.9444 51403.8889 91 | 84 25416.9444 51457.7778 92 | 85 25419.4444 50793.6111 93 | 86 25429.7222 50785.8333 94 | 87 25433.3333 51220.0000 95 | 88 25440.8333 51378.0556 96 | 89 25444.4444 50958.3333 97 | 90 25451.3889 50925.0000 98 | 91 25459.1667 51316.6667 99 | 92 25469.7222 51397.5000 100 | 93 25478.0556 51362.5000 101 | 94 25480.5556 50938.8889 102 | 95 25483.3333 51383.3333 103 | 96 25490.5556 51373.6111 104 | 97 25492.2222 51400.2778 105 | 98 25495.0000 50846.6667 106 | 99 25495.0000 50965.2778 107 | 100 25497.5000 51485.2778 108 | 101 25500.8333 50980.5556 109 | 102 25510.5556 51242.2222 110 | 103 25531.9444 51304.4444 111 | 104 25533.3333 50977.2222 112 | 105 25538.8889 51408.3333 113 | 106 25545.8333 51387.5000 114 | 107 25549.7222 51431.9444 115 | 108 25550.0000 51433.3333 116 | 109 25560.2778 51158.6111 117 | 110 25566.9444 51484.7222 118 | 111 25567.5000 50958.8889 119 | 112 25574.7222 51486.3889 120 | 113 25585.5556 51151.3889 121 | 114 25609.4444 51092.2222 122 | 115 25610.2778 51475.2778 123 | 116 25622.5000 51454.4444 124 | 117 25645.8333 51450.0000 125 | 118 25650.0000 51372.2222 126 | 119 25666.9444 51174.4444 127 | 120 25683.8889 51505.8333 128 | 121 25686.3889 51468.8889 129 | 122 25696.1111 51260.8333 130 | 123 25700.8333 51584.7222 131 | 124 25708.3333 51591.6667 132 | 125 25716.6667 51050.0000 133 | 126 25717.5000 51057.7778 134 | 127 25723.0556 51004.1667 135 | 128 25734.7222 51547.5000 136 | 129 25751.1111 51449.1667 137 | 130 25751.9444 50920.8333 138 | 131 25758.3333 51395.8333 139 | 132 25765.2778 51019.7222 140 | 133 25772.2222 51483.3333 141 | 134 25775.8333 51023.0556 142 | 135 25779.1667 51449.7222 143 | 136 25793.3333 51409.4444 144 | 137 25808.3333 51060.5556 145 | 138 25816.6667 51133.3333 146 | 139 25823.6111 51152.5000 147 | 140 25826.6667 51043.8889 148 | 141 25829.7222 51245.2778 149 | 142 25833.3333 51072.2222 150 | 143 25839.1667 51465.2778 151 | 144 25847.7778 51205.8333 152 | 145 25850.0000 51033.3333 153 | 146 25856.6667 51083.3333 154 | 147 25857.5000 51298.8889 155 | 148 25857.5000 51441.3889 156 | 149 25866.6667 51066.6667 157 | 150 25867.7778 51205.5556 158 | 151 25871.9444 51354.7222 159 | 152 25872.5000 51258.3333 160 | 153 25880.8333 51221.3889 161 | 154 25883.0556 51185.2778 162 | 155 25888.0556 51386.3889 163 | 156 25900.0000 51000.0000 164 | 157 25904.1667 51201.6667 165 | 158 25928.3333 51337.5000 166 | 159 25937.5000 51313.3333 167 | 160 25944.7222 51456.3889 168 | 161 25950.0000 51066.6667 169 | 162 25951.6667 51349.7222 170 | 163 25957.7778 51075.2778 171 | 164 25958.3333 51099.4444 172 | 165 25966.6667 51283.3333 173 | 166 25983.3333 51400.0000 174 | 167 25983.6111 51328.0556 175 | 168 26000.2778 51294.4444 176 | 169 26008.6111 51083.6111 177 | 170 26016.6667 51333.3333 178 | 171 26021.6667 51366.9444 179 | 172 26033.3333 51116.6667 180 | 173 26033.3333 51166.6667 181 | 174 26033.6111 51163.8889 182 | 175 26033.6111 51200.2778 183 | 176 26048.8889 51056.9444 184 | 177 26050.0000 51250.0000 185 | 178 26050.2778 51297.5000 186 | 179 26050.5556 51135.8333 187 | 180 26055.0000 51316.1111 188 | 181 26067.2222 51258.6111 189 | 182 26074.7222 51083.6111 190 | 183 26076.6667 51166.9444 191 | 184 26077.2222 51222.2222 192 | 185 26078.0556 51361.6667 193 | 186 26083.6111 51147.2222 194 | 187 26099.7222 51161.1111 195 | 188 26108.0556 51244.7222 196 | 189 26116.6667 51216.6667 197 | 190 26123.6111 51169.1667 198 | 191 26123.6111 51222.7778 199 | 192 26133.3333 51216.6667 200 | 193 26133.3333 51300.0000 201 | 194 26150.2778 51108.0556 202 | EOF 203 | -------------------------------------------------------------------------------- /report/report.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Self-Organizing Maps for solving the Traveling Salesman Problem 2 | #+AUTHOR: Diego Vicente Martín (=100317150@alumnos.uc3m.es=) 3 | #+EMAIL: 100317150@alumnos.uc3m.es 4 | #+LaTeX_CLASS: article 5 | #+LaTeX_CLASS_OPTIONS: [10pt] 6 | #+LaTeX_HEADER: \usepackage[export]{adjustbox}[2011/08/13] 7 | #+LATEX_HEADER: \setlength{\parskip}{\baselineskip} 8 | #+LATEX_HEADER: \usepackage{enumitem} 9 | #+LATEX_HEADER: \setlist[itemize]{noitemsep, 10 | #+LATEX_HEADER: topsep=0pt, before={\vspace*{-0.7\baselineskip}}} 11 | #+LATEX_HEADER: \usepackage{amsmath} 12 | 13 | #+OPTIONS: toc:nil date:nil H:2 14 | 15 | #+BEGIN_abstract 16 | Self-organizing maps (also known as Kohonen maps after its creator, Teuvo 17 | Kohonen) are an representation technique based on abstracting the data in a 18 | grid representation in order to obtain a low-dimensional version of the 19 | geometric relations in between. Using this technique, we are able to apply some 20 | slight modifications to the grid in order to solve the Traveling Salesman 21 | Problem and find sub-optimal solutions for it. In this report, there is an 22 | introduction to the concepts of the problem and the techniques used, as well as 23 | an evaluation of the Python representation. 24 | #+END_abstract 25 | 26 | * Summary of the original paper 27 | 28 | The original paper released by Teuvo Kohonen in 1998 cite:kohonen-1998-maps 29 | consists on a brief, masterful description of the technique. In there, it is 30 | explained that a /self-organizing map/ is described as an (usually 31 | two-dimensional) grid of nodes, inspired in a neural network. Closely related 32 | to the map, is the idea of the /model/, that is, the real world observation the 33 | map is trying to represent. The purpose of the technique is to represent the 34 | model with a lower number of dimensions, while maintaining the relations of 35 | similarity of the nodes contained in it. 36 | 37 | To capture this similarity, the nodes in the map are spatially organized to be 38 | closer the more similar they are with each other. For that reason, SOM are a 39 | great way for pattern visualization and organization of data. To obtain this 40 | structure, the map is applied a regression operation to modify the nodes 41 | position in order update the nodes, one element from the model (\(e\)) at a 42 | time. The expression used for the regression is: 43 | 44 | \[ 45 | n_{t+1} = n_{t} + h(w_{e}) \cdot \Delta(e, n_{t}) 46 | \] 47 | 48 | This implies that the position of the node \(n\) is updated adding the distance 49 | from it to the given element, multiplied by the neighborhood factor of the 50 | winner neuron, \(w_{e}\). The /winner/ of an element is the more similar node in 51 | the map to it, usually measured by the closer node using the Euclidean distance 52 | (although it is possible to use a different similarity measure if appropriate). 53 | 54 | On the other side, the /neighborhood/ is defined as a convolution-like kernel 55 | for the map around the winner. Doing this, we are able to update the winner and 56 | the neurons nearby closer to the element, obtaining a soft and proportional 57 | result. The function is usually defined as a Gaussian distribution, but other 58 | implementations are as well. One worth mentioning is a bubble neighborhood, 59 | that updates the neurons that are within a radius of the winner (based on a 60 | discrete Kronecker delta function). 61 | 62 | After this presentation to the technique, the paper suggest several nuances for 63 | the implementation that can be useful: using eigenvectors as initialization 64 | positions for the model instead of random, using Voronoi regions to speed up 65 | the computation of neighborhoods, and how to apply learning vector quantization 66 | for discrete classes in the sample vector. Finally, the last remark is the 67 | suggestion of using a hexagonal grid when using SOM to create a similarity 68 | graph or visualization. 69 | 70 | * Using SOM to solve the Traveling Salesman Problem 71 | 72 | The Traveling Salesman Problem (TSP) is an NP-Complete problem consisting of 73 | finding the shortest (or, in case of having defined costs, the cheapest) route 74 | that traverses all the cities given in a problem exactly once, with or without 75 | coming back to the initial point cite:hoffman-2013-tsp. 76 | 77 | In this work, the solution proposed uses some slight modifications on the 78 | concept of self-organizing maps to use them as a tool to solve the problem. 79 | Most of the modifications are inspired by cite:angeniol-1988-somtsp and some of 80 | the parametrization techniques are studied in cite:brocki-2010-somtsp. 81 | 82 | ** Modifying the algorithm 83 | 84 | To use the network to solve the TSP, there main concept to understand is how to 85 | modify the neighborhood function. If instead of a grid we declare a /circular 86 | array of neurons/, each node will only be conscious of the neurons in front of 87 | it and behind. That is, the similarity will work just in one dimension. Making 88 | this slight modification, the self-organizing map will behave as an elastic 89 | ring, getting closer to the cities but trying to minimize the perimeter of it 90 | thanks to the neighborhood function. 91 | 92 | Although this modification is the main idea behind the technique, it will not 93 | work as is: the algorithm will hardly converge any of the times. To ensure the 94 | convergence of it, we can include a learning rate, \alpha, to control the 95 | exploration and exploitation of the algorithm. To obtain high exploration 96 | first, and high exploitation after that in the execution, we must include 97 | /decay/ in both the neighborhood function and the learning rate. Decaying the 98 | learning rate will ensure less aggressive displacement of the neurons around 99 | the model, and decaying the neighborhood will result in a more moderate 100 | exploitation of the local minima of each part of the model. Then, our 101 | regression can be expressed as: 102 | 103 | \[ 104 | n_{t+1} = n_{t} + \alpha_{t} \cdot g(w_{e}, h_{t}) \cdot \Delta(e, n_{t}) 105 | \] 106 | 107 | Where \alpha is the learning rate at a given time, and \(g\) is the Gaussian 108 | function centered in a winner and with a neighborhood dispersion of \(h\). The 109 | decay function consists on simply multiplying the two given discounts, \gamma, for 110 | the learning rate and the neighborhood distance. 111 | 112 | \[ 113 | \alpha_{t+1} = \gamma_{\alpha} \cdot \alpha_{t} , \ \ h_{t+1} = \gamma_{h} \cdot h_{t} 114 | \] 115 | 116 | This expression is indeed quite similar to that of Q-Learning, and the 117 | convergence is search in a similar fashion to this technique. Decaying the 118 | parameters can be useful in unsupervised learning tasks like the aforementioned 119 | ones. 120 | 121 | Finally, to obtain the route from the SOM, it is only necessary to associate a 122 | city with its winner neuron, traverse the ring starting from any point and sort 123 | the cities by order of appearance of their winner neuron in the ring. As it is 124 | stated in cite:brocki-2010-somtsp, if several cities map to the same neuron, it 125 | is because the order of traversing such cities have not been contemplated by 126 | the SOM (due to lack of relevance for the final distance or because of not 127 | enough precision). In that case, any possible ordered can be considered for 128 | such cities. 129 | 130 | ** Implementation 131 | 132 | For the task, an implementation of the previously explained technique is 133 | provided in Python 3. It is able to parse and load any 2D instance problem 134 | modelled as a =TSPLIB= file and run the regression to obtain the shortest 135 | route. This format is chosen because for the testing and evaluation of the 136 | solution the problems in the National Traveling Salesman Problem instances 137 | offered by the University of Waterloo. 138 | 139 | All the functionalities of the implementation are collected in several files 140 | included in the =src= directory: 141 | - =distance.py=: contains the 2-Dimensional (Euclidean) distance functions, 142 | as well as other related functions for computing and evaluating distances. 143 | - =io_helper.py=: functions to open =.tsp= files and load them into valid 144 | runtime objects. 145 | - =main.py=: includes the general execution control of the self-organizing map. 146 | - =neuron.py=: includes all the network generation, neighborhood computation 147 | and route computation functions. 148 | - =plot.py=: some functions to generate graphical representations of different 149 | snapshots during and after the execution. 150 | 151 | On a lower level, the =numpy= package was used for the computations, which 152 | enables vectorization of the computations and higher performance in the 153 | execution, as well as more expressive and concise code. =pandas= is used for 154 | loading the =.tsp= files to memory easily, and =matplotlib= is used to plot the 155 | graphical representation. These dependencies are all included in the Anaconda 156 | distribution of Python, or can be easily installed using =pip=. 157 | 158 | * Evaluation 159 | 160 | To evaluate the implementation, we will use some instances provided by the 161 | National Traveling Salesman Problem library. These instances are inspired in 162 | real countries and also include the optimal route for most of them, which is a 163 | key part of our evaluation. The evaluation strategy consists in running several 164 | instances of the problem and study some metrics: 165 | - *Execution time* invested by the technique to find a solution. 166 | - *Quality* of the solution, measured in function of the optimal route: a route 167 | that we say is "10% longer that the optimal route" is exactly 1.1 times the 168 | length of the optimal one. 169 | 170 | The parameters used in the evaluation are the ones found by parametrization of 171 | the technique, by using the ones provided in cite:brocki-2010-somtsp as a 172 | starting point. These parameters are: 173 | - A population size of 8 times the cities in the problem. 174 | - An initial learning rate of 0.8, with a discount rate of 0.99997. 175 | - An initial neighbourhood of the number of cities, decayed by 0.9997. 176 | 177 | These parameters were applied to the following instances: 178 | - *Qatar*, containing 194 cities with an optimal tour of 9352. 179 | - *Uruguay*, containing 734 cities with an optimal tour of 79114. 180 | - *Finland*, containing 10639 cities with an optimal tour of 520527. 181 | - *Italy*, containing 16862 cities with an optimal tour of 557315. 182 | 183 | The implementation also stops the execution if some of the variables decays 184 | under the useful threshold. An uniform way of running the algorithm is tested, 185 | although a finer grained parameters can be found for each instance. The 186 | following table gathers the evaluation results, with the average result of 5 187 | executions in each of the instances. 188 | 189 | | Instance | Iterations | Time (s) | Length | Quality | 190 | |----------+------------+----------+-----------+---------| 191 | | Qatar | 14690 | 14.3 | 10233.89 | 9.4% | 192 | | Uruguay | 17351 | 23.4 | 85072.35 | 7.5% | 193 | | Finland | 37833 | 284.0 | 636580.27 | 22.3% | 194 | | Italy | 39368 | 401.1 | 723212.87 | 29.7% | 195 | 196 | We can see how the time consumption is directly related to the number of 197 | cities, since the complexity of finding the closest neuron of a city depends on 198 | the population to traverse to find it. It is possible to obtain better results 199 | in the large set of cities, but for time constraints it is usually cropped 200 | shorter. The results are never 30% longer than the optimal. In the other 201 | shorter cases, it is interesting to see how a better quality is obtained in 202 | Uruguay even the problem is harder, due to the topography of the country. 203 | 204 | #+CAPTION: Three different steps of execution of the Uruguay instance. 205 | #+ATTR_LATEX: :width 1.3\textwidth,center 206 | [[./img/uruguay.png]] 207 | 208 | It is possible to see in the graphical representation of the executions how the 209 | technique finds its way: first starting as an elastic, fast changing ring 210 | trying to adapt to its shorter form possible, and then starting to fix its 211 | position to find better local ways inside of it. For that purpose, a great 212 | number of neurons are added to the network and the parameters are decayed, to 213 | ensure that first exploration is used and then local exploitation is performed 214 | to refine the solution. 215 | 216 | #+CAPTION: Three different steps of execution of the Italy instance. 217 | #+ATTR_LATEX: :width 1.3\textwidth,center 218 | [[./img/italy.png]] 219 | 220 | The results are overall acceptable, except in extremely demanding settings for 221 | the TSP. We can see how in less than half a minute, a suboptimal route crossing 222 | more than 700 cities is found. 223 | 224 | * Conclusions 225 | 226 | The experiment show a really interesting way to use an organization technique 227 | like the self-organizing maps to find sub-optimal solutions for an NP-Complete 228 | problem like the traveling salesman problem. By modifying the technique used to 229 | find similarity, we are able to create a network that organizes the cities in 230 | the one of the shortest routes possible. Even though the technique is sensible 231 | to parametrization and may need to run for a great number of iterations in the 232 | biggest instances provided, the results are satisfactory and inspiring to find 233 | new uses in well-known, established techniques. 234 | 235 | #+LATEX: \newpage 236 | 237 | bibliography:~/Dropbox/org/bibliography/main.bib 238 | bibliographystyle:ieeetr 239 | 240 | # LocalWords: Teuvo Kohonen SOM eigenvectors Voronoi parametrization minima 241 | -------------------------------------------------------------------------------- /assets/uy734.tsp: -------------------------------------------------------------------------------- 1 | NAME : uy734 2 | COMMENT : 734 locations in Uruguay 3 | COMMENT : Derived from National Imagery and Mapping Agency data 4 | TYPE : TSP 5 | DIMENSION : 734 6 | EDGE_WEIGHT_TYPE : EUC_2D 7 | NODE_COORD_SECTION 8 | 1 -30133.3333 -57633.3333 9 | 2 -30166.6667 -57100.0000 10 | 3 -30233.3333 -57583.3333 11 | 4 -30250.0000 -56850.0000 12 | 5 -30250.0000 -56950.0000 13 | 6 -30250.0000 -57583.3333 14 | 7 -30300.0000 -56966.6667 15 | 8 -30316.6667 -56816.6667 16 | 9 -30400.0000 -56466.6667 17 | 10 -30400.0000 -56783.3333 18 | 11 -30433.3333 -57433.3333 19 | 12 -30466.6667 -56550.0000 20 | 13 -30483.3333 -56516.6667 21 | 14 -30500.0000 -56450.0000 22 | 15 -30500.0000 -56666.6667 23 | 16 -30550.0000 -57866.6667 24 | 17 -30566.6667 -56883.3333 25 | 18 -30600.0000 -57683.3333 26 | 19 -30616.6667 -56900.0000 27 | 20 -30633.3333 -56166.6667 28 | 21 -30683.3333 -57033.3333 29 | 22 -30683.3333 -57516.6667 30 | 23 -30716.6667 -56600.0000 31 | 24 -30733.3333 -56733.3333 32 | 25 -30733.3333 -57316.6667 33 | 26 -30750.0000 -56750.0000 34 | 27 -30783.3333 -57783.3333 35 | 28 -30833.3333 -56750.0000 36 | 29 -30866.6667 -56366.6667 37 | 30 -30900.0000 -55516.6667 38 | 31 -30916.6667 -56300.0000 39 | 32 -30933.3333 -55483.3333 40 | 33 -30933.3333 -55550.0000 41 | 34 -30950.0000 -56650.0000 42 | 35 -30966.6667 -55550.0000 43 | 36 -30966.6667 -57533.3333 44 | 37 -31000.0000 -55683.3333 45 | 38 -31000.0000 -56250.0000 46 | 39 -31016.6667 -56566.6667 47 | 40 -31033.3333 -56600.0000 48 | 41 -31033.3333 -56883.3333 49 | 42 -31083.3333 -56016.6667 50 | 43 -31083.3333 -56516.6667 51 | 44 -31083.3333 -57016.6667 52 | 45 -31083.3333 -57516.6667 53 | 46 -31083.3333 -57600.0000 54 | 47 -31083.3333 -57833.3333 55 | 48 -31100.0000 -55666.6667 56 | 49 -31100.0000 -55983.3333 57 | 50 -31100.0000 -57016.6667 58 | 51 -31116.6667 -56466.6667 59 | 52 -31166.6667 -55750.0000 60 | 53 -31166.6667 -57000.0000 61 | 54 -31166.6667 -57083.3333 62 | 55 -31183.3333 -56283.3333 63 | 56 -31183.3333 -56933.3333 64 | 57 -31200.0000 -55750.0000 65 | 58 -31200.0000 -57233.3333 66 | 59 -31216.6667 -55666.6667 67 | 60 -31216.6667 -56316.6667 68 | 61 -31233.3333 -55633.3333 69 | 62 -31233.3333 -55883.3333 70 | 63 -31233.3333 -57116.6667 71 | 64 -31250.0000 -55333.3333 72 | 65 -31250.0000 -55950.0000 73 | 66 -31250.0000 -56833.3333 74 | 67 -31250.0000 -57166.6667 75 | 68 -31250.0000 -57200.0000 76 | 69 -31283.3333 -56433.3333 77 | 70 -31300.0000 -55866.6667 78 | 71 -31300.0000 -56016.6667 79 | 72 -31300.0000 -57066.6667 80 | 73 -31300.0000 -57100.0000 81 | 74 -31300.0000 -57133.3333 82 | 75 -31300.0000 -57150.0000 83 | 76 -31300.0000 -57200.0000 84 | 77 -31300.0000 -57700.0000 85 | 78 -31316.6667 -55200.0000 86 | 79 -31333.3333 -57800.0000 87 | 80 -31333.3333 -57833.3333 88 | 81 -31333.3333 -57883.3333 89 | 82 -31350.0000 -55383.3333 90 | 83 -31350.0000 -56633.3333 91 | 84 -31350.0000 -57783.3333 92 | 85 -31350.0000 -57800.0000 93 | 86 -31350.0000 -57983.3333 94 | 87 -31366.6667 -55083.3333 95 | 88 -31366.6667 -55666.6667 96 | 89 -31366.6667 -55850.0000 97 | 90 -31383.3333 -55866.6667 98 | 91 -31383.3333 -57966.6667 99 | 92 -31400.0000 -56366.6667 100 | 93 -31400.0000 -57783.3333 101 | 94 -31416.6667 -54916.6667 102 | 95 -31416.6667 -56683.3333 103 | 96 -31433.3333 -55233.3333 104 | 97 -31450.0000 -55416.6667 105 | 98 -31450.0000 -56383.3333 106 | 99 -31466.6667 -55166.6667 107 | 100 -31466.6667 -56833.3333 108 | 101 -31483.3333 -54833.3333 109 | 102 -31500.0000 -54716.6667 110 | 103 -31500.0000 -55166.6667 111 | 104 -31500.0000 -56033.3333 112 | 105 -31500.0000 -57116.6667 113 | 106 -31516.6667 -54966.6667 114 | 107 -31516.6667 -55766.6667 115 | 108 -31516.6667 -55966.6667 116 | 109 -31516.6667 -57533.3333 117 | 110 -31516.6667 -57583.3333 118 | 111 -31533.3333 -55583.3333 119 | 112 -31533.3333 -55833.3333 120 | 113 -31533.3333 -56050.0000 121 | 114 -31550.0000 -55550.0000 122 | 115 -31550.0000 -57950.0000 123 | 116 -31566.6667 -54550.0000 124 | 117 -31583.3333 -55466.6667 125 | 118 -31583.3333 -57616.6667 126 | 119 -31600.0000 -55850.0000 127 | 120 -31600.0000 -56750.0000 128 | 121 -31616.6667 -56816.6667 129 | 122 -31633.3333 -55000.0000 130 | 123 -31633.3333 -56916.6667 131 | 124 -31650.0000 -56833.3333 132 | 125 -31666.6667 -56166.6667 133 | 126 -31666.6667 -56633.3333 134 | 127 -31666.6667 -57916.6667 135 | 128 -31683.3333 -54650.0000 136 | 129 -31683.3333 -54766.6667 137 | 130 -31683.3333 -55433.3333 138 | 131 -31683.3333 -55950.0000 139 | 132 -31683.3333 -56133.3333 140 | 133 -31683.3333 -57683.3333 141 | 134 -31700.0000 -56100.0000 142 | 135 -31716.6667 -55333.3333 143 | 136 -31733.3333 -54416.6667 144 | 137 -31733.3333 -55983.3333 145 | 138 -31750.0000 -55016.6667 146 | 139 -31750.0000 -55466.6667 147 | 140 -31750.0000 -56066.6667 148 | 141 -31766.6667 -54800.0000 149 | 142 -31766.6667 -56016.6667 150 | 143 -31766.6667 -56250.0000 151 | 144 -31783.3333 -54333.3333 152 | 145 -31783.3333 -54750.0000 153 | 146 -31783.3333 -55150.0000 154 | 147 -31783.3333 -56250.0000 155 | 148 -31800.0000 -54716.6667 156 | 149 -31800.0000 -55333.3333 157 | 150 -31800.0000 -55700.0000 158 | 151 -31800.0000 -56133.3333 159 | 152 -31816.6667 -54666.6667 160 | 153 -31816.6667 -55183.3333 161 | 154 -31816.6667 -55216.6667 162 | 155 -31816.6667 -55500.0000 163 | 156 -31816.6667 -55916.6667 164 | 157 -31816.6667 -55966.6667 165 | 158 -31833.3333 -54166.6667 166 | 159 -31833.3333 -55766.6667 167 | 160 -31833.3333 -55933.3333 168 | 161 -31833.3333 -55983.3333 169 | 162 -31833.3333 -57250.0000 170 | 163 -31850.0000 -56000.0000 171 | 164 -31866.6667 -54200.0000 172 | 165 -31866.6667 -57283.3333 173 | 166 -31883.3333 -55433.3333 174 | 167 -31883.3333 -55966.6667 175 | 168 -31883.3333 -56000.0000 176 | 169 -31883.3333 -57333.3333 177 | 170 -31883.3333 -57483.3333 178 | 171 -31883.3333 -57516.6667 179 | 172 -31900.0000 -54150.0000 180 | 173 -31900.0000 -54783.3333 181 | 174 -31900.0000 -55133.3333 182 | 175 -31900.0000 -55466.6667 183 | 176 -31900.0000 -55883.3333 184 | 177 -31916.6667 -54733.3333 185 | 178 -31916.6667 -55933.3333 186 | 179 -31916.6667 -56016.6667 187 | 180 -31916.6667 -57250.0000 188 | 181 -31916.6667 -57716.6667 189 | 182 -31950.0000 -57883.3333 190 | 183 -31966.6667 -55050.0000 191 | 184 -31966.6667 -57516.6667 192 | 185 -31983.3333 -54166.6667 193 | 186 -31983.3333 -55683.3333 194 | 187 -31983.3333 -57416.6667 195 | 188 -32000.0000 -54133.3333 196 | 189 -32000.0000 -55483.3333 197 | 190 -32000.0000 -57166.6667 198 | 191 -32000.0000 -57300.0000 199 | 192 -32000.0000 -57583.3333 200 | 193 -32016.6667 -54200.0000 201 | 194 -32016.6667 -55066.6667 202 | 195 -32016.6667 -57333.3333 203 | 196 -32016.6667 -57466.6667 204 | 197 -32033.3333 -54183.3333 205 | 198 -32033.3333 -54566.6667 206 | 199 -32033.3333 -55666.6667 207 | 200 -32033.3333 -55783.3333 208 | 201 -32050.0000 -54633.3333 209 | 202 -32050.0000 -54866.6667 210 | 203 -32050.0000 -55383.3333 211 | 204 -32066.6667 -53766.6667 212 | 205 -32066.6667 -56350.0000 213 | 206 -32083.3333 -54250.0000 214 | 207 -32083.3333 -55650.0000 215 | 208 -32083.3333 -56866.6667 216 | 209 -32083.3333 -57916.6667 217 | 210 -32100.0000 -53750.0000 218 | 211 -32100.0000 -54866.6667 219 | 212 -32100.0000 -57416.6667 220 | 213 -32100.0000 -57816.6667 221 | 214 -32116.6667 -54066.6667 222 | 215 -32116.6667 -57566.6667 223 | 216 -32150.0000 -54200.0000 224 | 217 -32150.0000 -54883.3333 225 | 218 -32150.0000 -54950.0000 226 | 219 -32150.0000 -55050.0000 227 | 220 -32150.0000 -56116.6667 228 | 221 -32166.6667 -53750.0000 229 | 222 -32166.6667 -54116.6667 230 | 223 -32166.6667 -55016.6667 231 | 224 -32166.6667 -55950.0000 232 | 225 -32183.3333 -55033.3333 233 | 226 -32183.3333 -55283.3333 234 | 227 -32183.3333 -56066.6667 235 | 228 -32200.0000 -54066.6667 236 | 229 -32200.0000 -58000.0000 237 | 230 -32216.6667 -55600.0000 238 | 231 -32216.6667 -56016.6667 239 | 232 -32233.3333 -54983.3333 240 | 233 -32233.3333 -55733.3333 241 | 234 -32233.3333 -56500.0000 242 | 235 -32250.0000 -55750.0000 243 | 236 -32250.0000 -56516.6667 244 | 237 -32250.0000 -57300.0000 245 | 238 -32266.6667 -54916.6667 246 | 239 -32266.6667 -55900.0000 247 | 240 -32283.3333 -58050.0000 248 | 241 -32300.0000 -55333.3333 249 | 242 -32321.3889 -58075.5556 250 | 243 -32333.3333 -55883.3333 251 | 244 -32333.3333 -55966.6667 252 | 245 -32333.3333 -57050.0000 253 | 246 -32333.3333 -57800.0000 254 | 247 -32333.3333 -57933.3333 255 | 248 -32333.3333 -58133.3333 256 | 249 -32350.0000 -53833.3333 257 | 250 -32350.0000 -54133.3333 258 | 251 -32350.0000 -55833.3333 259 | 252 -32350.0000 -56550.0000 260 | 253 -32350.0000 -57200.0000 261 | 254 -32366.6667 -54183.3333 262 | 255 -32366.6667 -54766.6667 263 | 256 -32366.6667 -57850.0000 264 | 257 -32366.6667 -57983.3333 265 | 258 -32383.3333 -54350.0000 266 | 259 -32383.3333 -54666.6667 267 | 260 -32383.3333 -55066.6667 268 | 261 -32383.3333 -56683.3333 269 | 262 -32383.3333 -57500.0000 270 | 263 -32383.3333 -57600.0000 271 | 264 -32400.0000 -55350.0000 272 | 265 -32400.0000 -56716.6667 273 | 266 -32400.0000 -56900.0000 274 | 267 -32416.6667 -56166.6667 275 | 268 -32416.6667 -56333.3333 276 | 269 -32416.6667 -57383.3333 277 | 270 -32416.6667 -57583.3333 278 | 271 -32416.6667 -58150.0000 279 | 272 -32433.3333 -56350.0000 280 | 273 -32450.0000 -55033.3333 281 | 274 -32450.0000 -56033.3333 282 | 275 -32466.6667 -54316.6667 283 | 276 -32466.6667 -55233.3333 284 | 277 -32466.6667 -56166.6667 285 | 278 -32483.3333 -53516.6667 286 | 279 -32483.3333 -53716.6667 287 | 280 -32483.3333 -56350.0000 288 | 281 -32483.3333 -57750.0000 289 | 282 -32500.0000 -54016.6667 290 | 283 -32500.0000 -54416.6667 291 | 284 -32500.0000 -56033.3333 292 | 285 -32516.6667 -53483.3333 293 | 286 -32516.6667 -54533.3333 294 | 287 -32516.6667 -54583.3333 295 | 288 -32516.6667 -54683.3333 296 | 289 -32516.6667 -57750.0000 297 | 290 -32533.3333 -54566.6667 298 | 291 -32533.3333 -55500.0000 299 | 292 -32533.3333 -57133.3333 300 | 293 -32566.6667 -53416.6667 301 | 294 -32566.6667 -56883.3333 302 | 295 -32566.6667 -57366.6667 303 | 296 -32566.6667 -57483.3333 304 | 297 -32583.3333 -53383.3333 305 | 298 -32600.0000 -55583.3333 306 | 299 -32616.6667 -54600.0000 307 | 300 -32616.6667 -55833.3333 308 | 301 -32616.6667 -56483.3333 309 | 302 -32633.3333 -53300.0000 310 | 303 -32633.3333 -53900.0000 311 | 304 -32633.3333 -55116.6667 312 | 305 -32633.3333 -56350.0000 313 | 306 -32633.3333 -56750.0000 314 | 307 -32650.0000 -54250.0000 315 | 308 -32650.0000 -54450.0000 316 | 309 -32666.6667 -53616.6667 317 | 310 -32666.6667 -55450.0000 318 | 311 -32683.3333 -54633.3333 319 | 312 -32683.3333 -56883.3333 320 | 313 -32683.3333 -57633.3333 321 | 314 -32683.3333 -58133.3333 322 | 315 -32700.0000 -53966.6667 323 | 316 -32716.6667 -55600.0000 324 | 317 -32716.6667 -57466.6667 325 | 318 -32750.0000 -53483.3333 326 | 319 -32750.0000 -53733.3333 327 | 320 -32750.0000 -54400.0000 328 | 321 -32750.0000 -55650.0000 329 | 322 -32750.0000 -57750.0000 330 | 323 -32766.6667 -55433.3333 331 | 324 -32766.6667 -55633.3333 332 | 325 -32766.6667 -57783.3333 333 | 326 -32766.6667 -57883.3333 334 | 327 -32783.3333 -53833.3333 335 | 328 -32783.3333 -55900.0000 336 | 329 -32800.0000 -55800.0000 337 | 330 -32800.0000 -56416.6667 338 | 331 -32800.0000 -57050.0000 339 | 332 -32816.6667 -56516.6667 340 | 333 -32833.3333 -54766.6667 341 | 334 -32833.3333 -55483.3333 342 | 335 -32833.3333 -56183.3333 343 | 336 -32833.3333 -56433.3333 344 | 337 -32833.3333 -57716.6667 345 | 338 -32850.0000 -57683.3333 346 | 339 -32866.6667 -55916.6667 347 | 340 -32866.6667 -56466.6667 348 | 341 -32883.3333 -55416.6667 349 | 342 -32883.3333 -55516.6667 350 | 343 -32883.3333 -56800.0000 351 | 344 -32900.0000 -55233.3333 352 | 345 -32900.0000 -56083.3333 353 | 346 -32900.0000 -56133.3333 354 | 347 -32916.6667 -54966.6667 355 | 348 -32916.6667 -57733.3333 356 | 349 -32933.3333 -53950.0000 357 | 350 -32933.3333 -54266.6667 358 | 351 -32933.3333 -55516.6667 359 | 352 -32933.3333 -57116.6667 360 | 353 -32933.3333 -57650.0000 361 | 354 -32950.0000 -54216.6667 362 | 355 -32966.6667 -55400.0000 363 | 356 -32983.3333 -54583.3333 364 | 357 -32983.3333 -58050.0000 365 | 358 -33000.0000 -53633.3333 366 | 359 -33000.0000 -55133.3333 367 | 360 -33000.0000 -55783.3333 368 | 361 -33016.6667 -53700.0000 369 | 362 -33016.6667 -53950.0000 370 | 363 -33016.6667 -55050.0000 371 | 364 -33016.6667 -56483.3333 372 | 365 -33033.3333 -57000.0000 373 | 366 -33050.0000 -54066.6667 374 | 367 -33050.0000 -54150.0000 375 | 368 -33050.0000 -56483.3333 376 | 369 -33066.6667 -55850.0000 377 | 370 -33083.3333 -55966.6667 378 | 371 -33083.3333 -56183.3333 379 | 372 -33083.3333 -57433.3333 380 | 373 -33100.0000 -55133.3333 381 | 374 -33100.0000 -57633.3333 382 | 375 -33100.0000 -57733.3333 383 | 376 -33116.6667 -54816.6667 384 | 377 -33116.6667 -54833.3333 385 | 378 -33116.6667 -55983.3333 386 | 379 -33132.5000 -58295.5556 387 | 380 -33133.3333 -54933.3333 388 | 381 -33133.3333 -57150.0000 389 | 382 -33150.0000 -54150.0000 390 | 383 -33166.6667 -54966.6667 391 | 384 -33166.6667 -57583.3333 392 | 385 -33183.3333 -53900.0000 393 | 386 -33183.3333 -55700.0000 394 | 387 -33183.3333 -57466.6667 395 | 388 -33200.0000 -53800.0000 396 | 389 -33200.0000 -54750.0000 397 | 390 -33200.0000 -56783.3333 398 | 391 -33216.6667 -54383.3333 399 | 392 -33216.6667 -56683.3333 400 | 393 -33233.3333 -53850.0000 401 | 394 -33233.3333 -54383.3333 402 | 395 -33233.3333 -57133.3333 403 | 396 -33250.0000 -53900.0000 404 | 397 -33250.0000 -53916.6667 405 | 398 -33250.0000 -54016.6667 406 | 399 -33250.0000 -54333.3333 407 | 400 -33250.0000 -56016.6667 408 | 401 -33250.0000 -57333.3333 409 | 402 -33255.8333 -58019.1667 410 | 403 -33266.6667 -53783.3333 411 | 404 -33266.6667 -54416.6667 412 | 405 -33266.6667 -55100.0000 413 | 406 -33266.6667 -55116.6667 414 | 407 -33283.3333 -53933.3333 415 | 408 -33300.0000 -56350.0000 416 | 409 -33333.3333 -54783.3333 417 | 410 -33333.3333 -56466.6667 418 | 411 -33333.3333 -56933.3333 419 | 412 -33333.3333 -57950.0000 420 | 413 -33350.0000 -55616.6667 421 | 414 -33350.0000 -55633.3333 422 | 415 -33366.6667 -53666.6667 423 | 416 -33366.6667 -56483.3333 424 | 417 -33383.3333 -55083.3333 425 | 418 -33383.3333 -56416.6667 426 | 419 -33383.3333 -57550.0000 427 | 420 -33400.0000 -54683.3333 428 | 421 -33400.0000 -58316.6667 429 | 422 -33413.0556 -56500.5556 430 | 423 -33416.6667 -55633.3333 431 | 424 -33416.6667 -57066.6667 432 | 425 -33450.0000 -54533.3333 433 | 426 -33450.0000 -57733.3333 434 | 427 -33466.6667 -54200.0000 435 | 428 -33466.6667 -54650.0000 436 | 429 -33466.6667 -54666.6667 437 | 430 -33466.6667 -55116.6667 438 | 431 -33466.6667 -55200.0000 439 | 432 -33466.6667 -55616.6667 440 | 433 -33483.3333 -55150.0000 441 | 434 -33483.3333 -55566.6667 442 | 435 -33483.3333 -56150.0000 443 | 436 -33483.3333 -56483.3333 444 | 437 -33500.0000 -55216.6667 445 | 438 -33500.0000 -56750.0000 446 | 439 -33500.0000 -56866.6667 447 | 440 -33516.6667 -53783.3333 448 | 441 -33516.6667 -54916.6667 449 | 442 -33516.6667 -56400.0000 450 | 443 -33516.6667 -57833.3333 451 | 444 -33533.3333 -54433.3333 452 | 445 -33533.3333 -54600.0000 453 | 446 -33533.3333 -56900.0000 454 | 447 -33533.3333 -56933.3333 455 | 448 -33538.8889 -56888.6111 456 | 449 -33544.1667 -58197.2222 457 | 450 -33550.0000 -55666.6667 458 | 451 -33550.0000 -56900.0000 459 | 452 -33566.6667 -53850.0000 460 | 453 -33583.3333 -57300.0000 461 | 454 -33583.3333 -57583.3333 462 | 455 -33583.3333 -58083.3333 463 | 456 -33600.0000 -54316.6667 464 | 457 -33600.0000 -55333.3333 465 | 458 -33600.0000 -56350.0000 466 | 459 -33600.0000 -57133.3333 467 | 460 -33600.0000 -57983.3333 468 | 461 -33616.6667 -53716.6667 469 | 462 -33616.6667 -57633.3333 470 | 463 -33616.6667 -58283.3333 471 | 464 -33650.0000 -53800.0000 472 | 465 -33650.0000 -57533.3333 473 | 466 -33666.6667 -54200.0000 474 | 467 -33683.3333 -53450.0000 475 | 468 -33683.3333 -53550.0000 476 | 469 -33683.3333 -54650.0000 477 | 470 -33683.3333 -57566.6667 478 | 471 -33716.6667 -54533.3333 479 | 472 -33716.6667 -58083.3333 480 | 473 -33716.6667 -58266.6667 481 | 474 -33733.3333 -54750.0000 482 | 475 -33733.3333 -56333.3333 483 | 476 -33733.3333 -57833.3333 484 | 477 -33750.0000 -55283.3333 485 | 478 -33750.0000 -56466.6667 486 | 479 -33750.0000 -57483.3333 487 | 480 -33750.0000 -57616.6667 488 | 481 -33766.6667 -58350.0000 489 | 482 -33800.0000 -54000.0000 490 | 483 -33800.0000 -58250.0000 491 | 484 -33816.6667 -55550.0000 492 | 485 -33816.6667 -57550.0000 493 | 486 -33833.3333 -56300.0000 494 | 487 -33850.0000 -55166.6667 495 | 488 -33850.0000 -56883.3333 496 | 489 -33850.0000 -57016.6667 497 | 490 -33850.0000 -57683.3333 498 | 491 -33866.6667 -55550.0000 499 | 492 -33866.6667 -57000.0000 500 | 493 -33866.6667 -57516.6667 501 | 494 -33866.6667 -57616.6667 502 | 495 -33883.3333 -53500.0000 503 | 496 -33883.3333 -54716.6667 504 | 497 -33883.3333 -56450.0000 505 | 498 -33883.3333 -57383.3333 506 | 499 -33883.3333 -57400.0000 507 | 500 -33883.3333 -57666.6667 508 | 501 -33883.3333 -58416.6667 509 | 502 -33900.0000 -55150.0000 510 | 503 -33900.0000 -56833.3333 511 | 504 -33916.6667 -57783.3333 512 | 505 -33933.3333 -55266.6667 513 | 506 -33933.3333 -55683.3333 514 | 507 -33933.3333 -56250.0000 515 | 508 -33933.3333 -57466.6667 516 | 509 -33933.3333 -58166.6667 517 | 510 -33950.0000 -55850.0000 518 | 511 -33950.0000 -56750.0000 519 | 512 -33950.0000 -57900.0000 520 | 513 -33950.0000 -58233.3333 521 | 514 -33966.6667 -57100.0000 522 | 515 -33966.6667 -58283.3333 523 | 516 -33983.3333 -53983.3333 524 | 517 -33983.3333 -57900.0000 525 | 518 -33983.3333 -58150.0000 526 | 519 -33983.3333 -58250.0000 527 | 520 -33989.1667 -58285.5556 528 | 521 -34000.0000 -55666.6667 529 | 522 -34000.0000 -58250.0000 530 | 523 -34016.6667 -57650.0000 531 | 524 -34033.3333 -54283.3333 532 | 525 -34033.3333 -55650.0000 533 | 526 -34033.3333 -57833.3333 534 | 527 -34033.3333 -58133.3333 535 | 528 -34050.0000 -54783.3333 536 | 529 -34050.0000 -55883.3333 537 | 530 -34050.0000 -56200.0000 538 | 531 -34066.6667 -53933.3333 539 | 532 -34066.6667 -54500.0000 540 | 533 -34066.6667 -56300.0000 541 | 534 -34066.6667 -56383.3333 542 | 535 -34066.6667 -57350.0000 543 | 536 -34066.6667 -57716.6667 544 | 537 -34083.3333 -57383.3333 545 | 538 -34095.5556 -56214.1667 546 | 539 -34100.0000 -58000.0000 547 | 540 -34116.6667 -53950.0000 548 | 541 -34133.3333 -56400.0000 549 | 542 -34150.0000 -56950.0000 550 | 543 -34152.2222 -58012.5000 551 | 544 -34153.0556 -58176.6667 552 | 545 -34166.6667 -53833.3333 553 | 546 -34166.6667 -53850.0000 554 | 547 -34166.6667 -54666.6667 555 | 548 -34166.6667 -56683.3333 556 | 549 -34183.3333 -53783.3333 557 | 550 -34183.3333 -55733.3333 558 | 551 -34183.3333 -57933.3333 559 | 552 -34189.1667 -56339.4444 560 | 553 -34200.0000 -53933.3333 561 | 554 -34200.0000 -54750.0000 562 | 555 -34200.0000 -56216.6667 563 | 556 -34200.0000 -56983.3333 564 | 557 -34200.0000 -57100.0000 565 | 558 -34200.0000 -57783.3333 566 | 559 -34200.0000 -57866.6667 567 | 560 -34216.6667 -57000.0000 568 | 561 -34233.3333 -55733.3333 569 | 562 -34233.3333 -56866.6667 570 | 563 -34250.0000 -55933.3333 571 | 564 -34250.0000 -56683.3333 572 | 565 -34266.6667 -53933.3333 573 | 566 -34266.6667 -54316.6667 574 | 567 -34266.6667 -57450.0000 575 | 568 -34283.3333 -54983.3333 576 | 569 -34283.3333 -55233.3333 577 | 570 -34283.3333 -56216.6667 578 | 571 -34283.3333 -56916.6667 579 | 572 -34283.3333 -57616.6667 580 | 573 -34290.5556 -56388.8889 581 | 574 -34300.0000 -55966.6667 582 | 575 -34300.0000 -57233.3333 583 | 576 -34300.0000 -57733.3333 584 | 577 -34316.6667 -56800.0000 585 | 578 -34316.6667 -57000.0000 586 | 579 -34316.6667 -57216.6667 587 | 580 -34316.6667 -57350.0000 588 | 581 -34319.1667 -56805.2778 589 | 582 -34333.3333 -55450.0000 590 | 583 -34333.3333 -55650.0000 591 | 584 -34333.3333 -57233.3333 592 | 585 -34333.3333 -57716.6667 593 | 586 -34337.5000 -56713.6111 594 | 587 -34350.0000 -55766.6667 595 | 588 -34350.0000 -56650.0000 596 | 589 -34350.0000 -57300.0000 597 | 590 -34350.0000 -57433.3333 598 | 591 -34350.0000 -57850.0000 599 | 592 -34351.6667 -56398.3333 600 | 593 -34366.6667 -53766.6667 601 | 594 -34366.6667 -53833.3333 602 | 595 -34366.6667 -54066.6667 603 | 596 -34366.6667 -55166.6667 604 | 597 -34366.6667 -55516.6667 605 | 598 -34366.6667 -55783.3333 606 | 599 -34366.6667 -56400.0000 607 | 600 -34366.6667 -57050.0000 608 | 601 -34366.6667 -57066.6667 609 | 602 -34366.6667 -57566.6667 610 | 603 -34370.0000 -55225.0000 611 | 604 -34382.7778 -56541.6667 612 | 605 -34383.3333 -56283.3333 613 | 606 -34383.3333 -56383.3333 614 | 607 -34383.3333 -56766.6667 615 | 608 -34400.0000 -53783.3333 616 | 609 -34400.0000 -56333.3333 617 | 610 -34400.0000 -56533.3333 618 | 611 -34400.0000 -57166.6667 619 | 612 -34400.0000 -57333.3333 620 | 613 -34400.0000 -57666.6667 621 | 614 -34400.0000 -57883.3333 622 | 615 -34411.6667 -56402.2222 623 | 616 -34416.6667 -56466.6667 624 | 617 -34416.6667 -57283.3333 625 | 618 -34416.6667 -57733.3333 626 | 619 -34419.7222 -56422.5000 627 | 620 -34433.3333 -55983.3333 628 | 621 -34433.3333 -57416.6667 629 | 622 -34433.3333 -57716.6667 630 | 623 -34433.3333 -57883.3333 631 | 624 -34442.2222 -56443.6111 632 | 625 -34449.7222 -56079.1667 633 | 626 -34450.0000 -55783.3333 634 | 627 -34450.0000 -56166.6667 635 | 628 -34450.0000 -56250.0000 636 | 629 -34450.0000 -56283.3333 637 | 630 -34450.0000 -57600.0000 638 | 631 -34453.3333 -56390.5556 639 | 632 -34466.6667 -57716.6667 640 | 633 -34466.6667 -57850.0000 641 | 634 -34483.3333 -54333.3333 642 | 635 -34483.3333 -55633.3333 643 | 636 -34483.3333 -55650.0000 644 | 637 -34483.3333 -56850.0000 645 | 638 -34497.5000 -56037.2222 646 | 639 -34500.0000 -55583.3333 647 | 640 -34500.0000 -56383.3333 648 | 641 -34516.6667 -55250.0000 649 | 642 -34519.7222 -56798.8889 650 | 643 -34521.9444 -56393.6111 651 | 644 -34522.7778 -56277.7778 652 | 645 -34533.3333 -56300.0000 653 | 646 -34533.3333 -56316.6667 654 | 647 -34550.0000 -55883.3333 655 | 648 -34566.6667 -55700.0000 656 | 649 -34583.3333 -55833.3333 657 | 650 -34583.8889 -56699.4444 658 | 651 -34589.4444 -56252.7778 659 | 652 -34600.0000 -54550.0000 660 | 653 -34600.0000 -55483.3333 661 | 654 -34600.0000 -56133.3333 662 | 655 -34605.0000 -56356.3889 663 | 656 -34633.3333 -55616.6667 664 | 657 -34633.3333 -55966.6667 665 | 658 -34633.3333 -56333.3333 666 | 659 -34633.3333 -56619.1667 667 | 660 -34646.9444 -56062.7778 668 | 661 -34650.0000 -55233.3333 669 | 662 -34650.0000 -55866.6667 670 | 663 -34650.0000 -56600.0000 671 | 664 -34650.0000 -56716.6667 672 | 665 -34650.0000 -56750.0000 673 | 666 -34665.0000 -56219.4444 674 | 667 -34666.6667 -54166.6667 675 | 668 -34666.6667 -55266.6667 676 | 669 -34666.6667 -56000.0000 677 | 670 -34683.3333 -55683.3333 678 | 671 -34683.3333 -56733.3333 679 | 672 -34698.3333 -56217.5000 680 | 673 -34700.0000 -55900.0000 681 | 674 -34715.2778 -56073.3333 682 | 675 -34716.6667 -55416.6667 683 | 676 -34716.6667 -55533.3333 684 | 677 -34716.6667 -55950.0000 685 | 678 -34726.3889 -56220.0000 686 | 679 -34733.3333 -55266.6667 687 | 680 -34733.3333 -55716.6667 688 | 681 -34733.6111 -56036.6667 689 | 682 -34742.2222 -56098.3333 690 | 683 -34750.0000 -55333.3333 691 | 684 -34750.0000 -55683.3333 692 | 685 -34761.6667 -56223.6111 693 | 686 -34762.5000 -56020.5556 694 | 687 -34763.3333 -56385.2778 695 | 688 -34764.1667 -56213.8889 696 | 689 -34766.6667 -55750.0000 697 | 690 -34781.1111 -56053.3333 698 | 691 -34790.2778 -56350.0000 699 | 692 -34800.0000 -54916.6667 700 | 693 -34800.0000 -55233.3333 701 | 694 -34800.0000 -55366.6667 702 | 695 -34800.0000 -56216.6667 703 | 696 -34800.0000 -56233.3333 704 | 697 -34801.6667 -56334.1667 705 | 698 -34803.0556 -56085.8333 706 | 699 -34813.0556 -56044.7222 707 | 700 -34816.6667 -56100.0000 708 | 701 -34816.6667 -56183.3333 709 | 702 -34828.6111 -56139.4444 710 | 703 -34833.3333 -56116.6667 711 | 704 -34833.3333 -56216.6667 712 | 705 -34833.3333 -56233.3333 713 | 706 -34850.0000 -56083.3333 714 | 707 -34850.0000 -56116.6667 715 | 708 -34850.0000 -56216.6667 716 | 709 -34850.0000 -56233.3333 717 | 710 -34858.0556 -56170.8333 718 | 711 -34860.2778 -56052.2222 719 | 712 -34866.6667 -54866.6667 720 | 713 -34866.6667 -56166.6667 721 | 714 -34870.5556 -56133.6111 722 | 715 -34875.0000 -56258.8889 723 | 716 -34877.2222 -56029.7222 724 | 717 -34883.3333 -56150.0000 725 | 718 -34883.3333 -56183.3333 726 | 719 -34883.3333 -56200.0000 727 | 720 -34883.3333 -56216.6667 728 | 721 -34883.3333 -56233.3333 729 | 722 -34885.2778 -56060.5556 730 | 723 -34900.0000 -54950.0000 731 | 724 -34900.0000 -55283.3333 732 | 725 -34900.0000 -56100.0000 733 | 726 -34900.0000 -56133.3333 734 | 727 -34900.0000 -56150.0000 735 | 728 -34900.0000 -56183.3333 736 | 729 -34905.0000 -56168.3333 737 | 730 -34905.2778 -56194.4444 738 | 731 -34908.3333 -56208.3333 739 | 732 -34909.7222 -56152.2222 740 | 733 -34922.7778 -56159.7222 741 | 734 -34966.6667 -54950.0000 742 | EOF 743 | --------------------------------------------------------------------------------