public Algorithm(int numberOfChromosomes, int replaceByGeneration, int trackBest) { ReplaceByGeneration = replaceByGeneration; CurrentBestSize = 0; Prototype = new Schedule(2, 2, 80, 3); CurrentGeneration = 0; State = AlgorithmState.Userstopped; // there should be at least 2 chromosomes in population if (numberOfChromosomes < 2) numberOfChromosomes = 2; // and algorithm should track at least on of best chromosomes if (trackBest < 1) trackBest = 1; if (ReplaceByGeneration < 1) ReplaceByGeneration = 1; else if (ReplaceByGeneration > numberOfChromosomes - trackBest) ReplaceByGeneration = numberOfChromosomes - trackBest; // reserve space for population Chromosomes = new List<Schedule>(numberOfChromosomes); BestFlags = new List<bool>(numberOfChromosomes); BestChromosomes = new List<int>(trackBest); for (int i = 0; i < numberOfChromosomes; i++) { Chromosomes.Add(null); BestFlags.Add(false); } for (int i = 0; i < trackBest; i++) BestChromosomes.Add(0); }
private void Save(Algorithm alg, Schedule schedule) { foreach (var entry in schedule.Classes) { var courseClass = entry.Key; var pos = entry.Value; var rooms = Configuration.Instance.GetNumberOfRooms(); var day = pos/(Consts.DayHours*rooms); var hour = pos%(Consts.DayHours*rooms); var room = hour/Consts.DayHours; var roomHour = hour%Consts.DayHours; var row = roomHour + 2; var column = day*rooms + room + 1; var sb = new StringBuilder(); var count = 0; foreach (var studentGroup in courseClass.StudentGroups) { sb.Append(studentGroup.Name + ", "); count += studentGroup.StudentCount; } var textblock = new TextBlock { Text = string.Format("Kurs: {0}\nGrupa: {1}\nProfesor: {2}\nLab: {3}\nIlosc: {4}", courseClass.Course.Name, sb, courseClass.Professor.Name, courseClass.IsLabRequired, count), }; var gen = new TextBlock { Text = "Generation: " + alg.CurrentGeneration, }; Grid.SetRow(textblock, row); Grid.SetColumn(textblock, column); Grid.SetRowSpan(textblock, courseClass.LessonDuration); MainGrid.Children.Add(textblock); Grid.SetRow(gen, 0); Grid.SetColumn(gen, 0); MainGrid.Children.Add(gen); } }
// Copy constructor public Schedule(Schedule c, bool setupOnly) { if (!setupOnly) { Slots = new List<List<CourseClass>>(c.Slots.Count); foreach (var tmp in c.Slots) { var list = new List<CourseClass>(tmp.Count); foreach (var el in tmp) list.Add((CourseClass)el.Clone()); Slots.Add(list); } Classes = new Dictionary<CourseClass, int>(c.Classes.Count); foreach (var tmp in c.Classes) Classes.Add((CourseClass)tmp.Key.Clone(), tmp.Value); Criteria = new List<bool>(c.Criteria); Fitness = c.Fitness; } else { Slots = new List<List<CourseClass>>(Consts.DayCount * Consts.DayHours * Configuration.Instance.GetNumberOfRooms()); for (int i = 0; i < Slots.Capacity; ++i) Slots.Add(new List<CourseClass>()); Criteria = new List<bool>(Configuration.Instance.GetNumberOfCourseClasses() * 5); for (int i = 0; i < Criteria.Capacity; ++i) Criteria.Add(false); Classes = new Dictionary<CourseClass, int>(); } NumberOfCrossoverPoints = c.NumberOfCrossoverPoints; MutationSize = c.MutationSize; MutationProbability = c.MutationProbability; CrossoverProbability = c.CrossoverProbability; }
// Makes new chromosome with same setup but with randomly chosen code public Schedule MakeNewFromPrototype() { // number of time-space slots int size = Slots.Count; //// make new chromosome, copy chromosome setup Schedule newChromosome = new Schedule(this, true); // place classes at random position List<CourseClass> c = Configuration.Instance.CourseClasses; foreach (var courseClass in c) { // determine random position of class int nr = Configuration.Instance.GetNumberOfRooms(); int duration = courseClass.LessonDuration; int day = random.Next(0, Consts.DayCount); int room = random.Next(0, nr); int time = random.Next(0, Consts.DayHours + 1 - duration); int pos = day * nr * Consts.DayHours + room * Consts.DayHours + time; // fill time-space slots, for each hour of class for (int i = duration - 1; i >= 0; i--) newChromosome.Slots[pos + i].Add(courseClass); // insert in class table of chromosome newChromosome.Classes.Add(courseClass, pos); } newChromosome.CalculateFitness(); return newChromosome; }
// Performes crossover operation using to chromosomes and returns pointer to offspring public Schedule Crossover(Schedule parent2) { // // check probability of crossover operation if (random.Next(100) > CrossoverProbability) // no crossover, just copy first parent return new Schedule(this, false); // new chromosome object, copy chromosome setup Schedule n = new Schedule(this, true); //// number of classes int size = Classes.Count; List<bool> cp = new List<bool>(size); for (int i = 0; i < size; ++i) cp.Add(false); // determine crossover point (randomly) for (int i = NumberOfCrossoverPoints; i > 0; i--) { while (true) { int p = random.Next(size); if (!cp[p]) { cp[p] = true; break; } } } // make new code by combining parent codes bool first = random.Next(1000) % 2 == 0; for (int i = 0, k = 0, j = 0; i < size; i++, j++, k++) { if (first) { // insert class from first parent into new chromosome's calss table var classValue = Classes.ElementAt(k); n.Classes.Add(classValue.Key, classValue.Value); // all time-space slots of class are copied for (int x = classValue.Key.LessonDuration - 1; x >= 0; x--) { n.Slots[classValue.Value + x].Add(classValue.Key); } } else { // insert class from second parent into new chromosome's calss table var classValue = parent2.Classes.ElementAt(j); n.Classes.Add(classValue.Key, classValue.Value); // all time-space slots of class are copied for (int x = classValue.Key.LessonDuration - 1; x >= 0; x--) { n.Slots[classValue.Value + x].Add(classValue.Key); } } //crossover point if (cp[i]) first = !first; } n.CalculateFitness(); return n; }