• No se han encontrado resultados

Solución al Problema de Programación de Tareas mediante Algoritmos Genéticos Cooperantes Edición Única

N/A
N/A
Protected

Academic year: 2020

Share "Solución al Problema de Programación de Tareas mediante Algoritmos Genéticos Cooperantes Edición Única"

Copied!
79
0
0

Texto completo

(1)Solución al Problema de Programación de Tareas mediante Algoritmos Genéticos Cooperantes. por. José Maximiliano Flores Flores. Tesis Presentada al Programa de Graduados en Electrónica, Computación, Información y Comunicación del Instituto Tecnológico y de Estudios Superiores de Monterrey, Campus Monterrey como requisito parcial para obtener el grado académico de. Maestro en Ciencias con especialidad en Sistemas Inteligentes. Instituto Tecnológico y de Estudios Superiores de Monterrey Campus Monterrey Monterrey, N.L. Mayo de 2002.

(2) c José Maximiliano Flores Flores, 2002 .

(3) Instituto Tecnológico y de Estudios Superiores de Monterrey Campus Monterrey División de Graduados en Electrónica, Computación, Información y Comunicación Programa de Graduados en Electrónica, Computación, Información y Comunicación. Los miembros del comité de tesis recomendamos que la presente tesis de José Maximiliano Flores Flores sea aceptada como requisito parcial para obtener el grado académico de Maestro en Ciencias, especialidad en: Sistemas Inteligentes. Comité de tesis:. Dr. Manuel Valenzuela Rendón Asesor de la tesis. Dr. Horacio Martı́nez Alfaro. Dr. Hugo Terashima Marı́n. Sinodal. Sinodal. Dr. David Garza Salazar Director del Programa de Graduados en Electrónica, Computación, Información y Comunicación. Mayo de 2002.

(4) A don Max y a su hija Teresita.

(5) Reconocimientos. Quiero expresar mi más sincero agradecimiento a las siguientes personas e instituciones por su enorme contribución a mi formación profesional y académica. Al ITESM Campus Monterrey, por otorgarme una beca para financiar mis estudios de maestrı́a. Al Dr. Francisco Cantú, por darme la oportunidad de trabajar en el Centro de Inteligencia Artificial. Al Dr. Manuel Valenzuela, por la gran cantidad de cosas que aprendı́ de él, y por la influencia definitiva en mi forma de realizar y reportar trabajos de investigación. Al Dr. Hugo Terashima, por su acertada conducción del programa de maestrı́a y por su contribución como sinodal en mi examen de grado. Al Dr. Horacio Martı́nez, por su contribución como sinodal en mi examen de grado.. José Maximiliano Flores Flores Instituto Tecnológico y de Estudios Superiores de Monterrey Mayo 2002. v.

(6) Solución al Problema de Programación de Tareas mediante Algoritmos Genéticos Cooperantes. José Maximiliano Flores Flores, M.C. Instituto Tecnológico y de Estudios Superiores de Monterrey, 2002. Asesor de la tesis: Dr. Manuel Valenzuela Rendón. Este trabajo de tesis aborda el problema de programación de tareas minimizando el criterio de justo a tiempo, mediante la combinación de algoritmo genético cooperante con una heurı́stica llamada dinámica de cuello de botella. La solución que se propone en este trabajo, es el uso de un algoritmo genético modificado, llamado algoritmo genético cooperante, en donde la representación de las tareas del problema se lleva a cabo mediante particiones del problema completo en varias poblaciones independientes. Cada una de estas poblaciones pertenecen a un algoritmo genético completo. Mediante un mecanismo de intercambio de información, cada uno de los algoritmos genéticos independientes utilizan la información generada por los individuos de las demás poblaciones para encontrar una mejor solución que la que se encontrarı́a con una sola población, con el mismo número de evaluaciones totales de la función objetivo. La aplicación del algoritmo genético cooperante que se propone, incluye un método para construir las particiones iniciales y un método de reinicialización para migrar tareas entre particiones, ası́ como una forma de representar algunas tareas en dos poblaciones distintas. La proposición del uso de un algoritmo genético cooperante se basa en la hipótesis de que en un conjunto de tareas a programar, existen tareas que están fuertemente relacionadas entre sı́, al igual que existen tareas que no tienen relación alguna en el resultado final de la programación. Con este enfoque, se pretende explotar la idea de independencia entre tareas para optimizar la representación de la solución y mejorar considerablemente el tiempo de respuesta de un algoritmo genético a los problemas de programación de tareas en una máquina. Los resultados de esta tesis son comparados con investigaciones anteriores donde se utilizaron algoritmos genéticos simples para resolver este mismo problema y objetivo de producción. El uso del algoritmo genéticos cooperante obtuvo de manera consistente mejores resultados que los algoritmos contra los que se comparó..

(7) Índice General. Reconocimientos. v. Resumen. vi. Índice de Tablas. ix. Índice de Figuras. x. Capı́tulo 1 Introducción. 1. Capı́tulo 2 El modelo de programación de tareas 2.1 Introducción . . . . . . . . . . . . . . . . . . . . . 2.2 La importancia de la programación de tareas . . 2.3 Enfoques usados en programación de tareas . . . 2.4 Programación de tareas en una máquina . . . . . 2.5 Clasificación de problemas en una máquina . . . 2.6 Objetivos de la producción . . . . . . . . . . . .. . . . . . .. 3 3 4 5 6 7 8. . . . . . .. 10 10 10 12 15 17 19. Capı́tulo 4 El algoritmo genético cooperante 4.1 Descripción y funcionamiento . . . . . . . . . . . . . . . . . . . . . . . . . . .. 21 21. Capı́tulo 5 Representación del problema 5.1 Representación del problema . . . . . 5.2 Creación de las particiones . . . . . . . 5.3 Codificación en el cromosoma . . . . . 5.4 Evaluación de los individuos . . . . . . 5.5 Ejemplo del uso del AGC . . . . . . .. 25 25 26 28 28 30. Capı́tulo 3 Dinámica de cuello de botella 3.1 Introducción . . . . . . . . . . . . . . . . . . . 3.2 Definición . . . . . . . . . . . . . . . . . . . . 3.3 DCB para diversos objetivos de producción . 3.4 DCB para justo a tiempo . . . . . . . . . . . 3.5 Modificaciones a DCB para justo a tiempo . . 3.6 Algoritmo para la evaluación rápida de DCB. vii. . . . . . .. . . . . . .. . . . . . .. . . . . . .. utilizando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . .. . . . . . .. . . . . . .. . . . . . .. un . . . . . . . . . .. . . . . . .. . . . . . .. . . . . . .. . . . . . .. . . . . . .. . . . . . .. . . . . . .. . . . . . .. AGC . . . . . . . . . . . . . . . . . . . .. . . . . . .. . . . . . .. . . . . .. . . . . . .. . . . . . .. . . . . .. . . . . . .. . . . . . .. . . . . .. . . . . . .. . . . . . .. . . . . .. . . . . . .. . . . . . .. . . . . .. . . . . . .. . . . . . .. . . . . .. . . . . . .. . . . . . .. . . . . .. . . . . . .. . . . . . .. . . . . .. . . . . ..

(8) 5.6 5.7. Particiones traslapadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Reinicialización . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. Capı́tulo 6 Experimentos y análisis de resultados 6.1 Generación de problemas de prueba . . . . . . . 6.2 Notación usada en los experimentos . . . . . . . 6.3 Los efectos de las particiones simples . . . . . . . 6.3.1 Diseño de los experimentos . . . . . . . . 6.3.2 Resultados . . . . . . . . . . . . . . . . . 6.3.3 Análisis de resultados . . . . . . . . . . . 6.4 Los efectos del traslape . . . . . . . . . . . . . . 6.4.1 Diseño de los experimentos . . . . . . . . 6.4.2 Resultados . . . . . . . . . . . . . . . . . 6.4.3 Análisis de resultados . . . . . . . . . . . 6.5 Los efectos de la reinicialización . . . . . . . . . . 6.5.1 Diseño de los experimentos . . . . . . . . 6.5.2 Resultados . . . . . . . . . . . . . . . . . 6.5.3 Análisis de resultados . . . . . . . . . . .. . . . . . . . . . . . . . .. . . . . . . . . . . . . . .. Capı́tulo 7 Conclusiones 7.1 Contribuciones y conclusiones . . . . . . . . . . . . . 7.1.1 Representación de la separabilidad implı́cita . 7.1.2 Uso de representación traslapada . . . . . . . 7.1.3 Desempeño del algoritmo genético cooperante 7.2 Trabajos futuros . . . . . . . . . . . . . . . . . . . . Vita. . . . . . . . . . . . . . .. . . . . .. . . . . . . . . . . . . . .. . . . . .. . . . . . . . . . . . . . .. . . . . .. . . . . . . . . . . . . . .. . . . . .. . . . . . . . . . . . . . .. . . . . .. . . . . . . . . . . . . . .. . . . . .. . . . . . . . . . . . . . .. . . . . .. . . . . . . . . . . . . . .. . . . . .. . . . . . . . . . . . . . .. . . . . .. . . . . . . . . . . . . . .. . . . . .. . . . . . . . . . . . . . .. . . . . .. . . . . . . . . . . . . . .. . . . . .. . . . . . . . . . . . . . .. . . . . .. 31 33. . . . . . . . . . . . . . .. 35 35 36 37 38 38 45 45 46 47 54 54 55 56 63. . . . . .. 65 65 65 66 66 67 68. viii.

