Algoritmo di calendario / pianificazione


24

Sto affrontando un problema non sono sicuro di come affrontare. Devo generare un calendario per i dipendenti, ognuno con specifici vincoli di lavoro (alcuni personali, altri comuni)

Con cosa sto lavorando:

  • Ho dei dottori
  • Ogni medico deve lavorare 5 giorni / settimana.
  • Ogni medico deve lavorare 1 notte / settimana
  • Ogni medico deve lavorare un numero uguale di notti rispetto ad altri medici (o il più vicino possibile)
  • Ogni medico deve lavorare un uguale numero di giovedì sera e domenica sera rispetto ad altri medici (o il più vicino possibile)
  • Alcuni medici non possono lavorare in determinati giorni / notti (input dell'utente)
  • Alcuni medici vorrebbero lavorare determinati giorni / notti (input dell'utente)
  • Alcuni medici vorrebbero non lavorare in determinati giorni / notti (input dell'utente)

L'utente in questione è la persona che si occupa del calendario, sto cercando di creare una soluzione che genererà automaticamente un calendario che obbedisce a tutti i vincoli. La soluzione è solo una grande impostazione di input "Aggiungi dottori" e "Aggiungi vincoli" per ogni medico, quindi un pulsante "Genera calendario". È davvero di base per l'utente.

Il mio problema :

Non sono sicuro di come generare la vera pianificazione, ho letto di reti neurali, algoritmi genetici e così via, e sembrano tutti la soluzione giusta, ma non proprio.

Quando guardo i GA, sono fatti per trovare una soluzione con una data popolazione (il mio problema), ma la popolazione iniziale deve già obbedire al set di vincoli dato, che sarebbe quindi ottimizzato. In tal caso, la mia popolazione iniziale è già la soluzione. Non ho bisogno che sia "ottimizzato". Non importa che una sola persona lavori 3 lunedì di seguito, purché sia ​​effettivamente corretta e che altri lavorino lo stesso importo, il che significa che altri lavoreranno anche 3 lunedì a un certo punto e va bene. Il che mi fa pensare che i GA siano troppo "avanzati" per me, poiché il mio problema è già risolto con il punto di partenza di un GA.

Ma ancora una volta, GA sembra davvero che siano fatti per questo, quindi potrei non capirlo correttamente?

Ad ogni modo, dato che non ho mai usato GA (o reti neurali, o qualcosa del genere), mi piacerebbe essere sicuro di seguire l'approccio corretto prima di impegnarmi in una curva di apprendimento come quella.

La mia domanda :

Quale pensi sia un buon approccio / algoritmo / tecnica per un problema come il mio? Gas? Reti neurali? Qualcos'altro completamente diverso?

Sono tutto pronto e aperto per ulteriori dettagli, se necessario, ma penso di essermi reso abbastanza chiaro :)


22
Probabilmente vale la pena guardare la letteratura sull'infermiera che presenta il problema en.wikipedia.org/wiki/Nurse_scheduling_problem
Renaud M.

Un termine così conveniente! Hehe, grazie per il tuo link;)
Gil Sand,

8
Non sono un esperto in questo settore, tuttavia se quello che stai cercando è un approccio che ti faccia risparmiare tempo nello sviluppo, potrebbe valere la pena provare a modellare il problema come un problema di programmazione con numeri interi misti ( en.wikipedia. org / wiki / Linear_programming # Integer_unknowns ) e quindi immetterlo a un risolutore MIP o come problema di programmazione di vincoli e quindi inserirlo in un risolutore di CP, come OR-tools ( developers.google.com/optimization ). In questo modo tutto ciò che devi fare è esprimere il tuo problema.
Renaud M.,

3
La programmazione lineare garantisce lasoluzione ottimale !
recursion.ninja,

2
@RenaudM. È un peccato che pochi programmatori professionisti comprendano questo campo matematico straordinariamente utile. Ogni volta che qualcuno suggerisce una ricottura simulata o algoritmi genetici al di fuori del campo dell'intelligenza artificiale, la mia risposta intestinale è: probabilmente può essere meglio modellata come ottimizzazione del Programma lineare
recursion.ninja

Risposte:


14

Gli algoritmi genetici e le reti neurali non sono adatti qui. Sono meta-euristiche per trovare una soluzione abbastanza buona e approssimativa a un problema. In particolare, entrambi richiedono di trovare una funzione di costo per valutare le soluzioni candidate. Una volta che hai una tale funzione di costo, potrebbe essere più facile elaborare manualmente un algoritmo che ottimizzi per questo costo.

Questo è un pensiero importante: dati due programmi, abbiamo bisogno di un modo per decidere se il programma A o il programma B è "migliore". Hai elencato vari criteri, ma non è chiaro come siano correlati. Il mancato rispetto di un criterio non riesce all'intera soluzione? O il fallimento parziale di un vincolo lo rende semplicemente una soluzione peggiore rispetto ad altri?

Al livello più elementare, puoi semplicemente dividere la settimana in fasce orarie discrete e forzare tutte le combinazioni slot-dottore. Tuttavia, è possibile utilizzare vincoli di errore per ridurre questo spazio di ricerca a dimensioni più gestibili. Le restrizioni sull'orario di lavoro e sui turni notturni sembrano essere adatte a limitare tale spazio di ricerca. Ti rimangono quindi centinaia di soluzioni candidate.

Per selezionare la migliore soluzione candidata, dovrai classificarle. Questo è abbastanza facile se un vincolo soft ha una chiara precedenza su tutti gli altri vincoli soft, ad esempio se un medico non può lavorare in un determinato turno, a cui viene data più importanza di un medico che non vuole lavorare in quel turno. Ma non posso decidere queste regole per te - questa è una decisione manageriale. È più difficile se due vincoli soft non hanno una chiara precedenza, nel qual caso dovrai inventare un qualche tipo di funzione di costo che unisca l'importanza di due vincoli in una singola metrica.


Probabilmente costruirò un algoritmo avido che riempie un calendario vuoto secondo alcuni criteri prioritari. Questa potrebbe non essere la soluzione più ottimale, ma è molto più facile che filosofare sul significato di "ottimale".

Come primo passo, potresti riempire i turni notturni nei fine settimana e cercare di selezionare quei dottori che non hanno fatto un turno notturno nel fine settimana da più tempo, tenendo anche conto dei desideri dell'utente "Non posso lavorare lì" . Supponendo che questi desideri siano settimanali e non continui, ciò significa che un medico che non può lavorare nelle notti del fine settimana per una settimana verrebbe scelto la settimana prossima.

Una procedura simile può essere utilizzata per le altre notti: dopo aver cercato di rispettare i desideri degli utenti, si inseriscono i medici in base a chi non ha svolto i turni notturni per il periodo di tempo più lungo. La procedura si ripete in modo simile per il terzo tipo di fascia oraria, il giorno cambia. Se non è possibile riconciliare i desideri di due utenti, è possibile tenere traccia della frequenza con cui è stato concesso un desiderio degli utenti e quindi dare priorità al medico con meno desideri concessi.

Sfortunatamente, riesco a vedere un paio di modi per giocare a questo sistema: ad es. Se un dottore venisse scelto per lavorare un turno di notte nel fine settimana ma inserisse una richiesta di "non lavorare lì", la sua scelta sarebbe ritardata di una settimana - riducendo il loro frequenza dei turni notturni del fine settimana a spese dei colleghi. Se viene implementata una procedura di risoluzione dei desideri che esamina il numero di richieste rifiutate, un utente potrebbe inserire un paio di richieste impossibili per aumentare una richiesta che desidera passare. Tuttavia, presupponendo una buona fede (e la flessibilità per i medici di scambiarsi turni tra loro), un tale algoritmo dovrebbe tradursi in una soluzione sufficientemente buona.


Grazie per la tua risposta, approfondirò un po 'di più con il mio collega :) Per darti maggiori informazioni: sì, possiamo classificare la maggior parte delle soluzioni / criteri e possiamo decidere se alcuni hanno la precedenza su altri. Inoltre, stanno davvero lavorando sulla buona fede ora e funziona bene. Stanno dong a mano e non usano troppo "non posso lavorare quel giorno". È abbastanza bello come riescano a farlo funzionare ora poiché lo fanno davvero a mano . Quindi una soluzione "praticabile" significherà già per loro il mondo e farà risparmiare loro MOLTO tempo di brainstorming su chi può lavorare quando
Gil Sand,

5
@Zil le persone che stanno attualmente creando i programmi probabilmente stanno già utilizzando un algoritmo informale. Potresti semplicemente parlare con loro e provare a capire il loro processo decisionale, quindi formalizzare e implementarlo. Ciò sarebbe molto più semplice della creazione e della formazione di una rete neurale.
amon,

Questo è il nostro primo passo: p abbiamo già organizzato un incontro con loro! Grazie per tutto il tuo aiuto :)
Gil Sand,

3
Per questo caso d'uso, gli algoritmi di genetica sono costantemente inferiori alla ricerca Tabu e alla ricottura simulata, come dimostrato dalle competizioni di ricerca International Nurse Rostering Competitions. (Ma ovviamente sono ancora meglio di un avido algo.)
Geoffrey De Smet

12

È possibile utilizzare la ricottura simulata .

Ho fatto qualcosa del genere prima di ottenere il mio primo lavoro - vedi https://vimeo.com/20610875 (demo che inizia alle 2:50, algoritmo spiegato dalle 6:15).

La ricottura simulata è un tipo di algoritmo genetico, e forse non era adatto in teoria (come sostiene @amon nella sua risposta ), ma ha funzionato molto bene nella pratica e riguardava lo stesso caso d'uso del tuo.

Il codice sorgente è disponibile (C #), ma mentre funziona, è terribile, temo, era qualche anno fa ed essendo un autodidatta, non sapevo nulla di manutenibilità. Ha prodotto risultati molto belli però.

Come funziona in poche parole:

  • Genera 1 possibile (potrebbe non essere molto buono, ma fisicamente possibile) come punto di partenza. A questo punto l'algoritmo genetico non è necessario: puoi solo raggiungere la prima soluzione che riesci a trovare. Ho usato il backtracking . La complessità computazionale può essere superata risolvendo la rotazione per ogni giorno separatamente. Se non esiste alcuna soluzione (a seconda del caso), è a questo punto che la si rileva.

  • Crea un pool di soluzioni - diciamo, per cominciare, 100 copie di questa soluzione entry-level.

  • Muta ogni soluzione a caso: chiedi ai medici di scambiare i turni tra di loro, togli un medico a caso dal loro turno e mettici sopra una persona disponibile, ecc.

  • Valuta ogni soluzione con una funzione di fitness che determina la sua efficacia. Un ragazzo lavora più notti di un altro? Sottrai punti penalità. Qualcuno voleva fare lunedì ma loro no? Sottrai nuovamente i punti penalità.

  • Prendi - diciamo - le 20 migliori soluzioni e copia ognuna di esse 5 volte, sovrascrivendone le restanti 80 e trasportandole alla generazione successiva. Sopravvivenza del più adatto.

  • Risciacqua e ripeti.

I numeri sono ovviamente arbitrari, potrebbe essere necessario armeggiare con i parametri per scoprire le impostazioni ottimali per il tuo scenario.

Per quanto riguarda la mutazione di una soluzione, la ricottura simulata introduce qualcosa chiamato temperatura. Fondamentalmente significa che all'inizio dovresti cambiare le tue soluzioni abbastanza duramente (diciamo, fai sempre 10 tentativi di scambiare i turni in una volta sola) e gradualmente diventare meno aggressivo con le iterazioni successive, quindi diventano più una messa a punto (diciamo, giù solo 2 tentativi di modifica per generazione).


4
Ho usato OptaPlanner (nee Drools Planner) con ricottura simulata per un orario del college. Dichiara i modelli: uno spostamento ha un tempo e un dottore. Scrivi regole dichiarative per la funzione fitness: vincoli forti (un medico non può fare turni sovrapposti) e penalità (Ann odia il lunedì). Scrivi scambi dichiarativi (questo è il punto!) Di turni. OptaPlanner creerà lo stato iniziale in modo casuale (potrebbe non essere fattibile), calcolerà la funzione di fitness dalle regole e persino gestirà gli swap secondo l'algoritmo di ottimizzazione. È possibile scegliere e ottimizzare i parametri come il programma di ricottura.
Jesvin Jose,

6

Gli algoritmi di genetica si applicano qui. Durante il mio corso di laurea, uno dei miei colleghi ha scritto un documento su un problema molto simile al tuo.

Puoi cercare Job Shop Scheduling e anche Open Shop Scheduling o Flow Shop Scheduling possono essere interessanti punti di partenza

Per utilizzare un algoritmo genetico non è necessaria una soluzione perfetta, è possibile iniziare con N candidati casuali e applicare una funzione di fitness a ciascuno di essi, ad esempio:

  • La differenza delle notti assegnate tra il medico più impegnato e il meno impegnato ha penalizzato la funzione di costo
  • Ogni volta che un medico lavora più di 5 giorni a settimana o 1 notte a settimana, si applica una sanzione
  • Ognuno dei tuoi vincoli, ecc ...

Generando N candidati, sceglieresti la X migliore di loro , sarebbero quelli a infliggere i vincoli di meno. Lavorando con loro, attraversando e mutando per diverse generazioni, si può arrivare a una buona soluzione.

Avendo parlato di tutto ciò, ogni volta che ho usato un algoritmo genetico che si basava più sulla mutazione che sull'attraversamento, potevo sviluppare una ricottura simulata che avrebbe funzionato molto meglio, con un'implementazione più semplice. Il costo / idoneità e la funzione di mutazione dell'algoritmo genetico saranno probabilmente molto simili a quelli utilizzati in una ricottura simulata. Vorrei iniziare da lì, guarda la risposta di @Konrad Morawski

La ricerca di Google trova buoni risultati per Job Shop e GA

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.