Algoritmo Modificado De Corrección De Etiquetas.

Preview only show first 6 pages with water mark for full document please download

Transcript

CO-5422 (F09) 27/11/2009 58 Complejidad: Como un valor finito de d(j) está acotado entre −nC y nC (la cota superior queda como ejercicio, se sugiere hacerlo por inducción en el tamaño del árbol T ), el algoritmo actualiza cada etiqueta a los sumo 2nC veces (datos enteros). En consecuencia el número total de actualizaciones está acotado por 2n2C. No podemos mejorarla pues carecemos de información. Esta complejidad se puede mejorar, modificando el algoritmo. Algoritmo modificado de corrección de etiquetas. La idea es encontrar un método de seleccionar el arco que viola HC que resulte en un algoritmo más eficiente (hasta ahora no se ha usado ninguna información). Una forma es mantener una lista de arcos candidatos a violar la condición (la lista contiene a todos los que violan la condición, pero puede contener “inocentes”). Se selecciona un arco (i, j) de la lista y, si éste viola la condición, se actualiza la etiqueta de j y se saca el arco de la lista. Al reducir una etiqueta d(j), los arcos (j, k) en A(j) son buenos candidatos a violar la condición de optimalidad (recordar cjk + d(j) − d(k)). Los que entran a j no violarán la condición si no lo hacían antes (en cuyo caso ya estaban en la lista de candidatos). Y esos son todos los que varían. Una buena forma de llevar esto a cabo es usar una lista de nodos, en vista de que ya tenemos almacenadas sus A (·) (en estrella, por ejemplo), en lugar de crear una nueva lista de arcos. En efecto, se guarda una lista de nodos que cumple que si un arco (i, j) viola HC, entonces el nodo salida i debe estar en la lista. De nuevo, puede haber nodos que no tengan “culpables” en su lista de adyacencia, pero ningún nodo que los tenga estará fuera. El algoritmo modificado queda: algoritmo modificado de corrección de etiquetas; begin d(s) := 0; pred (s) := 0; d(j) := +∞, j ∈ N \ {s}; LIST := {s} ; while (LIST 6= ∅) do begin quitar un nodo i de LIST ; for each (i, j) ∈ A (i) do if d(j) > d(i) + cij then begin d(j) := d(i) + cij; pred (j) := i; if j ∈ / LIST then añadir j a LIST ; end if end while end Este algoritmo cumple con la propiedad de que LIST contiene todo nodo i incidente a un arco (i, j) que viole HC (¡perdonen la insistencia!). Ejemplo (a ser agregado luego). CO-5422 (F09) 27/11/2009 59 Complejidad: Al actualizar d(j) se añade el nodo j a LIST . Luego eventualmente se selecciona j y se revisa A(j). Como cada actualización de d(j) ocurre a lo sumo 2nC veces se obtiene X 2nC |A(i)| = O(nmC) i∈N la cual todavía depende de C y no mejora la del algoritmo genérico. Sin embargo, nos pone en la ruta de implementaciones que sí lo hacen. Implementaciones: De nuevo, se trata de mejorar la complejidad práctica (y teórica) de este algoritmo. La primera idea es mantener LIST como una cola. Con esto se logra un tiempo de ejecución de O (mn) que es el mejor para este tipo de algoritmo, la eficiencia empírica es también muy buena. Con una pequeña modificación (usando una de-cola, se discrimina entre nodos previamente “atendidos” y los nuevos, como en un banco) se logra un excelente comportamiento empírico, aunque la complejidad teórica es mala. Los algoritmos que mejor se han comportado en la práctica para problemas arbitrarios, han sido implementaciones ingeniosas de este simple algoritmo de corrección de etiquetas. Se sugiere ver tabla al final del capítulo 5 de Ahuja, Magnanti y Orlin (p.155). Detección de ciclos negativos: La forma más obvia: Detectar si alguna etiqueta baja de −nC. Si esto ocurre para un nodo k, la detección del ciclo se logra iterando pred desde k. Hay otras formas ligeramente más complicadas que se pueden incorporar al algoritmo (genérico o modificado).