(9) Índice de Tablas. 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 6.10 6.11 6.12 6.13 6.14 6.15 6.16 6.17 6.18 6.19 6.20 6.21 6.22 6.23 6.24 6.25 6.26 6.27. Grupos de problemas de prueba utilizados en los experimentos. . . . . . . Parámetros de funcionamiento del AG gk ∈ Gp . . . . . . . . . . . . . . . . Experimento I(20, E) : [G(1, 0, 0) − G(2, 0, 0); G(3, 0, 0); G(4, 0, 0)]. . . . . Experimento I(20, H) : [G(1, 0, 0) − G(2, 0, 0); G(3, 0, 0); G(4, 0, 0)]. . . . . Experimento I(50, E) : [G(1, 0, 0) − G(2, 0, 0); G(3, 0, 0); G(4, 0, 0)]. . . . . Experimento I(50, H) : [G(1, 0, 0) − G(2, 0, 0); G(3, 0, 0); G(4, 0, 0)]. . . . . Experimento I(100, E) : [G(1, 0, 0) − G(2, 0, 0); G(3, 0, 0); G(4, 0, 0)]. . . . . Experimento I(100, H) : [G(1, 0, 0) − G(2, 0, 0); G(3, 0, 0); G(4, 0, 0)]. . . . Resultados condensados de los efectos del uso de particiones. . . . . . . . Experimentos para encontrar el efecto del factor de traslape. . . . . . . . Parámetros de funcionamiento del AG gk ∈ Gp . . . . . . . . . . . . . . . . Experimento I(20, E) : [G(3, 0, 0) − G(3, 1, 0), G(3, 2, 0), G(3, 4, 0)]. . . . . Experimento I(20, H) : [G(2, 0, 0) − G(2, 1, 0), G(2, 2, 0), G(2, 4, 0). . . . . Experimento I(50, E) : [G(3, 0, 0) − G(3, 2, 0), G(3, 4, 0), G(3, 6, 0). . . . . . Experimento I(50, H) : [G(2, 0, 0) − G(2, 2, 0), G(2, 4, 0), G(2, 6, 0). . . . . Experimento I(100, E) : [G(3, 0, 0) − G(3, 2, 0), G(3, 4, 0), G(3, 8, 0). . . . . Experimento I(100, H) : [G(4, 0, 0) − G(4, 2, 0), G(4, 4, 0), G(4, 8, 0). . . . . Resultados condensados de los efectos del uso de particiones con traslape. Experimentos para encontrar el efecto del factor de reinicialización. . . . . Parámetros de funcionamiento del AG gk ∈ Gp . . . . . . . . . . . . . . . . Experimento I(20, E) : [G(3, 0, 0) − G(3, 0, 1), G(3, 0, 2), G(3, 0, 3). . . . . . Experimento I(20, H) : [G(2, 0, 0) − G(2, 0, 1), G(2, 0, 2), G(2, 0, 3). . . . . Experimento I(50, E) : [G(3, 0, 0) − G(3, 0, 1), G(3, 0, 2), G(3, 0, 3). . . . . . Experimento I(50, H) : [G(2, 0, 0) − G(2, 0, 1), G(2, 0, 2), G(2, 0, 3). . . . . Experimento I(100, E) : [G(3, 2, 0) − G(3, 2, 1), G(3, 2, 2), G(3, 2, 3). . . . . Experimento I(100, H) : [G(4, 0, 0) − G(4, 0, 1), G(4, 0, 2), G(4, 0, 3). . . . . Resultados condensados de los efectos de la reinicialización. . . . . . . . .. ix. . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . .. 37 38 38 40 41 42 43 44 45 46 47 47 49 50 51 52 53 54 55 56 56 58 59 60 61 62 63.

(10) Índice de Figuras. 3.1 3.2 3.3 3.4 3.5. Dinámica de cuello de botella para retraso ponderado. . . . . DCB para tardanza pondera sin corrección de urgencia . . . . DCB para tardanza ponderada con corrección de la urgencia. DCB para tardanza ponderada con corrección suavizada de U DCB para el criterio de justo a tiempo . . . . . . . . . . . . .. . . . . .. 12 13 14 15 16. 4.1 4.2. Un AGC de tres poblaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . Esquema de la evaluación de una de las tres poblaciones . . . . . . . . . . . .. 22 23. 5.1 5.2 5.3 5.4. Creación de una sublista de tareas . . . . . . . . . . . . . . . . . . . . . . . . Representación de las tareas de la partición sk en el cromosoma binario. . . . Un AGC de p poblaciones para resolver un problema de programación de tareas Ejemplo de particiones con factor de traslape h = 2. . . . . . . . . . . . . . .. 27 29 30 32. 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 6.10 6.11 6.12 6.13 6.14 6.15 6.16 6.17 6.18. Resultados Resultados Resultados Resultados Resultados Resultados Resultados Resultados Resultados Resultados Resultados Resultados Resultados Resultados Resultados Resultados Resultados Resultados. 39 40 41 42 43 44 48 49 50 51 52 53 57 58 59 60 61 62. de de de de de de de de de de de de de de de de de de. 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10. ejecuciones ejecuciones ejecuciones ejecuciones ejecuciones ejecuciones ejecuciones ejecuciones ejecuciones ejecuciones ejecuciones ejecuciones ejecuciones ejecuciones ejecuciones ejecuciones ejecuciones ejecuciones. de de de de de de de de de de de de de de de de de de. G(3, G(2, G(3, G(2, G(3, G(4, G(3, G(2, G(3, G(2, G(3, G(4, G(3, G(2, G(3, G(2, G(3, G(4,. 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 0,. x. 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 0) 1) 2) 1) 2) 1) 1). para para para para para para para para para para para para para para para para para para. una una una una una una una una una una una una una una una una una una. instancia instancia instancia instancia instancia instancia instancia instancia instancia instancia instancia instancia instancia instancia instancia instancia instancia instancia. . . . . .. de de de de de de de de de de de de de de de de de de. . . . . .. . . . . .. . . . . .. . . . . .. . . . . .. . . . . .. . . . . .. I(20, E). . I(20, H). . I(50, E). . I(50, H). . I(100, E). I(100, H). I(20, E). . I(20, H). . I(50, E). . I(50, H). . I(100, E). I(100, H). I(20, E). . I(20, H). . I(50, E). . I(50, H). . I(100, E). I(100, H).. . . . . . . . . . . . . . . . . . ..

(11) Capı́tulo 1. Introducción. Este trabajo de tesis aborda la solución al problema de programación de tareas minimizando el criterio de justo a tiempo, mediante la combinación de un algoritmo genético cooperante con una heurı́stica de programación de tareas llamada dinámica de cuello de botella. El problema de programación de tareas trata sobre la asignación de recursos limitados a ciertas tareas u operaciones a través de cierto perı́odo de tiempo (Pinedo, 1995). Los recursos y tareas pueden tomar diferentes formas, de acuerdo al dominio del problema que se aborde; por ejemplo, en un problema de programación de vuelos, los recursos pueden ser las pistas de aterrizaje, las tareas pueden ser despegues y aterrizajes de aviones. Para el caso de una empresa de la construcción y de un sistema de procesamiento de información, los recursos serı́an las flotillas con que se cuentan y las unidades de procesamiento; las tareas serı́an las etapas del proceso de construcción y las ejecuciones de proceso de datos, respectivamente. El problema de programación de tareas existe en casi todos los ambientes de producción o de procesamiento de información y juega un papel importante en el desempeño general de la empresa o sistema de producción. La programación de tareas y el control del flujo de trabajos a través de un ambiente de producción es esencial en los procesos de manufactura (Gideon, 1995). Una adecuada programación puede reducir significativamente los costos de producción y reducir los tiempos de proceso permitiendo cumplir con los compromisos de entrega a tiempo. Los algoritmos genéticos (AGs) son algoritmos de búsqueda basados en la teorı́a de la selección natural y la genética poblacional; parten de la idea de abstraer el proceso adaptativo de los sistemas naturales y diseñar sistemas que simulen este proceso (Goldberg, 1989). Un algoritmo genético comienza con una población inicial de individuos representados por cadenas de caracteres comúnmente en el alfabeto binario; la población inicial es normalmente generada de manera aleatoria. El AG combina información entre los individuos de la población usando operadores análogos a la selección del más apto y la reproducción. También se incluye un operador de mutación que asemeja al proceso de mutación en los individuos naturales. Los algoritmos genéticos cooperantes (de la Cueva, 1998), son una clase de algoritmo genético modificado, en donde la representación del problema se lleva a cabo mediante particiones, en donde cada partición corresponde a una sección del problema completo. Dichas particiones son resueltas de manera independiente por un algoritmo genético. Mediante un mecanismo de intercambio de información, cada uno de los algoritmos genéticos independientes utilizan. 1.

(12) la información generada por los demás AGs para encontrar una mejor solución que la que se encontrarı́a con un solo algoritmo genético, con el mismo número de evaluaciones totales de la función objetivo. En los últimos años se han realizado numerosos trabajos de investigación abordando el problema de programación de tareas en ambientes tanto determinı́sticos como probabilı́sticos. Una significativa cantidad de trabajos se han enfocado en tratar de encontrar heurı́sticas y algoritmos de tiempo polinomial que resuelvan problemas de programación de tareas. Se han propuesto un gran número de enfoques para modelar y solucionar los diferentes problemas de programación de tareas, con diferentes grados de éxito. Entre estos enfoques podemos mencionar la programación matemática, reglas de despacho, sistemas expertos, redes neuronales, algoritmos genéticos, búsqueda tabú, recocido simulado, lógica difusa, entre otros (Jones, 1998). Existen trabajos directamente relacionados con el desarrollo de esta investigación, tales como la solución al problema de programación de tareas mediante la combinación de dinámica de cuello de botella y algoritmos genéticos simples (Martı́nez, 1999), ası́ como el uso de un algoritmo genético cooperante para el cálculo de trayectorias de dos robóts en un mismo ambiente (de la Cueva, 1998). De manera particular, esta investigación intenta mostrar las ventajas que ofrece un algoritmo genético cooperante para resolver un problema cuya representación no es claramente separable, tal como el problema que se pretende resolver. Para llevar a cabo lo anterior, se compara el desempeño del algoritmo genético simple mencionado, con un algoritmo genético cooperante con las mismas caracterı́sticas. La tesis presentada está organizada de la siguiente forma. En el capı́tulo 2 se presenta un panorama general del problema de programación de tareas, la definición formal del problema que se pretende resolver, ası́ como distintos objetivos de producción. En el capı́tulo 3 se describe la heurı́stica Dinámica de cuello de botella. Se presentan las variantes de la heurı́stica para distintos objetivos de producción. El algoritmo genético cooperante es descrito en el capı́tulo 4. Se muestra una definición intuitiva seguida por una definición formal. En el capı́tulo 5 se formaliza la representación del problema de programación de tareas en un algoritmo genético cooperante. Se definen además dos variantes del algoritmo que son exploradas con el fin de encontrar alguna mejora en su desempeño. El capı́tulo 6 describe la generación de los problemas de prueba utilizados para el desarrollo de la investigación. Se presentan los diseños de los experimentos y se presentan los resultados obtenidos en cada uno de ellos. Finalmente, en el capı́tulo 7 se muestran las conclusiones obtenidas a través del análisis de los experimentos realizados; adicionalmente, se mencionan posibles contribuciones futuras que pudieran expander y mejorar los resultados obtenidos en esta investigación.. 2.

(13) Capı́tulo 2. El modelo de programación de tareas. En este capı́tulo se aborda el tema de programación de tareas, el cual es el área de aplicación sobre la cual se concentran los experimentos realizados en esta tesis. El capı́tulo comienza con una introducción y definiciones de programación de tareas, posteriormente se discute su importancia dentro de los ambientes de producción, manufactura, servicios y otras industrias. Más adelante se mencionan las distintas formas en que se ha tratado de resolver este problema desde el punto de vista de diversas áreas del conocimiento, tales como la investigación de operaciones, la inteligencia artificial, entre otras. En este capı́tulo se define formalmente el problema de programación de tareas en una máquina, su clasificación y los distintos objetivos de producción para este tipo de problemas.. 2.1. Introducción. La programación de tareas o scheduling consiste principalmente en un problema de toma de decisiones cuyo objetivo es optimizar uno o más criterios de un plan de ejecución de ciertas actividades o tareas a través del tiempo. Estas actividades utilizan recursos limitados para ejecutarse, por lo que el problema de programación de tareas es un paso importante antes de iniciar un cierto proceso o plan. En ambientes de manufactura y de empresas de servicio, la programación de tareas juega un papel crucial, de manera que es una necesidad para mantenerse en el mercado competitivo actual. La idea japonesa de justo a tiempo (Morton y Pentico, 1993) para mantener la satisfacción del cliente y reducir los costos de inventario ha cambiado la forma de pensar de las industrias. La importancia de la programación de tareas se ha elevado, hoy en dı́a el estudio de este problema no es solamente académico, sino que existe una gran cantidad de aplicaciones comerciales. Las aplicaciones de programación de tareas a problemas reales son diversas y podemos mencionar como ejemplo sistemas de tránsito urbano, redes de distribución, calendarización de exámenes, despacho de procesos de cómputo, programación de uso de equipos de laboratorio, asignación de personal, mantenimiento, calendarización de proyectos, y una amplia diversidad de problemas en ambientes de manufactura. Tomar buenas decisiones puede tener resultados económicamente muy importantes dentro de la industria, ya que una eficiente programación de la producción se verá reflejada en una disminución de los costos de producción, en un aumento de la capacidad de producción y una mejor calidad de los productos; sin embargo, es un problema muy difı́cil de resolver. Su complejidad radica en que su espacio. 3.

(14) de soluciones está dado por la cardinalidad recursos×tareas×tiempo, por lo que para problemas de tamaño razonable el costo computacional requerido para solucionarlos es muy alto y en algunas ocasiones intratable (Matfeld, 1996). Esto sin tomar en cuenta el número de restricciones tales como el tiempo lı́mite para elaborar algún producto, restricciones técnicas de algunos procesos, escasez de recursos y otros más que dificultan la programación. Por esta razón, la programación de tareas ha sido objeto de numerosos estudios e investigaciones para definir métodos heurı́sticos y probabilı́sticos que permitan encontrar buenas soluciones de acuerdo a uno o varios objetivos económicos dentro de la producción. Algunos ejemplos de estos métodos son búsqueda tabú (Glover, 1990), recocido simulado (Laarhoven y Markov, 1992), redes neuronales (Shaw y Park, 1992), dinámica de cuello de botella (Morton y Pentico, 1993) y algoritmos genéticos (Goldberg, 1989). Todo problema de asignación de recursos a ciertas actividades en un periodo de tiempo es un problema de programación de tareas. Estas asignaciones de recursos pueden estar limitadas por restricciones de máquinas, por el orden de las tareas o por diversas restricciones propias del problema especı́fico. De esta breve descripción, notamos que un problema de programación de tareas puede tener varios niveles de complejidad dependiendo del ambiente y las restricciones que se tengan. Una definición del problema de programación de tareas es la siguiente (Pinedo, 1995): Es un proceso de toma de decisiones que trata sobre la asignación de recursos limitados a tareas a través del tiempo, cuya meta es la optimización de uno o más objetivos. Una definición adicional de programación de tareas es proporcionada por (Morton y Pentico, 1993): Es el proceso de organizar, escoger, y fijar los tiempos de uso de los recursos para llevar a cabo todas las actividades necesarias con el fin de producir las salidas deseadas en los tiempos deseados, cumpliendo con un gran número de restricciones de tiempo y de relación entre las actividades y los recursos. Es posible notar que ambas definiciones establecen una relación entre los recursos o máquinas y las tareas o actividades. La programación de tareas busca establecer dichas relaciones a través del tiempo entre estos dos elementos, de modo que se satisfaga un criterio de desempeño especı́fico de la aplicación.. 2.2. La importancia de la programación de tareas. El área de programación de tareas comenzó a ser tomada seriamente a principios del siglo veinte con los trabajos de Henry Gantt y de otros pioneros. No obstante, pasaron algunos años para que aparecieran las primeras publicaciones relacionadas al problema de scheduling en la literatura de investigación de operaciones. A principios de los años 50s aparecieron algunas publicaciones del área. En la década de los 60s se realizó una cantidad 4.

(15) significativa de trabajos utilizando programación dinámica y programación entera. En los 70s, la investigación se centró sobre las jerarquı́as de complejidad y en los 80s se generaron diversos trabajos académicos e industriales. La función de la programación de tareas dentro de una organización tiene que interactuar con diversas áreas, estas intertfaces son independientes de la organización o de la planta en sı́, y pueden diferir de una situación a otra. El proceso de programación de tareas es afectado por el proceso de planeación de la producción, el cual maneja la planeación a mediano y largo plazo para la organización entera. Este proceso debe considerar niveles de inventario, pronósticos y requerimientos de recursos para optimizar a un alto nivel la producción y asignación de recursos. La programación de tareas también recibe entradas del control de planta, debido a que pueden existir eventos inesperados en ella, tales como fallas de máquinas o tiempos de proceso que son mayores que los anticipados. Dichos eventos tienen que ser cuidadosamente tomados en cuenta por el posible impacto que causen a la programación completa. A medida que los problemas de programación de tareas empezaron a ser resueltos por medio de computadoras, las aplicaciones de software han empezado a tomar mayor importancia en esta área, con un enfoque principal en la aplicación práctica. El diseño y desarrollo han sido y están siendo realizados por cientı́ficos en el área de las ciencias computacionales, la investigación de operaciones y la ingenierı́a industrial.. 2.3. Enfoques usados en programación de tareas. En las décadas de los 50s y 60s el uso de las computadoras permitió representar la estructura de configuraciones de recursos, actividades y otras restricciones con cierto detalle, de tal forma que introduciendo datos apropiados y con heurı́sticas simples de despacho, podı́a observarse el comportamiento simulado del ambiente. En los 60s, se explotó el poder de las computadoras para desarrollar métodos de programación entera, los cuales permiten resolver en forma teóricamente exacta problemas reales de programación de tareas en job shops (Adams et al., 1988); el método de branch and bound crea un árbol de decisión a partir de las tareas iniciales y encuentra un lı́mite inferior para tomar decisiones de qué ramas del árbol ya no deben explorarse, reduciendo ası́ el tiempo de ejecución. En los 60s y 70s, algunos investigadores usaron la programación dinámica para problemas de secuenciamiento, usando todos los posibles subconjuntos de tareas como elementos del espacio de estado. Sin embargo, estos métodos no son aplicables para problemas grandes debido a que los problemas son no polinomiales, lo cual significa que el tiempo de ejecución de los algoritmos crece exponencialmente con el tamaño del problema. Por ejemplo, no es posible que una computadora encuentre todas las permutaciones de 50 tareas para una máquina (50! ≈ 3.04 × 10 64 ), y aunque existiera una máquina tan poderosa, si el problema se incrementara a 55 tareas, se requerirı́a una computadora 300,000,000 de veces más rápida. El método de relajación de Lagrange resuelve un problema de programación entera con restricciones, eliminando algunas restricciones e introduciendo una función de penalización proporcional a la magnitud en que las soluciones violen las restricciones eliminadas y a la importancia de las mismas. Es un método poderoso pero es complejo y aún no puede consi-. 5.

(16) derarse de propósito general. Dentro de los enfoques más nuevos para programación de tareas, podemos mencionar los métodos de intensificación/diversificación, beam search, métodos de cuello de botella, redes neuronales, sistemas expertos, ası́ como también sistemas hı́bridos de inteligencia artificial, investigación de operaciones y sistemas de soporte de decisión. En cuanto a los métodos de intensificación/diversificación, podemos mencionar la búsqueda tabú, recocido simulado y los algoritmos genéticos. Se les conoce ası́ debido a que realizan un balance ente las dos estrategias de búsqueda básicas: intensificar o explorar el espacio de búsqueda en una dirección determinada o diversificar o explotar nuevos espacios de búsqueda en otras direcciones. El método beam search es un método de enumeración parcial de árboles de decisión. Es similar a branch and bound, pero en lugar de cortar las ramas hasta garantizar que no son viables, lo hace con una medida de probabilidad. Un factor determinante de éxito es contar con una buena ponderación para esta medida de aplicabilidad del corte de ramas. En los 80s se realizaron diversas aplicaciones con sistemas expertos, como el caso de ISIS (Fox y Smith, 1984), OPAL (Bensana et al., 1988), CALLISTO, PATRIARCH, y MERLE. Algunos de ellos utilizan beam search, dinámicas de cuello de botella y diversas técnicas de Inteligencia Artificial. En la década de los 90s surgieron diversos trabajos experimentales que utilizan redes neuronales artificiales, sin embargo, aunque los resultados son prometedores, aún se considera un área de investigación.. 2.4. Programación de tareas en una máquina. La programación de tareas en una máquina consiste en un número finito de tareas n esperando ser procesados por un recurso único m (Pinedo, 1995). Cada tarea j hace fila para esperar por el recurso. El recurso puede procesar sólo una tarea a la vez. Cada tarea j está definida en términos de los siguientes conceptos (Morton y Pentico, 1993): • Tiempo de procesamiento (pj ). Es el tiempo que tarda el recurso m en procesar la tarea j. • Fecha de llegada (aj ). Es el tiempo en que la tarea j arriba al sistema, por lo que se encuentra lista para ser procesada. • Fecha de entrega (dj ). Es la fecha lı́mite en la cual la tarea j debe ser terminada, es decir, es la fecha de entrega convenida con el cliente. • Costo por entrega tardı́a (wTj ). Es el costo por unidad de tiempo que se genera por terminar la tarea j después de su fecha de entrega dj . Este costo tı́picamente representa una penalización por parte del cliente hacia la empresa por incumplimiento de un pedido, servicio, etcétera. • Costo por entrega anticipada (wEj ). Es el costo por unidad de tiempo que se genera por terminar la tarea j antes de su fecha de entrega dj . Esta clase de costo representa los gastos que la empresa tiene por concepto de almacenaje de las piezas. Usualmente 6.

(17) wEj es menor que wTj , aunque esto no es una regla que aplica en todos los esquemas de producción. • Tiempo de terminación (Cj ). Es el tiempo en que la tarea j completa su procesamiento desde el inicio de operaciones del sistema. • Demora (Lj ). Es el margen de tiempo positivo o negativo en que la tarea j excede su fecha lı́mite. Lj = Cj − dj .. (2.1). • Tardanza (Tj ). Es el margen de tiempo en que una tarea j termina su procesamiento después de la fecha lı́mite dj . Si termina antes, entonces la tardanza es cero. Tj = max{0, Lj }. j. (2.2). • Tempranez (Ej ). Es el margen de tiempo en que una tarea j termina su procesamiento antes de la fecha lı́mite dj . Si termina después, entonces la tempranez es igual a cero. Ej = max{0, −Lj }. j. 2.5. (2.3). Clasificación de problemas en una máquina. La programación de tareas en una máquina puede ser clasificada de diferentes maneras tomando en cuenta las restricciones que se pueden tener en el ambiente (estático o dinámico), en los procesos (con interrupciones o sin interrupciones) y en los objetivos de la producción (regulares o irregulares) que se intenten minimizar. De manera más especı́fica, los problemas de programación de tareas en una máquina se clasifican a continuación (Pinedo, 1995): • Ambiente estático. Todas las tareas se encuentran disponibles al inicio de la operación del sistema; es decir, el tiempo de arribo de cada tarea es cero. • Ambiente dinámico. Las tareas pueden estar llegando en el transcurso de la operación del sistema. • Procesos sin interrupción. En este criterio, una tarea no puede ser suspendida hasta finalizar su procesamiento. • Procesos con interrupción permitida. Se puede suspender sin costo alguno el proceso de una tarea para dar paso a una más importante. La tarea suspendida puede continuar su procesamiento más adelante. • Objetivos regulares. En un objetivo regular, siempre es preferible terminar una tarea antes de su fecha lı́mite dj , que incurrir en costos por terminarla después de esta fecha.. 7.

(18) • Objetivos irregulares. Los objetivos irregulares no solamente toman en cuenta el tiempo en que una tarea se propasa de su fecha lı́mite, sino que también penaliza otros factores, como el tiempo de anticipación con que se entrega.. 2.6. Objetivos de la producción. Un ambiente de producción basado en programación de tareas puede tener uno o más objetivos por cumplir. Dichos objetivos usualmente son clasificados como regulares o irregulares; ya sea para maximizar la utilización del recurso, minimizar el tiempo de flujo de una tarea en el sistema, o bien minimizar alguna medida de la tardanza de una tarea. A continuación se presentan algunos de los objetivos tı́picos utilizados en la producción (Pinedo, 1995): • Makespan. Este objetivo intenta minimizar el tiempo de finalización de las tareas. La idea intuitiva del makespan es que si se terminan de procesar antes de tiempo, permite a nuevas tareas empezar su procesamiento por adelantado. Cmax = max{Cj }. j. (2.4). • Tiempo de flujo ponderado. Trata de minimizar el lapso de tiempo que las tareas permanecen en el sistema de acuerdo a su importancia. Fwt =. . wj Fj .. (2.5). j. • Demora ponderada. Este objetivo intenta disminuir el margen de tiempo positivo o negativo que las tareas exceden su fecha lı́mite para evitar una penalización w j . Lwt =. . wj Lj .. (2.6). j. • Tardanza ponderada. Objetivo de la producción que intenta minimizar el margen de tiempo positivo que las tareas exceden su fecha lı́mite de acuerdo a su importancia relativa en el sistema.  wTj Tj . (2.7) Twt = j. • Tiempo de flujo máximo. Se intenta minimizar la cantidad de tiempo que las tareas permanecen dentro del sistema. Fmax = max{Fj }. j. (2.8). • Demora máxima. Este objetivo de la producción se encarga de reducir el lapso de tiempo (positivo o negativo) que las tareas exceden su fecha lı́mite. Lmax = max{Lj }. j. 8. (2.9).

(19) • Tardanza máxima. Minimiza la cantidad de tiempo positivo en que las tareas propasan su fecha lı́mite. Este objetivo es importante cuando los clientes soportan pequeñas tardanzas en la entrega de sus pedidos, pero su disgusto aumenta progresivamente en tardanzas mayores. (2.10) Tmax = max{Tj }. j. • Número de tareas tardı́as. Este objetivo intenta disminuir el número de tareas tardı́as resultando de gran utilidad cuando los clientes no aceptan tareas retrasadas, por lo que la orden se pierde. Nwt =. . WN j ρ(Tj ),. (2.11). j. . donde. 1, 0,. ρ(x) =. si x > 0; si no.. (2.12). • Justo a tiempo. En este objetivo de la producción se realizan penalizaciones por entregas prematuras y por entregas tardı́as. Es muy útil cuando los clientes no quieren sus tareas retrasadas pero tampoco las recogen cuando están listas con anticipación. ET wt =. . (wEj Ej + wTj Tj ).. (2.13). j. En cierto modo, justo a tiempo es el criterio de optimización menos tolerante a que se presenten alteraciones en las fechas de entrega reales. Por esta razón, los experimentos de la investigación que aquı́ se presenta están basados en la optimización de este criterio en particular.. 9.

(20) Capı́tulo 3. Dinámica de cuello de botella. En este capı́tulo se presenta la heurı́stica para problemas de programación de tareas llamada dinámica de cuello de botella. Se presenta una breve introducción y la definición formal de la heurı́stica. Más adelante se define la heurı́stica para la optimización de diversos objetivos de la producción, incluyendo el criterio de justo a tiempo, el cual será utilizado en los experimentos a lo largo de esta tesis. Se presenta un ejemplo de programación de tareas, ası́ como un algoritmo modificado que disminuye el tiempo de ejecución de la heurı́stica.. 3.1. Introducción. La dinámica de cuello de botella (DCB) es una heurı́stica que se deriva de los métodos de cuello de botella para resolver problemas de programación de tareas (Martı́nez, 1999). Los métodos de cuello de botella estiman precios o costos de retraso para cada tarea, por medio de la estimación del retraso final del trabajo al cual corresponde la tarea (Gálvez, 2000). En estos métodos se asigna una prioridad mayor a la tarea más crı́tica para ser programada primero. La mecánica es de la siguiente manera. Primero se tienen que calcular prioridades para todos los trabajos en t = 0. Después se programa el trabajo con más alta prioridad de acuerdo a algún objetivo. Una vez programada la tarea, se recalculan las prioridades de los trabajos restantes en t = t + pj , donde pj es el tiempo de procesamiento del último trabajo programado continuando con el mismo ciclo hasta que no queden más trabajos. Básicamente, la dinámica de cuello de botella estima un costo de retraso aproximado para cada actividad, estimando el correspondiente retraso de entrega del trabajo del cual es parte. La dinámica de cuello de botella también estima un costo de retraso aproximado por retrasar cualquier tarea agregando los costos de retraso para todas las actividades esperando por el recurso. Comparando los costos de retraso de un recurso contra los costos del retraso de cada actividad, permite que la actividad con mayor ahorro por unidad de costo del recurso sea programada primero.. 3.2. Definición. A continuación se presenta una definición formal de dinámica de cuello de botella (Morton y Pentico, 1993): • Sea R(t) el precio implı́cito por unidad de tiempo de usar el recurso en el tiempo t. 10.

(21) • Sea I la tasa de interés derivada del costo del capital de la empresa. • Por lo tanto IR(t) es el costo por unidad de tiempo en el cual el recurso se usa una unidad de tiempo antes o después. • El tiempo de terminación de una tarea j es la única influencia de dicha tarea sobre la función objetivo. • La importancia wj de la tarea j está dada por wj = Dj Vj , donde Dj es el valor agregado y Vj es la importancia del cliente. • El slack está dado por Sj (t) = dj − pj − t, donde dj es la fecha lı́mite de entrega del trabajo j y pj es el tiempo de procesamiento de la tarea j. • Sea Uj (t) = fj (Sj (t)) el factor de urgencia de la tarea j, si dicha tarea se programa primero y se espera completar su procesamiento en un tiempo Sj . Esto es, fj es el costo marginal de decrementar el slack en la función objetivo con el tiempo de procesamiento t + pj . • El precio del retraso de la tarea j está dado por wj Uj (t). Aplicando estas definiciones al problema estático de secuenciamiento de tareas en una sola máquina, se puede estimar la prioridad de la tarea j para ser programada primero. Se tiene que el recurso tiene un precio R y la tarea j tiene una importancia wj , ası́ como una urgencia Uj . Si decidimos procesar dicha tarea en un tiempo ∆t más temprano o más tarde, entonces el ahorro o el costo para la tarea j es ∆ t wj Uj ,. (3.1). pero el recurso es también utlizado un tiempo ∆t antes o después, resultando en un costo ∆t IRpj. (3.2). por el uso de dicho recurso. De esta manera, las ganancias de procesar un trabajo antes serı́an ∆t wj Uj − ∆t IRpj .. (3.3). Dado que sólo hay un recurso, el trabajo con la prioridad más alta deberı́a ser aquel con el ahorro más alto por unidad de costo del recurso. La prioridad Πj de la tarea j está dada por . Πj = ∆t. . wj Uj −1 . IRpj. (3.4). Considerando que ∆t , I y R son los mismos para todos los trabajos, las prioridades pueden ser estimadas por Πj =. wj Uj , pj. 11. (3.5).

(22) Πj ✻. wj pj. ✲ −Sj. Figura 3.1: Dinámica de cuello de botella para retraso ponderado. donde wj es la importancia de la tarea, pj es el tiempo de procesamiento y Uj es el factor de urgencia en el tiempo actual.. 3.3. DCB para diversos objetivos de producción. El método de dinámica de cuello de botella asigna una prioridad a cada una de las tareas cada vez que se va a decidir qué tarea se enviará al recurso único del sistema. Se programa la tarea de más alta prioridad y se recorre el reloj del sistema en el tiempo de procesamiento de la tarea que se programó. La fórmula 3.5 resume la forma en que la heurı́stica de dinámica de cuello de botella determina la prioridad de la tarea j. La urgencia U j depende del objetivo de producción que se desea optimizar. En general, no hay una forma única de expresión de la urgencia para un objetivo dado. Con el fin de ilustrar la aplicación de dinámica de cuello de botella, consideremos el objetivo de producción de retraso ponderado. En este caso se tiene que w j Uj (t) = wj para todos los tiempos t. Se deriva que el costo marginal del retraso es independiente del retraso mismo. Por lo tanto, no necesitamos calcular el factor de urgencia, es decir, U j (t) = 1 para todos los tiempos t. La función de prioridad es simplemente: Πj =. wj pj. (3.6). La gráfica de DCB para el objetivo de retraso ponderado se muestra en la figura 3.1. De igual forma, es posible utilizar dinámica de cuello de botella para minimizar el criterio de tardanza ponderada. En este criterio de optimización se penalizan los trabajos tardı́os; es decir, los trabajos que exceden su fecha lı́mite. La tardanza ponderada se define como: Twt =.  j. 12. wTj Tj ,. (3.7).

(23) Πj ✻. wj pj. ✲ −Sj. Figura 3.2: DCB para tardanza pondera sin corrección de urgencia donde . Tj =. 0, Cj − dj ,. si Cj − dj < 0; en caso contrario.. Cj es la fecha o tiempo en que se completa la tarea j. Una vez que se ha establecido este criterio de producción, dinámica de cuello de botella presenta varias alternativas de solución. Como primer alternativa de dinámica de cuello de botella para este objetivo de producción, se tiene la heurı́stica sin corrección de la urgencia. Para minimizar la tardanza ponderada debemos tomar en cuenta la holgura de la tarea. Si la tarea j se programa en el tiempo t, su holgura estará dada por Sj (t) = dj − (pj + t).. (3.8). Intuitivamente podemos decir que una tarea cuya holgura sea negativa, es decir, que su fecha de entrega ya pasó, tendrá una mayor prioridad por ser un trabajo tardı́o. Por esta razón, la prioridad de las tareas se calcula de la siguiente forma: . Πj =. 0, si Sj > 0; wj /pj si Sj ≤ 0.. (3.9). La gráfica de esta función se muestra en la figura 3.2. Esta heurı́stica tiene un desempeño aceptable, sin embargo, puede ser mejorada mediante la heurı́stica que toma en cuenta la corrección del factor de urgencia. Con esta correción, se considera que no es posible retrasar el inicio de una tarea por cualquier tiempo ∆. El retraso en iniciar una tarea es p i , el tiempo de procesamiento de la tarea que se está realizando en lugar de la tarea j. Si la tarea j tiene inicialmente una holgura mayor que pi , entonces de acuerdo a la heurı́stica presentada su prioridad es cero antes y después de realizar la tarea i. Pero si Sj /pj = β < 1 entonces la tarea j tendrı́a una prioridad de cero durante una fracción β de p i y una prioridad wj /pj 13.

(24) Πj ✻ ✡ ✡ wj ✡ pj ✡ ✡ ✡ ✡ ✡. ✲ −Sj. pav. Figura 3.3: DCB para tardanza ponderada con corrección de la urgencia. durante una fracción 1 − β de pi de donde la prioridad promedio serı́a (1 − β)wj /pj . Si la tarea i se realiza antes que la tarea j: wi pi. . S+ 1− i pj. +. wj ≥ pj. . Sj+ 1− pi. +. ,. (3.10). donde  +. x =. si x ≥ 0; si x < 0.. x, 0,. La heurı́stica anterior tiene el problema de que la prioridad de una tarea depende de los tiempos de procesamiento de las tareas con las cuales está compitiendo por un lugar en el programa de trabajo. Una solución práctica es utilizar el promedio de los tiempos de procesamiento de las tareas que están compitiendo por la más alta prioridad, p av , en lugar de pi . La prioridad de la tarea j que proporciona esta heurı́stica es: wj Πj = pj. . Sj+ 1− pav. +. .. (3.11). La gráfica del calculo de la prioridad Πj se muestra en la figura 3.3. La última corrección en el factor de urgencia U es un poco más sutil. Suponga cinco tareas con tiempo de procesamiento 1. Cuatro de las tareas tienen peso 8 y fecha de entrega en t = 4. Una de las tareas tiene peso 1 y fecha de entrega en t = 1. Es el tiempo cero y se tiene que tomar una decisión. Si aplicamos la heurı́stica anterior, las cuatro tareas están más de un tiempo de procesamiento lejos de ser tardı́os y por lo tanto, tienen prioridad cero. La tarea con peso 1 tiene una prioridad de 1 y es procesada primero. Pero una de las tareas con peso 8 se terminará tarde, costando 8; mientras que si se programan primero las tareas de alto costo, la tarea de bajo costo habrı́a tenido un costo total de 4. El problema es que la estimación 14.

(25) ✻. wj pj. ✲ −Sj. ✪. Figura 3.4: DCB para tardanza ponderada con corrección suavizada de U de holguras y prioridades tarea por tarea puede ser errónea si hay varias tareas con fecha de entrega similar. Un procedimiento simple es escoger un conjunto de pesos exponencialmente decrecientes que suman 1, y promediando las urgencias de tiempo adecuadamente, se obtiene la siguiente regla con la que se calcula la prioridad de las tareas: . Sj+ wj exp 1 − Πj = pj kpav. . ,. (3.12). donde k es un parámetro que ajusta el lı́mite de cambio de prioridad. La gráfica de Π j se muestra en la figura 3.3. En general, se puede decir que las heurı́sticas que toman en cuenta la corrección del factor de urgencia Uj , obtienen un mejor resultado que la heurı́stica sin urgencia. La actualización de los valores de urgencia con respecto al tiempo permiten a dinámica de cuello de botella programar cada tarea más información acerca del estado del sistema de producción. La selección de la heurı́stica con corrección que se debe utilizar, está relacionada con el problema en particular que se pretende resolver, tomando en cuenta la distribución de los tiempos de entrega y los tiempos de procesamiento de las tareas, ası́ como alguna otra información adicional que pudiera servir para seleccionar alguna heurı́sitca.. 3.4. DCB para justo a tiempo. Hasta ahora sólo se han explicado las heurı́sticas para con funciones incrementales en términos del tiempo de terminación de las tareas. Sin embargo, en muchas aplicaciones prácticas el objetivo es justo a tiempo (JIT), es decir, existe un costo asociado por entregar una tarea de forma tardı́a, ası́ como también de manera prematura. Esto es, se desea entregar cada tarea el dı́a o la hora exacta, y cualquier desviación de la entrega de la tarea con respecto a la fecha de entrega dj establecida tiene un costo asociado. El costo del objetivo justo a 15.

(26) Πj ✻. wTj pj ✡. ✡ ✡ ✡ pav ✡ ✡ ✡ ✡ ✡ ✡ ✡. ✲ −Sj. −. wEj pj. Figura 3.5: DCB para el criterio de justo a tiempo tiempo se define como: ETwt =. . (wEj Ej + wTj Tj ),. (3.13). j. tal como se describió en el capı́tulo anterior. La heurı́stica de DCB para minimizar el criterio de Justo a tiempo calcula las prioridad de la tarea j con la siguiente fórmula (Ow y Morton, 1989): . wTj − min 1, Πj =. Sj+ kpav pj. . (wTj + wEj ) .. (3.14). Bajo esta regla, las tareas de más alta prioridad son las más urgentes, por lo que son las que se programan. Si ninguna de ellas tiene prioridad mayor que cero, y no se permiten tiempos muertos insertados, la heurı́stica toma la tarea con prioridad mayor aunque no sea urgente en ese momento. Si se aceptan tiempos muertos insertados, la heurı́stica simplemente incrementa el reloj en una unidad de tiempo y no programa ninguna tarea. En la siguiente unidad de tiempo, dinámica de cuello de botella calcula nuevamente las prioridades y establece cuál es la tarea con mayor prioridad; de esta forma, dicha tarea es programada. En la figura 3.4 se muestra la gráfica de la heurı́stica en función del tiempo de ejecución para cualquier tarea a programar.. 16.

(27) 3.5. Modificaciones a DCB para justo a tiempo. La demanda de recursos de cómputo de dinámica de cuello de botella puede llegar a ser muy alta, sobre todo si el problema que se está resolviendo es de tamaño considerable, o bien si se ejecuta múltiples veces al ser combinada con otros algoritmos. Por esta razón, es conveniente realizar algunas modificaciones para minimizar el tiempo de ejecución de la heurı́stica dinámica de cuello de botella (Valenzuela, 2001). En la sección anterior se presentó la heurı́stica DCB para minimizar el criterio de justo a tiempo y la fórmula para el cálculo de prioridades. Podemos reescribir la prioridad de la tarea j como a continuación se muestra: . Πj pj = wTj − min 1,. Sj+ kpav. . (wTj + wEj ).. (3.15). De esta ecuación, podemos analizar varios casos. Si kpav ≤ Sj+ entonces: Πj pj = wTj − (wTj + wEj ) = wEj .. (3.16). Si kpav ≤ Sj+ obtenemos: Πj pj = wTj −. Sj+ kpav. (wTj + wEj ).. (3.17). Esta última ecuación se puede dividir en dos casos. Para el caso en que kpav ≤ Sj+ y Sj > 0, tenemos: Sj+ (wTj + wEj ). (3.18) Πj pj = wTj − kpav Si kpav ≤ Sj+ y Sj > 0, entonces: Πj pj = wTj .. (3.19). De esta forma, podemos reescribir la heurı́stica DCB de la siguiente manera:      . Πj pj =.     . si Sj ≤ 0;. wTj. wTj −. Sj+. (wTj + wEj ) si 0 < Sj < kpav ; kpav si Sj ≥ kpav . wE j. (3.20). Una tarea cualquiera en el tiempo t, solamente puede estar en una de las tres posiciones determinadas en la ecuación anterior. Es posible que aparezca en la recta superior, cuando Sj ≤ 0; de igual forma, puede presentarse en la diagonal ascendente, representando el movimiento gradual de urgencias de las tareas, que corresponde a 0 < Sj < kpav ; finalmente, puede estar en la recta inferior, que corresponde a Sj ≥ kpav . Para lograr una evaluación más rápida de la heurı́stica DCB, nos interesa conocer el tiempo cuando una tarea j alcanzará la prioridad 0, pues en este momento será posible 17.

(28) programarla, de esta forma evitaremos los incrementos unitarios del tiempo con el consecuente ahorro de cálculos de prioridades para todas las tareas. La diagonal de la figura 3.4 corresponde a la ecuación: Πj pj = wTj −. Sj+ kpav. (wTj + wEj ).. (3.21). Al despejar Sj de la ecuación anterior obtenemos Sj =. kpav wTj + wEj. (wTj − Πj pj ).. (3.22). La holgura Sj para cuando la prioridad Πj es mı́nima es: Sjmin = kpav .. (3.23). Recordando que la holgura se define como Sj = dj − pj − t, se puede despejar de la ecuación anterior el tiempo cuando la holgura es mı́nima: tmin = dj − pj − Sjmin = dj − pj − kpav . j. (3.24). La holgura para cuando la prioridad Πj es cero es: Sj0 =. kpav wTj + wEj. wTj .. (3.25). De la misma forma, se puede obtener el tiempo para el cual la prioridad se vuelve positiva: t0j = dj − pj − kpav. wTj wTj + wEj. .. (3.26). Las cantidades kpav , wTj + wEj y dj − pj permanecen constantes durante toda la generación de la secuencia de tareas de DCB, por esta razón pueden ser calculadas por anticipado. Para agrupar y simplificar operaciones, se proponen las siguientes definiciones: p̂ = kpav =. n k. n. pi ;. (3.27). i=1. Dj = d j − p j ;. (3.28). Wj = wTj + wEj .. (3.29). Sustituyendo las definiciones anteriores en las ecuaciones definidas en esta sección, se obtienen las siguientes ecuaciones: = Dj − p̂; tmin j 18. (3.30).

(29) t0j = Dj − p̂. wTj Wj. ;. (3.31). = Dj ; tmax j. Πj =. 1. wTj −. pj. (3.32). Dj − t p̂Wj. .. (3.33). Donde la prioridad es máxima, mayor o igual a cero y mı́nima para tmax , t0j y tmin j j , respectivamente.. 3.6. Algoritmo para la evaluación rápida de DCB. De acuerdo a las definiciones de los posibles casos en los que la prioridad de la tarea j puede encontrarse en un tiempo t cualquiera en la ejecución, es posible definir un algoritmo que disminuya el tiempo de ejecución del algoritmo de dinámica de cuello de botella con tiempos muertos (Valenzuela, 2001). La disminución de tiempo se hace más evidente, cuando en la iteración se involucran tiempos muertos insertados de manera consistente. El algoritmo se muestra a continuación: 1. Calcular p̂. 0 max . 2. Para todas las tareas, calcularDj , Wj , tmin j , tj y t j. 3. Fijar el tiempo de inicio t = t0 . 4. Para cada tarea: • Marcarla como tarea α si t < t0j ; • Marcarla como tarea β si t0j ≤ t ≤ tmax . j 5. Para todas las tareas, si t > tmax se marca como tarea γ y se calcula su prioridad como j Πj =. wTj pj. .. (3.34). 6. Para las tareas β se calcula su prioridad como Πj =. 1 pj. wTj −. Dj − t p̂Wj. .. (3.35). 7. Se encuentra la tarea β o γ con máxima prioridad Πj y se programa esta tarea recorriendo el reloj por su tiempo de procesamiento t ← t + pj . Ir al paso 6.. 19.

(30) 8. Si no existe ninguna tarea β o γ, se selecciona la tarea α con menor t 0j y se recorre el reloj en su tiempo de procesamiento. 9. Se repite hasta programar todas las tareas.. 20.

(31) Capı́tulo 4. El algoritmo genético cooperante. En este capı́tulo se presenta un algoritmo genético de varias poblaciones, llamado algoritmo genético cooperante (de la Cueva, 1998). Se realiza una descripción de su estructura, su funcionamiento y sus operadores. Se describe además su mecanismo de intercambio de información, el cual es indispensable para realizar la cooperación entre las poblaciones del algoritmo genético cooperante (AGC). Finalmente se comenta de manera breve una aplicación del algoritmo, ası́ como los tipos de problemas que es conveniente representar mediante un AGC.. 4.1. Descripción y funcionamiento. El algoritmo genético cooperante, es en realidad un conjunto de algoritmos genéticos que trabajan de manera coordinada para llegar a su objetivo planeado. La coordinación se realiza mediante un mecanismo de comunicación entre las poblaciones del algoritmo genético cooperante, similar al operador de migración de un algoritmo genético paralelo (Belding, 1995), llamado mecanismo de intercambio de información. Debido a que las poblaciones pueden representar componentes relacionados pero distintos, éstas pueden tener diferente número de individuos, ası́ como diferente longitud de los mismos. Otra caracterı́stica importante es que la función objetivo de cualquiera de las poblaciones puede ser distinta, sin embargo, su valor puede depender del valor de ciertos parámetros de las demás poblaciones. El AGC es similar a un algoritmo genético paralelo (AGP) en el sentido de que tiene varias poblaciones. El AGC cuenta con una serie de poblaciones, sólo que a diferencia de un AGP, estas poblaciones son de individuos que representan algo distinto. Esto implica que los elementos de una de las poblaciones no pueden emigrar para incorporarse a las otras, como lo hacen comúnmente en un AGP. Debido a esta caracterı́stica, cada población de un AGC puede representar un elemento distinto del problema que se pretende resolver. En un algoritmo genético cooperante, debe existir algún medio para intercambiar información entre las poblaciones; de este modo los elementos del AGC trabajan en una misma dirección para cumplir el objetivo global. Comúnmente, dicho medio de intercambio de información depende de la representación del problema que se establece en el AGC. Esta cooperación que se lleva a cabo entre las poblaciones es similar al operador de migración de un AGP, salvo que en el caso de un AGC los elementos que son transportados en ese operador no se incorporan como parte de otras poblaciones, sino que sólo se utiliza. 21.

(32) su valor como información para la evaluación de la población que lo recibe. Además, el mecanismo de intercambio de información puede transportar otro tipo de información que sirva para llevar a cabo la cooperación y la coordinación del sistema. Prácticamente, un AGC se puede considerar como un conjunto de algoritmos genéticos simples que operan de manera independiente, pero donde la evaluación de los individuos de su población depende del comportamiento de las otras poblaciones. A medida que un AG evoluciona, la función de aptitud de los demás AGs dentro del algoritmo genético cooperante puede ser modificada. Esto es importante ya que se está hablando de una función de aptitud dinámica, es decir, que puede cambiar con el tiempo con respecto a la evolución de todas las poblaciones que componen el AGC. Es entre estas funciones de aptitud individuales donde en realidad se lleva a cabo la comunicación, ya que la información recibida por medio de este mecanismo es necesaria para realizar la evaluación de cada una de las poblaciones. Los operadores genéticos de selección, cruce y mutación (Goldberg, 1989) de un AG independiente se realizan de la misma forma que un AG tradicional. Sólo en la evaluación es donde se toma en cuenta la cooperación con el resto de los AGs. En la figura 4.1 podemos ver un esquema de un AGC de tres poblaciones.. Función de Aptitud. aptitud. m1,i m2, j m3, k mejor3,k. mejor1,i mejor2 , j. Población 1. Población 2. m generaciones. n generaciones. Población 3 p generaciones. Figura 4.1: Un AGC de tres poblaciones Al final de cada generación, cada población envı́a su mejor elemento llamado m i,j , (el mejor individuo de la población i en la generación j). El elemento enviado no pasa a ser parte de las otras poblaciones como lo harı́a un AGP, por lo que a esto se le considera un mecanismo y no un operador genético, ya que no altera las poblaciones. Estos mejores elementos se utilizan para completar una plantilla, donde el valor de la función de aptitud depende de los valores que contenga esta plantilla. Las otras poblaciones usan los mejores elementos recolectados en la plantilla para evaluar cada uno de los elementos de su población. La función de aptitud de cada población puede cambiar a través del tiempo, en caso que la naturaleza del problema ası́ lo requiera. La. 22.

(33) evaluación de cada uno de los elementos de una población está basada en el valor de la plantilla en el momento de la evaluación, la cual está formada con los mejores individuos de las otras poblaciones en la generación anterior, los cuales son enviados por medio del mecanismo de intercambio de información, como se muestra en la figura 4.2. En caso de que sea la generación inicial, los mejores elementos son generados de manera aleatoria.. Individuo k a evaluar. 1 2 3. .... ... m1. .... ci , k. . . . mp. mejores. Función de Aptitud n. Población i de n individuos, m generaciones. Evaluación del elemento k. Figura 4.2: Esquema de la evaluación de una de las tres poblaciones Cada población envı́a su mejor individuo a un lugar especı́fico dentro de la plantilla. De esta forma, cuando una población va a ser evaluada simplemente coloca cada uno de sus elementos en su lugar, la cual es completada con los mejores de las otras poblaciones, y finalmente se aplica la función de aptitud correspondiente. Una vez terminada la evaluación de la población i, se procede a la colocación del mejor de dicha población en su lugar de la plantilla para que este valor sea utilizado por las otras poblaciones cuando tengan que evaluarse. Como se ha mencionado anteriormente, el algoritmo genético cooperante permite representar un problema mediante la separación de componentes de dicho problema, codificando cada uno de estos componentes en individuos que pertenecen a poblaciones distintas. Un ejemplo de aplicación exitosa del algoritmo genético cooperante, es la tesis doctoral donde se definió dicho concepto (de la Cueva, 1998). En esa investigación se resolvió el problema de cálculo de trayectorias de dos brazos de robot. En este ambiente, los brazos debı́an manipular un objeto en un ambiente común. El algoritmo genético cooperante fue utilizado para calcular las trayectorias de ambos brazos, de modo que éstas estuvieran libres de colisiones. La representación del problema consistió en dos poblaciones, cada una de las cuales codificaba la información de un brazo. La evalución de cada individuo se realizaba tomando en cuenta la posición del otro brazo. Para este problema en particular, el uso de un algoritmo genético 23.

(34) cooperante presentó una ventaja definitiva, debido a la naturaleza claramente separada del problema; existen dos brazos de robot y la aptitud de cada trayectoria depende claramente de la posición y trayectoria del otro brazo. Finalmente, debemos comentar que al igual que el algoritmo genético simple, el desempeño del AGC depende fuertemente de una acertada representación del problema en particular. En esta tesis se ha mencionado el concepto de problema separable; sin embargo, la separabilidad en buena medida depende de la representación misma del problema. Existen problemas cuya condición de separabilidad es evidente, como por ejemplo el cálculo de trayectorias de brazos robot; otros más cuya separabilidad se supone pero no podemos identificarla de manera explı́cita, tales como el problema de programación de tareas; y los últimos en los que no es necesario ni conveniente representar de forma separada. Para este tipo de problemas, un algoritmo genético cooperante puede tener un desempeño muy malo con respecto a otros métodos de búsqueda que utilicen la información completa del problema. Una análisis detallado del comportamiento del AGC, ası́ como las variantes de intercambio de información, fue presentado por Victor de la Cueva (1998).. 24.

(35) Capı́tulo 5. Representación del problema utilizando un AGC. En este capı́tulo se presenta el uso de un algoritmo genético cooperante (AGC) para resolver un problema de programación de tareas. Se presenta una justificación del uso de un AGC para la solución de este tipo de problemas, ası́ como también la suposición de la existencia de una separabilidad implı́cita presente en los problemas de programación de tareas. Se describe la codificación del problema en los elementos de un algoritmo genético cooperante, ası́ como el proceso de evaluación de los individuos de cada población del AGC. Se muestra además un ejemplo de solución de una instancia del problema. Finalmente se discuten dos variantes fundamentales para el desempeño del algoritmo: el uso de particiones traslapadas y la reinicialización.. 5.1. Representación del problema. La representación mediante un algoritmo genético cooperante de varias poblaciones se basa en la suposición de que en un problema de programación de tareas existen tareas que están fuertemente relacionadas entre sı́; de igual forma, existen tareas que no influyen en la programación de otras. Podemos llamar a esta propiedad la separabilidad implı́cita. Debido a que no es fácil identificar mediante un análisis heurı́stico dicha condición, se pretende utilizar la selección natural y la naturaleza dividida de un algoritmo genético cooperante para identificar los grupos de tareas relacionadas, y de esta forma encontrar mejores soluciones al problema que las heurı́sticas probadas anteriormente, e incluso encontrar un mejor desempeño que un algoritmo genético simple. Se desea representar el problema de programación de tareas en una máquina que deberá ser resuelto por el algoritmo genético cooperante. Para ello, definimos una tarea j como j = pj , dj , wEj , wTj ,. (5.1). donde pj , representa el tiempo de procesamiento de la tarea j en el único recurso del sistema, dj el tiempo de entrega de la tarea j, wEj es el costo por unidad de tiempo que se genera por entregar prematuramente la tarea, y wTj el costo por unidad de tiempo generado por entregar de manera tardı́a la tarea j. Definimos un conjunto finito de tareas no ordenadas J, de la siguiente forma: J = {j|j = 1, 2, . . . , n} ; 25. (5.2).

(36) donde n es el número de tareas que contiene el conjunto J. Dicho conjunto de tareas es la instancia del problema de programación de tareas que se pretende resolver mediante un AGC. Se define una secuencia ordenada de tareas S, que representa el orden en que se procesarán cada una de las tareas del conjunto J; es decir, la tarea j se ejecutará en el tiempo tj : S = {(j, tj )|j ∈ J}.. (5.3). La secuencia de tareas S es producida por: S = D(J),. (5.4). donde D es la función que ordena un conjunto de tareas J mediante el método de dinámica de cuello de botella. La secuencia S tiene un costo asociado cs , que se obtiene mediante la función de evaluación C, la cual evalúa el costo de programar el conjunto de tareas J con la secuencia S, es decir: cs = C(S, J).. (5.5). La función C, calcula el costo asociado cs , en base a un criterio de producción previamente establecido. En los experimentos llevados a cabo en esta tesis, una secuencia de tareas se evalúa con el criterio de producción justo a tiempo, definido en el capı́tulo 3.. 5.2. Creación de las particiones. Un algoritmo genético cooperante, tal como se describió en el capı́tulo anterior, contiene varias poblaciones que representan distintos elementos del problema en particular que se pretende resolver. Para el problema de programación de tareas, cada partición en un algoritmo genético cooperante contiene la representación de un subconjunto de tareas del problema original. El procedimiento de creación de dichos subconjuntos se define a continuación. Sea Gp un algoritmo genético cooperante (de la Cueva, 1998) de p poblaciones, tal como se definió en el capı́tulo 4: (5.6) {P1 , P2 , . . . , Pp } ∈ Gp . La población Pk de cromosomas binarios (Goldberg, 1989) de igual longitud se define como: (5.7) Pk = {c1,k , c2,k , . . . , cpk ,k } , donde pk es el número de individuos de la población Pk . La partición sk , k = 1, 2, . . . , p; está definida como la sublista de tareas ordenadas de la lista S, definida por: sk = fa,b (S);. 1 ≤ a ≤ n;. 26. 1 ≤ b ≤ n;. a < b.. (5.8).

(37) El número de poblaciones p de un algoritmo genético cooperante Gp , corresponde al número de particiones de la lista de tareas S, es decir: S = {s1 , s2 , . . . , sp } ,. (5.9). tal que s1 = f1,b1 (S),. s2 = fb1 +1,b2 (S),. .... sp = fbn−1 ,bn (S).. (5.10). La función fa,b regresa la sublista de tareas desde la posición a, hasta la posición b, tal como se muestra en la figura 5.1. El tamaño de las particiones sk de la secuencia de tareas S, es determinado por el número de dichas particiones p, con la expresión:  . λ=. n . p. (5.11). Por lo tanto, un conjunto de particiones {s1 , s2 , . . . , sp } ∈ S que será representado por un algoritmo genético cooperante Gp , se genera de la forma: s1 = f1,λ (S);. s2 = f1+λ,2λ (S);. . . . sp = f(p−1)λ+1,n (S).. (5.12). De manera más general, la partición sk se define como: . sk =. f1+(k−1)λ,kλ (S), si k < p; f1+(k−1)λ,n (S), si k = p.. (5.13). S. sk j. a a+1 . . b. f a ,b. 1 2 . . . a . . b . . . n. j. Figura 5.1: Creación de una sublista de tareas Cada población Pk del algoritmo genético cooperante Gp , representa una sublista ordenada de tareas sk de la lista completa de tareas S, mediante la función de representación R: (5.14) Pk ← R(sk ),. 27.

(38) la cual define dos factores δwEj y δwTj , para toda j ∈ sk . Dichos factores modifican el costo por entrega prematura de la tarea j, wEj ; ası́ como el costo por entrega tardı́a de dicha tarea, wTj , respectivamente. La función de representación fr define δwEj como: δwEj = ψ (αE , βE ) ,. (5.15). donde ψ regresa un valor aleatorio con distribución uniforme en el intervalo [α E , βE ]. De manera similar, δwTj está dada por: δwTj = ψ (αT , βT ) .. (5.16). Ambos factores se utilizan para calcular los pesos ajustados de la tarea j. Dichos valores ajustados de los pesos de la tarea j serán definidos más adelante en la evaluación de las poblaciones Pk del algoritmo genético cooperante Gp .. 5.3. Codificación en el cromosoma. Una vez que las particiones o subconjuntos de tareas han sido definidos, es necesario representar dichos subconjuntos de tareas en las poblaciones correspondientes. Los factores δwEj y δwTj para cada tarea j ∈ sk , se codifican en los cromosomas binarios de la población Pk que representa la partición sk , de la siguiente forma. Sea ci,k ∈ Pk un cromosoma binario de tamaño 2.(b−a), donde . se define como la longitud de representación para los factores δw, y b − a es el número de tareas que pertenecen a la partición sk . El cromosoma ci,k se divide en subconjuntos de bits de longitud 2., los cuales representarán los factores de modificación de cada tarea j ∈ sk . Para cada subconjunto creado, se generan dos factores de modificación δwEj y δwTj mediante las funciones 5.15 y 5.16. Cada factor δwEj generado, se codifica a binario ocupando los primeros . bits del subconjunto que representa la tarea j. De igual forma, cada factor δwTj será codificado en binario, ocupando . bits restantes del subconjunto de bits asignados en el cromosoma. En la figura 5.2 se ilustra la representación de cada tarea j ∈ sk , en un cromosoma binario de la población Pk . Como se puede apreciar, el tamaño del cromosoma crece linealmente con el número de tareas que se pretende representar en él.. 5.4. Evaluación de los individuos. Una vez que el algoritmo genético cooperante Gp ha llevado a cabo la representación de las sublistas de tareas sk en las poblaciones Pk ∈ Gp , es necesario definir la forma de evaluar la aptitud del elemento ci,k ∈ Pk . Sea gk un algoritmo genético simple, definido como gk (Pk , fk ), donde fk es la función de aptitud de los elementos ci,k de la población Pk .. 28. (5.17).

(39) tarea a. tarea a + 1. 01101. 01011. 00101. 01100. ❄. ❄. ❄. ❄. δwEa. δwTa. δwEa+1 δwTa+1. tarea b ···. ···. 10010. 10001. ❄. ❄. δwEb. δwTb. Figura 5.2: Representación de las tareas de la partición sk en el cromosoma binario. La función fk está dada por: ei,k = fk (m1 , m2 , . . . , ci,k , . . . , mp );. i = 1, 2, . . . , p;. (5.18). donde los elementos mx representan el mejor individuo de la población Px encontrado hasta ese momento, tal que Px = Pk . ei,k representa la evaluación del cromosoma ci,k . La función de aptitud fk , toma a los mejores elementos de las poblaciones encontrados hasta ese momento, los cuales representan las tareas que están fuera de la partición s k para completar un programa S y ası́ encontrar la evaluación del invididuo ci,k . De manera más especı́fica, para cada función que recibe, la función fk decodifica el segmento binario a un número real en el intervalo [α, β], el cual representa los factores δw Ej y δwTj de cada tarea j ∈ J, respectivamente. Para cada tarea j ∈ J, se obtienen los pesos  y w  mediante: ajustados wE Tj j  wE = wEj · δwEj j. (5.19). wT j = wTj · δwTj ,. (5.20). y respectivamente. Una vez que se han calculado los pesos ajustados para tarea, se define J  como el conjunto  y w  , es decir: de tareas j con pesos ajustados wE Tj j  , wT j J  = j|j = pj , dj , wE j. .. (5.21). Con el conjunto de tareas con pesos ajustados J  , se crea una secuencia ajustada de tareas S  mediante la función 5.4, de la siguiente forma: S  = D(J  ).. (5.22). Finalmente, la evaluación del individuo ci,k es el costo de programar el conjunto original de tareas J con la secuencia ajustada de tareas S  , mediante la función 5.5; es decir: ei,1 = C(S  , J).. 29. (5.23).

(40) Secuencia de tareas, S. s1. s2. sp. . . .. . gp. g2. g1. . . . . . .. P2. P1 f1. f2. . . .. Pp fp. Gp Figura 5.3: Un AGC de p poblaciones para resolver un problema de programación de tareas. 5.5. Ejemplo del uso del AGC. A continuación se presenta un ejemplo de solución a un problema de programación de tareas mediante un algoritmo genético cooperante, con el fin de ilustrar los conceptos introducidos en este capı́tulo. Sea J un conjunto de tareas no ordenadas de longitud n = 10. Se pretende optimizar el criterio de Justo a tiempo utilizando un algoritmo genético cooperante de 3 poblaciones, G 3 . Se crea el ordenamiento inicial de tareas S, mediante la heurı́stica de dinámica de cuello de botella, de la forma: S = D(J). (5.24) Ya que el algoritmo genético cooperante G3 utilizará tres poblaciones para optimizar el criterio justo a tiempo, es necesario construir tres particiones de S. Se calcula el tamaño de las particiones mediante 5.11 de la siguiente forma: . λ=. . 10 = 3. 3. (5.25). De esta forma, se crean las particiones s1 , s2 , s3 ∈ S de acuerdo a las fórmulas 5.13 de la siguiente forma: (5.26) s1 = f1,λ (S) = f1,3 (S), s2 = fλ+1,2λ (S) = f4,6 (S), y finalmente 30. (5.27).

Figure

Figura 3.3: DCB para tardanza ponderada con correcci´ on de la urgencia.
Figura 3.5: DCB para el criterio de justo a tiempo
Figura 4.1: Un AGC de tres poblaciones
Figura 4.2: Esquema de la evaluaci´ on de una de las tres poblaciones
+7

Referencias

Documento similar

La campaña ha consistido en la revisión del etiquetado e instrucciones de uso de todos los ter- mómetros digitales comunicados, así como de la documentación técnica adicional de

This section provides guidance with examples on encoding medicinal product packaging information, together with the relationship between Pack Size, Package Item (container)

dente: algunas decían que doña Leonor, &#34;con muy grand rescelo e miedo que avía del rey don Pedro que nueva- mente regnaba, e de la reyna doña María, su madre del dicho rey,

Y tendiendo ellos la vista vieron cuanto en el mundo había y dieron las gracias al Criador diciendo: Repetidas gracias os damos porque nos habéis criado hombres, nos

Entre nosotros anda un escritor de cosas de filología, paisano de Costa, que no deja de tener ingenio y garbo; pero cuyas obras tienen de todo menos de ciencia, y aun

o Si dispone en su establecimiento de alguna silla de ruedas Jazz S50 o 708D cuyo nº de serie figura en el anexo 1 de esta nota informativa, consulte la nota de aviso de la

De hecho, este sometimiento periódico al voto, esta decisión periódica de los electores sobre la gestión ha sido uno de los componentes teóricos más interesantes de la

Las manifestaciones musicales y su organización institucional a lo largo de los siglos XVI al XVIII son aspectos poco conocidos de la cultura alicantina. Analizar el alcance y