예제 #1
0
파일: Course.cs 프로젝트: ciction/cttEditor
        public string Print()
        {
            var maximumWorkingDaysString = MaximumWorkingDays == int.MaxValue ? "/" : MaximumWorkingDays.ToString();
            var MinimumWorkingDaysString = MinimumWorkingDays < 1 ? "/" : MinimumWorkingDays.ToString();
            var minimumDateString        = MinimumDate.Equals(DateTime.MinValue) ? "/         " : MinimumDate.ToString("dd/MM/yyy");
            var deadlineDateString       = DeadlineDate.Equals(DateTime.MaxValue) ? "/         " : DeadlineDate.ToString("dd/MM/yyy");

            string CourseCodeWhitespace  = EditorUtilities.GenerateTrailingWhiteSpace(CourseCode, 16);
            string TeacherCodeWhitespace = EditorUtilities.GenerateTrailingWhiteSpace(TeacherGroup.ToString(), 30);



            string line;

            line =
                CourseCode + CourseCodeWhitespace +
                TeacherGroup + TeacherCodeWhitespace + "\t" +
                LectureSize + " \t" + "\t" +
                MinimumWorkingDaysString + "\t" + "\t" +
                StudentSize + "\t" + "\t" + "\t" +
                minimumDateString + "\t" +
                deadlineDateString + "\t" +
                maximumWorkingDaysString + "\t" + "\t" + "\t" +
                IsPcNeeded + "\t" + "\t" + "\t" +
                HoursPerDay;

            return(line);
        }
