private byte Swap(Gene gene, ushort geneIndex) { ushort otherIndex = geneIndex; do { otherIndex = CROSSOVER_GEN.GetNext(); } while (otherIndex == geneIndex); Gene otherGene = Genes[otherIndex]; // this function handles the swap for both genes return(gene.FullSwap(otherGene)); }
// gene pool is a list of every possible event block, most of which will be inactive public static int CreatePool(string infoFilesFolder) { Path = infoFilesFolder; AddParameterType("Day", false, 1, 2, 3, 4, 5); AddParameterType("Time", false, 0, 1, 2, 3, 4, 5, 6); string path = infoFilesFolder.TrimEnd('\\') + "\\"; var activitiesCSV = Utils.LoadCSV <ActivityCSV>(path + "Activities.csv"); var activities = activitiesCSV.Select(a => a.ToInfo()).ToList(); var exclusives = activities.Select((a, i) => new { Index = i, Activity = a }).Where(a => a.Activity.Flags.HasFlag(ActivityFlags.Manual)); var dorms = File.ReadAllLines( path + "ExclusiveActivities.txt" ).Select( l => { var split = l.Split( new string[] { " - ", ", " }, StringSplitOptions.None ); return(new DormInfo( split[0], split.Skip(1).Select( a => Convert.ToInt32(a) ).ToArray() )); } ).ToArray(); var manuallyScheduled = Utils.LoadCSV <ManuallyScheduledCSV>(path + "Manually Scheduled.csv").OrderBy(a => a.Day).ThenBy(a => a.Start).ThenBy(a => a.Dorm).ToList(); var blocks = Utils.LoadCSV <BlockCSV>(path + "Days.csv"); AddParameterType("Activity", false, Enumerable.Range(0, activities.Count).Select(a => (byte)a).ToArray()); var dormBytes = Enumerable.Range(0, dorms.Count()).Select(d => (byte)d).Append <byte>(255).ToArray(); AddParameterType("Dorm", true, dormBytes); AddParameterType("OtherDorm", true, dormBytes.Skip(1).ToArray()); dormBytes = null; var immutableList = new List <Gene>(); int blockIndex = 0; byte time = 0; ushort geneID = ushort.MaxValue; foreach (var manual in manuallyScheduled) { while (blocks[blockIndex].Day < manual.Day) { ++blockIndex; time = 0; } while (blocks[blockIndex].Hour < manual.Start.Hours || blocks[blockIndex].Minute < manual.Start.Minutes) { ++blockIndex; ++time; } int blockIndexTemp = blockIndex; byte timeTemp = time; do { immutableList.Add( new Gene( geneID, new byte[] { (byte)manual.Day, time, (byte)exclusives.First(a => a.Activity.Abbreviation == manual.Activity).Index, (byte)Array.FindIndex(dorms, d => d.Abbreviation == manual.Dorm), 255 }, true ) ); --geneID; ++blockIndexTemp; ++timeTemp; } while ( blockIndexTemp < blocks.Length && blocks[blockIndexTemp].Day == manual.Day && blocks[blockIndexTemp].Hour < manual.End.Hours && blocks[blockIndexTemp].Minute < manual.End.Minutes ); } ImmutableGenes = immutableList.ToArray(); immutableList = null; //List<Gene> genePool = new List<Gene>(); //List<Tuple<byte, byte, byte>> genePool = new List<Tuple<byte, byte, byte>>(); List <SimpleImmutable> genePool = new List <SimpleImmutable>(); geneID = 0; var activitiesByDuration = activities.FindAll(a => !a.Flags.HasFlag(ActivityFlags.Manual) && !a.Flags.HasFlag(ActivityFlags.Concurrent)).GroupBy(a => a.Duration); byte concurrentActivity = (byte)activities.First(a => a.Flags.HasFlag(ActivityFlags.Concurrent)).ID; SetupConsts(dorms, activities, path); List <byte> times = new List <byte>(); List <byte> tailTimes = new List <byte>(); //Constants.SURVIVAL_DAYINFO = new DaySurvivalInfo[((byte)blocks.Last().Day) + 1]; int pointer = 0; byte currentDay = 0; byte dayGenesCount = 0; byte[] timesGenesCounts = new byte[7]; byte currentTime = 0; // time in the day while (pointer < blocks.Length) { List <BlockCSV> currentBlocks = new List <BlockCSV>(); BlockCSV nextBlock = blocks[pointer]; BlockCSV lastBlock = new BlockCSV(); byte total = 0; // total number of blocks in the set byte available = 0; // number of blocks in the set available to start activities byte excess = 0; // time at the start of this blockset byte timeTemp = currentTime; do { currentBlocks.Add(nextBlock); lastBlock = nextBlock; ++total; if (lastBlock.Excess) { ++excess; } else { ++available; } ++pointer; ++currentTime; if (pointer != blocks.Length) { nextBlock = blocks[pointer]; } } while ( pointer < blocks.Length && nextBlock.Day == lastBlock.Day && nextBlock.Hour - lastBlock.Hour <= 1 ); tailTimes.Add((byte)(timeTemp + available - 1)); foreach (var duration in activitiesByDuration) { if (duration.Key > currentBlocks.Count) { continue; } for (byte actualTime = timeTemp; actualTime < available + timeTemp; actualTime = (byte)(actualTime + duration.Key)) { //byte actualTime = (byte)(currentTime + timeOffset); foreach (var activity in duration) { /*genePool.Add( * new Gene( * geneID, * new byte[] * { * currentDay, * actualTime, * (byte)activity.ID, * 255, * 255 * } * ) * );*/ genePool.Add(new SimpleImmutable(currentDay, actualTime, (byte)activity.ID)); //++geneID; ++dayGenesCount; ++timesGenesCounts[actualTime]; } } } for (byte actualTime = timeTemp; actualTime < available; ++actualTime) { /*genePool.Add( * new Gene( * geneID, * new byte[] * { * currentDay, * actualTime, * concurrentActivity, * 255, * 255 * } * ) * ); ++geneID;*/ genePool.Add(new SimpleImmutable(currentDay, actualTime, concurrentActivity)); ++dayGenesCount; ++timesGenesCounts[actualTime]; } if (nextBlock.Day != lastBlock.Day) { /*Constants.SURVIVAL_DAYINFO[currentDay] = new DaySurvivalInfo( * timesGenesCounts, * tailTimes, * dayGenesCount * );*/ timesGenesCounts = new byte[7]; dayGenesCount = 0; ++currentDay; currentTime = 0; } } int numGenes = genePool.Count; NUM_GENES = (byte)numGenes; Chromosome.CROSSOVER_GEN = new ByteGenerator((byte)numGenes); Pool = new Chromosome[POOL_SIZE]; SamplePool = new Chromosome[SAMPLE_POOL_SIZE]; Func <GeneParameter[]> getGeneParams = () => GeneParams; ImmutableValues = genePool.ToArray(); /* * for (int i = 0; i < numGenes; ++i) * { * var gene = genePool[i]; * ImmutableValues[i, 0] = gene.Item1; * ImmutableValues[i, 1] = gene.Item2; * ImmutableValues[i, 2] = gene.Item3; * }*/ genePool = null; for (int c = 0; c < POOL_SIZE; ++c) { Gene[] chromosome = new Gene[numGenes]; for (int g = 0; g < numGenes; ++g) { //chromosome[g] = genePool[g].Randomize(2); } Pool[c] = new Chromosome(chromosome, getGeneParams); } PoolMinFitness = 0; return(numGenes); }
public Chromosome[] CrossoverWith(Chromosome other, int maxOffspring) { throw new NotImplementedException(); var geneParams = GetGeneParameters(); int numOffspring = (int)(maxOffspring * Stats.Fertility * other.Stats.Fertility) + 1; if (numOffspring % 2 == 1) { ++numOffspring; } int numGenes = Genes.Length; Chromosome[] offspring = new Chromosome[numOffspring]; for (int i = 0; i < numOffspring; i += 2) { int twins = 0; int twinsIndex = i; while (GEN.NextDouble() < TWIN_RATE && ++twinsIndex < numOffspring) { ++twins; } if (twins > 0) { byte[][] child = new byte[geneParams.Length][]; // partial crossover for (byte paramIndex = 0; paramIndex < GenePool.NUM_IMMUTABLE; ++paramIndex) { var point1 = GEN.Next(Genes.Length); var point2 = GEN.Next(Genes.Length); if (point2 > point1) { var temp = point2; point2 = point1; point1 = temp; } byte[] childGenes = new byte[Genes.Length]; SortedDictionary <byte, byte> swapper = new SortedDictionary <byte, byte>(); for (int p = point1; p <= point2; ++p) { byte parent1 = Genes[p][paramIndex]; byte parent2 = other.Genes[p][paramIndex]; if (parent1 == parent2) // shared compatibility/incompatibility { if (!Stats.Survives || !other.Stats.Survives) // shared incompatibility { //child[p] = GenePool.GetGeneParamRandomValue(paramIndex); } else { //child1Genes[p] = parent1; //child2Genes[p] = parent2; } } else { swapper.Add(parent1, parent2); swapper.Add(parent2, parent1); } } for (int p = 0; p < Genes.Length; ++p) { // gets this parameter from each gene byte value1 = Genes[p][paramIndex]; childGenes[p] = swapper.TryGetValue(value1, out byte value) ? value : value1; } child[paramIndex] = childGenes; } // simple crossover for (byte paramIndex = GenePool.NUM_IMMUTABLE; paramIndex < GenePool.NUM_PARAMS; ++paramIndex) { var point1 = GEN.Next(Genes.Length); var point2 = GEN.Next(Genes.Length); if (point2 > point1) { var temp = point2; point2 = point1; point1 = temp; } byte[] childGenes = new byte[Genes.Length]; for (int p = point1; p < point2; ++p) { childGenes[p] = Genes[p][paramIndex]; } for (int p = point2; p < Genes.Length; ++p) { childGenes[p] = other.Genes[p][paramIndex]; } for (int p = 0; p < point1; ++p) { childGenes[p] = other.Genes[p][paramIndex]; } child[paramIndex] = childGenes; } Gene[] genes = new Gene[numGenes]; for (ushort g = 0; g < numGenes; ++g) { byte[] gene = new byte[geneParams.Length]; for (int p = 0; p < geneParams.Length; ++p) { gene[p] = child[p][g]; } genes[g] = new Gene(g, gene); } if (twins % 2 == 0) { ++twinsIndex; } offspring[i] = new Chromosome(genes, GetGeneParameters); for (int k = i + 1; k <= twinsIndex; ++k) { offspring[k] = new Chromosome(genes, GetGeneParameters); } i = twinsIndex - 1; } else { byte[][] child1 = new byte[geneParams.Length][]; byte[][] child2 = new byte[geneParams.Length][]; // partial crossover for (byte paramIndex = 0; paramIndex < GenePool.NUM_IMMUTABLE; ++paramIndex) { //var geneParam = geneParams[index]; (child1[paramIndex], child2[paramIndex]) = PartialCrossover(other, paramIndex); } // simple crossover for (byte paramIndex = GenePool.NUM_IMMUTABLE; paramIndex < GenePool.NUM_PARAMS; ++paramIndex) { (child1[paramIndex], child2[paramIndex]) = SimpleCrossover(other, paramIndex); } Gene[] genes1 = new Gene[numGenes]; Gene[] genes2 = new Gene[numGenes]; for (ushort g = 0; g < numGenes; ++g) { byte[] gene1 = new byte[geneParams.Length]; byte[] gene2 = new byte[geneParams.Length]; for (int p = 0; p < geneParams.Length; ++p) { gene1[p] = child1[p][g]; gene2[p] = child2[p][g]; } genes1[g] = new Gene(g, gene1); genes2[g] = new Gene(g, gene2); } offspring[i] = new Chromosome(genes1, GetGeneParameters); offspring[i + 1] = new Chromosome(genes2, GetGeneParameters); } } return(offspring); }