Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Neural evolution algorithms implementation (CNE, NEAT, HyperNEAT) #686

Closed
wants to merge 72 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
dc27518
change .gitignore to ignore .DS_Store
BangLiu May 17, 2016
88788d6
create gene.hpp, add ne_test.cpp, and created or modified multiple CM…
BangLiu May 20, 2016
6ab9add
Created gene.happ, add tests and changed or created CMakeLists.txt
BangLiu May 20, 2016
ca73f95
Add aDepth to NeuronGene.
BangLiu May 20, 2016
30ec0ba
implement CNE, haven't finish.
BangLiu May 28, 2016
7fdd7ca
delete blank files
BangLiu May 28, 2016
e4fbabd
finished genome.hpp, revised gene.hpp
BangLiu Jun 7, 2016
3c8aa62
modified gene.hpp
BangLiu Jun 7, 2016
cbb79a2
implemented CNE skeleton; more genome and population functions.
BangLiu Jun 9, 2016
65f093d
implemented XOR test case; need debugging; one heart function -- CNE:…
BangLiu Jun 10, 2016
eb16ce2
solved most bugs for testing XOR
BangLiu Jun 11, 2016
c6976ac
further solved some bugs in code.
BangLiu Jun 11, 2016
8919bb9
Solved bugs. Need to fulfill Reproduce() to finish CNE.
BangLiu Jun 12, 2016
ee548b6
CNE algorithm finished. XOR test passes. Need to revise coding style …
BangLiu Jun 12, 2016
faf47a2
Create Species class.
BangLiu Jun 19, 2016
adc45b2
Revised LinkGene and related file for NEAT
BangLiu Jun 20, 2016
95c2e53
revised sortSpecies()
BangLiu Jun 21, 2016
1ee07a0
add aAdjustedFitness to genome
BangLiu Jun 21, 2016
39ef07b
fix bug in CNE Reproduce()
BangLiu Jun 21, 2016
74fb4a0
Implemented neat mutations, replace size_t by ssize_t
BangLiu Jun 24, 2016
d0883f4
Implemented crossover, some bug exist
BangLiu Jun 26, 2016
a605eef
Revise Crossover, solve bugs, more functions implementations.
BangLiu Jun 26, 2016
e059af0
revised neat functions. In paper,disabled links also consider for cro…
BangLiu Jun 27, 2016
6c11f32
neat almost finished. Need debugging,need revise coding style, need t…
BangLiu Jun 28, 2016
3c10995
NEAT finished, but has bugs. XOR not pass.
BangLiu Jun 29, 2016
57d4165
In progress of debugging. Add lots of printf ... Will clear them afte…
BangLiu Jun 30, 2016
6a770ec
seems bugs solved. keep printf. Seems information such as species siz…
BangLiu Jun 30, 2016
cce115b
solve more bugs
BangLiu Jun 30, 2016
2a9899c
solved more. But still have problem.
BangLiu Jun 30, 2016
1a2cfd8
solved CalcAverageRank bug. Still have more.
BangLiu Jun 30, 2016
dacc2e6
currently seems no bug. Previously we removed stale species even when…
BangLiu Jun 30, 2016
2a4c715
revised WeightDiff
BangLiu Jun 30, 2016
6f901a1
Removed redundant members in species, population. haven't remove in g…
BangLiu Jul 1, 2016
a80f5f7
Further cleaned some code.
BangLiu Jul 1, 2016
3db85fd
changed the place where we should set the childGenome's NumInput, Num…
BangLiu Jul 1, 2016
8168779
changed neuron_gene, genome's activation. Still need to revise neat.
BangLiu Jul 2, 2016
554a279
Revised MutateAddLink.
BangLiu Jul 2, 2016
1fe7d73
solved some bugs about activation.
BangLiu Jul 7, 2016
ff45785
Add Cart Pole test. Result not good. Fitness doesn't improve.
BangLiu Jul 10, 2016
48e15c4
Solved more bugs.
BangLiu Jul 13, 2016
fc982b9
Fixed a bug in task. Removed adjustFitness. Problems maybe the parame…
BangLiu Jul 16, 2016
66b0f41
further revised something.
BangLiu Jul 17, 2016
109f05b
Passed Cart Pole problem. Revised neat, task.
BangLiu Jul 20, 2016
8054f00
Implemented test MountainCar, not pass yet.
BangLiu Jul 21, 2016
5ef61fe
Seems passed Mountain Car.. in 1 iteration
BangLiu Jul 21, 2016
f213dd8
Revised a bug in TaskMountainCar Action()
BangLiu Jul 21, 2016
f234ebd
added Success() for tasks.
BangLiu Jul 21, 2016
96ccef5
Finished double pole. Non-Markov have bug.
BangLiu Aug 3, 2016
24f9baf
revised non-markov, still have bug
BangLiu Aug 3, 2016
4decb0e
revised neat MutateAddLink. Non-Markov still have bug.
BangLiu Aug 3, 2016
c46436e
revised neat, clean genome before evaluate.
BangLiu Aug 4, 2016
000d6aa
Merge pull request #1 from mlpack/master
BangLiu Aug 5, 2016
2599077
revised a bug in Activate()
BangLiu Aug 5, 2016
408b40f
fix conflict
BangLiu Aug 5, 2016
0fc792c
changed header file in ne_test
BangLiu Aug 5, 2016
847db95
solved compile bug
BangLiu Aug 5, 2016
10b99ab
change ssize_t, size_t to int. Windows doesn't support ssize_t
BangLiu Aug 6, 2016
da55507
revised comment style, bracket style etc. Have strange compile error.
BangLiu Aug 8, 2016
beb8ba8
rebuild, solved compile problem. Add default constructors back. Witho…
BangLiu Aug 8, 2016
3b66431
Revised the style of all current code
BangLiu Aug 10, 2016
9480379
revised some tiny styles
BangLiu Aug 11, 2016
4483fc8
Revised NeuronGene to add aCoordinate. Tests all previous testings an…
BangLiu Aug 13, 2016
190e639
Revised neat.hpp. NeuronInnovation considers activation function type…
BangLiu Aug 13, 2016
4cd0054
Implemented first version of Hyperneat.
BangLiu Aug 15, 2016
668fa6e
revised HyperNEAT. No inheritance.
BangLiu Aug 16, 2016
62d5885
Solved bugs. Implemented XOR test. Not pass. Need debug.
BangLiu Aug 16, 2016
e176571
in the progress of debugging XOR test
BangLiu Aug 18, 2016
dec32ac
Find important bug in Activate()! revised. Still not pass hyperneat xor.
BangLiu Aug 19, 2016
bc178c3
small change.
BangLiu Aug 19, 2016
432331b
Solved the duplicated link bug. Changed MutateAddNeuron. Still not pa…
BangLiu Aug 21, 2016
0944516
Make the new neuron type random when add new neuron. Still not pass xor.
BangLiu Aug 26, 2016
d66bb14
Revised naming style
BangLiu Aug 29, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 8 additions & 16 deletions src/mlpack/methods/ne/genome.hpp
Expand Up @@ -33,23 +33,26 @@ class Genome {
std::vector<LinkGene> aLinkGenes;

// Default constructor.
Genome() {}
Genome() {
aId = -1;
aNumInput = 0;
aNumOutput = 0;
aFitness = DBL_MAX;
}

// Parametric constructor.
Genome(ssize_t id,
const std::vector<NeuronGene>& neuronGenes,
const std::vector<LinkGene>& linkGenes,
ssize_t numInput,
ssize_t numOutput,
double fitness,
double adjustedFitness):
double fitness):
aId(id),
aNeuronGenes(neuronGenes),
aLinkGenes(linkGenes),
aNumInput(numInput),
aNumOutput(numOutput),
aFitness(fitness),
aAdjustedFitness(adjustedFitness)
aFitness(fitness)
{}

