Skip to content

hstove/genetic

master
Switch branches/tags
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 

Genetic

A Golang library for running simple genetic algorithms.

Usage

Define a Type that adhears to the Chromosome interface.

type Chromosome interface {
  Fitness() int16
  Recombine(newPopulation chan<- Chromosome, chromosome Chromosome)
  Mutate() Chromosome
}

Here is an example implementation of a Chromosome. Given a goal string, a Chromosome's fitness is the 'distance' between it and the goal. A fitness of 0 is the best. Chromosomes are sorted by Fitness() ascending.

package main

import (
  "fmt"
  "math/rand"
  "time"
  "github.com/hstove/genetic"
)

const chars = "abcdefghijklmnopqrstuvwxyz"
const goal = "hankstoeverisabadgolangprogrammer"

// Chromosome Implementation
type RandomString struct {
  Member string
}

var memoizedFitness = make(map[string]int16)

func (this RandomString) String() (str string){
  return fmt.Sprintf("{Member: %s | Fitness: %d}", this.Member, this.Fitness())
}

func NewRandomString() *RandomString {
  member := ""
  for i := 0; i < len(goal); i++ {
    char := string(chars[rand.Intn(len(chars))])
    member += char
  }
  return &RandomString{Member: member}
}

func (r RandomString) Fitness() int16{
  if val, ok := memoizedFitness[r.Member]; ok {
    return val
  }
  fitness := int16(0)
  for i := 0; i < len(goal); i++ {
    difference := int16(goal[i]) - int16(r.Member[i])
    if difference < 0 {
      fitness += -1 * difference
    } else {
      fitness += difference
    }
  }
  fitness *= -1
  memoizedFitness[r.Member] = fitness
  return fitness
}

func (r RandomString) Recombine(newPopulation chan<- genetic.Chromosome, chromosome genetic.Chromosome) {
  var other *RandomString = chromosome.(*RandomString)
  length := len(goal)
  split := rand.Intn(length-1)
  newMember := string(r.Member[0:split])
  newMember += string(other.Member[split:length])
  newPopulation <- &RandomString{newMember}
}

func (r RandomString) Mutate() genetic.Chromosome {
  return NewRandomString()
}

Then, create a Population with a bunch of Chromosomes in it. Evolve() until satisfied.

func main(){
  rand.Seed(time.Now().UTC().UnixNano())
  popSize := genetic.MaxPopulation
  var population genetic.Population
  for i := 0; i < popSize; i++ {
    population = append(population, NewRandomString())
  }
  i := 0
  for {
    i++
    population = population.Evolve()
    fmt.Println(i, population.BestFit(), population[len(population) - 1], len(population))
    if population.BestFit().Fitness() == 0 {
      fmt.Println(fmt.Sprintf("Found Champion after %d Generations", i))
      break
    }
  }
}

This outputs:

1 {Member: bqlijpphlfphvaemfhheafmopgjiggmbd | Fitness: -158} {Member: ikeyyfwbbgofgxowbgkiqpndjulokndbb | Fitness: -270} 10000
2 {Member: bqlijpphlfphvaemfhheafmopglodkkfd | Fitness: -147} {Member: dtjltogkiyckpymtckirnoelxuizererw | Fitness: -249} 10000
3 {Member: iatqvxcfugtiojfaeuojflvpqvjuhoogs | Fitness: -122} {Member: wupvqtpdmbhjszsfgujlkdxlizbueqcdo | Fitness: -235} 10000
4 {Member: iatqvxcfugtiojfaeuojflvpqvjuhoogs | Fitness: -122} {Member: qlkyqwjosdpfsvjsrxdinsfoqsdglqidk | Fitness: -224} 10000
5 {Member: sfnvkslewcoizdlachmycmhxyqiocnsen | Fitness: -121} {Member: memlkzogvfhomqfesswnshfncojfhqdzn | Fitness: -213} 10000
6 {Member: iaogkslewcoizdlachmycmhxyqiocnstv | Fitness: -115} {Member: hggmrixdypzcrkmtiwudimgkmkjzksebt | Fitness: -204} 10000
7 {Member: iaogkslewcoizdlachmycmhxyqiocnstv | Fitness: -115} {Member: qgmjorcyzjvppedghqeflgitrqdmhqvvv | Fitness: -195} 10000
8 {Member: iaogkslewcoizdlachmycmhxyqiocnmiv | Fitness: -98} {Member: dtnhvjsgsavjdfxcdaeipnxqpzgobckht | Fitness: -187} 10000
9 {Member: iaogkslewcoizdlachmycmhxyqiocnmiv | Fitness: -98} {Member: tqvnsrrhshpmyohcocgkmkagomdwenuop | Fitness: -179} 10000
...
60 {Member: hamkssoewerisabadgolangqrogrammer | Fitness: -4} {Member: hamkstnevfrjrabadgolangotnhqammer | Fitness: -11} 10000
61 {Member: hankstoeverisabacgolangqrogrammdr | Fitness: -3} {Member: hamkstogvfrjtabacgolangorogrammds | Fitness: -10} 10000
62 {Member: hankstodwerisabadgolangqrogrammer | Fitness: -3} {Member: hamkstodwerjrabacgolangorogrammds | Fitness: -9} 10000
63 {Member: hankstoeterisabadgolangorogrammer | Fitness: -3} {Member: hamlruoeverjrabacgolangprogrammfr | Fitness: -8} 10000
64 {Member: hankstoeverjsabadgolangqrogrammer | Fitness: -2} {Member: hamkstoexerjrabacgolangorpgrammer | Fitness: -8} 10000
65 {Member: hankstoeverhsabadgolangprogrammer | Fitness: -1} {Member: hankstoeteriqabacgolangoroframmer | Fitness: -7} 10000
66 {Member: hankstoeverhsabadgolangprogrammer | Fitness: -1} {Member: hankstneverjrabacholangqrogrammer | Fitness: -6} 10000
67 {Member: hankstoevfrisabadgolangprogrammer | Fitness: -1} {Member: hamkssoewerisabacholangorogrammer | Fitness: -6} 10000
68 {Member: hankstneverisabadgolangprogrammer | Fitness: -1} {Member: hamkstneverjrabadgolangqrogrammer | Fitness: -5} 10000
69 {Member: hankstoeverisabadgolangprogrammer | Fitness: 0} {Member: hankstoewerjsacacgolangorogrammer | Fitness: -5} 10000
Found Champion after 69 Generations

About

A genetic algorithm library in Go

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages