12.07.2015 Views

Cap. 4 Complejidad temporal de algoritmos - Inicio

Cap. 4 Complejidad temporal de algoritmos - Inicio

Cap. 4 Complejidad temporal de algoritmos - Inicio

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>Cap</strong>ítulo 4.1<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong>.4.1. Tiempo <strong>de</strong> ejecución y tamaño <strong>de</strong> la entrada.Se <strong>de</strong>sea tener una medida <strong>de</strong> la duración <strong>de</strong>l tiempo <strong>de</strong> ejecución <strong>de</strong> un algoritmo en función<strong>de</strong>l tamaño <strong>de</strong> la entrada.A través <strong>de</strong> llamados al sistema operativo se pue<strong>de</strong> conocer el valor <strong>de</strong>l reloj <strong>de</strong> tiempo real.Invocando al reloj, antes y <strong>de</strong>spués <strong>de</strong> realizar el algoritmo se tendrá una medida <strong>de</strong> la duración<strong>de</strong>l tiempo <strong>de</strong> ejecución. Sin embargo esta medida es muy <strong>de</strong>pendiente <strong>de</strong>l hardware (memoria,reloj, procesador), <strong>de</strong>l sistema operativo (multitarea, multiusuario) y pue<strong>de</strong> variarsignificativamente <strong>de</strong>pendiendo <strong>de</strong>l computador, <strong>de</strong>l compilador, y <strong>de</strong> la carga <strong>de</strong>l sistema. Aldisponer <strong>de</strong> sistemas con multiprocesadores o que la ejecución sea distribuida también afectamedir el tiempo con cronómetro.Por la razón anterior como una medida <strong>de</strong>l tiempo <strong>de</strong> ejecución, se consi<strong>de</strong>ra contar lasinstrucciones <strong>de</strong>l lenguaje <strong>de</strong> alto nivel que son necesarias realizar.El tamaño <strong>de</strong> la entrada <strong>de</strong>be ser precisado con más <strong>de</strong>talle. Podría ser el número <strong>de</strong> bits quemi<strong>de</strong>n la información que el algoritmo procesa, pero en forma tradicional se consi<strong>de</strong>ra elnúmero <strong>de</strong> elementos o componentes básicas que son sometidos al proceso.Por ejemplo si tenemos un arreglo <strong>de</strong> n componentes, y el algoritmo tiene por objetivo, sumarlos valores <strong>de</strong> las componentes, o bien or<strong>de</strong>nar las componentes, se suele <strong>de</strong>cir que n es eltamaño <strong>de</strong> la entrada. In<strong>de</strong>pendientemente si el arreglo es <strong>de</strong> enteros, o <strong>de</strong> estructuras.4.2. <strong>Complejidad</strong> <strong>temporal</strong>. Definición.Se <strong>de</strong>nomina complejidad <strong>temporal</strong> a la función T(n) que mi<strong>de</strong> el número <strong>de</strong> instruccionesrealizadas por el algoritmo para procesar los n elementos <strong>de</strong> entrada.Cada instrucción tiene asociado un costo <strong>temporal</strong>.Afecta al tiempo <strong>de</strong> ejecución el or<strong>de</strong>n en que se procesen los elementos <strong>de</strong> entrada.Podría consi<strong>de</strong>rarse que los valores <strong>de</strong> los n casos que se presentan como entrada son loscorrespondientes: a un caso típico, o a un caso promedio, o <strong>de</strong> peor caso. El peor caso es el mássencillo <strong>de</strong> <strong>de</strong>finir (el que <strong>de</strong>more más para cualquier entrada), pero si se <strong>de</strong>sea otros tipos <strong>de</strong>entrada habría que <strong>de</strong>finir qué se consi<strong>de</strong>ra típico, o la distribución <strong>de</strong> los valores en el casopromedio.Profesor Leopoldo Silva Bijit 20-01-2010


2 Estructuras <strong>de</strong> Datos y Algoritmos4.3. Tipos <strong>de</strong> funciones.Las funciones <strong>de</strong> n pue<strong>de</strong>n ser <strong>de</strong> diferente tipo:Funciones constantes: f(n) = 5, o bien g(n) =10.Funciones logarítmicas: f(n) = log (n), o bien g(n) = nlog(n)Funciones polinomiales: f(n) = 2 n 2 , o bien g(n) = 8 n 2 + 5 nFunciones exponenciales: f(n) = 2 n , o bien g(n) = 2 5n .O mezclas <strong>de</strong> las anteriores, o cualquier función <strong>de</strong> n en un caso general.En general, a medida que aumenta n, las exponenciales son mayores que las polinomiales; a suvez éstas son mayores que las logarítmicas, que son mayores que las constantes.4.4. Acotamiento <strong>de</strong> funciones.Veremos algunas <strong>de</strong>finiciones que permiten clasificar las funciones por su or<strong>de</strong>n <strong>de</strong> magnitud.Interesa encontrar una cota superior <strong>de</strong> la complejidad <strong>temporal</strong>. Consi<strong>de</strong>remos la siguiente<strong>de</strong>finición preliminar <strong>de</strong> la función O mayúscula (big oh), con la intención <strong>de</strong> clasificarfunciones polinomiales.Se dice que T(n) es O(n i ) , si existen c y k tales que: T(k) =1,43764n 32n 3(n+1) 2Figura 4.1. T(n) es O(n 3 ).Se advierte que T(n) queda acotada por arriba por 2n 3 para n>1.5. Entonces T(n) es O(n 3 ).Profesor Leopoldo Silva Bijit 20-01-2010


4 Estructuras <strong>de</strong> Datos y AlgoritmosSi seguimos disminuyendo c, por ejemplo 1.1, T(n) queda acotada para n>20,48.Consi<strong>de</strong>rando los casos anteriores, una mejor <strong>de</strong>finición <strong>de</strong> la función O es la siguiente:Se dice que T(n) es O(n i ) , si existen c y n 0 tales que: T(n) =n 0Intentemos probar que: T(n) = 3n 3 + 2 n 2 es O(n 3 )Debemos encontrar un c que cumpla: 3n 3 + 2 n 2 =1. Por lo tanto c=5 y n 0 =1.Debido a que existen c y n 0 , T(n) es O(n 3 )La generalización para otro tipo <strong>de</strong> funciones se logra, con la siguiente <strong>de</strong>finición.4.5. Función O.Se dice que T(n) es O( f(n) ) , si existen c y n 0 tales que: T(n) =n 0Sin embargo se necesita un mejor concepto para acotar el or<strong>de</strong>n o magnitud <strong>de</strong> una función.Esto consi<strong>de</strong>rando el primer ejemplo, en el que se podía <strong>de</strong>cir que T(n) era O(n 3 ) y también queera O(n 2 ).4.6. Función .Una mejor <strong>de</strong>finición para acotar funciones, es la función que <strong>de</strong>fine simultáneamente cotassuperior e inferior para T(n).Se dice que T(n) es ( f(n) ) , si existen c 1 , c 2 y n 0 tales que:c 1 f(n)


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 5La <strong>de</strong>finición <strong>de</strong> encuentra una f(n) que acota tipo sándwich a la función T(n).Cuando empleemos a lo largo <strong>de</strong>l texto la notación O, realmente estamos refiriéndonos a la<strong>de</strong>finición <strong>de</strong> .4.7. Costo unitario.Aplicando la <strong>de</strong>finición pue<strong>de</strong> comprobarse que las funciones constantes tienen complejidadO(1).Ejemplo. Sea T(n) = 5.Se pue<strong>de</strong> escribir: c 1 *1 =n 0 se tiene: T(n) = T 1 (n) + T 2 (n) g(n)Entonces el lado <strong>de</strong>recho <strong>de</strong> la relación (1):c 1 f(n) + c 2 g(n) = (c 1 +c 2 )f(n) - c 2 ( f(n) - g(n) )Y como c 2 ( f(n) - g(n) ) es positivo, se pue<strong>de</strong> escribir:c 1 f(n) + c 2 g(n) < = (c 1 +c 2 )f(n)Profesor Leopoldo Silva Bijit 20-01-2010


