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 :)
Antworten:
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.
quelle
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).
quelle
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:
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
quelle