xaoD04ErRuxp0RKl - rub6K3lNRKPv - 5gQ-Lectura Fundamental 6
xaoD04ErRuxp0RKl - rub6K3lNRKPv - 5gQ-Lectura Fundamental 6
1 //Escenario
Escenario26
Lectura fundamental
Fundamental
Programación
Etapas de un plan
dinámica
de comunicación
estratégica
Contenido
2 Distancia de edición
3 Resumen
La programación dinámica es una técnica de diseño de algoritmos que permite evaluar eficientemente
ecuaciones de recurrencia con algunas propiedades. El enfoque recursivo toma un problema y lo
divide en problemas más pequeños, pero de igual naturaleza, hasta alcanzar un caso base en el que la
recursión termina. A este enfoque se le conoce como enfoque hacia abajo, ya que el tamaño de los
subproblemas decrece. La programación dinámica se caracteriza por su enfoque hacia arriba, esto
es, primero se resuelven los problemas más pequeños (casos base) y a partir de ellos se construyen
las soluciones a subproblemas cada vez más grandes, hasta obtener la solución del problema original.
Este enfoque, como se evidenciará a continuación, permite obtener algoritmo de orden polinómico
cuando el enfoque hacia abajo produce algoritmos de orden exponencial.
La presente Lectura fundamental expone las principales ideas de la programación dinámica tomando
como ejemplo los problemas clásicos de la sucesión de Fibonacci y la distancia de edición. La sección
1 describe el algoritmo recursivo para calcular el enésimo número de la sucesión de Fibonacci junto
con su respectivo análisis, expone las características del algoritmo recursivo que lo hacen ineficiente
y presenta la técnica de programación dinámica y como esta es aplicada al problema discutido. La
sección 2 realiza un estudio similar del problema del cálculo de la distancia de edición entre dos
cadenas de textos.
POLITÉCNICO GRANCOLOMBIANO 2
La anterior ecuación sugiere inmediatamente el siguiente algoritmo recursivo para su evaluación:
fib(n)
if n=0 ∨ n=1 then
return n
return fib(n-1) + fib(n-2)
Sea T(n) el tiempo requerido por el algoritmo para calcular fib(n). Además del tiempo que toma
la evaluación de la instrucción condicional y la suma, se debe considerar el tiempo que toma la
evaluación de fib(n-1) y fib(n-2). Se tiene entonces que T(n) es descrito por la ecuación de
recurrencia:
POLITÉCNICO GRANCOLOMBIANO 3
Puede probarse que la ecuación de recurrencia con caso inductivo T(n) = 2T(n-2) y caso base Θ(1)
tiene como solución T(n) = Θ(√2ⁿ). Además, la ecuación de recurrencia con caso inductivo T(n)
= 2T(n-1) y caso base Θ(1) tiene como solución T(n) = Θ(2ⁿ). Se tiene entonces que T(n) =
Ω(√2ⁿ) y T(n) = O(2ⁿ). Por tanto, el algoritmo tiene complejidad temporal exponencial.
Para entender por qué el algoritmo recursivo para calcular los números de Fibonacci es ineficiente,
considere el árbol de recursión resultante de invocar fib(n) presentado en la figura 2.
Una observación rápida que puede hacerse sobre el árbol es que fib(n-2) es calculado dos veces y
fib(n-3) es calculado tres veces. De manera similar, fib(n-4) será calculado cinco veces y fib(n-5)
ocho veces. En general, fib(n-k) será calculado fib(k+1) veces. Dado que los números de Fibonacci
crecen exponencialmente, fib(1) será calculado un número exponencial de veces.
Note que el número ideal de veces que la función fib debería ser invocada es n + 1, una vez por
cada valor entero en el intervalo [0, n]. Se hace evidente que la función recursiva fib repite cálculos
innecesariamente.
POLITÉCNICO GRANCOLOMBIANO 4
1.3. Algoritmo de programación dinámica
El uso de una estructura de datos para mantener los valores ya calculados: esta estructura sirve como
memoria de los resultados intermedios y así evitar realizar cálculos duplicados.
Figura 3. Orden en que son evaluados los subproblemas de la recurrencia de Fibonacci por un algoritmo de programación
dinámica
Fuente: elaboración propia.
POLITÉCNICO GRANCOLOMBIANO 5
La estructura de datos idónea para el problema de Fibonacci es un arreglo F con n + 1 posiciones, tal
que F[i] = fib(i).
El primer paso del algoritmo será llenar las posiciones correspondientes a los casos base:
F[0] := 0
F[1] := 1
Luego, deberán llenarse las posiciones 2 a n, en orden no decreciente. Esto es fácilmente realizable
con una instrucción iterativa:
for i := 2 to n
F[i] := F[i-1] + F[i-2]
fib(n)
F[0] := 0
F[1] := 1
for i := 2 to n
F[i] := F[i-1] + F[i-2]
return F[n]
Dado que el algoritmo consiste en un ciclo que itera n-1 veces, su complejidad es 𝚯(n)1.
2. Distancia de edición
Como segundo ejemplo de aplicación de programación dinámica, se estudiará el problema de calcular
la distancia de edición entre dos palabras.
¹El análisis del algoritmo supone que una suma de dos números arbitrariamente grandes es (1).
POLITÉCNICO GRANCOLOMBIANO 6
Sean S y T cadenas de caracteres. La distancia de edición entre S y T es el mínimo número de cambios
que deben realizarse sobre la cadena S para obtener la cadena T. Existen tres tipos de cambios
(Dasgupta et al., 2006):
• Insertar en S un carácter.
• Eliminar de S un carácter.
A manera de ejercicio, el lector puede verificar que no existe una forma de transformar S en T en un
menor número de cambios.
Para deducir la ecuación de recurrencia que permite calcular la distancia de edición entre S y T se
considerarán dos casos:
²Muhammad ibn Musa al-Khwarizmi fue un matemático persa de cuyo nombre se deriva la palabra algoritmo.
POLITÉCNICO GRANCOLOMBIANO 7
Figura 4. Cuando los últimos caracteres de S y T coinciden, el problema se simplifica ignorando estos caracteres
Fuente: elaboración propia.
Figura 5. (a) El último carácter de S es sustituido por el último carácter de T. (b) El último carácter de T es agregado al
final de S. (c) El último carácter de S es eliminado.
Fuente: elaboración propia.
El mínimo número de cambios requeridos en cada alternativa es igual a 1 más el número de cambios
requeridos en cada subproblema:
i. 1 + distancia(S[0..m-2], T[0..n-2])
POLITÉCNICO GRANCOLOMBIANO 8
distancia(S, T) es el mínimo valor entre los tres anteriores
distancia(S[0..m-1], T[0..n-2]),
distancia(S[0..m-2], T[0..n-1]) )
La ecuación de recurrencia se completa con los casos base (“” representa la cadena vacía)
distancia(“”, T) = n
distancia(S, “”) = m
if m = 0 then
return n
if n = 0 then
return m
if S[m-1] = T[n-1] then
return distancia(S[0..m-2], T[0..n-2])
return 1 + min( distancia(S[0..m-2], T[0..n-2]),
distancia(S[0..m-1], T[0..n-2]),
distancia(S[0..m-2], T[0..n-1]))
Se deja como ejercicio al lector verificar en el árbol de recursión resultante que la función
es invocada múltiples veces con idénticos parámetros. Debido a la repetición de cálculos, el
algoritmo es en peor caso Ω(√3m+n).
POLITÉCNICO GRANCOLOMBIANO 9
2.2. Algoritmo de programación dinámica
El algoritmo primero debe rellenar las posiciones de la matriz correspondientes a los casos base,
esto es, la primera fila y columna de la matriz.
for i := 0 to m
D[i][0] := i
for j := 0 to n
D[0][j] := j
Para llenar el resto de la matriz se deben considerar los dos casos inductivos (S[m-1] = T[n-1] y S[m-1]
≠ T[n-1]). La matriz debe ser recorrida de arriba hacia abajo y de izquierda a derecha.
for i := 1 to m
for j := 1 to n
if S[i-1] = T[j-1] then
D[i][j] := D[i-1][j-1]
else
D[i][j] := 1 + min(D[i-1][j-1], D[i][j-1], D[i-1][j]))
El algoritmo resultante es
distancia(S[0..m-1], T[0..n-1])
for i := 0 to m
D[i][0] := i
for j := 0 to n
D[0][j] := j
for i := 1 to m
for j := 1 to n
if S[i-1] = T[j-1] then
D[i][j] := D[i-1][j-1]
else
D[i][j] := 1 + min(D[i-1][j-1], D[i][j-1], D[i-1][j]))
return D[m][n]
Dado que el código consiste en dos ciclos anidados, iterando cada uno sobre una de las cadenas, el
algoritmo es (mn).
POLITÉCNICO GRANCOLOMBIANO 10
3. Resumen
La programación dinámica permite evaluar una ecuación de recurrencia en un orden de complejidad
polinómico, en contraste con el orden súper polinómico del correspondiente algoritmo recursivo,
cuando la evaluación directa de la ecuación exhibe la propiedad de repetir invocaciones con idénticos
parámetros una cantidad considerable de veces.
• Un enfoque de abajo hacia arriba en la evaluación de los subproblemas. Esto es, resolviendo
primero los subproblemas más pequeños.
El problema del cálculo de enésimo número de la sucesión de Fibonacci puede ser efectiva y
eficientemente resuelto mediante el enfoque de la programación dinámica. De igual forma, el
problema del cálculo de la distancia de edición entre dos cadenas de texto es resuelto mediante la
misma técnica.
POLITÉCNICO GRANCOLOMBIANO 11
Referencias
Cormen, T., Leiserson, C., Rivest, R. y Stein, C. (2009). Introduction to Algorithms (3rd ed.). The MIT
Press.
POLITÉCNICO GRANCOLOMBIANO 12
INFORMACIÓN TÉCNICA
POLITÉCNICO GRANCOLOMBIANO 13