Me he estado preguntando si existen soluciones conocidas para el algoritmo de creación de un horario escolar. Básicamente, se trata de optimizar la "dispersión de horas" (tanto en el caso de los profesores como de las clases) para determinadas asociaciones de clase, asignatura y profesor. Podemos suponer que tenemos conjuntos de clases, asignaturas y profesores asociados entre sí en la entrada y que el horario debe ajustarse entre las 8 a. M. Y las 4 p. M.
Supongo que probablemente no exista un algoritmo preciso para eso, pero tal vez alguien conozca una buena aproximación o sugerencias para desarrollarla.
algorithm
language-agnostic
np
candó
fuente
fuente
Respuestas:
¡Este problema es NP-Complete !
En pocas palabras, es necesario explorar todas las combinaciones posibles para encontrar la lista de soluciones aceptables. Debido a las variaciones en las circunstancias en las que aparece el problema en las distintas escuelas (por ejemplo: ¿hay limitaciones en cuanto a las aulas ?, ¿algunas de las clases se dividen en subgrupos alguna vez ?, ¿es este un horario semanal? etc.) no existe una clase de problema bien conocida que corresponda a todos los problemas de programación. Quizás, el problema de la mochila tiene muchos elementos de similitud con estos problemas en general.
Una confirmación de que este es un problema difícil y para el que la gente busca constantemente una solución es consultar esta (larga) lista de herramientas de programación de software (en su mayoría comerciales)
Debido a la gran cantidad de variables involucradas, la mayor fuente de las cuales son, típicamente, los deseos del miembro de la facultad; -) ..., típicamente no es práctico considerar enumerar todas las combinaciones posibles . En su lugar, debemos elegir un enfoque que visite un subconjunto de los espacios de problema / solución.
- Los algoritmos genéticos , citados en otra respuesta, están (o, en mi humilde opinión, parecen ) bien equipados para realizar este tipo de búsqueda semi-guiada (el problema es encontrar una buena función de evaluación para que los candidatos se mantengan para la próxima generación)
- Gráfico Los enfoques de reescritura también son útiles con este tipo de problemas de optimización combinatoria.
En lugar de centrarme en implementaciones particulares de un programa generador automático de horarios, me gustaría sugerir algunas estrategias que se pueden aplicar, al nivel de la definición del problema .
El fundamento general es que en la mayoría de los problemas de programación del mundo real, se requerirán algunos compromisos, no todas las restricciones, expresas e implícitas: se cumplirán por completo. Por eso nos ayudamos a nosotros mismos:
Esto puede parecer contrario a la intuición, pero, por ejemplo, al proporcionar un horario inicial parcialmente llenado (digamos aproximadamente el 30% de los intervalos de tiempo), de una manera que satisfaga completamente todas las restricciones, y al considerar este horario parcial inmutable, reducimos significativamente el tiempo / espacio necesario para producir soluciones candidatas.
Otra forma en que las restricciones adicionales ayudan es, por ejemplo, agregando "artificialmente" una restricción que impida enseñar algunas materias en algunos días de la semana (si se trata de un horario semanal ...); este tipo de restricciones da como resultado la reducción de los espacios de problema / solución, sin, por lo general, excluir a un número significativo de buenos candidatos.
Al revisar esta respuesta, me doy cuenta de que es bastante tímido para proporcionar una respuesta definitiva, pero no obstante, está llena de sugerencias prácticas. Espero que esto ayude con lo que, después de todo, es un "problema difícil".
fuente
Es un desastre. un lío real. Para agregar a las respuestas, ya muy completas, quiero señalar mi experiencia familiar. Mi madre era maestra y solía participar en el proceso.
Resulta que tener una computadora para hacerlo no solo es difícil de codificar per-se, también es difícil porque hay condiciones que son difíciles de especificar para un programa de computadora prefabricado. Ejemplos:
Como puede ver, el problema no es NP-completo, es NP-loco.
Entonces, lo que hacen es que tienen una mesa grande con pequeñas inserciones de plástico y mueven las inserciones hasta obtener un resultado satisfactorio. Nunca parten de cero: normalmente parten del horario del año anterior y hacen ajustes.
fuente
El Concurso Internacional de Horarios 2007 tenía un itinerario de programación de lecciones y un itinerario de programación de exámenes. Muchos investigadores participaron en ese concurso. Se probaron muchas heurísticas y metaheurísticas, pero al final las metaheurísticas de búsqueda local (como Tabu Search y Simulated Annealing) superaron claramente a otros algoritmos (como los algoritmos genéticos).
Eche un vistazo a los 2 marcos de código abierto utilizados por algunos de los finalistas:
fuente
Una de mis asignaciones de medio término fue una generación de tablas escolares con algoritmos genéticos.
Toda la mesa es un "organismo". Hubo algunos cambios y advertencias en el enfoque de los algoritmos genéticos genéricos:
Se establecieron reglas para las "mesas ilegales": dos clases en el mismo aula, un maestro enseñando a dos grupos al mismo tiempo, etc. Estas mutaciones se consideraron letales de inmediato y un nuevo "organismo" brotó en lugar del "fallecido" inmediatamente. El inicial fue generado por una serie de intentos aleatorios para obtener uno legal (aunque sin sentido). La mutación letal no se contabilizó para el recuento de mutaciones en iteración.
Las mutaciones de "intercambio" eran mucho más comunes que las mutaciones de "modificación". Los cambios se produjeron solo entre partes del gen que tenían sentido, sin sustituir a un maestro por un aula.
Se asignaron pequeñas bonificaciones por agrupar ciertas 2 horas juntas, por asignar la misma clase genérica en secuencia para el mismo grupo, por mantener continuas las horas de trabajo del maestro y la carga de la clase. Se asignaron bonificaciones moderadas por dar las aulas correctas para un tema determinado, mantener las horas de clase dentro de los límites (mañana o tarde), etc. Las grandes bonificaciones fueron por asignar el número correcto de asignaturas determinadas, carga de trabajo dada para un maestro, etc.
Los profesores pueden crear sus horarios de carga de trabajo de "quiere trabajar entonces", "está bien trabajar entonces", "no le gusta trabajar entonces", "no puedo trabajar entonces", con los pesos adecuados asignados. Las 24 horas completas eran horas de trabajo legales, excepto que la noche era muy indeseable.
La función de peso ... oh sí. La función de peso era un producto enorme y monstruoso (como en la multiplicación) de pesos asignados a características y propiedades seleccionadas. Era extremadamente empinado, una propiedad podía cambiarlo fácilmente en un orden de magnitud hacia arriba o hacia abajo, y había cientos o miles de propiedades en un organismo. Esto resultó en números absolutamente ENORMES como pesos y, como resultado directo, es necesario usar una biblioteca bignum (gmp) para realizar los cálculos. Para un caso de prueba pequeño de unos 10 grupos, 10 maestros y 10 aulas, el conjunto inicial comenzó con una nota de 10 ^ -200 algo y terminó con 10 ^ + 300 algo. Era totalmente ineficaz cuando era más plano. Además, los valores crecieron mucho más con las "escuelas" más grandes.
En cuanto al tiempo de cálculo, hubo poca diferencia entre una población pequeña (100) durante mucho tiempo y una población grande (10k +) durante menos generaciones. El cálculo durante el mismo tiempo produjo aproximadamente la misma calidad.
El cálculo (en una CPU de 1 GHz) tardaría alrededor de 1 hora en estabilizarse cerca de 10 ^ + 300, generando programas que se veían bastante bien, para dicho caso de prueba de 10x10x10.
El problema es fácilmente paralelizable al proporcionar una instalación de red que intercambiaría las mejores muestras entre computadoras que ejecutan el cálculo.
El programa resultante nunca vio la luz del día afuera, lo que me dio una buena calificación para el semestre. Se mostró prometedor, pero nunca tuve la motivación suficiente para agregar una GUI y hacerla utilizable para el público en general.
fuente
Este problema es más difícil de lo que parece.
Como otros han aludido, este es un problema NP-completo, pero analicemos lo que eso significa.
Básicamente, significa que debes buscar todas las combinaciones posibles.
Pero "mirar" no te dice mucho de lo que necesitas hacer.
Generar todas las combinaciones posibles es fácil. Puede producir una gran cantidad de datos, pero no debería tener muchos problemas para comprender los conceptos de esta parte del problema.
El segundo problema es el de juzgar si una combinación posible dada es buena, mala o mejor que la solución "buena" anterior.
Para ello, necesita algo más que "¿es una posible solución"?
Por ejemplo, ¿el mismo profesor trabaja 5 días a la semana durante X semanas seguidas? Incluso si esa es una solución que funciona, puede que no sea mejor que alternar entre dos personas para que cada maestro haga una semana cada uno. Oh, ¿no pensaste en eso? Recuerde, estas son personas con las que está tratando, no solo un problema de asignación de recursos.
Incluso si un maestro pudiera trabajar a tiempo completo durante 16 semanas seguidas, esa podría ser una solución subóptima en comparación con una solución en la que intentas alternar entre maestros, y este tipo de equilibrio es muy difícil de integrar en el software.
En resumen, producir una buena solución a este problema valdrá mucho, para muchas personas. Por lo tanto, no es un problema fácil de analizar y resolver. Esté preparado para marcar algunos objetivos que no están al 100% y llamarlos "suficientemente buenos".
fuente
Mi algoritmo de programación de horarios, implementado en FET (Free Timetabling Software, http://lalescu.ro/liviu/fet/ , una aplicación exitosa):
El algoritmo es heurístico. Lo llamé "intercambio recursivo".
Entrada: un conjunto de actividades A_1 ... A_n y las limitaciones.
Salida: un conjunto de tiempos TA_1 ... TA_n (el intervalo de tiempo de cada actividad. Las habitaciones están excluidas aquí, por simplicidad). El algoritmo debe colocar cada actividad en un intervalo de tiempo, respetando las limitaciones. Cada TA_i está entre 0 (T_1) y max_time_slots-1 (T_m).
Limitaciones:
C1) Básico: una lista de pares de actividades que no pueden ser simultáneas (por ejemplo, A_1 y A_2, porque tienen el mismo profesor o los mismos alumnos);
C2) Muchas otras restricciones (excluidas aquí, por simplicidad).
El algoritmo de programación de horarios (que llamé "intercambio recursivo"):
Intente colocar cada actividad (A_i) en un intervalo de tiempo permitido, siguiendo el orden anterior, una a la vez. Busque un espacio disponible (T_j) para A_i, en el que esta actividad se pueda colocar respetando las restricciones. Si hay más espacios disponibles, elija uno al azar. Si no hay ninguno disponible, realice un intercambio recursivo:
a . Para cada intervalo de tiempo T_j, considere lo que sucede si coloca A_i en T_j. Habrá una lista de otras actividades que no están de acuerdo con este movimiento (por ejemplo, la actividad A_k está en el mismo espacio T_j y tiene el mismo maestro o los mismos estudiantes que A_i). Mantenga una lista de actividades en conflicto para cada intervalo de tiempo T_j.
b . Elija un espacio (T_j) con el menor número de actividades en conflicto. Digamos que la lista de actividades en este espacio contiene 3 actividades: A_p, A_q, A_r.
c . Coloque A_i en T_j y haga que A_p, A_q, A_r no estén asignados.
d . Intente recursivamente colocar A_p, A_q, A_r (si el nivel de recursividad no es demasiado grande, digamos 14, y si el número total de llamadas recursivas contadas desde el paso 2) en A_i comenzó no es demasiado grande, digamos 2 * n), como en el paso 2).
e . Si colocó con éxito A_p, A_q, A_r, regrese con éxito; de lo contrario, pruebe con otras franjas horarias (vaya al paso 2 b) y elija la siguiente mejor franja horaria).
f . Si todos (o un número razonable de) intervalos de tiempo se probaron sin éxito, regrese sin éxito.
g . Si estamos en el nivel 0, y no tuvimos éxito en colocar A_i, colóquelo como en los pasos 2 b) y 2 c), pero sin recursividad. Ahora tenemos 3 - 1 = 2 actividades más para colocar. Vaya al paso 2) (aquí se utilizan algunos métodos para evitar el ciclismo).
fuente
ACTUALIZACIÓN: de los comentarios ... ¡también debería tener heurística!
Yo iría con Prolog ... luego usaría Ruby o Perl o algo para limpiar su solución en una forma más bonita.
Estoy (todavía) en el proceso de hacer algo similar a este problema pero usando la misma ruta que acabo de mencionar. Prolog (como lenguaje funcional) realmente facilita la resolución de problemas NP-Hard.
fuente
Los algoritmos genéticos se utilizan a menudo para dicha programación.
Encontré este ejemplo (Cómo hacer un horario de clases usando un algoritmo genético) que coincide bastante bien con sus requisitos.
fuente
Aquí hay algunos enlaces que encontré:
Horario escolar : enumera algunos problemas relacionados
Un algoritmo genético híbrido para el horario escolar
Programación de utilidades y herramientas
fuente
Este artículo describe bastante bien el problema del horario escolar y su enfoque del algoritmo: " El desarrollo de SYLLABUS: un programador interactivo basado en restricciones para escuelas y universidades " . [PDF]
El autor me informa que el software SYLLABUS todavía se está utilizando / desarrollando aquí: http://www.scientia.com/uk/
fuente
Trabajo en un motor de programación ampliamente utilizado que hace exactamente esto. Sí, es NP-Complete; los mejores enfoques buscan aproximarse a una solución óptima. Y, por supuesto, hay muchas formas diferentes de decir cuál es la "mejor" solución: ¿es más importante que sus profesores estén contentos con sus horarios o que los estudiantes asistan a todas sus clases, por ejemplo?
La pregunta más importante que debe resolver desde el principio es ¿qué hace que una forma de programar este sistema sea mejor que otra ? Es decir, si tengo un horario con la Sra. Jones enseñando matemáticas a las 8 y el Sr. Smith enseñando matemáticas a las 9, ¿es mejor o peor que una con ambos enseñando matemáticas a las 10? ¿Es mejor o peor que uno con la Sra. Jones enseñando a los 8 años y el Sr. Jones enseñando a los 2? ¿Por qué?
El principal consejo que daría aquí es dividir el problema tanto como sea posible, tal vez curso por curso, tal vez maestro por maestro, tal vez sala por sala, y trabajar primero en resolver el subproblema. Allí debería terminar con múltiples soluciones para elegir, y debe elegir una como la más probable. Luego, trabaje en hacer que los subproblemas "anteriores" tengan en cuenta las necesidades de los subproblemas posteriores al calificar sus posibles soluciones. Entonces, tal vez trabaje en cómo salir de situaciones arrinconadas (asumiendo que no puede anticipar esas situaciones en subproblemas anteriores) cuando llegue a un estado de "no hay soluciones válidas".
Un pase de optimización de búsqueda local se usa a menudo para "pulir" la respuesta final para obtener mejores resultados.
Tenga en cuenta que, por lo general, estamos tratando con sistemas de programación escolar con grandes limitaciones de recursos. Las escuelas no pasan el año con muchas aulas vacías o profesores sentados en el salón el 75% del día. Los enfoques que funcionan mejor en entornos ricos en soluciones no son necesariamente aplicables en la programación escolar.
fuente
He diseñado algoritmos comerciales tanto para el horario de clases como para el horario de exámenes. Para el primero usé programación de enteros; para el segundo, una heurística basada en maximizar una función objetivo eligiendo intercambios de tragamonedas, muy similar al proceso manual original que se había desarrollado. Lo principal para lograr la aceptación de tales soluciones es la capacidad de representar todas las limitaciones del mundo real; y que los cronometradores humanos no puedan ver formas de mejorar la solución. Al final, la parte algorítmica fue bastante sencilla y fácil de implementar en comparación con la preparación de las bases de datos, la interfaz de usuario, la capacidad de informar estadísticas como la utilización de la sala, la educación del usuario, etc.
fuente
Generalmente, la programación de restricciones es un buen enfoque para este tipo de problema de programación. Una búsqueda sobre "programación de restricciones" y programación o "programación basada en restricciones" tanto dentro del desbordamiento de pila como en Google generará algunas buenas referencias. No es imposible, es un poco difícil pensar en ello cuando se utilizan métodos de optimización tradicionales como la optimización lineal o entera. Un resultado sería: ¿existe un programa que satisfaga todos los requisitos? Eso, en sí mismo, es obviamente útil.
Buena suerte !
fuente
Puedes abordarlo con algoritmos genéticos, sí. Pero no deberías :). Puede ser demasiado lento y el ajuste de parámetros puede llevar demasiado tiempo, etc.
Hay otros enfoques exitosos. Todo implementado en proyectos de código abierto:
Consulte aquí para obtener una lista de software de programación de horarios
fuente
Creo que deberías usar un algoritmo genético porque:
La calidad de la solución depende de cuánto tiempo pretenda dedicar a resolver el programa.
Definición de algoritmos genéticos
Tutorial de algoritmos genéticos
Proyecto de programación de clases con GA
También eche un vistazo a: una pregunta similar y otra
fuente
No sé que nadie estará de acuerdo con este código, pero desarrollé este código con la ayuda de mi propio algoritmo y funciona para mí en ruby.Espero que les ayude a quienes lo buscan en el siguiente código: periodflag, dayflag subjectflag y teacherflag son el hash con la identificación correspondiente y el valor de la bandera que es booleano. Cualquier problema contáctame ....... (-_-)
periodflag.each do | k2, v2 |
fuente