示例#1
0
        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;
 }