-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmutator_interval_base.go
121 lines (96 loc) · 3.44 KB
/
mutator_interval_base.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package genetic_algorithm
import (
"fmt"
"math/rand"
)
const (
mutatorInvertExactLen = 0
mutatorInvertPercentageLen = 1
)
// Base class for mutators that mutate some interval of genes
type MutatorIntervalBase struct {
MutatorIntervalBaseVirtualMInterface
probability float64
chromosomeConstructor EmptyChromosomeConstructor
kind int
fromExact int
toExact int
fromPercent float64
toPercent float64
temp GenesInterface
}
// MutatorIntervalBase's virtual methods
type MutatorIntervalBaseVirtualMInterface interface {
MutateGenes(genes GenesInterface, from, to int)
}
// Probability is applied to each chromosome
// By default interval will be equal one third of the chromosome
func NewMutatorIntervalBase(virtual MutatorIntervalBaseVirtualMInterface, probability float64, chromosomeConstructor EmptyChromosomeConstructor) *MutatorIntervalBase {
if probability > 1 || probability < 0 {
panic(fmt.Sprintf("Incorrect probability %v", probability))
}
mutator := new(MutatorIntervalBase)
mutator.MutatorIntervalBaseVirtualMInterface = virtual
mutator.probability = probability
mutator.chromosomeConstructor = chromosomeConstructor
mutator.kind = mutatorInvertPercentageLen
mutator.fromPercent = 0.33
mutator.toPercent = 0.33
return mutator
}
// Sets interval len to be randomly choosen from [from:to]
func (mutator *MutatorIntervalBase) ExactInterval(from, to int) *MutatorIntervalBase {
if from > to || from < 0 || to < 1 {
panic(fmt.Sprintf("Incorrect interval [%d:%d]", from, to))
}
mutator.kind = mutatorInvertExactLen
mutator.fromExact = from
mutator.toExact = to
return mutator
}
// Sets interval len to be randomly choosen from [from*chromLen : to*chromLen]
func (mutator *MutatorIntervalBase) PercentageInterval(from, to float64) *MutatorIntervalBase {
if from > to || from < 0 || to < 0 || from > 1 || to > 1 {
panic(fmt.Sprintf("Incorrect percentage interval [%v:%v]", from, to))
}
mutator.kind = mutatorInvertPercentageLen
mutator.fromPercent = from
mutator.toPercent = to
return mutator
}
func (mutator *MutatorIntervalBase) Mutate(population Chromosomes) {
for _, chrom := range population {
if mutator.probability < rand.Float64() {
continue
}
genesLen := chrom.Genes().Len()
intervalLen := mutator.getIntervalLen(genesLen)
if intervalLen == 0 || intervalLen == genesLen {
continue
}
from, to := mutator.getInterval(genesLen, intervalLen)
mutator.MutateGenes(chrom.Genes(), from, to)
}
}
func (mutator *MutatorIntervalBase) getIntervalLen(genesLen int) int {
if mutator.kind == mutatorInvertExactLen {
return rand.Intn(mutator.toExact-mutator.fromExact+1) + mutator.fromExact
}
percent := rand.Float64()*(mutator.toPercent-mutator.fromPercent) + mutator.fromPercent
return round(percent * float64(genesLen))
}
func (mutator *MutatorIntervalBase) getInterval(genesLen, intervalLen int) (int, int) {
if intervalLen > genesLen {
panic(fmt.Sprintf("Interval bigger than chromosome. %d > %d", intervalLen, genesLen))
}
firstPoint := rand.Intn(genesLen - intervalLen + 1)
return firstPoint, firstPoint + intervalLen
}
func (mutator *MutatorIntervalBase) getIntervalCopy(genes GenesInterface, from, to int) GenesInterface {
genesLen := genes.Len()
if mutator.temp == nil || mutator.temp.Len() != genesLen {
mutator.temp = mutator.chromosomeConstructor(genesLen).Genes()
}
mutator.temp.Copy(genes, from, from, to)
return mutator.temp
}