6 Estructuras <strong>de</strong> Datos y AlgoritmosCaso b) Sea f(n) < g(n)Entonces el lado <strong>de</strong>recho <strong>de</strong> la relación (1):c 1 f(n) + c 2 g(n) = (c 1 +c 2 )g(n) – c 1 ( g(n) - f(n) )Y como c 1 ( g(n) - f(n) ) es positivo, se pue<strong>de</strong> escribir:c 1 f(n) + c 2 g(n) < = (c 1 +c 2 )g(n)De los dos resultados anteriores, se obtiene la <strong>de</strong>sigualdad:T(n) = T 1 (n) + T 2 (n) g, entonces: O( f + g ) es O(f).Ejemplo:O( n 2 + n ) = O (n 2 ) para valores <strong>de</strong> n tales que n 2 > n.4.9. Regla <strong>de</strong> productos.Si T 1 (n) es O(f(n)) y T 2 (n) es O(g(n)) entonces: T 1 (n)T 2 (n) es O( f(n) g(n) ).Demostración.Por <strong>de</strong>finición:T 1 (n) = n 1T 2 (n) = n 2Sea n 0 = max(n 1 , n 2 )Para n>=n 0 se tiene: T(n) = T 1 (n) T 2 (n) =n 0 .Ejemplos:O( 3 n 2 ) = O (n 2 ) ya que 3 es O(1), y n 2 es O(n 2 ).La regla <strong>de</strong>l producto también pue<strong>de</strong> aplicarse en: n*O( n ) = O (n 2 )Si c es una constante y n el tamaño <strong>de</strong> la entrada:O(c) = c*O(1) = O(1)O(cn) = c*O(n) = O(n)4.10. Regla <strong>de</strong> alternativa.if (c) a1; else a2;Profesor Leopoldo Silva Bijit 20-01-2010


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 7En cálculos <strong>de</strong> peor caso se toma la complejidad <strong>de</strong> la acción <strong>de</strong> mayor or<strong>de</strong>n. Luego seconsi<strong>de</strong>ra la regla <strong>de</strong> sumas para el cálculo <strong>de</strong> la condición y la acción.Consi<strong>de</strong>rando <strong>de</strong> costo unitario el cálculo <strong>de</strong> la condición, la Figura 4.5 muestra la complejidad<strong>de</strong> la sentencia if.Sentencia IfO(1)O( f ( n ))O( g( n))O(max{ f ( n), g( n)})4.11. Regla <strong>de</strong> iteración.Figura 4.5. Costo <strong>de</strong> alternativa.for ( i=0; i< n; i++) a;Por regla <strong>de</strong> sumas se tiene n veces la complejidad <strong>temporal</strong> <strong>de</strong> la acción a.Si la acción <strong>de</strong>l bloque a es O(1) entonces el for es <strong>de</strong> complejidad n*O(1) = O(n)La Figura 4.6, consi<strong>de</strong>ra costos unitarios para la inicialización, reinicio, y cálculo <strong>de</strong> lacondición; la complejidad <strong>de</strong>l bloque es O(f(n)); el número <strong>de</strong> veces es <strong>de</strong> complejidad O(g(n)).Sentencia ForO(1)Sentencia WhileO(1)O(1)O( g( n))O( f ( n))O(1)O( g( n))O( f ( n))O( g( n) f ( n))O( g( n) f ( n))Figura 4.6. Costo <strong>de</strong> lazo for y while.Profesor Leopoldo Silva Bijit 20-01-2010