예제 #2
0
        public string AnalyzeSolution()
        {
            var maxCourseSb       = new StringBuilder();
            var unavailableSb     = new StringBuilder();
            var multipleRoomsSb   = new StringBuilder();
            var multipleCoursesSb = new StringBuilder();
            var lecturerSb        = new StringBuilder();
            var curriculumSb      = new StringBuilder();

            var violations = 0.0;

            Objective = 0.0;

            IsFeasible = false;

            UnscheduledLectures   = 0.0;
            RoomCapacity          = 0.0;
            MinimumWorkingDays    = 0.0;
            CurriculumCompactness = 0.0;
            RoomStability         = 0.0;
            StudentMinMaxLoad     = 0.0;
            BadTimeslots          = 0.0;
            RoomUnsuitability     = 0.0;
            RoomCost  = 0.0;
            RoomsUsed = 0.0;

            var courseAssignments       = _assignments.GroupBy(a => a.Course).ToDictionary(g => g.Key, g => g.ToList());
            var curriculaAssignments    = _data.Curricula.ToDictionary(curriculum => curriculum, curriculum => new List <Assignment>());
            var consideredAloneTimeSlot = _data.Courses.ToDictionary(course => course, course => new HashSet <TimeSlot>());

            PenaltyForCourse = new Dictionary <Course, int>();
            foreach (var course in _data.Courses)
            {
                PenaltyForCourse[course] = 0;
            }

            if (!RoomAssignmentsExists && DoStageIRoomCheck)
            {
                CheckStageIFeasibility();
            }

            foreach (var course in _data.Courses)
            {
                if (!courseAssignments.ContainsKey(course))
                {
                    UnscheduledLectures += course.Lectures;
                    if (course.MinimumWorkingDays > 0)
                    {
                        MinimumWorkingDays += course.MinimumWorkingDays;
                    }
                    continue;
                }
                if (courseAssignments[course].Count > course.Lectures)
                {
                    maxCourseSb.AppendFormat(
                        "Course {0} has been scheduled for {1} lectures but is only allowed to be scheduled for {2}.\n",
                        course, courseAssignments[course].Count, course.Lectures);

                    violations += courseAssignments[course].Count - course.Lectures;
                }
                else if (courseAssignments[course].Count < course.Lectures)
                {
                    UnscheduledLectures += course.Lectures - courseAssignments[course].Count;
                }

                foreach (var curriculum in course.Curricula)
                {
                    foreach (var assignment in courseAssignments[course])
                    {
                        curriculaAssignments[curriculum].Add(assignment);
                    }
                }

                var timeSlotAssignments = courseAssignments[course].GroupBy(ca => ca.TimeSlot).ToDictionary(g => g.Key, g => g.ToList());

                foreach (var timeSlotAssign in timeSlotAssignments)
                {
                    BadTimeslots             += timeSlotAssign.Key.Cost * timeSlotAssign.Value.Count;
                    PenaltyForCourse[course] += timeSlotAssign.Key.Cost * timeSlotAssign.Value.Count;

                    if (course.UnavailableTimeSlots.Contains(timeSlotAssign.Key))
                    {
                        unavailableSb.AppendFormat(
                            "Course {0} has been scheduled at day {1}, period {2} but this time slot is unavailable for this course.\n",
                            course, timeSlotAssign.Key.Day, timeSlotAssign.Key.Period);

                        violations += 1.0;
                    }

                    if (timeSlotAssign.Value.Count <= 1)
                    {
                        continue;
                    }

                    multipleRoomsSb.AppendFormat(
                        "Course {0} has been scheduled day {1}, period {2} in rooms {3}\n",
                        course, timeSlotAssign.Key.Day, timeSlotAssign.Key.Period,
                        string.Join(", ", timeSlotAssign.Value.Select(a => a.Room)));

                    violations += timeSlotAssign.Value.Count - 1.0;
                }

                var workDays = timeSlotAssignments.Select(t => t.Key.Day).Distinct().ToList().Count;

                if (workDays < course.MinimumWorkingDays)
                {
                    MinimumWorkingDays += (course.MinimumWorkingDays - workDays);
                }

                if (RoomAssignmentsExists)
                {
                    RoomStability += (courseAssignments[course].Select(a => a.Room).Distinct().Count() - 1);
                }
            }
            foreach (var timeSlotAssigns in _data.Curricula.Select(curriculum => curriculaAssignments[curriculum].Select(a => a.TimeSlot).Distinct().ToList()))
            {
                CurriculumCompactness +=
                    timeSlotAssigns.Count(
                        timeSlotAssign => !timeSlotAssigns.Any(ts => TimeSlot.TimeSlotsAreConsequtive(ts, timeSlotAssign)));
            }
            if (RoomAssignmentsExists)
            {
                var roomAssignments = _assignments.GroupBy(a => a.Room).ToDictionary(g => g.Key, g => g.ToList());
                foreach (var roomAssign in roomAssignments)
                {
                    var timeSlotAssigns = roomAssign.Value.GroupBy(a => a.TimeSlot)
                                          .ToDictionary(g => g.Key, g => g.Distinct().ToList());
                    foreach (var timeSlotAssign in timeSlotAssigns)
                    {
                        var courseAssigns = timeSlotAssign.Value.Select(a => a.Course).Distinct().ToList();
                        if (courseAssigns.Count > 1)
                        {
                            multipleCoursesSb.AppendFormat(
                                "Room {0} has been scheduled at day {1}, period {2} for courses {3}\n",
                                roomAssign.Key, timeSlotAssign.Key.Day, timeSlotAssign.Key.Period,
                                string.Join(", ", courseAssigns));

                            violations += timeSlotAssign.Value.Count - 1.0;
                        }
                        var students = timeSlotAssign.Value.Sum(a => a.Course.NumberOfStudents);
                        if (students > roomAssign.Key.Capacity)
                        {
                            RoomCapacity += students - roomAssign.Key.Capacity;
                        }
                    }
                    if (roomAssign.Value.Count > 0)
                    {
                        RoomsUsed += 1;
                        RoomCost  += roomAssign.Key.Cost;
                    }

                    RoomUnsuitability += roomAssign.Value.Count(a => a.Course.UnsuitableRooms.Contains(roomAssign.Key));
                }
            }

            var lecturerAssigns = _assignments.GroupBy(a => a.Course.Lecturer).ToDictionary(g => g.Key, g => g.ToList());

            foreach (var lecturerAssign in lecturerAssigns)
            {
                var timeSlotAssigns = lecturerAssign.Value.GroupBy(l => l.TimeSlot).ToDictionary(g => g.Key, g => g.Distinct().ToList());
                foreach (var timeSlotAssign in timeSlotAssigns)
                {
                    var roomsAssigns = timeSlotAssign.Value.Select(a => a.Course).Distinct().ToList();

                    if (roomsAssigns.Count <= 1)
                    {
                        continue;
                    }

                    lecturerSb.AppendFormat(
                        "Lecturer {0} has been scheduled at day {1}, period {2} for courses {3}\n",
                        lecturerAssign.Key, timeSlotAssign.Key.Day, timeSlotAssign.Key.Period, string.Join(", ", roomsAssigns));

                    violations += timeSlotAssign.Value.Count - 1.0;
                }
            }


            foreach (var curriculumAssign in curriculaAssignments)
            {
                var timeSlotAssigns = curriculumAssign.Value.GroupBy(cu => cu.TimeSlot).ToDictionary(g => g.Key, g => g.Distinct().ToList());
                foreach (var timeSlotAssign in timeSlotAssigns)
                {
                    var courseAssigns = timeSlotAssign.Value.Select(a => a.Course).Distinct().ToList();

                    if (courseAssigns.Count <= 1)
                    {
                        continue;
                    }

                    curriculumSb.AppendFormat(
                        "Curriculum {0} has been scheduled at day {1}, period {2} for courses {3}\n",
                        curriculumAssign.Key, timeSlotAssign.Key.Day, timeSlotAssign.Key.Period, string.Join(", ", courseAssigns));

                    violations += timeSlotAssign.Value.Count - 1.0;
                }
                var dayAssign = curriculumAssign.Value.GroupBy(a => a.TimeSlot.Day).ToDictionary(g => g.Key, g => g.Count());
                foreach (var day in dayAssign)
                {
                    var minMaxLoadViol = Math.Max(day.Value - _data.MaximumPeriodsPerDay, 0)
                                         + Math.Max(_data.MinimumPeriodsPerDay - day.Value, 0);
                    StudentMinMaxLoad += minMaxLoadViol;
                    if (minMaxLoadViol > 0.5)
                    {
                        //   Console.WriteLine($"S:StudentloadViol: {curriculumAssign.Key} {day.Key}: {minMaxLoadViol}");
                    }
                }
            }

            var sB = new StringBuilder();

            if (violations > 0.0)
            {
                if (maxCourseSb.Length > 0)
                {
                    sB.AppendLine("Each course is only allowed to be scheduled for a given maximum number of lectures\n");
                    sB.AppendLine(maxCourseSb.ToString());
                }
                if (unavailableSb.Length > 0)
                {
                    if (maxCourseSb.Length > 0)
                    {
                        sB.AppendLine();
                    }
                    sB.AppendLine("Courses are not allowed to be scheduled in time slots marked as unavailable\n");
                    sB.AppendLine(unavailableSb.ToString());
                }
                if (multipleRoomsSb.Length > 0)
                {
                    if ((maxCourseSb.Length > 0 | unavailableSb.Length > 0))
                    {
                        sB.AppendLine();
                    }
                    sB.AppendLine("Each course is only allowed to be scheduled in a single room in each time slot\n");
                    sB.AppendLine(multipleRoomsSb.ToString());
                }
                if (multipleCoursesSb.Length > 0)
                {
                    if ((maxCourseSb.Length | unavailableSb.Length | multipleRoomsSb.Length) > 0)
                    {
                        sB.AppendLine();
                    }
                    sB.AppendLine("Each room can only accommodate a single course in each time slot\n");
                    sB.AppendLine(multipleCoursesSb.ToString());
                }
                if (lecturerSb.Length > 0)
                {
                    if ((maxCourseSb.Length | unavailableSb.Length | multipleRoomsSb.Length | multipleCoursesSb.Length) > 0)
                    {
                        sB.AppendLine();
                    }
                    sB.AppendLine("Each lecturer can only teach a single course in each time slot\n");
                    sB.AppendLine(lecturerSb.ToString());
                }
                if (curriculumSb.Length > 0)
                {
                    if ((maxCourseSb.Length | unavailableSb.Length | multipleRoomsSb.Length | multipleCoursesSb.Length | lecturerSb.Length) > 0)
                    {
                        sB.AppendLine();
                    }
                    sB.AppendLine("Only a single course in a curriculum can be scheduled in each time slot\n");
                    sB.AppendLine(curriculumSb.ToString());
                }

                ResultLine = "RESULT WRONG";
                TextLine   = "The solution is infeasible. The number of violations is " + violations;
                ScoreLine  = "SCORE " + violations.ToString();
                return(sB.ToString());
            }

            IsFeasible = true;

            Objective = 0
                        + RoomCapacity * Formulation.RoomCapacityWeight
                        + MinimumWorkingDays * Formulation.MinimumWorkingDaysWeight
                        + CurriculumCompactness * Formulation.CurriculumCompactnessWeight
                        + RoomStability * Formulation.RoomStabilityWeight
                        + BadTimeslots * Formulation.BadTimeslotsWeight
                        + RoomUnsuitability * Formulation.UnsuitableRoomsWeight
                        + StudentMinMaxLoad * Formulation.StudentMinMaxLoadWeight;

            var calculatedWidth = "Violation".Length;

            sB.AppendLine("Table 1: Penalty values");
            sB.AppendLine();
            sB.AppendFormat("Name                  | {0} | {1} | \n", "Violation".PadRight(calculatedWidth), "Obj".PadLeft(calculatedWidth));
            sB.AppendFormat("============================={0}\n", new string('=', calculatedWidth * 2), 0);
            sB.AppendFormat("UNSCHEDULED           | {0} | {1} |\n", UnscheduledLectures.ToString().PadLeft(calculatedWidth), "".PadRight(calculatedWidth));
            sB.AppendFormat("ROOMCAPACITY          | {0} | {1} |\n", RoomCapacity.ToString().PadLeft(calculatedWidth), (RoomCapacity * Formulation.RoomCapacityWeight).ToString().PadLeft(calculatedWidth));
            sB.AppendFormat("MINIMUMWORKINGDAYS    | {0} | {1} |\n", MinimumWorkingDays.ToString().PadLeft(calculatedWidth), (MinimumWorkingDays * Formulation.MinimumWorkingDaysWeight).ToString().PadLeft(calculatedWidth));
            sB.AppendFormat("CURRICULUMCOMPACTNESS | {0} | {1} |\n", CurriculumCompactness.ToString().PadLeft(calculatedWidth), (CurriculumCompactness * Formulation.CurriculumCompactnessWeight).ToString().PadLeft(calculatedWidth));
            sB.AppendFormat("ROOMSTABILITY         | {0} | {1} |\n", RoomStability.ToString().PadLeft(calculatedWidth), (RoomStability * Formulation.RoomStabilityWeight).ToString().PadLeft(calculatedWidth));
            sB.AppendFormat("RoomUnsuitability     | {0} | {1} |\n", RoomUnsuitability.ToString().PadLeft(calculatedWidth), (RoomUnsuitability * Formulation.UnsuitableRoomsWeight).ToString().PadLeft(calculatedWidth));
            sB.AppendFormat("StudentMinMaxLoad     | {0} | {1} |\n", StudentMinMaxLoad.ToString().PadLeft(calculatedWidth), (StudentMinMaxLoad * Formulation.StudentMinMaxLoadWeight).ToString().PadLeft(calculatedWidth));
            sB.AppendFormat("BadTimeslots          | {0} | {1} |\n", BadTimeslots.ToString().PadLeft(calculatedWidth), (BadTimeslots * Formulation.BadTimeslotsWeight).ToString().PadLeft(calculatedWidth));
            sB.AppendFormat("OBJECTIVE             | {0} | {1} |\n", " ".PadLeft(calculatedWidth), Objective.ToString().PadLeft(calculatedWidth));
            sB.AppendLine();
            sB.AppendLine();
            sB.AppendLine("Table 2: Used Room stat");
            sB.AppendLine();
            sB.AppendLine("Name                  | Value");
            sB.AppendLine("================================================================");
            sB.AppendFormat("Used Rooms           | {0}/{1} ({2:0.00%})\n", RoomsUsed, _data.Rooms.Count, RoomsUsed / _data.Rooms.Count);
            sB.AppendFormat("Room Cost            | {0}/{1} ({2:0.00%})\n", RoomCost, _data.Rooms.Sum(r => r.Cost), RoomCost / _data.Rooms.Sum(r => r.Cost));
            // sB.AppendFormat("Utilization    | Total violation of minimum working days");


            ResultLine = "RESULT CORRECT";
            TextLine   = "The solution is feasible. The Objective value is " + Objective;
            ScoreLine  = "SCORE " + Objective;
            return(sB.ToString());
        }