310 likes | 536 Views
Eficiencia de los algoritmos. Curso 2004/2005 Daniel García José Moya José A. Gallud. 1. Concepto y análisis de algoritmos. Métodos de resolución, algoritmos y programas Existencia frente a factibilidad de una solución
E N D
Eficiencia de los algoritmos Curso 2004/2005 Daniel García José Moya José A. Gallud Eficiencia de los algoritmos
1. Concepto y análisis de algoritmos • Métodos de resolución, algoritmos y programas • Existencia frente a factibilidad de una solución • Método de resolución de un problema P: descripción de pasos discretos, basados en unos fundamentos y resultados teóricos, de forma que la realización de estos pasos, junto a unos datos necesarios, lleva a una solución del problema. • Semialgoritmo: descripción precisa de un método, con pasos numerados y bien ordenados que da la solución de P si existe, en un número finito de pasos. • Algoritmo: si además es capaz de determinar que no tiene solución en un número finito de pasos. • A partir de un método más de un algoritmo Eficiencia de los algoritmos
Programa: algoritmo (o semialgoritmo) dispuesto en pasos comprensibles por una máquina, junto a las estructuras de datos con las que opera. • Análisis de algoritmos • Complejidad en tiempo y espacio • Complejidad: medida de la eficiencia de un algoritmo en tiempo o espacio • La fórmula de la complejidad nos indica el comportamiento • Hablaremos del comportamiento mas que del propio valor • Tamaño del problema • Variable utilizada para las funciones de complejidad • Suele depender del número de datos del problema • Rara vez se eligen dos o más variables como tamaño del problema Eficiencia de los algoritmos
Función de complejidad: • Función que tiene como variable independiente el tamaño del problema y que sirve para medir la complejidad (espacial o temporal) • Mide el tiempo/espacio relativo en función del tamaño del problema • El comportamiento de la función determina la eficiencia • No es única para un algoritmo: depende de los datos • Funciones de complejidad más interesantes: • La del mejor caso fm(n) • La del peor caso fp(n) • La que resulta del cálculo de la esperanza matemática: fa(n) • fm es interesante para encontrar cotas inferiores para el mal comportamiento de un algoritmo • Las funciones con los comportamientos más usuales: 1, log n, n, n·log n, n2, n3, ..., 2n, 3n O(1) < O(log n) < O(n) < O(n·log n) < O(n2) < ... < O(2n) < O(n·2n) Eficiencia de los algoritmos
Convenio de Edmonds: • Problema tratable: complejidad polinomial • Problema intratable: complejidad exponencial • Los algoritmos de complejidad mayor que n·log n son poco prácticos • Los exponenciales son válidos para valores pequeños de n • Simbolismos: O, Ω, θ, o Definición 1: f(n) O(g(n)) si c>0 : f(n) c·g(n) • El comportamiento de f está acotado por g • O(g(n)): conjunto de todas las funciones acotadas superiormente por g • Ejemplo: • sea P(n) = am·nm + ... + a1·n + a0 • P(n) O(nm) Eficiencia de los algoritmos
Propiedades: • g(n) = O(g(n)) • c·O(g(n)) = O(g(n)), donde c es una constante • O(g(n))+O(g(n)) = O(g(n)) • O(g(n))·O(h(n)) = O(g(n)·h(n)) • h(n)·O(g(n)) = O(h(n)·g(n)) • O(g(n))+O(h(n)) = O del mayor • O(g(n))-O(g(n)) = O(g(n)) • La notación O la utilizaremos en la búsqueda de cotas superiores del comportamiento de una función de complejidad (la menor cota superior posible) • Observación: n=O(n) ; n=O(n2) ; n=O(n3) se toma la menor Eficiencia de los algoritmos
Definición 2: f(n) Ω(g(n)), si existe una constante real positiva tal que f(n) c·g(n) a partir de un n0 • Propiedades análogas a las de O • Ω se emplea para acotar inferiormente la función de complejidad en el mejor de los casos • Se toma la mayor de las posibles • Definición 3: f(n) θ(g(n)) si existen dos constantes reales positivas tal que c1·g(n) f(n) c2·g(n) a partir de un n0 • Significa que f(n) es tanto O(g(n)) como Ω(g(n)) • θ(g(n))=O(g(n)) Ω(g(n)) • Definición 4: • f(n) o(g(n)) para n si f(n)=α(n)·g(n) • α(n) es un infinitésimo en n (tiene límite 0 cuando n) • f(n) g(n) si f(n)-g(n)=o(g(n)) ( se dice que f es asintóticamente equivalente a g) Eficiencia de los algoritmos
Definición formalizada del orden de los órdenes: • O(f(n)) < O(g(n)) si f(n) = (n) o(g(n)) • En vez de O, se puede poner Ω ó θ • Ejemplo: Un polinomio P(n)= am·nm+...+a1·n+a0 es asintóticamente equivalente a su primer término. • Propiedad: si f(n) g(n) θ(f(n)) θ(g(n)) • Puedo intercambiar una función por otra (asint. equiv.) • Existen dos estudios posibles sobre el tiempo de ejecución de un algoritmo: • Obtener una medida teórica a priori mediante la función de complejidad • Obtener una medida real del algoritmo, a posteriori, para unos valores concretos en un computador determinado • No se puede medir el tiempo en segundos porque no existe un ordenador estándar de referencia número de operaciones • Principio de invarianza (máquinas distintas o códigos distintos) Eficiencia de los algoritmos
Cómo contar el número de operaciones: • Operaciones elementales: las que realiza el computador en tiempo acotado por una constante: • operaciones aritméticas básicas • asignaciones de tipos predefinidos • saltos (llamadas a funciones, proced. y retorno) • comparaciones lógicas • Acceso a estructuras indexadas básicas (vectores y matrices) • Es posible realizar el estudio de la complejidad de un algoritmo sólo en base a un conjunto reducido de sentencias, las que más influyen en el tiempo de ejecución. • Ejemplo... Eficiencia de los algoritmos
Algoritmo de ordenación por inserción directa desde i=2 hasta n hacer x := a[i] a[0] := x j := i - 1 mientras x < a[j] hacer a[j+1] := a[j] j := j - 1 fin mientras a[j+1] := x fin desde • Mejor caso: O(n) • Peor caso: O(n2) • Caso medio: O(n2) Eficiencia de los algoritmos
Resultados prácticos en el cálculo de complejidades • Fórmulas frecuentes en la búsqueda de órdenes de complejidad • Suma de potencias: • 1i n ik ( nk+1 / (k+1) ) siendo k una constante • 1i n ik = O(nk+1) 1i n i = O(n2) • 1i n xi = O(xn) siendo x una constante • Suma de logaritmos • 1i n log i log i = O(n·log n) • Suma de fracciones • 1i n 1/i log n + e = O(log n) • 1i n 1/ic = O(1) c>1 cte • 1i n 1/xi = O(1) x cte • O(1/n) = O(1) Eficiencia de los algoritmos
Técnicas básicas para el análisis de los algoritmos • El análisis se realiza desde dentro hacia fuera • Secuencias: • P1, P2son fragmentos del mismo algoritmo t1, t2 • Regla de la composición secuencial: P1; P2 es t1+ t2 • Por la regla del máximo: O(f(n) + g(n)) = O(max(f(n),g(n))) • Bucles for: • Para i=1 hasta m hacer P(i) • Siendo t el tiempo necesario para calcular P(i) • Caso sencillo (t es una cte) : m·t • Considerando las sentencias de control • Despreciarlas puede dar lugar a graves errores • Se considera O(m·t) con algún umbral m1 • Se considera O(n) Eficiencia de los algoritmos
Caso complejo (t es función de i): • Se trata de operaciones aritméticas complejas • Se consideran más costosas cuanto mayores sean los operandos y cuanto mayor sea m • Tiempo de calcular una operación en la iteración k c·k para k1: • Tiempo algoritmo 1i n c·k = c·1i n k = c·n·(n+1)/2 O(n2) • Contar o no las operaciones como de coste unitario influye bastante • Bucles for que comiencen en un valor diferente de 1 o que avancen a pasos mayores que 1: • (Final-principio)/salto +1 • Ejemplo de caso complejo: cálculo sucesión de Fibonacci Eficiencia de los algoritmos
Bucles Mientras y Repetir: • No existe una forma sencilla de conocer el número de iteraciones • Dos técnicas: • Hallar una función de las variables implicadas, cuyo valor se decremente en cada iteración • Tratarlo como un algoritmo recursivo • Ejemplo: Búsqueda binaria: encontrar un elemento x en un vector T[1..n] ordenado crecientemente. i=1;j=n mientras i<j hacer k=(i+j)/2 caso_de x<T[k]: j=k-1 x=T[k]: i=k ; j=k x>T[k]: i=k+1 fin_caso fin_mientras devolver i Eficiencia de los algoritmos
Solución buscando una función: • La función es j-i+1 • El bucle termina cuando i j 0 j-i 1 j-i+1 (d=j-i+1) • En cada pasada d’=d/2 si xT[k] y d’=1 si x=T[k] • En la vuelta m dm dm-1 /2 dm n/2m • La sucesión es 1 ... n/8 n/4 n/2 n • Calculamos m=lg n (en base 2) O(lg n) • Considerando que es una función recursiva: • t(d) es el tiempo máximo para terminar el bucle • t(d) tiempo-cte-una-iteración + t(d/2) • t(n) O(log n) • Ejemplo: algoritmo recursivo de la sucesión de Fibonacci • Otros: • Sentencias if • Sentencias case • Llamadas a procedimientos o funciones Eficiencia de los algoritmos
Resolución de recurrencias: • Cuatro técnicas: • Expansión de la recurrencia • Ecuaciones características • Cambio de variable • Transformación de intervalo 1. Expansión de la recurrencia: • Se obtiene una fórmula general a partir de varios valores • Ejemplo: función factorial funcion factorial(n:integer):integer if n 1 factorial=1 else factorial=n·factorial(n-1) fin_funcion Eficiencia de los algoritmos
d si n 1 c + T(n-1) si n > 1 • T(n)= • La recurrencia a calcular es T(n)=c+T(n-1) T(n-1)=c+T(n-2) n2 T(n)=2·c+T(n-2) n2 T(n-2)=c+T(n-3) n3 T(n)=3·c+T(n-3) n3 ... T(n)=i·c+T(n-i) ni y llegará un momento en que n-i=1 (acabará) Si n-i=1 i=n-1 T(n) = c·(n-1)+T(1) = c(n-1) + d O(n) • Nota: es más correcto utilizar θ en vez de O • Esta técnica se aplica cuando sólo hay un término en t, aunque esté multiplicado o sumado por una constante Eficiencia de los algoritmos
2. Técnica de la ecuación característica • Tres tipos: • Recurrencias homogéneas lineales con coeficientes constantes • Recurrencias no homogéneas • Otras 2.1 Recurrencias homogéneas con coeficientes constantes • a0tn + a1tn-1 +...+ aktn-k = 0 (e-1) • Lineal: no aparecen productos o potencias de t • Homogénea: la combinación lineal de ti es igual a 0 • Los ai son constantes • Generalmente los algoritmos recursivos suelen tener una ecuación no homogénea ... • Si hacemos tn=xn a0xn + a1xn-1 + ... + akxn-k = 0 dividiendo por xn-k a0xk + a1xk-1 + ... + ak = 0 • Ejemplo: función FibRec Eficiencia de los algoritmos
funcion FibRec(n) • si n<2 devolver n • sino devolver FibRec(n-1)+FibRec(n-2) • fin_funcion • Ecuación de la recurrencia: tn – tn-1 – tn-2 = 0 • Dos posibles formas de resolver la ecuación: • Raíces distintas: • se aplica el teorema fundamental del álgebra • Raíces múltiples: • Si el polinomio característico tiene raíces múltiples, es decir, las k raíces no son todas distintas Eficiencia de los algoritmos
Teorema fundamental del Álgebra • Todo polinomio p(x) de grado k posee k raíces de tal modo que p(x) = i=1,k (x-ri) donde ri son las soluciones de p(x)=0 como p(x)=0 y x=ri y tn=xn entonces rin es una solución de la recurrencia • Toda combinación lineal de soluciones es también una solución xn = tn = i=1,k cirin donde c1, c2, ... cn son constantes • La ecuación (e-1) sólo posee soluciones de esta forma cuando los ri son distintos • Ejemplo 1: tn = • Ejemplo 2: tn= n n=0,n=1 tn-1 + tn-2 n>1 n n=0,n=1 tn-1 + tn-2 n>1 0 n=0 1 n=1 3tn-1+4tn-2 en otro caso Eficiencia de los algoritmos
Raíces múltiples: • Ahora tenemos (x-r1)m1 (x-r2)m2··· (x-rk)mk • Esta nueva ecuación se resuelve mediante: T(n) = i=1,m1 c1ini-1r1n + i=1,m2 c2ini-1r2n + ... + i=1,mk ckini-1rkn O lo que es equivalente: T(n)= i=1,k j=1,mi cijnj-1rin donde los cij 1i k y 1j mi se determinan con las condiciones iniciales • Ejemplo: • T(n) = n si n=0,1,2 5tn-1 - 8tn-2 + 4tn-3 en otro caso Eficiencia de los algoritmos
2.2 Recurrencias no homogéneas • Un recurrencia es no homogénea cuando la combinación lineal no es igual a 0 • a0tn + a1tn-1 +...+ aktn-k = bn·p(n) • Donde b es cte y p(n) es un polinomio de grado d • Solución: reducir al caso homogéneo: • Con habilidad matemática • Aplicando el polinomio característico (tn=xn) • (a0xk + a1xk-1 + ... + ak)·(x-b)d+1 donde d es el grado de p(n) • Las ctes se determinan con las condiciones iniciales y con la propia recurrencia • Ejemplo de 1: tn – 2·tn-1 = 3n • Ejemplo de 2: • T(n) = • t(n) – 2t(n-1) = 1 0 si n=0 2t(n-1) + 1 en otro caso Eficiencia de los algoritmos
Ejemplo con raíces múltiples: • tn = 2·tn-1 + n (a) • Polinomio característico: (x-2)(x-1)2 • Solución de la forma: tn = c12n + c21n + c3n1n (b) • Para obtener las ctes sustituimos (b) en (a) • (...) • Solución: (2n) • Nota: se puede obtener c1, c2, c3 como función de t0 y los valores de t1 y t2 a partir de la ecuación. • Para obtener el orden exacto a veces es imprescindible conocer los valores de las constantes • Ejemplo: • tn = • Solución general: tn = c14n + c22n parece (4n) 1 si n=0 4tn-1 – 2n en otro caso Eficiencia de los algoritmos
Recurrencias de la forma: • a0tn + a1tn-1 +...+ aktn-k = b1n·p1(n) + b2n·p2(n) + ... • bi 0 y pi(n) son polinomios en n de grado di • Se resuelven usando el polinomio característico: • (a0xk + a1xk-1 + ... + ak) (x-b1)d1+1(x-b2)d2+1... • Contiene un factor por el término de la izquierda y tantos como términos haya en la parte derecha • Ejemplo: • tn = • tn – 2tn-1 = n + 2n polinomio característico (x-2)(x-1)2(x-2) • Soluciones de la forma: • tn = c11n + c2n1n + c32n + c4n2n t(n) O(n·2n) • para saber si es (n·2n) tenemos que calcular las constantes (...) 0 si n=0 2tn-1 + n + 2n en otro caso Eficiencia de los algoritmos
3. Resolución de recurrencias mediante el cambio de variable • T(n) término de una recurrencia original • Ti término de un nueva recurrencia obtenida de la original mediante cambio de variable • Ejemplo: • t(n) = • a) n = 2i i=lg2 n ; para transformarla en algo conocido hacemos: • ti = t(2i) • ti = t(2i) = 3t(2i-1) + 2i ti – 3ti-1 = 2i (x-2)(x-3) • ti = c1·3i + c22icomo i = lg2 n y clg n=nlg c • ti = c1nlg 3 + c2nlg 2 t(n) O(nlg 3) (a) • para determinar el orden exacto hay que calcular c1 y c2 • b) cálculo de las constantes • -sustituyendo (a) en la ecuación de recurrencia • -Obtener t(n) en dos puntos, obteniendo dos ecuaciones 1 si n=1 3t(n/2) + n si n es potencia de 2, n>1 Eficiencia de los algoritmos
Ejemplo: • T(n) = 2·T(n/2) + n·lg n siendo n potencia de 2 • ti = T(2i) = 2·T(2i-1) + 2i ·i = 2·ti-1 + 2i ·i • raíces: (x-2)(x-2)2 • ti = c1·2i + c2·i2i + c3·i2·2i T(n) = c1n + c2nlg n + c3nlg2n • O(n·lg2n) siendo n potencia de 2 • Obtenemos los coeficientes (...) (nlg2n) • Caso general: • n0 1 ; l 1 ; b 2 ; k 0 enteros • c>0 real • T:NR+ no decreciente • T(n) = l· T(n/b) + c·nk n >n01 , n/n0 es potencia exacta de b, es decir, • n {bn0, b2n0, b3n0, ...} • cambio de variable adecuado: • n=bi·n0 ti = T(bi·n0) = l· T(bi-1·n0) + c·(bi·n0)k = l·ti-1 + c·n0kbik • ti – l·ti-1 = c·n0k·(bk)i (x-l)(x-bk)d+1 Eficiencia de los algoritmos
Las soluciones son de la forma: • ti = c1li + c2(bk)i como n=bin0, i=logb(n/n0) • si deshacemos el cambio de i (...) • T(n) = c3nlogbl + c4·nk (a) • Para conocer las constantes : • sustituimos (a) en la recurrencia original • c·nk = T(n) – l·T(n/b) (...) c4 = c/(1 – (l/bk)) • Para expresar T(n) en notación asintótica, necesitamos saber el cuál es el término dominante en (a), tenemos 3 casos: • 1) si l<bk c4>0 y k>logbl c4nk dominante • T(n) (nk | n/n0 potencia exacta de b) • 2) si l>bk c4<0 y k< logbl c3 >0 c3nlogbl dominante • T(n) (nlogbl | n/n0 sea potencia de b) • 3) si l=bk problema en c4de división por 0 • el polinomio característico tiene 1 raíz de m=2 • solución general: ti = c5(bk)i + c6i(bk)i como i=logb(n/n0) • T(n) = c7nk + c8nklogb(n/n0) obtenemos (...) c8=c • término dominante: cnklogbn T(n) (nklogbn) Eficiencia de los algoritmos
Resumen: • T(n) = l·T(n/b) +c·nk • T(n) = • Observación: en la notación asintótica no es necesario especificar la base del algoritmo por la propiedad: • logan = logab · logbn O(logan) = O(logbn) (nk) si l<bk (nk log n) si l=bk (nlogbl) si l>bk Eficiencia de los algoritmos
4. Resolución de recurrencias por transformaciones de intervalo • El cambio de variable transforma el dominio de la recurrencia • Podemos transformar el intervalo para obtener una recurrencia que se pueda resolver • Se pueden utilizar ambas transformaciones • Ejemplo: • T(n) = • 1) Cambio de variable: ti=T(2i) n=2i i=lg n • ti = T(2i) = 2iT2(2i-1) = 2iti-12 no lineal y 2i no cte • 2) Transformar el intervalo o rango ni=lg ti ti=2ni • ni=lg ti = log (2iti-12 ) = log (2i) + log (ti-12 ) = i + 2lg ti-1 = • = i +2ni-1 ni – 2ni-1 = i cuyo pol. caract. es (x-2)(x-1)2 • ni = c12i + c21i + c3i1i • obtengo las ctes (...) c3=-1, c2=-2 • deshacer el 2º cambio: ti = 2ni = 2c12i - 2 – i • deshacer el 1er cambio: T(n) = tlg n = (...) = 2c1n / 4n ¿c1? ... 1/3 si n=1 nT2(n/2) en otro caso Eficiencia de los algoritmos