private void Initialize()
        {
            #region Create parameters
            Parameters.Add(new ValueLookupParameter <IRandom>("Random", "A pseudo random number generator."));
            Parameters.Add(new ValueLookupParameter <BoolValue>("Maximization", "True if the problem is a maximization problem, otherwise false."));
            Parameters.Add(new ScopeTreeLookupParameter <DoubleValue>("Quality", "The value which represents the quality of a solution."));
            Parameters.Add(new ValueLookupParameter <IOperator>("Selector", "The operator used to select solutions for reproduction."));
            Parameters.Add(new ValueLookupParameter <IOperator>("Crossover", "The operator used to cross solutions."));
            Parameters.Add(new ValueLookupParameter <PercentValue>("MutationProbability", "The probability that the mutation operator is applied on a solution."));
            Parameters.Add(new ValueLookupParameter <IOperator>("Mutator", "The operator used to mutate solutions."));
            Parameters.Add(new ValueLookupParameter <IOperator>("Evaluator", "The operator used to evaluate solutions. This operator is executed in parallel, if an engine is used which supports parallelization."));
            Parameters.Add(new LookupParameter <IntValue>("EvaluatedSolutions", "The number of evaluated solutions."));
            Parameters.Add(new ValueLookupParameter <IntValue>("Elites", "The numer of elite solutions which are kept in each generation."));
            Parameters.Add(new ValueLookupParameter <BoolValue>("ReevaluateElites", "Flag to determine if elite individuals should be reevaluated (i.e., if stochastic fitness functions are used.)"));
            Parameters.Add(new LookupParameter <DoubleValue>("ComparisonFactor", "The comparison factor is used to determine whether the offspring should be compared to the better parent, the worse parent or a quality value linearly interpolated between them. It is in the range [0;1]."));
            Parameters.Add(new LookupParameter <DoubleValue>("CurrentSuccessRatio", "The current success ratio."));
            Parameters.Add(new ValueLookupParameter <DoubleValue>("SuccessRatio", "The ratio of successful to total children that should be achieved."));
            Parameters.Add(new LookupParameter <DoubleValue>("SelectionPressure", "The actual selection pressure."));
            Parameters.Add(new ValueLookupParameter <DoubleValue>("MaximumSelectionPressure", "The maximum selection pressure that terminates the algorithm."));
            Parameters.Add(new ValueLookupParameter <BoolValue>("OffspringSelectionBeforeMutation", "True if the offspring selection step should be applied before mutation, false if it should be applied after mutation."));
            Parameters.Add(new ValueLookupParameter <BoolValue>("FillPopulationWithParents", "True if the population should be filled with parent individual or false if worse children should be used when the maximum selection pressure is exceeded."));
            #endregion

            #region Create operators
            Placeholder                      selector                   = new Placeholder();
            SubScopesProcessor               subScopesProcessor1        = new SubScopesProcessor();
            ChildrenCreator                  childrenCreator            = new ChildrenCreator();
            ConditionalBranch                osBeforeMutationBranch     = new ConditionalBranch();
            UniformSubScopesProcessor        uniformSubScopesProcessor1 = new UniformSubScopesProcessor();
            Placeholder                      crossover1                 = new Placeholder();
            UniformSubScopesProcessor        uniformSubScopesProcessor2 = new UniformSubScopesProcessor();
            Placeholder                      evaluator1                 = new Placeholder();
            SubScopesCounter                 subScopesCounter1          = new SubScopesCounter();
            WeightedParentsQualityComparator qualityComparer1           = new WeightedParentsQualityComparator();
            SubScopesRemover                 subScopesRemover1          = new SubScopesRemover();
            UniformSubScopesProcessor        uniformSubScopesProcessor3 = new UniformSubScopesProcessor();
            StochasticBranch                 mutationBranch1            = new StochasticBranch();
            Placeholder                      mutator1                   = new Placeholder();
            VariableCreator                  variableCreator1           = new VariableCreator();
            VariableCreator                  variableCreator2           = new VariableCreator();
            ConditionalSelector              conditionalSelector        = new ConditionalSelector();
            SubScopesProcessor               subScopesProcessor2        = new SubScopesProcessor();
            UniformSubScopesProcessor        uniformSubScopesProcessor4 = new UniformSubScopesProcessor();
            Placeholder                      evaluator2                 = new Placeholder();
            SubScopesCounter                 subScopesCounter2          = new SubScopesCounter();
            MergingReducer                   mergingReducer1            = new MergingReducer();
            UniformSubScopesProcessor        uniformSubScopesProcessor5 = new UniformSubScopesProcessor();
            Placeholder                      crossover2                 = new Placeholder();
            StochasticBranch                 mutationBranch2            = new StochasticBranch();
            Placeholder                      mutator2                   = new Placeholder();
            UniformSubScopesProcessor        uniformSubScopesProcessor6 = new UniformSubScopesProcessor();
            Placeholder                      evaluator3                 = new Placeholder();
            SubScopesCounter                 subScopesCounter3          = new SubScopesCounter();
            WeightedParentsQualityComparator qualityComparer2           = new WeightedParentsQualityComparator();
            SubScopesRemover                 subScopesRemover2          = new SubScopesRemover();
            OffspringSelector                offspringSelector          = new OffspringSelector();
            SubScopesProcessor               subScopesProcessor3        = new SubScopesProcessor();
            BestSelector                     bestSelector               = new BestSelector();
            WorstSelector                    worstSelector              = new WorstSelector();
            RightReducer                     rightReducer               = new RightReducer();
            LeftReducer                      leftReducer                = new LeftReducer();
            MergingReducer                   mergingReducer2            = new MergingReducer();
            ConditionalBranch                reevaluateElitesBranch     = new ConditionalBranch();
            UniformSubScopesProcessor        uniformSubScopesProcessor7 = new UniformSubScopesProcessor();
            Placeholder                      evaluator4                 = new Placeholder();
            SubScopesCounter                 subScopesCounter4          = new SubScopesCounter();

            selector.Name = "Selector (placeholder)";
            selector.OperatorParameter.ActualName = SelectorParameter.Name;

            childrenCreator.ParentsPerChild = new IntValue(2);

            osBeforeMutationBranch.Name = "Apply OS before mutation?";
            osBeforeMutationBranch.ConditionParameter.ActualName = OffspringSelectionBeforeMutationParameter.Name;

            crossover1.Name = "Crossover (placeholder)";
            crossover1.OperatorParameter.ActualName = CrossoverParameter.Name;

            uniformSubScopesProcessor2.Parallel.Value = true;

            evaluator1.Name = "Evaluator (placeholder)";
            evaluator1.OperatorParameter.ActualName = EvaluatorParameter.Name;

            subScopesCounter1.Name = "Increment EvaluatedSolutions";
            subScopesCounter1.ValueParameter.ActualName = EvaluatedSolutionsParameter.Name;

            qualityComparer1.ComparisonFactorParameter.ActualName = ComparisonFactorParameter.Name;
            qualityComparer1.LeftSideParameter.ActualName         = QualityParameter.Name;
            qualityComparer1.MaximizationParameter.ActualName     = MaximizationParameter.Name;
            qualityComparer1.RightSideParameter.ActualName        = QualityParameter.Name;
            qualityComparer1.ResultParameter.ActualName           = "SuccessfulOffspring";

            subScopesRemover1.RemoveAllSubScopes = true;

            mutationBranch1.ProbabilityParameter.ActualName = MutationProbabilityParameter.Name;
            mutationBranch1.RandomParameter.ActualName      = RandomParameter.Name;

            mutator1.Name = "Mutator (placeholder)";
            mutator1.OperatorParameter.ActualName = MutatorParameter.Name;

            variableCreator1.Name = "MutatedOffspring = true";
            variableCreator1.CollectedValues.Add(new ValueParameter <BoolValue>("MutatedOffspring", null, new BoolValue(true), false));

            variableCreator2.Name = "MutatedOffspring = false";
            variableCreator2.CollectedValues.Add(new ValueParameter <BoolValue>("MutatedOffspring", null, new BoolValue(false), false));

            conditionalSelector.ConditionParameter.ActualName = "MutatedOffspring";
            conditionalSelector.ConditionParameter.Depth      = 1;
            conditionalSelector.CopySelected.Value            = false;

            uniformSubScopesProcessor4.Parallel.Value = true;

            evaluator2.Name = "Evaluator (placeholder)";
            evaluator2.OperatorParameter.ActualName = EvaluatorParameter.Name;

            subScopesCounter2.Name = "Increment EvaluatedSolutions";
            subScopesCounter2.ValueParameter.ActualName = EvaluatedSolutionsParameter.Name;

            crossover2.Name = "Crossover (placeholder)";
            crossover2.OperatorParameter.ActualName = CrossoverParameter.Name;

            mutationBranch2.ProbabilityParameter.ActualName = MutationProbabilityParameter.Name;
            mutationBranch2.RandomParameter.ActualName      = RandomParameter.Name;

            mutator2.Name = "Mutator (placeholder)";
            mutator2.OperatorParameter.ActualName = MutatorParameter.Name;

            uniformSubScopesProcessor6.Parallel.Value = true;

            evaluator3.Name = "Evaluator (placeholder)";
            evaluator3.OperatorParameter.ActualName = EvaluatorParameter.Name;

            subScopesCounter3.Name = "Increment EvaluatedSolutions";
            subScopesCounter3.ValueParameter.ActualName = EvaluatedSolutionsParameter.Name;

            qualityComparer2.ComparisonFactorParameter.ActualName = ComparisonFactorParameter.Name;
            qualityComparer2.LeftSideParameter.ActualName         = QualityParameter.Name;
            qualityComparer2.MaximizationParameter.ActualName     = MaximizationParameter.Name;
            qualityComparer2.RightSideParameter.ActualName        = QualityParameter.Name;
            qualityComparer2.ResultParameter.ActualName           = "SuccessfulOffspring";

            subScopesRemover2.RemoveAllSubScopes = true;

            offspringSelector.CurrentSuccessRatioParameter.ActualName        = CurrentSuccessRatioParameter.Name;
            offspringSelector.MaximumSelectionPressureParameter.ActualName   = MaximumSelectionPressureParameter.Name;
            offspringSelector.SelectionPressureParameter.ActualName          = SelectionPressureParameter.Name;
            offspringSelector.SuccessRatioParameter.ActualName               = SuccessRatioParameter.Name;
            offspringSelector.OffspringPopulationParameter.ActualName        = "OffspringPopulation";
            offspringSelector.OffspringPopulationWinnersParameter.ActualName = "OffspringPopulationWinners";
            offspringSelector.SuccessfulOffspringParameter.ActualName        = "SuccessfulOffspring";
            offspringSelector.FillPopulationWithParentsParameter.ActualName  = FillPopulationWithParentsParameter.Name;

            bestSelector.CopySelected = new BoolValue(false);
            bestSelector.MaximizationParameter.ActualName = MaximizationParameter.Name;
            bestSelector.NumberOfSelectedSubScopesParameter.ActualName = ElitesParameter.Name;
            bestSelector.QualityParameter.ActualName = QualityParameter.Name;

            worstSelector.CopySelected = new BoolValue(false);
            worstSelector.MaximizationParameter.ActualName = MaximizationParameter.Name;
            worstSelector.NumberOfSelectedSubScopesParameter.ActualName = ElitesParameter.Name;
            worstSelector.QualityParameter.ActualName = QualityParameter.Name;

            reevaluateElitesBranch.ConditionParameter.ActualName = "ReevaluateElites";
            reevaluateElitesBranch.Name = "Reevaluate elites ?";

            uniformSubScopesProcessor7.Parallel.Value = true;

            evaluator4.Name = "Evaluator (placeholder)";
            evaluator4.OperatorParameter.ActualName = EvaluatorParameter.Name;

            subScopesCounter4.Name = "Increment EvaluatedSolutions";
            subScopesCounter4.ValueParameter.ActualName = EvaluatedSolutionsParameter.Name;
            #endregion

            #region Create operator graph
            OperatorGraph.InitialOperator = selector;
            selector.Successor            = subScopesProcessor1;
            subScopesProcessor1.Operators.Add(new EmptyOperator());
            subScopesProcessor1.Operators.Add(childrenCreator);
            subScopesProcessor1.Successor        = offspringSelector;
            childrenCreator.Successor            = osBeforeMutationBranch;
            osBeforeMutationBranch.TrueBranch    = uniformSubScopesProcessor1;
            osBeforeMutationBranch.FalseBranch   = uniformSubScopesProcessor5;
            osBeforeMutationBranch.Successor     = null;
            uniformSubScopesProcessor1.Operator  = crossover1;
            uniformSubScopesProcessor1.Successor = uniformSubScopesProcessor2;
            crossover1.Successor = null;
            uniformSubScopesProcessor2.Operator  = evaluator1;
            uniformSubScopesProcessor2.Successor = subScopesCounter1;
            evaluator1.Successor                 = qualityComparer1;
            qualityComparer1.Successor           = subScopesRemover1;
            subScopesRemover1.Successor          = null;
            subScopesCounter1.Successor          = uniformSubScopesProcessor3;
            uniformSubScopesProcessor3.Operator  = mutationBranch1;
            uniformSubScopesProcessor3.Successor = conditionalSelector;
            mutationBranch1.FirstBranch          = mutator1;
            mutationBranch1.SecondBranch         = variableCreator2;
            mutationBranch1.Successor            = null;
            mutator1.Successor            = variableCreator1;
            variableCreator1.Successor    = null;
            variableCreator2.Successor    = null;
            conditionalSelector.Successor = subScopesProcessor2;
            subScopesProcessor2.Operators.Add(new EmptyOperator());
            subScopesProcessor2.Operators.Add(uniformSubScopesProcessor4);
            subScopesProcessor2.Successor        = mergingReducer1;
            uniformSubScopesProcessor4.Operator  = evaluator2;
            uniformSubScopesProcessor4.Successor = subScopesCounter2;
            evaluator2.Successor                 = null;
            subScopesCounter2.Successor          = null;
            mergingReducer1.Successor            = null;
            uniformSubScopesProcessor5.Operator  = crossover2;
            uniformSubScopesProcessor5.Successor = uniformSubScopesProcessor6;
            crossover2.Successor                 = mutationBranch2;
            mutationBranch2.FirstBranch          = mutator2;
            mutationBranch2.SecondBranch         = null;
            mutationBranch2.Successor            = null;
            mutator2.Successor = null;
            uniformSubScopesProcessor6.Operator  = evaluator3;
            uniformSubScopesProcessor6.Successor = subScopesCounter3;
            evaluator3.Successor               = qualityComparer2;
            qualityComparer2.Successor         = subScopesRemover2;
            subScopesRemover2.Successor        = null;
            subScopesCounter3.Successor        = null;
            offspringSelector.OffspringCreator = selector;
            offspringSelector.Successor        = subScopesProcessor3;
            subScopesProcessor3.Operators.Add(bestSelector);
            subScopesProcessor3.Operators.Add(worstSelector);
            subScopesProcessor3.Successor        = mergingReducer2;
            bestSelector.Successor               = rightReducer;
            rightReducer.Successor               = reevaluateElitesBranch;
            reevaluateElitesBranch.TrueBranch    = uniformSubScopesProcessor7;
            uniformSubScopesProcessor7.Operator  = evaluator4;
            uniformSubScopesProcessor7.Successor = subScopesCounter4;
            subScopesCounter4.Successor          = null;
            reevaluateElitesBranch.FalseBranch   = null;
            reevaluateElitesBranch.Successor     = null;
            worstSelector.Successor              = leftReducer;
            leftReducer.Successor     = null;
            mergingReducer2.Successor = null;
            #endregion
        }
