func TestLognormal(t *testing.T) { var s evo.Stats for i := 0; i < 65536; i++ { x := math.Log(real.Lognormal(1e-3)) s = s.Put(x) } mean := s.Mean() if mean < -1e-3 || 1e-3 < mean || math.IsNaN(mean) { t.Fail() } }
func TestBinaryTournament(t *testing.T) { var stats evo.Stats pop := dummies() for i := 0; i < 1e6; i++ { winner := sel.BinaryTournament(pop...).(dummy) stats = stats.Put(float64(winner)) } if stats.Mean() < 5.5 || 6.5 < stats.Mean() { t.Fail() } }
func TestMerge(t *testing.T) { var a, b evo.Stats for i := float64(0); i < 5; i++ { a = a.Put(i) } for i := float64(5); i < 10; i++ { b = b.Put(i) } stats := a.Merge(b) if stats.Mean() != 4.5 { t.Fail() } if stats.Var() != 8.25 { t.Fail() } }
// run implements the main goroutine. func run(pop Population, body evo.EvolveFn) { var ( // drives the main loop loop = make(chan struct{}, 1) // receives the results of evolutions nextgen = make(chan evo.Genome, len(pop.members)) // synchronizes pending evolutions pending sync.WaitGroup // used to access/mutate pop.members getter = make(chan int) setter = make(chan int) statsc = make(chan evo.Stats) ) for i := range pop.members { nextgen <- pop.members[i] } loop <- struct{}{} for { select { case <-loop: for i := range pop.members { pop.members[i] = <-nextgen } pending.Add(len(pop.members)) for i := range pop.members { val := pop.members[i] go func() { nextgen <- body(val, pop.members) pending.Done() }() } go func() { pending.Wait() loop <- struct{}{} }() case pop.getc <- getter: i := <-getter pop.valuec <- pop.members[i] case pop.setc <- setter: i := <-setter pop.members[i] = <-pop.valuec case pop.statsc <- statsc: var s evo.Stats for i := range pop.members { s = s.Put(pop.members[i].Fitness()) } statsc <- s case ch := <-pop.stopc: pending.Wait() for i := range pop.members { if subpop, ok := pop.members[i].(evo.Population); ok { subpop.Stop() } } ch <- struct{}{} pop.stopc <- ch return } } }