private static List<List<string>> GetGroupExportList(int groupIndex, Individual individual, TimetableData ttData)
        {
            //output[row][col]
            List<List<string>> output = InitializeExportList(individual.Groups, ttData);
            //title
            output[0][0] = ttData.Groups[groupIndex].Name;

            //Fill in the data
            for (int day = 0; day < individual.Groups.GetLength(1); day++)
            {
                for (int block = 0; block < individual.Groups.GetLength(2); block++)
                {
                    if (individual.Groups[groupIndex, day, block] != -1)
                    {
                        Course c = ttData.Courses[individual.Groups[groupIndex, day, block]];
                        if (individual.Courses[c.Index, day, block] != -1)
                        {
                            Room r = ttData.Rooms[individual.Courses[c.Index, day, block]];
                            output[block * 3 + 1][day + 1] = c.Name;
                            output[block * 3 + 2][day + 1] = r.Name;
                            for (int l = 0; l < c.Lecturers.Length; l++)
                            {
                                output[block * 3 + 3][day + 1] = output[block * 3 + 3][day + 1] + c.Lecturers[l].LastName + (l == c.Lecturers.Length - 1 ? "" : ", ");
                            }
                        }
                    }
                }
            }
            return output;
        }
 public static void ExportAllRooms(Individual individual, TimetableData ttData, string filePath)
 {
     List<List<string>> output = new List<List<string>>();
     for (int room = 0; room < ttData.Rooms.Length; room++)
     {
         output.AddRange(GetRoomExportList(room, individual, ttData));
     }
     WriteCSV(filePath, output);
 }
 public static void ExportAllLecturers(Individual individual, TimetableData ttData, string filePath)
 {
     List<List<string>> output = new List<List<string>>();
     for (int lecuterer = 0; lecuterer < ttData.Lecturers.Length; lecuterer++)
     {
         output.AddRange(GetLecturerExportList(lecuterer, individual, ttData));
     }
     WriteCSV(filePath, output);
 }
 public static void ExportAllGroups(Individual individual, TimetableData ttData, string filePath)
 {
     List<List<string>> output = new List<List<string>>();
     for (int group = 0; group < ttData.Groups.Length; group++)
     {
         output.AddRange(GetGroupExportList(group, individual, ttData));
     }
     WriteCSV(filePath, output);
 }
