Avarap

862 views

Published on

Published in: Business
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
862
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
17
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Avarap

  1. 1. Algoritmos voraces <ul><li>1. Método general. </li></ul><ul><li>2. Análisis de tiempos de ejecución. </li></ul><ul><li>3. Ejemplos. </li></ul><ul><li>3.1. Problema de la mochila. </li></ul><ul><li>3.2. Planificación de tareas. </li></ul><ul><li>4. Técnicas heurísticas. </li></ul><ul><li>4.1. El problema del viajante. </li></ul><ul><li>4.2. Coloración de grafos. </li></ul>
  2. 2. Método general <ul><li>Los algoritmos voraces , ávidos o de avance rápido ( greedy ) se utilizan normalmente en problemas de optimización, donde una solución está formada por un conjunto de elementos entre un conjunto de candidatos (con un orden determinado o no). </li></ul><ul><li>El algoritmo voraz funciona por pasos: </li></ul><ul><ul><li>Partimos de una solución vacía. </li></ul></ul><ul><ul><li>En cada paso se escoge el siguiente elemento para añadir a la solución, entre los candidatos. </li></ul></ul><ul><ul><li>Una vez tomada esta decisión no se podrá deshacer. </li></ul></ul><ul><ul><li>El algoritmo acabará cuando el conjunto de elementos seleccionados constituya una solución. </li></ul></ul>
  3. 3. Método general <ul><li>Esquema general de un algoritmo voraz: </li></ul><ul><li>voraz (C: conjunto_candidatos; var S: conjunto_solución); </li></ul><ul><li>S = Ø </li></ul><ul><li>mientras (C  Ø) y no solución (S) hacer </li></ul><ul><li> x = seleccionar (C) </li></ul><ul><li> C = C - {x} </li></ul><ul><li> si factible (S  {x}) entonces </li></ul><ul><li>S = S  {x} </li></ul><ul><li>finmientras </li></ul><ul><li>si no solución (S) entonces </li></ul><ul><li> devolver “No se puede encontrar una solución” </li></ul><ul><li>En cada paso tenemos los siguientes conjuntos: </li></ul><ul><ul><li>Candidatos seleccionados para la solución S. </li></ul></ul><ul><ul><li>Candidatos seleccionados pero rechazados luego. </li></ul></ul><ul><ul><li>Candidatos pendientes de seleccionar C. </li></ul></ul>
  4. 4. Método general <ul><li>Funciones: </li></ul><ul><ul><li>solución (S). Comprueba si un conjunto de candidatos es una solución (independientemente de que sea óptima o no). </li></ul></ul><ul><ul><li>seleccionar (C) . Devuelve el elemento más “prometedor” del conjunto de candidatos pendientes (no seleccionados ni rechazados). </li></ul></ul><ul><ul><li>factible (C) . Indica si a partir del conjunto de candidatos C es posible construir una solución (posiblemente añadiendo otros elementos). </li></ul></ul><ul><ul><li>Insertar un elemento en la solución. Además de la inserción, puede ser necesario hacer otras cosas. </li></ul></ul><ul><ul><li>Función objetivo (S) . Dada una solución devuelve el coste asociado a la misma (resultado del problema de optimización). </li></ul></ul>
  5. 5. <ul><li>Problema del cambio de monedas </li></ul><ul><li>Disponemos de monedas de distintos valores: de 1, 2, 5, 10, 20 y 50 céntimos de euro, y de 1 y 2 euros. </li></ul><ul><li>Supondremos una cantidad ilimitada de cada una. </li></ul><ul><li>Construir un algoritmo que dada una cantidad P devuelva esa cantidad con monedas de estos tipos, usando un número mínimo de monedas. </li></ul><ul><li>P. ej.: para devolver 3.89 €: 1 monedas de 2€, 1 moneda de 1€, 1 moneda de 50 c€, 1 moneda de 20 c€, 3 monedas de 5 c€ y 2 monedas de 2 c€. </li></ul><ul><li>Podemos aplicar la técnica voraz : en cada paso añadir una moneda nueva a la solución actual, hasta que el valor llegue a P . </li></ul>
  6. 6. Problema del cambio de monedas <ul><li>Candidatos iniciales : todos los tipos de monedas disponibles. Solución : conjunto de monedas que suman la cantidad P . </li></ul><ul><li>Una solución será de la forma (x 1 , x 2 , x 3 , x 4 , x 5 , x 6 , x 7 , x 8 ) , donde x i es el número de monedas de tipo i . Suponemos que la moneda i vale c i . </li></ul><ul><li>Funciones : </li></ul><ul><ul><li>solución . El valor actual será solución si  x i ·c i = P </li></ul></ul><ul><ul><li>objetivo . La función a minimizar es  x i , el número de monedas resultante. </li></ul></ul><ul><ul><li>seleccionar . Elegir en cada paso la moneda de valor más alto posible, pero menor que el valor que queda por devolver. </li></ul></ul><ul><ul><li>factible . Valdrá siempre verdad. </li></ul></ul><ul><li>En lugar de seleccionar monedas de una en una, podemos usar la división entera y coger todas las monedas posibles de mayor valor. </li></ul>
  7. 7. Problema del cambio de monedas <ul><li>Devolver-cambio (P: integer; C: array [1..N] of integer; var X: array [1..N] of integer); </li></ul><ul><li>act = 0 </li></ul><ul><li>para i = 1,2,...,N </li></ul><ul><li> X[i] = 0 </li></ul><ul><li>mientras act  P </li></ul><ul><li> j = el mayor elemento de C tal que C[j]  (P - act) </li></ul><ul><li> si j=0 then { Si no existe ese elemento } </li></ul><ul><li>devolver “No existe solución”; </li></ul><ul><li> X[j] = (P - act) div C[j] </li></ul><ul><li> act = act + C[j]*X[j] </li></ul>
  8. 8. Problema del cambio de monedas <ul><li>Para este sistema monetario encuentra siempre la solución óptima. </li></ul><ul><li>Puede no encontrar la solución óptima: supongamos que tenemos monedas de 100, 90 y 1. Queremos devolver 180. </li></ul><ul><ul><li>Algoritmo voraz: 1 moneda de 100 y 80 monedas de 1: total 81 monedas. </li></ul></ul><ul><ul><li>Solución óptima: 2 monedas de 90: total 2 monedas. </li></ul></ul><ul><li>Puede haber solución y no encontrarla. </li></ul><ul><li>Puede no haber solución y no lo detecta. </li></ul>
  9. 9. Análisis de tiempos de ejecución <ul><li>El orden de complejidad depende del número de candidatos, de las funciones básicas a utilizar, del número de elementos de la solución. </li></ul><ul><li>N : número de elementos de C. M : número de elementos de una solución. </li></ul><ul><li>Repetir, como máximo N veces y como mínimo M: </li></ul><ul><ul><li>Comprobar si el valor actual es solución: f(M). Normalmente O(1) ó O(M). </li></ul></ul><ul><ul><li>Selección de un elemento entre los candidatos: g(N). Entre O(1) y O(N). </li></ul></ul><ul><ul><li>La función factible es parecida a solución , pero con una solución parcial h(M). </li></ul></ul><ul><ul><li>La unión de un nuevo elemento a la solución puede requerir otras operaciones de cálculo, j(N, M). </li></ul></ul><ul><li>Tiempo de ejecución genérico : t(N,M)  O(N*(f(M)+g(N)+h(M))+M*j(N, M)) </li></ul><ul><li>En la práctica los algoritmos voraces suelen ser bastante rápidos , encontrándose dentro de órdenes de complejidad polinomiales . </li></ul>
  10. 10. <ul><li>Tenemos n objetos, cada uno con un peso ( w i ) y un beneficio ( v i ). También tenemos una mochila en la que podemos meter objetos, con una capacidad de peso máximo M . (Supondremos todos los valores > 0) </li></ul><ul><li>El objetivo es llenar la mochila, maximizando el valor de los objetos transportados, y respetando la limitación de capacidad máxima M . </li></ul><ul><li>Supondremos que los objetos se pueden partir. De cada objeto i podremos coger un fracción x i , entre 0 y 1. </li></ul><ul><li>Una solución será de la forma S = (x 1 , x 2 , ..., x n ), cumpliendo: </li></ul>Problema de la mochila
  11. 11. Problema de la mochila <ul><li>Ejemplo: n = 3; M = 20 </li></ul><ul><ul><li>w = (18, 15, 10) </li></ul></ul><ul><ul><li> v = (25, 24, 15) </li></ul></ul><ul><ul><li>Solución 1 : S = (1, 2/15, 0), Valor total = 25 + 24*2/15 = 28.2 </li></ul></ul><ul><ul><li>Solución 2 : S = (0, 2/3, 1), Valor total = 15 + 24*2/3 = 31 </li></ul></ul><ul><li>Diseño de la solución. Podemos utilizar un algoritmo voraz para resolver el problema. </li></ul><ul><ul><li>Candidatos : Cada uno de los n objetos de partida. </li></ul></ul><ul><ul><li>Función solución : Tendremos una solución si hemos introducido en la mochila el peso máximo M (o si se han acabado los objetos). </li></ul></ul><ul><ul><li>Función seleccionar : Escoger el objeto más “prometedor”. </li></ul></ul><ul><ul><li>Función factible : Será siempre cierta (podemos añadir trozos de objetos). </li></ul></ul><ul><ul><li>Añadir a la solución: Añadir el objeto entero si cabe en la mochila, o en otro caso la proporción del mismo que quede para completarla. </li></ul></ul><ul><ul><li>Función objetivo : Suma de los beneficios de cada candidato por la proporción seleccionada del mismo. </li></ul></ul>
  12. 12. Problema de la mochila <ul><li>Mochila (M: integer; V, W: array [1..N] of integer; var X: array [1..N] of integer); </li></ul><ul><li>para i = 1,2,...,N </li></ul><ul><li> X[i] = 0 </li></ul><ul><li>peso_act = 0 </li></ul><ul><li>mientras peso_act < M </li></ul><ul><li> j = el mejor objeto restante </li></ul><ul><li> si peso_act + W[i]  M </li></ul><ul><li>X[i] = 1 </li></ul><ul><li>peso_act = peso_act + W[i] </li></ul><ul><li> en otro caso </li></ul><ul><li>X[i] = (M - peso_act)/W[i] </li></ul><ul><li>peso_act = M </li></ul><ul><li> </li></ul>
  13. 13. Problema de la mochila <ul><li>Criterios para seleccionar el mejor objeto de los restantes: </li></ul><ul><ul><li>1. El objeto con más beneficio v i . </li></ul></ul><ul><ul><li>2. El objeto menos pesado w i (para poder añadir muchos objetos). </li></ul></ul><ul><ul><li>3. El objeto con mejor proporción v i /w i (coste por unidad de peso). </li></ul></ul><ul><li>El criterio 3 obtiene siempre la solución óptima. </li></ul>
  14. 14. Secuenciamiento de trabajos <ul><li>Tenemos n tareas requieren un tiempo unitario en ejecutarse, y un único procesador donde ejecutarlas. </li></ul><ul><li>En cualquier instante T = 1, 2, ... podemos ejecutar una única tarea i . La ejecución de esta tarea provocará un beneficio g i . </li></ul><ul><li>Restricción : una tarea i sólo puede ejecutarse si se hace antes de un plazo d i . Cada tarea tiene un plazo de ejecución y un beneficio dados. </li></ul><ul><li>En general puede que no sea posible ejecutar todas las tareas. </li></ul><ul><li>Objetivo: dar una planificación de las tareas a ejecutar (i 1 , i 2 , ..., i m ) de forma que se maximice el beneficio obtenido: </li></ul>
  15. 15. Secuenciamiento de trabajos <ul><li>Ejemplo : n = 4 </li></ul><ul><ul><li>g = (100, 10, 15, 27) </li></ul></ul><ul><ul><li>d = ( 2, 1, 2, 1) </li></ul></ul><ul><ul><li>Soluciones: </li></ul></ul><ul><ul><li>(1) G TOTAL = 100 (2, 1) G TOTAL = 110 </li></ul></ul><ul><ul><li>(4, 3) G TOTAL = 42 (4, 1) G TOTAL = 127 </li></ul></ul><ul><li>Comprobar todas las posibilidades tendría una complejidad n! </li></ul><ul><li>Con un algoritmo voraz construimos la solución paso a paso. </li></ul><ul><li>Una solución estará formada por un conjunto de candidatos, junto con un orden de ejecución de los mismos, S = (i 1 , i 2 , ..., i m ). </li></ul><ul><li>Función solución : Tendremos la solución cuando hayamos tratado todos los candidatos. </li></ul><ul><li>Función de selección : de los candidatos restantes elegir el que tenga mayor valor de beneficio. </li></ul><ul><li>Solución (1,3) no óptima. </li></ul>
  16. 16. Secuenciamiento de trabajos <ul><li>Función factible : Dada una planificación (i 1 , i 2 , ..., i k ) en un paso del algoritmo y un nuevo candidato j, </li></ul><ul><ul><li>¿Cuándo será factible la solución parcial que incluye a j? </li></ul></ul><ul><ul><li>¿Dónde debería ser colocado j dentro de la planificación? </li></ul></ul><ul><li>Solución : buscar si existe alguna ordenación de {i 1 , i 2 , ..., i k , j} que respete los plazos de ejecución d i . Problema: complejidad (k+1)! </li></ul><ul><li>Parece lógico no comprobar todas las posibles ordenaciones, sino hacer una ordenación de forma que las tareas con plazos d i más tempranos se ejecuten antes, y dejar para después las que tengan plazos mayores. </li></ul><ul><li>Lema: Sea J un conjunto de k tareas, entonces existe una ordenación factible de J (es decir que respeta los plazos) sí y sólo sí la ordenación S = (s 1 , s 2 , ..., s k ), con d s1  d s2  ...  d sk es factible. </li></ul><ul><li>Es decir, sólo es necesario probar la planificación en orden creciente de plazo de ejecución. </li></ul>
  17. 17. Secuenciamiento de trabajos <ul><li>Estructura del algoritmo voraz: </li></ul><ul><ul><li>Empezar con una secuencia vacía, con todos las tareas como candidatas. </li></ul></ul><ul><ul><li>Ordenar los candidatos según el valor de g i . </li></ul></ul><ul><ul><li>En cada paso, hasta que se acaben los candidatos, repetir: </li></ul></ul><ul><ul><ul><li>Elegir entre los candidatos restantes el que tenga mayor beneficio. </li></ul></ul></ul><ul><ul><ul><li>Comprobar si es posible añadir la tarea elegida a la solución actual. Para ello introducir la nueva tarea en la posición adecuada, según el valor de plazo d. </li></ul></ul></ul><ul><ul><ul><li>Si el nuevo orden (s 1 , s 2 , ..., s k ) es tal que d si  i, para todo i entre 1 y k, entonces el nuevo candidato es factible. Sino rechazar el candidato. </li></ul></ul></ul>
  18. 18. Secuenciamiento de trabajos <ul><li>Trabajos(in d:array[1..n] of real; out s:array[0..n] of 0..n) </li></ul><ul><li>d[0] = 0 ; s[0] = 0 ; k = 1 ; s[1] = 1 </li></ul><ul><li>para i = 2,3,..,n </li></ul><ul><li>r = k </li></ul><ul><li>mientras d[s[r]]>d[i] y d[s[r]]  r </li></ul><ul><li>r = r-1 </li></ul><ul><li>finmientras </li></ul><ul><li>si d[s[r]]  d[i] y d[i]>r </li></ul><ul><li>para l = k,k-1,..,r+1 </li></ul><ul><li>s[l+1] = s[l] </li></ul><ul><li>finpara </li></ul><ul><li>s[r+1] = i </li></ul><ul><li>k = k+1 </li></ul><ul><li>finsi </li></ul><ul><li>finpara </li></ul>
  19. 19. Secuenciamiento de trabajos <ul><li>Orden de complejidad del algoritmo, suponiendo n tareas: </li></ul><ul><ul><li>Primero, ordenar las tareas por orden creciente de plazo: O(n·log n) </li></ul></ul><ul><ul><li>Repetir para i desde 1 hasta n: </li></ul></ul><ul><ul><ul><li>Elegir el próximo candidato: O(1). </li></ul></ul></ul><ul><ul><ul><li>Comprobar si la nueva planificación es factible, y añadirlo a la solución en caso afirmativo: O(i) en el peor caso. </li></ul></ul></ul><ul><ul><ul><li>En total, el algoritmo es de O(n 2 ). </li></ul></ul></ul><ul><ul><li>En promedio es una ordenación por inserción:  (n 2 ). </li></ul></ul>
  20. 20. Técnicas heurísticas <ul><li>Existen muchos problemas para los cuales no se conocen algoritmos que puedan encontrar la solución de forma eficiente: problemas NP-completos . </li></ul><ul><li>La solución exacta puede requerir un orden factorial o exponencial: el problema de la explosión combinatoria. </li></ul><ul><li>Se hace necesario utilizar algoritmos heurísticos: </li></ul><ul><li>Un algoritmo heurístico (o simplemente heurística ) puede producir una buena solución (puede que la óptima) pero también puede que no produzca ninguna solución o dar una solución no muy buena. Normalmente, se basa en un conocimiento intuitivo del programador sobre un determinado problema. </li></ul><ul><li>La estructura de algoritmo voraz se puede utilizar para construir procedimientos heurísticos: hablamos de heurísticas voraces . </li></ul><ul><li>Objetivo: obtener buenas soluciones en un tiempo de ejecución corto. </li></ul>
  21. 21. <ul><li>Problema: Dado un grafo no dirigido y con pesos G = (V, A), encontrar un ciclo simple de costo mínimo que pase por todos los nodos. </li></ul>El problema del viajante <ul><li>Es un problema NP, pero necesitamos una solución eficiente. </li></ul><ul><li>Problema de optimización, donde la solución está formada por un grupo de elementos en cierto orden: podemos aplicar el esquema voraz. </li></ul><ul><li>Posibilidades : </li></ul><ul><ul><li>1) Los nodos son los candidatos. Empezar en un nodo cualquiera. En cada paso moverse al nodo no visitado más próximo al último nodo seleccionado. </li></ul></ul><ul><ul><li>2) Las aristas son los candidatos, pero garantizando que se forme un ciclo. </li></ul></ul>15 30 20 25 50 45 10 35 40 55 5 4 3 1 2
  22. 22. El problema del viajante <ul><li>Heurística voraz 1) </li></ul><ul><ul><li>Una solución será un cierto orden en el conjunto de nodos (c 1 , c 2 , ..., c n ): el orden de visita de los nodos. </li></ul></ul><ul><ul><li>Inicialización : seleccionar un nodo cualquiera. </li></ul></ul><ul><ul><li>Función de selección : de los nodos candidatos seleccionar el más próximo al último (o al primero) de la secuencia actual (c 1 , c 2 , ..., c a ). </li></ul></ul><ul><ul><li>Acabamos cuando tengamos n nodos. </li></ul></ul><ul><li>Ejemplo. </li></ul><ul><li>Empezando en el nodo 1. </li></ul><ul><li>Solución: (1, 4, 5, 3, 2) </li></ul><ul><li>Coste: 30+15+25+10+45=125 </li></ul><ul><li>Empezando en el nodo 3. </li></ul><ul><li>Solución: (5, 4, 3, 2, 1) </li></ul><ul><li>Coste: 15+20+10+45+50=140 </li></ul>2 3 4 1 5 15 30 25 45 10 2 3 4 1 5 15 20 50 45 10
  23. 23. El problema del viajante <ul><li>Heurística voraz 2) </li></ul><ul><ul><li>Una solución será un conjunto de aristas (a 1 , a 2 , ..., a n-1 ) que formen un ciclo hamiltoniano, sin importar el orden. </li></ul></ul><ul><ul><li>Empezar con un grafo sin aristas. </li></ul></ul><ul><ul><li>Selección : seleccionar la arista candidata de menor coste. </li></ul></ul><ul><ul><li>Factible : una arista se puede añadir a la solución actual si no se forma un ciclo (excepto para la última arista añadida) y si los nodos unidos no tienen grado mayor que 2. </li></ul></ul><ul><li>Ejemplo. </li></ul><ul><li>Solución: ((2, 3), (4, 5), (3, 4), (1, 2), (1, 5)) </li></ul><ul><li>Coste = 10+15+20+45+50 = 140 </li></ul><ul><li>Conclusiones: </li></ul><ul><ul><li>Ninguno de las dos funciones de selección garantiza una solución óptima. Sin embargo, normalmente ambos dan soluciones buenas, próximas a la óptima. </li></ul></ul><ul><ul><li>Posibles mejoras: buscar heurísticas mejores; repetir la heurística 1 con varios orígenes; o bien, a partir de la solución del algoritmo intentar hacer modificaciones locales para mejorar esa solución: búsqueda local . </li></ul></ul>2 3 4 1 5 15 20 50 45 10
  24. 24. Coloración de grafos <ul><li>Problema: dado un grafo no dirigido, realizar una coloración utilizando el número mínimo de colores. </li></ul><ul><li>Coloración: asignación de un color a cada nodo, de forma que dos nodos unidos con un arco tengan siempre distinto color. </li></ul><ul><li>Una solución será un conjunto de pares de la forma (nodo, color) cumpliendo que para todo (n i , c i ) y (n j , c j ), si (n i , n j ) es una arista del grafo, entonces c i  c j . </li></ul><ul><li>Podemos usar una heurística voraz para obtener una solución: </li></ul><ul><ul><li>Empezar con un color c 1 , y todos los nodos sin colorear. </li></ul></ul><ul><ul><li>Para cada uno de los nodos que no tienen asignado un color, comprobar si es posible asignarles el color actual. Repetir hasta comprobar todos los candidatos. </li></ul></ul><ul><ul><li>Si quedan nodos sin colorear, escoger otro color y volver al paso anterior. </li></ul></ul>1 2 5 4 3
  25. 25. Coloración de grafos <ul><li>Ejemplo. </li></ul><ul><li>Solución: ((1, 1), (2, 1), (3, 2), (4, 3), (5, 3)) </li></ul><ul><li>Número de colores = 3 </li></ul><ul><li>La estructura básica del esquema voraz se repite varias veces, una por cada color, hasta que todos los nodos estén coloreados. </li></ul><ul><li>Función de selección : seleccionar cualquier candidato restante. </li></ul><ul><li>Función factible : se puede asignar un color al candidato actual si ninguno de sus adyacentes tiene ese mismo color. </li></ul><ul><li>El algoritmo no garantiza la solución óptima (en el ejemplo 2 colores). </li></ul><ul><li>¿Cuál será el tiempo de ejecución en el peor caso? </li></ul>1 2 5 4 3 1 2 5 4 3

×