示例#1
0
 /// <summary>
 /// Mutates the weights of a neural net. For each connection in the genotype there is a random chance of different mutations occuring according to the properties defined on this class.
 /// </summary>
 /// <param name="genotype">Genotype to mutate.</param>
 /// <param name="random">Random for number generation.</param>
 /// <param name="innovationIdManager"></param>
 public override void Mutate(NeatBrainGenotype genotype, Random random, InnovationIdManager innovationIdManager)
 {
     foreach (ConnectionGene gene in genotype.ConnectionGenes)
     {
         if (random.NextDouble() < this.ProbPerturbWeight)
         {
             // Perturb the weights
             gene.Weight += (float)random.Normal(0.0d, NewWeightStd) * WeightPerturbScale;
         }
         if (random.NextDouble() < this.ProbResetWeight)
         {
             // Reset the weight to a new random value
             gene.Weight = (float)random.Normal(0.0d, NewWeightStd) * NewWeightPower;
         }
         if (random.NextDouble() < this.ProbEnableConn)
         {
             if (!genotype.CreatesCycle(gene))
             {
                 gene.Enabled = true;
             }
         }
         if (random.NextDouble() < this.ProbDisableConn)
         {
             gene.Enabled = false;
         }
     }
 }
示例#2
0
        public void TestAdder()
        {
            NeatBrainGenotype test = new NeatBrainGenotype();

            test.AddNamedNode("input1", NodeType.INPUT, ActivationFunctionType.RELU);
            test.AddNamedNode("hidden1", NodeType.HIDDEN, ActivationFunctionType.RELU);
            test.AddNamedNode("output1", NodeType.OUTPUT, ActivationFunctionType.RELU);

            test.ConnectionGenes.Add(new ConnectionGene(1, 0, 1, 1));             // Input to hidden
            test.ConnectionGenes.Add(new ConnectionGene(2, 1, 1, 1, true, true)); // Hidden to hidden (recurrent)
            test.ConnectionGenes.Add(new ConnectionGene(3, 1, 2, 1));             //# Hidden to output

            var network = new NeatBrainPhenotype(test);

            network.SetInput("input1", 1.0f);
            Assert.AreEqual(1.0f, network.Get("input1"));
            network.Calculate();
            Assert.AreEqual(0, network.Get("output1"));
            network.SetInput("input1", 2.0f);
            network.Calculate();
            Assert.AreEqual(1, network.Get("output1"));
            network.SetInput("input1", 10.0f);
            network.Calculate();
            Assert.AreEqual(3, network.Get("output1"));
            Assert.AreEqual(13, network.Get("hidden1"));
            Assert.AreEqual(10, network.Get("input1"));
        }
示例#3
0
        public void TestCreatesCycleIgnoresRecurrentConnections()
        {
            // Test that a gene already in the genome can be tested fro recurrence
            NeatBrainGenotype test = new NeatBrainGenotype();

            test.AddNamedNode("input1", NodeType.INPUT, ActivationFunctionType.RELU);
            test.AddNamedNode("input2", NodeType.INPUT, ActivationFunctionType.RELU);

            test.AddNamedNode("hidden1", NodeType.HIDDEN, ActivationFunctionType.RELU);
            test.AddNamedNode("hidden2", NodeType.HIDDEN, ActivationFunctionType.RELU);

            test.AddNamedNode("output1", NodeType.OUTPUT, ActivationFunctionType.RELU);

            test.ConnectionGenes.Add(new ConnectionGene(1, 0, 2, 1));
            test.ConnectionGenes.Add(new ConnectionGene(3, 1, 3, 1));
            test.ConnectionGenes.Add(new ConnectionGene(4, 2, 4, 1));
            test.ConnectionGenes.Add(new ConnectionGene(5, 3, 4, 1));

            var nonRecurrentGene = new ConnectionGene(2, 2, 3, 1, true, true);

            Assert.IsFalse(test.CreatesCycle(nonRecurrentGene));
            test.ConnectionGenes.Add(nonRecurrentGene);

            var recurrentGene = new ConnectionGene(2, 3, 2, 1);

            Assert.IsFalse(test.CreatesCycle(recurrentGene));
        }
