Algorítmica y Complejidad Tema Divide y Vencerás.
. Método.. Un ejemplo sencillo.. Complejidad del método.. Ejemplo: El máximo subarray.. Ejemplo: Multiplicación de enteros.
. Método.. Un ejemplo sencillo.. Complejidad del método.. Ejemplo: El máximo subarray.. Ejemplo: Multiplicación de enteros.
Método. Esquema de tres etapas! Dividir. El problema se divide en varios problemas similares de menor tamaño. Resolver. Si los subproblemas son asumibles se resuelven. En caso contrario se vuelve a aplicar el método. Combinar. Se combinan las soluciones de los subproblemas para obtener la solución total.
Método. Características que deben cumplir los problemas para que se pueda aplicar esta técnica: El problema se debe poder descomponer en otros similares pero más pequeños. Los nuevos problemas deben ser disjuntos. Debe ser posible combinar las soluciones individuales para obtener la global.
Método. procedure Divide_y_Vencerás (P : problema) is begin if P es simple then Solucionar P; else Descomponer P en {P, P,..., Pn}; Divide_y_Vencerás (P); Divide_y_Vencerás (P);................... Divide_y_Vencerás (Pn); Combinar las soluciones de {P, P,..., Pn}; end if; end Divide_y_Vencerás;
Método. Hasta donde conviene subdividir el problema? T (n) Algoritmo Inmediato Existirá un umbral n 0 por debajo del cuál será más rápido aplicar el algoritmo inmediato. Algoritmo Div. y Venc. n 0 n El cálculo de n 0 no es trivial y depende de la implementación. Es habitual utilizar métodos empíricos para su determinación.
. Método.. Un ejemplo sencillo.. Complejidad del método.. Ejemplo: El máximo subarray.. Ejemplo: Multiplicación de enteros.
Un ejemplo sencillo. Problema: Encontrar el valor máximo en un array de números enteros." A : - -.... n- n - La solución inmediata sería: function Maximo (i, j : integer) return integer is max : integer := integer'first; begin for k in i.. j loop if A(k) > max then max := A(k); end if; end loop; return max; end Maximo; _ put ("Valor maximo:"); put (Maximo(A'first, A'last));
Un ejemplo sencillo. Enfoque "divide y vencerás":. Dividir el array en dos partes.. Hallar el máximo de cada parte.. Seleccionar el mayor de los dos. Se sigue aplicando de forma recursiva. 0
Un ejemplo sencillo. function Maximo (i, j : integer) return integer is med, max_i, max_d : integer; begin end Maximo; _ put ("Valor maximo:"); put (Maximo(A'first, A'last));
Un ejemplo sencillo. function Maximo (i, j : integer) return integer is med, max_i, max_d : integer; begin if i=j then return A(i); else end if; end Maximo; _ put ("Valor maximo:"); put (Maximo(A'first, A'last));
Un ejemplo sencillo. function Maximo (i, j : integer) return integer is med, max_i, max_d : integer; begin if i=j then return A(i); else med := (i + j) / ; max_i := Maximo (i, med); max_d := Maximo (med+, j); end if; end Maximo; _ put ("Valor maximo:"); put (Maximo(A'first, A'last));
Un ejemplo sencillo. function Maximo (i, j : integer) return integer is med, max_i, max_d : integer; begin if i=j then return A(i); else med := (i + j) / ; max_i := Maximo (i, med); max_d := Maximo (med+, j); if max_i > max_d then return max_i; else return max_d; end if; end if; end Maximo; _ put ("Valor maximo:"); put (Maximo(A'first, A'last));
. Método.. Un ejemplo sencillo.. Complejidad del método.. Ejemplo: El máximo subarray.. Ejemplo: Multiplicación de enteros.
Complejidad del método. Problema Problema a- Problema Problema Problema... Problema a T(n) T(n/b) + T(n/b ) + T(n/b) +... + T(n/b) + T(n/b) a T ( n / b ) Descomposición del problema y combinación de las soluciones O ( n k )
Complejidad del método. En general responderá a esta ecuación: T ( n ) = a T ( n / b ) + O ( n k ) a, b, k 0 a : Número de subproblemas en que se descompone. n/b : Tamaño de cada nuevo subproblema. Cuya solución es: O ( n k ), a < b k T ( n ) = O ( n k log n ), a = b k O ( n log b a ), a > b k Teorema maestro!
Complejidad del método. Complejidad del ejemplo sencillo: (Enfoque Divide y Vencerás) function Maximo (i, j : integer) return integer is med, max_i, max_d : integer; begin if i=j then return A(i); else med := (i + j) / ; max_i := Maximo (i, med); max_d := Maximo (med+, j); if max_i > max_d then return max_i; else return max_d; end if; end if; end Maximo; O ( ) O ( )
Complejidad del método. Complejidad del ejemplo sencillo: (Enfoque Divide y Vencerás) function Maximo (i, j : integer) return integer is med, max_i, max_d : integer; begin if i=j then return A(i); else med := (i + j) / ; max_i := Maximo (i, med); max_d := Maximo (med+, j); if max_i > max_d then return max_i; else return max_d; end if; end if; end Maximo; T ( n / ) T ( n / )
Complejidad del método. Complejidad del ejemplo sencillo: (Enfoque Divide y Vencerás) T ( n ) = a T ( n / b ) + O ( n k ) a = b = k = 0 T ( n ) = T ( n / ) + O ( ) a > b k > 0 > O ( n log b a ) = O ( n log ) = O ( n ) 0
Complejidad del método. Complejidad del ejemplo sencillo: (Enfoque Inmediato) function Maximo (i, j : integer) return integer is max : integer := integer'first; begin for k in i.. j loop if A(k) > max then max := A(k); end if; end loop; return max; end Maximo; O ( n ) Ambos métodos tienen la misma complejidad. Divide y Vencerás es más lento por la recursividad. En este caso es mejor el Enfoque Inmediato.
. Método.. Un ejemplo sencillo.. Complejidad del método.. Ejemplo: El máximo subarray.. Ejemplo: Multiplicación de enteros.
Ejemplo: El máximo subarray. Problema: "Dados varios números que supondremos almacenados en un array, se trata de encontrar la secuencia de números contiguos cuya suma sea máxima." Por ejemplo, dado: 0 A : - - - - La solución sería: cuya suma es. Si existe más de una solución, nos conformaremos con hallar una de ellas.
Ejemplo: El máximo subarray. - - - - 0 - - - - 0 - - - - 0 - - - - 0 - - - - 0 - - - - 0 - - - - 0 - - - - 0 - - - - 0 - - - - 0 - - - - 0 - - - - 0 Una solución inmediata:
Ejemplo: El máximo subarray. procedure Maximo_Subarray is.............. begin max := integer'first; for i in A'range loop suma := 0; for j in i.. A'last loop suma := suma + A(j); if suma > max then O ( n ) max := suma; inf := i; sup := j; end if; end loop; end loop; put ("Indice inferior: "); put (inf); new_line; put ("Indice superior: "); put (sup); new_line; put ("Valor de la suma : "); put (max); new_line; end Maximo_Subarray;
Ejemplo: El máximo subarray. Enfoque "divide y vencerás": Se divide el array en dos partes. 0 Pueden darse tres casos: 0 0 El subarray está totalmente en la parte izquierda. 0 El subarray está totalmente en la parte derecha. El subarray atraviesa la división.
Ejemplo: El máximo subarray. Si el subarray está completamente en uno de los lados, se puede resolver de forma recursiva, finalizando cuando el tamaño sea de un sólo elemento. En el otro caso, el subarray tendrá una parte en el lado izquierdo y otra en el derecho. Las partes se corresponderán con uno de estos casos: 0 0 - - - - - - - - 0 0 - - - - - - - - 0 0 - - - - - - - - 0 0 - - - - - - - - 0 0 - - - - - - - - El máximo subarray estará formado por la unión del de mayor suma en el lado izquierdo y el de mayor suma del lado derecho.
Ejemplo: El máximo subarray. procedure Maximo_Subarray (E_inf, E_sup : in natural; S_inf, S_sup : out natural; S_suma : out integer) is........................................ begin end Maximo_Subarray; _ Maximo_Subarray (A'first, A'last, inf, sup, max);
Ejemplo: El máximo subarray. procedure Maximo_Subarray (E_inf, E_sup : in natural; S_inf, S_sup : out natural; S_suma : out integer) is........................................ begin if E_inf = E_sup then S_suma := A(E_inf); S_inf := E_inf; S_sup := S_inf; else O ( ) end if; end Maximo_Subarray; _ Maximo_Subarray (A'first, A'last, inf, sup, max);
Ejemplo: El máximo subarray. procedure Maximo_Subarray (E_inf, E_sup : in natural; S_inf, S_sup : out natural; S_suma : out integer) is........................................ begin if E_inf = E_sup then S_suma := A(E_inf); S_inf := E_inf; S_sup := S_inf; else med := (E_inf + E_sup) / ; Maximo_Subarray (E_inf, med, inf_i, sup_i, max_i); Maximo_Subarray (med +, E_sup,inf_d, sup_d, max_d); Subarray_Comun (E_inf, med, E_sup, inf_c, sup_c, max_c); O ( ) O ( ) T ( n / ) T ( n / )? end if; end Maximo_Subarray; _ Maximo_Subarray (A'first, A'last, inf, sup, max);
Ejemplo: El máximo subarray. procedure Maximo_Subarray (E_inf, E_sup : in natural; S_inf, S_sup : out natural; S_suma : out integer) is........................................ begin if E_inf = E_sup then S_suma := A(E_inf); S_inf := E_inf; S_sup := S_inf; else med := (E_inf + E_sup) / ; Maximo_Subarray (E_inf, med, inf_i, sup_i, max_i); Maximo_Subarray (med +, E_sup,inf_d, sup_d, max_d); Subarray_Comun (E_inf, med, E_sup, inf_c, sup_c, max_c); if max_i > max_d and max_i > max_c then S_suma := max_i; S_inf := inf_i; S_sup := sup_i; elsif max_d > max_i and max_d > max_c then S_suma := max_d; S_inf := inf_d; S_sup := sup_d; else S_suma := max_c; S_inf := inf_c; S_sup := sup_c; end if; O ( ) O ( ) T ( n / ) T ( n / )? O ( ) end if; end Maximo_Subarray; _ Maximo_Subarray (A'first, A'last, inf, sup, max);
Ejemplo: El máximo subarray. procedure Subarray_Comun (E_inf, med, E_sup : in natural; S_inf, S_sup : out natural; S_suma : out integer) is........................................ begin end Subarray_Comun;
Ejemplo: El máximo subarray. procedure Subarray_Comun (E_inf, med, E_sup : in natural; S_inf, S_sup : out natural; S_suma : out integer) is........................................ begin suma_izq := integer'first; suma_tmp := 0; for i in reverse E_inf.. med loop suma_tmp := suma_tmp + A(i); if suma_tmp > suma_izq then suma_izq := suma_tmp; S_inf := i; end if; end loop; O ( n ) end Subarray_Comun;
Ejemplo: El máximo subarray. procedure Subarray_Comun (E_inf, med, E_sup : in natural; S_inf, S_sup : out natural; S_suma : out integer) is........................................ begin suma_izq := integer'first; suma_tmp := 0; for i in reverse E_inf.. med loop suma_tmp := suma_tmp + A(i); if suma_tmp > suma_izq then suma_izq := suma_tmp; S_inf := i; end if; end loop; suma_der := integer'first; suma_tmp := 0; for i in med+.. E_sup loop suma_tmp := suma_tmp + A(i); if suma_tmp > suma_der then suma_der := suma_tmp; S_sup := i; end if; end loop; O ( n ) O ( n ) end Subarray_Comun;
Ejemplo: El máximo subarray. procedure Subarray_Comun (E_inf, med, E_sup : in natural; S_inf, S_sup : out natural; S_suma : out integer) is........................................ begin suma_izq := integer'first; suma_tmp := 0; for i in reverse E_inf.. med loop suma_tmp := suma_tmp + A(i); if suma_tmp > suma_izq then suma_izq := suma_tmp; S_inf := i; end if; end loop; suma_der := integer'first; suma_tmp := 0; for i in med+.. E_sup loop suma_tmp := suma_tmp + A(i); if suma_tmp > suma_der then suma_der := suma_tmp; S_sup := i; end if; end loop; S_suma := suma_izq + suma_der; end Subarray_Comun; O ( n ) O ( n ) O ( )
Ejemplo: El máximo subarray. Complejidad del enfoque Divide y Vencerás: T ( n ) = O () + O () + T (n / ) + T (n / ) + O (? ) + O () O (n) + O (n) + O () T ( n ) = T ( n / ) + O ( n ) a = b = k = T ( n ) = a T ( n / b ) + O ( n k ) T (n) n O ( n log n ) = O ( n log n ) n n log n
. Método.. Un ejemplo sencillo.. Complejidad del método.. Ejemplo: El máximo subarray.. Ejemplo: Multiplicación de enteros.
Ejemplo: Multiplicación de enteros. Problema: "Dados dos números enteros X e Y de n bits cada uno, calcular su producto Algoritmo tradicional: Ejemplo en decimal: x 00 x 0 00 0000 00 00 0000 Complejidad: O ( n )
Ejemplo: Multiplicación de enteros. Algoritmo alternativo : X n bits Ejemplo en decimal: X X 0 n / bits n / bits X = X n/ + X 0 = 0 / + 000 +
Ejemplo: Multiplicación de enteros. Los números a multiplicar se pueden representar así: X = X n / + X 0 Y = Y n / + Y 0 el producto sería: X Y = ( X n / + X 0 ) ( Y n / + Y 0 ) operando: X Y = X Y n + ( X Y 0 + X 0 Y ) n / + X 0 Y 0 0
Ejemplo: Multiplicación de enteros. + + + X Y = X Y n + ( X Y 0 + X 0 Y ) n / + X 0 Y 0 x x x x sumas desplazamientos multiplicaciones O ( n) O ( n) T(n) = T(n/) + O ( n) a = b = k = > O ( n l o g ) = O(n )
Ejemplo: Multiplicación de enteros. Algoritmo alternativo : Ecuación obtenida por el método anterior: X Y = X Y n + ( X Y 0 + X 0 Y ) n / + X 0 Y 0 ( X X 0 ) ( Y 0 Y ) + X Y + X 0 Y 0 X Y = X Y n + ((X X 0 )(Y 0 Y ) + X Y + X 0 Y 0 ) n / + X 0 Y 0
Ejemplo: Multiplicación de enteros. + + + + + + X Y = X Y n + ((X X 0 )(Y 0 Y ) + X Y + X 0 Y 0 ) n / + X 0 Y 0 x x x x x Iguales Iguales sumas (restas) desplazamientos multiplicaciones O ( n) O ( n) T(n) = T(n/) + O ( n) a = b = k = > O ( n l o g ) = O(n, )