示例#5
0
 public static Individual Clone(Individual source)
 {
     Individual clone = new Individual();
     clone.Courses = Clone(source.Courses);
     clone.Lecturers = Clone(source.Lecturers);
     clone.Rooms = Clone(source.Rooms);
     clone.Groups = Clone(source.Groups);
     return clone;
 }
 public static void ExportAll(Individual individual, TimetableData ttData, string filePath)
 {
     List<List<string>> output = new List<List<string>>();
     for (int group = 0; group < ttData.Groups.Length; group++)
     {
         output.AddRange(GetGroupExportList(group, individual, ttData));
     }
     for (int lecuterer = 0; lecuterer < ttData.Lecturers.Length; lecuterer++)
     {
         output.AddRange(GetLecturerExportList(lecuterer, individual, ttData));
     }
     for (int room = 0; room < ttData.Rooms.Length; room++)
     {
         output.AddRange(GetRoomExportList(room, individual, ttData));
     }
     WriteCSV(filePath, output);
 }
        /// <summary>
        /// Random fill the given individual
        /// </summary>
        /// <param name="individual">individual to be filled</param>
        /// <returns>success</returns>
        private bool RandomFillIndividual(Individual individual)
        {
            for (int courseIndex = 0; courseIndex < individual.Courses.GetLength(0); courseIndex++)
            {
                List<PlacementContainer> possibilities = GetPossibilitiesForCourse(courseIndex, individual);
                if (possibilities.Count <= 0)
                {
                    //When no possibilities left, restart
                    individual.Clear();
                    return false;
                }

                possibilities.Sort(SortPlacementContainerByBlock);
                List<PlacementContainer> subset = new List<PlacementContainer>();
                if (ttData.Courses[courseIndex].IsDummy)
                {
                    //choose possibility that is late
                    subset.Add(possibilities[possibilities.Count - 1]);
                    for (int i = possibilities.Count - 2; i >= 0; i--)
                    {
                        if (possibilities[i].block >= subset[0].block)
                            subset.Add(possibilities[i]);
                        else
                            break;
                    }
                }
                else
                {
                    //choose possibility that is early
                    subset.Add(possibilities[0]);
                    for (int i = 1; i < possibilities.Count; i++)
                    {
                        if (possibilities[i].block >= subset[0].block)
                            subset.Add(possibilities[i]);
                        else
                            break;
                    }
                }
                int chosenPossibility = random.Next(0, subset.Count);

                for (int blockOffset = 0; blockOffset < ttData.Courses[courseIndex].NumberOfBlocks; blockOffset++)
                {
                    individual.SetChromosome(courseIndex,
                        subset[chosenPossibility].day,
                        subset[chosenPossibility].block + blockOffset,
                        subset[chosenPossibility].room,
                        ttData.Courses[courseIndex].Group.Index,
                        GetLecturerIndices(courseIndex));
                }
            }
            return true;
        }
 private static int GetCourseDiff(TimetableData ttData, Individual individual)
 {
     int numberOfCoursesExpected = 0;
     for (int c = 0; c < ttData.Courses.Length; c++)
     {
         numberOfCoursesExpected += ttData.Courses[c].NumberOfBlocks;
     }
     int numberOfCoursesFound = 0;
     for (int c = 0; c < individual.Courses.GetLength(0); c++)
     {
         for (int d = 0; d < individual.Courses.GetLength(1); d++)
         {
             for (int b = 0; b < individual.Courses.GetLength(2); b++)
             {
                 if (individual.Courses[c, d, b] != -1)
                     numberOfCoursesFound++;
             }
         }
     }
     return numberOfCoursesExpected - numberOfCoursesFound;
 }
 private static int GetFreeDaysForLecturer(Individual individual, int lIndex, TimetableData ttData)
 {
     int freeDayCount = 0;
     for (int d = 0; d < individual.Lecturers.GetLength(1); d++)
     {
         if (ttData.Lecturers[lIndex].AvailableResearchDays.Contains(d))
         {
             bool isFree = true;
             for (int b = 0; b < individual.Lecturers.GetLength(2); b++)
             {
                 if (individual.Lecturers[lIndex, d, b] != -1)
                 {
                     isFree = false;
                 }
             }
             if (isFree)
                 freeDayCount++;
         }
     }
     return freeDayCount;
 }
 private static int SortByFitness(Individual x, Individual y)
 {
     if (x.Fitness > y.Fitness)
         return -1;
     if (x.Fitness < y.Fitness)
         return +1;
     return 0;
 }
 private void SortIndividuals(Individual[] individuals)
 {
     Array.Sort(individuals, SortByFitness);
 }
 private void CalculateFitness(Individual[] individuals)
 {
     foreach (Individual individual in individuals)
     {
         CalculateFitness(individual);
     }
 }
        /// <summary>
        /// Creates a mutation of the given individual
        /// </summary>
        /// <param name="individual"></param>
        /// <returns></returns>
        private Individual PerformMutation(Individual individual)
        {
            Individual mutation = Individual.Clone(individual);
            int chosenCourse = random.Next(0, mutation.Courses.GetLength(0));

            List<PlacementContainer> possibilities = GetPossibilitiesForCourse(chosenCourse, mutation);
            if (possibilities.Count <= 0)
                return mutation;
            int chosenPossibility = random.Next(0, possibilities.Count);

            mutation.ClearChromosome(chosenCourse, ttData);

            List<int> lecturers = new List<int>();
            foreach (Lecturer lecturer in ttData.Courses[chosenCourse].Lecturers)
            {
                lecturers.Add(lecturer.Index);
            }

            for (int blockOffset = 0; blockOffset < ttData.Courses[chosenCourse].NumberOfBlocks; blockOffset++)
            {
                mutation.SetChromosome(chosenCourse,
                    possibilities[chosenPossibility].day,
                    possibilities[chosenPossibility].block + blockOffset,
                    possibilities[chosenPossibility].room,
                    ttData.Courses[chosenCourse].Group.Index,
                    lecturers);
            }

            return mutation;
        }
        /// <summary>
        /// Checks if the placement for the course is valid
        /// </summary>
        /// <param name="course"></param>
        /// <param name="day"></param>
        /// <param name="block"></param>
        /// <param name="room"></param>
        /// <param name="individual"></param>
        /// <returns>Placement is valid</returns>
        private bool IsValidForCourse(int course, int day, int block, int room, Individual individual)
        {
            for (int blockOffset = 0; blockOffset < ttData.Courses[course].NumberOfBlocks; blockOffset++)
            {
                //block available at that day?
                foreach (DayOfWeek exceptionDay in ttData.Blocks[block + blockOffset].Exceptions)
                {
                    if ((int)exceptionDay == day + 1)
                        return false;
                }

                //Course already set?
                if (individual.Courses[course, day, block + blockOffset] != -1)
                    return false;

                //Room already occupied?
                if (individual.Rooms[room, day, block + blockOffset] != -1)
                    return false;

                //Lab?
                if (ttData.Courses[course].NeedsLab != ttData.Rooms[room].IsLab)
                    return false;

                int test = ttData.Courses[course].Lecturers.Length;
                //Lecturers available?
                for (int neededLecturer = 0; neededLecturer < ttData.Courses[course].Lecturers.Length; neededLecturer++)
                {
                    if (!ttData.Courses[course].Lecturers[neededLecturer].IsDummy)
                    {
                        if (individual.Lecturers[ttData.Courses[course].Lecturers[neededLecturer].Index, day, block + blockOffset] != -1)
                            return false;
                    }
                }

                //Group available?
                if (individual.Groups[ttData.Courses[course].Group.Index, day, block + blockOffset] != -1)
                    return false;
            }

            //Researchdays restriction for lecturers
            foreach (Lecturer l in ttData.Courses[course].Lecturers)
            {
                int tmp = individual.Lecturers[l.Index, day, block];
                individual.Lecturers[l.Index, day, block] = course;
                int freeDays = GetFreeDaysForLecturer(individual, l.Index, ttData);
                individual.Lecturers[l.Index, day, block] = tmp;
                if (freeDays < l.NeededNumberOfResearchDays)
                    return false;
            }

            return true;
        }
 /// <summary>
 /// Get a list of all possiblities for course placement
 /// </summary>
 /// <param name="course">course to inspect</param>
 /// <param name="individual">individual to be inspected</param>
 /// <returns>List of the possibilities</returns>
 private List<PlacementContainer> GetPossibilitiesForCourse(int course, Individual individual)
 {
     List<PlacementContainer> possibilities = new List<PlacementContainer>();
     int neededNumberOfBlocks = ttData.Courses[course].NumberOfBlocks;
     for (int day = 0; day < individual.Courses.GetLength(1); day++)
     {
         for (int block = 0; block < individual.Courses.GetLength(2); block++)
         {
             if (block + neededNumberOfBlocks - 1 < individual.Courses.GetLength(2))
             {
                 for (int room = 0; room < individual.Rooms.GetLength(0); room++)
                 {
                     if (IsValidForCourse(course, day, block, room, individual))
                     {
                         PlacementContainer c = new PlacementContainer();
                         c.day = day;
                         c.block = block;
                         c.room = room;
                         possibilities.Add(c);
                     }
                 }
             }
         }
     }
     return possibilities;
 }
 public static void ExportGroup(int groupIndex, Individual individual, TimetableData ttData, string filePath)
 {
     WriteCSV(filePath, GetGroupExportList(groupIndex, individual, ttData));
 }
        private void CalculateFitness(Individual individual)
        {
            int fitness = 0;
            for (int day = 0; day < numberOfDays; day++)
            {
                Dictionary<int, int> groupFirstBlock = new Dictionary<int, int>();
                Dictionary<int, int> groupLastBlock = new Dictionary<int, int>();
                Dictionary<int, int> groupBlockCount = new Dictionary<int, int>();
                Dictionary<string, int> courseIdBlackList = new Dictionary<string, int>();
                Dictionary<int, List<int>> courseBlockStartHours = new Dictionary<int, List<int>>();

                for (int block = 0; block < ttData.Blocks.Length; block++)
                {
                    for (int course = 0; course < individual.Courses.GetLength(0); course++)
                    {
                        if (individual.Courses[course, day, block] != -1)
                        {
                            //Courses should not appear more than once a day
                            if (!courseIdBlackList.ContainsKey(ttData.Courses[course].Id))
                                courseIdBlackList[ttData.Courses[course].Id] = 0;
                            courseIdBlackList[ttData.Courses[course].Id]++;
                            if (courseIdBlackList[ttData.Courses[course].Id] > ttData.Courses[course].NumberOfBlocks)
                                fitness -= 100;

                            //Courses should start before 13:00
                            //Opposite for dummy courses
                            fitness += (ttData.Blocks[block].Start.Hour - 13) * 25 * (ttData.Courses[course].IsDummy ? 1 : -1);

                            //Roompreference
                            if (ttData.Courses[course].RoomPreference != null)
                            {
                                if (individual.Courses[course, day, block] == ttData.Courses[course].RoomPreference.Index)
                                    fitness += 100;
                            }

                            //Measurements that are not applied on dummys
                            if (!ttData.Courses[course].IsDummy)
                            {
                                //Store the first and last block of the group
                                int group = ttData.Courses[course].Group.Index;
                                if (!groupFirstBlock.ContainsKey(group))
                                    groupFirstBlock.Add(group, block);
                                if (!groupLastBlock.ContainsKey(group))
                                    groupLastBlock.Add(group, block);
                                if (!groupBlockCount.ContainsKey(group))
                                    groupBlockCount.Add(group, 1);
                                groupLastBlock[group] = block;
                                groupBlockCount[group]++;

                                //A course should not by-pass the lunch break at 13:00
                                //--> Store the start hours
                                if (!courseBlockStartHours.ContainsKey(course))
                                    courseBlockStartHours.Add(course, new List<int>());
                                courseBlockStartHours[course].Add(ttData.Blocks[block].Start.Hour);
                            }
                        }
                    }
                }

                //Groups should not have gaps in their plan
                for (int group = 0; group < ttData.Groups.Length; group++)
                {
                    if (groupFirstBlock.ContainsKey(group))
                        fitness -= (groupLastBlock[group] - groupFirstBlock[group] - groupBlockCount[group]) * 30;
                }

                //A course should not by-pass the lunch break at 13:00
                foreach (var key in courseBlockStartHours.Keys)
                {
                    int start = courseBlockStartHours[key][0];
                    int end = courseBlockStartHours[key][courseBlockStartHours[key].Count - 1];
                    if (start - 13 < 0 && !(end - 13 < 0))
                        fitness -= 50;
                }
            }

            for (int g = 0; g < individual.Groups.GetLength(0); g++)
            {
                for (int d = 0; d < individual.Groups.GetLength(1); d++)
                {
                    int count = 0;
                    for (int b = 0; b < individual.Groups.GetLength(2); b++)
                    {
                        if (individual.Groups[g, d, b] != -1)
                        {
                            if (!ttData.Courses[individual.Groups[g, d, b]].IsDummy)
                                count++;
                        }
                    }
                    //Increase fitness when a group gets a free day
                    if (count == 0)
                        fitness += 100;
                }
            }

            individual.Fitness = fitness;
        }
示例#18
0
 private static int GetCourseCountForGroup(int gIndex, Individual individual)
 {
     int count = 0;
     for (int d = 0; d < individual.Groups.GetLength(1); d++)
     {
         for (int b = 0; b < individual.Groups.GetLength(2); b++)
         {
             if (individual.Groups[gIndex, d, b] != -1)
                 count++;
         }
     }
     return count;
 }
 public static void ExportLecturer(int lecturerIndex, Individual individual, TimetableData ttData, string filePath)
 {
     WriteCSV(filePath, GetLecturerExportList(lecturerIndex, individual, ttData));
 }
示例#20
0
 private static int GetCourseCountForLecturer(Individual individual, int lIndex)
 {
     int count = 0;
     for (int d = 0; d < individual.Lecturers.GetLength(1); d++)
     {
         for (int b = 0; b < individual.Lecturers.GetLength(2); b++)
         {
             if (individual.Lecturers[lIndex, d, b] != -1)
                 count++;
         }
     }
     return count;
 }
 public static void ExportRoom(int roomIndex, Individual individual, TimetableData ttData, string filePath)
 {
     WriteCSV(filePath, GetRoomExportList(roomIndex, individual, ttData));
 }