Kalender / Planungsalgorithmus

24

Ich stehe vor einem Problem und bin mir nicht sicher, wie ich vorgehen soll. Ich muss einen Kalender für Mitarbeiter erstellen, die jeweils bestimmte (teilweise persönliche, teilweise gemeinsame) Arbeitsbedingungen haben.

Womit ich arbeite:

  • Ich habe Ärzte
  • Jeder Arzt muss 5 Tage die Woche arbeiten.
  • Jeder Arzt muss 1 Nacht / Woche arbeiten
  • Jeder Arzt muss die gleiche Anzahl von Nächten im Vergleich zu anderen Ärzten (oder so nah wie möglich) arbeiten
  • Jeder Arzt muss eine gleiche Anzahl von Donnerstagnächten und Sonntagnächten im Vergleich zu anderen Ärzten (oder so nah wie möglich) arbeiten.
  • Einige Ärzte können bestimmte Tage / Nächte nicht arbeiten (Eingabe durch Benutzer)
  • Einige Ärzte möchten bestimmte Tage / Nächte arbeiten (Eingabe durch Benutzer)
  • Einige Ärzte möchten bestimmte Tage / Nächte nicht arbeiten (Eingabe durch Benutzer)

Der fragliche Benutzer ist die Person, die mit dem Kalender befasst ist. Ich versuche, eine Lösung zu erstellen, die automatisch einen Kalender generiert, der alle Einschränkungen berücksichtigt. Die Lösung ist nur eine große Einstellungs-Eingabe "Ärzte hinzufügen" und "Einschränkungen hinzufügen" für jeden Arzt, dann eine Schaltfläche "Kalender generieren". Es ist wirklich grundlegend für den Benutzer.

Mein Problem :

Ich bin mir nicht sicher, wie ich die eigentliche Planung generieren soll, ich habe über neuronale Netze, genetische Algorithmen usw. gelesen und sie scheinen alle die richtige Lösung zu sein, aber auch nicht wirklich.

Wenn ich mir die GAs ansehe, werden sie dazu gebracht, eine Lösung für eine bestimmte Population (mein Problem) zu finden, aber die Startpopulation muss bereits die gegebenen Einschränkungen einhalten, die dann optimiert würden. In diesem Fall ist meine Startpopulation bereits die Lösung. Ich brauche es nicht, um "optimiert" zu werden. Es spielt keine Rolle, dass eine einzelne Person 3 Montagnächte hintereinander arbeitet, solange es richtig ist und andere die gleiche Menge arbeiten. Das bedeutet, dass andere Personen irgendwann auch 3 Montagnächte arbeiten und es in Ordnung ist. Was mich denken lässt, dass GA's für mich zu "fortgeschritten" sind, da mein Problem bereits mit dem Startpunkt eines GA gelöst ist.

Aber andererseits sieht GA wirklich wirklich so aus, als wären sie dafür gemacht, also verstehe ich es vielleicht nicht richtig?

Da ich noch nie GAs (oder neuronale Netze oder ähnliches) verwendet habe, möchte ich sichergehen, dass ich mich auf den richtigen Ansatz einlasse, bevor ich mich auf eine Lernkurve wie diese einlasse.

Meine Frage :

Was halten Sie für einen guten Ansatz / Algorithmus / eine gute Technik für ein Problem wie das meine? Gas? Neuronale Netze? Noch etwas ganz anderes?

Ich bin ganz offen für Details, aber ich denke, ich habe mich ziemlich klar ausgedrückt :)

