Skip to content

Commit

Permalink
Add parallel Genetic algorithm.
Browse files Browse the repository at this point in the history
Currenly very crude as it dosen't exchange genetic information between parallel procsses.
  • Loading branch information
thoj committed May 16, 2010
1 parent a593ae2 commit 4c74693
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 0 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ include $(GOROOT)/src/Make.$(GOARCH)
TARG=ga

GOFILES=ga.go \
ga_parallel.go \
selector.go \
mutator.go \
mutator_shift.go \
Expand Down
70 changes: 70 additions & 0 deletions example/floating_parallel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
Copyright 2009 Thomas Jager <[email protected]> All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
subset sum solver
*/
package main

import (
"math"
"fmt"
"rand"
"time"
"../_obj/ga"
)

var scores int

func ackley(g *ga.GAFloatGenome) float64 {
scores++
var sum1 float64 = 0.0
for _, c := range g.Gene {
sum1 += float64(c * c)
}
t1 := math.Exp(-0.2 * (math.Sqrt((1.0 / 5.0) * sum1)))
sum1 = 0.0
for _, c := range g.Gene {
sum1 += math.Cos(float64(2.0 * math.Pi * c))
}
t2 := math.Exp((1.0 / 5.0) * sum1)
return (20 + math.Exp(1) - 20*t1 - t2)
}

func rosenbrock(g *ga.GAFloatGenome) float64 {
scores++
var sum float64
for i := 1; i < len(g.Gene); i++ {
sum += 100.0*math.Pow(math.Pow(g.Gene[i]-g.Gene[i-1], 2), 2) + math.Pow(1-g.Gene[i-1], 2)
}
return sum
}


func main() {
rand.Seed(time.Nanoseconds())

param := ga.GAParameter{
Initializer: new(ga.GARandomInitializer),
Selector: ga.NewGATournamentSelector(0.2, 5),
Breeder: new(ga.GA2PointBreeder),
Mutator: ga.NewGAGaussianMutator(0.4, 0),
PMutate: 0.5,
PBreed: 0.2}

// Second parameter is the number of Optimize Processes.
gao := ga.NewGAParallel(param, 4)

genome := ga.NewFloatGenome(make([]float64, 20), rosenbrock, 1, -1)

gao.Init(100, genome) //Total population

gao.OptimizeUntil(func(best ga.GAGenome) bool {
return best.Score() < 1e-3
})

best := gao.Best().(*ga.GAFloatGenome)
fmt.Printf("%s = %f\n", best, best.Score())
fmt.Printf("Calls to score = %d\n", scores)
}
78 changes: 78 additions & 0 deletions ga_parallel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
Copyright 2010 Thomas Jager <[email protected]> All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
Crude Parallel Genetic Algorithm
*/

package ga

import (
"fmt"
)

type GAParallel struct {
ga []*GA
Parameter GAParameter
numproc int
}

func NewGAParallel(parameter GAParameter, numproc int) *GAParallel {
gap := new(GAParallel)
gap.Parameter = parameter
gap.ga = make([]*GA, numproc)
gap.numproc = numproc
for i := 0; i < numproc; i++ {
gap.ga[i] = NewGA(parameter)
}
return gap
}

func (ga *GAParallel) String() string {
return fmt.Sprintf("Initializer = %s, Selector = %s, Mutator = %s Breeder = %s",
ga.Parameter.Initializer,
ga.Parameter.Selector,
ga.Parameter.Mutator,
ga.Parameter.Breeder)
}

func (ga *GAParallel) Init(popsize int, init GAGenome) {
for i := 0; i < ga.numproc; i++ {
ga.ga[i].Init(popsize, init)
}
}

func optimize_worker(ga *GA, gen int, c chan int) {
ga.Optimize(gen)
c <- 1
}

func (ga *GAParallel) Optimize(gen int) {
c := make(chan int, ga.numproc)
for i := 0; i < ga.numproc; i++ {
go optimize_worker(ga.ga[i], gen, c)
}
for i := 0; i < ga.numproc; i++ {
<-c
}
}


func (ga *GAParallel) OptimizeUntil(stop func(best GAGenome) bool) {
for !stop(ga.Best()) {
ga.Optimize(10)
}
}


func (ga *GAParallel) Best() GAGenome {
best := ga.ga[0].Best()
for i := 1; i < ga.numproc; i++ {
nbest := ga.ga[i].Best()
if nbest.Score() < best.Score() {
best = nbest
}
}
return best
}

0 comments on commit 4c74693

Please sign in to comment.