public new NEATGenome Crossover(NEATGenome mom, NEATGenome dad)
{
NEATParent best;
// first determine who is more fit, the mother or the father?
if (mom.Score == dad.Score)
{
if (mom.NumGenes == dad.NumGenes)
{
if (ThreadSafeRandom.NextDouble() > 0)
{
best = NEATParent.Mom;
}
else
{
best = NEATParent.Dad;
}
}
else
{
if (mom.NumGenes < dad.NumGenes)
{
best = NEATParent.Mom;
}
else
{
best = NEATParent.Dad;
}
}
}
else
{
if (Comparator.IsBetterThan(mom.Score, dad.Score))
{
best = NEATParent.Mom;
}
else
{
best = NEATParent.Dad;
}
}
var babyNeurons = new Chromosome();
var babyGenes = new Chromosome();
var vecNeurons = new List<long>();
int curMom = 0;
int curDad = 0;
NEATLinkGene momGene;
NEATLinkGene dadGene;
NEATLinkGene selectedGene = null;
while ((curMom < mom.NumGenes) || (curDad < dad.NumGenes))
{
if (curMom < mom.NumGenes)
{
momGene = (NEATLinkGene) mom.Links.Get(curMom);
}
else
{
momGene = null;
}
if (curDad < dad.NumGenes)
{
dadGene = (NEATLinkGene) dad.Links.Get(curDad);
}
else
{
dadGene = null;
}
if ((momGene == null) && (dadGene != null))
{
if (best == NEATParent.Dad)
{
selectedGene = dadGene;
}
curDad++;
}
else if ((dadGene == null) && (momGene != null))
{
if (best == NEATParent.Mom)
{
selectedGene = momGene;
}
curMom++;
}
else if (momGene.InnovationId < dadGene.InnovationId)
{
if (best == NEATParent.Mom)
{
selectedGene = momGene;
}
curMom++;
}
else if (dadGene.InnovationId < momGene.InnovationId)
{
if (best == NEATParent.Dad)
{
selectedGene = dadGene;
}
curDad++;
}
else if (dadGene.InnovationId == momGene.InnovationId)
{
if (ThreadSafeRandom.NextDouble() < 0.5f)
{
selectedGene = momGene;
}
else
{
selectedGene = dadGene;
}
curMom++;
curDad++;
}
if (babyGenes.Size() == 0)
{
babyGenes.Add(selectedGene);
}
else
{
if (((NEATLinkGene) babyGenes.Get(babyGenes.Size() - 1))
.InnovationId != selectedGene.InnovationId)
{
babyGenes.Add(selectedGene);
}
}
// Check if we already have the nodes referred to in SelectedGene.
// If not, they need to be added.
AddNeuronID(selectedGene.FromNeuronID, vecNeurons);
AddNeuronID(selectedGene.ToNeuronID, vecNeurons);
} // end while
// now create the required nodes. First sort them into order
vecNeurons.Sort();
for (int i = 0; i < vecNeurons.Count; i++)
{
babyNeurons.Add(Innovations.CreateNeuronFromID(
vecNeurons[i]));
}
// finally, create the genome
var babyGenome = new NEATGenome(Population
.AssignGenomeID(), babyNeurons, babyGenes, mom.InputCount,
mom.OutputCount);
babyGenome.GA = this;
babyGenome.Population = Population;
return babyGenome;
}