示例#4
0
 /// <summary>
 /// Mutates the given genotype with the assigned mutators.
 /// Mutators each have an assigned probability of activating (ProbabiltiyOfMutation). The list of mutators is read from the lowest index up until the highest.
 /// If a mutator activates, then no more mutators can be activated and the mutattion finishes.
 /// A mutator with a ProbabiltiyOfMutation will always activate if we reach it in the list.
 /// </summary>
 /// <param name="genotype">Genotype to mutate</param>
 /// <param name="innovationIdManager">Innovation id manager. New innovation ids will be taken from here.</param>
 public void Mutate(NeatBrainGenotype genotype, InnovationIdManager innovationIdManager)
 {
     foreach (AbstractMutator mutator in Mutators)
     {
         if (Random.NextDouble() < mutator.ProbabiltiyOfMutation)
         {
             mutator.Mutate(genotype, Random, innovationIdManager);
         }
     }
 }
示例#5
0
        public void TestRecurrentFromOutput()
        {
            NeatBrainGenotype test = new NeatBrainGenotype();

            test.AddNamedNode("input1", NodeType.INPUT, ActivationFunctionType.RELU);
            test.AddNamedNode("input2", NodeType.INPUT, ActivationFunctionType.RELU);
            test.AddNamedNode("input3", NodeType.INPUT, ActivationFunctionType.RELU);

            // Hidden genes
            test.NodeGenes.Add(new NodeGene(3, NodeType.HIDDEN, ActivationFunctionType.RELU));
            test.NodeGenes.Add(new NodeGene(4, NodeType.HIDDEN, ActivationFunctionType.RELU));

            // Output genes
            test.AddNamedNode("output", NodeType.OUTPUT, ActivationFunctionType.RELU);

            test.NodeGenes.Add(new NodeGene(5, NodeType.OUTPUT, ActivationFunctionType.RELU));


            // Input connections
            test.ConnectionGenes.Add(new ConnectionGene(1, 0, 3, 1));
            test.ConnectionGenes.Add(new ConnectionGene(2, 1, 3, 1));
            test.ConnectionGenes.Add(new ConnectionGene(3, 1, 4, 1));
            test.ConnectionGenes.Add(new ConnectionGene(4, 2, 4, 1));
            // Hidden connection
            test.ConnectionGenes.Add(new ConnectionGene(5, 3, 4, 1));
            // The recurrent connection from 4 to 3
            test.ConnectionGenes.Add(new ConnectionGene(6, 4, 3, 1, true, true));
            // Hidden to output
            test.ConnectionGenes.Add(new ConnectionGene(7, 3, 5, 1));
            test.ConnectionGenes.Add(new ConnectionGene(8, 4, 5, 1));
            // The recurrent connection from 5 to 3
            test.ConnectionGenes.Add(new ConnectionGene(9, 5, 3, -1));

            var network = new NeatBrainPhenotype(test);

            network.SetInput("input1", 1.0f);
            network.SetInput("input2", 2.0f);
            network.SetInput("input3", 3.0f);
            network.Calculate();
            Assert.AreEqual(0.0d, network.Get(5));
            network.SetInput("input1", 1.0f);
            network.SetInput("input2", 2.0f);
            network.SetInput("input3", 3.0f);
            network.Calculate();
            Assert.AreEqual(8.0d, network.Get(5));
            network.SetInput("input1", 1.0f);
            network.SetInput("input2", 2.0f);
            network.SetInput("input3", 3.0f);
            network.Calculate();
            Assert.AreEqual(16.0d, network.Get(5));
        }
示例#6
0
        public void TestNamedNodes()
        {
            NeatBrainGenotype test = new NeatBrainGenotype();

            test.AddNamedNode("bias", NodeType.BIAS, ActivationFunctionType.RELU);
            test.AddNamedNode("input1", NodeType.INPUT, ActivationFunctionType.RELU);
            test.AddNamedNode("input2", NodeType.INPUT, ActivationFunctionType.RELU);

            Assert.IsTrue(test.NodeGenes.Count == 3);

            Assert.IsTrue(test.NodeNameMap.ContainsKey("bias"));
            Assert.IsTrue(test.NodeNameMap.ContainsKey("input1"));
            Assert.IsTrue(test.NodeNameMap.ContainsKey("input2"));
        }