Esempio n. 2
0
    IEnumerator Start()
    {
        var logPath = string.Format("logs_{0}", DateTime.Now.Ticks);

        Debug.LogFormat("Logging to {0}", logPath);

        if (!Directory.Exists(logPath))
        {
            Directory.CreateDirectory(logPath);
        }

        elitesLog     = File.CreateText(Path.Combine(logPath, "elites.csv"));
        populationLog = File.CreateText(Path.Combine(logPath, "populations.csv"));
        generationLog = File.CreateText(Path.Combine(logPath, "generations.csv"));
        speciesLog    = File.CreateText(Path.Combine(logPath, "species.csv"));

        var populationSize = 100;
        var innovations    = new InnovationCollection();

        var mutations = new MutationCollection();

        mutations.Add(0.01f, new AddNeuronMutator(innovations));     // 0.1%
        mutations.Add(0.05f, new AddSynapseMutator(innovations));    // 1%
        mutations.Add(0.05f, new ToggleSynapseMutator(0.125f));
        mutations.Add(0.20f, new PerturbNeuronMutator(0.5f, 0.25f)); // 98% vvv
        mutations.Add(0.20f, new PerturbSynapseMutator(0.5f, 0.25f));
        mutations.Add(0.20f, new ReplaceNeuronMutator(0.5f));
        mutations.Add(0.20f, new ReplaceSynapseMutator(0.5f));

        var eliteSelector = new EliteSelector();

        var crossover         = new MultipointCrossover();
        var offspringSelector = new OffspringSelector(crossover);

        var distanceMetric = new DistanceMetric(2.0f, 2.0f, 1.0f);
        var speciation     = new Speciation(10, 6.0f, 0.3f, distanceMetric);

        var neuronGenes = new [] {
            new NeuronGene(innovations.GetInitialNeuronInnovationId(0), NeuronType.UpperNeuron),
            new NeuronGene(innovations.GetInitialNeuronInnovationId(1), NeuronType.LowerNeuron),
            new NeuronGene(innovations.GetInitialNeuronInnovationId(2), NeuronType.PositionNeuron),
            new NeuronGene(innovations.GetInitialNeuronInnovationId(3), NeuronType.SpeedNeuron),
        }.ToGeneList();
        var synapseGenes  = new GeneList <SynapseGene>();
        var protoGenotype = new Genotype(neuronGenes, synapseGenes);

        var genotypes = new GenotypeStream(protoGenotype)
                        .Take(populationSize).ToArray();

        var species    = new Specie[0];
        var generation = 0;

        var elitePhenotypes     = new List <Phenotype>();
        var offspringPhenotypes = genotypes.Select(gt => new Phenotype(gt)).ToList();

        while (true)
        {
            yield return(StartCoroutine(EvaluatePopulation(offspringPhenotypes)));

            var phenotypes = new List <Phenotype>(elitePhenotypes.Count + offspringPhenotypes.Count);
            phenotypes.AddRange(elitePhenotypes);
            phenotypes.AddRange(offspringPhenotypes);

            Assert.AreEqual(phenotypes.Count, populationSize,
                            "Population size must remain constant");

            var longest = phenotypes.OrderByDescending(pt => pt.BestDuration).First();
            Debug.LogFormat("[{0}] Fitness: {1}, Duration: {2}s ({3}, {4}) (Longest)",
                            generation, longest.MeanFitness, longest.MeanDuration,
                            longest.Genotype.NeuronCount,
                            longest.Genotype.SynapseCount);

            var best = phenotypes.OrderByDescending(pt => pt.Fitness).First();
            Debug.LogFormat("[{0}] Fitness: {1}, Duration: {2}s ({3}, {4}) (Best)",
                            generation, best.MeanFitness, best.MeanDuration,
                            best.Genotype.NeuronCount,
                            best.Genotype.SynapseCount);

            elitesLog.WriteLine(string.Join(",", new string[] {
                generation.ToString(),
                best.Fitness.ToString(),
                best.BestDuration.ToString(),
                JSON.Serialize(best.Genotype.ToJSON()),
            }));

            var meanComplexity = phenotypes.Aggregate(0.0f,
                                                      (sum, pt) => sum + (float)pt.Genotype.Complexity,
                                                      (sum) => sum / (float)phenotypes.Count);

            var meanNeuronCount = phenotypes.Aggregate(0.0f,
                                                       (sum, pt) => sum + (float)pt.Genotype.NeuronCount,
                                                       (sum) => sum / (float)phenotypes.Count);

            var meanSynapseCount = phenotypes.Aggregate(0.0f,
                                                        (sum, pt) => sum + (float)pt.Genotype.SynapseCount,
                                                        (sum) => sum / (float)phenotypes.Count);

            var meanFitness = phenotypes.Aggregate(0.0f,
                                                   (sum, pt) => sum + (float)pt.Fitness,
                                                   (sum) => sum / (float)phenotypes.Count);

            var stdevFitness = phenotypes.Aggregate(0.0f,
                                                    (sum, pt) => sum + Mathf.Pow(pt.Fitness - meanFitness, 2.0f),
                                                    (sum) => Mathf.Sqrt(sum / (float)phenotypes.Count));

            var stdevComplexity = phenotypes.Aggregate(0.0f,
                                                       (sum, pt) => sum + Mathf.Pow((float)pt.Genotype.Complexity - meanComplexity, 2.0f),
                                                       (sum) => Mathf.Sqrt(sum / (float)phenotypes.Count));

            var stdevNeuronCount = phenotypes.Aggregate(0.0f,
                                                        (sum, pt) => sum + Mathf.Pow((float)pt.Genotype.NeuronCount - meanNeuronCount, 2.0f),
                                                        (sum) => Mathf.Sqrt(sum / (float)phenotypes.Count));

            var stdevSynapseCount = phenotypes.Aggregate(0.0f,
                                                         (sum, pt) => sum + Mathf.Pow((float)pt.Genotype.SynapseCount - meanSynapseCount, 2.0f),
                                                         (sum) => Mathf.Sqrt(sum / (float)phenotypes.Count));

            species = speciation.Speciate(species, phenotypes.ToArray());

            Debug.LogFormat("[{0}] Species Count: {1} (Threshold: {2})",
                            generation, species.Length, speciation.DistanceThreshold);

            var meanAdjustedFitness = phenotypes.Aggregate(0.0f,
                                                           (sum, pt) => sum + (float)pt.AdjustedFitness,
                                                           (sum) => sum / (float)phenotypes.Count);

            // standard deviation:
            // take the square root of the average of the squared deviations of the values from their average value
            var stdevAdjustedFitness = phenotypes.Aggregate(0.0f,
                                                            (sum, pt) => sum + Mathf.Pow(pt.AdjustedFitness - meanAdjustedFitness, 2.0f),
                                                            (sum) => Mathf.Sqrt(sum / (float)phenotypes.Count));

            generationLog.WriteLine(new [] {
                generation,
                best.Fitness,
                best.MeanDuration,
                meanAdjustedFitness, stdevAdjustedFitness,
                meanFitness, stdevFitness,
                meanComplexity, stdevComplexity,
                meanNeuronCount, stdevNeuronCount,
                meanSynapseCount, stdevSynapseCount
            }.Stringify());

            foreach (var sp in species)
            {
                speciesLog.WriteLine(new [] {
                    generation,
                    sp.SpeciesId, sp.Count,
                    sp.BestFitness,
                    sp.MeanFitness,
                    sp.MeanAdjustedFitness,
                    sp.MeanComplexity,
                }.Stringify());

                foreach (var pt in sp)
                {
                    populationLog.WriteLine(new [] {
                        generation,
                        sp.SpeciesId,
                        pt.Fitness,
                        pt.AdjustedFitness,
                        pt.BestDuration,
                        pt.Genotype.Complexity,
                        pt.Genotype.NeuronCount,
                        pt.Genotype.SynapseCount,
                    }.Stringify());
                }
            }

            var eliteCount = species.Length;
            elitePhenotypes = eliteSelector.Select(species, eliteCount);

            var offspringCount     = populationSize - elitePhenotypes.Count;
            var offspringGenotypes = offspringSelector.Select(species, offspringCount);

            var mutationResults = mutations.Mutate(offspringGenotypes);
            Debug.LogFormat("[{0}] Mutations: Added Neurons: {1}, Added Synapses: {2}, Perturbed Neurons: {3}, Perturbed Synapses: {4}, Replaced Neurons: {5}, Replaced Synapses: {6}, Toggled Synapses: {7}, Pruned Synapses: {8}, Orphaned Neurons: {9}",
                            generation,
                            mutationResults.addedNeurons,
                            mutationResults.addedSynapses,
                            mutationResults.perturbedNeurons,
                            mutationResults.perturbedSynapses,
                            mutationResults.replacedNeurons,
                            mutationResults.replacedSynapses,
                            mutationResults.toggledSynapses,
                            mutationResults.prunedSynapses,
                            mutationResults.orphanedNeurons);

            offspringPhenotypes = offspringGenotypes.Select(gt => new Phenotype(gt)).ToList();

            generation++;

            // Flush these so we can preview results while it runs
            generationLog.Flush();
            populationLog.Flush();
            speciesLog.Flush();
        }
    }