Алгоритм создания школьного расписания

Мне было интересно, есть ли известные решения для алгоритма создания школьного расписания. В основном речь идет об оптимизации "часовой дисперсии" (как в случае учителей, так и в случае классов) для данных ассоциаций класс-предмет-учитель. Мы можем предположить, что у нас есть наборы классов, предметов урока и учителей, связанных друг с другом на входе, и что расписание должно соответствовать между 8 утра и 4 вечера.

Я думаю, что для этого, вероятно, нет точного алгоритма, но, возможно кто-то знает хорошее приближение или подсказки для его разработки.

16 ответов


эта проблема NP-Complete!
В двух словах нужно изучить все возможные комбинации, чтобы найти список приемлемых решений. Из-за различий в условиях, в которых эта проблема возникает в различных школах (например: существуют ли ограничения в отношении классных комнат?, Некоторые из классов разделены на подгруппы некоторое время? Это еженедельный график? так далее.) нет хорошо известного класса проблем, который соответствует всем проблемы с расписанием. Может быть,проблема с рюкзаком есть много элементов сходства с этими проблемами в целом.

подтверждение того, что это и сложная проблема, и та, для которой люди постоянно ищут решение, - это проверить это (долго) список (в основном коммерческих) программных средств планирования

из-за большого количества переменных, участвующих, самый большой источник которых, как правило, факультет желания участника ;-)... это обычно нецелесообразно рассматривать перечисление всех возможных комбинаций. Вместо этого нам нужно выбрать подход, который посещает подмножество пространств проблем/решений.
- Генетические Алгоритмы, цитируется в другом ответе (или, ИМХО,кажется) хорошо оснащены для выполнения такого рода полууправляемого поиска (проблема заключается в том, чтобы найти хорошую функцию оценки для кандидатов, которые будут сохранены для следующего поколения)
- График Рерайтинг подходы также используются с этим типом задач комбинаторной оптимизации.