// Copy constructor.
Expand All @@ -60,7 +63,6 @@ class Genome {
aNumInput = genome.aNumInput;
aNumOutput = genome.aNumOutput;
aFitness = genome.aFitness;
aAdjustedFitness = genome.aAdjustedFitness;
}

// Destructor.
Expand All @@ -75,7 +77,6 @@ class Genome {
aNumInput = genome.aNumInput;
aNumOutput = genome.aNumOutput;
aFitness = genome.aFitness;
aAdjustedFitness = genome.aAdjustedFitness;
}

return *this;
Expand Down Expand Up @@ -105,12 +106,6 @@ class Genome {
// Get fitness.
double Fitness() const { return aFitness; }

// Set adjusted fitness.
void AdjustedFitness(double adjustedFitness) { aAdjustedFitness = adjustedFitness; }

// Get adjusted fitness.
double AdjustedFitness() const { return aAdjustedFitness; }

// Get neuron number.
ssize_t NumNeuron() const {
return aNeuronGenes.size();
Expand Down Expand Up @@ -330,9 +325,6 @@ class Genome {
// Genome fitness.
double aFitness;

// Genome adjusted fitness.
double aAdjustedFitness;

};

} // namespace ne
Expand Down
48 changes: 13 additions & 35 deletions src/mlpack/methods/ne/neat.hpp
Expand Up @@ -487,7 +487,6 @@ class NEAT {

Species newSpecies = Species();
newSpecies.AddGenome(genome);
newSpecies.Id(population.NextSpeciesId()); // NOTICE: changed species id.
newSpecies.StaleAge(0);
population.AddSpecies(newSpecies);
}
Expand All @@ -501,19 +500,6 @@ class NEAT {
}
}

