Mantén la atención ya que en este escrito hallarás la respuesta que buscas.Esta división fue aprobado por nuestros especialistas para asegurar la calidad y veracidad de nuestro contenido.
Solución:
Nota: Esta es una respuesta a una versión anterior de la pregunta.
Creo que la solución devuelta por el solucionador es correcta; cada persona es trabajando su MinHours
, simplemente no son consecutivos. Ejecuté tu código, luego dije
for person in persons:
print(": ".format(person, sum([staffed[(timeslot, person)].value() for timeslot in timeslots])))
y consiguió:
C1: 12.0
C2: 12.0
C3: 12.0
C4: 20.0
C5: 23.0
C6: 18.0
C7: 22.0
C8: 29.0
C9: 22.0
C10: 27.0
C11: 32.0
Entonces todos están trabajando al menos 12 turnos, es decir, 3 horas.
Si desea que los turnos sean consecutivos (es decir, una persona no puede trabajar en el espacio 1 y luego en el espacio 3), entonces la forma típica de manejar esto es usar una variable de decisión que diga a qué hora comienza cada empleado su turno, en lugar de una variable que especifica cada período de tiempo que están trabajando. Luego, introduce un parámetro como a[j][t]
lo que equivale 1
si un empleado que comienza un turno en la ranura j
está trabajando en la ranura t
. A partir de ahí, puede calcular quién está trabajando durante qué franjas horarias.
La razón por la que el problema es inviable cuando establece MinHours
a 5 es que obliga a demasiadas personas a estar trabajando durante ciertas horas. Por ejemplo, 6 personas tienen que completar sus turnos antes de la franja horaria 41. Eso significa que 6 x 4 x 5 = 120 franjas horarias deben trabajarse antes de la franja horaria 41. Pero solo se requieren 97 franjas horarias entre las franjas horarias 1 y 41.
Este problema se puede solucionar cambiando la restricción “Administrar el número correcto de personas” a >=
en vez de ==
, suponiendo que sea admisible para el sistema de dotación de personal. (Si no es así, entonces solo tiene una instancia inviable en sus manos).
(Por cierto, es posible que le interese el nuevo sitio propuesto de Stack Exchange sobre investigación y análisis de operaciones. Responderemos a preguntas como esta allí. :-))
Aquí hay una respuesta a su pregunta revisada, es decir, cómo agregar una restricción que requiera que cada empleado trabaje períodos de tiempo consecutivos.
Le sugiero que agregue la siguiente restricción (escrita aquí algebraicamente):
x[t+1,p] <= x[t,p] + (1 - (1/T) * sum_s=1^t-1 x[s,p]) for all p, for all t < T
donde x
es tuyo staffed
variable (escrita aquí como x
por compacidad), t
es el índice de tiempo, T
es el número de periodos de tiempo, y p
es el índice de empleados.
La lógica de la restricción es: Si x[t,p] = 0
(el empleado no está trabajando en el período t
) y x[s,p] = 1
por ningunas < t
(el empleado estuvo trabajando en cualquier período anterior), luego x[t+1,p]
deber = 0
(el empleado no puede estar trabajando en el período t+1
. Así, una vez que el empleado deja de trabajar, no puede volver a empezar. Tenga en cuenta que si x[t,p] = 1
ox[s,p] = 0
para cada s < t
entonces x[t+1,p]
puede igualar 1
.
Aquí está mi implementación de esta restricción en pulp
:
# If an employee works and then stops, they can't start again
num_slots = max(timeslots)
for timeslot in timeslots:
if timeslot < num_slots:
for person in persons:
prob += staffed[timeslot+1, person] <= staffed[timeslot, person] +
(1 - (1./num_slots) *
sum([staffed[(s, person)] for s in timeslots if s < timeslot]))
Ejecuté el modelo y obtuve:
Optimal
Staffed
Timeslot Staffmember
1 C2 1.0
2 C2 1.0
3 C2 1.0
4 C2 1.0
5 C2 1.0
6 C2 1.0
7 C2 1.0
8 C2 1.0
9 C2 1.0
C6 1.0
10 C2 1.0
C6 1.0
11 C2 1.0
C6 1.0
12 C2 1.0
C6 1.0
13 C3 1.0
C6 1.0
14 C3 1.0
C6 1.0
etc. Entonces, los empleados están trabajando en períodos de tiempo consecutivos.
Tenga en cuenta que las nuevas restricciones ralentizan un poco el modelo. Todavía se resuelve en <30 segundos más o menos. Pero si está resolviendo instancias mucho más grandes, es posible que deba volver a pensar en las restricciones.
Si estás de acuerdo, tienes la habilidad dejar una noticia acerca de qué te ha impresionado de este tutorial.