вместо того, чтобы сосредоточиться на конкретных реализациях программы автоматического генератора расписания, я хотел бы предложить несколько стратегий, которые могут быть применены, на уровне определения задачи.
Общее обоснование заключается в том, что в большинстве реальных проблем планирования в мире потребуются некоторые компромиссы, не все ограничения, выраженные и подразумеваемые: будут полностью удовлетворены. Поэтому мы помогаем себе:

  • определение и ранжирование всех известных ограничений
  • уменьшение проблемного пространства вручную, предоставляя набор дополнительные ограничения.
    Это может показаться противоречащим интуиции, но, например, предоставляя начальный, частично заполненный график (скажем, примерно 30% временных интервалов), таким образом, что полностью удовлетворяет всем ограничениям, и учитывая, что этот частичный график неизменен, мы значительно сокращаем время / пространство, необходимое для получения решений-кандидатов.
    другой способ дополнительные ограничения помогают, например, "искусственно" добавление ограничения, которые мешают преподаванию некоторых предметов в некоторые дни недели (если это еженедельный график...); этот тип ограничений приводит к сокращению пространства проблем / решений, как правило, без исключения значительного числа хороших кандидатов.
  • сделать некоторые ограничения задачи можно быстро вычислить. Это часто связано с выбором модели данных, используемой для представления проблемы; идея состоит в том, чтобы иметь возможность быстро выбрать (или обрезать) некоторые из вариантов.
  • переопределение проблемы и разрешение некоторых ограничений быть нарушенными несколько раз (как правило, к конечным узлам графика). Идея здесь состоит в том, чтобы либо удалить некоторые ограничений для заполнения последних нескольких слотов в расписание, или чтобы программа автоматического генератора расписания перестала стесняться завершения всего расписания, вместо этого предоставляя нам список из дюжины или около того правдоподобных кандидатов. Человек часто находится в лучшем положении, чтобы завершить головоломку, как указано, возможно, нарушив несколько противопоказаний, используя информацию, которая обычно не делится с автоматизированной логикой (например, правило " нет математики во второй половине дня "может быть нарушено при случае для класса" advanced math and physics"; или "это лучше нарушить одно из требований мистера Джонса, чем мисс Смит ... ; -))

  • два учителя женаты, и их ребенок учится в одной школе. Опять же, вы должны помешать двум учителям преподавать в конкретный класс, где находится их ребенок.
  • школа имеет отдельные помещения, как один день класс находится в одном институте, а другой день класс находится в другом.
  • в школе есть общие лаборатории, но эти лаборатории доступны только в определенные будние дни (по соображениям безопасности, например, когда требуется дополнительный персонал).
  • некоторые учителя имеют предпочтения для свободного дня: некоторые предпочитают в понедельник, некоторые в пятницу, некоторые в среду. Некоторые предпочитают приходить рано утром, некоторые предпочитают приходить позже.
  • у вас не должно быть ситуаций, когда у вас есть урок, скажем, истории в первый час, затем три часа математики, затем еще один час истории. Это не имеет смысла ни для учеников, ни для учителя.
  • вы должны равномерно распределить аргументы. Не имеет смысла в первые дни недели заниматься только математикой, а в остальные-только литературой.
  • вы должны дать некоторые учителя два часа подряд делают оценочные тесты.
  • Как вы можете видеть, проблема не NP-полная, это NP-безумие.

    Так что они делают, что у них есть большой стол с небольшими пластиковыми вставками, и они перемещают вставки вокруг, пока не будет получен удовлетворительный результат. Они никогда не начинают с нуля: обычно они начинают с графика предыдущего года и вносят коррективы.


    на Международный Конкурс Расписания 2007 был урок планирования трек и экзамен планирования трек. В этом конкурсе приняли участие многие исследователи. Многие эвристики и метаэвристики были опробованы, но в конце концов метаэвристики локального поиска (такие как поиск табу и имитационный отжиг) явно превзошли другие алгоритмы (такие как генетические алгоритмы).

    взгляните на 2 фреймворка с открытым исходным кодом, используемые некоторыми из финалисты:

    • С JBoss OptaPlanner (Java, с открытым исходным кодом)
    • Unitime (Java, с открытым исходным кодом) - больше для университетов

    одним из моих полугодовых заданий было поколение школьной таблицы генетического алгоритма.

    весь стол-это один "организм". Были некоторые изменения и оговорки к подходу родовых генетических алгоритмов:

    • правила были сделаны для "незаконных таблиц": два класса в одном классе, один учитель, обучающий две группы одновременно и т. д. Эти мутации были немедленно признаны смертельными, и на месте "умершего" появился новый "организм"." немедленно. Первоначальный был сгенерирован серией случайных попыток получить законный (если бессмысленный). Летальная мутация не учитывалась при подсчете мутаций в итерации.

    • мутации"обмена" были гораздо более распространенными, чем мутации" модификации". Изменения были только между частями гена, которые имели смысл-не заменяя учителя классом.

    • небольшие бонусы были назначены за объединение определенных 2 часов вместе, для назначения тот же общий класс в последовательности для той же группы, для поддержания рабочего времени учителя и нагрузки класса непрерывно. Были назначены умеренные премии за правильную организацию занятий по данному предмету, за удержание часов занятий в пределах нормы (утром или днем) и так далее. Большие бонусы были за присвоение правильного количества данного предмета, заданной рабочей нагрузки для учителя и т. д.

    • учителя могут создавать свои графики рабочей нагрузки "хотите работать тогда", "хорошо работать тогда", " не нравится работать тогда", "не могу работать тогда", с соответствующими весами. Все 24h были законными рабочими часами, кроме ночного времени, было очень нежелательно.

    • функции веса... О да. Весовая функция была огромным, чудовищным произведением (как при умножении) Весов, присвоенных выбранным признакам и свойствам. Он был чрезвычайно крут, одно свойство легко могло изменить его на порядок вверх или вниз - и в одном организме были сотни или тысячи свойств. Этот привело к абсолютно огромным числам в качестве весов, и как прямой результат, необходимо использовать библиотеку bignum (gmp) для выполнения вычислений. Для небольшого набора из 10 групп, 10 учителей и 10 классных комнат начальный набор начинался с отметки 10^-200something и заканчивался 10^+300something. Он был совершенно неэффективен, когда был более плоским. Кроме того, ценности выросли намного шире расстояния с большими "школами".

    • расчет времени было мало разница между небольшой популяцией (100) за долгое время и большой популяцией (10k+) за меньшее количество поколений. Вычисление за то же время дало примерно такое же качество.

    • расчет (на некотором процессоре 1GHz) займет около 1 ч, чтобы стабилизировать около 10^ + 300, генерируя графики, которые выглядели довольно хорошо, для упомянутого тестового случая 10x10x10.

    • проблема легко paralellizable путем обеспечивать средство сети которое обменяло бы самое лучшее образцы между компьютерами, выполняющими вычисления.

    результирующая программа никогда не видела дневного света снаружи, получая мне хорошую оценку за семестр. Он показал некоторое обещание, но я никогда не получал достаточной мотивации, чтобы добавить какой-либо GUI и сделать его доступным для широкой публики.


    эта проблема сложнее, чем кажется.

    Как уже упоминалось, это NP-полная проблема, но давайте проанализируем, что это значит.

    в основном, это означает, что вы должны смотреть на все возможные комбинации.

    но "посмотрите на" не говорит вам много, что вам нужно сделать.

    генерация всех возможных комбинаций легко. Это может привести к огромному количеству данных, но у вас не должно быть много проблем с пониманием концепций этой части проблемы.

    вторая проблема заключается в том, чтобы судить, является ли данная возможная комбинация хорошей, плохой или лучшей, чем предыдущее "хорошее" решение.

    для этого вам нужно больше, чем просто "это возможное решение".

    например, один и тот же учитель работает 5 дней в неделю в течение X недель подряд? Даже если это рабочее решение,оно не может быть лучшим решением, чем чередование двух людей, чтобы каждый учитель делал одну неделю каждый. О, вы не думал об этом? Помните, что вы имеете дело с людьми, а не только с проблемой распределения ресурсов.

    даже если один учитель может работать полный рабочий день в течение 16 недель подряд, это может быть неоптимальным решением по сравнению с решением, где вы пытаетесь переключаться между учителями, и такой баланс очень трудно встроить в программное обеспечение.

    подводя итог, производить хорошее разрешение к этой проблеме будет стоить много, к много много людей. Следовательно, это не легкая задача, чтобы сломать и решить. Будьте готовы поставить некоторые цели, которые не являются 100% и называть их "достаточно хорошо".


    обновление: из комментариев ... должна быть и эвристика!

    Я бы пошел с Пролог ... затем используйте Ruby или Perl или что-то еще, чтобы очистить ваше решение в более красивую форму.

    teaches(Jill,math).
    teaches(Joe,history).
    
    involves(MA101,math).
    involves(SS104,history).
    
    myHeuristic(D,A,B) :- [test_case]->D='<';D='>'.
    createSchedule :- findall(Class,involves(Class,Subject),Classes),
                      predsort(myHeuristic,Classes,ClassesNew),
                      createSchedule(ClassesNew,[]).
    createSchedule(Classes,Scheduled) :- [the actual recursive algorithm].
    

    Я (все еще) в процессе выполнения чего-то похожего на эту проблему, но используя тот же путь, что я только что упомянул. Пролог (как функциональный язык) действительно облегчает решение NP-трудных задач.


    генетические алгоритмы часто используются для такого планирования.

    нашел этот пример (составление расписания занятий с использованием генетического алгоритма) что соответствует вашему требованию довольно хорошо.


    вот несколько ссылок, которые я нашел:

    школьное расписание - перечисляет некоторые проблемы, связанные

    гибридный генетический алгоритм для школьных расписаний

    планирование утилиты и инструменты


    мой алгоритм расписания, реализованный в FET (бесплатное программное обеспечение расписания,http://lalescu.ro/liviu/fet/, успешное приложение):

    алгоритм эвристический. Я назвал это "рекурсивным обменом".

    Input: набор действий A_1...A_n и ограничений.

    Output: набор раз TA_1...TA_n (временной интервал каждого действия. Номера здесь исключены, для простоты). Алгоритм должен помещать каждое действие в временной интервал, уважение ограничений. Каждый TA_i находится между 0 (T_1) и max_time_slots-1 (T_m).

    ограничения:

    C1) Basic: список пар действий, которые не могут быть одновременными (например, A_1 и A_2, потому что у них один учитель или одни и те же ученики);

    C2) множество других ограничений (исключено здесь, для простоты).

    алгоритм расписания (который я назвал "рекурсивным обменом"):

    1. рода деятельности, большинство сначала трудно. Не критический шаг, но ускоряет алгоритм, возможно, в 10 раз или более.
    2. Попробуйте поместить каждое действие (A_i) в разрешенный временной интервал, следуя вышеуказанному порядку, по одному за раз. Поиск доступного слота (T_j) для A_i, в котором это действие может быть помещено с учетом ограничений. Если доступно больше слотов, выберите случайный. Если нет, выполните рекурсивную замену:

      a. Для каждого временного слота T_j рассмотрим, что происходит, если вы помещаете A_i в T_j. Будет список других действий, которые не согласны с этим ходом (например, activity A_k находится на том же слоте T_j и имеет того же учителя или тех же студентов, что и A_i). Держите список конфликтующих действий для каждого временного слота T_j.

      b. Выберите слот (T_j) с наименьшим количеством конфликтующих действий. Скажем, список действий в этом слоте содержит 3 действия: A_p, A_q, A_r.

      c. Место A_i в T_j и сделайте a_p, A_q, a_r нераспределенными.

      d. Рекурсивно попробуйте разместить A_p, A_q, A_r (если уровень рекурсии не слишком велик, скажем, 14, и если общее количество рекурсивных вызовов, подсчитанных с шага 2) на a_i, не слишком велико, скажем, 2*n), как на Шаге 2).

      e. Если успешно размещены A_p, A_q, a_r, возврат с успехом, в противном случае попробуйте другие временные интервалы (перейдите к Шагу 2 b) и выберите следующий лучшее время шлиц.)

      f. Если все (или разумное количество) временных интервалов были опробованы безуспешно, вернитесь без успеха.

      g. Если мы находимся на уровне 0, и у нас не было успеха в размещении A_i, поместите его, как в шагах 2 b) и 2 c), но без рекурсии. Теперь у нас есть 3 - 1 = 2 больше мероприятий для размещения. Перейдите к Шагу 2) (здесь используются некоторые методы, чтобы избежать езды на велосипеде).


    Я разработал коммерческие алгоритмы как для расписания классов, так и для расписания экзаменов. Для первого я использовал целочисленное программирование; для второго-эвристику, основанную на максимизации целевой функции путем выбора слотовых свопов, очень похожих на первоначальный ручной процесс, который был разработан. Для того чтобы такие решения были приняты, главное-это способность представлять все реальные ограничения, а для того, чтобы люди не могли видеть пути улучшения решения. В конце концов, алгоритмическая часть была довольно простой и простой в реализации по сравнению с подготовкой баз данных, пользовательским интерфейсом, возможностью сообщать о статистике, такой как использование помещений, обучение пользователей и так далее.


    эта статья описывает проблему школьного расписания и их подход к алгоритму довольно хорошо:"разработка учебной программы-интерактивный, основанный на ограничениях планировщик для школ и колледжей. " [PDF]

    автор сообщает мне, что программное обеспечение SYLLABUS все еще используется / разрабатывается здесь:http://www.scientia.com/uk/


    Я работаю над широко используемым механизмом планирования, который делает именно это. Да, он NP-полный; лучшие подходы стремятся приблизить оптимальное решение. И, конечно, есть много разных способов сказать, какое из них является "лучшим" решением - это более важно, чтобы ваши учителя были довольны своим расписанием или, например, чтобы ученики попадали во все свои классы?

    абсолютный самый важный вопрос, который вам нужно решить на раннем этапе, это что делает один из способов планирования этой системы лучше, чем другой? То есть, если у меня есть график с миссис Джонс, преподающей математику в 8, и мистером Смитом, преподающим математику в 9, это лучше или хуже, чем один с ними обоими, преподающими математику в 10? Лучше или хуже, чем когда миссис Джонс преподает в 8, а мистер Джонс-в 2? Почему?

    главный совет, который я бы дал здесь, - это разделить проблему как можно больше - может быть, курс за курсом, может быть, учитель за учителем, может быть, комната за комнатой - и работать сначала о решении подзадачи. Там вы должны в конечном итоге с несколькими решениями на выбор, и нужно выбрать один как наиболее вероятно оптимальным. Затем работа над тем, чтобы" ранние " подзадачи учитывали потребности более поздних подзадач в оценке их потенциальных решений. Затем, возможно, поработайте над тем, как выйти из ситуаций, окрашенных в угол (предполагая, что вы не можете предвидеть эти ситуации в более ранних подзадачах), когда вы доберетесь до " Нет допустимых решений" государство.

    пропуск оптимизации локального поиска часто используется для" полировки " конечного ответа для получения лучших результатов.

    обратите внимание, что обычно мы имеем дело с сильно ограниченными ресурсами системами в школьном расписании. Школы не проходят через год с большим количеством пустых комнат или учителей, сидящих в гостиной 75% дня. Подходы, которые лучше всего работают в богатых решениями средах, не обязательно применимы в школьном расписании.


    Как правило, Программирование ограничений является хорошим подходом к этому типу проблемы планирования. Поиск по " программированию ограничений "и планированию или" планированию на основе ограничений " как в Stack overflow, так и в Google создаст некоторые хорошие ссылки. Это не невозможно - просто немного сложно думать об использовании традиционных методов оптимизации, таких как линейная или целочисленная оптимизация. Один вывод будет - Существует ли расписание, которое удовлетворяет всем требованиям? Что, в само по себе, очевидно, полезно.

    удачи !


    вы можете взять его с генетическими алгоритмами, да. Но вы не должны :). Он может быть слишком медленным и настройки параметров могут быть слишком продолжительными и т. д.

    есть и другие успешные подходы. Все реализовано в проектах с открытым исходным кодом:

    • подход на основе ограничений
      • реализовала в UniTime (не для школы)
      • вы также можете пойти дальше и использовать целочисленное Программирование. Успешно сделано в Удине университет а также в Университете Байройт (я там участвовал) с использованием коммерческого программного обеспечения (ILOG CPLEX)
      • подход на основе правил с heuristisc-см. слюнки текут планировщик
    • различные эвристики - фета и моей

    посмотреть здесь список программного обеспечения расписания


    Я думаю, вы должны использовать генетический алгоритм, так как:

    Смотрите также :аналогичный вопрос и еще один


    Я не знаю, кто согласится с этим кодом, но я разработал этот код с помощью моего собственного алгоритма и работает для меня в ruby.Надеюсь, это поможет тем, кто ищет его в следующем коде periodflag, dayflag subjectflag и teacherflag являются хэшем с соответствующим идентификатором и значением флага, которое является логическим. Любой вопрос, свяжитесь со мной.......(- _ - )

    periodflag.каждый do / k2, v2/

                if(TimetableDefinition.find(k2).period.to_i != 0)
                    subjectflag.each do |k3,v3|
                        if (v3 == 0)
                            if(getflag_period(periodflag,k2))
                                @teachers=EmployeesSubject.where(subject_name: @subjects.find(k3).name, division_id: division.id).pluck(:employee_id)
                                @teacherlists=Employee.find(@teachers)
                                teacherflag=Hash[teacher_flag(@teacherlists,teacherflag,flag).to_a.shuffle] 
                                teacherflag.each do |k4,v4|
                                    if(v4 == 0)
                                        if(getflag_subject(subjectflag,k3))
                                            subjectperiod=TimetableAssign.where("timetable_definition_id = ? AND subject_id = ?",k2,k3)
                                            if subjectperiod.blank?
                                                issubjectpresent=TimetableAssign.where("section_id = ? AND subject_id = ?",section.id,k3)
                                                if issubjectpresent.blank?
                                                    isteacherpresent=TimetableAssign.where("section_id = ? AND employee_id = ?",section.id,k4)
                                                    if isteacherpresent.blank?
                                                        @finaltt=TimetableAssign.new
                                                        @finaltt.timetable_struct_id=@timetable_struct.id
                                                        @finaltt.employee_id=k4
                                                        @finaltt.section_id=section.id
                                                        @finaltt.standard_id=standard.id
                                                        @finaltt.division_id=division.id
                                                        @finaltt.subject_id=k3
                                                        @finaltt.timetable_definition_id=k2
                                                        @finaltt.timetable_day_id=k1
                                                        set_school_id(@finaltt,current_user)
                                                        if(@finaltt.save)
    
                                                            setflag_sub(subjectflag,k3,1)
                                                            setflag_period(periodflag,k2,1)
                                                            setflag_teacher(teacherflag,k4,1)
                                                        end
                                                    end
                                                else
                                                    @subjectdetail=TimetableAssign.find_by_section_id_and_subject_id(@section.id,k3)
                                                    @finaltt=TimetableAssign.new
                                                    @finaltt.timetable_struct_id=@subjectdetail.timetable_struct_id
                                                    @finaltt.employee_id=@subjectdetail.employee_id
                                                    @finaltt.section_id=section.id
                                                    @finaltt.standard_id=standard.id
                                                    @finaltt.division_id=division.id
                                                    @finaltt.subject_id=@subjectdetail.subject_id
                                                    @finaltt.timetable_definition_id=k2
                                                    @finaltt.timetable_day_id=k1
                                                    set_school_id(@finaltt,current_user)
                                                    if(@finaltt.save)
    
                                                        setflag_sub(subjectflag,k3,1)
                                                        setflag_period(periodflag,k2,1)
                                                        setflag_teacher(teacherflag,k4,1)
                                                    end
                                                end
                                            end
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
            end