Skip to content

Instantly share code, notes, and snippets.

@EdgeCaseBerg
Created May 20, 2014 12:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EdgeCaseBerg/9c535f1cd71f2c2a8012 to your computer and use it in GitHub Desktop.
Save EdgeCaseBerg/9c535f1cd71f2c2a8012 to your computer and use it in GitHub Desktop.
Implementation of a Simple Binary Genome hill climber. The fitness is determined simply by how many 1's are turned on in the genome of the child. So a perfect fitness is 100.
package main
import (
"fmt"
"math/rand"
"time"
"runtime"
)
/* HillClimber
* By Ethan J Eldridge.
* Keep the population size great than 25 or you might have issues.
*/
var populationSize int; //How many there are
var genomeSize int; //How big their genome is
var generations int; //How many generations to run
type Child struct{
genome []int
resultChan chan int
fitness int
}
func (c* Child) init(resChan * chan int) {
c.resultChan = *resChan
c.genome = make([]int, genomeSize)
initilizeChannel := make(chan int, genomeSize)
for i := 0; i < genomeSize; i++ {
i := i //overshadow local
go func(){
c.genome[i] = rand.Intn(2)
initilizeChannel <- c.genome[i]
}()
}
//Compute initial fitness from initalization
c.fitness = 0
for i := 0; i < genomeSize; i++ {
c.fitness += <- initilizeChannel
}
}
func (c* Child) CopyTo(o * Child){
o.genome = c.genome
o.fitness = c.fitness
o.resultChan = c.resultChan
}
func (c* Child) Mutate() {
doneChannel := make(chan int, genomeSize)
for i := 0; i < genomeSize; i++ {
i := i
go func(){
if rand.Intn(2) == 1 {
c.genome[i] = rand.Intn(2)
}
doneChannel <- c.genome[i]
}()
}
c.fitness = 0
for i := 0; i < genomeSize; i++ {
c.fitness += <- doneChannel
}
//Send fitness out
c.resultChan <- c.fitness
}
func main() {
fmt.Printf("Simple HillClimber by Ethan J Eldridge\n SettingUsing %v CPU's\n", runtime.NumCPU())
runtime.GOMAXPROCS(runtime.NumCPU()) //use all the cpus!
populationSize = 100
genomeSize = 100
generations = 50
rand.Seed(time.Now().Unix())
children := make([]Child, populationSize)
resultsChan := make(chan int, populationSize)
fmt.Printf(" Initializing Population...\n")
for i := 0; i < populationSize; i++ {
i := i
go func(){
children[i].init(&resultsChan)
resultsChan <- children[i].fitness
}()
}
bestFitness := 0
bestIdx := 0
for i := 0; i < populationSize; i++ {
r := <-resultsChan
if r > bestFitness {
bestIdx = i
bestFitness = r
}
}
fmt.Printf(" Population Ready, best child fitness: %v\n", bestFitness)
for i := 0; i < generations; i++ {
fmt.Printf(" Running Generation %v\n", i)
for j := 0; j < populationSize; j++ {
j := j
go func(){
children[j].Mutate()
}()
}
//Collect results of population mutation
for j := 0; j < populationSize; j++ {
tmpFitness := <- resultsChan
if tmpFitness > bestFitness {
bestFitness = tmpFitness
bestIdx = j
}
}
fmt.Printf(" Best Of Generation %v : Child: %v, fitness: %v\n", i, bestIdx,bestFitness)
//'Breed' new results from the best child
if bestIdx < populationSize/2 {
for i := bestIdx+1; i < bestIdx + 11; i++ {
children[bestIdx].CopyTo( &children[i] )
children[i].Mutate()
<- resultsChan //discard the mutated value
}
} else {
for i := bestIdx-11; i < bestIdx; i++ {
children[bestIdx].CopyTo( &children[i] )
children[i].Mutate()
<- resultsChan //discard the mutated value
}
}
}
fmt.Printf(" Overall Best: %v with %v fitness score\n", bestIdx, bestFitness)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment