private NeatGenome <T> CreateGenomeInner( NeatGenome <T> parent1, NeatGenome <T> parent2, IRandomSource rng) { // Resolve a flag that determines if *all* disjoint genes from the secondary parent will be included in the child genome, or not. // This approach is from SharpNEAT v2.x and is preserved to act as baseline in v4.x, but better strategies may exist. bool includeSecondaryParentGene = DiscreteDistribution.SampleBernoulli(rng, _secondaryParentGeneProbability); // Enumerate over the connection genes in both parents. foreach (var geneIndexPair in EnumerateParentGenes(parent1.ConnectionGenes, parent2.ConnectionGenes)) { // Create a connection gene based on the current position in both parents. ConnectionGene <T>?connGene = CreateConnectionGene( parent1.ConnectionGenes, parent2.ConnectionGenes, geneIndexPair.Item1, geneIndexPair.Item2, includeSecondaryParentGene, rng); if (connGene.HasValue) { // Attempt to add the gene to the child genome we are building. _connGeneListBuilder.TryAddGene(connGene.Value); } } // Convert the genes to the structure required by NeatGenome. ConnectionGenes <T> connGenes = _connGeneListBuilder.ToConnectionGenes(); // Create and return a new genome. return(_genomeBuilder.Create( _genomeIdSeq.Next(), _generationSeq.Peek, connGenes)); }
private ConnectionGene <T>?CreateConnectionGene( ConnectionGenes <T> connGenes1, ConnectionGenes <T> connGenes2, int idx1, int idx2, IRandomSource rng) { // Select gene at random if it is present on both parents. if (-1 != idx1 && -1 != idx2) { if (rng.NextBool()) { return(CreateConnectionGene(connGenes1, idx1)); } else { return(CreateConnectionGene(connGenes2, idx2)); } } // Use the primary parent's gene if it has one. if (-1 != idx1) { return(CreateConnectionGene(connGenes1, idx1)); } // Otherwise use the secondary parent's gene stochastically. if (DiscreteDistribution.SampleBernoulli(rng, _secondaryParentGeneProbability)) { return(CreateConnectionGene(connGenes2, idx2)); } return(null); }