/// <summary>
        /// Changes the given genome by mutating the gene corresponding to the given <see cref="IParameterNode" />.
        /// </summary>
        /// <param name="genome">The genome to mutate. Will be modified.</param>
        /// <param name="parameterNode">Specification of the parameter / gene to mutate.</param>
        protected void MutateParameter(Genome genome, IParameterNode parameterNode)
        {
            var currentValue = genome.GetGeneValue(parameterNode.Identifier);
            var mutatedValue = parameterNode.Domain.MutateGeneValue(
                currentValue,
                this._mutationVariancePercentage);

            genome.SetGene(parameterNode.Identifier, mutatedValue);
        }
        /// <summary>
        /// Creates a genome with random gene values. A repair operation is applied after the creation
        /// to ensure the genome is valid.
        /// </summary>
        /// <param name="age">The genome's age.</param>
        /// <returns>The created genome.</returns>
        public virtual Genome CreateRandomGenome(int age)
        {
            // Create genome with correct age.
            var genome = new Genome(age);

            // Randomly set each gene value.
            foreach (var parameterNode in this._parameterNodes)
            {
                genome.SetGene(parameterNode.Identifier, parameterNode.Domain.GenerateRandomGeneValue());
            }

            this.MakeGenomeValid(genome);
            return(genome);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Creates a genome with random or default gene values. A repair operation is applied after the creation
        /// to ensure the genome is valid.
        /// </summary>
        /// <param name="age">The genome's age.</param>
        /// <param name="useDefaultValues">Indicates whether to use the domain-default values [false], or random domain values [true]. </param>
        /// <returns>The created genome.</returns>
        protected Genome CreateGenome(int age, bool useDefaultValues = false)
        {
            // Create genome with correct age.
            var genome = new Genome(age);

            // Randomly set each gene value.
            foreach (var parameterNode in this._parameterNodes)
            {
                genome.SetGene(
                    parameterNode.Identifier,
                    useDefaultValues ? parameterNode.Domain.GetDefaultValue() : parameterNode.Domain.GenerateRandomGeneValue());
            }

            this.MakeGenomeValid(genome);
            return(genome);
        }
        /// <summary>
        /// Sets the value for the specified gene on the given child,
        /// respecting its parents and the latest parameter origin.
        /// </summary>
        /// <param name="node">
        /// Specifies the gene to set the value for.
        /// Is allowed to be an <see cref="AndNode" />. In this case, nothing happens.
        /// </param>
        /// <param name="parent1">The first parent.</param>
        /// <param name="parent2">The second parent.</param>
        /// <param name="child">The child. Genome will be modified.</param>
        /// <param name="lastParameterOrigin">
        /// The latest parameter origin.
        /// Influences the probability which parent's gene the child inherits.
        /// </param>
        /// <returns>
        /// The origin of the inherited gene value.
        /// For an <see cref="AndNode" />, returns the given parameter origin.
        /// </returns>
        private ParameterOrigin SetGeneValue(
            IParameterTreeNode node,
            Genome parent1,
            Genome parent2,
            Genome child,
            ParameterOrigin lastParameterOrigin = ParameterOrigin.Open)
        {
            // If the node is not a parameter node, we do not have to set a value.
            // The parameter origin does not change.
            var nodeAsParameter = node as IParameterNode;

            if (nodeAsParameter == null)
            {
                return(lastParameterOrigin);
            }

            // If it is a parameter node, find the parents' gene values.
            var parameterName    = nodeAsParameter.Identifier;
            var parent1GeneValue = parent1.GetGeneValue(parameterName);
            var parent2GeneValue = parent2.GetGeneValue(parameterName);

            // If they are equal and the last parameter's origin is open, set child's parameter value to it
            // and keep the origin.
            if (lastParameterOrigin == ParameterOrigin.Open && object.Equals(parent1GeneValue, parent2GeneValue))
            {
                child.SetGene(parameterName, parent1GeneValue);
                return(lastParameterOrigin);
            }

            // Otherwise, randomly decide on one of the two parents.
            // The probability for the parents is dependent on the last parameter's origin.
            double probabilityForFirstParent;

            switch (lastParameterOrigin)
            {
            case ParameterOrigin.FirstParent:
                probabilityForFirstParent = 1 - this._crossoverSwitchProbability;
                break;

            case ParameterOrigin.SecondParent:
                probabilityForFirstParent = this._crossoverSwitchProbability;
                break;

            case ParameterOrigin.Open:
                probabilityForFirstParent = 0.5;
                break;

            default:
                throw new ArgumentException($"Parameter origin {lastParameterOrigin} is unknown.");
            }

            // Throw a (biased) coin and decide on one parent to inherit the gene value from.
            var useFirstParent = Randomizer.Instance.Decide(probabilityForFirstParent);

            if (useFirstParent)
            {
                child.SetGene(parameterName, parent1GeneValue);
                return(ParameterOrigin.FirstParent);
            }

            child.SetGene(parameterName, parent2GeneValue);
            return(ParameterOrigin.SecondParent);
        }