MaxHalford/eaopt

View on GitHub
mutation.go

Summary

Maintainability
A
0 mins
Test Coverage
package eaopt

import (
    "math/rand"
)

// Type specific mutations for slices

// MutNormalFloat64 modifies a float64 gene if a coin toss is under a defined
// mutation rate. The new gene value is a random value sampled from a normal
// distribution centered on the gene's current value and with a standard
// deviation proportional to the current value. It does so for each gene.
func MutNormalFloat64(genome []float64, rate float64, rng *rand.Rand) {
    for i := range genome {
        // Flip a coin and decide to mutate or not
        if rng.Float64() < rate {
            genome[i] += rng.NormFloat64() * genome[i]
        }
    }
}

// MutUniformString picks a gene at random and replaces it with a random from a
// provided corpus. It repeats this n times.
func MutUniformString(genome []string, corpus []string, n int, rng *rand.Rand) {
    for i := 0; i < n; i++ {
        var (
            element = corpus[rng.Intn(len(corpus))]
            pos     = rng.Intn(len(genome))
        )
        genome[pos] = element
    }
}

// Generic mutations for slices

// MutPermute permutes two genes at random n times.
func MutPermute(genome Slice, n int, rng *rand.Rand) {
    // Nothing to permute
    if genome.Len() <= 1 {
        return
    }
    for i := 0; i < n; i++ {
        // Choose two points on the genome
        var points = randomInts(2, 0, genome.Len(), rng)
        genome.Swap(points[0], points[1])
    }
}

// MutPermuteInt calls MutPermute on an int slice.
func MutPermuteInt(s []int, n int, rng *rand.Rand) {
    MutPermute(IntSlice(s), n, rng)
}

// MutPermuteFloat64 calls MutPermute on a float64 slice.
func MutPermuteFloat64(s []float64, n int, rng *rand.Rand) {
    MutPermute(Float64Slice(s), n, rng)
}

// MutPermuteString callsMutPermute on a string slice.
func MutPermuteString(s []string, n int, rng *rand.Rand) {
    MutPermute(StringSlice(s), n, rng)
}

// MutSplice splits a genome in 2 and glues the pieces back together in reverse
// order.
func MutSplice(genome Slice, rng *rand.Rand) {
    var (
        k    = rng.Intn(genome.Len()-1) + 1
        a, b = genome.Split(k)
    )
    genome.Replace(b.Append(a))
}

// MutSpliceInt calls MutSplice on an int slice.
func MutSpliceInt(s []int, rng *rand.Rand) {
    MutSplice(IntSlice(s), rng)
}

// MutSpliceFloat64 calls MutSplice on a float64 slice.
func MutSpliceFloat64(s []float64, rng *rand.Rand) {
    MutSplice(Float64Slice(s), rng)
}

// MutSpliceString calls MutSplice on a string slice.
func MutSpliceString(s []string, rng *rand.Rand) {
    MutSplice(StringSlice(s), rng)
}