Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor #7

Merged
merged 12 commits into from
Feb 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ jobs:
${{ runner.os }}-test-${{ env.cache-name }}-
${{ runner.os }}-test-
${{ runner.os }}-
- name: Install dependencies
run: julia --project=. -e 'using Pkg; Pkg.add(url="""https://github.com/matago/TSPLIB.jl"""); Pkg.instantiate()'
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
- uses: julia-actions/julia-processcoverage@v1
Expand Down
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ version = "0.1.0"
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
TSPLIB = "b1c258e7-59ae-4b06-a547-f10871db1548"

[compat]
julia = "1"
Expand Down
1 change: 1 addition & 0 deletions deps/build.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Libdl


const QSOPT_LOCATION = Dict(
"Darwin" => [
"https://www.math.uwaterloo.ca/~bico/qsopt/beta/codes/mac64/qsopt.a",
Expand Down
148 changes: 4 additions & 144 deletions src/Concorde.jl
Original file line number Diff line number Diff line change
@@ -1,153 +1,13 @@
module Concorde

using Random, LinearAlgebra
using TSPLIB


include("../deps/deps.jl")
include("dist.jl")
# Write your package code here.

function read_solution(filepath)
sol = readlines(filepath)
n_nodes = sol[1]
tour = parse.(Int, split(join(sol[2:end]))) .+ 1
return tour
end

function tour_length(tour, M)
n_nodes = length(tour)
len = 0
for i in 1:n_nodes
j = i + 1
if i == n_nodes
j = 1
end

len += M[tour[i], tour[j]]
end
return len
end


function cleanup(name)
exts = ["mas", "pul", "sav", "sol", "tsp"]
for ext in exts
file = "$(name).$(ext)"
rm(file, force=true)
file = "O$(name).$(ext)"
rm(file, force=true)
end
end

function solve_tsp(dist_mtx::Matrix{Int})
if !issymmetric(dist_mtx)
error("Asymmetric TSP is not supported.")
end

n_nodes = size(dist_mtx, 1)
name = randstring(10)
filepath = name * ".tsp"
lower_diag_row = Int[]
for i in 1:n_nodes
for j in 1:i
push!(lower_diag_row, dist_mtx[i, j])
end
end
buf = 10
n_rows = length(lower_diag_row) / buf |> ceil |> Int
rows = String[]
for i in 1:n_rows
s = buf * (i-1) + 1
t = min(buf * i, length(lower_diag_row))
push!(rows, join(lower_diag_row[s:t], " "))
end

open(filepath, "w") do io
write(io, "NAME: $(name)\n")
write(io, "TYPE: TSP\n")
write(io, "COMMENT: $(name)\n")
write(io, "DIMENSION: $(n_nodes)\n")
write(io, "EDGE_WEIGHT_TYPE: EXPLICIT\n")
write(io, "EDGE_WEIGHT_FORMAT: LOWER_DIAG_ROW \n")
write(io, "EDGE_WEIGHT_SECTION\n")
for r in rows
write(io, "$r\n")
end
write(io, "EOF\n")
end

status = run(`$(Concorde.CONCORDE_EXECUTABLE) $(filepath)`, wait=false)
while !success(status)
#
end

sol_filepath = name * ".sol"
opt_tour = read_solution(sol_filepath)
opt_len = tour_length(opt_tour, dist_mtx)

cleanup(name)

return opt_tour, opt_len
end


function solve_tsp(x::Vector{Float64}, y::Vector{Float64}; dist="EUC_2D")
n_nodes = length(x)
@assert length(x) == length(y)

name = randstring(10)
filepath = name * ".tsp"

open(filepath, "w") do io
write(io, "NAME: $(name)\n")
write(io, "TYPE: TSP\n")
write(io, "COMMENT: $(name)\n")
write(io, "DIMENSION: $(n_nodes)\n")
write(io, "EDGE_WEIGHT_TYPE: $(dist)\n")
write(io, "EDGE_WEIGHT_FORMAT: FUNCTION \n")
write(io, "NODE_COORD_TYPE: TWOD_COORDS \n")
write(io, "NODE_COORD_SECTION\n")
for i in 1:n_nodes
write(io, "$i $(x[i]) $(y[i])\n")
end
write(io, "EOF\n")
end

status = run(`$(Concorde.CONCORDE_EXECUTABLE) $(filepath)`, wait=false)
while !success(status)
#
end

sol_filepath = name * ".sol"
opt_tour = read_solution(sol_filepath)
opt_len = tour_length(opt_tour, dist_matrix(x, y, dist=dist))

cleanup(name)

return opt_tour, opt_len
end

function solve_tsp(tsp_file::String)
if !isfile(tsp_file)
error("$(tsp_file) is not a file.")
end

name = randstring(10)
filepath = name * ".tsp"
cp(tsp_file, filepath)

status = run(`$(Concorde.CONCORDE_EXECUTABLE) $(filepath)`, wait=false)
while !success(status)
#
end

sol_filepath = name * ".sol"
opt_tour = read_solution(sol_filepath)
opt_len = - 1 # Need to implement the calculation of the obj function

cleanup(name)

return opt_tour, opt_len
end
include("util.jl")
include("solver.jl")


export solve_tsp
Expand Down
110 changes: 55 additions & 55 deletions src/dist.jl
Original file line number Diff line number Diff line change
@@ -1,63 +1,63 @@
function nint(x::Float64)
return round(Int, x)
end
# function nint(x::Float64)
# return round(Int, x)
# end

function geo_coordinate(x, y)
PI = 3.141592
# function geo_coordinate(x, y)
# PI = 3.141592

deg = nint(x)
m = x - deg
latitude = PI * (deg + 5.0 * m / 3.0) / 180.0
# deg = nint(x)
# m = x - deg
# latitude = PI * (deg + 5.0 * m / 3.0) / 180.0

deg = nint(y)
m = y - deg
longitude = PI * (deg + 5.0 * m / 3.0) / 180.0
# deg = nint(y)
# m = y - deg
# longitude = PI * (deg + 5.0 * m / 3.0) / 180.0

return latitude, longitude
end
# return latitude, longitude
# end

function distance2D(xi, yi, xj, yj; dist="EUC_2D")
if dist == "EUC_2D"
xd = xi - xj
yd = yi - yj
return nint(sqrt(xd*xd + yd*yd))
elseif dist == "MAN_2D"
xd = abs(xi - xj)
yd = abs(yi - yj)
return nint(xd + yd)
elseif dist == "MAX_2D"
xd = abs(xi - xj)
yd = abs(yi - yj)
return max(nint(xd), nint(yd))
elseif dist == "GEO"
lat_i, long_i = geo_coordinate(xi, yi)
lat_j, long_j = geo_coordinate(xj, yj)
RRR = 6378.388
q1 = cos(long_i - long_j)
q2 = cos(lat_i - lat_j)
q3 = cos(lat_i + lat_j)
dij = RRR * acos( 0.5*((1.0+q1)*q2 - (1.0-q1)*q3) ) + 1.0
return floor(Int, dij)
else
error("Distance function $dist is not supported.")
end
end
# function distance2D(xi, yi, xj, yj; dist="EUC_2D")
# if dist == "EUC_2D"
# xd = xi - xj
# yd = yi - yj
# return nint(sqrt(xd*xd + yd*yd))
# elseif dist == "MAN_2D"
# xd = abs(xi - xj)
# yd = abs(yi - yj)
# return nint(xd + yd)
# elseif dist == "MAX_2D"
# xd = abs(xi - xj)
# yd = abs(yi - yj)
# return max(nint(xd), nint(yd))
# elseif dist == "GEO"
# lat_i, long_i = geo_coordinate(xi, yi)
# lat_j, long_j = geo_coordinate(xj, yj)
# RRR = 6378.388
# q1 = cos(long_i - long_j)
# q2 = cos(lat_i - lat_j)
# q3 = cos(lat_i + lat_j)
# dij = RRR * acos( 0.5*((1.0+q1)*q2 - (1.0-q1)*q3) ) + 1.0
# return floor(Int, dij)
# else
# error("Distance function $dist is not supported.")
# end
# end

function dist_matrix(x::Vector{Float64}, y::Vector{Float64}; dist="EUC_2D")
n_nodes = length(x)
@assert length(x) == length(y)
# function dist_matrix(x::Vector{Float64}, y::Vector{Float64}; dist="EUC_2D")
# n_nodes = length(x)
# @assert length(x) == length(y)

M = Matrix{Int}(undef, n_nodes, n_nodes)
# M = Matrix{Int}(undef, n_nodes, n_nodes)

for i in 1:n_nodes
for j in i:n_nodes
if i == j
M[i, j] = 0
else
M[i, j] = distance2D(x[i], y[i], x[j], y[j]; dist=dist)
M[j, i] = M[i, j]
end
end
end
return M
end
# for i in 1:n_nodes
# for j in i:n_nodes
# if i == j
# M[i, j] = 0
# else
# M[i, j] = distance2D(x[i], y[i], x[j], y[j]; dist=dist)
# M[j, i] = M[i, j]
# end
# end
# end
# return M
# end
Loading