Ejemplo n.º 1
0
 public Multilesson(Group g, Teacher t, Subject s, IntInInterval val)
 {
     this.g   = g;
     this.t   = t;
     this.s   = s;
     this.val = val;
 }
Ejemplo n.º 2
0
        private DaySchedule generateDay(int day, bool isFinal)
        {
            /*
             * if(isFinal==true && (!(lastConfig[day] is null)) && tryConfig(lastConfig[day], day)==true)
             * {
             *  System.Console.WriteLine("SKIPPPPP");
             *  return useConfig(lastConfig[day], day);
             * }
             */

            G.reset();

            // ----- setting node demands -----
            G.setDemand(allTeachersNode, -(Enumerable.Range(0, groups.Count).Sum(ind => dayState[day].groupLeftLessons[ind])));
            for (int g = 0; g < groups.Count; g++)
            {
                G.setDemand(groupNode[g], dayState[day].groupLeftLessons[g]);
            }

            // ----- adding edges -----

            //connecting teachers to allTeachersNode
            for (int t = 0; t < teachers.Count; t++)
            {
                int requested = 0;
                for (int g = 0; g < groups.Count; g++)
                {
                    foreach (int s in teacherGroup2Subjects[t, g])
                    {
                        if (groups[g].subject2Teacher[s].Item2.Equals(teachers[t]) == true)
                        {
                            requested += dayState[day].groups[g].getSubjectWeekLim(s);
                        }
                    }
                }

                for (int d = day + 1; d <= workDays; d++)
                {
                    requested -= dayState[d].teacherLeftLessons[t];
                }

                int u = allTeachersNode;
                int v = teacherNode[t];
                int l = Math.Max(requested, 0);
                int c = dayState[day].teacherLeftLessons[t];

                //Console.WriteLine($"{teachers[t].name} -> {l} {c}");
                G.addEdge(u, v, l, Math.Min(c, minLessons), true);
            }

            //connecting teachers to possible lessons
            for (int t = 0; t < teachers.Count; t++)
            {
                for (int g = 0; g < groups.Count; g++)
                {
                    foreach (int s in teacherGroup2Subjects[t, g])
                    {
                        IntInInterval      scheduledLessons = new IntInInterval(0);
                        List <Multilesson> important        = multilessons[day].Where(m => m.t.Equals(teachers[t]) == true &&
                                                                                      m.g.Equals(groups[g]) == true && m.s.Equals(groups[g].subject2Teacher[s].Item1)).ToList();

                        foreach (Multilesson r in important)
                        {
                            scheduledLessons = scheduledLessons + r.val;
                        }

                        if (important.Count > 0)
                        {
                            G.addEdge(teacherNode[t], groupSubjectNode[g, s], scheduledLessons.l, scheduledLessons.r, true);
                        }
                        else
                        {
                            G.addEdge(teacherNode[t], groupSubjectNode[g, s], 0, minLessons, true);
                        }
                    }
                }
            }

            //connecting the actual higharcy structures
            for (int g = 0; g < groups.Count; g++)
            {
                void dfs(TreeNode x)
                {
                    if (x.GetType() == typeof(SubjectTreeNode))
                    {
                        int s = dayState[day].groups[g].findSubject((x as SubjectTreeNode).s);

                        if (s == -1)
                        {
                            return;
                        }
                        if (dayState[day].groups[g].subject2Teacher[s].Item2 == null)
                        {
                            return;
                        }

                        int teacherInd  = groupSubject2Teacher[g, s];
                        int lessonsLeft = dayState[day].groups[g].getSubjectWeekLim(s);

                        for (int d = day + 1; d <= workDays; d++)
                        {
                            IEnumerable <Multilesson> important = multilessons[d].Where(m => m.g.Equals(groups[g]) == true &&
                                                                                        m.s.Equals((x as SubjectTreeNode).s) == true);

                            int rm = 0;
                            if (important.Any() == false)
                            {
                                rm = Math.Min(dayState[d].groups[g].getDayBottleneck(s), dayState[d].teacherLeftLessons[teacherInd]);
                                rm = Math.Min(rm, dayState[d].groupLeftLessons[g]);
                            }
                            else
                            {
                                rm = important.Sum(m => m.val.r);
                            }

                            lessonsLeft -= rm;
                        }

                        int subjectLim = Math.Min(dayState[day].groups[g].getDayBottleneck(s),
                                                  dayState[day].groups[g].getSubjectWeekLim(s));

                        int subjectDemand = 0;
                        for (int d = day + 1; d <= workDays; d++)
                        {
                            subjectDemand += multilessons[d].Where(r => r.g.Equals(groups[g]) == true && r.s.Equals((x as SubjectTreeNode).s))
                                             .Sum(r => r.val.l);
                        }

                        int fixatedLessons = multilessons[day].Where(r => r.g.Equals(groups[g]) == true && r.s.Equals((x as SubjectTreeNode).s))
                                             .Sum(r => r.val.l);

                        groupSubjectEdge[g, s] = G.addEdge(x.nodeCode, x.parent.nodeCode,
                                                           Math.Max(fixatedLessons, Math.Max(0, lessonsLeft)),
                                                           Math.Min(subjectLim, dayState[day].groups[g].getSubjectWeekLim(s) - subjectDemand));

                        return;
                    }

                    if (x.parent != null)
                    {
                        int lim = maxLessons;
                        if (x.GetType() == typeof(LimitationTreeNode))
                        {
                            lim = Math.Min(lim, dayState[day].groups[g].getLimGroupDayLim((x as LimitationTreeNode).lg));
                        }

                        int lessonsLeft = groups[g].subject2Teacher.Where(t => t.Item1.limGroups.Contains((x as LimitationTreeNode).lg) == true)
                                          .Sum(t => dayState[1].groups[g].getSubjectWeekLim(groups[g].findSubject(t.Item1)));

                        for (int d = day + 1; d <= workDays; d++)
                        {
                            IEnumerable <Multilesson> important = multilessons[d].Where(m => m.g.Equals(groups[g]) == true &&
                                                                                        m.s.limGroups.Contains((x as LimitationTreeNode).lg) == true);

                            int rm = 0;
                            if (important.Any() == false)
                            {
                                rm = Math.Min(dayState[d].groups[g].getLimGroupDayLim((x as LimitationTreeNode).lg), dayState[d].groupLeftLessons[g]);
                            }
                            else
                            {
                                rm = important.Sum(m => m.val.r);
                            }

                            lessonsLeft -= rm;
                        }

                        G.addEdge(x.nodeCode, x.parent.nodeCode, Math.Max(0, lessonsLeft), lim);
                    }

                    foreach (TreeNode y in x.children)
                    {
                        dfs(y);
                    }
                }

                dfs(groupHigharchy[g]);
            }

            //connecting groups to their higharchy trees
            for (int g = 0; g < groups.Count; g++)
            {
                int allLeft = dayState[day].groups[g].subject2Teacher.Sum(t => dayState[day].groups[g].getSubjectWeekLim(dayState[day].groups[g].findSubject(t.Item1)));
                for (int d = day + 1; d <= workDays; d++)
                {
                    allLeft -= dayState[d].groupLeftLessons[g];
                }

                int fixatedLessons = multilessons[day].Where(r => r.g.Equals(groups[g]) == true).Sum(r => r.val.l);

                int upperBound = dayState[day].groups[g].subject2Teacher.Sum(t => dayState[day].groups[g].getSubjectWeekLim(dayState[day].groups[g].findSubject(t.Item1)));
                for (int d = day + 1; d <= workDays; d++)
                {
                    upperBound -= Math.Min(dayState[d].groupLeftLessons[g], groups[g].minLessons);
                }

                G.addEdge(groupHigharchy[g].nodeCode, groupNode[g],
                          Math.Max(Math.Max(groups[g].minLessons - dayState[day].groups[g].curriculum.Count, allLeft), fixatedLessons),
                          Math.Min(dayState[day].groupLeftLessons[g], upperBound));
            }

            //connecting groups to allTeachersNode
            for (int g = 0; g < groups.Count; g++)
            {
                G.addEdge(allTeachersNode, groupNode[g], 0, Math.Min(maxLessons - minLessons, maxLessons - dayState[day].groups[g].curriculum.Count));
            }

            G.eval();

            List <Tuple <int, int> >[] currConfig = new List <Tuple <int, int> > [groups.Count];
            for (int g = 0; g < groups.Count; g++)
            {
                //Console.WriteLine($"---- {groups[g].name} - {g} ---");

                int        expectedCnt = dayState[day].groupLeftLessons[g];
                List <int> teacherInds = new List <int>();
                currConfig[g] = new List <Tuple <int, int> >();

                for (int s = 0; s < groups[g].subject2Teacher.Count; s++)
                {
                    if (groups[g].subject2Teacher[s].Item2 is null)
                    {
                        continue;
                    }

                    for (int i = 0; i < G.getEdge(groupSubjectEdge[g, s]); i++)
                    {
                        currConfig[g].Add(Tuple.Create(s, groupSubject2Teacher[g, s]));
                        teacherInds.Add(groupSubject2Teacher[g, s]);
                        //Console.WriteLine(teachers[groupSubject2Teacher[g, s]].name);

                        if (dayState[day].updateLimits(g, s, groupSubject2Teacher[g, s], +1) == false)
                        {
                            Console.WriteLine($"ebalo si maikata {g}");
                            return(null);
                        }
                    }
                }

                if (dayState[day].groups[g].curriculum.Count <dayState[day].groups[g].minLessons ||
                                                              dayState[day].groups[g].curriculum.Count> maxLessons)
                {
                    Console.WriteLine($"e de {dayState[day].groups[g].curriculum.Count} {g} || {day}");
                    return(null);
                }
            }

            Console.WriteLine("pak faida e ");
            DaySchedule ds = null;

            if (ds is null)
            {
                ScheduleCompleters.DFS.ScheduleCompleter sc = new ScheduleCompleters.DFS.ScheduleCompleter(dayState[day].groups, teachers, supergroupMultilessons[day], maxLessons);
                ds = sc.gen(true);

                if (!(ds is null))
                {
                    lastConfigSolution[day] = ds;
                    lastConfig[day]         = currConfig;
                }
            }
            if (ds is null)
            {
                ScheduleCompleters.GeneticAlgorithm.ScheduleCompleter sc = new ScheduleCompleters.GeneticAlgorithm.ScheduleCompleter(dayState[day].groups, teachers, supergroupMultilessons[day], maxLessons);
                ds = sc.gen(true);

                if (!(ds is null))
                {
                    lastConfigSolution[day] = ds;
                    lastConfig[day]         = currConfig;
                }
            }

            return(ds);
        }