Gil Sand
quelle
22
Wahrscheinlich lohnt sich , Literatur schaut sich um die Krankenschwester rostering Problem en.wikipedia.org/wiki/Nurse_scheduling_problem
Renaud M.
So ein bequemer Begriff! Hehe, danke für deinen Link;)
Gil Sand
8
Ich bin kein Experte auf diesem Gebiet. Wenn Sie jedoch nach einem Ansatz suchen, mit dem Sie Zeit bei der Entwicklung sparen, lohnt es sich möglicherweise, das Problem als Mixed Integer Programming Problem ( en.wikipedia. org / wiki / Linear_programming # Integer_unknowns ) und geben Sie es dann in einen MIP-Solver oder als Einschränkungsprogrammierproblem ein und geben Sie es dann in einen CP-Solver wie OR-Tools ein ( developers.google.com/optimization ). Auf diese Weise müssen Sie nur Ihr Problem ausdrücken.
Renaud M.
3
Die lineare Programmierung liefert garantiert die optimale Lösung!
recursion.ninja
2
@RenaudM. Es ist eine Schande, wie wenige professionelle Programmierer dieses erstaunlich nützliche Gebiet der Mathematik verstehen. Wann immer jemand außerhalb des KI-Feldes simuliertes Annealing oder genetische Algorithmen vorschlägt, lautet meine Darmreaktion: Kann wahrscheinlich besser als lineare Programmoptimierung modelliert werden
recursion.ninja

Antworten:

14

Genetische Algorithmen und neuronale Netze sind hier nicht geeignet. Sie sind Meta-Heuristiken, um eine hinreichend gute, ungefähre Lösung für ein Problem zu finden. Beides setzt voraus, dass Sie eine Kostenfunktion finden, um Kandidatenlösungen zu bewerten. Sobald Sie eine solche Kostenfunktion haben, ist es möglicherweise einfacher, manuell einen Algorithmus zu entwickeln, der für diese Kosten optimiert.

Dies ist ein wichtiger Gedanke: Bei zwei Zeitplänen müssen wir entscheiden, ob Zeitplan A oder Zeitplan B „besser“ ist. Sie haben verschiedene Kriterien aufgelistet, aber es ist nicht klar, in welcher Beziehung sie zueinander stehen. Scheitert die Nichterfüllung eines Kriteriums an der gesamten Lösung? Oder ist es eine schlechtere Lösung als andere, wenn eine Einschränkung teilweise nicht erfüllt wird?

Auf der einfachsten Ebene können Sie die Woche einfach in diskrete Zeitfenster unterteilen und alle Slot-Doctor-Kombinationen brachial erzwingen. Sie können jedoch hartnäckige Einschränkungen verwenden, um diesen Suchbereich auf eine handlichere Größe zu reduzieren. Die Beschränkungen der Arbeitszeit und der Nachtschichten scheinen für eine solche Begrenzung des Suchraums geeignet zu sein. Ihnen bleiben dann Hunderte von Lösungskandidaten.

Um die beste Kandidatenlösung auszuwählen, müssen Sie sie klassifizieren. Dies ist ziemlich einfach, wenn eine weiche Einschränkung eindeutig Vorrang vor allen anderen weichen Einschränkungen hat, z. B. wenn ein Arzt eine bestimmte Schicht nicht ausführen kann, wird dies wichtiger als ein Arzt, der diese Schicht nicht ausführen möchte. Aber ich kann diese Regeln nicht für Sie festlegen - das ist eine Entscheidung des Managements. Es ist schwieriger, wenn zwei weiche Abhängigkeiten keine eindeutige Priorität haben. In diesem Fall müssen Sie eine Kostenfunktion entwickeln, die die Wichtigkeit von zwei Abhängigkeiten in einer einzigen Metrik vereint.


Ich würde wahrscheinlich einen gierigen Algorithmus konstruieren, der einen leeren Zeitplan nach einigen priorisierten Kriterien ausfüllt. Dies ist vielleicht nicht die optimalste Lösung, aber es ist viel einfacher als zu philosophieren, was "optimal" eigentlich bedeutet.

Als ersten Schritt könnten Sie die Nachtschichten am Wochenende ausfüllen und versuchen, diejenigen Ärzte auszuwählen, die am Wochenende die längste Zeit keine Nachtschicht mehr gemacht haben, und dabei auch die Benutzerwünsche berücksichtigen, dass ich dort nicht arbeiten kann . Vorausgesetzt, dass diese Wünsche pro Woche und nicht kontinuierlich sind, bedeutet dies, dass nächste Woche ein Arzt ausgewählt wird, der an Wochenendabenden eine Woche lang nicht arbeiten kann.

Ein ähnliches Verfahren kann für die anderen Abende angewendet werden: Nachdem Sie versucht haben, Benutzerwünsche zu berücksichtigen, geben Sie Ärzte an, die die längste Zeit keine Nachtschicht mehr absolviert haben. Die Prozedur wiederholt sich in ähnlicher Weise für die dritte Art von Zeitfenster, die Tagverschiebung. Wenn zwei Benutzerwünsche nicht in Einklang gebracht werden können, können Sie nachverfolgen, wie oft ein Benutzerwunsch gewährt wurde, und dann dem Arzt mit weniger gewährten Wünschen Prioritäten zuweisen.

Leider sehe ich einige Möglichkeiten, um dieses System zu spielen: Wenn beispielsweise ein Arzt für eine Wochenendnachtschicht ausgewählt wird, aber die Anfrage "Kann dort nicht arbeiten" eingeht, wird die Auswahl um eine Woche verzögert, wodurch sich die Anzahl verringert Häufigkeit der Nachtschichten am Wochenende auf Kosten der Kollegen. Wenn ein Wunschlösungsverfahren implementiert ist, das die Anzahl der abgelehnten Anfragen betrachtet, kann ein Benutzer einige unmögliche Anfragen stellen, um eine Anfrage zu erhöhen, die er durchlaufen möchte. Unter der Annahme von Treu und Glauben (und der Flexibilität für Ärzte, Schichten untereinander auszutauschen) sollte ein solcher Algorithmus jedoch zu einer ausreichend guten Lösung führen.

amon
quelle
Vielen Dank für Ihre Antwort, ich werde mit meinem Kollegen ein bisschen mehr darüber nachdenken :) Um Ihnen mehr Informationen zu geben: Ja, wir können die meisten Lösungen / Kriterien bewerten und entscheiden, ob einige Vorrang vor anderen haben. Außerdem arbeiten sie jetzt wirklich an Treu und Glauben und es funktioniert gut. Sie tun es mit der Hand und verwenden das Wort "Ich kann nicht an einem Tag arbeiten" nicht zu oft. Es ist ganz nett, wie sie das jetzt zum Laufen bringen, da sie es wirklich von Hand machen . Eine "tragfähige" Lösung wird ihnen also bereits die Welt bedeuten und ihnen eine Menge Brainstorming-Zeit ersparen, wer wann arbeiten kann
Gil Sand
5
@Zil Die Leute, die gerade Zeitpläne erstellen, verwenden wahrscheinlich bereits einen informellen Algorithmus. Sie könnten einfach mit ihnen sprechen und versuchen, ihren Entscheidungsprozess zu verstehen, und das dann formalisieren und umsetzen. Dies wäre viel einfacher als das Einrichten und Trainieren eines neuronalen Netzwerks.
amon
Das ist unser erster Schritt: p Wir haben ein Treffen mit ihnen bereits vereinbart! Vielen Dank für all Ihre Hilfe :)
Gil Sand
3
Für diesen Anwendungsfall sind Genetik-Algorithmen der Tabu-Suche und dem simulierten Tempern durchweg unterlegen, wie die Forschungswettbewerbe "International Nurse Rostering Competitions" belegen. (Aber natürlich sind sie immer noch besser als nur eine gierige Algo.)
Geoffrey De Smet
12

