diff --git a/notebooks/tsp.ipynb b/notebooks/tsp.ipynb new file mode 100644 index 0000000..f8017c4 --- /dev/null +++ b/notebooks/tsp.ipynb @@ -0,0 +1,260 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "8850d90e", + "metadata": {}, + "outputs": [], + "source": [ + "using Distributed" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "5d4935ee", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4-element Vector{Int64}:\n", + " 2\n", + " 3\n", + " 4\n", + " 5" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "if procs() == workers()\n", + " addprocs(4)\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "4a2756ae", + "metadata": {}, + "outputs": [], + "source": [ + "@everywhere function visited(city,hops,path)\n", + " for i = 1:hops\n", + " if path[i] == city\n", + " return true\n", + " end\n", + " end\n", + " return false\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "39e9e667", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tsp_serial_impl (generic function with 1 method)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "function tsp_serial_impl(connections,hops,path,current_distance,min_distance)\n", + " num_cities = length(connections)\n", + " if hops == num_cities\n", + " if current_distance < min_distance\n", + " return current_distance\n", + " end\n", + " else\n", + " current_city = path[hops]\n", + " next_hops = hops + 1\n", + " for (next_city,distance_increment) in connections[current_city]\n", + " if !visited(next_city,hops,path)\n", + " path[next_hops] = next_city\n", + " next_distance = current_distance + distance_increment\n", + " if next_distance < min_distance\n", + " return tsp_serial_impl(connections,next_hops,path,next_distance,min_distance)\n", + " end\n", + " end\n", + " end \n", + " end\n", + " min_distance\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "83b58881", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tsp_serial (generic function with 1 method)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "function tsp_serial(connections,city)\n", + " num_cities = length(connections)\n", + " path=zeros(Int,num_cities)\n", + " hops = 1\n", + " path[hops] = city\n", + " current_distance = 0\n", + " min_distance = typemax(Int)\n", + " min_distance = tsp_serial_impl(connections,hops,path,current_distance,min_distance)\n", + " (;path=path,distance=min_distance)\n", + "end" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "78095098", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(path = [1, 4, 5, 2, 3, 6], distance = 222)" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "connections = [\n", + " [(1,0),(4,39),(5,76), (6,78),(3,94),(2,97)],\n", + " [(2,0),(5,25),(4,58),(3,62),(1,97),(6,109)],\n", + " [(3,0),(6,58),(2,62),(4,68),(5,70),(1,94)],\n", + " [(4,0),(5,38),(1,39),(2,58),(3,68),(6,78)],\n", + " [(5,0),(2,25),(4,38),(3,70),(1,76),(6,104)],\n", + " [(6,0),(3,58),(1,78),(4,78),(5,104),(2,109)]\n", + "]\n", + "city = 1\n", + "tsp_serial(connections,city)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "03f0dd8e", + "metadata": {}, + "outputs": [], + "source": [ + "@everywhere function tsp_dist_impl(connections,hops,path,current_distance,min_distance,max_hops,jobs_chnl,ftr_result)\n", + " num_cities = length(connections)\n", + " if hops == num_cities\n", + " if current_distance < min_distance\n", + " if ftr_result !== nothing\n", + " @spawnat 1 begin\n", + " result = fetch(ftr_result)\n", + " result.path .= path\n", + " result.min_distance_ref[] = current_distance\n", + " end |> wait\n", + " end\n", + " return current_distance\n", + " end\n", + " elseif hops <= max_hops\n", + " current_city = path[hops]\n", + " next_hops = hops + 1\n", + " for (next_city,distance_increment) in connections[current_city]\n", + " if !visited(next_city,hops,path)\n", + " path[next_hops] = next_city\n", + " next_distance = current_distance + distance_increment\n", + " if next_distance < min_distance\n", + " return tsp_dist_impl(connections,next_hops,path,next_distance,min_distance,max_hops,jobs_chnl,ftr_result)\n", + " end\n", + " end\n", + " end \n", + " else\n", + " if jobs_channel !== nothing\n", + " put!(jobs_chnl,(;hops,path,current_distance))\n", + " end\n", + " end\n", + " min_distance\n", + "end\n", + "\n", + "function tsp_dist(connections,city)\n", + " max_hops = 2\n", + " num_cities = length(connections)\n", + " path=zeros(Int,num_cities)\n", + " hops = 1\n", + " path[hops] = city\n", + " current_distance = 0\n", + " min_distance = typemax(Int)\n", + " jobs_chnl = RemoteChannel(()->Channel{Any}(10))\n", + " ftr_result = @spawnat 1 (;path,min_distance_ref=Ref(min_distance))\n", + " task = @async begin\n", + " tsp_dist_impl(connections,hops,path,current_distance,min_distance,max_hops,jobs_chnl,nothing)\n", + " for w in workers()\n", + " put!(job_chnl,nothing)\n", + " end\n", + " end\n", + " @sync for w in workers()\n", + " @spawnat w begin\n", + " max_hops = typemax(Int)\n", + " jobs_channel = nothing\n", + " while true\n", + " job = take!(jobs_chnl)\n", + " if job == nothing\n", + " break\n", + " end\n", + " hobs = job.hobs\n", + " path = job.path\n", + " current_distance = job.current_distance\n", + " tsp_dist_impl(connections,hops,path,current_distance,min_distance,max_hops,jobs_chnl,ftr_result)\n", + " end\n", + " end\n", + " end \n", + " (;path=path,distance=min_distance)\n", + "end\n", + "city = 1\n", + "tsp_dist(connections,city)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "370a1205", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Julia 1.9.0", + "language": "julia", + "name": "julia-1.9" + }, + "language_info": { + "file_extension": ".jl", + "mimetype": "application/julia", + "name": "julia", + "version": "1.9.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}