Skip to content

Commit

Permalink
Merge pull request #27 from tanghaibao/master
Browse files Browse the repository at this point in the history
[tanghaibao] Add support for CrossRate in models
  • Loading branch information
MaxHalford authored Jan 15, 2018
2 parents cd089b9 + 47df520 commit 1ce3f44
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 13 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -434,10 +434,11 @@ Alas you still have to implement the `Genome` interface. You can however provide
type Vector []float64

func (X Vector) Crossover(Y gago.Genome, rng *rand.Rand) (gago.Genome, gago.Genome) {
return X, Y.(Vector)
}
```

Or you can set `CrossRate: 0` when initializing the GA model.


**Why aren't my `Mutate` and `Crossover` methods modifying my `Genome`s?**

Expand Down
38 changes: 28 additions & 10 deletions models.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ import (
)

var (
errNilSelector = errors.New("Selector cannot be nil")
errInvalidMutRate = errors.New("MutRate should be between 0 and 1")
errNilSelector = errors.New("Selector cannot be nil")
errInvalidMutRate = errors.New("MutRate should be between 0 and 1")
errInvalidCrossRate = errors.New("CrossRate should be between 0 and 1")
)

// Two parents are selected from a pool of individuals, crossover is then
// applied to generate two offsprings. The selection and crossover process is
// repeated until n offsprings have been generated. If n is uneven then the
// second offspring of the last crossover is discarded.
func generateOffsprings(n int, indis Individuals, sel Selector, rng *rand.Rand) (Individuals, error) {
func generateOffsprings(n int, indis Individuals, sel Selector, crossRate float64, rng *rand.Rand) (Individuals, error) {
var (
offsprings = make(Individuals, n)
i = 0
Expand All @@ -27,7 +28,9 @@ func generateOffsprings(n int, indis Individuals, sel Selector, rng *rand.Rand)
return nil, err
}
// Generate 2 offsprings from the parents
selected[0].Crossover(selected[1], rng)
if rng.Float64() < crossRate {
selected[0].Crossover(selected[1], rng)
}
if i < len(offsprings) {
offsprings[i] = selected[0]
i++
Expand All @@ -50,8 +53,9 @@ type Model interface {

// ModGenerational implements the generational model.
type ModGenerational struct {
Selector Selector
MutRate float64
Selector Selector
MutRate float64
CrossRate float64
}

// Apply ModGenerational.
Expand All @@ -61,6 +65,7 @@ func (mod ModGenerational) Apply(pop *Population) error {
len(pop.Individuals),
pop.Individuals,
mod.Selector,
mod.CrossRate,
pop.RNG,
)
if err != nil {
Expand Down Expand Up @@ -90,14 +95,19 @@ func (mod ModGenerational) Validate() error {
if mod.MutRate < 0 || mod.MutRate > 1 {
return errInvalidMutRate
}
// Check the crossover rate
if mod.CrossRate < 0 || mod.CrossRate > 1 {
return errInvalidCrossRate
}
return nil
}

// ModSteadyState implements the steady state model.
type ModSteadyState struct {
Selector Selector
KeepBest bool
MutRate float64
Selector Selector
KeepBest bool
MutRate float64
CrossRate float64
}

// Apply ModSteadyState.
Expand All @@ -107,7 +117,9 @@ func (mod ModSteadyState) Apply(pop *Population) error {
return err
}
var offsprings = selected.Clone(pop.RNG)
offsprings[0].Crossover(offsprings[1], pop.RNG)
if pop.RNG.Float64() < mod.CrossRate {
offsprings[0].Crossover(offsprings[1], pop.RNG)
}
// Apply mutation to the offsprings
if mod.MutRate > 0 {
if pop.RNG.Float64() < mod.MutRate {
Expand Down Expand Up @@ -148,6 +160,10 @@ func (mod ModSteadyState) Validate() error {
if mod.MutRate < 0 || mod.MutRate > 1 {
return errInvalidMutRate
}
// Check the crossover rate
if mod.CrossRate < 0 || mod.CrossRate > 1 {
return errInvalidCrossRate
}
return nil
}

Expand All @@ -157,6 +173,7 @@ type ModDownToSize struct {
SelectorA Selector
SelectorB Selector
MutRate float64
CrossRate float64
}

// Apply ModDownToSize.
Expand All @@ -165,6 +182,7 @@ func (mod ModDownToSize) Apply(pop *Population) error {
mod.NOffsprings,
pop.Individuals,
mod.SelectorA,
mod.CrossRate,
pop.RNG,
)
if err != nil {
Expand Down
20 changes: 19 additions & 1 deletion models_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,20 @@ var (
Selector: SelTournament{1},
MutRate: 0.2,
},
ModGenerational{
Selector: SelTournament{1},
CrossRate: 0.7,
},
ModSteadyState{
Selector: SelTournament{1},
KeepBest: false,
MutRate: 0.2,
},
ModSteadyState{
Selector: SelTournament{1},
KeepBest: false,
CrossRate: 0.7,
},
ModSteadyState{
Selector: SelTournament{1},
KeepBest: true,
Expand Down Expand Up @@ -59,6 +68,10 @@ var (
Selector: SelTournament{1},
MutRate: -1,
},
ModGenerational{
Selector: SelTournament{1},
CrossRate: -1,
},
ModSteadyState{
Selector: nil,
KeepBest: false,
Expand All @@ -74,6 +87,11 @@ var (
KeepBest: true,
MutRate: -1,
},
ModSteadyState{
Selector: SelTournament{1},
KeepBest: true,
CrossRate: -1,
},
ModDownToSize{
NOffsprings: -1,
SelectorA: SelTournament{1},
Expand Down Expand Up @@ -163,7 +181,7 @@ func TestGenerateOffsprings(t *testing.T) {
indis = newIndividuals(20, NewVector, rng)
)
for _, n := range []int{0, 1, 3, 10} {
var offsprings, _ = generateOffsprings(n, indis, SelTournament{1}, rng)
var offsprings, _ = generateOffsprings(n, indis, SelTournament{1}, 1.0, rng)
if len(offsprings) != n {
t.Error("GenerateOffsprings didn't produce the expected number of offsprings")
}
Expand Down
3 changes: 2 additions & 1 deletion presets.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ func Generational(NewGenome NewGenome) GA {
Selector: SelTournament{
NContestants: 3,
},
MutRate: 0.5,
MutRate: 0.5,
CrossRate: 0.7,
},
}
}
Expand Down

0 comments on commit 1ce3f44

Please sign in to comment.