Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/rellermeyer/99tsp
Browse files Browse the repository at this point in the history
  • Loading branch information
Hari Sridhar committed Dec 6, 2016
2 parents 843044c + 1388181 commit da3f6cd
Show file tree
Hide file tree
Showing 14 changed files with 975 additions and 2 deletions.
2 changes: 2 additions & 0 deletions go/sa/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
all:
go run main/run.go
26 changes: 26 additions & 0 deletions go/sa/Node.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package tspsa

import (
"math"
"strconv"
)

type Node struct {
x int // x cord
y int // y cord
}

/*
* Calculate the Euclidean distance between the two nodes
* return the distance (float64)
*/
func (i *Node) GetEuDistance(j *Node) float64 {
return math.Sqrt(math.Pow(float64(i.x - j.x), 2) + math.Pow(float64(i.y - j.y), 2))
}

/*
* String function for Node
*/
func (i *Node) String() string {
return "NODE:\tX: " + strconv.FormatInt(int64(i.x), 10) + "\tY: " + strconv.FormatInt(int64(i.y), 10) + "\n"
}
19 changes: 18 additions & 1 deletion go/sa/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,18 @@
Spencer Bull: SA for TSP
# tspsa (Traveling Salesman Problem: Simulated Annealing)

## Description
Implementation of the Traveling Salesman Problem (TSP) using the Simulated Annealing (SA) Algorithm written in GO.

## Contributors
- Spencer Bull (bullapse) [sgb695]

## Usage
The following will return a path of Nodes in the shortest distance as a splice of Nodes ([]Node) containing *x* and *y* corridinates
- `RunSARandom(itterations (int), temperature (float64), Mintemp (float64), coolrate (float64), max x cordinate (int), max y cordinate (int), number of locations (int), verbose (bool))`
- TODO: `RunSAFromFile(itterations (int), temperature (float64), Mintemp (float64), coolrate (float64), filename (string))`

## Testing
- `go build; go test` will run a few tests in the `tspsa_test.go` file

#### Citation
- http://katrinaeg.com/simulated-annealing.html
58 changes: 58 additions & 0 deletions go/sa/Route.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package tspsa


type Route struct {
R []Node // Routes
D float64 // distance
}

/*
* Swap the Nodes in the Route for the given 2 positions
*
* n1: Node1 index
* n2: Node2 index
*/
func (r *Route) SwapNodes(n1 int, n2 int) {
t1 := r.R[n1]
t2 := r.R[n2]
r.R[n1] = t2
r.R[n2] = t1
}

/*
* Return the number of Nodes in the route
* return: (int)
*/
func (r *Route) Nodes() int {
return len(r.R)
}

/*
* Calculate the total route distance for the traveling salesman and return the float value
* return: Route Distance (float64)
*/
func (r *Route) CalcDistance() float64 {
td := 0.0
for i := 0; i < r.Nodes(); i++ {
s := r.R[i]
var e Node
if i+1 < r.Nodes() {
e = r.R[i+1]
} else {
e = r.R[0]
}
td += s.GetEuDistance(&e)
}
r.D = td
return r.D
}
/*
* String function for the Route Struct
*/
func (r *Route) String() string {
t := ""
for i := 0; i < r.Nodes(); i++ {
t += r.R[i].String()
}
return t
}
123 changes: 123 additions & 0 deletions go/sa/SA.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package tspsa

import (
"math/rand"
"math"
"fmt"
"io/ioutil"
"strings"
"strconv"
)

/*
* Wrapper to call SA with random points
* it: Itterations
* t: temp
* tmin: Min Temp
* c: coolrate
* x: Number of x coordinates
* y: Number of y coordinates
* p: Number of Points
* v: Verbose
*/
func RunSARandom(it int, t float64, tmin float64, c float64, x int, y int, p int, v bool) Route {
return RunSA(it, t, tmin, c, CreateRandomMAP(x, y, p), v)
}

/* TODO
* Run Simmulated Annealing Algorithm from a given XML file
*/
func RunSAFromFile(it int, t float64, tmin float64, c float64, f string, v bool) Route {
lines, err := readFile(f)
if err != nil {
fmt.Println(err.Error())
}
n := createNodesFromString(lines)
return RunSA(it, t, tmin, c, n, v)
}
/*
* l: splice of strings as lines in a file
*/
func createNodesFromString(lines []string) []Node {
var r []Node
for i := 0; i < len(lines); i++ {
l := strings.Fields(lines[i])
if len(l) == 3 {
x, err1 := strconv.Atoi(l[1])
y, err2 := strconv.Atoi(l[2])
if err1 == nil && err2 == nil {
n := Node{x, y}
r = append(r, n)
}
}
}
return r
}

/*
* File parsing
* f: filename
*/
func readFile(f string) ([]string, error) {
file, err := ioutil.ReadFile(f)
if err != nil {
return nil, err
}
return strings.Split(string(file), "\n"), nil
}

/*
* Run the SA algorithm with the given itterations, temp, min temp, coolrate, and a splice of Node objects
*
* i: Itterations
* t: temp
* tmin: temp min
* c: coolrate
*/
func RunSA(it int, t float64, tmin float64, c float64, n []Node, p bool) Route {
// Set the Routes for the current SA given the list of nodes
cur := Route{n, math.MaxFloat64}
cur.CalcDistance() // old cost
best := Route{n, math.MaxFloat64}
next := Route{n, math.MaxFloat64}
l := cur.Nodes() // Length
for t > tmin {
for i := 0; i < it; i++ {
next.SwapNodes(rand.Intn(l), rand.Intn(l))
next.CalcDistance()
if acceptProb(cur.D, next.D, t) >= 0.5 {
cur.R = next.R
cur.D = next.D
}
if (cur.D < best.D) {
best.R = cur.R
best.D = cur.D
}
}
t = t * c
}
if p {
fmt.Println(best.String())
fmt.Printf("Distance: %.6f\n", best.D)
}
return best
}

/*
* acceptance Probability Calculation
* This should return 1.0 if the new energy is greater than the current energy
* Else it will return the acceptance Probability
*/
func acceptProb(e float64, ne float64, t float64) float64 {
if ne > e {
return 1
} else {
// acceptance probability
return math.Exp((e - ne) / t)
}
}





21 changes: 21 additions & 0 deletions go/sa/TSPManager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package tspsa

import (
"math/rand"
)

/*
* Create a random map for the TSP problem
* Modifies the map in the subsequent given TSPMAP struct
* x: Max x cord
* y: Max y cord
* p: Number of points
*/
func CreateRandomMAP(x int, y int, p int) []Node{
var r []Node
for i := 0; i < p; i++ {
n := Node{rand.Intn(x), rand.Intn(y)}
r = append(r, n)
}
return r
}
Loading

0 comments on commit da3f6cd

Please sign in to comment.