/// <summary> /// Mutates each element of a <see cref="ListEntityBase"/> if it meets a certain /// probability. /// </summary> /// <param name="entity"><see cref="ListEntityBase"/> to be mutated.</param> /// <returns>True if a mutation occurred; otherwise, false.</returns> /// <exception cref="ArgumentNullException"><paramref name="entity"/> is null.</exception> protected override bool GenerateMutation(GeneticEntity entity) { if (entity is null) { throw new ArgumentNullException(nameof(entity)); } ListEntityBase listEntity = (ListEntityBase)entity; if (RandomNumberService.Instance.GetDouble() <= this.MutationRate) { int firstPosition = RandomNumberService.Instance.GetRandomValue(listEntity.Length - 1); int secondPosition; do { secondPosition = RandomNumberService.Instance.GetRandomValue(listEntity.Length - 1); } while (secondPosition == firstPosition); object?firstValue = listEntity.GetValue(firstPosition); listEntity.SetValue(firstPosition, listEntity.GetValue(secondPosition)); listEntity.SetValue(secondPosition, firstValue); return(true); } return(false); }
/// <summary> /// Mutates each bit of a <see cref="ListEntityBase{T}"/> if it meets a certain /// probability. /// </summary> /// <param name="entity"><see cref="ListEntityBase{T}"/> to be mutated.</param> /// <returns>True if a mutation occurred; otherwise, false.</returns> /// <exception cref="ArgumentNullException"><paramref name="entity"/> is null.</exception> protected override bool GenerateMutation(GeneticEntity entity) { if (entity is null) { throw new ArgumentNullException(nameof(entity)); } bool isMutated = false; ListEntityBase <bool> bsEntity = (ListEntityBase <bool>)entity; for (int i = 0; i < bsEntity.Length; i++) { if (RandomNumberService.Instance.GetDouble() <= this.MutationRate) { isMutated = true; if (!bsEntity[i]) { bsEntity[i] = true; } else { bsEntity[i] = false; } } } return(isMutated); }
/// <summary> /// When overriden in a derived class, generates a crossover based on the parent entities. /// </summary> /// <param name="parents">The <see cref="GeneticEntity"/> objects to be operated upon.</param> /// <returns> /// Collection of the <see cref="GeneticEntity"/> objects resulting from the crossover. /// </returns> protected override IEnumerable <GeneticEntity> GenerateCrossover(IList <GeneticEntity> parents) { if (parents == null) { throw new ArgumentNullException(nameof(parents)); } ListEntityBase listEntity1 = (ListEntityBase)parents[0]; ListEntityBase listEntity2 = (ListEntityBase)parents[1]; int crossoverLocus1 = RandomNumberService.Instance.GetRandomValue(listEntity1.Length); int crossoverLocus2 = RandomNumberService.Instance.GetRandomValue(listEntity2.Length); IList <GeneticEntity> crossoverOffspring = new List <GeneticEntity>(); List <object?> entity1Elements = GetEntityElements(listEntity1); List <object?> entity2Elements = GetEntityElements(listEntity2); ReplaceBits(listEntity1, entity2Elements, crossoverLocus1, crossoverLocus2); ReplaceBits(listEntity2, entity1Elements, crossoverLocus2, crossoverLocus1); crossoverOffspring.Add(listEntity1); crossoverOffspring.Add(listEntity2); return(crossoverOffspring); }
/// <summary> /// Replaces the elements in <paramref name="entity"/>, starting at <paramref name="targetCrossoverLocus"/>, /// with the elements located in <paramref name="sourceElements"/> starting at <paramref name="sourceCrossoverLocus"/>. /// </summary> /// <param name="entity"><see cref="ListEntityBase"/> whose bits are to be replaced.</param> /// <param name="sourceElements">List of elements to replace with.</param> /// <param name="targetCrossoverLocus">Element position at which to begin replacement.</param> /// <param name="sourceCrossoverLocus">Element position of the source elements to begin copying from.</param> private static void ReplaceBits(ListEntityBase entity, List <object?> sourceElements, int targetCrossoverLocus, int sourceCrossoverLocus) { entity.Length = targetCrossoverLocus + sourceElements.Count - sourceCrossoverLocus; for (int sourceBitIndex = sourceCrossoverLocus, targetBitIndex = targetCrossoverLocus; sourceBitIndex < sourceElements.Count; sourceBitIndex++, targetBitIndex++) { entity.SetValue(targetBitIndex, sourceElements[sourceBitIndex]); } }
/// <summary> /// Returns the list of bits contained in <paramref name="entity"/>. /// </summary> /// <param name="entity"><see cref="ListEntityBase"/> whose bits are to be returned.</param> /// <returns>List of bits contained in <paramref name="entity"/>.</returns> private static List <object?> GetEntityElements(ListEntityBase entity) { List <object?> elements = new List <object?>(); for (int i = 0; i < entity.Length; i++) { elements.Add(entity.GetValue(i)); } return(elements); }
/// <summary> /// Returns whether the entity contains the specified value. /// </summary> /// <param name="entity">Entity to use.</param> /// <param name="value">Value to search for.</param> /// <param name="maxIndex">The max index to iterate to when searching for the value.</param> /// <returns>True if the value was found; otherwise, false.</returns> private static bool ContainsValue(ListEntityBase entity, object?value, int maxIndex) { for (int i = 0; i <= maxIndex; i++) { if (Object.Equals(entity.GetValue(i), value)) { return(true); } } return(false); }
/// <summary> /// Mutates each bit of a <see cref="ListEntityBase"/> if it meets a certain /// probability. /// </summary> /// <param name="entity"><see cref="ListEntityBase"/> to be mutated.</param> /// <returns>True if a mutation occurred; otherwise, false.</returns> /// <exception cref="ArgumentNullException"><paramref name="entity"/> is null.</exception> protected override bool GenerateMutation(GeneticEntity entity) { if (entity is null) { throw new ArgumentNullException(nameof(entity)); } ListEntityBase listEntity = (ListEntityBase)entity; if (RandomNumberService.Instance.GetDouble() <= this.MutationRate) { int firstPosition = RandomNumberService.Instance.GetRandomValue(listEntity.Length); int secondPosition; do { secondPosition = RandomNumberService.Instance.GetRandomValue(listEntity.Length); } while (secondPosition == firstPosition); if (firstPosition < secondPosition) { object?currentMovingValue = listEntity.GetValue(firstPosition); for (int i = firstPosition + 1; i <= secondPosition; i++) { object?savedValue = listEntity.GetValue(i); listEntity.SetValue(i, currentMovingValue); currentMovingValue = savedValue; } listEntity.SetValue(firstPosition, currentMovingValue); } else { object?currentMovingValue = listEntity.GetValue(firstPosition); for (int i = firstPosition - 1; i >= secondPosition; i--) { object?savedValue = listEntity.GetValue(i); listEntity.SetValue(i, currentMovingValue); currentMovingValue = savedValue; } listEntity.SetValue(firstPosition, currentMovingValue); } return(true); } return(false); }
private object?GetEntityValue(int index, ListEntityBase entity, ListEntityBase sourceEntity, ListEntityBase originalEntity, ListEntityBase originalOtherEntity) { object?entitySourceVal = sourceEntity.GetValue(index); if (((ListEntityBase?)this.Algorithm?.GeneticEntitySeed)?.RequiresUniqueElementValues == true) { while (ContainsValue(entity, entitySourceVal, index - 1)) { int duplicateValueIndex = originalOtherEntity.IndexOf(entitySourceVal); entitySourceVal = originalEntity.GetValue(duplicateValueIndex); } } return(entitySourceVal); }
/// <summary> /// Returns whether <paramref name="component"/> is valid. /// </summary> /// <param name="component"><see cref="GeneticComponent"/> to be validated.</param> /// <param name="errorMessage">Error message that should be displayed if the component fails validation.</param> /// <returns>True if <paramref name="component"/> is valid; otherwise, false.</returns> public override bool IsValid(GeneticComponent component, out string?errorMessage) { errorMessage = null; ListEntityBase entity = (ListEntityBase)component; if (entity.MinimumStartingLength > entity.MaximumStartingLength) { errorMessage = StringUtil.GetFormattedString( Resources.ErrorMsg_MismatchedMinMaxValues, nameof(ListEntityBase.MinimumStartingLength), nameof(ListEntityBase.MaximumStartingLength)); } return(errorMessage == null); }
/// <summary> /// When overriden in a derived class, generates a crossover based on the parent entities. /// </summary> /// <param name="parents">The <see cref="GeneticEntity"/> objects to be operated upon.</param> /// <returns> /// Collection of the <see cref="GeneticEntity"/> objects resulting from the crossover. /// </returns> protected override IEnumerable <GeneticEntity> GenerateCrossover(IList <GeneticEntity> parents) { if (parents == null) { throw new ArgumentNullException(nameof(parents)); } ListEntityBase listEntity1 = (ListEntityBase)parents[0]; ListEntityBase listEntity2 = (ListEntityBase)parents[1]; int entity1Length = listEntity1.Length; int entity2Length = listEntity2.Length; int crossoverLocus = RandomNumberService.Instance.GetRandomValue(Math.Min(entity1Length, entity2Length)); IList <GeneticEntity> crossoverOffspring = new List <GeneticEntity>(); int maxLength = Math.Max(entity1Length, entity2Length); // Normalize the lists into a common length if (entity1Length != entity2Length) { listEntity1.Length = maxLength; listEntity2.Length = maxLength; } // swap the elements of the lists starting at the crossover locus for (int i = crossoverLocus; i < maxLength; i++) { object?tempGeneValue = listEntity1.GetValue(i); listEntity1.SetValue(i, listEntity2.GetValue(i)); listEntity2.SetValue(i, tempGeneValue); } // Set the length based on their swapped length listEntity1.Length = entity2Length; listEntity2.Length = entity1Length; crossoverOffspring.Add(listEntity1); crossoverOffspring.Add(listEntity2); return(crossoverOffspring); }
/// <summary> /// Executes a single-point crossover between two list-based entities. /// </summary> /// <param name="parents">The <see cref="GeneticEntity"/> objects to be operated upon.</param> /// <returns> /// Collection of the list-based entities resulting from the crossover. /// </returns> protected override IEnumerable <GeneticEntity> GenerateCrossover(IList <GeneticEntity> parents) { if (parents == null) { throw new ArgumentNullException(nameof(parents)); } ListEntityBase listEntity1 = (ListEntityBase)parents[0]; ListEntityBase listEntity2 = (ListEntityBase)parents[1]; int entity1Length = listEntity1.Length; int entity2Length = listEntity2.Length; List <int> crossoverLoci = new List <int>(); int minLength = Math.Min(entity1Length, entity2Length); // Generate the set of crossover points. for (int i = 0; i < this.CrossoverPointCount; i++) { int crossoverLocus; do { crossoverLocus = RandomNumberService.Instance.GetRandomValue(minLength); } while (crossoverLoci.Contains(crossoverLocus)); crossoverLoci.Add(crossoverLocus); } crossoverLoci.Sort(); IList <GeneticEntity> crossoverOffspring = new List <GeneticEntity>(); // If the number of crossover points is odd and the lengths of the entities are not the // same, the crossover will cause the lengths of the entities to be swapped. bool entityLengthsAreSwapped = (this.CrossoverPointCount % 2 != 0 && entity1Length != entity2Length); int maxLength = Math.Max(entity1Length, entity2Length); if (entityLengthsAreSwapped) { // Normalize the lists into a common length if (entity1Length != entity2Length) { listEntity1.Length = maxLength; listEntity2.Length = maxLength; } } ListEntityBase originalEntity1 = (ListEntityBase)listEntity1.Clone(); ListEntityBase originalEntity2 = (ListEntityBase)listEntity2.Clone(); ListEntityBase entity1Source = listEntity1; ListEntityBase entity2Source = listEntity2; for (int i = crossoverLoci[0]; i < maxLength; i++) { // If this is a crossover point, swap the source entities if (crossoverLoci.Contains(i)) { if (listEntity1 == entity1Source) { entity1Source = listEntity2; entity2Source = listEntity1; } else { entity1Source = listEntity1; entity2Source = listEntity2; } } object?entity1SourceVal = null; object?entity2SourceVal = null; if (i < listEntity1.Length) { entity1SourceVal = this.GetEntityValue(i, listEntity1, entity1Source, originalEntity1, originalEntity2); } if (i < listEntity2.Length) { entity2SourceVal = this.GetEntityValue(i, listEntity2, entity2Source, originalEntity2, originalEntity1); } if (entity1SourceVal != null) { listEntity1.SetValue(i, entity1SourceVal); } if (entity2SourceVal != null) { listEntity2.SetValue(i, entity2SourceVal); } } if (entityLengthsAreSwapped) { // Set the length based on their swapped length listEntity1.Length = entity2Length; listEntity2.Length = entity1Length; } crossoverOffspring.Add(listEntity1); crossoverOffspring.Add(listEntity2); return(crossoverOffspring); }