Skip to content

Commit

Permalink
crossover: produces two children (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
khezen authored Mar 6, 2021
1 parent d06637e commit 17fff12
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 20 deletions.
2 changes: 1 addition & 1 deletion crosser.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ package evoli

// Crosser produces a new individual from two individuals. This operators provides convergence to a population.
type Crosser interface {
Cross(individual1, individual2 Individual) (Individual, error)
Cross(parent1, parent2 Individual) (child1, child2 Individual, err error)
}
16 changes: 10 additions & 6 deletions examplegnetic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,17 @@ func (m HMutater) Mutate(indiv evoli.Individual) (evoli.Individual, error) {
type HCrosser struct {
}

func (h HCrosser) Cross(indiv1, indiv2 evoli.Individual) (evoli.Individual, error) {
fIndiv1, _ := indiv1.(*HIndividual)
fIndiv2, _ := indiv2.(*HIndividual)
func (h HCrosser) Cross(parent1, parent2 evoli.Individual) (child1, child2 evoli.Individual, err error) {
fIndiv1, _ := parent1.(*HIndividual)
fIndiv2, _ := parent2.(*HIndividual)
w := 0.1 + 0.8*rand.Float64()
return &HIndividual{
x: []float64{(fIndiv1.x[0] + fIndiv2.x[0]) / 2, (fIndiv1.x[1] + fIndiv2.x[1]) / 2},
v: []float64{(fIndiv1.v[0] + fIndiv2.v[0]) / 2, (fIndiv1.v[1] + fIndiv2.v[1]) / 2},
}, nil
x: []float64{w*fIndiv1.x[0] + (1-w)*fIndiv2.x[0], w*fIndiv1.x[1] + (1-w)*fIndiv2.x[1]},
v: []float64{w*fIndiv1.v[0] + (1-w)*fIndiv2.v[0], w*fIndiv1.v[1] + (1-w)*fIndiv2.v[1]},
}, &HIndividual{
x: []float64{(1-w)*fIndiv1.x[0] + w*fIndiv2.x[0], (1-w)*fIndiv1.x[1] + w*fIndiv2.x[1]},
v: []float64{(1-w)*fIndiv1.v[0] + w*fIndiv2.v[0], (1-w)*fIndiv1.v[1] + w*fIndiv2.v[1]},
}, nil
}

type HEvaluater struct {
Expand Down
25 changes: 14 additions & 11 deletions genetic.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ func (g *genetic) Next() error {
if deads != nil {
deads.Close()
}
newBorns, err := g.crossovers(survivors)
offsprings, err := g.crossovers(survivors)
if err != nil {
return err
}
newBorns, err = g.mutations(newBorns)
offsprings, err = g.mutations(offsprings)
if err != nil {
return err
}
survivors.Add(newBorns.Slice()...)
survivors.Add(offsprings.Slice()...)
g.pop = survivors
return nil
}
Expand Down Expand Up @@ -88,15 +88,15 @@ func (g *genetic) evaluation(pop Population) error {

func (g *genetic) crossovers(pop Population) (Population, error) {
var (
newBorns = NewPopulation(pop.Cap() - pop.Len())
capacity = pop.Cap() - pop.Len()
offsprings = NewPopulation(capacity)
mut sync.Mutex
capacity = newBorns.Cap()
wg = sync.WaitGroup{}
bubbledErr error
)
for index := 0; index < capacity; index++ {
for index := 0; index < capacity; index += 2 {
wg.Add(1)
go func() {
go func(index int) {
defer wg.Done()
var i, j = rand.Intn(pop.Len()), rand.Intn(pop.Len())
if i == j {
Expand All @@ -108,21 +108,24 @@ func (g *genetic) crossovers(pop Population) (Population, error) {
}
}
indiv1, indiv2 := pop.Get(i), pop.Get(j)
newBorn, err := g.crosser.Cross(indiv1, indiv2)
child1, child2, err := g.crosser.Cross(indiv1, indiv2)
if err != nil {
bubbledErr = err
return
}
mut.Lock()
newBorns.Add(newBorn)
offsprings.Add(child1)
if index+1 < capacity {
offsprings.Add(child2)
}
mut.Unlock()
}()
}(index)
}
wg.Wait()
if bubbledErr != nil {
return nil, bubbledErr
}
return newBorns, nil
return offsprings, nil
}

func (g *genetic) mutations(pop Population) (Population, error) {
Expand Down
9 changes: 7 additions & 2 deletions mock_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package evoli

import "math/rand"

type crosserMock struct {
}

func (c crosserMock) Cross(individual1, individual2 Individual) (Individual, error) {
return NewIndividual((individual1.Fitness() + individual2.Fitness()) / 2), nil
func (c crosserMock) Cross(parent1, parent2 Individual) (child1, child2 Individual, err error) {
w := 0.1 + 0.8*rand.Float64()
return NewIndividual(w*parent1.Fitness() + (1-w)*parent2.Fitness()),
NewIndividual((1-w)*parent1.Fitness() + w*parent2.Fitness()),
nil
}

type evaluaterMock struct {
Expand Down

0 comments on commit 17fff12

Please sign in to comment.