public Schedule(Schedule firstParent, Schedule secondParent, AlgorithmParameters parameters) : this() { this.DifficultyPattern = parameters; if (firstParent.Timetable.Count != secondParent.Timetable.Count) { throw new GeneticAlgorithmException("Passed pair of parents with different count of days"); } #region Lessons combination List<Day> d = new List<Day>{}; Dictionary<Tuple<Lesson, Parent>, List<Index>> dict = new Dictionary<Tuple<Lesson, Parent>, List<Index>>{ }; Dictionary<Index, List<Tuple<Lesson, Parent>>> indexesDict = new Dictionary<Index,List<Tuple<Lesson,Parent>>>(); for (int day = 0; day < firstParent.Timetable.Count; ++day) { if (firstParent.Timetable[day].Classes.Count != secondParent.Timetable[day].Classes.Count) { throw new GeneticAlgorithmException("Passed pair of parents with different classes for a given day"); } List<ClassSchedule> schedules = new List<ClassSchedule>{ }; for (int classN = 0; classN < firstParent.Timetable[day].Classes.Count; ++classN) { List<Lesson> lessons = new List<Lesson>{ }; for (int lesson = 0; lesson < Math.Max(firstParent.Timetable[day].Classes[classN].Lessons.Count, secondParent.Timetable[day].Classes[classN].Lessons.Count); ++lesson) { bool should = false; /*if (firstParent.Timetable[day].Classes[classN].Lessons[lesson].Equals(secondParent.Timetable[day].Classes[classN].Lessons[lesson])) { lessons.Add(firstParent.Timetable[day].Classes[classN].Lessons[lesson]); } else { lessons.Add(null); }*/ if (firstParent.Timetable[day].Classes[classN].Lessons[lesson] == null && secondParent.Timetable[day].Classes[classN].Lessons[lesson] == null) { lessons.Add(null); } else { if (firstParent.Timetable[day].Classes[classN].Lessons[lesson] != null && secondParent.Timetable[day].Classes[classN].Lessons[lesson] != null) { if (firstParent.Timetable[day].Classes[classN].Lessons[lesson].Equals(secondParent.Timetable[day].Classes[classN].Lessons[lesson])) { lessons.Add(secondParent.Timetable[day].Classes[classN].Lessons[lesson]); } else { should = true; lessons.Add(null); } } else { should = true; lessons.Add(null); } } if (should) { #region dictionary Index shit = new Index(day, classN, lesson); Tuple<Lesson, Parent> t = new Tuple<Lesson, Parent>(firstParent.Timetable[day].Classes[classN].Lessons[lesson], Parent.FirstParent); indexesDict.Add(shit, new List<Tuple<Lesson,Parent>>{ t }); if (dict.ContainsKey(t)) dict[t].Add(shit); else dict.Add(t, new List<Index> { shit }); t = new Tuple<Lesson, Parent>(secondParent.Timetable[day].Classes[classN].Lessons[lesson], Parent.SecondParent); indexesDict[shit].Add(t); if (dict.ContainsKey(t)) dict[t].Add(shit); else dict.Add(t, new List<Index> { shit }); #endregion } } ClassSchedule cs = new ClassSchedule(firstParent.Timetable[day].Classes[classN].Class, lessons); schedules.Add(cs); } Day current = new Day(schedules); d.Add(current); } this.mDays = d; Tuple<Lesson, Parent>[] a = new Tuple<Lesson,Parent>[dict.Keys.Count]; dict.Keys.CopyTo(a, 0); int rand; Random rnd = new Random(); #region Old resolving /* int left = dict.Count; while (dict.Count != 0 && left > 0) { rand = rnd.Next(left); Tuple<Lesson, Parent> t = a[rand]; if (!dict.ContainsKey(t)) { goto end; } List<Index> li = dict[t]; Index inx = li[li.Count - 1]; li.RemoveAt(li.Count - 1); if (li.Count == 0) { if (t.Item2 == Parent.FirstParent) { dict.Remove(new Tuple<Lesson,Parent>(t.Item1, Parent.SecondParent)); } else { dict.Remove(new Tuple<Lesson,Parent>(t.Item1, Parent.FirstParent)); } dict.Remove(t); } if (t.Item2 == Parent.FirstParent) { d[inx.Day].Classes[inx.ClassN].Lessons[inx.Period] = firstParent.Timetable[inx.Day].Classes[inx.ClassN].Lessons[inx.Period]; } else { d[inx.Day].Classes[inx.ClassN].Lessons[inx.Period] = secondParent.Timetable[inx.Day].Classes[inx.ClassN].Lessons[inx.Period]; } end: left--; Tuple<Lesson, Parent> swap = a[rand]; a[rand] = a[left]; a[left] = swap; }*/ #endregion int ConflictsCount = 0; #region New Resolving - up-to-date at 21 March of 2011 foreach (var item in dict) { ConflictsCount += item.Value.Count; } ConflictsCount /= 2; int ConflictsResolved = 0; try { while (ConflictsResolved < ConflictsCount) { #region build indexesDict indexesDict = new Dictionary<Index, List<Tuple<Lesson, Parent>>>(); for (int day = 0; day < firstParent.Timetable.Count; ++day) { if (firstParent.Timetable[day].Classes.Count != secondParent.Timetable[day].Classes.Count) { throw new GeneticAlgorithmException("Passed pair of parents with different classes for a given day"); } for (int classN = 0; classN < firstParent.Timetable[day].Classes.Count; ++classN) { for (int lesson = 0; lesson < Math.Max(firstParent.Timetable[day].Classes[classN].Lessons.Count, secondParent.Timetable[day].Classes[classN].Lessons.Count); ++lesson) { bool should = false; if (firstParent.Timetable[day].Classes[classN].Lessons[lesson] == null && secondParent.Timetable[day].Classes[classN].Lessons[lesson] == null) { should = false; } else { if (firstParent.Timetable[day].Classes[classN].Lessons[lesson] != null && secondParent.Timetable[day].Classes[classN].Lessons[lesson] != null) { if (firstParent.Timetable[day].Classes[classN].Lessons[lesson].Equals(secondParent.Timetable[day].Classes[classN].Lessons[lesson])) { should = false; } else { should = true; } } else { should = true; } } if (this.Timetable[day].Classes[classN].Lessons[lesson] != null) if (should) { #region dictionary Index shit = new Index(day, classN, lesson); Tuple<Lesson, Parent> t = new Tuple<Lesson, Parent>(firstParent.Timetable[day].Classes[classN].Lessons[lesson], Parent.FirstParent); indexesDict.Add(shit, new List<Tuple<Lesson, Parent>> { t }); t = new Tuple<Lesson, Parent>(secondParent.Timetable[day].Classes[classN].Lessons[lesson], Parent.SecondParent); indexesDict[shit].Add(t); #endregion } } } } #endregion if (dict.Count == 0) { throw new GeneticAlgorithmException(); } dict.Keys.CopyTo(a, 0); rand = rnd.Next(dict.Keys.Count); var key = a[rand]; #region Opposite construction Parent oppositeParent = Parent.FirstParent; if (key.Item2 == Parent.FirstParent) { oppositeParent = Parent.SecondParent; } else { oppositeParent = Parent.FirstParent; } #endregion var oppositeKey = new Tuple<Lesson, Parent>(key.Item1, oppositeParent); Index ind = dict[key][dict[key].Count - 1]; if (dict.ContainsKey(oppositeKey)) { Index oppositeIndex = dict[oppositeKey][dict[oppositeKey].Count - 1]; this.Timetable[ind.Day].Classes[ind.ClassN].Lessons[ind.Period] = key.Item1; #region Dictionary update var found = indexesDict[ind]; Tuple<Lesson, Parent> keyToChange; if (found[0].Item2 != key.Item2) { keyToChange = found[0]; } else { keyToChange = found[1]; } var swap = indexesDict[ind][(int)oppositeParent]; indexesDict[oppositeIndex][(int)oppositeParent] = indexesDict[ind][(int)oppositeParent]; indexesDict[ind][(int)oppositeParent] = swap; for (int i = 0; i < dict[keyToChange].Count; ++i) { if (dict[keyToChange][i].Equals(ind)) { dict[keyToChange][i] = new Index(ind.Day, ind.ClassN, ind.Period); } } dict[key].RemoveAt(dict[key].Count - 1); if (dict[key].Count == 0) dict.Remove(key); dict[oppositeKey].RemoveAt(dict[oppositeKey].Count - 1); if (dict[oppositeKey].Count == 0) dict.Remove(oppositeKey); ConflictsResolved++; #endregion } else throw new GeneticAlgorithmException(); } } catch (KeyNotFoundException e) { goto end; } if (dict.Count != 0) { throw new Exception(); } #endregion #endregion #region Classrooms switching Dictionary<Classroom, bool> classrooms = new Dictionary<Classroom, bool>(); for (int day = 0; day < d.Count; ++day) { for (int lesson = 0; lesson < d[day].Classes[0].Lessons.Count; ++lesson) { classrooms.Clear(); for (int classN = 0; classN < d[day].Classes.Count; ++classN) { Lesson l = d[day].Classes[classN].Lessons[lesson]; if (l == null) continue; foreach (Group g in l.Groups) { if (g.Room != null) { if (classrooms.ContainsKey(g.Room)) { bool broken = false; for (int i = 0; i < g.AlternativeRooms.Count; ++i) { if (!classrooms.ContainsKey(g.AlternativeRooms[i])) { g.Room = g.AlternativeRooms[i]; classrooms.Add(g.Room, true); broken = true; break; } } if (!broken) { g.Room = g.DesiredRoom; } } else { classrooms.Add(g.Room, true); } } } } } } #endregion end: this.mDays = d; this.mRating = CalculateRating(); }
private void MakeNewGeneration(int mutationsCount) { Random rnd = new Random(); /* foreach (var item in mCurrentGeneration) { mNextGeneration.Add(item); }*/ for (int f = 0; f < this.mCurrentGeneration.Count; ++f) { for (int s = 0; s < this.mCurrentGeneration.Count; ++s) { if (f != s) { s1 = new Schedule(this.mCurrentGeneration[f], this.mCurrentGeneration[s], SubjectsDifficulty); double randomNumber = rnd.NextDouble(); if (randomNumber < MutationPercentage) { s1.Mutate(mutationsCount); } /*if (s1.Not(this.compDict)) { s1 = new Schedule(SaveCopy.Timetable, mSubjectsDifficulty); s1.Shuffle(rnd); }*/ mNextGeneration[f * this.mCurrentGeneration.Count + s] = s1; } else { mNextGeneration[f * mCurrentGeneration.Count + s] = mCurrentGeneration[f]; } } } //mNextGeneration[rnd.Next(mNextGeneration.Count)].Mutate(Days * PeriodsCount); //EqualityComparer<Schedule> comp = new ScheduleComparator(false); this.mCurrentGeneration = mNextGeneration. OrderByDescending(x => { return x.Rating.Errors ; }). /*Distinct(comp).*/ToList().GetRange(0, GenerationSize); // my generation, babyy :D }
public void Generate() { if (this.mIsInitialized == false) { throw new GeneticAlgorithmNotInitializedException("Initialization not completed"); } compDict = new Dictionary<Tuple<Class, Subject, List<Group>>, int>(); for (int day = 0; day < SaveCopy.Timetable.Count; ++day) { for (int classN = 0; classN < SaveCopy.Timetable[day].Classes.Count; ++classN) { for (int lesson = 0; lesson < SaveCopy.Timetable[day].Classes[classN].Lessons.Count; ++lesson) { Lesson l = SaveCopy.Timetable[day].Classes[classN].Lessons[lesson]; if (l != null) { Tuple<Class, Subject, List<Group>> t = new Tuple<Class, Subject, List<Group>>(l.Class, l.Subject, l.Groups); if (compDict.ContainsKey(t)) { compDict[t]++; } else { compDict.Add(t, 1); } } } } } this.mNextGeneration = new List<Schedule>(); for (int i = 0; i < GenerationSize * GenerationSize; ++i) mNextGeneration.Add(null); Random rnd = new Random(); while (!IsThereAScheduleOkWithConstraints()) { this.mLastSuiting = this.mCurrentGeneration[0]; int timeBeforeStartingTheNewGeneration = DateTime.Now.Millisecond + (DateTime.Now.Second * 1000); MakeNewGeneration(MutationsCount); this.Time = (DateTime.Now.Second * 1000 + DateTime.Now.Millisecond) - timeBeforeStartingTheNewGeneration; mGenerationCycles++; //this.mCurrentGeneration[GenerationSize - 1].Shuffle(rnd); if (this.SameRatingCount > 30) { for (int i = 0; i < this.mCurrentGeneration.Count; i++) { this.mCurrentGeneration[i].Mutate(MutationsCount); } } } this.mFinished = true; }
private bool IsThereAScheduleOkWithConstraints() { if (this.mGenerationCycles > 2) { if (this.mLastSuiting.Rating.Errors == this.mCurrentGeneration[0].Rating.Errors) { this.SameRatingCount++; } else { this.SameRatingCount = 1; } } this.mLastSuiting = this.mCurrentGeneration[0]; this.mSuitingConstraints = this.mCurrentGeneration[0]; this.mSuitingConstraints.CalculateRating(); if (this.mCurrentGeneration[0].Rating.Errors > -3) { return true; } return false; }
public void EndInit() { if (this.mIsInitBegan == false) { throw new GeneticAlgorithmInitializationNotStartedException("EndInit() invoked before BeginInit()"); } try { this.CheckInitFinished(); } catch (GeneticAlgorithmNotInitializedException e) { throw new GeneticAlgorithmNotInitializedException("Initialization not completed", e); } this.mCurrentGeneration = new List<Schedule> { }; var data = from p in this.mData group p by p.Class into gr select new { Class = gr.Key, Subjects = from t in gr group t by t.Subject into c select new { Subject = c.Key, Groups = c } }; List<Day> timetable = new List<Day>{ }; for (int i = 0; i < mDaysCount; ++i) { Day d = new Day(new List<ClassSchedule>{}); for (int j = 0;j < data.Count(); ++j) { List<Lesson> lessons = new List<Lesson>{}; for (int k = 0; k < PeriodsCount; ++k) { lessons.Add(null); } ClassSchedule cs = new ClassSchedule(null, lessons); d.Classes.Add(cs); } timetable.Add(d); } int day = 0; int period = 0; int classN = 0; int hoursWeekly; foreach (var item in data) { day = 0; period = 0; for (int i = 0; i < Days; ++i) { timetable[i].Classes[classN].Class = item.Class; } foreach (var current in item.Subjects) { hoursWeekly = 0; List<Group> groups = new List<Group>(); foreach (Curriculum curric in current.Groups) { hoursWeekly = curric.HoursPerWeek; Group g = new Group(curric.Teacher, curric.Group, curric.DesiredClassroom, curric.AlternativeClassrooms); groups.Add(g); } for (int i = 0; i < hoursWeekly; i++) { Lesson l = new Lesson(item.Class, current.Subject, groups); timetable[day].Classes[classN].Lessons[period] = l; if (period == PeriodsCount - 1) { day++; period = 0; } else { period++; } } } classN++; } Random rnd = new Random(); Schedule s = new Schedule(timetable, mSubjectsDifficulty); SaveCopy = new Schedule(s.Timetable, mSubjectsDifficulty); s.Shuffle(rnd); this.mLastSuiting = s; this.mSuitingConstraints = s; this.mCurrentGeneration.Add(s); for (int i = 0; i < GenerationSize * 10; ++i) { s = new Schedule(timetable, mSubjectsDifficulty); s.Shuffle(rnd); this.mCurrentGeneration.Add(s); } EqualityComparer<Schedule> comp = new ScheduleComparator(); this.mCurrentGeneration = mCurrentGeneration.OrderByDescending(x => x.Rating.Errors). Distinct(comp).ToList(); this.mCurrentGeneration = mCurrentGeneration.GetRange(0, GenerationSize); this.mIsInitialized = true; }