Sie können simuliertes Tempern verwenden .

Ich habe so etwas gemacht, bevor ich meinen ersten Job bekam - siehe https://vimeo.com/20610875 (Demo ab 2:50, Algorithmus erklärt ab 6:15).

Das simulierte Tempern ist eine Art genetischer Algorithmus, und vielleicht war es theoretisch nicht geeignet (wie @amon in seiner Antwort behauptet ), aber in der Praxis hat es sehr gut funktioniert, und es war ungefähr der gleiche Anwendungsfall wie bei Ihnen.

Quellcode ist verfügbar (C #), aber während es funktioniert, ist es schrecklich, ich fürchte, es war vor ein paar Jahren und als Autodidakt wusste ich nichts über Wartbarkeit. Es lieferte jedoch sehr gute Ergebnisse.

So funktioniert es auf den Punkt gebracht:

  • Generieren Sie einen möglichen (möglicherweise nicht sehr guten, aber physisch möglichen) Zeitplan als Ausgangspunkt. Ein genetischer Algorithmus ist an dieser Stelle nicht erforderlich - Sie können sich einfach den Weg zu der ersten Lösung bahnen, die Sie finden können. Ich habe Backtracking verwendet . Die Komplexität der Berechnungen kann überwunden werden, indem die Rota für jeden Tag separat gelöst wird. Wenn es überhaupt keine Lösung gibt (wie es der Fall sein könnte), erkennen Sie dies an diesem Punkt.

  • Erstellen Sie einen Pool von Lösungen - beispielsweise 100 Kopien dieser Einstiegslösung.

  • Mutieren Sie jede Lösung nach dem Zufallsprinzip: Lassen Sie die Ärzte die Schichten untereinander tauschen, nehmen Sie einen zufälligen Arzt aus der Schicht und legen Sie eine zufällig verfügbare Person darauf usw.

  • Bewerten Sie jede Lösung mit einer Fitnessfunktion , die feststellt, wie gut sie ist. Ein Mann arbeitet mehr Nächte als ein anderer? Strafpunkte abziehen. Jemand wollte Montag machen, aber nicht? Strafpunkte erneut abziehen.

  • Nehmen Sie - sagen wir - 20 beste Lösungen und kopieren Sie jede von ihnen fünfmal. Überschreiben Sie dabei die verbleibenden 80 und tragen Sie sie zur nächsten Generation. Überleben der Stärksten.

  • Spülen und wiederholen.

Zahlen sind offensichtlich willkürlich. Möglicherweise müssen Sie mit Parametern experimentieren, um die optimalen Einstellungen für Ihr Szenario zu ermitteln.

Was das Mutieren einer Lösung angeht, führt simuliertes Tempern etwas ein, das als Temperatur bezeichnet wird. Grundsätzlich bedeutet dies, dass Sie Ihre Lösungen am Anfang ziemlich stark mutieren sollten (z. B. immer 10 Versuche, die Schichten auf einmal zu vertauschen) und bei nachfolgenden Iterationen allmählich weniger aggressiv werden sollten, damit sie sich feiner abstimmen (z. B. nach unten) nur 2 Optimierungsversuche pro Generation).

