Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Pump, Cedric
PVS_TSP
Commits
fd029285
Commit
fd029285
authored
May 20, 2021
by
CedricPump
Browse files
- added serial solver
parent
7df196e2
Changes
3
Hide whitespace changes
Inline
Side-by-side
main.go
View file @
fd029285
...
@@ -83,7 +83,7 @@ func postTsp(w http.ResponseWriter, r *http.Request) {
...
@@ -83,7 +83,7 @@ func postTsp(w http.ResponseWriter, r *http.Request) {
// Response
// Response
w
.
WriteHeader
(
http
.
StatusOK
)
w
.
WriteHeader
(
http
.
StatusOK
)
json
.
NewEncoder
(
w
)
.
Encode
(
sol
.
String
())
json
.
NewEncoder
(
w
)
.
Encode
(
sol
.
String
Full
())
}
}
// ------------------------------------
// ------------------------------------
...
...
tspreader/tspreader.go
View file @
fd029285
// =======================================================
// =======================================================
// read tsp
d
ata saved in
d
ata format of
// read tsp
D
ata saved in
D
ata format of
// Gerhard Reinelt
// Gerhard Reinelt
// Universität Heidelberg
// Universität Heidelberg
// Institut für Informatik
// Institut für Informatik
//
d
ata: http://comopt.ifi.uni-heidelberg.de/software/TSPLIB95/tsp/
//
D
ata: http://comopt.ifi.uni-heidelberg.de/software/TSPLIB95/tsp/
//
//
// Documentation: http://comopt.ifi.uni-heidelberg.de/software/TSPLIB95/tsp95.pdf
// Documentation: http://comopt.ifi.uni-heidelberg.de/software/TSPLIB95/tsp95.pdf
//
//
...
@@ -25,18 +25,18 @@ import (
...
@@ -25,18 +25,18 @@ import (
)
)
type
TspSpec
struct
{
type
TspSpec
struct
{
n
ame
string
N
ame
string
p
roblemType
string
P
roblemType
string
c
omment
string
C
omment
string
d
imension
int
D
imension
int
e
dgeWeightType
string
E
dgeWeightType
string
e
dgeWeightFormat
string
E
dgeWeightFormat
string
d
ata
*
TspData
D
ata
*
TspData
}
}
type
TspData
struct
{
type
TspData
struct
{
d
atatype
string
D
atatype
string
v
alues
*
[][]
float64
V
alues
*
[][]
float64
}
}
// NewTspSpec
// NewTspSpec
...
@@ -44,7 +44,7 @@ type TspData struct {
...
@@ -44,7 +44,7 @@ type TspData struct {
// Constructs empty TSP Specification
// Constructs empty TSP Specification
// ------------------------------------
// ------------------------------------
func
NewTspSpec
()
*
TspSpec
{
func
NewTspSpec
()
*
TspSpec
{
return
&
TspSpec
{
n
ame
:
""
,
p
roblemType
:
"TSP"
,
c
omment
:
""
,
d
imension
:
0
,
e
dgeWeightType
:
""
,
d
ata
:
NewTspData
()}
return
&
TspSpec
{
N
ame
:
""
,
P
roblemType
:
"TSP"
,
C
omment
:
""
,
D
imension
:
0
,
E
dgeWeightType
:
""
,
D
ata
:
NewTspData
()}
}
}
// NewTspData
// NewTspData
...
@@ -52,7 +52,7 @@ func NewTspSpec() *TspSpec {
...
@@ -52,7 +52,7 @@ func NewTspSpec() *TspSpec {
// Constructs empty TSP Specification Data
// Constructs empty TSP Specification Data
// ------------------------------------
// ------------------------------------
func
NewTspData
()
*
TspData
{
func
NewTspData
()
*
TspData
{
return
&
TspData
{
d
atatype
:
"EDGE_WEIGHT_SECTION"
,
v
alues
:
&
[][]
float64
{}}
return
&
TspData
{
D
atatype
:
"EDGE_WEIGHT_SECTION"
,
V
alues
:
&
[][]
float64
{}}
}
}
// String
// String
...
@@ -60,7 +60,7 @@ func NewTspData() *TspData {
...
@@ -60,7 +60,7 @@ func NewTspData() *TspData {
// Returns string representation of TSP Specification
// Returns string representation of TSP Specification
// ------------------------------------
// ------------------------------------
func
(
t
TspSpec
)
String
()
string
{
func
(
t
TspSpec
)
String
()
string
{
return
fmt
.
Sprintf
(
"%s [%s] - %s %s %d"
,
t
.
n
ame
,
t
.
p
roblemType
,
t
.
e
dgeWeightType
,
t
.
e
dgeWeightFormat
,
t
.
d
imension
)
return
fmt
.
Sprintf
(
"%s [%s] - %s %s %d"
,
t
.
N
ame
,
t
.
P
roblemType
,
t
.
E
dgeWeightType
,
t
.
E
dgeWeightFormat
,
t
.
D
imension
)
}
}
// String
// String
...
@@ -68,12 +68,12 @@ func (t TspSpec) String() string {
...
@@ -68,12 +68,12 @@ func (t TspSpec) String() string {
// Returns string representation of TSP Data
// Returns string representation of TSP Data
// ------------------------------------
// ------------------------------------
func
(
t
TspData
)
String
()
string
{
func
(
t
TspData
)
String
()
string
{
return
fmt
.
Sprintf
(
"Datatype: %s"
,
t
.
d
atatype
)
return
fmt
.
Sprintf
(
"Datatype: %s"
,
t
.
D
atatype
)
}
}
// Read
// Read
// ------------------------------------
// ------------------------------------
// Reads TSP
d
ata from .tsp file
// Reads TSP
D
ata from .tsp file
// ------------------------------------
// ------------------------------------
func
Read
(
path
string
)
(
*
TspSpec
,
error
)
{
func
Read
(
path
string
)
(
*
TspSpec
,
error
)
{
file
,
err
:=
os
.
Open
(
path
)
file
,
err
:=
os
.
Open
(
path
)
...
@@ -96,37 +96,37 @@ func Read(path string) (*TspSpec, error) {
...
@@ -96,37 +96,37 @@ func Read(path string) (*TspSpec, error) {
strs
:=
strings
.
Split
(
line
,
":"
)
strs
:=
strings
.
Split
(
line
,
":"
)
switch
strings
.
ReplaceAll
(
strs
[
0
],
" "
,
""
)
{
switch
strings
.
ReplaceAll
(
strs
[
0
],
" "
,
""
)
{
case
"NAME"
:
{
case
"NAME"
:
{
spec
.
n
ame
=
strings
.
ReplaceAll
(
strs
[
1
],
" "
,
""
)
spec
.
N
ame
=
strings
.
ReplaceAll
(
strs
[
1
],
" "
,
""
)
break
break
}
}
case
"TYPE"
:
{
case
"TYPE"
:
{
spec
.
p
roblemType
=
strings
.
ReplaceAll
(
strs
[
1
],
" "
,
""
)
spec
.
P
roblemType
=
strings
.
ReplaceAll
(
strs
[
1
],
" "
,
""
)
break
break
}
}
case
"COMMENT"
:
{
case
"COMMENT"
:
{
spec
.
c
omment
=
strings
.
ReplaceAll
(
strs
[
1
],
" "
,
""
)
spec
.
C
omment
=
strings
.
ReplaceAll
(
strs
[
1
],
" "
,
""
)
break
break
}
}
case
"DIMENSION"
:
{
case
"DIMENSION"
:
{
i
,
e
:=
strconv
.
ParseInt
(
strings
.
ReplaceAll
(
strs
[
1
],
" "
,
""
),
10
,
64
)
i
,
e
:=
strconv
.
ParseInt
(
strings
.
ReplaceAll
(
strs
[
1
],
" "
,
""
),
10
,
64
)
if
(
e
==
nil
)
{
if
(
e
==
nil
)
{
spec
.
d
imension
=
int
(
i
)
spec
.
D
imension
=
int
(
i
)
}
}
break
break
}
}
case
"EDGE_WEIGHT_TYPE"
:
{
case
"EDGE_WEIGHT_TYPE"
:
{
spec
.
e
dgeWeightType
=
strings
.
ReplaceAll
(
strs
[
1
],
" "
,
""
)
spec
.
E
dgeWeightType
=
strings
.
ReplaceAll
(
strs
[
1
],
" "
,
""
)
break
break
}
}
case
"EDGE_WEIGHT_FORMAT"
:
{
case
"EDGE_WEIGHT_FORMAT"
:
{
spec
.
e
dgeWeightFormat
=
strings
.
ReplaceAll
(
strs
[
1
],
" "
,
""
)
spec
.
E
dgeWeightFormat
=
strings
.
ReplaceAll
(
strs
[
1
],
" "
,
""
)
break
break
}
}
}
}
}
else
{
}
else
{
// Sace Data as Multi Dimensional Array
// Sace Data as Multi Dimensional Array
if
dataLine
==
-
1
{
if
dataLine
==
-
1
{
spec
.
d
ata
.
d
atatype
=
strings
.
ReplaceAll
(
line
,
" "
,
""
)
spec
.
D
ata
.
D
atatype
=
strings
.
ReplaceAll
(
line
,
" "
,
""
)
dataLine
++
dataLine
++
}
else
{
}
else
{
entries
:=
strings
.
Split
(
line
,
" "
)
entries
:=
strings
.
Split
(
line
,
" "
)
...
@@ -146,9 +146,9 @@ func Read(path string) (*TspSpec, error) {
...
@@ -146,9 +146,9 @@ func Read(path string) (*TspSpec, error) {
}
}
}
}
spec
.
d
ata
.
v
alues
=
&
arr
spec
.
D
ata
.
V
alues
=
&
arr
if
spec
.
d
ata
.
d
atatype
!=
"EDGE_WEIGHT_SECTION"
{
if
spec
.
D
ata
.
D
atatype
!=
"EDGE_WEIGHT_SECTION"
{
cordToMatrix
(
spec
)
cordToMatrix
(
spec
)
}
}
...
@@ -157,11 +157,11 @@ func Read(path string) (*TspSpec, error) {
...
@@ -157,11 +157,11 @@ func Read(path string) (*TspSpec, error) {
}
}
func
cordToMatrix
(
spec
*
TspSpec
)
{
func
cordToMatrix
(
spec
*
TspSpec
)
{
arr
:=
*
spec
.
d
ata
.
v
alues
arr
:=
*
spec
.
D
ata
.
V
alues
outarr
:=
[][]
float64
{}
outarr
:=
[][]
float64
{}
switch
spec
.
e
dgeWeightType
{
switch
spec
.
E
dgeWeightType
{
case
"EUC_
3
D"
:
{
case
"EUC_
2
D"
:
{
// entries in euclidean 3d space in form of [index, lat, long]
// entries in euclidean 3d space in form of [index, lat, long]
// distance calculation for points p1 to p2 with
// distance calculation for points p1 to p2 with
// p1 = (x1, y1) and p2 = (x2, y2):
// p1 = (x1, y1) and p2 = (x2, y2):
...
@@ -176,7 +176,7 @@ func cordToMatrix(spec *TspSpec) {
...
@@ -176,7 +176,7 @@ func cordToMatrix(spec *TspSpec) {
break
break
}
}
case
"EUC_
2
D"
:
{
case
"EUC_
3
D"
:
{
// entries in euclidean 2d space in form of [index, lat, long]
// entries in euclidean 2d space in form of [index, lat, long]
// distance calculation for points p1 to p2 with
// distance calculation for points p1 to p2 with
// p1 = (x1, y1), p2 = (x2, y2) and p3 = (z1, z2):
// p1 = (x1, y1), p2 = (x2, y2) and p3 = (z1, z2):
...
@@ -192,8 +192,8 @@ func cordToMatrix(spec *TspSpec) {
...
@@ -192,8 +192,8 @@ func cordToMatrix(spec *TspSpec) {
}
}
}
}
spec
.
d
ata
.
v
alues
=
&
outarr
spec
.
D
ata
.
V
alues
=
&
outarr
spec
.
d
ata
.
d
atatype
=
"EDGE_WEIGHT_SECTION"
spec
.
D
ata
.
D
atatype
=
"EDGE_WEIGHT_SECTION"
spec
.
e
dgeWeightType
=
"EXPLICIT"
spec
.
E
dgeWeightType
=
"EXPLICIT"
spec
.
e
dgeWeightFormat
=
"FULL_MATRIX"
spec
.
E
dgeWeightFormat
=
"FULL_MATRIX"
}
}
tspsolver/tspsolver.go
View file @
fd029285
...
@@ -5,13 +5,19 @@
...
@@ -5,13 +5,19 @@
package
tspsolver
package
tspsolver
import
(
import
(
"errors"
"fmt"
"fmt"
"log"
"math"
"math/rand"
"pvs_tsp/tspreader"
"pvs_tsp/tspreader"
"time"
)
)
type
TspSolution
struct
{
type
TspSolution
struct
{
path
[]
int
path
[]
int
length
float64
length
float64
strategy
string
}
}
// NewTspSolution
// NewTspSolution
...
@@ -19,7 +25,7 @@ type TspSolution struct {
...
@@ -19,7 +25,7 @@ type TspSolution struct {
// Constructs empty TSP Solution
// Constructs empty TSP Solution
// ------------------------------------
// ------------------------------------
func
NewTspSolution
()
TspSolution
{
func
NewTspSolution
()
TspSolution
{
return
TspSolution
{
path
:
[]
int
{},
length
:
0
}
return
TspSolution
{
path
:
[]
int
{},
length
:
0
,
strategy
:
""
}
}
}
// String
// String
...
@@ -35,9 +41,10 @@ func (t TspSolution) String() string {
...
@@ -35,9 +41,10 @@ func (t TspSolution) String() string {
// returns full string representation of solution
// returns full string representation of solution
// ------------------------------------
// ------------------------------------
func
(
t
TspSolution
)
StringFull
()
string
{
func
(
t
TspSolution
)
StringFull
()
string
{
return
fmt
.
Sprintf
(
"solution - length: %f path:
%+q"
,
t
.
length
,
t
.
path
)
return
fmt
.
Sprintf
(
"solution - length: %f path:
[%d, %d, ... %d] strategy: %s"
,
t
.
length
,
t
.
path
[
0
],
t
.
path
[
1
],
t
.
path
[
len
(
t
.
path
)
-
1
],
t
.
strategy
)
}
}
// Solve
// Solve
// ------------------------------------
// ------------------------------------
// solve TSP
// solve TSP
...
@@ -45,5 +52,159 @@ func (t TspSolution) StringFull() string {
...
@@ -45,5 +52,159 @@ func (t TspSolution) StringFull() string {
func
Solve
(
spec
tspreader
.
TspSpec
)
TspSolution
{
func
Solve
(
spec
tspreader
.
TspSpec
)
TspSolution
{
// do tsp magic here
// do tsp magic here
return
NewTspSolution
()
// strategies:
// - Random
// - Nearest Neighbor
// - Ant Colony Optimization
solrand
:=
SolveRandom
(
spec
,
1000000
)
solnear
:=
SolveNearest
(
spec
)
log
.
Println
(
"done"
)
if
solrand
.
length
<
solnear
.
length
{
return
solrand
}
else
{
return
solnear
}
}
// SolveRandom
// ------------------------------------
// solve TSP
// ------------------------------------
func
SolveRandom
(
spec
tspreader
.
TspSpec
,
turns
int
)
TspSolution
{
bestsol
:=
TspSolution
{[]
int
{},
math
.
MaxFloat64
,
""
}
for
turn
:=
0
;
turn
<
turns
;
turn
++
{
sol
:=
NewTspSolution
()
sol
.
strategy
=
"Random"
var
locs
[]
int
for
i
:=
0
;
i
<
spec
.
Dimension
;
i
++
{
locs
=
append
(
locs
,
i
)
}
// select random start
rand
.
Seed
(
time
.
Now
()
.
Unix
())
n
:=
rand
.
Int
()
%
len
(
locs
)
node
:=
locs
[
n
];
sol
.
path
=
append
(
sol
.
path
,
node
)
locs
=
removeCopy
(
locs
,
n
)
// until all node are taken
for
len
(
sol
.
path
)
<
spec
.
Dimension
{
dists
:=
(
*
spec
.
Data
.
Values
)[
node
]
n
:=
rand
.
Int
()
%
len
(
locs
)
node
=
locs
[
n
]
index
:=
indexOf
(
locs
,
node
)
dist
:=
dists
[
node
]
sol
.
path
=
append
(
sol
.
path
,
node
)
sol
.
length
=
sol
.
length
+
dist
locs
=
removeElementCopy
(
locs
,
index
)
}
if
sol
.
length
<
bestsol
.
length
{
bestsol
=
sol
}
log
.
Println
(
bestsol
.
length
)
}
return
bestsol
}
// SolveNearest
// ------------------------------------
// solve TSP
// ------------------------------------
func
SolveNearest
(
spec
tspreader
.
TspSpec
)
TspSolution
{
bestsol
:=
TspSolution
{[]
int
{},
math
.
MaxFloat64
,
""
}
for
turn
:=
0
;
turn
<
spec
.
Dimension
;
turn
++
{
sol
:=
NewTspSolution
()
sol
.
strategy
=
"NearestNeighbor"
var
locs
[]
int
for
i
:=
0
;
i
<
spec
.
Dimension
;
i
++
{
locs
=
append
(
locs
,
i
)
}
// start at 0
n
:=
turn
node
:=
locs
[
n
];
sol
.
path
=
append
(
sol
.
path
,
node
)
locs
=
removeCopy
(
locs
,
n
)
// until all node are taken
for
len
(
sol
.
path
)
<
spec
.
Dimension
{
dists
:=
(
*
spec
.
Data
.
Values
)[
node
]
var
err
error
var
dist
float64
node
,
dist
,
err
=
minNotZero
(
dists
,
locs
)
if
err
!=
nil
{
panic
(
err
)
}
sol
.
path
=
append
(
sol
.
path
,
node
)
sol
.
length
=
sol
.
length
+
dist
index
:=
indexOf
(
locs
,
node
)
locs
=
removeElementCopy
(
locs
,
index
)
}
if
sol
.
length
<
bestsol
.
length
{
bestsol
=
sol
}
log
.
Println
(
bestsol
.
length
)
}
return
bestsol
}
func
removeCopy
(
slice
[]
int
,
i
int
)
[]
int
{
copy
(
slice
[
i
:
],
slice
[
i
+
1
:
])
return
slice
[
:
len
(
slice
)
-
1
]
}
func
removeElementCopy
(
slice
[]
int
,
i
int
)
[]
int
{
copy
(
slice
[
i
:
],
slice
[
i
+
1
:
])
return
slice
[
:
len
(
slice
)
-
1
]
}
func
minNotZero
(
slice
[]
float64
,
locs
[]
int
)
(
int
,
float64
,
error
)
{
if
len
(
slice
)
==
0
{
return
0
,
0
,
errors
.
New
(
"slice is empty"
)
}
min
:=
math
.
MaxFloat64
minIndex
:=
-
1
for
i
,
e
:=
range
slice
{
if
indexOf
(
locs
,
i
)
>
-
1
{
if
e
<
min
&&
e
!=
0
{
min
=
e
minIndex
=
i
}
}
}
return
minIndex
,
min
,
nil
}
func
indexOf
(
slice
[]
int
,
item
int
)
int
{
for
i
,
_
:=
range
slice
{
if
slice
[
i
]
==
item
{
return
i
}
}
return
-
1
}
}
\ No newline at end of file
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment