Skip to content

Commit 889809a

Browse files
committed
Fixed Mutate_RemoveSimpleNeuron
1 parent 5d26484 commit 889809a

8 files changed

Lines changed: 150 additions & 63 deletions

File tree

MultiNEAT/viz.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,12 @@ def AlmostEqual(a, b, margin):
3030
except:
3131
print('Install NumPy for visualization')
3232

33-
3433
try:
3534
import cv2
3635
cvnumpy_installed = True
3736
except:
3837
print ('Tip: install the OpenCV computer vision library (2.0+) with '
39-
'Python bindings')
40-
print (' to get convenient neural network visualization to NumPy '
41-
'arrays')
38+
'Python bindings to get convenient neural network visualization to NumPy arrays.')
4239
cvnumpy_installed = False
4340

4441
try:

src/Genome.cpp

Lines changed: 69 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2088,7 +2088,7 @@ namespace NEAT
20882088
// Helper functions for the pruning procedure
20892089

20902090
// Removes the link with the specified innovation ID
2091-
void Genome::RemoveLinkGene(int a_InnovID)
2091+
/*void Genome::RemoveLinkGene(int a_InnovID)
20922092
{
20932093
// for iterating through the genes
20942094
std::vector<LinkGene>::iterator t_curlink = m_LinkGenes.begin();
@@ -2104,6 +2104,21 @@ namespace NEAT
21042104
21052105
t_curlink++;
21062106
}
2107+
}*/
2108+
2109+
// this version uses a simple index
2110+
void Genome::RemoveLinkGene(int a_idx)
2111+
{
2112+
// for iterating through the genes
2113+
auto t_curlink = m_LinkGenes.begin();
2114+
if (a_idx > 0)
2115+
{
2116+
m_LinkGenes.erase(m_LinkGenes.begin() + a_idx);
2117+
}
2118+
else
2119+
{
2120+
m_LinkGenes.clear();
2121+
}
21072122
}
21082123

21092124

@@ -2113,22 +2128,31 @@ namespace NEAT
21132128
{
21142129
// the list of links connected to this neuron
21152130
std::vector<int> t_link_removal_queue;
2116-
2117-
// OK find all links connected to this neuron ID
2118-
for (unsigned int i = 0; i < NumLinks(); i++)
2131+
2132+
bool removed=false;
2133+
2134+
do
21192135
{
2120-
if ((m_LinkGenes[i].FromNeuronID() == a_ID) || (m_LinkGenes[i].ToNeuronID() == a_ID))
2136+
removed=false;
2137+
// Remove all links connected to this neuron ID
2138+
for (int i = 0; i < NumLinks(); i++)
21212139
{
2122-
// found one, add it
2123-
t_link_removal_queue.emplace_back(m_LinkGenes[i].InnovationID());
2140+
if ((m_LinkGenes[i].FromNeuronID() == a_ID) || (m_LinkGenes[i].ToNeuronID() == a_ID))
2141+
{
2142+
// found one, remove it
2143+
//t_link_removal_queue.emplace_back(i);//m_LinkGenes[i].InnovationID());
2144+
RemoveLinkGene(i);
2145+
removed=true;
2146+
break;
2147+
}
21242148
}
2125-
}
2149+
} while (removed);
21262150

21272151
// Now remove them
2128-
for (unsigned int i = 0; i < t_link_removal_queue.size(); i++)
2152+
/*for (unsigned int i = 0; i < t_link_removal_queue.size(); i++)
21292153
{
21302154
RemoveLinkGene(t_link_removal_queue[i]);
2131-
}
2155+
}*/
21322156

21332157
// Now is safe to remove the neuron
21342158
// find it first
@@ -2338,7 +2362,7 @@ namespace NEAT
23382362

