Soy tutor de prácticas de laboratorio en la universidad, según los comentarios de los estudiantes del año pasado, queríamos que mi jefe y yo nos dirigiéramos a ellos. Mi jefe decidió escribir un script en C y elegí python (restricción de python) para tratar de resolver nuestro problema.
Informaciones
- Hay 6 sesiones
- Hay 4 roles
- Hay 6 prácticas
- Hay 32 estudiantes
- Hay 4 estudiantes por equipo.
Problema:
Asigne a cada alumno a 4 roles, en 4 prácticas en 4 sesiones diferentes.
Restricciones:
- Los estudiantes deben hacer un papel una vez
- Los estudiantes deben hacer 4 prácticas diferentes de 6
- Los estudiantes deben hacer solo una práctica por sesión
- El estudiante debe encontrarse con el mismo compañero solo una vez
Plantillas:
Aquí está la plantilla que siento con los estudiantes, donde cada equipo está compuesto por 4 estudiantes, las posiciones [0, 1, 2 o 3] son roles asignados a ellos. Cada posición disponible está numerada del 1 al 128
[# Semester
[ # Session
[ # Practice/Team
1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24]],
[[25, 26, 27, 28],
[29, 30, 31, 32],
[33, 34, 35, 36],
[37, 38, 39, 40],
[41, 42, 43, 44],
[45, 46, 47, 48]],
[[49, 50, 51, 52],
[53, 54, 55, 56],
[57, 58, 59, 60],
[61, 62, 63, 64],
[65, 66, 67, 68],
[69, 70, 71, 72]],
[[73, 74, 75, 76],
[77, 78, 79, 80],
[81, 82, 83, 84],
[85, 86, 87, 88],
[89, 90, 91, 92],
[93, 94, 95, 96]],
[[97, 98, 99, 100],
[101, 102, 103, 104],
[105, 106, 107, 108],
[109, 110, 111, 112]],
[[113, 114, 115, 116],
[117, 118, 119, 120],
[121, 122, 123, 124],
[125, 126, 127, 128]]]
En otras palabras :
Esta es una sesión:
[[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24]],
Esos equipos hacen la misma práctica:
[
[1, 2, 3, 4],
[25, 26, 27, 28],
[49, 50, 51, 52],
[73, 74, 75, 76],
[97, 98, 99, 100],
[113, 114, 115, 116]
]
Esas posiciones hacen el mismo papel:
[
1,
5,
9,
13,
17,
21,
25,
...
]
Lo que tengo hasta ahora:
Usando python-restriction pude validar las tres primeras restricciones:
Valid solution : False
- sessions : [True, True, True, True, True, True]
- practices : [True, True, True, True, True, True]
- roles : [True, True, True, True]
- teams : [False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False]
Para aquellos que pueden ser interesantes, simplemente hago esto:
Para cada condición uso AllDifferentConstraint . Por ejemplo, para una sesión hago:
problem.addConstraint(AllDifferentConstraint(), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24])
No puedo encontrar una manera de restringir al equipo, mi último intento semester
fue:
def team_constraint(self, *semester):
students = defaultdict(list)
# get back each teams based on the format [# Semester [ #Session [# Practice/Team ...
teams = [list(semester[i:i+4]) for i in range(0, len(semester), 4)]
# Update Students dict with all mate they work with
for team in teams:
for student in team:
students[student] += [s for s in team if s != student]
# Compute for each student if they meet someone more than once
dupli = []
for student, mate in students.items():
dupli.append(len(mate) - len(set(mate)))
# Loosly constraint, if a student meet somone 0 or one time it's find
if max(dupli) >= 2:
print("Mate encounter more than one time", dupli, min(dupli) ,max(dupli))
return False
pprint(students)
return True
Preguntas:
- ¿Es posible hacer lo que quiero para las condiciones del equipo? Lo que quiero decir es que no tengo idea si es posible asignar 12 compañeros a cada estudiante y cada uno de ellos se encuentra con el mismo compañero solo una vez.
- Para la restricción del equipo, ¿me perdí un algoritmo más eficaz?
- ¿Algún pistón que pueda seguir?
fuente
(4, 4)
lugar de(4, 6)
como los otros?Respuestas:
La pregunta principal se respondería con algo como ...
Edición añadida
Ayer volví a ver tu problema (ciertamente no mucho, ya que tengo mucho trabajo por el momento) y ...
En primer lugar, veo que su entidad de "equipo" es más o menos lo que yo llamé una entidad de "acción", y en retrospectiva creo que "equipo" (o "grupo") era una mejor palabra para ello.
Si todavía encuentra difíciles las restricciones, le sugiero que las separe y trabaje en ellas individualmente, particularmente las restricciones de equipo / persona / sesión, seguidas de las restricciones de rol / tarea.
/ Agregado Editar
Tuve un problema similar recientemente, y al final recurrí a las herramientas OR. https://developers.google.com/optimization/cp/cp_solver
En particular, eche un vistazo al problema de programación de enfermeras: https://developers.google.com/optimization/scheduling/employee_scheduling#nurse_scheduling
De todos modos, el problema no es demasiado complejo, por lo que tal vez usar un solucionador sería excesivo para usted.
Del mismo modo, para este tipo de problema puede ser mejor usar un dict con clave de tupla para contener sus variables, en lugar de listas anidadas:
{Equipo, Sesión, Persona: BoolVar}
La razón principal es que luego puede aplicar restricciones a través de filtros, lo cual es mucho más fácil que tener que hacer manipulaciones de listas anidadas, por ejemplo, para aplicar una restricción entre personas / equipos, puede hacerlo (donde la persona es el índice 2 y el equipo es el índice 0):
fuente
p for p in all_people
?Solo una idea de algoritmo de permutación, para cada iteración podría centrarse en uno de cada alumno o en una de cada sesión:
Aquí el estudiante 2 toma lugar del estudiante 1 en la sesión 1 y continúa así
Continuar con el alumno 1 S3 R 1234 St 10,9,1,8
Al final, elimina las interacciones para el alumno 1, como en las permutaciones para la próxima iteración, elimina la actual.
Es como un cubo de rubik.
Si puede codificar esto o conocer algún código con este algo, hágamelo saber.
Tal vez con las permutaciones de itertools
Las sesiones son más que prácticas, creo que no es tan relevante su número. Solo un grupo para tomar más cuando te quedas sin espacio o más espacio para la rotación. ¿Quizás podría simplificar el problema primero apuntando a 4 sesiones = prácticas?
fuente