-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of https://github.com/rellermeyer/99tsp
- Loading branch information
Showing
14 changed files
with
975 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
all: | ||
go run main/run.go |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
} | ||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
Oops, something went wrong.