-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathselector_roulette_wheel_rank_weighting.go
56 lines (43 loc) · 1.39 KB
/
selector_roulette_wheel_rank_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
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 RouletteWheelRankWeightingSelector struct {
*SelectorBase
weights []float64
}
func NewRouletteWheelRankWeightingSelector() *RouletteWheelRankWeightingSelector {
selector := new(RouletteWheelRankWeightingSelector)
selector.SelectorBase = NewSelectorBase(selector)
return selector
}
func (selector *RouletteWheelRankWeightingSelector) Prepare(population Chromosomes) {
log.Tracef("Preparing")
selector.SelectorBase.Prepare(population)
if selector.weights == nil || len(selector.weights) != len(population) {
selector.recalcWeights(len(population))
}
}
func (selector *RouletteWheelRankWeightingSelector) recalcWeights(n int) {
selector.weights = make([]float64, n)
sum := float64(n * (n + 1) / 2)
for i := 1; i <= n; i++ {
selector.weights[i-1] = float64(n+1-i) / sum
}
log.Tracef("Recalced weights %v\n", selector.weights)
}
func (selector *RouletteWheelRankWeightingSelector) SelectInd() int {
rnd := rand.Float64()
sum := 0.0
for i := 0; i < len(selector.population); i++ {
sum += selector.weights[i]
if rnd < sum {
log.Tracef("Found chrom on %d", i)
return i
}
}
panic("Select can't select")
}