HiveBrain v1.2.0
Get Started
← Back to all entries
patterngoMinor

Solving the travelling salesman problem using a genetic algorithm

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
problemsolvingthesalesmantravellinggeneticalgorithmusing

Problem

I've got a simple program written in Golang that takes a map as input and tries to solve the travelling salesman problem by using a genetic algorithm. My Crossover method is a real performance killer due to intense use of make() (allocate memory / will provoke the GC).

What I'd like to do - and yet failed to do is outsource the creation of newGenes. pCrossover and therefore the size of newGenes will be the same over all calls of the function, so I'd like to avoid creating that slice again and again.

I am also interested in any suggestions for improvements of my coding style in Golang and other performance improvements I can take a look at.

My source is at Github.

Here is an excerpt of the function I am trying to improve:

```
func (ts *TravellingSalesman) Crossover() {
// Crossover
var nCrossover = int(ts.pCrossover * float64(ts.nGenes))
var newGenes = make([]ga.Gene, nCrossover)
for i:=0; i take m
if existN && !existM {
newGenes[i].Data[k] = nextM
currentCity = nextM
} else if !existN && existM {
newGenes[i].Data[k] = nextN
currentCity = nextN
} else if existN && existM {
nextRandom := findNextRandomCity(newGenes[i].Data[0:k], &(ts.genes[n].Data))
newGenes[i].Data[k] = nextRandom
currentCity = nextRandom
} else {
// If both didn't exist, take the shorter one
distN := ts.distMatrix.GetDistance(currentCity-1, nextN-1)
distM := ts.distMatrix.GetDistance(currentCity-1, nextM-1)

// Take the shorter route
if distN < distM {
newGenes[i].Data[k] = nextN
currentCity = nextN
} else {
newGenes[i].Data[k] = nextM
currentCity = nextM
}
}
}
}

copy(ts.ge

Solution

How about using a slice for Gene.Data?

You just allocate

var allData := make([]int, nCrossover * ts.geneLength)


before entering the for loop and assign

newGenes[i].Data = allData[i * ts.geneLength: (i + 1) * ts.geneLength]


You'd cut down on the amount of allocations (and system calls) without changing much else (except findNextCity and isInArray - but they should be written to accept slices instead of array pointers anyway).

And you'd follow the advice given by the languages creators in Effective Go.

Code Snippets

var allData := make([]int, nCrossover * ts.geneLength)
newGenes[i].Data = allData[i * ts.geneLength: (i + 1) * ts.geneLength]

Context

StackExchange Code Review Q#6464, answer score: 2

Revisions (0)

No revisions yet.