123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- package gago
- import (
- "math"
- "math/rand"
- "sort"
- "strings"
- )
- // Individuals is a convenience type, methods that belong to an Individual can
- // be called declaratively.
- type Individuals []Individual
- // String representation of a slice of Individuals.
- func (indis Individuals) String() string {
- var str string
- for _, indi := range indis {
- str += indi.String() + "\n"
- }
- return strings.TrimSuffix(str, "\n")
- }
- // 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()))
- }
|