23392363
// Replaces a hidden neuron having only one input and only one output with
23402364
// a direct link between them.
2341-
bool Genome::Mutate_RemoveSimpleNeuron(InnovationDatabase &a_Innovs, RNG &a_RNG)
2365+
bool Genome::Mutate_RemoveSimpleNeuron(InnovationDatabase &a_Innovs, const Parameters &a_Parameters, RNG &a_RNG)
23422366
{
23432367
// At least one hidden node must be present
23442368
if (NumNeurons() == (NumInputs() + NumOutputs()))
@@ -2411,29 +2435,39 @@ namespace NEAT
24112435
// a novel innovation?
24122436
if (t_innovid == -1)
24132437
{
2414-
// Add the innovation and the link gene
2415-
int t_newinnov = a_Innovs.AddLinkInnovation(m_LinkGenes[t_l1idx].FromNeuronID(),
2416-
m_LinkGenes[t_l2idx].ToNeuronID());
2417-
m_LinkGenes.emplace_back(
2418-
LinkGene(m_LinkGenes[t_l1idx].FromNeuronID(), m_LinkGenes[t_l2idx].ToNeuronID(), t_newinnov,
2419-
t_weight, false));
2420-
2421-
// Remove the neuron now
2438+
// Save the IDs for a while
2439+
int from = m_LinkGenes[t_l1idx].FromNeuronID();
2440+
int to = m_LinkGenes[t_l2idx].ToNeuronID();
2441+
2442+
// Remove the neuron and its links now
24222443
RemoveNeuronGene(m_NeuronGenes[t_neurons_to_delete[t_choice]].ID());
24232444

2445+
// Add the innovation and the link gene
2446+
int t_newinnov = a_Innovs.AddLinkInnovation(from, to);
2447+
LinkGene lg = LinkGene(from, to, t_newinnov, t_weight, false);
2448+
lg.InitTraits(a_Parameters.LinkTraits, a_RNG);
2449+
2450+
m_LinkGenes.emplace_back(lg);
2451+
24242452
// bye
24252453
return true;
24262454
}
2427-
// not a novel innovation
2455+
// not a novel innovation
24282456
else
24292457
{
2430-
// Add the link and remove the neuron
2431-
m_LinkGenes.emplace_back(
2432-
LinkGene(m_LinkGenes[t_l1idx].FromNeuronID(), m_LinkGenes[t_l2idx].ToNeuronID(), t_innovid,
2433-
t_weight, false));
2434-
2435-
// Remove the neuron now
2458+
// Save the IDs for a while
2459+
int from = m_LinkGenes[t_l1idx].FromNeuronID();
2460+
int to = m_LinkGenes[t_l2idx].ToNeuronID();
2461+
2462+
// Remove the neuron and its links now
24362463
RemoveNeuronGene(m_NeuronGenes[t_neurons_to_delete[t_choice]].ID());
2464+
2465+
// Add the link
2466+
LinkGene lg = LinkGene(from, to, t_innovid, t_weight, false);
2467+
lg.InitTraits(a_Parameters.LinkTraits, a_RNG);
2468+
m_LinkGenes.emplace_back(lg);
2469+
2470+
// TODO: Maybe inherit the traits from one of the links
24372471

24382472
// bye
24392473
return true;
@@ -2477,21 +2511,22 @@ namespace NEAT
24772511
{
24782512
if ((!t_severe_mutation) && (a_RNG.RandFloat() < a_Parameters.WeightMutationRate))
24792513
{
2480-
bool ontail = (i >= t_genometail);
2514+
bool ontail = false; //(i >= t_genometail);
24812515
double t_LinkGenesWeight = m_LinkGenes[i].GetWeight();
24822516

24832517
if (ontail || (a_RNG.RandFloat() < a_Parameters.WeightReplacementRate))
24842518
{
2485-
//t_LinkGenesWeight = a_RNG.RandFloatSigned() * a_Parameters.WeightReplacementMaxPower;
2486-
t_LinkGenesWeight = a_RNG.RandFloat();
2487-
Scale(t_LinkGenesWeight, 0, 1, a_Parameters.MinWeight, a_Parameters.MaxWeight);
2519+
t_LinkGenesWeight = a_RNG.RandFloatSigned() * a_Parameters.WeightReplacementMaxPower;
2520+
2521+
//t_LinkGenesWeight = a_RNG.RandFloat();
2522+
//Scale(t_LinkGenesWeight, 0.0, 1.0, a_Parameters.MinWeight, a_Parameters.MaxWeight);
24882523
}
24892524
else
24902525
{
24912526
t_LinkGenesWeight += a_RNG.RandFloatSigned() * a_Parameters.WeightMutationMaxPower;
2492-
Clamp(t_LinkGenesWeight, a_Parameters.MinWeight, a_Parameters.MaxWeight);
24932527
}
2494-
2528+
2529+
Clamp(t_LinkGenesWeight, a_Parameters.MinWeight, a_Parameters.MaxWeight);
24952530
m_LinkGenes[i].SetWeight(t_LinkGenesWeight);
24962531

24972532
did_mutate = true;
@@ -2501,7 +2536,7 @@ namespace NEAT
25012536
if (a_RNG.RandFloat() < a_Parameters.WeightMutationRate)
25022537
{
25032538
double t_LinkGenesWeight = a_RNG.RandFloat();
2504-
Scale(t_LinkGenesWeight, 0, 1, a_Parameters.MinWeight, a_Parameters.MaxWeight);
2539+
Scale(t_LinkGenesWeight, 0.0, 1.0, a_Parameters.MinWeight, a_Parameters.MaxWeight);
25052540
m_LinkGenes[i].SetWeight(t_LinkGenesWeight);
25062541

25072542
did_mutate = true;
@@ -2521,7 +2556,7 @@ namespace NEAT
25212556
{
25222557
double nf=0;
25232558
nf = a_RNG.RandFloat();
2524-
Scale(nf, 0, 1, a_Parameters.MinWeight, a_Parameters.MaxWeight);
2559+
Scale(nf, 0.0, 1.0, a_Parameters.MinWeight, a_Parameters.MaxWeight);
25252560
m_LinkGenes[i].SetWeight(nf);
25262561
}
25272562
}

src/Genome.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ namespace NEAT
527527

528528
// Removes a hidden neuron having only one input and only one output with
529529
// a direct link between them.
530-
bool Mutate_RemoveSimpleNeuron(InnovationDatabase &a_Innovs, RNG &a_RNG);
530+
bool Mutate_RemoveSimpleNeuron(InnovationDatabase &a_Innovs, const Parameters &a_Parameters, RNG &a_RNG);
531531

532532
// Perturbs the weights
533533
bool Mutate_LinkWeights(const Parameters &a_Parameters, RNG &a_RNG);

src/Main.cpp

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ int main()
7878
{
7979
Parameters params;
8080

81-
params.PopulationSize = 8;
81+
params.PopulationSize = 32;
8282
params.DynamicCompatibility = true;
8383
params.WeightDiffCoeff = 0.0;
8484
params.CompatTreshold = 3.0;
@@ -102,9 +102,9 @@ int main()
102102
params.MinWeight = -4;
103103
params.MaxWeight = 4;
104104

105-
params.MutateAddNeuronProb = 0.003;
106-
params.MutateAddLinkProb = 0.05;
107-
params.MutateRemLinkProb = 0.01;
105+
params.MutateAddNeuronProb = 0.1;
106+
params.MutateAddLinkProb = 0;//0.05;
107+
params.MutateRemLinkProb = 0;//0.01;
108108

109109
params.MinActivationA = 4.9;
110110
params.MaxActivationA = 4.9;
@@ -126,6 +126,7 @@ int main()
126126

127127
params.MutateNeuronTraitsProb = 0;//0.2;
128128
params.MutateLinkTraitsProb = 0;//0.2;
129+
params.MutateGenomeTraitsProb = 0;
129130

130131
params.ExcessCoeff = 1.2;
131132
params.DisjointCoeff = 1.2;
@@ -138,6 +139,17 @@ int main()
138139
params.ArchiveEnforcement = false;
139140

140141
params.CustomConstraints = constraints;
142+
143+
params.MinWeight = -12.0;
144+
params.MaxWeight = 12.0;
145+
params.MutateWeightsProb = 0.0;
146+
params.MutateWeightsSevereProb = 0.2;
147+
params.WeightMutationRate = 0.333;
148+
params.WeightMutationMaxPower = 3.0;
149+
params.WeightReplacementRate = 0.25;
150+
params.WeightReplacementMaxPower = 6.0;
151+
152+
params.MutateRemSimpleNeuronProb = 1.001;
141153

142154
TraitParameters tp1;
143155
tp1.m_ImportanceCoeff = 0.0;
@@ -219,15 +231,15 @@ int main()
219231
params.GenomeTraits["y"] = tps;
220232
params.NeuronTraits["z"] = tp3;
221233

222-
Genome s(0, 12,
234+
Genome s(0, 4,
223235
1,
224236
1,
225-
true,
237+
false,
226238
UNSIGNED_SIGMOID,
227239
UNSIGNED_SIGMOID,
228240
0,
229241
params,
230-
2, 3);
242+
0, 3);
231243

232244
Population pop(s, params, true, 1.0, time(0));
233245

@@ -251,7 +263,7 @@ int main()
251263
double bestf = -999999;
252264
Genome gx;
253265

254-
/* Genome* baby;
266+
Genome* baby;
255267
baby = pop.Tick(gx);
256268

257269
double f = xortest(*baby);
@@ -263,7 +275,7 @@ int main()
263275
if (f > bestf)
264276
{
265277
bestf = f;
266-
}*/
278+
}
267279

268280
/*for(unsigned int i=0; i < pop.m_Species.size(); i++)
269281
{
@@ -290,7 +302,7 @@ int main()
290302

291303
printf("Tick: %d, best fitness: %3.5f\n", k, bestf);
292304
printf("Species: %d CT: %3.3f\n", pop.m_Species.size(), pop.m_Parameters.CompatTreshold);
293-
pop.Epoch();
305+
//pop.Epoch();
294306
}
295307

296308
for(int i=0; i<100; i++)

src/Parameters.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,12 @@ namespace NEAT
246246

247247
// Maximum number of tries to find 2 neurons to add/remove a link
248248
LinkTries = 64;
249+
250+
// Maximum number of links in the genome (originals not counted). -1 is unlimited
251+
MaxLinks = -1;
252+
253+
// Maximum number of neurons in the genome (originals not counted). -1 is unlimited
254+
MaxNeurons = -1;
249255

250256
// Probability that a link mutation will be made recurrent
251257
RecurrentProb = 0.25;
@@ -372,9 +378,9 @@ namespace NEAT
372378

373379

374380
// Trait mutation probabilities
375-
MutateNeuronTraitsProb = 1.0;
376-
MutateLinkTraitsProb = 1.0;
377-
MutateGenomeTraitsProb = 1.0;
381+
MutateNeuronTraitsProb = 0.0;
382+
MutateLinkTraitsProb = 0.0;
383+
MutateGenomeTraitsProb = 0.0;
378384

379385

380386
/////////////////////////////
@@ -393,7 +399,7 @@ namespace NEAT
393399
ExcessCoeff = 1.0;
394400

395401
// Average weight difference importance
396-
WeightDiffCoeff = 0.5;
402+
WeightDiffCoeff = 0.0;
397403

398404
// Node-specific activation parameter A difference importance
399405
ActivationADiffCoeff = 0.0;
@@ -411,10 +417,10 @@ namespace NEAT
411417
ActivationFunctionDiffCoeff = 0.0;
412418

413419
// Compatibility treshold
414-
CompatTreshold = 5.0;
420+
CompatTreshold = 3.0;
415421

416422
// Minumal value of the compatibility treshold
417-
MinCompatTreshold = 0.1;
423+
MinCompatTreshold = 0.0;
418424

419425
// Modifier per generation for keeping the species stable
420426
CompatTresholdModifier = 0.1;
@@ -707,6 +713,11 @@ namespace NEAT
707713

708714
if (s == "LinkTries")
709715
a_DataFile >> LinkTries;
716+
717+
if (s == "MaxLinks")
718+
a_DataFile >> MaxLinks;
719+
if (s == "MaxNeurons")
720+
a_DataFile >> MaxNeurons;
710721

711722
if (s == "RecurrentProb")
712723
a_DataFile >> RecurrentProb;
@@ -1035,6 +1046,8 @@ namespace NEAT
10351046
fprintf(a_fstream, "MutateRemLinkProb %3.20f\n", MutateRemLinkProb);
10361047
fprintf(a_fstream, "MutateRemSimpleNeuronProb %3.20f\n", MutateRemSimpleNeuronProb);
10371048
fprintf(a_fstream, "LinkTries %d\n", LinkTries);
1049+
fprintf(a_fstream, "MaxLinks %d\n", MaxLinks);
1050+
fprintf(a_fstream, "MaxNeurons %d\n", MaxNeurons);
10381051
fprintf(a_fstream, "RecurrentProb %3.20f\n", RecurrentProb);
10391052
fprintf(a_fstream, "RecurrentLoopProb %3.20f\n", RecurrentLoopProb);
10401053
fprintf(a_fstream, "MutateWeightsProb %3.20f\n", MutateWeightsProb);

src/Parameters.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,13 @@ class Parameters
272272

273273
// Maximum number of tries to find 2 neurons to add/remove a link
274274
unsigned int LinkTries;
275-
275+
276+
// Maximum number of links in the genome (originals not counted). -1 is unlimited
277+
int MaxLinks;
278+
279+
// Maximum number of neurons in the genome (originals not counted). -1 is unlimited
280+
int MaxNeurons;
281+
276282
// Probability that a link mutation will be made recurrent
277283
double RecurrentProb;
278284

@@ -884,6 +890,8 @@ class Parameters
884890
ar & MutateRemLinkProb;
885891
ar & MutateRemSimpleNeuronProb;
886892
ar & LinkTries;
893+
ar & MaxLinks;
894+
ar & MaxNeurons;
887895
ar & RecurrentProb;
888896
ar & RecurrentLoopProb;
889897
ar & MutateWeightsProb;

0 commit comments

Comments
 (0)