/// <summary> /// Create a new genome by combining two genomes. /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static TankGenome CrossOver(TankGenome a, TankGenome b) { if (a == null || b == null) { throw new ArgumentNullException(a == null ? "a" : "b"); } var result = new TankGenome(); var points = TotalAttributePoints; // populate the attributes with the minimum value from each parent foreach (var attribute in Attributes) { var value = Math.Min(a.GetAttribute(attribute), b.GetAttribute(attribute)); result.m_attributes[attribute] = value; points -= value; } // distribute the remaining points while (points > 0) { result.m_attributes[result.GetRandomAttribute(false, true, null)]++; points--; } result.GenomeType = GenomeType.CrossOver; Debug.Assert(result.Validate()); return(result); }
// select two random genomes from the list and cross them to make a child private static TankGenome DoCrossover(IReadOnlyList <TankGenome> genomes) { var a = genomes[Random.Next(genomes.Count)]; var b = a; while (a == b) { b = genomes[Random.Next(genomes.Count)]; } return(TankGenome.CrossOver(a, b)); }
/// <summary> /// Create the population in a randomized state. /// </summary> /// <param name="size"></param> public TankPopulation(int size) { if (size <= 0) { throw new ArgumentOutOfRangeException("size"); } m_size = size; Generation = 1; for (var i = 0; i < Size; i++) { var genome = new TankGenome { Id = i }; genome.Randomize(); m_genomes[i] = genome; } }
/// <summary> /// Attempts to get a genome from the population. /// </summary> /// <param name="id"></param> /// <param name="genome"></param> /// <returns> /// True if the genome was retrieved. /// </returns> public bool TryGetGenome(int id, out TankGenome genome) { return(m_genomes.TryGetValue(id, out genome)); }