// Set adjusted fitness.
// NOTICE: we assume fitness have already evaluated before adjust it.
void SetAdjustedFitness(Population& population) {
for (ssize_t i=0; i<population.aSpecies.size(); ++i) {
ssize_t speciesSize = population.aSpecies[i].aGenomes.size();
for (ssize_t j=0; j<speciesSize; ++j) {
double fitness = population.aSpecies[i].aGenomes[j].Fitness();
double adjustedFitness = fitness / speciesSize;
population.aSpecies[i].aGenomes[j].AdjustedFitness(adjustedFitness);
}
}
}

// Aggregate population's genomes.
void AggregateGenomes(Population& population, std::vector<Genome>& genomes) {
genomes.clear();
Expand All @@ -529,14 +515,6 @@ class NEAT {
std::sort(genomes.begin(), genomes.end(), Species::CompareGenome);
}

// SortGenomes by adjusted fitness. Smaller is better.
static bool CompareGenomeByAdjustedFitness(Genome lg, Genome rg) {
return (lg.AdjustedFitness() < rg.AdjustedFitness());
}
void SortGenomesByAdjustedFitness(std::vector<Genome>& genomes) {
std::sort(genomes.begin(), genomes.end(), CompareGenomeByAdjustedFitness);
}

// Get genome index in a genomes vector.
ssize_t GetGenomeIndex(std::vector<Genome>& genomes, ssize_t id) {
for (ssize_t i=0; i<genomes.size(); ++i) {
Expand All @@ -546,12 +524,11 @@ class NEAT {
return -1;
}

// Calculate species' average rank in population by adjusted fitness. Bigger is better.
// Calculate species' average rank in population by fitness. Bigger is better.
void CalcSpeciesAverageRank(Population& population, std::vector<double>& speciesAverageRank) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we have to use the fitness of the genomes to calculate the rank?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, but I am not clear what this means.
The average rank is the average of each genome's rank in this species. And
the rank of each genome is using the fitness of genome.

2016-07-16 16:10 GMT-06:00 Marcus Edel notifications@github.com:

In src/mlpack/methods/ne/neat.hpp
#686 (comment):

  • // Sort genomes by fitness. Smaller fitness is better and put first.
  • void SortGenomes(std::vector& genomes) {
  • std::sort(genomes.begin(), genomes.end(), Species::CompareGenome);
  • }
  • // Get genome index in a genomes vector.
  • ssize_t GetGenomeIndex(std::vector& genomes, ssize_t id) {
  • for (ssize_t i=0; i<genomes.size(); ++i) {
  •  if (genomes[i].Id() == id)
    
  •    return i;
    
  • }
  • return -1;
  • }
  • // Calculate species' average rank in population by fitness. Bigger is better.
  • void CalcSpeciesAverageRank(Population& population, std::vector& speciesAverageRank) {

Don't we have to use the fitness of the genomes to calculate the rank?


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/mlpack/mlpack/pull/686/files/fc982b9406838eb9697000481e816165702e8ba9#r71072586,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AD9tIVCQH5xIrGfVvpnSYirkncnnHtBGks5qWVbmgaJpZM4IwJa6
.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought it would be easier to rank the genomes, directly by the fitness value instead of checking at which position the genome is after sorting.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure, but after we sort with fitness, isn't the position is
exactly the rank of genomes?

2016-07-17 15:25 GMT-06:00 Marcus Edel notifications@github.com:

In src/mlpack/methods/ne/neat.hpp
#686 (comment):

  • // Sort genomes by fitness. Smaller fitness is better and put first.
  • void SortGenomes(std::vector& genomes) {
  • std::sort(genomes.begin(), genomes.end(), Species::CompareGenome);
  • }
  • // Get genome index in a genomes vector.
  • ssize_t GetGenomeIndex(std::vector& genomes, ssize_t id) {
  • for (ssize_t i=0; i<genomes.size(); ++i) {
  •  if (genomes[i].Id() == id)
    
  •    return i;
    
  • }
  • return -1;
  • }
  • // Calculate species' average rank in population by fitness. Bigger is better.
  • void CalcSpeciesAverageRank(Population& population, std::vector& speciesAverageRank) {

I thought it would be easier to rank the genomes, directly by the fitness
value instead of checking at which position the genome is after sorting.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/mlpack/mlpack/pull/686/files/fc982b9406838eb9697000481e816165702e8ba9#r71089856,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AD9tIW74f1sPpqVfwNsFlmqZzVJ1A1Niks5qWp3VgaJpZM4IwJa6
.

std::vector<Genome> genomes;
SetAdjustedFitness(population);
AggregateGenomes(population, genomes);
SortGenomesByAdjustedFitness(genomes); //!! we use adjusted fitness here for rank.
SortGenomes(genomes);
speciesAverageRank.clear();

for (ssize_t i=0; i<population.aSpecies.size(); ++i) {
Expand Down Expand Up @@ -698,22 +675,19 @@ class NEAT {
// keep best genome.
Genome lastBestGenome = aPopulation.BestGenome();

// Remove stale species.
if (aPopulation.aSpecies.size() > 10) {
RemoveStaleSpecies(aPopulation);
}

// Remove weak genomes in each species.
CullSpecies(aPopulation, aCullSpeciesPercentage);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, is this a technique to avoid local minima? Truncating each species by 50% sounds like an counterproductive idea. Maybe I missed a reference in the NEAT paper?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I referred to this implementation which seems performs good on Mario game:
http://pastebin.com/ZZmSNaHX
And truncating species by 50%, or by only one left are also come from this.
Actually I am now in the progress of reviewing other implementation ideas, such as the neat-python. The NEAT's implementation seems are all quite different for different packages. I am trying to come up with a progress which combines the goodness of different packages.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the information, maybe it's a good idea, but it sounds counterproductive to me. I think it should work without, since RemoveStaleSpecies should remove old species anyway.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My current plan is keep the functions, but when we do the Reproduce(), we need further decision about whether to use it. Organizing these steps in Reproduce() are flexible.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, since there is a parameter (aCullSpeciesPercentage) it's super easy to disable the function.


// Remove weak species.
// Remove stale species, weak species.
if (aPopulation.aSpecies.size() > 10) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for the number of stale species, we should also provide a parameter for the number of weak species.

RemoveStaleSpecies(aPopulation);
RemoveWeakSpecies(aPopulation);
}

// Breed children in each species.
std::vector<double> speciesAverageRank;
CalcSpeciesAverageRank(aPopulation, speciesAverageRank);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding https://groups.yahoo.com/neo/groups/neat/conversations/topics/2203 we don't use the adjusted fitness.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you mean, as we are calculation the average fitness of species, we doesn't need to use the adjustedFitness, because it likes we average it for twice, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think that's what Stanley is trying to explain.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I now removed all adjustedFitness, even in the genome class.


//DEBUGGING!!!!!!!!!
printf("Species average rank are: ");
for (ssize_t s=0; s<speciesAverageRank.size(); ++s) {
Expand All @@ -729,7 +703,7 @@ class NEAT {
ssize_t numBreed = std::floor(speciesAverageRank[i] * aPopulationSize / totalAverageRank) - 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the right position, I would go with offspring here.

ssize_t numBreedSuccess = 0;
while (numBreedSuccess < numBreed) {
Genome genome; //!!!!!!!!!!!!!
Genome genome;
bool hasBaby = BreedChild(aPopulation.aSpecies[i], genome, aCrossoverRate);
if (hasBaby) {
childGenomes.push_back(genome);
Expand All @@ -739,14 +713,17 @@ class NEAT {
}

// Keep the best in each species.

//DEBUGGING!!!!!!!!!
printf("before, species sizes are: ");
for (ssize_t s=0; s<aPopulation.aSpecies.size(); ++s) {
std::cout<< aPopulation.aSpecies[s].aGenomes.size() << " ";
}
printf("\n");
//DEBUGGING!!!!!!!!!
CullSpeciesToOne(aPopulation);

CullSpeciesToOne(aPopulation); // NOTICE: I found that this makes XOR test converges fast.

//DEBUGGING!!!!!!!!!
printf("after, species sizes are: ");
for (ssize_t s=0; s<aPopulation.aSpecies.size(); ++s) {
Expand All @@ -759,7 +736,7 @@ class NEAT {
childGenomes.push_back(lastBestGenome);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't just add the lastBestGenome, because it's possible that at the time we add the genome it doesn't exist anymore. Also the population already contains the genome, so we would add the genome twice.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

childGenomes.push_back(lastBestGenome);
Yeah, I use this to make sure the fitness will always decrease (at least not increase) during each iteration.
"it's possible that at the time we add the genome it doesn't exist anymore", sorry, but I am not quite clear about the meaning of this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, right I thought the lastBestGenome is a reference but it's a copy, so it does exist.

while (childGenomes.size() + aPopulation.aSpecies.size() < aPopulationSize) {
ssize_t speciesIndex = mlpack::math::RandInt(0, aPopulation.aSpecies.size());
Genome genome; //!!!!!!!!!!!!!
Genome genome;
bool hasBaby = BreedChild(aPopulation.aSpecies[speciesIndex], genome, aCrossoverRate);
if (hasBaby) childGenomes.push_back(genome);
}
Expand All @@ -779,7 +756,8 @@ class NEAT {
aPopulation.ReassignGenomeId();
}

// Evaluate genomes in population, set genomes' fitness.
// Evaluate genomes in population.
// Set genomes' fitness, species' and population's best fitness and genome.
void Evaluate() {
for (ssize_t i=0; i<aPopulation.aSpecies.size(); ++i) {
for (ssize_t j=0; j<aPopulation.aSpecies[i].aGenomes.size(); ++j) {
Expand Down
11 changes: 6 additions & 5 deletions src/mlpack/methods/ne/tasks.hpp
Expand Up @@ -121,8 +121,8 @@ class TaskCartPole {
// Update status.
void Action(double action, double& x, double& x_dot, double& theta, double& theta_dot) {
double force = action * F; // action is -1 or 1. TODO: or continuous???
double cos_theta = cos(theta * M_PI / 180.0);
double sin_theta = sin(theta * M_PI / 180.0);
double cos_theta = cos(theta);
double sin_theta = sin(theta);
double total_mass = mp + mc;
double temp = (force + mp * l * theta_dot * theta_dot * sin_theta) / total_mass;
double theta_acc = (g * sin_theta - cos_theta * temp) / (l * (4.0 / 3.0 - mp * cos_theta * cos_theta / total_mass));
Expand All @@ -140,7 +140,8 @@ class TaskCartPole {
assert(genome.NumInput() == 5);
assert(genome.NumOutput() == 1);

double fitness = 0; // For this task, bigger is better.
mlpack::math::RandomSeed(1); // If no seed set, each time the fitness will change.
double fitness = 0;
for (ssize_t trial=0; trial<num_trial; ++trial) {
// Initialize inputs: x, x_dot, theta, theta_dot. As used by Stanley
double x = mlpack::math::Random(-2.4, 2.4);
Expand Down Expand Up @@ -168,11 +169,11 @@ class TaskCartPole {

Action(action, x, x_dot, theta, theta_dot);
fitness += 1;
if(abs(x)>=track_limit || abs(theta)>=theta_limit) break;
if (abs(x)>=track_limit || abs(theta)>=theta_limit) break;
}
}

return 1/fitness;
return (1.0 / fitness);
Copy link
Member

@zoq zoq Jul 19, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it's a good idea to normalize the fitness?

return = 1 - double(fitness) / (num_trial * num_step);

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea! In this case, 0 will always be the best fitness!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And we can let algorithm stop when fitness reaches to 0, for both XOR and CartPole.
Do you think it is a good idea?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, we should do that for each task.

}

};
Expand Down
30 changes: 11 additions & 19 deletions src/mlpack/tests/ne_test.cpp
Expand Up @@ -97,7 +97,6 @@ BOOST_AUTO_TEST_CASE(NEGenomeTest)
ssize_t numInput = 3;
ssize_t numOutput = 1;
double fitness = -1;
double adjustedFitness = -1;
std::vector<NeuronGene> neuronGenes;
std::vector<LinkGene> linkGenes;

Expand Down Expand Up @@ -134,8 +133,7 @@ BOOST_AUTO_TEST_CASE(NEGenomeTest)
linkGenes,
numInput,
numOutput,
fitness,
adjustedFitness);
fitness);

// Test seed genome.
std::vector<std::vector<double>> inputs; // TODO: use arma::mat for input.
Expand Down Expand Up @@ -190,7 +188,6 @@ BOOST_AUTO_TEST_CASE(NECneXorTest)
ssize_t numInput = 3;
ssize_t numOutput = 1;
double fitness = -1;
double adjustedFitness = -1;
std::vector<NeuronGene> neuronGenes;
std::vector<LinkGene> linkGenes;

Expand Down Expand Up @@ -227,8 +224,7 @@ BOOST_AUTO_TEST_CASE(NECneXorTest)
linkGenes,
numInput,
numOutput,
fitness,
adjustedFitness);
fitness);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be a good idea to set a default initial genome inside the CNE method. The authors start with a genome where each input unit is connected with the output units. But, we could also use a hidden units as you did. This way, we can directly start by evolving the network.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zoq Yeah, I will put it in the default constructor. It is just for the testing, I use this style to demonstrate how to use and test the parametric constructor.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, okay, good idea, just checked the CNE method, and couldn't find a default genome.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zoq Yeah, I will set seedGenome in default constructor. Currently I haven't add the default constructor. I am planning to add it after the tests passed.

// Specify task type.
TaskXor<ann::MeanSquaredErrorFunction> task;
Expand Down Expand Up @@ -273,7 +269,6 @@ BOOST_AUTO_TEST_CASE(NENeatXorTest)
ssize_t numInput = 3;
ssize_t numOutput = 1;
double fitness = -1;
double adjustedFitness = -1;
std::vector<NeuronGene> neuronGenes;
std::vector<LinkGene> linkGenes;

Expand Down Expand Up @@ -310,8 +305,7 @@ BOOST_AUTO_TEST_CASE(NENeatXorTest)
linkGenes,
numInput,
numOutput,
fitness,
adjustedFitness);
fitness);

// Specify task type.
TaskXor<ann::MeanSquaredErrorFunction> task;
Expand Down Expand Up @@ -350,28 +344,27 @@ BOOST_AUTO_TEST_CASE(NENeatCartPoleTest)
Parameters params;
params.aPopulationSize = 500;
params.aMaxGeneration = 500;
params.aCoeffDisjoint = 2.0;
params.aCoeffWeightDiff = 0.4;
params.aCoeffDisjoint = 1.0;
params.aCoeffWeightDiff = 0.5;
params.aCompatThreshold = 1.0;
params.aStaleAgeThreshold = 15;
params.aCrossoverRate = 0.75;
params.aCullSpeciesPercentage = 0.5;
params.aMutateWeightProb = 0.2;
params.aPerturbWeightProb = 0.9;
params.aPerturbWeightProb = 0.5;
params.aMutateWeightSize = 0.1;
params.aMutateAddLinkProb = 0.5;
params.aMutateAddLinkProb = 0.3;
params.aMutateAddRecurrentLinkProb = 0;
params.aMutateAddLoopLinkProb = 0;
params.aMutateAddNeuronProb = 0.5;
params.aMutateEnabledProb = 0.2;
params.aMutateDisabledProb = 0.2;
params.aMutateAddNeuronProb = 0.1;
params.aMutateEnabledProb = 0.1;
params.aMutateDisabledProb = 0.1;

// Set seed genome for cart pole task.
ssize_t id = 0;
ssize_t numInput = 5;
ssize_t numOutput = 1;
double fitness = -1;
double adjustedFitness = -1;
std::vector<NeuronGene> neuronGenes;
std::vector<LinkGene> linkGenes;

Expand Down Expand Up @@ -420,8 +413,7 @@ BOOST_AUTO_TEST_CASE(NENeatCartPoleTest)
linkGenes,
numInput,
numOutput,
fitness,
adjustedFitness);
fitness);

// Construct NEAT instance.
NEAT<TaskCartPole> neat(task, seedGenome, params);
Expand Down