8 Estructuras <strong>de</strong> Datos y AlgoritmosEjemplo 4.1.Se tienen tres for anidados:for (i=1; i


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 9Es <strong>de</strong>cir el algoritmo aplicado a una entrada <strong>de</strong> tamaño n, pue<strong>de</strong> <strong>de</strong>scomponerse en un problema<strong>de</strong> la mitad <strong>de</strong>l tamaño. El costo <strong>de</strong> la <strong>de</strong>scomposición es una constante <strong>de</strong> valor c.Para resolver una relación <strong>de</strong> recurrencia es preciso conocer el costo para una entrada dada; eneste caso para entrada unitaria el costo es la constante c.Otra forma <strong>de</strong> visualizar el tipo <strong>de</strong> solución que da el algoritmo al problema anterior, esconsi<strong>de</strong>rar que en cada pasada se <strong>de</strong>scarta la mitad <strong>de</strong> los datos <strong>de</strong> entrada.Si a partir <strong>de</strong>l caso conocido se van evaluando casos más complejos, pue<strong>de</strong>n obtenerse:T(1) = c = c = 0 + cT(2) = T(1) + c = 2c = c + cT(4) = T(2) + c = 3c = 2c + cT(8) = T(4) + c = 4c = 3c + cT(16) = T(8) + c = 5c = 4c + cT(2 i ) = T(2 i-1 ) + c = (i+1)c= ic + c = c( i+1)Nótese que se han evaluado en números que son potencias <strong>de</strong> dos, para obtener con facilidaduna expresión para el término general.Con 2 i = n, se tiene sacando logaritmo <strong>de</strong> dos en ambos lados:log 2 (2 i ) = log 2 (n), pero log 2 (2 i ) = i log 2 (2) = i. Resultando i = log 2 (n).Reemplazando en el término general resulta: T(n) = c(log 2 (n) +1)2log 2 (n)c(log 2 (n) +1)log 2 (n)n 0Figura 4.7. T(n) = c(log 2 (n) +1) es O( log 2 (n) )Las gráficas <strong>de</strong> la Figura 4.7, muestran que para T(n) existen c 1 y c 2 que la acotan por encima ypor <strong>de</strong>bajo, para n> 2,2. Finalmente, se tiene que la solución <strong>de</strong> la ecuación <strong>de</strong> recurrencia es:Profesor Leopoldo Silva Bijit 20-01-2010


10 Estructuras <strong>de</strong> Datos y AlgoritmosT(n) = O( log 2 (n) )Las gráficas comparan el costo lineal versus el logarítmico.O(n)O(log 2 (n))Figura 4.8 Costo lineal versus costo logarítmico.Ejemplo 4.2. Evaluando la complejidad en función <strong>de</strong>l tiempo.Si T(n) refleja el número <strong>de</strong> instrucciones <strong>de</strong> costo unitario que <strong>de</strong>ben realizarse para resolverpara n entradas, pue<strong>de</strong> tenerse una medida en unida<strong>de</strong>s <strong>de</strong> tiempo conociendo el valoraproximado <strong>de</strong> la duración <strong>de</strong> una instrucción.Si O(1) es equivalente a 1 [seg], se pue<strong>de</strong> construir la siguiente tabla, en cada columna se tieneuna complejidad <strong>temporal</strong> diferente:n 3n 2 + 7n n 2 n log 2 n100 0,03 [seg] 0,01 [seg] 6,6 [mseg]10.000 5 [minutos] 1,7 [minutos] 133 [mseg]100.000 8 [horas] 3 [horas] 1,66[seg]1.000.000 35 [días] 12 [días] 6 [seg]Figura 4.9 Costo <strong>temporal</strong>.Usando teoremas sobre comparación <strong>de</strong> funciones, se tiene que: O(3n 2 + 7n) = O(n 2 ).La tabla muestra que las complejida<strong>de</strong>s <strong>de</strong> los dos <strong>algoritmos</strong> cuadráticos son comparables en elor<strong>de</strong>n <strong>de</strong> magnitud.Ejemplo 4.3. Aplicación a un algoritmo sencillo.Calcular la complejidad <strong>de</strong>l segmento que obtiene el mínimo elemento <strong>de</strong> un arreglo.min = A[0];Profesor Leopoldo Silva Bijit 20-01-2010


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 11for(i=1; i


12 Estructuras <strong>de</strong> Datos y Algoritmos4.13. Búsqueda secuencial.La búsqueda secuencial compara la clave con cada una <strong>de</strong> las componentes. La primera vez queencuentre un elemento <strong>de</strong>l arreglo igual al valor buscado se <strong>de</strong>tiene el proceso. No encuentraclaves repetidas y no se requiere que el arreglo esté or<strong>de</strong>nado.Si lo recorre en su totalidad, cuidando <strong>de</strong> no exce<strong>de</strong>r los rangos <strong>de</strong>l arreglo, y no lo encuentra<strong>de</strong>be indicarlo con algún valor específico <strong>de</strong> retorno. En el diseño se consi<strong>de</strong>ra retornar el índice<strong>de</strong> la componente que cumple el criterio <strong>de</strong> búsqueda, se <strong>de</strong>ci<strong>de</strong> entonces que un retorno convalor -1 (ya que no es un índice válido), indicará que el valor buscado no fue hallado.Indice BusquedaSecuencial(Tipo A[], Indice Inf, Indice Sup, Tipo Clave){ Indice i;for(i = Inf; i


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 13El costo, en un arreglo con una componente, es constante; es <strong>de</strong>cir T(1) = O(1). La solución <strong>de</strong>esta ecuación <strong>de</strong> recurrencia es: T(n) = O(log(n)).int BusquedaBinaria(Tipo A[], Indice Inf, Indice Sup, Tipo Clave){ Indice M;}while (verda<strong>de</strong>ro){M = (Inf + Sup)/2;if (Clave < A[M])Sup = M - 1;else if (Clave > A[M])Inf = M + 1;else return M;if (Inf > Sup) return (noencontrado) ;}012…….M-1MM+1….….n-3n-2n-1Figura 4.10 Búsqueda binaria.Un aspecto importante <strong>de</strong>l diseño <strong>de</strong> un bloque repetitivo es asegurar que éste termina. Al iniciose tiene que Sup> Inf. Cada vez que Sup disminuye, Inf no cambia; y también cuando Infaumenta Sup no cambia. En ambos casos la condición Inf >Sup cada vez está más cercana acumplirse.Si el valor buscado es menor que el menor valor contenido en el arreglo, <strong>de</strong>spués <strong>de</strong> algunasiteraciones, no importando si n inicialmente es par o impar, se llega a que Inf, Sup y M apuntana la primera componente <strong>de</strong>l arreglo, etapa en la que se compara con la primera componente,produciendo Inf>Sup. Similar situación se produce cuando el valor buscado es mayor que lamayor componente <strong>de</strong>l arreglo. Lo cual verifica que el algoritmo siempre termina en un númerofinito <strong>de</strong> pasos, y que trata bien el caso <strong>de</strong> que la búsqueda falle.Profesor Leopoldo Silva Bijit 20-01-2010


14 Estructuras <strong>de</strong> Datos y Algoritmos4.15. Sobre el costo O(1).Las personas que conocen los <strong>de</strong>talles internos <strong>de</strong> un procesador saben que una suma <strong>de</strong>moramenos que una multiplicación o división; esto si los números son enteros. En el caso <strong>de</strong>flotantes los costos son aún mayores que para enteros.Veamos esto con más <strong>de</strong>talle. Si consi<strong>de</strong>ramos números <strong>de</strong> n bits, y un sumador organizado <strong>de</strong>tal manera que sume primero los bits menos significativos, luego la reserva <strong>de</strong> salida <strong>de</strong> éstosmás los dos bits siguientes; y así sucesivamente. Si se consi<strong>de</strong>ra O(1) el costo <strong>de</strong> la suma <strong>de</strong> unbit, entonces la suma <strong>de</strong> dos enteros <strong>de</strong> n bits será O(n). Esta estructura <strong>de</strong> un sumador conpropagación ondulada <strong>de</strong> la reserva pue<strong>de</strong> mejorarse con circuitos adicionales para generarreservas a<strong>de</strong>lantadas.Un algoritmo primitivo para efectuar multiplicaciones es mediante la suma repetitiva <strong>de</strong> uno <strong>de</strong>los operandos.Por ejemplo el producto <strong>de</strong> dos números <strong>de</strong> 4 bits:0101*1100------0000000001010101-------0111100Esto implica efectuar n sumas si los operandos son <strong>de</strong> n bits. Lo cual implica un costo O(n 2 )para la multiplicación, consi<strong>de</strong>rando que cada suma es <strong>de</strong> costo O(n). Razón por la cual sesuelen diseñar unida<strong>de</strong>s <strong>de</strong> multiplicación, en hardware, con mejores <strong>algoritmos</strong>.En un ambiente <strong>de</strong> microcontroladores o microprocesadores que no tengan implementada laoperación multiplicación o división, pero que si tengan en su repertorio <strong>de</strong> acciones: sumas,restas y <strong>de</strong>splazamientos a la izquierda y <strong>de</strong>recha en un bit, se consi<strong>de</strong>ran esas instrucciones <strong>de</strong>costo O(1); nótese que en el ambiente anterior, la suma era O(n).Consi<strong>de</strong>remos, en este último contexto, dos <strong>algoritmos</strong> para multiplicar:4.17.1. Algoritmos <strong>de</strong> multiplicación./* retorna m*n */unsigned int multipliquelineal(unsigned int m, unsigned int n){ unsigned int r=0;while ( n>0 ){ r+=m; n--; }return(r);}Profesor Leopoldo Silva Bijit 20-01-2010


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 15El bloque se repite n veces, y está constituido por un test <strong>de</strong> condición, una suma y unincremento. Todas operaciones que pue<strong>de</strong>n traducirse a instrucciones <strong>de</strong> máquina, y seconsi<strong>de</strong>ran <strong>de</strong> costo O(1). Entonces esta multiplicación es <strong>de</strong> costo O(n) o lineal./* retorna m*n */unsigned int multipliquelog(unsigned int m, unsigned int n){ unsigned int r=0;}while ( n>0 ){ if(n&1) r+=m;m*=2; n/=2;}return(r);En cada ciclo <strong>de</strong>l while se divi<strong>de</strong> por dos el valor <strong>de</strong> n.La multiplicación por dos, equivale a un corrimiento a la izquierda en una posición; la divisiónpor dos equivale a un corrimiento a la <strong>de</strong>recha en una posición; el test <strong>de</strong>l bit menossignificativo se realiza con una operación and; acumular el producto parcial en la local r, seefectúa con una suma. Todas estas operaciones, en este ambiente se consi<strong>de</strong>ran <strong>de</strong> costoconstante: O(1).El algoritmo pue<strong>de</strong> <strong>de</strong>scribirse según:T(n) = T(n/2) + O(1) con T(1) = O(1).Resultado obtenido antes, como solución <strong>de</strong> una ecuación <strong>de</strong> recurrencia, con costo logarítmico:O(log 2 n); concluyendo que la segunda rutina, es mucho mejor que la primera. Debe notarse queen este ejemplo se emplea el valor <strong>de</strong> uno <strong>de</strong> los operandos como el tamaño <strong>de</strong> la entrada.Dependiendo <strong>de</strong> lo que consi<strong>de</strong>remos como costo unitario, un algoritmo pue<strong>de</strong> tener costos muydiferentes.4.17.2. Algoritmos <strong>de</strong> división.Consi<strong>de</strong>remos un algoritmo primitivo <strong>de</strong> división, basado en restas sucesivas.//Retorna cuociente q y resto r. n = q*d + r. El resto r se pasa por referencia.unsigned int divi<strong>de</strong>lineal(unsigned int n, unsigned int d, unsigned int *r){ unsigned int q=0;}while (n>=d) { n-=d; q++; }*r= n; //escribe el restoreturn(q);En su peor caso, con <strong>de</strong>nominador unitario, y n el máximo representable, se tiene costo: O(n).Profesor Leopoldo Silva Bijit 20-01-2010


16 Estructuras <strong>de</strong> Datos y AlgoritmosEl siguiente algoritmo ha sido tradicionalmente usado en procesadores que no tenganimplementada una unidad <strong>de</strong> multiplicación <strong>de</strong> enteros en hardware.//Retorna cuociente q y resto r. Con n = q*d + r .unsigned int divi<strong>de</strong>log(unsigned int n, unsigned int d, unsigned int *r){ unsigned int dd=d, q=0;*r = n;while (dd d){ dd/=2; q= q*2;if (dd


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 17La cual pue<strong>de</strong> calcularse en forma similar al caso <strong>de</strong> costo logarítmico.T(1) = cT(2) = 2*T(1) + c*2 = 4c = 2c *2T(4) = 2*T(2) + c*4 = 12c = 4c *3T(8) = 2*T(4) + c*8 = 32c = 8c *4T(16) = 2*T(8) + c*16 = 80c = 16c *5T(2 i ) = 2*T(2 i-1 ) + c*2 i = = 2 i c *(i+1)Con 2 i = n, se tiene i = log 2 (n), sacando logaritmo <strong>de</strong> dos en ambos lados.Reemplazando en: T(2 i ) = 2 i c *(i+1)Se obtiene, finalmente:T(n) = n c *( log 2 (n) + 1)La complejidad <strong>temporal</strong> <strong>de</strong> T(n) es ( n log(n) ) para n>=2.Por el teorema <strong>de</strong> los productos, no importa la base <strong>de</strong> los logaritmos.2n(log 2 (n))n(log 2 (n)+1)n(log 2 (n))Figura 4.11 <strong>Complejidad</strong> ( n log(n) ).La gráfica a continuación compara la complejidad cuadrática con la n*log(n).Profesor Leopoldo Silva Bijit 20-01-2010


18 Estructuras <strong>de</strong> Datos y Algoritmosn 2n(log 2 (n))Figura 4.12 ( n log(n) ) versus cuadrática.La cuadrática crece mucho más rápidamente que la n*log(n).La n*log(n) crece mucho más rápidamente que la lineal, lo que se muestra a continuación:n(log 2 (n))nFigura 4.13 ( n log(n) ) versus lineal.Para mayores valores <strong>de</strong> n, se aprecian mejor las diferencias.4.19. Comparación entre complejida<strong>de</strong>s típicas.La siguiente gráfica compara cuatro complejida<strong>de</strong>s usuales.Profesor Leopoldo Silva Bijit 20-01-2010


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 19n 2n(log 2 (n))n(log 2 (n))nlog 2 (n)Figura 4.14 Comparación entre cuatro tipos <strong>de</strong> complejida<strong>de</strong>s.Cuando un programador principiante encuentra que el primer algoritmo que se le ocurrió, pararesolver un problema, es O(n 2 ), es posible que le sorprenda la existencia <strong>de</strong> un algoritmo (queestudiaremos en este texto) <strong>de</strong> complejidad O(nlog(n)).Lo mismo pue<strong>de</strong> <strong>de</strong>cirse <strong>de</strong> primeros intentos <strong>de</strong> diseño <strong>de</strong> <strong>algoritmos</strong> que conducen a uno <strong>de</strong>costo O(n), que pue<strong>de</strong>n ser planteados con complejidad O(log(n)).4.20. Estudio adicional.En los textos <strong>de</strong> referencia existen, normalmente al inicio, capítulos <strong>de</strong>dicados al cálculo <strong>de</strong>complejida<strong>de</strong>s <strong>temporal</strong>es, y al acotamiento <strong>de</strong>l or<strong>de</strong>n <strong>de</strong> crecimiento. Don<strong>de</strong> se dan métodospara acotar funciones o para resolver relaciones <strong>de</strong> recurrencia.4.21. Solución <strong>de</strong> ecuaciones <strong>de</strong> recurrencia.4.21.1. Recurrencias homogéneas.Son <strong>de</strong>l tipo:a T( n) a T( n 1) a T( n 2) ... a T( n k) 00 1 2kDon<strong>de</strong> los aison coeficientes reales y k un número natural entre 1 y n.nSi se reemplaza T ( n) x , resulta la ecuación:Factorizando:a x a x a x a xn n1 n2nk012... k 0( a x a x a x ... a ) x 0k k 1 k 2n k0 1 2kSe tiene entonces la ecuación característica:a x a x a x a kk k 1 k 2012... 0Profesor Leopoldo Silva Bijit 20-01-2010


20 Estructuras <strong>de</strong> Datos y Algoritmos4.21.1.1. Raíces diferentes.Si las k raíces resultan distintas: x1, x2,...., xk, la solución <strong>de</strong> la ecuación <strong>de</strong> recurrencia es unacombinación lineal <strong>de</strong> las soluciones. Don<strong>de</strong> los cise <strong>de</strong>terminan a partir <strong>de</strong> las condicionesiniciales.ikT( n) cixiPara resolverla se requieren k condiciones iniciales: T(0), T(1), T(2),..., T( k 1)i1nEjemplo 4.6.La ecuación <strong>de</strong> recurrencia para cálculos <strong>de</strong> complejidad en árboles AVL, queda dada por laecuación <strong>de</strong> recurrencia <strong>de</strong> segundo or<strong>de</strong>n, <strong>de</strong> Fibonacci, con n 2 :T( n) T( n 1) T( n 2)Para resolverla es necesario conocer los valores iniciales: T(0) 0, T(1) 1.nCon el reemplazo: T ( n) x , resulta:x1,215 . Entonces la solución <strong>de</strong> la ecuación <strong>de</strong> recurrencia es:21 5 n 1 5 nT( n) c1( ) c2( )2 2x2 x 1, ecuación <strong>de</strong> segundo grado con solución:La que evaluada en n=0 y n=1, permite calcular las constantes, resultando:1 15 n 1 15Tn ( ) ( ) ( )5 2 5 2Realizando los cálculos con el procesador Maple, se obtiene:> S3:= rsolve( { T(n)=T(n-1)+T(n-2), T(0) = 0,T(1)=1}, T(n)):> evalf(S3);.4472135952 1.618033988 n .4472135956 (-.6180339886 )nPue<strong>de</strong> comprobarse que el segundo término es una serie alternada que tien<strong>de</strong> rápidamente acero; y es menor que 0,2 para n>2. Graficando los valores absolutos <strong>de</strong>l segundo término,mediante:> plot(abs(-.4472135956*(-.6180339886)^n),n=0..10,thickness=2);Se obtiene el gráfico:nProfesor Leopoldo Silva Bijit 20-01-2010


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 21Figura 4.15 Acotamiento serie alternadaPara el primer término, se obtiene el crecimiento <strong>de</strong> T(n), mediante:> plot(.4472135952*1.618033988^n,n=0..10,thickness=2);15Don<strong>de</strong> 1,618033.. se <strong>de</strong>nomina razón áurea.2Figura 4.16 Crecimiento exponencialUn gráfico <strong>de</strong> la función y dos adicionales que la acotan, se logra con:> plot([.4472135952*1.618033988^n,.1*1.618^n,1.618^n],n=20..30,thickness=2,color=[black,red,blue]);Profesor Leopoldo Silva Bijit 20-01-2010


22 Estructuras <strong>de</strong> Datos y AlgoritmosLo que permite establecer que:4.21.1.2. Raíces múltiples.Figura 4.17 Or<strong>de</strong>n <strong>de</strong> complejidad <strong>de</strong> recurrencia FibonaccinTn ( ) ( )En caso <strong>de</strong> tener una raíz múltiple <strong>de</strong> or<strong>de</strong>n m, conservando el grado k <strong>de</strong> la ecuación <strong>de</strong>recurrencia, se tiene la ecuación característica:m( x x1 ) ( x x2) ... ( x xk m 1) 0Si tuviéramos que contar los elementos <strong>de</strong> la secuencia: s3, s4,s5, po<strong>de</strong>mos realizar el cálculosegún: (5-3 +1) = 3. Del mismo modo, po<strong>de</strong>mos contar los elementos <strong>de</strong>s<strong>de</strong>:s2, s3, s4, ...., sk m 1, según: ( k m 1) 2 1 k m , lo cual muestra que la ecuacióncaracterística tiene k raíces en total.La cual tiene como solución general a:imiki1n n i 1 i im1i1 im1T( n) c n x c xLa primera sumatoria introduce m constantes en un polinomio <strong>de</strong> grado (m-1) en n.imi1c n x ( c n c n ... c n ) xii1 n 0 1 m1n1 1 2 m 1nLa forma polinomial se <strong>de</strong>be a que si x1es solución <strong>de</strong> la ecuación <strong>de</strong> recurrencia, entoncesnnnx1también será solución. Reemplazando1x en la ecuación <strong>de</strong> recurrencia, <strong>de</strong>be cumplirse:a x a x a x ... a x 0n n1 n2nk0 1 1 1 2 1 k 1Profesor Leopoldo Silva Bijit 20-01-2010


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 23La que <strong>de</strong>rivada, respecto <strong>de</strong> x1, resulta:a nx a ( n 1) x ... a ( n k)xxn n1nk0 1 1 1 k11 0Si x1no es cero, <strong>de</strong>be cumplirse:a nx a ( n 1) x a ( n 2) x ... a ( n k) x 0n n1 n2nk0 1 1 1 2 1 k1nLo que comprueba que nx1también es solución <strong>de</strong> la ecuación <strong>de</strong> recurrencia.i nSimilar <strong>de</strong>mostración pue<strong>de</strong> realizarse para comprobar que nx1es solución, con i mLa segunda sumatoria es una combinación lineal <strong>de</strong> las (m-k) raíces diferentes restantes.Ejemplo 4.7.Para la ecuación, con n 3:T( n) 5 T( n 1) 8 T( n 2) 4 T( n 3)con condiciones iniciales T(0) 0, T(1) 2, T(2) 8 para k = 0, 1, 2.La ecuación característica resulta:3 2x x x5 8 4 0Una gráfica <strong>de</strong>l polinomio, muestra que tiene una raíz en x=1.> plot(x^3-5*x^2+8*x-4,x=0.5..3);Figura 4.17.a Raíces <strong>de</strong> polinomio cúbico.Dividiendo el polinomio cúbico por (x-1) se obtiene:Profesor Leopoldo Silva Bijit 20-01-2010


24 Estructuras <strong>de</strong> Datos y Algoritmos3 2x x x 5 8 4 x 4x 4 ( x 2)( x 1)2 2La ecuación característica tiene una raíz <strong>de</strong> multiplicidad dos:3 2 2x x x x x5 8 4 ( 2) ( 1) 0Entonces la solución general es:0 1 nT ( n) ( c n c n )2 c 11 2 3Evaluando T(n) en las condiciones iniciales obtenemos, tres ecuaciones:nT(0) ( c c 0)2 c 001 2 3T(1) ( c c )2 c 211 2 3T(2) ( c c 2)2 c 8Las que permiten obtener: c1 0, c2 1, c3 0 .21 2 3> solve({c1+c3=0,2*c1+2*c2+c3=2,4*c1+8*c2+c3=8},{c1,c2,c3});Reemplazando las constantes, la solución <strong>de</strong> la recurrencia, resulta:T( n) n2 nEmpleando Maple:> S1:=rsolve({T(n)= 5*T(n-1)-8*T(n-2)+4*T(n-3),T(0)=0,T(1)=2,T(2)=8},T(n)):> simplify(factor(S1));2 n nPue<strong>de</strong> graficarse la función y sus cotas, mediante:> plot([S1,2*S1,0.5*S1],n=4..9,color=[black,blue,red]);Profesor Leopoldo Silva Bijit 20-01-2010


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 25Figura 4.18 Cotas Ejemplo 4.7Entonces la complejidad <strong>de</strong> T(n), resulta:nT( n) ( n2 )Este crecimiento exponencial, no polinomial, es característico <strong>de</strong> <strong>de</strong>terminado tipo <strong>de</strong> problemasque son clasificados como NP. Algunos <strong>de</strong> estos problemas no pue<strong>de</strong>n ser resueltos por lascomputadoras actuales; a éstos se los <strong>de</strong>nomina NPC por NP completo.4.21.2. Recurrencias no homogéneas.Veremos algunos tipos <strong>de</strong> ecuaciones <strong>de</strong> recurrencia no homogéneas que tienen soluciónconocida.4.21.2.1. Excitación potencia <strong>de</strong> n.Cuando la excitación, el lado <strong>de</strong>recho <strong>de</strong> la ecuación <strong>de</strong> recurrencia, es una potencia <strong>de</strong> n; con bun número real, se tiene:a T( n) a T( n 1) a T( n 2) ... a T( n k) b0 1 2knPue<strong>de</strong> intentarse, mediante una manipulación algebraica, la transformación a una ecuaciónhomogénea. Esto no siempre es sencillo.Ejemplo 4.8.Sea la relación <strong>de</strong> recurrencia no homogénea, con n 1:Con condición inicial: (0) 0 T Si se plantea, la relación, en (n+1), se obtiene:T( n) 2 T ( n 1) 3 nProfesor Leopoldo Silva Bijit 20-01-2010


26 Estructuras <strong>de</strong> Datos y AlgoritmosT( n 1) 2 T( n) 3 n1Multiplicando por 3, la ecuación original, y restándolas, se logra la homogénea:Con ecuación característica:T( n 1) 5 T( n) 6 T( n 1) 0x25x 6 0Con soluciones: x1 3, x2 2 . La solución general es:T( n) c 3 c 2n1 2n1En la ecuación original, se pue<strong>de</strong> calcular: T(1) 2 T(0) 3 3Evaluando las constantes, mediante las ecuaciones:Se obtienen: c1 3, c2 3T(0) c 3 c 2 00 01 2T (1) c 3 c 2 31 11 2Finalmente:n nTn ( ) 33 32En Maple:> S4:= rsolve( { T(n)-2*T(n-1) =3^n, T(0) = 0, T(1)=3}, T(n));S4 := 3 2 n 3 3 nPue<strong>de</strong>n encontrarse dos funciones que acoten, por encima y por <strong>de</strong>bajo, a la función, mediante:> plot([S4,1*3^n,2*3^n],n=1..5,thickness=2,color=[black,red,blue]);Figura 4.19 Cotas Ejemplo 4.8Profesor Leopoldo Silva Bijit 20-01-2010


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 27nEntonces, se concluye que para n>1: Tn ( ) (3 )4.21.2.2. Excitación polinómica.a T( n) a T( n 1) a T( n 2) ... a T( n k) p( n)0 1 2kDon<strong>de</strong> p(n) es un polinomio <strong>de</strong> grado d.Se intenta llegar a una ecuación característica <strong>de</strong>l tipo:( a x a x a x ... a )( x 1) 0k k 1 k 2 d 10 1 2kLa cual pue<strong>de</strong> tratarse como una ecuación homogénea con raíces múltiples. La raíz múltipleestará asociada a un polinomio en n, y ya conocemos un método general para resolverlas.Ejemplo 4.9.T( n) 2 T( n 1) nEl polinomio es <strong>de</strong> grado 1, por lo tanto d=1.La ecuación característica resulta:2( x 2)( x1) 0Con solución general, para raíz simple en 2 y una múltiple doble en 1:T( n) c 2 ( c c n)1n1 2 3nCon T(0) =0, resultan: T(1)=1, T(2)=4; y pue<strong>de</strong>n calcularse las constantes:Finalmente, la solución resulta:c 2, c 2, c 11 2 3nnT( n) 2 2 n 2 (2 )La ecuación característica, en forma <strong>de</strong> polinomio, resulta:Lo cual equivale a la ecuación homogénea:3 2x x x 4 5 2 0T( n) 4 T( n 1) 5 T( n 2) 2 T( n 3)Profesor Leopoldo Silva Bijit 20-01-2010


28 Estructuras <strong>de</strong> Datos y AlgoritmosComparando con la ecuación original, <strong>de</strong>bería cumplirse:2 T( n 1) 5 T( n 2) 2 T( n 3) nEntonces para transformar en una ecuación homogénea se nos <strong>de</strong>bería haber ocurrido <strong>de</strong>rivar laecuación homogénea anterior a partir <strong>de</strong> la original no homogénea. Para esto es precisoencontrar una expresión para n que <strong>de</strong>penda <strong>de</strong> Tn ( 1) , Tn ( 2) y Tn ( 3) .Empleando la ecuación original se obtienen para: Tn ( 1) y Tn ( 2) :T( n 1) 2 T( n 2) n 1T( n 2) 2 T( n 3) n 2Eliminando éstas en la ecuación anterior se comprueba la igualdad <strong>de</strong>l lado izquierdo con n.En Maple, basta escribir:> S3:=rsolve( { T(n) = 2*T(n-1)+n , T(0) = 0}, T(n));S3 := 2 2 n 2nPara verificar el or<strong>de</strong>n <strong>de</strong>l crecimiento, pue<strong>de</strong>n dibujarse:> plot([S3,2^n,3*2^n],n=2..6,thickness=2,color=[black,red,blue]);nQue muestra que Tn ( ) (2 ) para n 2 .Figura 4.20 Cotas Ejemplo 4.94.21.2.3. Método <strong>de</strong> los coeficientes in<strong>de</strong>terminados.Permiten resolver ecuaciones <strong>de</strong> recurrencia con la forma:na T( n) a T ( n 1) a T ( n 2) ... a T ( n k) b p( n)0 1 2kProfesor Leopoldo Silva Bijit 20-01-2010


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 29Don<strong>de</strong> p(n) es un polinomio <strong>de</strong> grado d.Están basadas en <strong>de</strong>scomponer la solución en sus partes homogénea y particular:T ( n) T ( n) T ( n)hDon<strong>de</strong> Th( n ) es la solución homogénea, con excitación cero; y Tp( n ) es la solución particular.T ( n) p ( n) n m bnpDon<strong>de</strong> p ( n ) es un polinomio, <strong>de</strong> or<strong>de</strong>n d, con coeficientes que serán <strong>de</strong>terminados; m es ladmultiplicidad <strong>de</strong> la raíz b en la ecuación característica. Notar que con excitación solamente <strong>de</strong>tipo polinomio, m es la multiplicidad <strong>de</strong> la raíz 1 en la ecuación característica (con b=1).Se resolverán los ejemplos anteriores, usando este método.dpEjemplo 4.10.Para:Con condición inicial: T(0) 0Se tiene la ecuación homogénea:T( n) 2 T ( n 1) 3 nT ( n) 2 T ( n 1) 0hhnn n 1Reemplazando Th( n) x se obtiene la ecuación: x 2x 0Entonces, la ecuación característica es: x 2 0, resultando:T ( n) c2 nhComo 3 no es raíz <strong>de</strong> la ecuación homogénea, se tendrá que m es cero; a<strong>de</strong>más la excitación nocontiene un polinomio, entonces po<strong>de</strong>mos escoger, la solución particular:T ( n) a 3 nCon a el coeficiente <strong>de</strong> un polinomio <strong>de</strong> grado 0, que <strong>de</strong>berá <strong>de</strong>terminarse:Reemplazando en la ecuación <strong>de</strong> recurrencia:pArreglando, resulta:a 13 n 2( 3 n a ) 3n2an( a ) 3 33nProfesor Leopoldo Silva Bijit 20-01-2010


30 Estructuras <strong>de</strong> Datos y AlgoritmosDe don<strong>de</strong> resulta que:Obteniéndose:La solución general es:2aa 13a 3nT ( n) T ( n) T ( n) c2 33Para evaluar la constante c, se tiene:0 0T(0) c2 33 0La que permite calcular c 3Obteniéndose igual solución que la anterior, <strong>de</strong>terminada en el Ejemplo 4.8.hpnEjemplo 4.11.Con condición inicial: T(0) 0T( n) 2 T( n 1) nLa solución homogénea, resulta: T ( n) c2 nhComo 1 no es solución <strong>de</strong> la ecuación homogénea, se tendrá que m es cero; a<strong>de</strong>más b es uno,por lo tanto el polinomio p <strong>de</strong>be ser <strong>de</strong> grado uno. Tenemos entonces la siguiente soluciónparticular:T ( ) ( )pn p1n an bQue al ser reemplazada en la ecuación <strong>de</strong> recurrencia, permite obtener:Arreglando, para <strong>de</strong>terminar coeficientes:De la cual se pue<strong>de</strong>n plantear:Entonces: T ( n) an b n 2pLa solución general: T( n) c2 n n 2( an b) 2 ( a( n 1) b) n( a) n (2 a b) na12ab00La constante se calcula <strong>de</strong>: T(0) c2 0 2 0 , obteniéndose igual solución que la anterior,<strong>de</strong>terminada en el Ejemplo 4.9.Ejemplo 4.12.Profesor Leopoldo Silva Bijit 20-01-2010


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 31Con condición inicial: T(0) 0T( n) 2 T( n 1) 2 nComo b es igual a la raíz <strong>de</strong> la ecuación homogénea, se tendrá con d=0, m=1, b=2, que lasolución particular resulta:T ( n) p ( n) n b a n 2Reemplazando en la relación <strong>de</strong> recurrencia, se obtiene:pdm n na n a n n n1n2 2( ( 1)2 ) 2El coeficiente <strong>de</strong>be cumplir: an a( n 1) 1, resultando a 1.La solución general: ( ) 2 n nT n c n2, evaluada en 0:Como c 0 , la solución es:T0 0(0) c2 02 0nnT( n) n2 ( n2 )En Maple, se obtiene igual solución:> S4:= rsolve( { T(n)-2*T(n-1) =2^n, T(0) = 0}, T(n));S4 := 2 n ( n1 ) 2 n> simplify(S4);2 n n4.21.2.4. Método cuando n es potencia <strong>de</strong> dos.Ejemplo 4.13.Con condición inicial: T(1) 1T( n) 4 T( n / 2) nNótese que n <strong>de</strong>be ser 2 o mayor. Para n=2, pue<strong>de</strong> calcularse: T(2) 4 T(1) 2 6 ; por estarazón la condición inicial se da con n=1.Si n es una potencia <strong>de</strong> dos, se tiene que:recurrencia:n 2 k, entonces reemplazando en la ecuación <strong>de</strong>T1(2 k ) 4 (2 k T ) 2kProfesor Leopoldo Silva Bijit 20-01-2010


32 Estructuras <strong>de</strong> Datos y AlgoritmoskCon el siguiente cambio <strong>de</strong> variable: U ( k) T(2 )Se obtiene, la ecuación <strong>de</strong> recurrencia:U( k) 4 U( k 1) 2 kEcuación que po<strong>de</strong>mos resolver, obteniéndose:kU ( k) c 4 2Arreglando, y cambiando la variable U, se obtiene:kExpresando en términos <strong>de</strong> n:T2(2 k ) c(2 k ) 2k2T( n) c n nLa cual evaluada en n=1, permite calcular c.2T(1) c1 1 1Finalmente:2 2T( n) 2 n n ( n )En Maple:> S6:= rsolve( { T(n)-4*T(n/2) =n, T(1) = 1}, T(n));S6 := n ( 2 n1)La <strong>de</strong>terminación <strong>de</strong>l or<strong>de</strong>n <strong>de</strong> complejidad se logra con:> plot([S6,1*n^2,2*n^2],n=2..8,thickness=2,color=[black,red,blue]);Figura 4.21 Cotas Ejemplo 4.13Ejemplo 4.14.T( n) 2 T( n / 2) nProfesor Leopoldo Silva Bijit 20-01-2010


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 33Con condición inicial: T(1) 1Nótese que n <strong>de</strong>be ser 2 o mayor. Para n=2, se tiene: T(2) 2 T(1) 2 . Por esta razón lacondición inicial se da con n=1.Se tiene que:n 2 k, entonces:T1(2 k ) 2 (2 k T ) 2kkCon el siguiente cambio <strong>de</strong> variable: U ( k) T(2 )Se obtiene, la ecuación <strong>de</strong> recurrencia:U( k) 2 U( k 1) 2 kEcuación que po<strong>de</strong>mos resolver, obteniéndose:U( k) c2 k k 2 k T(2 k )Expresando en términos <strong>de</strong> n, y empleando k log2( n):T( n) cn nlog ( n)2La cual evaluada en n=1, permite calcular que c es uno.Finalmente:T(1) c110 1T( n) n nlog ( n) ( nlog ( n))2 2En Maple:> S7:= rsolve( { T(n)-2*T(n/2) =n, T(1) = 1}, T(n));n ln( n )S7 := nln( 2 )La <strong>de</strong>terminación <strong>de</strong>l or<strong>de</strong>n <strong>de</strong> complejidad se logra con:> plot([S7,n*ln(n)/ln(2),2*n*ln(n)/ln(2)],n=2..8,thickness=2,color=[black,red,blue]);Profesor Leopoldo Silva Bijit 20-01-2010


34 Estructuras <strong>de</strong> Datos y AlgoritmosFigura 4.22 Cotas Ejemplo 4.144.22. Cálculos <strong>de</strong> complejidad a partir <strong>de</strong>l código.Los cálculos <strong>de</strong> complejidad pue<strong>de</strong>n efectuarse, in<strong>de</strong>pendientemente <strong>de</strong> la función que elalgoritmo realiza. Se analiza un ejemplo, que muestra los diferentes costos basándose encriterios <strong>de</strong> cuenta <strong>de</strong> instrucciones.Si bien no es necesario conocer la función realizada por el algoritmo para efectuar el cálculo <strong>de</strong>la complejidad <strong>temporal</strong>, la siguiente función implementa un algoritmo <strong>de</strong> or<strong>de</strong>namientoconocido como burbuja. Opera sobre un arreglo <strong>de</strong> enteros <strong>de</strong> n posiciones.void Alg1(int a[], int n){int i, j, temp;for (i=0; i=i+1; j--) //2if(a[j-1] > a[j]) //3{ temp=a[j-1]; //4a[j-1]=a[j]; //5a[j]=temp; //6}}4.22.1. Cálculo <strong>de</strong> complejidad basada en operaciones elementales.Se calculan las operaciones elementales asociadas a cada línea consi<strong>de</strong>rando como operaciónelemental, a: comparaciones, asignaciones, sumas, restas, y acceso a componentes <strong>de</strong> un vector.Línea 1: se ejecuta una asignación <strong>de</strong> inicio; una resta y una comparación <strong>de</strong> salida; una resta,una comparación y una suma por cada una <strong>de</strong> las iteraciones <strong>de</strong>l lazo.Línea 2: se ejecutan una resta y asignación <strong>de</strong> inicio y una suma más una comparación <strong>de</strong>salida; una suma y una comparación más una resta por cada una <strong>de</strong> las iteraciones.Profesor Leopoldo Silva Bijit 20-01-2010


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 35Línea 3: se efectúa la condición, con 4 O(1): una diferencia, dos accesos a un vector, y unacomparación.Las líneas 4 a 6, es una acción compuesta que sólo se ejecuta si se cumple la condición <strong>de</strong> lalínea 3, y se realiza un total <strong>de</strong> 9 O(1): 3, 4 y 2 O(1) respectivamente.En el peor caso se efectúa siempre el bloque asociado al if. Tenemos entonces que el lazointerno se realiza:1n1T ( n) 2 O(1) (2 4 9 1) O(1) 2 O(1)ji 1La sumatoria se realiza: el número final menos el inicial, más uno:( n 1) ( i 1) 1 ( n i 1)Entonces, en peor caso, el lazo interno tiene un costo:T ( n ) (4 16 ( n i 1)) O (1)1El lazo externo, tiene un costo <strong>de</strong>:n2T( n) 1 O(1) (2 (4 16 ( n i 1)) 1) O(1) 2 O(1)i0Arreglando, y consi<strong>de</strong>rando que los términos que no <strong>de</strong>pen<strong>de</strong>n <strong>de</strong> i, se suman (n-1) veces, seobtiene:n2T ( n) 3 (7 16n 16)( n 1) 16 i O(1)i0La suma <strong>de</strong> los primeros (n-2) términos, pue<strong>de</strong> plantearse:n2 n2( n2)( n1)ii2i0 i1Reemplazando en la ecuación anterior, se obtiene:Finalmente:T n n n n n O2( ) (16 25 12 8( 2)( 1)) (1)T n n n O2( ) (8 4) (1)T n2( ) O( n )Profesor Leopoldo Silva Bijit 20-01-2010


36 Estructuras <strong>de</strong> Datos y Algoritmos4.22.2. Cálculo <strong>de</strong> complejidad basada en instrucciones <strong>de</strong>l lenguaje <strong>de</strong> alto nivel.Cada instrucción <strong>de</strong>l lenguaje se consi<strong>de</strong>ra <strong>de</strong> costo unitario.Se consi<strong>de</strong>ra que las líneas 4, 5 y 6 son O(1), la acción compuesta tiene costo: O(1)+O(1)+O(1),es <strong>de</strong>cir 3O(1).El peor caso es que se realice siempre el bloque <strong>de</strong>l if, y si se consi<strong>de</strong>ra que éste es <strong>de</strong> costoO(1), entonces, las líneas 3, 4, 5 y 6 son 4O(1).El for interno tiene un costo: ( n i 1) 4 O(1)Para el for externo, se tiene:n2( n2)( n1)T( n) 4( n i 1) O(1) 4( n 1)( n 2) 4 O(1)i02 Resultando:2 2T( n) (2n 6n 4) O(1) O( n )Debe notarse que el costo unitario, <strong>de</strong>l cálculo basado en contar instrucciones <strong>de</strong> alto nivel, esdiferente <strong>de</strong>l realizado contando operaciones elementales.Pue<strong>de</strong> comprobarse que los costos, <strong>de</strong> los dos procedimientos <strong>de</strong> cálculo, difieren en unaconstante:2(8nn4)Rn ( ) 2(2n6n4)Aplicando la regla <strong>de</strong> L’Hôpital, para calcular el límite, se tiene:lim Rn ( ) 4nLa gráfica siguiente ilustra la relación anterior:Profesor Leopoldo Silva Bijit 20-01-2010


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 37Se obtiene, mediante:> e:=(8*n^2 -n-4)/(2*n^2-6*n+4);Figura 4.23. Razón entre complejida<strong>de</strong>se :=8 n 2 n42 n 2 6 n4> limit(e,n=infinity);4> plot(e,n=2.2..8,thickness=2);4.22.3. Cálculo <strong>de</strong> complejidad basada en instrucciones <strong>de</strong>l lenguaje <strong>de</strong> máquina.La compilación <strong>de</strong> la función en C, genera el listado <strong>de</strong> las instrucciones en assembler, para elmicrocontrolador MSP430; el que se muestra más a<strong>de</strong>lante.Una aproximación para efectuar la cuenta es consi<strong>de</strong>rar que todas las instrucciones tienen igualcosto.Al listado se le han agregado comentarios para hacerlo más legible, y <strong>de</strong>l listado pue<strong>de</strong>nobtenerse las siguientes cuentas:Antes <strong>de</strong> realizar i=0, se han ejecutado 9 instrucciones assembler, cuestión que no se contemplaen los cálculos anteriores; tampoco se contemplan las 6 instrucciones que se realizan para salir<strong>de</strong> la función; correspon<strong>de</strong>n a armar y <strong>de</strong>sarmar el frame <strong>de</strong> la función. También aparecen lastres instrucciones necesarias para pasar los argumentos e invocar a la función.El <strong>de</strong>sarrollo <strong>de</strong>l if resulta con 11 instrucciones. La acción compuesta <strong>de</strong>ntro <strong>de</strong>l if, se logra con21 instrucciones. Reinicio <strong>de</strong> los for con 3 instrucciones; evaluación <strong>de</strong> las condiciones <strong>de</strong> losfor en 4 instrucciones. <strong>Inicio</strong> <strong>de</strong>l primer for con una instrucción, <strong>de</strong>l segundo for con 3.Entonces el for interno, tiene un costo:Arreglando, y realizando la sumatoria:1n1T ( n) 3 O(1) (4 11 21 3) O(1) 4 O(1)ji 11n1T ( n) 7 O(1) 39 O(1) (7 39( n i 1)) O(1) (39n 32 39 i) O(1)El primer for, tiene costo:2ji 1n2T ( n) 9 O(1) 1 O(1) (4 (39n 32 39 i) 3) O(1) 4 O(1) 6 O(1)Simplificando:i0Profesor Leopoldo Silva Bijit 20-01-2010


38 Estructuras <strong>de</strong> Datos y Algoritmos2n2T ( n) 20 O(1) (39n 25 39 i) O(1)i0Extrayendo el término que no <strong>de</strong>pen<strong>de</strong> <strong>de</strong> i <strong>de</strong> la sumatoria:2n2T ( n) 20 O(1) (39n 25)( n 1) O(1) 39 i O(1)Realizando la sumatoria:T n n n O( n2)( n1)O2Simplificando, se obtiene:239n11n12T2( n) O(1)2i022( ) (39 64 45) (1) 39 (1)Existen tres adicionales, requeridas para pasarle valores a los argumentos e invocar a la función:2(39n11n18)T( n) O(1)2Alg1(a, N);0025EE 3E400500 mov.w #0x5, R14 ;copia valor constante N en R140025F2 3C400011 mov.w #0x1100,R12 ;copia valor <strong>de</strong> la dirección <strong>de</strong> a en R120025F6 B0126E25 call #Alg1 ;Invocación <strong>de</strong> la funciónvoid Alg1(int *a, int n){Alg1:00256E 0A12 push.w R10 ;formación <strong>de</strong>l frame002570 0B12 push.w R11 ;salva registros002572 0812 push.w R8002574 0912 push.w R9002576 0D4C mov.w R12,R13 ;argumento a en R12, copia en R13002578 0C4E mov.w R14,R12 ;argumento n en R14, copia en R12for (i=0; i a[j]) //300257E 0F4B mov.w R11,R15 ;en R11 almacena j002580 0F5F rla.w R15 ;cada entero ocupa 2 bytes. j*2002582 0E4D mov.w R13,R14 ;a pasa a R14002584 0E5F add.w R15,R14 ;en R14 apunta a a[j]002586 084B mov.w R11,R8 ;mueve j a R8002588 3853 add.w #0xFFFF,R8 ;R8=j-100258A 0858 rla.w R8 ;(j-1)*2 en bytes00258C 0F4D mov.w R13,R1500258E 0F58 add.w R8,R15 ;en R15 forma a[j-1]Profesor Leopoldo Silva Bijit 20-01-2010


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 39002590 AE9F0000 cmp.w @R15,0x0(R14) ;compara002594 1734 jge 0x25C4 ;salta a fin <strong>de</strong>l if{ temp=a[j-1]; //4002596 0F4B mov.w R11,R15002598 3F53 add.w #0xFFFF,R1500259A 0F5F rla.w R15 ;R15=2(j-1)00259C 0E4D mov.w R13,R1400259E 0E5F add.w R15,R14 ;R14 apunta a a[j-1]0025A0 284E mov.w @R14,R8 ;temp =R8=*(a+2(j-1))a[j-1]=a[j]; //50025A2 0F4B mov.w R11,R150025A4 0F5F rla.w R150025A6 0E4D mov.w R13,R140025A8 0E5F add.w R15,R14 ;R14 apunta a a[j]0025AA 094B mov.w R11,R90025AC 3953 add.w #0xFFFF,R90025AE 0959 rla.w R90025B0 0F4D mov.w R13,R150025B2 0F59 add.w R9,R15 ;R15 apunta a a[j-1]0025B4 AF4E0000 mov.w @R14,0x0(R15) ;asignacióna[j]=temp; //60025B8 0E4B mov.w R11,R140025BA 0E5E rla.w R140025BC 0F4D mov.w R13,R150025BE 0F5E add.w R14,R150025C0 8F480000 mov.w R8,0x0(R15)for (j=n-1; j>=i+1; j--) //20025C4 3B53 add.w #0xFFFF,R11 ;reinicio segundo forfor (j=n-1; j>=i+1; j--) //20025C6 0F4A mov.w R10,R15 ;mueve j al registro R15;evalúa condición segundo for0025C8 1F53 inc.w R15 ; incrementa i0025CA 0B9F cmp.w R15,R11 ;compara j (en R10) con i+1 (en R15)0025CC D837 jge 0x257E ;entra al bloque <strong>de</strong>l segundo forfor (i=0;i


40 Estructuras <strong>de</strong> Datos y Algoritmos004672 3841 pop.w R8 ;restaura registros004674 3B41 pop.w R11004676 3A41 pop.w R10004678 3041 ret ;retorno <strong>de</strong> Alg1Un cálculo más exacto consiste en contar los ciclos <strong>de</strong> reloj necesarios para ejecutar lasinstrucciones. Esta información se obtiene en el manual <strong>de</strong>l procesador en que se estécompilando. Esto <strong>de</strong>bido a que, <strong>de</strong>pendiendo <strong>de</strong> la estructura <strong>de</strong>l procesador, algunasinstrucciones <strong>de</strong>moran más que otras. Por ejemplo, la instrucción: mov.w @R14,0x0(R15)<strong>de</strong>mora más en su ejecución que las instrucciones ret o pop.Otros aspectos que muestra el código assembler, es la aritmética <strong>de</strong> punteros y las instruccionesrelativas a registros para indireccionar; a<strong>de</strong>más <strong>de</strong>l uso <strong>de</strong> registros y saltos.El conteo <strong>de</strong> las instrucciones <strong>de</strong>pen<strong>de</strong>rá <strong>de</strong> la calidad <strong>de</strong>l compilador que se esté empleando, ysi dispone o no <strong>de</strong> niveles <strong>de</strong> optimización. También <strong>de</strong>pen<strong>de</strong>rá <strong>de</strong>l procesador y su repertorio<strong>de</strong> instrucciones, y <strong>de</strong>l sistema operativo que se esté empleando. Por estas razones, en cálculos<strong>de</strong> complejidad, no suelen contarse las instrucciones <strong>de</strong> un procesador, sino las <strong>de</strong>l lenguaje <strong>de</strong>alto nivel o <strong>de</strong>l pseudo código.El or<strong>de</strong>n <strong>de</strong> complejidad, que resulta <strong>de</strong> contar las instrucciones assembler, también es2 ( n ).Pue<strong>de</strong> compararse el costo obtenido mediante contar instrucciones assembler, con la cuenta <strong>de</strong>operaciones elementales, mediante:2(39n11n18)Rn ( ) 22(8nn4)lim Rn ( ) 2nSe observa que R(n) tien<strong>de</strong> rápidamente a la constante dos.> e2:=2*(39*n^2-11*n+18)/(8*n^2 -n-4);2 ( 39 n 2 11 n18)e2 :=8 n 2 n4> limit(e2,n=infinity);394> plot(e2,n=1..6,thickness=2);Profesor Leopoldo Silva Bijit 20-01-2010


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 41Figura 4.24 Razón constante entre complejida<strong>de</strong>s.Se concluye <strong>de</strong> este ejemplo, que una metodología razonablemente útil para calcular lacomplejidad <strong>de</strong> un algoritmo es contar las instrucciones <strong>de</strong>l lenguaje <strong>de</strong> alto nivel o <strong>de</strong>l pseudocódigo.4.23. Resumen.Se pue<strong>de</strong> cuantificar el or<strong>de</strong>n <strong>de</strong> crecimiento empleando la notación .El or<strong>de</strong>n <strong>de</strong> crecimiento es el principal factor que <strong>de</strong>termina el tiempo <strong>de</strong> ejecución <strong>de</strong> unalgoritmo.Si se reduce el or<strong>de</strong>n <strong>de</strong> crecimiento se logran enormes reducciones en el tiempo <strong>de</strong> ejecución.Profesor Leopoldo Silva Bijit 20-01-2010


42 Estructuras <strong>de</strong> Datos y AlgoritmosProblemas resueltos.P4.1Determinar la solución <strong>de</strong> la siguiente relación <strong>de</strong> recurrencia:T(n) = T(n/2) + n, con T(1)= 2.Si es necesario pue<strong>de</strong> emplear que la suma <strong>de</strong> la siguiente progresión geométrica es:¿Cuál es el or<strong>de</strong>n <strong>de</strong> complejidad?Solución.T(2) = T(1) + 2 = 4 = 2 2T(4) = T(2) + 4 = 8 = 2 3T(8) = T(4) + 8 = 16 = 2 4T(16) = T(8) + 16 = 32 = 2 5T(2 i ) = T(2 i-1 ) + 2 i = 2 i+1 =2*2 iCon 2 i = n, se obtiene la solución:T(n) = 2*nEntonces: T(n) es ( n ), para todo n.ni12 ( n1)22 i Ya que existen c1, c2 y n 0 tales que:c1 f(n)


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 43Ejercicios propuestos.E4.1.Dado un número n, encontrar a y b tales que: a*a+b*b = n*n, con a, b y n enteros mayores quecero.Determinar la complejidad <strong>temporal</strong> y su or<strong>de</strong>n <strong>de</strong> crecimiento.E4.2.Calcular la complejidad <strong>de</strong>: T(n) = T(n-1) + n con T(0)=0.E4.3.Calcular la complejidad:T(n) = 3T(n–1) + 4T(n–2) si n>1; T(0) = 0; T(1) = 1.Sol. T(n)=O(4n)E4.4.Calcular la complejidad:T(n) = 2T(n–1) – (n+5)3 n si n>0; T(0) = 0.Sol. T(n) = 9·2 n – 9·3 n – 3n3 n con or<strong>de</strong>n <strong>de</strong> complejidad: Θ(n3 n ).E4.5.Calcular la complejidad:T(n) = 4T(n/2) + n 2 si n>4, n potencia <strong>de</strong> 2; T(1) = 1; T(2) = 8.Sol. T(n) = n 2 + n 2 logn Θ(n 2 logn).Profesor Leopoldo Silva Bijit 20-01-2010


44 Estructuras <strong>de</strong> Datos y AlgoritmosÍndice general.CAPÍTULO 4. ............................................................................................................................................. 1COMPLEJIDAD TEMPORAL DE ALGORITMOS. ............................................................................ 14.1. TIEMPO DE EJECUCIÓN Y TAMAÑO DE LA ENTRADA. ........................................................................... 14.2. COMPLEJIDAD TEMPORAL. DEFINICIÓN. ............................................................................................. 14.3. TIPOS DE FUNCIONES. ......................................................................................................................... 24.4. ACOTAMIENTO DE FUNCIONES. .......................................................................................................... 24.5. FUNCIÓN O. ........................................................................................................................................ 44.6. FUNCIÓN . ........................................................................................................................................ 44.7. COSTO UNITARIO. ............................................................................................................................... 54.8. REGLA DE CONCATENACIÓN DE ACCIONES. REGLA DE SUMAS........................................................... 5Teorema <strong>de</strong> sumas. ............................................................................................................................... 5Corolario. ............................................................................................................................................ 64.9. REGLA DE PRODUCTOS. ...................................................................................................................... 64.10. REGLA DE ALTERNATIVA. ................................................................................................................. 64.11. REGLA DE ITERACIÓN. ...................................................................................................................... 7Ejemplo 4.1. ......................................................................................................................................... 84.12. ALGORITMOS RECURSIVOS. .............................................................................................................. 8Ejemplo 4.2. Evaluando la complejidad en función <strong>de</strong>l tiempo. ........................................................ 10Ejemplo 4.3. Aplicación a un algoritmo sencillo. .............................................................................. 10Ejemplo 4.4. Comparación <strong>de</strong> complejidad entre dos <strong>algoritmos</strong>. .................................................... 11Ejemplo 4.5. Búsqueda en arreglos. .................................................................................................. 114.13. BÚSQUEDA SECUENCIAL. ................................................................................................................ 124.14. BÚSQUEDA BINARIA (BINARY SEARCH) ......................................................................................... 124.15. SOBRE EL COSTO O(1). ................................................................................................................... 144.17.1. Algoritmos <strong>de</strong> multiplicación. ................................................................................................ 144.17.2. Algoritmos <strong>de</strong> división. .......................................................................................................... 154.18. COMPLEJIDAD NLOG(N). ................................................................................................................ 164.19. COMPARACIÓN ENTRE COMPLEJIDADES TÍPICAS. ............................................................................ 184.20. ESTUDIO ADICIONAL. ..................................................................................................................... 194.21. SOLUCIÓN DE ECUACIONES DE RECURRENCIA. ............................................................................... 194.21.1. Recurrencias homogéneas. .................................................................................................... 194.21.1.1. Raíces diferentes. ............................................................................................................................ 204.21.1.2. Raíces múltiples. ............................................................................................................................. 224.21.2. Recurrencias no homogéneas. ............................................................................................... 254.21.2.1. Excitación potencia <strong>de</strong> n. ................................................................................................................ 254.21.2.2. Excitación polinómica. .................................................................................................................... 274.21.2.3. Método <strong>de</strong> los coeficientes in<strong>de</strong>terminados. .................................................................................... 284.21.2.4. Método cuando n es potencia <strong>de</strong> dos. .............................................................................................. 314.22. CÁLCULOS DE COMPLEJIDAD A PARTIR DEL CÓDIGO....................................................................... 344.22.1. Cálculo <strong>de</strong> complejidad basada en operaciones elementales. ............................................... 344.22.2. Cálculo <strong>de</strong> complejidad basada en instrucciones <strong>de</strong>l lenguaje <strong>de</strong> alto nivel. ........................ 364.22.3. Cálculo <strong>de</strong> complejidad basada en instrucciones <strong>de</strong>l lenguaje <strong>de</strong> máquina. ......................... 374.23. RESUMEN. ...................................................................................................................................... 41PROBLEMAS RESUELTOS. ........................................................................................................................ 42Profesor Leopoldo Silva Bijit 20-01-2010


<strong>Complejidad</strong> <strong>temporal</strong> <strong>de</strong> <strong>algoritmos</strong> 45P4.1 ................................................................................................................................................... 42EJERCICIOS PROPUESTOS. ....................................................................................................................... 43E4.1. .................................................................................................................................................. 43E4.2. .................................................................................................................................................. 43E4.3. .................................................................................................................................................. 43E4.4. .................................................................................................................................................. 43E4.5. .................................................................................................................................................. 43ÍNDICE GENERAL. ................................................................................................................................... 44ÍNDICE DE FIGURAS. ................................................................................................................................ 46Profesor Leopoldo Silva Bijit 20-01-2010


46 Estructuras <strong>de</strong> Datos y AlgoritmosÍndice <strong>de</strong> figuras.FIGURA 4.1. T(N) ES O(N 3 ). ............................................................................................................................ 2FIGURA 4.2. T(N) TAMBIÉN ES O(N 2 ). ............................................................................................................. 3FIGURA 4.3. T(N) = (N+1) 2 ES O(N 2 ). .............................................................................................................. 3FIGURA 4.4. T(N)= 3N 3 + 2 N 2 ES (N 3 ). .......................................................................................................... 4FIGURA 4.5. COSTO DE ALTERNATIVA. .......................................................................................................... 7FIGURA 4.6. COSTO DE LAZO FOR Y WHILE. ................................................................................................... 7FIGURA 4.7. T(N) = C(LOG 2 (N) +1) ES O( LOG 2 (N) ) ........................................................................................ 9FIGURA 4.8 COSTO LINEAL VERSUS COSTO LOGARÍTMICO. .......................................................................... 10FIGURA 4.9 COSTO TEMPORAL. ................................................................................................................... 10FIGURA 4.10 BÚSQUEDA BINARIA. .............................................................................................................. 13FIGURA 4.11 COMPLEJIDAD ( N LOG(N) ). ................................................................................................. 17FIGURA 4.12 ( N LOG(N) ) VERSUS CUADRÁTICA. ...................................................................................... 18FIGURA 4.13 ( N LOG(N) ) VERSUS LINEAL. ................................................................................................ 18FIGURA 4.14 COMPARACIÓN ENTRE CUATRO TIPOS DE COMPLEJIDADES. .................................................... 19FIGURA 4.15 ACOTAMIENTO SERIE ALTERNADA .......................................................................................... 21FIGURA 4.16 CRECIMIENTO EXPONENCIAL .................................................................................................. 21FIGURA 4.17 ORDEN DE COMPLEJIDAD DE RECURRENCIA FIBONACCI ......................................................... 22FIGURA 4.17.A RAÍCES DE POLINOMIO CÚBICO. ........................................................................................... 23FIGURA 4.18 COTAS EJEMPLO 4.7 ............................................................................................................... 25FIGURA 4.19 COTAS EJEMPLO 4.8 ............................................................................................................... 26FIGURA 4.20 COTAS EJEMPLO 4.9 ............................................................................................................... 28FIGURA 4.21 COTAS EJEMPLO 4.13 ............................................................................................................. 32FIGURA 4.22 COTAS EJEMPLO 4.14 ............................................................................................................. 34FIGURA 4.23. RAZÓN ENTRE COMPLEJIDADES ............................................................................................. 37FIGURA 4.24 RAZÓN CONSTANTE ENTRE COMPLEJIDADES. .......................................................................... 41FIGURA P4.1 COTAS DE T(N). ...................................................................................................................... 42Profesor Leopoldo Silva Bijit 20-01-2010

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!