-
Notifications
You must be signed in to change notification settings - Fork 1
/
selector_roulette_wheel_cost_weighting.go
61 lines (46 loc) · 1.49 KB
/
selector_roulette_wheel_cost_weighting.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package genetic_algorithm
import (
log "github.com/cihub/seelog"
"math/rand"
)
// Selects individual with probability proportional to it fitness value.
// Warning! In order to use this selector cost value must be normalized, i.e. chromosome with cost=0 is the best solution.
type RouletteWheelCostWeightingSelector struct {
*SelectorBase
fitnessSum float64
}
func NewRouletteWheelCostWeightingSelector() *RouletteWheelCostWeightingSelector {
selector := new(RouletteWheelCostWeightingSelector)
selector.SelectorBase = NewSelectorBase(selector)
return selector
}
func (selector *RouletteWheelCostWeightingSelector) Prepare(population Chromosomes) {
log.Tracef("Preparing")
selector.SelectorBase.Prepare(population)
fitnessSum := 0.0
for i := 0; i < len(selector.population); i++ {
chrom := selector.population[i]
fitnessSum += selector.fitness(chrom.Cost())
}
selector.fitnessSum = fitnessSum
log.Tracef("Prepared fs=%f\n", selector.fitnessSum)
}
func (selector *RouletteWheelCostWeightingSelector) fitness(cost float64) float64 {
if cost < 0 {
panic("Can't calc fitness for negative cost")
}
return 1 / (cost + 1)
}
func (selector *RouletteWheelCostWeightingSelector) SelectInd() int {
rnd := rand.Float64() * selector.fitnessSum
sum := 0.0
for i := 0; i < len(selector.population); i++ {
chrom := selector.population[i]
sum += selector.fitness(chrom.Cost())
if rnd < sum {
log.Tracef("Found chrom %v, on %d", chrom, i)
return i
}
}
panic("Select can't select")
}