Está en la página 1de 41

Programaci on din amica

Problemas, algoritmos y programaci on

31 de Agosto 2011

Problemas, algoritmos y programaci on

Programaci on din amica

Problema: di

El comando di di es un comando de Linux que muestra las diferencias en el contenido de dos textos (equivalente a fc.exe de Windows/DOS) C uando se usa? Se usa, entre otras cosas, para comparar ediciones (versiones) de un mismo archivo C omo compara? El criterio por defecto es buscar l neas comunes a ambos archivos.

Problemas, algoritmos y programaci on

Programaci on din amica

Problema: di - Ejemplo

Nueva versi on
/** * main class of diff program */ */ class Diff { /* calculate common lines */ int commonLines(File a, File b) { String contentA = read(a); //fixed String contentB = read(b); ParsedText pA = parse(contentA); ParsedText pB = parse(contentB); int result = LCS.calculate(pA, pB); return result; } }

Versi on original
class Diff { int commonLines(File a, File b) { String contentA = read(b); String contentB = read(b); String[] pA = split(contentA); String[] pB = split(contentB); int result = LCS.calculate(pA, pB); return result; } }

Referencia de colores l neas sin cambios l neas nuevas l neas eliminadas

Problemas, algoritmos y programaci on

Programaci on din amica

Problema: di

Operaciones de mociaci on Sin operaci on : las l neas comunes Inserci on : las l neas no comunes del nuevo Borrado : las l neas no comunes del original Cu al es el problema? Para hacer una buena comparaci on de archivos, hay que tener un algoritmo que encuentre la mayor cantidad de l neas comunes entre as, las l neas comunes tienen que aparecer con el ambos. Adem m smo orden en ambos archivos.

Problemas, algoritmos y programaci on

Programaci on din amica

Problema: di
Generalizaci on A este problema se lo conoce como encontrar la sub-secuencia com un de mayor longitud (o Longest Common Subsequence) Longest Common Subsequence Entrada: dos sequencias (vectores, arreglos) A y B Salida: la longitud de la sub-secuencia com un a A y a B mas larga posible LCS : (T [], T []) int Ejemplos LCS ([X AABBDZ ], [AX AC BDY ]) = 4 LCS ([], [XXYY ]) = 0 LCS ([123456], [123456]) = 6 LCS ([], []) = 3
Problemas, algoritmos y programaci on Programaci on din amica

Problema: di - C omo se puede resolver?

M as problemas Se calculan las LCS de todos los prejos de A contra todos los prejos de B Entre estos resultados est a la LCS de A y B Si n y m son el tama no de A y B, la cantidad de LCS que se van a calcular son (n + 1)(m + 1) Cada prejo de A se puede identicar con su longitud, que es un n umero del 0 al n. De la misma forma, cada prejo de B se identica con los n umeros del 0 al m. LCS2 : (int , int , T [], T []) int

Problemas, algoritmos y programaci on

Programaci on din amica

Problema: di - C omo se puede resolver?


Ejemplo con los archivos Prejo 8
/** * main class of diff program */ */ class Diff { /* calculate common lines */ int commonLines(File a, File b) { String contentA = read(a); //fixed String contentB = read(b);

Prejo 5
class Diff { int commonLines(File a, File b) { String contentA = read(b); String contentB = read(b); String[] pA = split(contentA);

Algunos valores de LCS2 LCS2 (8, 5, nuevo , original ) = 3 LCS2 (4, 1, nuevo , original ) = 1 LCS2 (5, 0, nuevo , original ) = 0 LCS2 (5, 1, nuevo , original ) = 1 LCS2 (6, 2, nuevo , original ) = 2
Problemas, algoritmos y programaci on Programaci on din amica

Problema: di - C omo se puede resolver?

Caso 1/3 - Base Alguno de los dos prejos tiene longitud 0, entonces la LCS es 0 LCS2 (0, , , ) = 0 LCS2 ( , 0, , ) = 0

Problemas, algoritmos y programaci on

Programaci on din amica

Problema: di - C omo se puede resolver?


Caso 2/3 - Terminan igual Los dos prejos terminan con el mismo elemento, entonces hay una LCS para estos prejos que termina en este elemento com un. Ejemplo con los archivos Prejo 6
/** * main class of diff program */ */ class Diff { /* calculate common lines */ int commonLines(File a, File b) {

Prejo 2
class Diff { int commonLines(File a, File b) {

Cu anto vale LCS2 ? A[i 1] = B [j 1] LCS2 (i , j , A, B ) = 1 + LCS2 (i 1, j 1, A, B )


Problemas, algoritmos y programaci on Programaci on din amica

Problema: di - C omo se puede resolver?


Caso 3/3 - Terminan distinto Los dos prejos terminan con distintos elementos, entonces hay una LCS para estos prejos que no usa, al menos, una terminaci on. Ejemplo con los archivos Prejo 6
/** * main class of diff program */ */ class Diff { /* calculate common lines */ int commonLines(File a, File b) {

Prejo 3
class Diff { int commonLines(File a, File b) { String contentA = read(b);

Cu anto vale LCS2 ? A[i 1] = B [j 1] LCS2 (i , j , A, B ) = LCS2 (i , j 1, A, B ) max LCS2 (i 1, j , A, B )


Problemas, algoritmos y programaci on Programaci on din amica

Problema: di - C omo se puede resolver?

Denici on partida de LCS2


0 1 + LCS2 (i 1, j 1, A, B ) LCS2 (i , j 1, A, B ) max LCS2 (i 1, j , A, B ) i =0j =0 A[i 1] = B [j 1] A[i 1] = B [j 1]

LCS2 (i , j , A, B ) =

LCS en base a LCS2 LCS (A, B ) = LCS2 ( largo (A), largo (B ), A, B )

Problemas, algoritmos y programaci on

Programaci on din amica

Problema: di - C omo se puede programar?

Primeras consideraciones Si se dispone de la funci on LCS2 , la funci on LCS se programa muy simplemente La funci on LCS2 se puede programar recursivamente Los argumentos A y B de LCS2 son siempre los mismos Entonces LCS2 se puede programar como una funci on recursiva de dos variables (los prejos i y j ). Los arreglos A y B se pueden considerar como variables globales El caso base de la recursi on es cuando i = 0 o j = 0

Problemas, algoritmos y programaci on

Programaci on din amica

Problema: di - C omo se puede programar?


Una cosa m as: el arbol de llamadas Para calcular LCS2 (i , j ) se necesita el valor de LCS2 (i 1, j ), LCS2 (i , j 1) y LCS2 (i 1, j 1). i 3, j i 2, j i 1, j i, j i, j 1 i, j 2 i, j 3 Hay m ultiples llamadas iguales!
La funci on LCS2 recorre todas las sub-sequencias comunes. No hacer la misma llamada dos veces es fundamental para resolver el problema con una complejidad temporal optima Problemas, algoritmos y programaci on Programaci on din amica

i 2, j 1 i 1, j 2

i 1, j 1

Problema: di - C omo se puede programar?


Primer programa: recursi on memorizada (memoization)
T[] A, B; int mem[][]; int lcs(T[] a, T[] b) { A = a; B = b; int n = length(A), m = length(B); init(mem, n+1, m+1, -1); return lcs2(n, m); } int lcs2(int i, int j) { if( mem[i][j] == -1 ) { if( i == 0 || j == 0 ) { mem[i][j] = 0; } else if( A[i-1] == B[j-1] ) { mem[i][j] = 1 + lcs2(i - 1, j - 1); } else { mem[i][j] = max(lcs2(i - 1, j), lcs2(i, j - 1)); } } return mem[i][j]; }

Observaci on Este programa calcula todos los valores de la funci on LCS2 en la matriz mem
Problemas, algoritmos y programaci on Programaci on din amica

Problema: di - C omo se puede programar?


Recursi on vs. C alculo de valores de la matriz mem
0, 0 0, 1 0, 2 0, 3 0, 4 0, 5 0, 6 0, m

1, 0

1, 1

1, 2

1, 3

1, 4

1, 5

1, 6

1, m

2, 0 . . . n, 0

2, 1 . . . n, 1

2, 2 . . . n, 2

2, 3 . . . n, 3

2, 4 . . . n, 4

2, 5 . . . n, 5

2, 6 . . . n, 6

. ..

2, m . . . n, m

Recursi on (dependencia) i 1, j 1 i 1, j

C alculo de mem 0, 0 0, m

i, j 1

i, j

n, 0
Programaci on din amica

n, m

Problemas, algoritmos y programaci on

Problema: di - C omo se puede programar?


Observaci on Se puede eliminar la recursi on calculando los valores de mem directamente. El orden en que se vayan calculando los valores debe satisfacer todas las dependencias. Segundo programa: sin recursi on
int mem[][]; int lcs(T[] A, T[] B) { int n = length(A), m = length(B); init(mem, n+1, m+1, -1); for(i : 0 ... n) { for(j : 0 ... m) { if( i == 0 || j == 0 ) { mem[i][j] = 0; } else if( A[i-1] == B[j-1] ) { mem[i][j] = 1 + mem[i - 1][j - 1]; } else { mem[i][j] = max(mem[i - 1, j], mem[i, j - 1]); } } } return mem[n][m]; }

Problemas, algoritmos y programaci on

Programaci on din amica

Problema: di - C omo se puede programar?


Segundo programa: sin recursi on La complejidad temporal es O (n.m) La complejidad espacial es O (n.m). Se puede hacer mejor? Se puede hacer en complejidad espacial O (n + m) ( optimo). Observaci on: La comparaci on de elementos La complejidad temporal O (n.m) asume que la comparaci on de elementos es O (1) (constante) Si son elementos complejos se puede hacer un hashing inicial de los mismos para facilitar la comparaci on Observaci on: Obtener la sub-sequencia El algoritmo presentado calcula s olo la longitud, pero siguiendo la tabla de atr as hacia adelante se puede obtener una sub-sequencia com un de mayor longitud
Problemas, algoritmos y programaci on Programaci on din amica

Programaci on din amica

Introducci on Programaci on Din amica es una t ecnica para resolver cierto tipo de problemas (como LCS)

Problemas, algoritmos y programaci on

Programaci on din amica

Programaci on din amica: Deniciones


Problema Un problema dene un valor buscado (resultado) sobre ciertos par ametros gen ericos (entrada) Ejemplo: LCS Entrada: Dos arreglos Resultado: La longitud de la sub-secuencia com un mas larga Ejemplo: Ordenamiento Entrada: Un arreglo Resultado: Un arreglo con los elementos ordenados Ejemplo: SAT Entrada: Un sistema de ecuaciones booleanas Resultado: La satisfacibilidad del sistema
Problemas, algoritmos y programaci on Programaci on din amica

Programaci on din amica: Deniciones


Instancia de un problema Es un problema con par ametros de entrada concretos (no gen ericos). Toda instancia tiene un resultado denido. Ejemplo: LCS LCS de XAABBDZ y AXACBDY 4 LCS de 123456 y 123456 6 Ejemplo: Ordenamiento Ordernar: [perro,casa,gato] [casa,gato,perro] Ordernar: [0, 3, 0, 3, 4, 5, 6] [0, 0, 3, 3, 4, 5, 6] Ejemplo: SAT El sistema a b es satisfacible? S b (a b )
Programaci on din amica

Problemas, algoritmos y programaci on

Programaci on din amica: Deniciones


Problema recursivo En un problema recurisvo el resultado de una instancia se puede obtener en base a otros resultados de instancias mas chicas del mismo problema (sub-problemas / sub-instancias) Ejemplo: LCS El resultado se puede obtener combinando resultados de los prejos. Ejemplo: Ordenamiento El resultado se puede obtener encontrando el menor, intercambiarlo con el primero y ordenando el resto (Selection sort) El resultado se puede obtener ordenando dos mitades del arreglo y combinando ambos resultados (Merge sort)
Problemas, algoritmos y programaci on Programaci on din amica

Programaci on din amica: Aplicaciones


Sub-problemas La programaci on din amica es u til si la cantidad de sub-problemas es abaracable computacionalmente Ejemplos: LCS y Ordenamiento Mal ejemplo: SAT (por algo es NP completo) Sub-problemas superpuestos La programaci on din amica es u til si distintos sub-problemas se pueden resolver en base a sub-sub-problemas comunes Ejemplo: LCS (as se ve en el arbol de llamadas) Mal ejemplo: Merge sort Principio de optimalidad La soluci on de un problema esta formada por soluciones de sub-problemas (sub-soluciones)
Problemas, algoritmos y programaci on Programaci on din amica

Programaci on din amica: Aplicaciones


Principio de optimalidad - Ejemplos Camino m nimo: Si el camino mas corto de A a B pasa por C, ese camino est a formado por un camino m nimo de A a C y otro de C a B LCS: La soluci on contiene pedazos que son LCS de sus prejos Principio de optimalidad y recursi on Un problema que cumpla con el principio de optimalidad se puede abaracar como problema recursivo sub-problemas sub-soluciones

Problemas, algoritmos y programaci on

Programaci on din amica

Programaci on din amica: Resumen


Problemas Con sub-problemas Que cumplan el principio de optimalidad Superpuestos Algoritmos Enfoque recursivo Inducci on / Inducci on estructural Divide & Conquer Programaci on Memoization (funci on recursiva memorizada) Llenado de tabla
Problemas, algoritmos y programaci on Programaci on din amica

Problema: Distancia de edic on (Edit Distance)

Problema Encontrar la menor cantidad de ediciones para llegar de una palabra a otra. Operaciones de edici on Eliminaci on de una letra Inserci on de una letra Substituci on de una letra Ejemplo: gato blanco gato (g b) bato (+ n) banto (+ l) blanto (t c) blanco La distancia de edici on es 4

Problemas, algoritmos y programaci on

Programaci on din amica

Problema: Distancia de edic on (Edit Distance)


Variantes del problema Las variantes del problema se dan al cambiar las operaciones posibles Solo con eliminaci on e inserci on se reduce a LCS Eliminaci on, inserci on y substituci on: distancia de Levenshtein Agregando transposici on de letras: distancia de Levenshtein-Damerau Todas esta variantes se pueden resolver usando programaci on din amica Usos comunes Corregir errores de tipeo Detecci on de fraude Encontrar variaciones en ADN
Problemas, algoritmos y programaci on Programaci on din amica

Problema: Distancia de edic on (Edit Distance)

Edit distance Entrada: dos cadenas A y B Salida: la distancia de Levenshtein entre A y a B LEV : (String , String ) int Una soluci on con programaci on din amica Enfoque similar al usado en LCS Se calculan las distancias de todos los prejos de A a todos los prejos de B LEV2 : (int , int , String , String ) int

Problemas, algoritmos y programaci on

Programaci on din amica

Problema: Distancia de edic on (Edit Distance)


Determinar LEV2 (similar a LCS2 ) Caso base: alguno de los prejos tiene longitud 0, la distancia es la longitud del otro Terminan igual: lo optimo es que esas letras se correspondan y no se haga ninguna operaci on al nal de A LEV ( gato, blanco ) = LEV ( gat, blanc ) Terminan distinto: se tiene que aplicar alguna operaci on al nal de A LEV ( gat, blanc ) es el m nimo de:
(insertar c) 1 + LEV ( gatc, blanc ) (insertar c) 1 + LEV ( gat, blan ) (borrar t) 1 + LEV ( ga, blanc ) (t c) 1 + LEV ( gac, blanc ) (t c) 1 + LEV ( ga, blan )

Problemas, algoritmos y programaci on

Programaci on din amica

Problema: Distancia de edic on (Edit Distance)

Denici on partida de LEV2 LEV2 (i , j , A, B ) = i +j LEV2 (i 1, j 1, A, B ) LEV2 (i , j 1, A, B ) LEV2 (i 1, j , A, B ) 1 + min LEV2 (i 1, j 1, A, B )

i =0j =0 A[i 1] = B [j 1]

A[i 1] = B [j 1]

Problemas, algoritmos y programaci on

Programaci on din amica

Problema: Distancia de edic on (Edit Distance)


Posible implementaci on (sin recursi on)
int mem[][]; int lev(T[] A, T[] B) { int n = length(A), m = length(B); init(mem, n+1, m+1, -1); for(i : 0 ... n) { for(j : 0 ... m) { if( i == 0 || j == 0 ) { mem[i][j] = i + j; } else if( A[i-1] == B[j-1] ) { mem[i][j] = mem[i - 1][j - 1]; } else { mem[i][j] = 1 + min(mem[i - 1, j], mem[i, j - 1], mem[i - 1, j - 1]); } } } return mem[n][m]; }

Observaciones El orden de llenado satisface las dependencias Complejidad temporal: O (n.m), espacial: O (n.m) Se puede lograr complejidad espacial O (n + m)
Problemas, algoritmos y programaci on Programaci on din amica

Otros problemas de cadenas


Transformar en pal ndromo Problema: Dada una cadena, encontrar la m nima cantidad de ediciones para transformarla en pal ndromo (capic ua) Sub-problemas a considerar: todas las sub-cadenas (recortes) de la original. Complejidad temporal: O (n2 ) Compresi on RLE (run-length encoding) Problema: Dada una cadena, encontrar una compresi on RLE de tama no m nimo. Un ejemplo de compresi on RLE de la cadena XAABCBCBCAABCBCBCX es X2(2A3(BC))X. Sub-problemas a considerar: todas las sub-cadenas (recortes) de la original. Tambi en hay que detectar cuales sub-cadenas son repeticiones. AABCBCBCAABCBCBC 2(AABCBCBC) Complejidad temporal: O (n3 )
Problemas, algoritmos y programaci on Programaci on din amica

Problema: Mayor sub-sequencia creciente


Descripci on Dada una sequencia de n umeros, encontrar el m aximo largo de una sub-sequencia con sus elementos en orden estrictamente creciente LIS : (int []) int Ejemplos LIS ([0, 8, 4, 12, 2, 10, 6, 14, 6, 9, 5]) 4 LIS ([2, 3, 7, 10, 15]) 5 LIS ([]) 0 LIS ([15, 10, 7, 3, 2]) 1 Soluci on O (n2 ) usando LCS Una sub-sequencia creciente de A es una sub-sequencia com un entre A y A ordenada (A). LIS (A) = LCS (A, A)
Problemas, algoritmos y programaci on Programaci on din amica

Problema: Mayor sub-sequencia creciente


Considerando otros sub-problemas y sub-soluciones De todas las sub-secuencias de un mismo tama no siempre es m as u til la que termina en lo menor posible Para cada prejo Ai y cada tama no j , se busca la terminaci on optima de una sub-sequencia creciente. j [1, LIS (Ai )] Si Ti [j ] son estos valores, entonces Ti es creciente y su tama no es LIS (Ai ) Denici on recursiva de T [i ] T1 [1] = A[0] (caso base) Todos los valores de Ti +1 son iguales a los de Ti excepto:
Si A[i ] Ti [1] Ti +1 [1] = A[i ] Si A[i ] > Ti [LIS (Ai )] Ti +1 [LIS (Ai ) + 1] = A[i ] Si Ti [j ] < A[i ] Ti [j + 1]] Ti +1 [j + 1] = A[i ] usqueda binaria El valor que cambia se puede encontrar con b
Problemas, algoritmos y programaci on Programaci on din amica

Problema: Mayor sub-sequencia creciente


Posible implementaci on
int lis(int[] A) { if( length(A) == 0 ) return 0; int[] T = [ A[0] ]; for(i : 1 ... length(A)) { if ( A[i] <= T[0] ) { T[0] = A[i]; } else { int j = binary_search(T, A[i]); if(j == length(T) - 1) { T.add(A[i]); } else { T[j+1] = A[i]; } } } return length(T); }

// mayor j tal que T[j] < A[i]

Observaciones Complejidad temporal: O (n.log (n)) Complejidad espacial: O (n) Se puede aplicar sobre cualquier conjunto con orden total
Problemas, algoritmos y programaci on Programaci on din amica

Problema: C alculo de probabilidades


Calcular la problabilidad de: tirar un dado 6 veces y sumar 20 tirar una moneda 20 veces y sacar 11 caras Algunos c alculos de probabilidad se pueden plantear recursivamente Ejemplo La probabiliad de tirar un dado 6 veces y sumar 20 es la suma de + 1/6 la probabilidad de tirar un dado 5 veces y sumar 19 + 1/6 la probabilidad de tirar un dado 5 veces y sumar 18 + 1/6 la probabilidad de tirar un dado 5 veces y sumar 17 + 1/6 la probabilidad de tirar un dado 5 veces y sumar 16 + 1/6 la probabilidad de tirar un dado 5 veces y sumar 15 + 1/6 la probabilidad de tirar un dado 5 veces y sumar 14
Problemas, algoritmos y programaci on Programaci on din amica

Problema: C alculo de probabilidades


Generalizaci on Los problemas: tirar un dado 6 veces y sumar 20 tirar una moneda 20 veces y sacar 11 caras se pueden generalizar a calcular la probabilidad de sumar s tirando n veces un dado de d caras. P (s , n, d ) [0, 1] Denici on recursiva P (0, 0, ) = 1 y P ( , 0, ) = 0 P (s , n, d ) =
d 1 i =1 d P (s

i , n 1, d )

Observaciones Hay sub-problemas superpuestos d es siempre el mismo Complejidad temporal: O (s .n.d ) y espacial: O (s .n)
Problemas, algoritmos y programaci on Programaci on din amica

Programaci on din amica y juegos


Juegos Algunos juegos pueden ser analizados con programaci on din amica. En especial aquellos que sean: por turnos nitos y sin empate Qu e se puede analizar? Si un estado del juego es ganador o perdedor Si existe alguna estrategia ganadora En cu antas jugadas termina C omo se pueden analizar estos juegos recursivamente? Los estados terminales del juego son los casos bases Un estado no terminal es ganador si existe una jugada que lleva a un estado perdedor (no ganador)
Problemas, algoritmos y programaci on Programaci on din amica

Programaci on din amica sobre subconjuntos


Problema: el viajante de comercio Entrada: un conjunto de n ciudades y los costos cij de viajar de la ciudad i a la j . 0 i , j < n Salida: el costo del itinerario mas barato que visita todas las ciudades una sola vez C (int , int [][]) int Sub-problemas El itinerario m as barato para todos los sub-conjuntos de ciudades (sub-grafo inducido) y todas sus terminaciones. La cantidad de sub-grafos es 2n La cantidad de sub-problemas es O (2n .n) C2 (int , int [][], SubConjunto , int ) int C (n, c ) = min0i <n {C2 (n, c , S , i )} siendo S el sub-conjunto de todas las ciudades (impropio)
Problemas, algoritmos y programaci on Programaci on din amica

Programaci on din amica sobre subconjuntos


Denici on recursiva de C2 C2 ( , , {t }, t ) = 0 C2 (n, c , S , t ) = mini S {t } {c [i ][t ] + C2 (n, c , S {t }, i )} Manipulaci on de sub-conjuntos (m ascara de bits) Los sub-conjuntos de un conjunto de n elementos se pueden asociar, uno a uno, con los n umeros del 0 al 2n El sub-conjunto S se representa con el n umero m (S ) = i S 2i El n umero s representa al sub-conjunto S = {i [0, n 1]/biti (s ) = 1} Si T S m(T ) < m(S ) Si t S (m(S )&2t ) = 2t (& es el and de bits) Si t S m(S {t }) = m(S ) 2t
Problemas, algoritmos y programaci on Programaci on din amica

Programaci on din amica sobre subconjuntos

Nueva denici on recursiva de C2 C2 (int , int [][], int , int ) int C2 ( , , 2t , t ) = 0 C2 (n, c , m, t ) = minm&2i =2i i =t {c [i ][t ] + C2 (n, c , m 2t , i )} Dependencias de C2 El valor de C2 (n, c , m(S ), t ) depende de los valores de C2 para todos los sub-conjuntos de S Los sub-conjuntos de S se representan con un n umero menor a m(S ) C2 se puede calcular en orden creciente de m(S )

Problemas, algoritmos y programaci on

Programaci on din amica

Programaci on din amica sobre subconjuntos


Posible implementaci on
int C(int n, int[][] c) { int mem[1 << n][n]; // 1 << n = 2^n for(m : 1 ... (1 << n) ) { for(t : 0 ... (n - 1) ) { if(bit_count(m) == 1) { mem[m][t] = 0; } else { mem[m][t] = INF; for(i : 0 ... (n - 1)) if ( (m & (1 << i) == (1 << i)) && i != t) { mem[m][t] = min(mem[m][t], mem[m-(1<<t)][i]); } } } } int r = INF; for(i : 0 ... (n - 1)) r = min(r, mem[1<<n - 1][i]; return r; }

Observaciones Complejidad temporal: O (2n .n2 ), espacial: O (2n .n) Es mejor que la fuerza bruta O (n!), para n = 25 es 1015 veces m as r apido y necesita 1G de memoria.
Problemas, algoritmos y programaci on Programaci on din amica

También podría gustarte