public void AddNode3() { var pop = CreateNeatPopulation(); var generationSeq = new Int32Sequence(); var genomeBuilder = NeatGenomeBuilderFactory <double> .Create(pop.MetaNeatGenome); var genome = pop.GenomeList[0]; var strategy = new AddNodeStrategy <double>( pop.MetaNeatGenome, genomeBuilder, pop.GenomeIdSeq, pop.InnovationIdSeq, generationSeq, pop.AddedNodeBuffer); IRandomSource rng = RandomDefaults.CreateRandomSource(); CircularBuffer <NeatGenome <double> > genomeRing = new(10); genomeRing.Enqueue(genome); for (int i = 0; i < 5000; i++) { NeatGenome <double> childGenome = CreateAndTestChildGenome(genome, strategy, rng); // Add the new child genome to the ring. genomeRing.Enqueue(childGenome); // Take the genome at the tail of the ring for the next parent. genome = genomeRing[0]; } }
/// <summary> /// Construct a new instance. /// </summary> /// <param name="metaNeatGenome">NeatGenome metadata.</param> /// <param name="genomeBuilder">NeatGenome builder.</param> /// <param name="genomeIdSeq">Genome ID sequence; for obtaining new genome IDs.</param> /// <param name="innovationIdSeq">Innovation ID sequence; for obtaining new innovation IDs.</param> /// <param name="generationSeq">Generation sequence; for obtaining the current generation number.</param> /// <param name="addedNodeBuffer">A history buffer of added nodes.</param> /// <param name="settings">Asexual reproduction settings.</param> /// <param name="weightMutationScheme">Connection weight mutation scheme.</param> public NeatReproductionAsexual( MetaNeatGenome <T> metaNeatGenome, INeatGenomeBuilder <T> genomeBuilder, Int32Sequence genomeIdSeq, Int32Sequence innovationIdSeq, Int32Sequence generationSeq, AddedNodeBuffer addedNodeBuffer, NeatReproductionAsexualSettings settings, WeightMutationScheme <T> weightMutationScheme) { _settings = settings; // Instantiate reproduction strategies. _mutateWeightsStrategy = new MutateWeightsStrategy <T>(metaNeatGenome, genomeBuilder, genomeIdSeq, generationSeq, weightMutationScheme); _deleteConnectionStrategy = new DeleteConnectionStrategy <T>(metaNeatGenome, genomeBuilder, genomeIdSeq, generationSeq); // Add connection mutation; select acyclic/cyclic strategy as appropriate. if (metaNeatGenome.IsAcyclic) { _addConnectionStrategy = new AddAcyclicConnectionStrategy <T>( metaNeatGenome, genomeBuilder, genomeIdSeq, innovationIdSeq, generationSeq); } else { _addConnectionStrategy = new AddCyclicConnectionStrategy <T>( metaNeatGenome, genomeBuilder, genomeIdSeq, innovationIdSeq, generationSeq); } _addNodeStrategy = new AddNodeStrategy <T>(metaNeatGenome, genomeBuilder, genomeIdSeq, innovationIdSeq, generationSeq, addedNodeBuffer); }
public NeatPopulation( MetaNeatGenome <T> metaNeatGenome, List <NeatGenome <T> > genomeList, Int32Sequence genomeIdSeq, Int32Sequence innovationIdSeq) : this(metaNeatGenome, genomeList, genomeIdSeq, innovationIdSeq, __defaultInnovationHistoryBufferSize, __defaultInnovationHistoryBufferSize) { }
public void Int32Sequence() { ISequence <int> sequence = new Int32Sequence(); for (var i = 0; i < 100; i++) { Assert.That(sequence.GetNext(), Is.EqualTo(i + 1)); } }
/// <summary> /// Construct a new instance. /// </summary> /// <param name="genomeBuilder">NeatGenome builder.</param> /// <param name="genomeIdSeq">Genome ID sequence; for obtaining new genome IDs.</param> /// <param name="generationSeq">Generation sequence; for obtaining the current generation number.</param> public DeleteConnectionStrategy( INeatGenomeBuilder <T> genomeBuilder, Int32Sequence genomeIdSeq, Int32Sequence generationSeq) { _genomeBuilder = genomeBuilder; _genomeIdSeq = genomeIdSeq; _generationSeq = generationSeq; }
/// <summary> /// Construct a new instance. /// </summary> /// <param name="eaSettings">NEAT evolution algorithm settings.</param> /// <param name="evaluator">An evaluator of lists of genomes.</param> /// <param name="speciationStrategy">Speciation strategy.</param> /// <param name="population">An initial population of genomes.</param> /// <param name="complexityRegulationStrategy">Complexity regulation strategy.</param> /// <param name="reproductionAsexualSettings">Asexual reproduction settings.</param> /// <param name="reproductionSexualSettings">Sexual reproduction settings.</param> /// <param name="weightMutationScheme">Connection weight mutation scheme.</param> /// <param name="rng">Random source.</param> public NeatEvolutionAlgorithm( NeatEvolutionAlgorithmSettings eaSettings, IGenomeListEvaluator <NeatGenome <T> > evaluator, ISpeciationStrategy <NeatGenome <T>, T> speciationStrategy, NeatPopulation <T> population, IComplexityRegulationStrategy complexityRegulationStrategy, NeatReproductionAsexualSettings reproductionAsexualSettings, NeatReproductionSexualSettings reproductionSexualSettings, WeightMutationScheme <T> weightMutationScheme, IRandomSource rng) { _eaSettingsCurrent = eaSettings ?? throw new ArgumentNullException(nameof(eaSettings)); _eaSettingsComplexifying = eaSettings; _eaSettingsSimplifying = eaSettings.CreateSimplifyingSettings(); _evaluator = evaluator ?? throw new ArgumentNullException(nameof(evaluator)); _speciationStrategy = speciationStrategy ?? throw new ArgumentNullException(nameof(speciationStrategy)); _pop = population ?? throw new ArgumentNullException(nameof(population)); _complexityRegulationStrategy = complexityRegulationStrategy ?? throw new ArgumentNullException(nameof(complexityRegulationStrategy)); if (reproductionAsexualSettings == null) { throw new ArgumentNullException(nameof(reproductionAsexualSettings)); } if (reproductionSexualSettings == null) { throw new ArgumentNullException(nameof(reproductionSexualSettings)); } _rng = rng; _genomeComparerDescending = new GenomeComparerDescending(evaluator.FitnessComparer); if (eaSettings.SpeciesCount > population.PopulationSize) { throw new ArgumentException("Species count is higher then the population size."); } _generationSeq = new Int32Sequence(); _reproductionAsexual = new NeatReproductionAsexual <T>( _pop.MetaNeatGenome, _pop.GenomeBuilder, _pop.GenomeIdSeq, population.InnovationIdSeq, _generationSeq, _pop.AddedNodeBuffer, reproductionAsexualSettings, weightMutationScheme); _reproductionSexual = new NeatReproductionSexual <T>( _pop.MetaNeatGenome, _pop.GenomeBuilder, _pop.GenomeIdSeq, _generationSeq, reproductionSexualSettings); _offspringBuilder = new OffspringBuilder <T>( _reproductionAsexual, _reproductionSexual, eaSettings.InterspeciesMatingProportion, evaluator.FitnessComparer); }
/// <summary> /// Construct a new instance. /// </summary> /// <param name="genomeBuilder">NeatGenome builder.</param> /// <param name="genomeIdSeq">Genome ID sequence; for obtaining new genome IDs.</param> /// <param name="generationSeq">Generation sequence; for obtaining the current generation number.</param> /// <param name="weightMutationScheme">Connection weight mutation scheme.</param> public MutateWeightsStrategy( INeatGenomeBuilder <T> genomeBuilder, Int32Sequence genomeIdSeq, Int32Sequence generationSeq, WeightMutationScheme <T> weightMutationScheme) { _genomeBuilder = genomeBuilder; _genomeIdSeq = genomeIdSeq; _generationSeq = generationSeq; _weightMutationScheme = weightMutationScheme; }
public void TestAddAcyclicConnection() { var pop = CreateNeatPopulation(); var generationSeq = new Int32Sequence(); var genomeBuilder = NeatGenomeBuilderFactory <double> .Create(pop.MetaNeatGenome); var genome = pop.GenomeList[0]; var strategy = new AddAcyclicConnectionStrategy <double>( pop.MetaNeatGenome, genomeBuilder, pop.GenomeIdSeq, pop.InnovationIdSeq, generationSeq); IRandomSource rng = RandomDefaults.CreateRandomSource(); var nodeIdSet = GetNodeIdSet(genome); var connSet = GetDirectedConnectionSet(genome); CyclicGraphAnalysis cyclicGraphAnalysis = new CyclicGraphAnalysis(); for (int i = 0; i < 1000;) { var childGenome = strategy.CreateChildGenome(genome, rng); // Note. the strategy will return a null if it cannot find an acyclic connection to add; // test for this and try again. The test will be for N successful mutations rather than N attempts. if (null == childGenome) { continue; } // The child genome should have one more connection than parent. Assert.AreEqual(genome.ConnectionGenes.Length + 1, childGenome.ConnectionGenes.Length); // The child genome's new connection should not be a duplicate of any of the existing/parent connections. var childConnSet = GetDirectedConnectionSet(childGenome); var newConnList = new List <DirectedConnection>(childConnSet.Except(connSet)); Assert.AreEqual(1, newConnList.Count); // The connection genes should be sorted. Assert.IsTrue(SortUtils.IsSortedAscending(childGenome.ConnectionGenes._connArr)); // The child genome should have the same set of node IDs as the parent. var childNodeIdSet = GetNodeIdSet(childGenome); Assert.IsTrue(nodeIdSet.SetEquals(childNodeIdSet)); // The child genome should describe an acyclic graph, i.e. the new connection should not have // formed a cycle in the graph. var digraph = childGenome.DirectedGraph; Assert.IsFalse(cyclicGraphAnalysis.IsCyclic(digraph)); // Increment for successful tests only. i++; } }
/// <summary> /// Construct a new instance. /// </summary> /// <param name="metaNeatGenome">NEAT genome metadata.</param> /// <param name="genomeBuilder">NeatGenome builder.</param> /// <param name="genomeIdSeq">Genome ID sequence; for obtaining new genome IDs.</param> /// <param name="generationSeq">Generation sequence; for obtaining the current generation number.</param> public DeleteConnectionStrategy( MetaNeatGenome <T> metaNeatGenome, INeatGenomeBuilder <T> genomeBuilder, Int32Sequence genomeIdSeq, Int32Sequence generationSeq) { _metaNeatGenome = metaNeatGenome; _genomeBuilder = genomeBuilder; _genomeIdSeq = genomeIdSeq; _generationSeq = generationSeq; }
/// <summary> /// Construct the population with the provided list of genomes that make up the initial population. /// </summary> /// <param name="genomeList"></param> public Population(List <TGenome> genomeList) { this.GenomeList = genomeList ?? throw new ArgumentNullException(nameof(genomeList)); this.PopulationSize = genomeList.Count; this.GenerationSeq = new Int32Sequence(); if (genomeList.Count == 0) { throw new ArgumentException("Empty genome list. The initial population cannot be empty.", nameof(genomeList)); } }
public void AddCyclicConnection() { var pop = CreateNeatPopulation(); var generationSeq = new Int32Sequence(); var genomeBuilder = NeatGenomeBuilderFactory <double> .Create(pop.MetaNeatGenome); var genome = pop.GenomeList[0]; var strategy = new AddCyclicConnectionStrategy <double>( pop.MetaNeatGenome, genomeBuilder, pop.GenomeIdSeq, generationSeq); IRandomSource rng = RandomDefaults.CreateRandomSource(); var nodeIdSet = GetNodeIdSet(genome); var connSet = GetDirectedConnectionSet(genome); const int loops = 1000; int nullResponseCount = 0; for (int i = 0; i < loops; i++) { var childGenome = strategy.CreateChildGenome(genome, rng); // The strategy may return null if no appropriately connection could be found to add. if (childGenome is null) { nullResponseCount++; continue; } // The child genome should have one more connection than parent. Assert.Equal(genome.ConnectionGenes.Length + 1, childGenome.ConnectionGenes.Length); // The child genome's new connection should not be a duplicate of any of the existing/parent connections. var childConnSet = GetDirectedConnectionSet(childGenome); var newConnList = new List <DirectedConnection>(childConnSet.Except(connSet)); Assert.Single(newConnList); // The connection genes should be sorted. Assert.True(SortUtils.IsSortedAscending <DirectedConnection>(childGenome.ConnectionGenes._connArr)); // The child genome should have the same set of node IDs as the parent. var childNodeIdSet = GetNodeIdSet(childGenome); Assert.True(nodeIdSet.SetEquals(childNodeIdSet)); } // nullResponseProportion will typically be 0, with 1.0% being so unlikely // it probably will never be observed. double nullResponseProportion = nullResponseCount / (double)loops; Assert.True(nullResponseProportion <= 0.01); }
/// <summary> /// Construct a new instance. /// </summary> /// <param name="metaNeatGenome">NeatGenome metadata.</param> /// <param name="genomeBuilder">NeatGenome builder.</param> /// <param name="genomeIdSeq">Genome ID sequence; for obtaining new genome IDs.</param> /// <param name="generationSeq">Generation sequence; for obtaining the current generation number.</param> /// <param name="settings">Sexual reproduction settings.</param> public NeatReproductionSexual( MetaNeatGenome <T> metaNeatGenome, INeatGenomeBuilder <T> genomeBuilder, Int32Sequence genomeIdSeq, Int32Sequence generationSeq, NeatReproductionSexualSettings settings) { _strategy = new UniformCrossoverReproductionStrategy <T>( metaNeatGenome.IsAcyclic, settings.SecondaryParentGeneProbability, genomeBuilder, genomeIdSeq, generationSeq); }
/// <summary> /// Construct a new instance. /// </summary> /// <param name="metaNeatGenome">NEAT genome metadata.</param> /// <param name="genomeBuilder">NeatGenome builder.</param> /// <param name="genomeIdSeq">Genome ID sequence; for obtaining new genome IDs.</param> /// <param name="generationSeq">Generation sequence; for obtaining the current generation number.</param> public AddCyclicConnectionStrategy( MetaNeatGenome <T> metaNeatGenome, INeatGenomeBuilder <T> genomeBuilder, Int32Sequence genomeIdSeq, Int32Sequence generationSeq) { _metaNeatGenome = metaNeatGenome; _genomeBuilder = genomeBuilder; _genomeIdSeq = genomeIdSeq; _generationSeq = generationSeq; _weightSamplerA = UniformDistributionSamplerFactory.CreateStatelessSampler <T>(metaNeatGenome.ConnectionWeightScale, true); _weightSamplerB = UniformDistributionSamplerFactory.CreateStatelessSampler <T>(metaNeatGenome.ConnectionWeightScale * 0.01, true); }
public void CreateGenome() { var metaNeatGenome = new MetaNeatGenome <double>( inputNodeCount: 10, outputNodeCount: 20, isAcyclic: true, activationFn: new NeuralNets.Double.ActivationFunctions.ReLU()); var genomeBuilder = NeatGenomeBuilderFactory <double> .Create(metaNeatGenome); int count = 100; NeatPopulation <double> pop = NeatPopulationFactory <double> .CreatePopulation(metaNeatGenome, 0.1, count, RandomDefaults.CreateRandomSource()); var generationSeq = new Int32Sequence(); var strategy = new UniformCrossoverReproductionStrategy <double>( pop.MetaNeatGenome.IsAcyclic, 0.02, genomeBuilder, pop.GenomeIdSeq, generationSeq); IRandomSource rng = RandomDefaults.CreateRandomSource(0); var cyclicGraphCheck = new CyclicGraphCheck(); for (int i = 0; i < 1000; i++) { // Randomly select two parents from the population. var genome1 = pop.GenomeList[rng.Next(count)]; var genome2 = pop.GenomeList[rng.Next(count)]; var childGenome = strategy.CreateGenome(genome1, genome2, rng); // The connection genes should be sorted. Assert.True(SortUtils.IsSortedAscending <DirectedConnection>(childGenome.ConnectionGenes._connArr)); // The child genome should describe an acyclic graph, i.e. the new connection should not have // formed a cycle in the graph. var digraph = childGenome.DirectedGraph; Assert.False(cyclicGraphCheck.IsCyclic(digraph)); // The child genome node IDs should be a superset of those from parent1 + parent2. var childNodeIdSet = GetNodeIdSet(childGenome); var parentIdSet = GetNodeIdSet(genome1); parentIdSet.IntersectWith(GetNodeIdSet(genome2)); Assert.True(childNodeIdSet.IsSupersetOf(parentIdSet)); } }
/// <summary> /// Construct with the given strategy arguments. /// </summary> /// <param name="isAcyclic">Indicates that the strategy will be operating on acyclic graphs/genomes.</param> /// <param name="secondaryParentGeneProbability">The probability that a gene that exists only on the secondary parent is copied into the child genome.</param> /// <param name="genomeBuilder">A neat genome builder.</param> /// <param name="genomeIdSeq">Genome ID sequence; for obtaining new genome IDs.</param> /// <param name="generationSeq">A sequence that provides the current generation number.</param> public UniformCrossoverReproductionStrategy( bool isAcyclic, double secondaryParentGeneProbability, INeatGenomeBuilder <T> genomeBuilder, Int32Sequence genomeIdSeq, Int32Sequence generationSeq) { _isAcyclic = isAcyclic; _secondaryParentGeneProbability = secondaryParentGeneProbability; _genomeBuilder = genomeBuilder; _genomeIdSeq = genomeIdSeq; _generationSeq = generationSeq; _connGeneListBuilder = new ConnectionGeneListBuilder <T>(_isAcyclic, 1024); }
public UniformCrossoverReproductionStrategy( MetaNeatGenome <T> metaNeatGenome, INeatGenomeBuilder <T> genomeBuilder, Int32Sequence genomeIdSeq, Int32Sequence generationSeq, IRandomSource rng) { _metaNeatGenome = metaNeatGenome; _genomeBuilder = genomeBuilder; _genomeIdSeq = genomeIdSeq; _generationSeq = generationSeq; _rng = rng; _builder = new ConnectionGeneListBuilder <T>(_metaNeatGenome.IsAcyclic, 1024); }
/// <summary> /// Construct a new instance. /// </summary> /// <param name="metaNeatGenome">NEAT genome metadata.</param> /// <param name="genomeBuilder">NeatGenome builder.</param> /// <param name="genomeIdSeq">Genome ID sequence; for obtaining new genome IDs.</param> /// <param name="innovationIdSeq">Innovation ID sequence; for obtaining new innovation IDs.</param> /// <param name="generationSeq">Generation sequence; for obtaining the current generation number.</param> /// <param name="addedNodeBuffer">A history buffer of added nodes.</param> public AddNodeStrategy( MetaNeatGenome <T> metaNeatGenome, INeatGenomeBuilder <T> genomeBuilder, Int32Sequence genomeIdSeq, Int32Sequence innovationIdSeq, Int32Sequence generationSeq, AddedNodeBuffer addedNodeBuffer) { _metaNeatGenome = metaNeatGenome; _genomeBuilder = genomeBuilder; _genomeIdSeq = genomeIdSeq; _innovationIdSeq = innovationIdSeq; _generationSeq = generationSeq; _addedNodeBuffer = addedNodeBuffer; }
public NeatPopulation( MetaNeatGenome <T> metaNeatGenome, List <NeatGenome <T> > genomeList, Int32Sequence genomeIdSeq, Int32Sequence innovationIdSeq, int addedConnectionHistoryBufferSize, int addedNodeHistoryBufferSize) : base(genomeList) { this.MetaNeatGenome = metaNeatGenome; this.GenomeIdSeq = genomeIdSeq; this.InnovationIdSeq = innovationIdSeq; this.AddedNodeBuffer = new AddedNodeBuffer(addedNodeHistoryBufferSize); // Assert that the ID sequences have a current IDs higher than any existing ID. Debug.Assert(ValidateIdSequences(genomeList, genomeIdSeq, innovationIdSeq)); }
public NeatReproductionSexual( MetaNeatGenome <T> metaNeatGenome, INeatGenomeBuilder <T> genomeBuilder, Int32Sequence genomeIdSeq, Int32Sequence innovationIdSeq, Int32Sequence generationSeq, AddedNodeBuffer addedNodeBuffer, NeatReproductionSexualSettings settings, IRandomSourceBuilder rngBuilder) { _settings = settings; _rng = rngBuilder.Create(); _strategy = new UniformCrossoverReproductionStrategy <T>( metaNeatGenome, genomeBuilder, genomeIdSeq, generationSeq, rngBuilder.Create()); }
/// <summary> /// Construct a new population with the provided genomes and accompanying objects. /// </summary> /// <param name="metaNeatGenome">NeatGenome metadata.</param> /// <param name="genomeBuilder">NeatGenome builder.</param> /// <param name="genomeList">A list of genomes that will make up the population.</param> /// <param name="genomeIdSeq">Genome ID sequence.</param> /// <param name="innovationIdSeq">Innovation ID sequence.</param> /// <param name="addedNodeHistoryBufferSize">The size to allocate for the added node history buffer.</param> public NeatPopulation( MetaNeatGenome <T> metaNeatGenome, INeatGenomeBuilder <T> genomeBuilder, List <NeatGenome <T> > genomeList, Int32Sequence genomeIdSeq, Int32Sequence innovationIdSeq, int addedNodeHistoryBufferSize) : base(genomeList) { this.MetaNeatGenome = metaNeatGenome ?? throw new ArgumentNullException(nameof(metaNeatGenome)); this.GenomeBuilder = genomeBuilder ?? throw new ArgumentNullException(nameof(genomeBuilder)); this.GenomeIdSeq = genomeIdSeq ?? throw new ArgumentNullException(nameof(genomeIdSeq)); this.InnovationIdSeq = innovationIdSeq ?? throw new ArgumentNullException(nameof(innovationIdSeq)); this.AddedNodeBuffer = new AddedNodeBuffer(addedNodeHistoryBufferSize); // Assert that the ID sequence objects represent an ID higher than any existing ID used by the genomes. Debug.Assert(ValidateIdSequences(genomeList, genomeIdSeq, innovationIdSeq)); }
public AddCyclicConnectionStrategy( MetaNeatGenome <T> metaNeatGenome, INeatGenomeBuilder <T> genomeBuilder, Int32Sequence genomeIdSeq, Int32Sequence innovationIdSeq, Int32Sequence generationSeq, IRandomSource rng) { _metaNeatGenome = metaNeatGenome; _genomeBuilder = genomeBuilder; _genomeIdSeq = genomeIdSeq; _innovationIdSeq = innovationIdSeq; _generationSeq = generationSeq; _weightDistA = ContinuousDistributionFactory.CreateUniformDistribution <T>(_metaNeatGenome.ConnectionWeightRange, true); _weightDistB = ContinuousDistributionFactory.CreateUniformDistribution <T>(_metaNeatGenome.ConnectionWeightRange * 0.01, true); _rng = rng; }
public async Task Test() { using var _ = HConsoleForTest(); var options = HazelcastOptions.Build(); options.Messaging.RetryTimeoutSeconds = 1; var loggerFactory = new NullLoggerFactory(); var address = NetworkAddress.Parse("127.0.0.1:11000"); var state = new ServerState { Id = 0, MemberId = Guid.NewGuid(), Address = address }; await using var server = new Server(address, ServerHandler, loggerFactory, state, "0") { MemberId = state.MemberId, }; await server.StartAsync(); var serializationService = HazelcastClientFactory.CreateSerializationService(options.Serialization, loggerFactory); var authenticator = new Authenticator(options.Authentication, serializationService); ISequence <int> connectionIdSequence = new Int32Sequence(); ISequence <long> correlationIdSequence = new Int64Sequence(); var memberConnection = new MemberConnection(address, authenticator, options.Messaging, options.Networking, options.Networking.Ssl, connectionIdSequence, correlationIdSequence, loggerFactory); var memberConnectionHasClosed = false; memberConnection.Closed += connection => { memberConnectionHasClosed = true; return(default);
public static bool ValidateIdSequences <T>( List <NeatGenome <T> > genomeList, Int32Sequence genomeIdSeq, Int32Sequence innovationIdSeq) where T : struct { GetMaxObservedIds(genomeList, out int maxGenomeId, out int maxInnovationId); if (maxGenomeId >= genomeIdSeq.Peek) { return(false); } if (maxInnovationId >= innovationIdSeq.Peek) { return(false); } return(true); }
public void AddNode1() { var pop = CreateNeatPopulation(); var generationSeq = new Int32Sequence(); var genomeBuilder = NeatGenomeBuilderFactory <double> .Create(pop.MetaNeatGenome); var genome = pop.GenomeList[0]; var strategy = new AddNodeStrategy <double>( pop.MetaNeatGenome, genomeBuilder, pop.GenomeIdSeq, pop.InnovationIdSeq, generationSeq, pop.AddedNodeBuffer); IRandomSource rng = RandomDefaults.CreateRandomSource(); for (int i = 0; i < 10_000; i++) { CreateAndTestChildGenome(genome, strategy, rng); } }
private NeatPopulationFactory( MetaNeatGenome <T> metaNeatGenome, double connectionsProportion, IRandomSource rng) { _metaNeatGenome = metaNeatGenome; _genomeBuilder = NeatGenomeBuilderFactory <T> .Create(metaNeatGenome); _connectionsProportion = connectionsProportion; // Define the set of all possible connections between the input and output nodes (fully interconnected). int inputCount = metaNeatGenome.InputNodeCount; int outputCount = metaNeatGenome.OutputNodeCount; _connectionDefArr = new DirectedConnection[inputCount * outputCount]; // Notes. // Nodes are assigned innovation IDs. By convention the input nodes are assigned IDs first starting at zero, then the output nodes. // Thus, because all of the evolved networks have a fixed number of inputs and outputs, the IDs of these nodes are always fixed. int firstOutputNodeId = inputCount; for (int srcId = 0, i = 0; srcId < inputCount; srcId++) { for (int tgtIdx = 0; tgtIdx < outputCount; tgtIdx++) { _connectionDefArr[i++] = new DirectedConnection(srcId, firstOutputNodeId + tgtIdx); } } // Init RNG and ID sequences. _rng = rng; _genomeIdSeq = new Int32Sequence(); int nextInnovationId = inputCount + outputCount; _innovationIdSeq = new Int32Sequence(nextInnovationId); // Init random connection weight source. _connWeightDist = ContinuousDistributionFactory.CreateUniformDistribution <T>(_metaNeatGenome.ConnectionWeightRange, true); }
public void TestDeleteConnection() { var pop = CreateNeatPopulation(); var generationSeq = new Int32Sequence(); var genomeBuilder = NeatGenomeBuilderFactory <double> .Create(pop.MetaNeatGenome); var genome = pop.GenomeList[0]; var strategy = new DeleteConnectionStrategy <double>( pop.MetaNeatGenome, genomeBuilder, pop.GenomeIdSeq, generationSeq); IRandomSource rng = RandomDefaults.CreateRandomSource(); var nodeIdSet = GetNodeIdSet(genome); var connSet = GetDirectedConnectionSet(genome); for (int i = 0; i < 1000; i++) { var childGenome = strategy.CreateChildGenome(genome, rng); // The child genome should have one less connection than the parent. Assert.AreEqual(genome.ConnectionGenes.Length - 1, childGenome.ConnectionGenes.Length); // The child genome's connections should be a proper subset of the parent genome's. var childConnSet = GetDirectedConnectionSet(childGenome); Assert.IsTrue(childConnSet.IsProperSubsetOf(connSet)); // The connection genes should be sorted. Assert.IsTrue(SortUtils.IsSortedAscending(childGenome.ConnectionGenes._connArr)); // Test that the array of hidden node IDs is correct, i.e. corresponds with the hidden node IDs described by the connections. Assert.IsTrue(ConnectionGenesUtils.ValidateHiddenNodeIds( childGenome.HiddenNodeIdArray, childGenome.ConnectionGenes._connArr, childGenome.MetaNeatGenome.InputOutputNodeCount)); } }
public void AddNode2() { var pop = CreateNeatPopulation(); var generationSeq = new Int32Sequence(); var genomeBuilder = NeatGenomeBuilderFactory <double> .Create(pop.MetaNeatGenome); var genome = pop.GenomeList[0]; var strategy = new AddNodeStrategy <double>( pop.MetaNeatGenome, genomeBuilder, pop.GenomeIdSeq, pop.InnovationIdSeq, generationSeq, pop.AddedNodeBuffer); IRandomSource rng = RandomDefaults.CreateRandomSource(); for (int i = 0; i < 2000; i++) { NeatGenome <double> childGenome = CreateAndTestChildGenome(genome, strategy, rng); // Make the child genome the parent in the next iteration. I.e. accumulate add node mutations. genome = childGenome; } }
/// <summary> /// Construct a new instance. /// </summary> /// <param name="metaNeatGenome">NeatGenome metadata.</param> /// <param name="genomeBuilder">NeatGenome builder.</param> /// <param name="genomeIdSeq">Genome ID sequence; for obtaining new genome IDs.</param> /// <param name="innovationIdSeq">Innovation ID sequence; for obtaining new innovation IDs.</param> /// <param name="generationSeq">Generation sequence; for obtaining the current generation number.</param> /// <param name="addedNodeBuffer">A history buffer of added nodes.</param> /// <param name="settings">Asexual reproduction settings.</param> /// <param name="weightMutationScheme">Connection weight mutation scheme.</param> public NeatReproductionAsexual( MetaNeatGenome <T> metaNeatGenome, INeatGenomeBuilder <T> genomeBuilder, Int32Sequence genomeIdSeq, Int32Sequence innovationIdSeq, Int32Sequence generationSeq, AddedNodeBuffer addedNodeBuffer, NeatReproductionAsexualSettings settings, WeightMutationScheme <T> weightMutationScheme) { var settingsComplexifying = settings; var settingsSimplifying = settings.CreateSimplifyingSettings(); _mutationTypeDistributionsComplexifying = new MutationTypeDistributions(settingsComplexifying); _mutationTypeDistributionsSimplifying = new MutationTypeDistributions(settingsSimplifying); _mutationTypeDistributionsCurrent = _mutationTypeDistributionsComplexifying; // Instantiate reproduction strategies. _mutateWeightsStrategy = new MutateWeightsStrategy <T>(genomeBuilder, genomeIdSeq, generationSeq, weightMutationScheme); _deleteConnectionStrategy = new DeleteConnectionStrategy <T>(genomeBuilder, genomeIdSeq, generationSeq); // Add connection mutation; select acyclic/cyclic strategy as appropriate. if (metaNeatGenome.IsAcyclic) { _addConnectionStrategy = new AddAcyclicConnectionStrategy <T>( metaNeatGenome, genomeBuilder, genomeIdSeq, generationSeq); } else { _addConnectionStrategy = new AddCyclicConnectionStrategy <T>( metaNeatGenome, genomeBuilder, genomeIdSeq, generationSeq); } _addNodeStrategy = new AddNodeStrategy <T>(metaNeatGenome, genomeBuilder, genomeIdSeq, innovationIdSeq, generationSeq, addedNodeBuffer); }
public Population( List <TGenome> genomeList) { this.GenomeList = genomeList; this.GenerationSeq = new Int32Sequence(); }
public void TestAddAcyclicConnection_CumulativeAdditions() { var pop = CreateNeatPopulation(); var generationSeq = new Int32Sequence(); var genomeBuilder = NeatGenomeBuilderFactory <double> .Create(pop.MetaNeatGenome); var rootGenome = pop.GenomeList[0]; var strategy = new AddAcyclicConnectionStrategy <double>( pop.MetaNeatGenome, genomeBuilder, pop.GenomeIdSeq, pop.InnovationIdSeq, generationSeq); IRandomSource rng = RandomDefaults.CreateRandomSource(); var nodeIdSet = GetNodeIdSet(rootGenome); CyclicGraphAnalysis cyclicGraphAnalysis = new CyclicGraphAnalysis(); AcyclicGraphDepthAnalysis graphDepthAnalysis = new AcyclicGraphDepthAnalysis(); // Run the inner loop test multiple times. // Note. The add-connection mutations are random, thus each loop accumulates a different set of mutations. for (int i = 0; i < 50; i++) { var parentGenome = rootGenome; // Accumulate random mutations for some number of loops. for (int j = 0; j < 20;) { var childGenome = strategy.CreateChildGenome(rootGenome, rng); // Note. the strategy will return a null if it cannot find an acyclic connection to add; // test for this and try again. The test will be for N successful mutations rather than N attempts. if (null == childGenome) { continue; } // The child genome should have one more connection than parent. Assert.AreEqual(rootGenome.ConnectionGenes.Length + 1, childGenome.ConnectionGenes.Length); // The child genome's new connection should not be a duplicate of any of the existing/parent connections. var connSet = GetDirectedConnectionSet(rootGenome); var childConnSet = GetDirectedConnectionSet(childGenome); var newConnList = new List <DirectedConnection>(childConnSet.Except(connSet)); Assert.AreEqual(1, newConnList.Count); // The connection genes should be sorted. Assert.IsTrue(SortUtils.IsSortedAscending(childGenome.ConnectionGenes._connArr)); // The child genome should have the same set of node IDs as the parent. var childNodeIdSet = GetNodeIdSet(childGenome); Assert.IsTrue(nodeIdSet.SetEquals(childNodeIdSet)); // The child genome should describe an acyclic graph, i.e. the new connection should not have // formed a cycle in the graph. var digraph = childGenome.DirectedGraph; Assert.IsFalse(cyclicGraphAnalysis.IsCyclic(digraph)); // Run the acyclic graph depth analysis algorithm. GraphDepthInfo depthInfo = graphDepthAnalysis.CalculateNodeDepths(childGenome.DirectedGraph); // Run again with the alternative algorithm (that uses function recursion). GraphDepthInfo depthInfo2 = AcyclicGraphDepthAnalysisByRecursion.CalculateNodeDepths(childGenome.DirectedGraph); Assert.AreEqual(nodeIdSet.Count, depthInfo._nodeDepthArr.Length); Assert.AreEqual(nodeIdSet.Count, depthInfo2._nodeDepthArr.Length); ArrayTestUtils.Compare(depthInfo2._nodeDepthArr, depthInfo._nodeDepthArr); // Set the child genome to be the new parent, thus we accumulate random new connections over time. parentGenome = childGenome; // Increment for successful tests only. j++; } } }