示例#7
0
        public void TestReEnableCreatesCycle()
        {
            // Test that a gene already in the genome can be tested fro recurrence
            NeatBrainGenotype test = new NeatBrainGenotype();

            test.AddNamedNode("input1", NodeType.INPUT, ActivationFunctionType.RELU);
            test.AddNamedNode("hidden1", NodeType.HIDDEN, ActivationFunctionType.RELU);
            test.AddNamedNode("output1", NodeType.OUTPUT, ActivationFunctionType.RELU);

            test.ConnectionGenes.Add(new ConnectionGene(1, 0, 1, 1));
            var recurrentGene = new ConnectionGene(2, 1, 1, 1, false, true);

            test.ConnectionGenes.Add(recurrentGene);
            test.ConnectionGenes.Add(new ConnectionGene(3, 1, 2, 1));

            // This new gene should not create a cycle
            Assert.IsTrue(test.CreatesCycle(recurrentGene));
        }
示例#8
0
        public void Update(uint tick, float _gameSpeed)
        {
            Random r = new Random();

            for (int i = 0; i < Compatible.Count; i++)
            {
                var parentEntity = Compatible[i];
                var reproduction = parentEntity.GetComponent <ReproductionComponent>();

                if (reproduction.Reproduce > reproduction.ReproductionThreshold)
                {
                    var energy = parentEntity.GetComponent <EnergyComponent>();

                    // check if we have the energy
                    if (!energy.CanAfford(reproduction.ReproductionEnergyCost))
                    {
                        continue;
                    }
                    if (energy.Energy - reproduction.ReproductionEnergyCost < reproduction.RequiredRemainingEnergy)
                    {
                        continue;
                    }

                    // charge teh parent energy. Each critter has an efficency rating, so some energy gets wasted an the rest gets sent to the child.
                    float charged = energy.ChargeEnergy(reproduction.ReproductionEnergyCost);

                    float toChild = reproduction.Efficency * charged;
                    float wasted  = charged - toChild;

                    // Let the energy manager know about the wasted energy.
                    _energyManager.DepositEnergy(wasted);

                    // Some set up for the new child, setting positions/giving energy.
                    var babyEntity = Pool.AddEntityFromDefinition(reproduction.ChildDefinitionId, _simulation.JsonSettings, parentEntity.Tag);

                    babyEntity.GetComponent <EnergyComponent>().Energy = toChild;
                    var parentPosition = parentEntity.GetComponent <TransformComponent>().LocalPosition;
                    babyEntity.GetComponent <TransformComponent>().LocalPosition = parentPosition;

                    // The new child will need a mutated brain
                    var originalBrainComponent = parentEntity.GetComponent <BrainComponent>();
                    var originalBrain          = originalBrainComponent.Brain;


                    AbstractBrainGenotype parentGenotype = ((NeatBrainPhenotype)originalBrain).Genotype;
                    NeatBrainGenotype     childGenotype  = (NeatBrainGenotype)parentGenotype.Clone();


                    _muationManager.Mutate(childGenotype, _innovationIdManager);
                    var newBrain = babyEntity.GetComponent <BrainComponent>();
                    newBrain.SetGenotype(childGenotype);

                    // Do not need to pass it type as we have already set the brain, therefore it does not need initializing.
                    newBrain.SetUpLinks(null, _simulation.Settings);
                    newBrain.ParentSpecies = originalBrainComponent.Species;

                    BirthEventInfo e = new BirthEventInfo(parentPosition, tick * _gameSpeed, parentEntity.Id, parentEntity.Tag, babyEntity.Id, babyEntity.Tag, childGenotype, originalBrainComponent.Species.Id);
                    BirthEvent?.Invoke(e);
                }
            }
        }
示例#9
0
 /// <summary>
 /// Mutates a given genotype
 /// </summary>
 /// <param name="genotype">Genotype to mutate</param>
 public abstract void Mutate(NeatBrainGenotype genotype, Random random, InnovationIdManager innovationIdManager);