Calendrier / algorithme de planification

24

Je fais face à un problème, je ne sais pas trop comment aborder Je dois générer un calendrier pour les employés, chacun ayant des contraintes de travail spécifiques (certaines personnelles, d'autres communes)

Avec quoi je travaille:

  • J'ai des médecins
  • Chaque médecin doit travailler 5 jours / semaine.
  • Chaque médecin doit travailler 1 nuit / semaine
  • Chaque médecin doit travailler un nombre de nuits égal par rapport aux autres médecins (ou le plus près possible)
  • Chaque médecin doit travailler un nombre égal de jeudi soir et dimanche soir par rapport aux autres médecins (ou le plus près possible)
  • Certains médecins ne peuvent pas travailler certains jours / nuits (saisie par l'utilisateur)
  • Certains médecins aimeraient travailler certains jours / nuits (saisie par l'utilisateur)
  • Certains médecins aimeraient ne pas travailler certains jours / nuits (saisie par l'utilisateur)

L'utilisateur en question est la personne qui s'occupe du calendrier, j'essaye de construire une solution qui va générer automatiquement un calendrier qui obéit à toutes les contraintes. La solution est juste une grande entrée de paramètres "ajouter des médecins" et "ajouter des contraintes" pour chaque médecin, puis un bouton "générer un calendrier". C'est vraiment basique pour l'utilisateur.

Mon problème :

Je ne sais pas comment générer la planification réelle, j'ai lu sur les réseaux de neurones, les algorithmes génétiques, etc., et ils semblent tous être la bonne solution mais pas vraiment.

Quand je regarde les GA, ils sont faits pour trouver une solution avec une population donnée (mon problème), mais la population de départ doit déjà obéir à l'ensemble de contraintes donné, qui serait alors optimisé. Dans ce cas, ma population de départ est déjà la solution. Je n'ai pas besoin qu'il soit "optimisé". Peu importe qu'une seule personne travaille 3 lundi soirs d'affilée, tant que c'est correct et que d'autres travaillent le même montant, cela signifie que d'autres travailleront également 3 lundi soir à un moment donné et ça va. Ce qui me fait penser que les GA sont trop "avancés" pour moi, car mon problème est déjà résolu avec le point de départ d'une GA.

Mais là encore, les GA semblent vraiment vraiment faits pour ça, donc je ne peux pas le comprendre correctement?

Quoi qu'il en soit, comme je n'ai jamais utilisé d'AG (ou de réseaux de neurones, ou quoi que ce soit du genre), je voudrais être sûr de choisir la bonne approche avant de m'engager dans une courbe d'apprentissage comme celle-ci.

Ma question :

Selon vous, quelle est la bonne approche / algorithme / technique pour un problème comme le mien? Gaz? Les réseaux de neurones? Quelque chose de complètement différent?

Je suis à l'écoute et ouvert pour plus de détails si nécessaire, mais je pense que je me suis bien fait comprendre :)

Gil Sand
la source
22
Il vaut probablement la peine de consulter la littérature sur le problème du fichier des infirmières en.wikipedia.org/wiki/Nurse_scheduling_problem
Renaud M.
Un terme si pratique! Hehe, merci pour votre lien;)
Gil Sand
8
Je ne suis pas un expert dans ce domaine, mais si ce que vous recherchez est une approche qui vous ferait gagner du temps sur le développement, il pourrait être utile d'essayer de modéliser le problème comme un problème de programmation en nombres mixtes ( en.wikipedia. org / wiki / Linear_programming # Integer_unknowns ), puis saisissez-le dans un solveur MIP, ou en tant que problème de programmation par contraintes, puis saisissez-le dans un solveur CP, tel que des outils OR ( developers.google.com/optimization ). De cette façon, tout ce que vous avez à faire est d'exprimer votre problème.
Renaud M.
3
La programmation linéaire est garantie de dériver lasolution optimale !
recursion.ninja
2
@RenaudM. Il est dommage que peu de programmeurs professionnels comprennent ce domaine incroyablement utile des mathématiques. Chaque fois que quelqu'un suggère un recuit simulé ou des algorithmes génétiques en dehors du champ de l'IA, ma réponse intestinale est: peut probablement être mieux modélisée comme une optimisation de programme linéaire
recursion.ninja

Réponses:

14

Les algorithmes génétiques et les réseaux de neurones ne conviennent pas ici. Ce sont des méta-heuristiques pour trouver une solution approximative suffisamment bonne à un problème. Notamment, les deux nécessitent que vous trouviez une fonction de coût pour évaluer les solutions candidates. Une fois que vous avez une telle fonction de coût, il peut être plus facile de trouver manuellement un algorithme qui optimise ce coût.

C'est une pensée importante: étant donné deux horaires, nous avons besoin d'un moyen de décider si l'annexe A ou l'annexe B est «meilleure». Vous avez énuméré divers critères, mais leur relation n'est pas claire. Le non-respect d'un critère échoue-t-il à toute la solution? Ou l'échec partiel d'une contrainte en fait-il simplement une pire solution que d'autres?

Au niveau le plus élémentaire, vous pouvez simplement partitionner la semaine en intervalles de temps discrets et forcer toutes les combinaisons slot-docteur. Cependant, vous pouvez utiliser des contraintes qui échouent fortement pour réduire cet espace de recherche à une taille plus gérable. Les restrictions sur le temps de travail et les quarts de nuit semblent convenir à une telle limitation de l'espace de recherche. Il vous reste alors des centaines de solutions candidates.

Pour sélectionner la meilleure solution candidate, vous devrez les classer. C'est assez facile si une contrainte souple a une priorité claire sur toutes les autres contraintes souples, par exemple si un médecin ne peut pas travailler un certain quart de travail, cela est plus important qu'un médecin ne voulant pas travailler ce quart de travail. Mais je ne peux pas décider de ces règles pour vous - c'est une décision de gestion. C'est plus difficile si deux contraintes souples n'ont pas de priorité claire, auquel cas vous devrez trouver une sorte de fonction de coût qui unifie l'importance de deux contraintes dans une seule métrique.


Je construirais probablement un algorithme gourmand qui remplit un calendrier vide en fonction de certains critères de priorité. Ce n'est peut-être pas la solution la plus optimale, mais c'est beaucoup plus facile que de penser à ce que signifie réellement «optimal».

Dans un premier temps, vous pouvez remplir les quarts de nuit le week-end et essayer de sélectionner les médecins qui n'ont pas effectué de quart de nuit le week-end le plus longtemps, en tenant également compte des souhaits des utilisateurs «Je ne peux pas travailler là-bas» . En supposant que ces souhaits sont hebdomadaires et non continus, cela signifie qu'un médecin qui ne peut pas travailler les soirs de week-end pendant une semaine serait choisi la semaine prochaine.

Une procédure similaire peut être utilisée pour les autres nuits: après avoir essayé de respecter les souhaits des utilisateurs, vous remplissez des médecins en fonction de qui n'a pas effectué de quarts de nuit depuis le plus longtemps. La procédure se répète de manière similaire pour le troisième type de créneau horaire, le jour change. Si deux souhaits d'utilisateurs ne peuvent pas être conciliés, vous pouvez garder une trace de la fréquence à laquelle un souhait d'utilisateurs a été accordé, puis prioriser le médecin avec moins de souhaits accordés.

Malheureusement, je peux voir deux façons de jouer à ce système: par exemple, si un médecin était choisi pour travailler un quart de nuit le week-end mais présentait une demande «ne peut pas travailler là-bas», leur choix serait retardé d'une semaine - réduisant ainsi leur fréquence des quarts de nuit le week-end au détriment de leurs collègues. Si une procédure de résolution de souhaits est mise en œuvre qui examine le nombre de demandes refusées, un utilisateur peut soumettre quelques demandes impossibles pour augmenter une demande qu'il souhaite traiter. Cependant, en supposant la bonne foi (et la flexibilité pour les médecins de permuter les changements entre eux), un tel algorithme devrait aboutir à une solution suffisamment bonne.

amon
la source
Merci pour votre réponse, je vais creuser un peu plus avec mon collègue :) Pour vous donner plus d'informations: oui, nous pouvons classer la plupart des solutions / critères, et nous pouvons décider si certaines ont priorité sur les autres. De plus, ils travaillent vraiment de bonne foi maintenant, et cela fonctionne bien. Ils le font à la main et n'utilisent pas trop le "je ne peux pas travailler le jour". C'est assez agréable de voir comment ils font fonctionner cela maintenant, car ils le font vraiment à la main . Donc, une solution "viable" signifiera déjà le monde pour eux, et leur épargnera BEAUCOUP de temps de réflexion pour savoir qui peut travailler quand
Gil Sand
5
@Zil les personnes qui créent actuellement les horaires utilisent déjà probablement un algorithme informel. Vous pourriez simplement leur parler et essayer de comprendre leur processus de décision, puis formaliser et mettre en œuvre cela. Ce serait beaucoup plus facile que de mettre en place et de former un réseau de neurones.
amon
C'est notre première étape: p nous avons un rendez-vous avec eux déjà organisé! Merci pour toute votre aide :)
Gil Sand
3
Pour ce cas d'utilisation, les algorithmes génétiques sont systématiquement inférieurs à la recherche Tabu et au recuit simulé, comme l'ont démontré les concours de recherche International Nurse Rostering Competitions. (Mais bien sûr, ils sont toujours meilleurs qu'un simple algo gourmand.)
Geoffrey De Smet
12

Vous pouvez utiliser un recuit simulé .

J'ai fait quelque chose comme ça avant de décrocher mon premier emploi - voir https://vimeo.com/20610875 (démo à partir de 2:50, algorithme expliqué à partir de 6:15).

Le recuit simulé est un type d'algorithme génétique, et peut-être qu'il n'était pas adapté en théorie (comme @amon le soutient dans sa réponse ), mais cela a très bien fonctionné dans la pratique, et il s'agissait du même cas d'utilisation que le vôtre.

Le code source est disponible (C #), mais pendant qu'il fonctionne, c'est terrible, je le crains, c'était il y a quelques années et étant un autodidacte, je ne savais rien de la maintenabilité. Cela a cependant donné de très bons résultats.

Comment cela fonctionne en un mot:

  • Générez 1 horaire possible (ce n'est peut-être pas très bon, mais physiquement possible) comme point de départ. Un algorithme génétique n'est pas nécessaire à ce stade - vous pouvez simplement forcer votre chemin vers la première solution que vous pouvez trouver. J'ai utilisé le retour en arrière . La complexité de calcul peut être surmontée en résolvant le rota pour chaque jour séparément. S'il n'y a aucune solution (selon le cas), c'est à ce stade que vous la détectez.

  • Faites un pool de solutions - disons, 100 copies de cette solution d'entrée de gamme pour commencer.

  • Muter toutes les solutions au hasard: demandez aux médecins d'échanger leurs quarts de travail, de retirer un médecin au hasard de son quart de travail et de mettre une personne disponible au hasard, etc.

  • Évaluez chaque solution avec une fonction de fitness qui détermine sa qualité. Un gars travaille plus de nuits qu'un autre? Soustrayez les points de pénalité. Quelqu'un voulait faire lundi mais ils ne le font pas? Soustrayez à nouveau les points de pénalité.

  • Prenez - disons - les 20 meilleures solutions et copiez chacune d'elles 5 fois, en écrasant les 80 restantes avec elles, les transportant ainsi à la prochaine génération. La survie du plus fort.

  • Rincez et répétez.

Les nombres sont évidemment arbitraires, vous devrez peut-être jouer avec les paramètres pour trouver les paramètres optimaux pour votre scénario.

Quant à la mutation d'une solution, le recuit simulé introduit quelque chose appelé température. Fondamentalement, cela signifie qu'au début, vous devez muter vos solutions assez fort (par exemple, faites toujours 10 tentatives de permutation de changements en une seule fois) et devenez progressivement moins agressif avec les itérations suivantes, de sorte qu'elles deviennent plus un réglage fin (par exemple, vers le bas à seulement 2 tentatives de réglages par génération).

Konrad Morawski
la source
4
J'ai utilisé OptaPlanner (nee Drools Planner) avec recuit simulé pour un horaire de collège. Déclarez les modèles - un Shift a un temps et un docteur. Écrivez des règles déclaratives pour la fonction fitness - contraintes dures (un docteur ne peut pas prendre des quarts qui se chevauchent) et pénalités (Ann déteste les lundis). Écrire des échanges déclaratifs (c'est le point!) De changements. OptaPlanner créera l'état de départ au hasard (peut être impossible), calculera la fonction de fitness à partir des règles et même opérera les swaps selon l'algorithme d'optimisation. Vous pouvez choisir et régler des paramètres comme le calendrier de recuit.
Jesvin Jose
6

Les algorithmes de génétique s'appliquent ici. Au cours de mon programme de premier cycle, un de mes collègues a écrit un article sur votre problème très similaire.

Vous pouvez rechercher la planification de l'atelier de travail et également la planification de l'atelier ouvert ou la planification de l'atelier de flux peuvent être des points de départ intéressants

Pour utiliser un algorithme génétique, vous n'avez pas besoin d'une solution parfaite, vous pouvez commencer avec N candidats aléatoires et appliquer une fonction de fitness à chacun d'eux, par exemple:

  • La différence de nuits attribuées entre le médecin le plus occupé et le moins occupé est une pénalisation de la fonction de coût
  • Chaque fois qu'un médecin travaille plus de 5 jours par semaine ou 1 nuit par semaine, vous appliquez une pénalité
  • Chacune de vos contraintes, etc ...

En générant N candidats, vous choisiriez les X meilleurs d'entre eux , ce seraient eux qui infligeraient le moins de contraintes. Travailler avec eux, traverser et muter sur plusieurs générations peut aboutir à une bonne solution.

Après avoir parlé de tout cela, chaque fois que j'utilisais un algorithme génétique qui reposait davantage sur la mutation que sur le croisement, je pouvais développer un recuit simulé qui fonctionnerait beaucoup mieux, avec une mise en œuvre plus facile. Le coût / fitness et la fonction de mutation pour l'algorithme génétique seront probablement très similaires à ceux utilisés dans un recuit simulé. Je commencerais par là, regardez la réponse de @Konrad Morawski

La recherche Google trouve de bons résultats pour Job Shop et GA

RMalke
la source