Konrad Morawski
quelle
4
Ich habe OptaPlanner (nee Drools Planner) mit Simulated Annealing für einen College-Stundenplan verwendet. Deklarieren Sie die Modelle - eine Schicht hat eine Zeit und einen Arzt. Schreiben Sie deklarative Regeln für die Fitnessfunktion - harte Einschränkungen (ein Arzt kann keine überlappenden Schichten einnehmen) und Strafen (Ann hasst Montags). Schreiben Sie deklarative (das ist der Punkt!) Schichtwechsel. OptaPlanner erstellt den Startzustand nach dem Zufallsprinzip (möglicherweise nicht realisierbar), berechnet die Fitnessfunktion aus den Regeln und bedient die Swaps sogar nach dem Optimierungsalgorithmus. Sie können Parameter wie den Zeitplan für das Tempern auswählen und einstellen.
Jesvin Jose
6

Genetische Algorithmen treffen hier zu. Während meines Grundstudiums schrieb einer meiner Kollegen eine Arbeit zu einem sehr ähnlichen Problem von Ihnen.

Sie können nach Job Shop Scheduling suchen und auch Open Shop Scheduling oder Flow Shop Scheduling können interessante Ausgangspunkte sein

Um einen genetischen Algorithmus zu verwenden, benötigen Sie keine perfekte Lösung. Beginnen Sie mit N zufälligen Kandidaten und wenden Sie auf jeden von ihnen eine Fitnessfunktion an. Beispiel:

  • Die Differenz der Übernachtungen zwischen dem am stärksten beschäftigten Arzt und dem am wenigsten beschäftigten Arzt ist eine Bestrafung der Kostenfunktion
  • Jedes Mal, wenn ein Arzt mehr als 5 Tage pro Woche oder 1 Nacht pro Woche arbeitet, wird eine Strafe verhängt
  • Jede Ihrer Einschränkungen, etc ...

Wenn Sie N Kandidaten generieren, wählen Sie die X besten von ihnen aus . Sie sind diejenigen, die die Einschränkungen umso weniger auslösen. Wenn man über mehrere Generationen hinweg mit ihnen zusammenarbeitet, sie kreuzt und mutiert, kann man eine gute Lösung finden.

Nachdem ich all das besprochen hatte, konnte ich jedes Mal, wenn ich einen genetischen Algorithmus verwendete, der mehr auf Mutationen als auf Kreuzungen beruhte, ein simuliertes Annealing entwickeln, das eine weitaus bessere Leistung bei einer einfacheren Implementierung erbrachte. Die Kosten / Eignung und die Mutationsfunktion für den genetischen Algorithmus werden wahrscheinlich einer sehr ähnlichen sein, die bei einem simulierten Annealing verwendet wird. Ich würde dort anfangen, siehe @Konrad Morawski Antwort

Google-Suche findet gute Ergebnisse für Job Shop und GA

RMalke
quelle