Je me demandais s'il existait des solutions connues pour un algorithme de création d'un emploi du temps scolaire. En gros, il s’agit d’optimiser la "dispersion des heures" (à la fois dans le cas des enseignants et des classes) pour des associations données de professeurs de matières. Nous pouvons supposer que nous avons des ensembles de classes, de matières de cours et d'enseignants associés en entrée et que l'horaire doit être compris entre 8h00 et 16h00.
Je suppose qu'il n'y a probablement pas d'algorithme précis pour cela, mais peut-être que quelqu'un connaît une bonne approximation ou des astuces pour le développer.
Ce problème est NP-Complete !
En résumé, il faut explorer toutes les combinaisons possibles pour trouver la liste des solutions acceptables. En raison des différences dans les circonstances dans lesquelles le problème apparaît dans les différentes écoles (par exemple: y a-t-il des contraintes en ce qui concerne les salles de classe?), Certaines classes sont-elles divisées en sous-groupes ?, S'agit-il d'un horaire hebdomadaire? etc.) il n’existe pas de classe de problèmes bien connue qui corresponde à tous les problèmes de planification. Peut-être que le problème de Knapsack présente de nombreux éléments de similitude avec ces problèmes en général.
Une confirmation que c’est à la fois un problème difficile et un problème pour lequel les gens cherchent constamment une solution consiste à vérifier cette liste (longue) ) (principalement commerciale)
En raison du grand nombre de variables impliquées, dont les sources les plus importantes sont généralement les désirs du membre du corps professoral; -) ..., il est généralement impossible d’énumérer toutes les combinaisons possibles . Au lieu de cela, nous devons choisir une approche qui visite un sous-ensemble des espaces de problèmes/solutions.
- Algorithmes génétiques , cité dans une autre réponse est (ou, à mon humble avis, semble ) bien équipé pour effectuer ce type de recherche semi-guidée (le problème étant de trouver une bonne fonction d'évaluation pour les candidats à conserver pour la prochaine génération)
- Réécriture de graphes Les approches == sont également utiles pour ce type de problèmes d'optimisation combinatoire.
Plutôt que de nous concentrer sur des implémentations particulières d'un programme de génération automatique de programme, j'aimerais suggérer quelques stratégies pouvant être appliquées, au niveau de la définition de le problème .
L’argument général est que, dans la plupart des problèmes d’ordonnancement dans le monde réel, certains compromis seront nécessaires, pas toutes les contraintes, explicites ou implicites: seront pleinement satisfaites. Nous nous aidons donc par:
En corrigeant cette réponse, je me rends compte qu’elle est assez timide pour donner une réponse définitive, mais elle n'en est pas moins pleine de suggestions pratiques. J'espère que cette aide, avec ce qui est, après tout, un "problème difficile".
C'est le bordel. un désordre royal. Pour ajouter aux réponses, déjà très complètes, je tiens à souligner mon expérience familiale. Ma mère était enseignante et avait l'habitude de participer au processus.
Il s'avère qu’avoir un ordinateur pour le faire est non seulement difficile à coder en tant que tel, mais aussi parce qu’il existe des conditions difficiles à spécifier pour un programme informatique déjà cuit. Exemples:
Comme vous pouvez le constater, le problème n’est pas NP-complet, c’est NP-fou.
Donc, ce qu’ils font, c’est qu’ils ont une grande table avec de petits encarts en plastique et qu’ils les déplacent jusqu’à obtention d’un résultat satisfaisant. Ils ne partent jamais de zéro: ils partent normalement du calendrier de l'année précédente et font des ajustements.
Le International Timetabling Competition 2007 proposait une piste de planification de cours et de suivi d’examen. De nombreux chercheurs ont participé à ce concours. Beaucoup d'heuristiques et de métaheuristiques ont été essayés, mais à la fin, les métaheuristiques de recherche locales (telles que Tabu Search et Simulated Annealing) surpassent nettement d'autres algorithmes (tels que les algorithmes génétiques).
Jetez un coup d’œil aux 2 frameworks open source utilisés par certains des finalistes:
Une de mes missions à mi-parcours était une génération de tables d’école à algorithme génétique.
Toute la table est un "organisme". L’approche fondée sur les algorithmes génétiques génériques a été modifiée et mise en garde:
Des règles ont été établies pour les "tables illégales": deux classes dans la même classe, un enseignant enseignant deux groupes à la fois, etc. Ces mutations ont été immédiatement jugées mortelles et un nouvel "organisme" a immédiatement germé à la place du "défunt". Le premier a été généré par une série d'essais aléatoires pour en obtenir un légal (si insensé). La mutation létale n'a pas été prise en compte dans le nombre de mutations itératives.
Les mutations "Exchange" étaient beaucoup plus courantes que les mutations "Modify". Les changements ne concernaient que des parties du gène qui avaient du sens - pas de substitution d'un enseignant à une salle de classe.
De petits bonus ont été attribués pour regrouper certaines 2 heures ensemble, pour affecter la même salle de classe générique dans l'ordre pour le même groupe, pour maintenir les heures de travail de l'enseignant et la charge de la classe en continu. Des bonus modérés ont été attribués pour donner les salles de classe correctes à un sujet donné, maintenir les heures de cours dans les coffres (matin ou après-midi), etc. Les gros bonus servaient à attribuer un nombre correct de sujets donnés, une charge de travail donnée à un enseignant, etc.
Les enseignants peuvent créer leurs calendriers de charge de travail "vouloir travailler ensuite", "okay pour travailler ensuite", "n'aime pas travailler ensuite", "ne peut pas travailler ensuite", avec les poids appropriés attribués. Les heures entières étaient légales, sauf que la nuit était très indésirable.
La fonction de poids ... oh ouais. La fonction de pondération était un énorme produit monstrueux (comme dans la multiplication) des pondérations attribuées aux caractéristiques et propriétés sélectionnées. C'était extrêmement raide, une propriété pouvant facilement la changer d'un ordre de grandeur à la fois - et il y avait des centaines ou des milliers de propriétés dans un seul organisme. Cela s'est traduit par des nombres absolument ÉNORMES comme poids et, par conséquent, il est nécessaire d'utiliser une bibliothèque bignum (gmp) pour effectuer les calculs. Pour un petit test de quelque 10 groupes, 10 enseignants et 10 salles de classe, l’ensemble initial a commencé avec une note de 10 ^ -200 et quelque chose et a fini avec 10 ^ + 300. C'était totalement inefficace quand c'était plus plat. En outre, les valeurs ont augmenté beaucoup plus loin avec de plus grandes "écoles".
En termes de temps de calcul, il y avait peu de différence entre une petite population (100) sur une longue période et une grande population (10 000+) sur un nombre inférieur de générations. Le calcul sur le même temps produit à peu près la même qualité.
Le calcul (sur un processeur de 1 GHz environ) prend environ 1 heure pour se stabiliser vers 10 ^ + 300, générant ainsi des programmes qui paraissaient assez sympas, pour ledit scénario de test 10x10x10.
Le problème peut facilement être comparé en fournissant un service de réseau permettant d'échanger les meilleurs spécimens entre des ordinateurs exécutant le calcul.
Le programme qui en a résulté n'a jamais vu la lumière du jour dehors me procurer une bonne note pour le semestre. Cela promettait quelque chose, mais je n’ai jamais assez de motivation pour ajouter une interface graphique et la rendre utilisable par le grand public.
Ce problème est plus difficile qu'il n'y parait.
Comme d'autres l'ont mentionné, il s'agit d'un problème NP-complet, mais analysons ce que cela signifie.
En gros, cela signifie que vous devez examiner toutes les combinaisons possibles.
Mais "regarder" ne vous dit pas beaucoup ce que vous devez faire.
Générer toutes les combinaisons possibles est facile. Cela pourrait produire une énorme quantité de données, mais vous ne devriez pas avoir beaucoup de difficultés à comprendre les concepts de cette partie du problème.
Le deuxième problème est celui de juger si une combinaison possible donnée est bonne, mauvaise ou meilleure que la "bonne" solution précédente.
Pour cela, vous avez besoin de plus que simplement "est-ce une solution possible".
Par exemple, le même enseignant travaille-t-il 5 jours par semaine pendant X semaines d'affilée? Même si c'est une solution qui fonctionne, ce ne serait peut-être pas une meilleure solution que d'alterner deux personnes pour que chaque enseignant consacre une semaine chacune. Oh, tu n'y as pas pensé? N'oubliez pas qu'il s'agit de personnes avec lesquelles vous traitez, pas simplement d'un problème d'allocation de ressources.
Même si un enseignant pouvait travailler à plein temps pendant 16 semaines d'affilée, cela pourrait être une solution sous-optimale par rapport à une solution qui consiste à alterner les enseignants. Ce type d'équilibrage est très difficile à intégrer au logiciel.
En résumé, produire une bonne solution à ce problème vaudra beaucoup, pour beaucoup de gens. Ce n'est donc pas un problème facile à résoudre et à résoudre. Préparez-vous à fixer des objectifs qui ne sont pas à 100% et à les qualifier de «suffisamment bons».
UPDATE: à partir de commentaires ... devrait aussi avoir des heuristiques!
J'irais avec Prolog ... puis utilisez Ruby ou Perl ou quelque chose pour nettoyer votre solution sous une forme plus jolie.
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].
Je suis (encore) en train de faire quelque chose de similaire à ce problème mais en utilisant le même chemin que je viens de mentionner. Prolog (en tant que langage fonctionnel) facilite vraiment la résolution des problèmes NP-Hard.
Mon algorithme de chronométrage, implémenté dans FET (Free Timetabling Software, http://lalescu.ro/liviu/fet/ , une application réussie):
L'algorithme est heuristique. Je l'ai nommé "échange récursif".
Entrée: un ensemble d'activités A_1 ... A_n et les contraintes.
Sortie: un ensemble d'heures TA_1 ... TA_n (le créneau horaire de chaque activité. Les salles sont exclues ici, pour des raisons de simplicité). L'algorithme doit placer chaque activité à un créneau horaire en respectant les contraintes. Chaque TA_i est compris entre 0 (T_1) et max_time_slots-1 (T_m).
Contraintes:
C1) Basic: liste de paires d’activités qui ne peuvent pas être simultanées (par exemple, A_1 et A_2, car elles ont le même enseignant ou les mêmes étudiants);
C2) Beaucoup d'autres contraintes (exclues ici, pour des raisons de simplicité).
L'algorithme de chronométrage (que j'ai nommé "échange récursif"):
Essayez de placer chaque activité (A_i) dans un créneau horaire autorisé, en respectant l'ordre indiqué ci-dessus, un à la fois. Recherchez un emplacement disponible (T_j) pour A_i, dans lequel cette activité peut être placée en respectant les contraintes. Si plusieurs emplacements sont disponibles, choisissez-en un au hasard. Si aucun n'est disponible, effectuez un échange récursif:
une. Pour chaque créneau horaire T_j, réfléchissez à ce qui se passe si vous mettez A_i dans T_j. Il y aura une liste d'autres activités qui ne sont pas en accord avec ce mouvement (par exemple, l'activité A_k se trouve sur le même emplacement T_j et a le même enseignant ou les mêmes étudiants que A_i). Conservez une liste des activités en conflit pour chaque créneau horaire T_j.
b. Choisissez un emplacement (T_j) avec le nombre le plus bas d’activités en conflit. Disons que la liste des activités dans cet emplacement contient 3 activités: A_p, A_q, A_r.
c. Placez A_i à T_j et rendez A_p, A_q, A_r non alloué.
ré. Essayez récursivement de placer A_p, A_q, A_r (si le niveau de récursion n’est pas trop grand, disons 14 et si le nombre total d’appels récursifs comptés depuis l’étape 2) sur A_i commencé n’est pas trop grand, disons 2 * n), comme à l'étape 2).
e. Si vous avez placé avec succès A_p, A_q, A_r, revenez avec succès, sinon essayez d’autres créneaux horaires (passez à l’étape 2 b) et choisissez le créneau horaire suivant).
F. Si tous (ou un nombre raisonnable) de créneaux horaires ont été essayés sans succès, revenez sans succès.
g. Si nous sommes au niveau 0 et que nous n’avons pas réussi à placer A_i, placez-le comme dans les étapes 2 b) et 2 c), mais sans récursion. Nous avons maintenant 3 - 1 = 2 activités supplémentaires à placer. Passez à l'étape 2) (certaines méthodes pour éviter le cyclisme sont utilisées ici).
Les algorithmes génétiques sont souvent utilisés pour une telle planification.
Trouvé cet exemple (Créer un programme de cours à l'aide d'un algorithme génétique) qui correspond assez bien à vos besoins.
Voici quelques liens que j'ai trouvés:
Calendrier scolaire - Répertorie certains problèmes rencontrés
Un algorithme génétique hybride pour la programmation scolaire
Ce document décrit assez bien le problème des horaires scolaires et leur approche de l’algorithme: " Le développement de SYLLABUS - Un ordonnanceur interactif à base de contraintes pour les écoles et les collèges. " [PDF]
L'auteur m'informe que le logiciel SYLLABUS est encore utilisé/développé ici: http://www.scientia.com/uk/
Je travaille sur un moteur de planification largement utilisé qui fait exactement cela. Oui, c'est NP-Complete; les meilleures approches cherchent à approximer une solution optimale. Et bien sûr, il y a beaucoup de façons différentes de dire laquelle est la "meilleure" solution - est-il plus important que vos professeurs soient satisfaits de leur emploi du temps, ou que les étudiants entrent dans toutes les classes, par exemple?
La question la plus importante à résoudre dès le départ est Qu'est-ce qui rend une méthode de planification de ce système meilleure qu'une autre ? En d’autres termes, si j’ai un horaire avec Mme Jones qui enseigne les mathématiques à 8 heures et M. Smith qui enseigne les mathématiques à 9 ans, est-ce que c’est mieux ou pire qu’un qui enseigne les mathématiques à 10 ans? Est-ce mieux ou pire que Mme Jones enseignant à 8 ans et M. Jones enseignant à 2 ans? Pourquoi?
Le principal conseil que je voudrais donner ici est de diviser le problème autant que possible - peut-être cours par cours, peut-être professeur par enseignant, salle par salle, et de résoudre le problème en premier. Là, vous devriez vous retrouver avec plusieurs solutions parmi lesquelles choisir et choisir l'une des solutions les plus probables. Ensuite, essayez de faire en sorte que les sous-problèmes "antérieurs" tiennent compte des besoins des sous-problèmes ultérieurs lors de l'évaluation de leurs solutions potentielles. Ensuite, essayez peut-être de vous sortir de situations délicates (en supposant que vous ne pouvez pas anticiper ces situations dans les sous-problèmes précédents) lorsque vous arrivez à un état "pas de solutions valables".
Une passe d'optimisation de la recherche locale est souvent utilisée pour "peaufiner" la réponse finale afin d'obtenir de meilleurs résultats.
Notez que nous traitons généralement avec des systèmes fortement limités en ressources dans le calendrier scolaire. Les écoles ne passent pas toute l'année avec beaucoup de salles vides ou d'enseignants assis dans le salon 75% de la journée. Les approches qui fonctionnent le mieux dans des environnements riches en solutions ne sont pas nécessairement applicables dans le calendrier scolaire.
J'ai conçu des algorithmes commerciaux pour les horaires de cours et d'examen. Pour le premier j'ai utilisé la programmation entière; pour la seconde une heuristique basée sur la maximisation d'une fonction objectif en choisissant des échanges de slots, très similaire au processus manuel original qui avait été développé. Pour que ces solutions soient acceptées, il est essentiel de pouvoir représenter toutes les contraintes du monde réel; et que les calendriers humains ne puissent pas voir les moyens d’améliorer la solution. Au final, la partie algorithmique était relativement simple et facile à mettre en œuvre par rapport à la préparation des bases de données, à l'interface utilisateur, à la possibilité de générer des statistiques telles que l'utilisation des salles, la formation des utilisateurs, etc.
En règle générale, la programmation par contraintes constitue une bonne approche de ce type de problème de planification. Une recherche sur la "programmation par contraintes" et la planification ou "planification par contraintes" à la fois dans le dépassement de capacité de la pile et sur Google génère de bonnes références. Ce n'est pas impossible - il est juste un peu difficile de penser à l'utilisation de méthodes d'optimisation traditionnelles telles que l'optimisation linéaire ou entière. Un résultat serait: existe-t-il un calendrier qui satisfait à toutes les exigences? Cela, en soi, est évidemment utile.
Bonne chance !
Vous pouvez le faire avec des algorithmes génétiques, oui. Mais tu ne devrais pas :). Cela peut être trop lent et le réglage des paramètres peut prendre trop de temps, etc.
Il existe d'autres approches réussies. Tous mis en œuvre dans des projets open source:
Voir ici pour une liste de logiciels schedabling
Je pense que vous devriez utiliser un algorithme génétique parce que:
La qualité de la solution dépend du temps que vous avez l'intention de consacrer à la résolution du programme.
Définition des algorithmes génétiques
Regardez aussi: une question similaire et une autre
Je ne sais pas si quelqu'un sera d'accord avec ce code, mais j'ai développé ce code à l'aide de mon propre algorithme et travaille pour moi dans Ruby.Espoir que cela aidera ceux qui le recherchent Dans le code suivant, le periodflag, dayflag subjectflag et teacherflag sont le hachage avec l'identifiant correspondant et la valeur de drapeau qui est Boolean . Tout problème contactez-moi ....... (-_-)
periodflag.each 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
@[email protected]_struct_id
@[email protected]_id
@finaltt.section_id=section.id
@finaltt.standard_id=standard.id
@finaltt.division_id=division.id
@[email protected]_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