forked from MaxHalford/eaopt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
individuals.go
107 lines (93 loc) · 2.88 KB
/
individuals.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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package gago
import (
"math"
"math/rand"
"sort"
)
// Individuals is a convenience type, methods that belong to an Individual can
// be called declaratively.
type Individuals []Individual
// Clone returns the same exact same slice of individuals but with different
// pointers and ID fields.
func (indis Individuals) Clone(rng *rand.Rand) Individuals {
var clones = make(Individuals, len(indis))
for i, indi := range indis {
clones[i] = indi.Clone(rng)
}
return clones
}
// Generate a slice of n new individuals.
func newIndividuals(n int, gf GenomeFactory, rng *rand.Rand) Individuals {
var indis = make(Individuals, n)
for i := range indis {
indis[i] = NewIndividual(gf(rng), rng)
}
return indis
}
// Evaluate each individual.
func (indis Individuals) Evaluate() {
for i := range indis {
indis[i].Evaluate()
}
}
// Mutate each individual.
func (indis Individuals) Mutate(mutRate float64, rng *rand.Rand) {
for i := range indis {
if rng.Float64() < mutRate {
indis[i].Mutate(rng)
}
}
}
// SortByFitness ascendingly sorts individuals by fitness.
func (indis Individuals) SortByFitness() {
var less = func(i, j int) bool { return indis[i].Fitness < indis[j].Fitness }
sort.Slice(indis, less)
}
// IsSortedByFitness checks if individuals are ascendingly sorted by fitness.
func (indis Individuals) IsSortedByFitness() bool {
var less = func(i, j int) bool { return indis[i].Fitness < indis[j].Fitness }
return sort.SliceIsSorted(indis, less)
}
// SortByDistanceToMedoid sorts Individuals according to their distance to the
// medoid. The medoid is the Individual that has the lowest average distance to
// the rest of the Individuals.
func (indis Individuals) SortByDistanceToMedoid(dm DistanceMemoizer) {
var (
avgDists = calcAvgDistances(indis, dm)
less = func(i, j int) bool {
return avgDists[indis[i].ID] < avgDists[indis[j].ID]
}
)
sort.Slice(indis, less)
}
// Extract the fitness of a slice of individuals into a float64 slice.
func (indis Individuals) getFitnesses() []float64 {
var fitnesses = make([]float64, len(indis))
for i, indi := range indis {
fitnesses[i] = indi.Fitness
}
return fitnesses
}
// FitMin returns the best fitness of a slice of individuals.
func (indis Individuals) FitMin() float64 {
if indis.IsSortedByFitness() {
return indis[0].Fitness
}
return minFloat64s(indis.getFitnesses())
}
// FitMax returns the best fitness of a slice of individuals.
func (indis Individuals) FitMax() float64 {
if indis.IsSortedByFitness() {
return indis[len(indis)-1].Fitness
}
return maxFloat64s(indis.getFitnesses())
}
// FitAvg returns the average fitness of a slice of individuals.
func (indis Individuals) FitAvg() float64 {
return meanFloat64s(indis.getFitnesses())
}
// FitStd returns the standard deviation of the fitness of a slice of
// individuals.
func (indis Individuals) FitStd() float64 {
return math.Sqrt(varianceFloat64s(indis.getFitnesses()))
}