forked from meepen/neatevolve
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmutate.lua
More file actions
153 lines (126 loc) · 3.34 KB
/
Copy pathmutate.lua
File metadata and controls
153 lines (126 loc) · 3.34 KB
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
local exports = {}
package.loaded.mutate = exports
local linkMutate, pointMutate, randomNeuron, newGene, enableDisableMutate, copyGene
local function newInnovation(pool)
pool.innovation = pool.innovation + 1
return pool.innovation
end
exports.pointMutate = function(genome)
local step = genome.mutationRates["step"]
for i=1,#genome.genes do
local gene = genome.genes[i]
if math.random() < PerturbChance then
gene.weight = gene.weight + math.random() * step*2 - step
else
gene.weight = math.random()*4-2
end
end
end
local function containsLink(genes, link)
for i=1,#genes do
local gene = genes[i]
if gene.into == link.into and gene.out == link.out then
return true
end
end
end
exports.linkMutate = function(genome, forceBias, pool)
local neuron1 = randomNeuron(genome.genes, false)
local neuron2 = randomNeuron(genome.genes, true)
local newLink = newGene()
if neuron1 <= Inputs and neuron2 <= Inputs then
--Both input nodes
return
end
if neuron2 <= Inputs then
-- Swap output and input
neuron1, neuron2 = neuron2, neuron1
end
newLink.into = neuron1
newLink.out = neuron2
if forceBias then
newLink.into = Inputs
end
if containsLink(genome.genes, newLink) then
return
end
newLink.innovation = newInnovation(pool)
newLink.weight = math.random()*4-2
table.insert(genome.genes, newLink)
end
exports.nodeMutate = function(genome, pool)
if #genome.genes == 0 then
return
end
genome.maxneuron = genome.maxneuron + 1
local gene = genome.genes[math.random(1,#genome.genes)]
if not gene.enabled then
return
end
gene.enabled = false
local gene1 = copyGene(gene)
gene1.out = genome.maxneuron
gene1.weight = 1.0
gene1.innovation = newInnovation(pool)
gene1.enabled = true
table.insert(genome.genes, gene1)
local gene2 = copyGene(gene)
gene2.into = genome.maxneuron
gene2.innovation = newInnovation(pool)
gene2.enabled = true
table.insert(genome.genes, gene2)
end
exports.mutate = function(genome, pool)
for mutation,rate in pairs(genome.mutationRates) do
if math.random(1,2) == 1 then
genome.mutationRates[mutation] = 0.95*rate
else
genome.mutationRates[mutation] = 1.05263*rate
end
end
if math.random() < genome.mutationRates.connections then
pointMutate(genome)
end
local p = genome.mutationRates.link
while p > 0 do
if math.random() < p then
linkMutate(genome, false, pool)
end
p = p - 1
end
p = genome.mutationRates.bias
while p > 0 do
if math.random() < p then
linkMutate(genome, true, pool)
end
p = p - 1
end
p = genome.mutationRates.node
while p > 0 do
if math.random() < p then
exports.nodeMutate(genome, pool)
end
p = p - 1
end
p = genome.mutationRates.enable
while p > 0 do
if math.random() < p then
enableDisableMutate(genome, true)
end
p = p - 1
end
p = genome.mutationRates.disable
while p > 0 do
if math.random() < p then
enableDisableMutate(genome, false)
end
p = p - 1
end
end
linkMutate = exports.linkMutate
pointMutate = exports.pointMutate
randomNeuron = require "construct".randomNeuron
newGene = require "new".newGene
enableDisableMutate = require "construct".enableDisableMutate
copyGene = require "construct".copyGene
return exports