// <summary> /// Parses a NeuralChromosome attributes. /// </summary> /// <param name="chromosomeMetadata">The chromosome metadata.</param> /// <param name="element">The NeuralChromosome element.</param> private static void ParseNeuralChromosomeAttributes(ref IChromosomeMetadata chromosomeMetadata, XElement element) { foreach (var attribute in element.Attributes()) { switch (attribute.Name.LocalName) { case "InputSize": chromosomeMetadata.Properties["InputSize"] = UInt32.Parse(attribute.Value); break; case "OutputSize": chromosomeMetadata.Properties["OutputSize"] = UInt32.Parse(attribute.Value); break; case "C1": chromosomeMetadata.Properties["C1"] = Double.Parse(attribute.Value); break; case "C2": chromosomeMetadata.Properties["C2"] = Double.Parse(attribute.Value); break; case "C3": chromosomeMetadata.Properties["C3"] = Double.Parse(attribute.Value); break; case "ActivationFunction": chromosomeMetadata.Properties["ActivationFunction"] = (int)Enum.Parse(typeof(ActivationFunction), attribute.Value); break; } } }
/// <summary> /// Parses a Chromosome element. /// </summary> /// <param name="element">The Chromosome element.</param> /// <returns>The parsed chromosome.</returns> private static IList <IChromosomeMetadata> ParseChromosome(XElement element) { var attributes = element.Attributes(); var repeatAttribute = attributes.FirstOrDefault(attribute => attribute.Name.LocalName == "Repeat"); var repeat = repeatAttribute == null ? 1 : Int32.Parse(repeatAttribute.Value); var chromosomeMetadataList = new List <IChromosomeMetadata>(); for (var i = 0; i < repeat; i++) { IChromosomeMetadata chromosomeMetadata = null; switch (element.Name.LocalName) { case "BinaryChromosome": chromosomeMetadata = ParseBinaryChromosome(element); break; case "PermutationChromosome": chromosomeMetadata = ParsePermutationChromosome(element); break; case "NeuralChromosome": chromosomeMetadata = ParseNeuralChromosome(element); break; } ParseChromosomeAttributes(ref chromosomeMetadata, element, i); chromosomeMetadataList.Add(chromosomeMetadata); } return(chromosomeMetadataList); }
/// <summary> /// Validates the chromosome metadata properties. /// </summary> /// <param name="chromosomeMetadata">The chromosome metatadata to validate.</param> private static void ValidateChromosomeProperties(IChromosomeMetadata chromosomeMetadata) { if (chromosomeMetadata.CrossoverRate < 0 || chromosomeMetadata.CrossoverRate > 1) { throw new ArgumentException("Error! Crossover rate must be a value between 0 and 1."); } if (chromosomeMetadata.MutationRate < 0 || chromosomeMetadata.MutationRate > 1) { throw new ArgumentException("Error! Mutation rate must be a value between 0 and 1."); } switch (chromosomeMetadata.Type) { case ChromosomeType.Binary: ValidateBinaryChromosomeProperties(chromosomeMetadata); break; case ChromosomeType.Permutation: ValidatePermutationChromosomeProperties(chromosomeMetadata); break; case ChromosomeType.Neural: ValidateNeuralChromosomeProperties(chromosomeMetadata); break; } }
/// <summary> /// Validate that the given property existis in the metadata. /// </summary> /// <param name="chromosomeMetadata">The chromosome metatadata to validate.</param> /// <param name="name">The property name.</param> private static void ValidatePropertyExists(IChromosomeMetadata chromosomeMetadata, string name) { if (!chromosomeMetadata.Properties.ContainsKey(name)) { throw new ArgumentException($"Error! Binary chromosome metadata must contain the {name} property"); } }
/// <summary> /// Adds chromosome metadata to the metadata. /// </summary> /// <param name="metadata">The metadata to add.</param> internal void AddChromosomeMetadata(IChromosomeMetadata metadata) { if (_chromosomeMetadata.Any(t => t.Name == metadata.Name)) { throw new ArgumentException($"Error! Chromosome metadata named {metadata.Name} already exists."); } _chromosomeMetadata.Add(metadata); }
// <summary> /// Parses a PermutationChromosome attributes. /// </summary> /// <param name="chromosomeMetadata">The chromosome metadata.</param> /// <param name="element">The PermutationChromosome element.</param> private static void ParsePermutationChromosomeAttributes(ref IChromosomeMetadata chromosomeMetadata, XElement element) { foreach (var attribute in element.Attributes()) { switch (attribute.Name.LocalName) { case "GeneCount": chromosomeMetadata.Properties["GeneCount"] = UInt32.Parse(attribute.Value); break; } } }
/// <summary> /// Parses the chromosome mutation operators. /// </summary> /// <typeparam name="TCrossover">The crossover operator type.</typeparam> /// <typeparam name="TMutation">The mutation operator type.</typeparam> /// <param name="chromosomeMetadata">The chromosome metadata.</param> /// <param name="element">The chromosome element.</param> private static void ParseMutationOperators <TCrossover, TMutation>(ref IChromosomeMetadata chromosomeMetadata, XElement element) { foreach (var child in element.Elements()) { var weightAttribute = child.Attributes().FirstOrDefault(attribute => attribute.Name.LocalName == "Weight"); var weight = weightAttribute == null ? 1 : Double.Parse(weightAttribute.Value); var mutations = ParseOperator <TMutation>(child); var metadata = (ChromosomeMetadata <TCrossover, TMutation>)chromosomeMetadata; metadata.AddMutationOperators(mutations, weight); } }
/// <summary> /// Parses the chromosome genetic operators. /// </summary> /// <typeparam name="TCrossover">The crossover operator type.</typeparam> /// <typeparam name="TMutation">The mutation operator type.</typeparam> /// <param name="chromosomeMetadata">The chromosome metadata.</param> /// <param name="element">The chromosome element.</param> private static void ParseOperators <TCrossover, TMutation>(ref IChromosomeMetadata chromosomeMetadata, XElement element) { foreach (var child in element.Elements()) { switch (child.Name.LocalName) { case "Crossovers": ParseCrossoverOperators <TCrossover, TMutation>(ref chromosomeMetadata, child); break; case "Mutations": ParseMutationOperators <TCrossover, TMutation>(ref chromosomeMetadata, child); break; } } }
/// <summary> /// Constructs a chromosome from metadata. /// </summary> /// <param name="metadata">The chromosome metadata.</param> /// <returns>The chromosome.</returns> public static IChromosome ConstructChromosome(IChromosomeMetadata metadata) { switch (metadata.Type) { case ChromosomeType.Binary: return(new BinaryChromosome((uint)metadata.Properties[@"GeneCount"])); case ChromosomeType.Permutation: return(new PermutationChromosome((uint)metadata.Properties[@"GeneCount"])); case ChromosomeType.Neural: return(new NeuralChromosome((uint)metadata.Properties[@"InputSize"], (uint)metadata.Properties["OutputSize"], metadata.Name, metadata.Properties[@"C1"], metadata.Properties[@"C2"], metadata.Properties[@"C3"], (ActivationFunction)metadata.Properties["ActivationFunction"])); default: throw new ArgumentException($"Error! Invalid chromosome type."); } }
/// <summary> /// Parses the chromosome attributes. /// </summary> /// <param name="chromosomeMetadata">The chromosome metadata.</param> /// <param name="element">The chromosome element.</param> /// <param name="i">The current repeat count.</param> private static void ParseChromosomeAttributes(ref IChromosomeMetadata chromosomeMetadata, XElement element, int i) { foreach (var attribute in element.Attributes()) { switch (attribute.Name.LocalName) { case "Name": chromosomeMetadata.Name = Regex.Replace(attribute.Value, "%i", $"{i}"); break; case "CrossoverRate": chromosomeMetadata.CrossoverRate = Double.Parse(attribute.Value); break; case "MutationRate": chromosomeMetadata.MutationRate = Double.Parse(attribute.Value); break; } } }
/// <summary> /// Validates the neural chromosome metadata properties. /// </summary> /// <param name="chromosomeMetadata">The chromosome metatadata to validate.</param> private static void ValidateNeuralChromosomeProperties(IChromosomeMetadata chromosomeMetadata) { ValidatePropertyExists(chromosomeMetadata, "InputSize"); ValidatePropertyExists(chromosomeMetadata, "OutputSize"); ValidatePropertyExists(chromosomeMetadata, "C1"); ValidatePropertyExists(chromosomeMetadata, "C2"); ValidatePropertyExists(chromosomeMetadata, "C3"); ValidatePropertyExists(chromosomeMetadata, "ActivationFunction"); if (chromosomeMetadata.Properties["C1"] < 0) { throw new ArgumentException("Error! C1 must be a positive value."); } if (chromosomeMetadata.Properties["C2"] < 0) { throw new ArgumentException("Error! C2 must be a positive value."); } if (chromosomeMetadata.Properties["C3"] < 0) { throw new ArgumentException("Error! C3 must be a positive value."); } }
/// <summary> /// Validates the permutation chromosome metadata properties. /// </summary> /// <param name="chromosomeMetadata">The chromosome metatadata to validate.</param> private static void ValidatePermutationChromosomeProperties(IChromosomeMetadata chromosomeMetadata) { ValidatePropertyExists(chromosomeMetadata, "GeneCount"); }