Vous êtes sur la page 1sur 12

Programacin Dinmica

como Solucin al Problema


de la Eficiencia en la
Recursividad
Autor:
Jorge Jimnez Muoz 1A Gestin
2
INDICE:
1. Introduccin al trabajo.
2. Recursividad.
i. Introduccin a la recursividad.
ii. Conceptos de Recursividad.
iii. Propiedades de las definiciones o algoritmos
recursivos.
iv. Programacin recursiva,
v. Diseo de algoritmos recursivos.
vi. Recursividad directa e indirecta.
vii. Recursividad Vs Iteracin.
3. Programacin Dinmica.
i. Introduccin a la programacin dinmica.
ii. Concepto de programacin dinmica.
iii. Procesos polietapicos de decisin.
4. Conclusiones
5. Bibliografa
3
1. Introduccin al trabajo.
El siguiente trabajo trata del anlisis, de la programacin dinmica. Siendo esta
una solucin de mejora a la poca eficiencia de la programacin recursiva. La manera de
afrontar este trabajo, y explicar en un modo sencillo, que entienda todo el mundo, tras
consultar muchas fuentes, es el siguiente, primero veremos a grandes rasgos, en que
consiste la programacin recursiva, sus propiedades, definiciones, ventajas e
inconvenientes, y todo ello acompaado de ejemplos, y uno en comn junto a la
programacin dinmica, de manera que podamos observar el mismo problema desde las
dos perspectivas, que es, el calculo de los nmeros de Fibonacci. El por que de hablar
extendidamente de la programacin recursiva es, porque esta, junto con algunas
tcnicas de programacin como el divide y vencers, algoritmo voraz, o backtracking,
la programacin dinmica no es mas que una mejora bastante significativa basada en la
programacin recursiva, aprovechando los clculos que generan las llamadas, e ir
almacenndolos para su posterior uso, no teniendo que volver a calcularlo, aunque lo
veremos con mas extensin mas adelante.
2. Recursividad
2.i. Introduccin a la Recursividad.
El rea de la programacin es muy amplia y con muchos detalles. Los
programadores necesitan ser capaces de resolver todos los problemas que se les presente
a travs del computador aun cuando en el lenguaje que utilizan no haya una manera
directa de resolver los problemas. En los lenguajes de programacin, se puede aplicar
una tcnica que se le dio el nombre de recursividad por su funcionalidad. Esta tcnica es
utilizada en la programacin estructurada para resolver problemas que tengan que ver
con el factorial de un nmero, o juegos de lgica. Las asignaciones de memoria pueden
ser dinmicas o estticas y hay diferencias entre estas dos y se pueden aplicar las dos en
un programa cualquiera.
2.ii Conceptos de Recursividad.
La recursividad es una tcnica de programacin importante. Se utiliza para
realizar una llamada a una funcin desde la misma funcin. Como ejemplo til se puede
presentar el clculo de nmeros factoriales. l factorial de 0 es, por definicin, 1. Los
factoriales de nmeros mayores se calculan mediante la multiplicacin de 1 * 2 * ...,
incrementando el nmero de 1 en 1 hasta llegar al nmero para el que se est calculando
el factorial.
El siguiente prrafo muestra una funcin, expresada con palabras, que calcula un
factorial.
4
"Si el nmero es menor que cero, se rechaza. Si no es un entero, se redondea al
siguiente entero. Si el nmero es cero, su factorial es uno. Si el nmero es mayor que
cero, se multiplica por l factorial del nmero me nor inmediato."
Para calcular el factorial de cualquier nmero mayor que cero hay que calcular
como mnimo el factorial de otro nmero. La funcin que se utiliza es la funcin en la
que se encuentra en estos momentos, esta funcin debe llamarse a s misma para el
nmero menor inmediato, para poder ejecutarse en el nmero actual. Esto es un ejemplo
de recursividad.
La recursividad y la iteracin (ejecucin en bucle) estn muy relacionadas,
cualquier accin que pueda realizarse con la recursividad puede realizarse con iteracin
y viceversa. Normalmente, un clculo determinado se prestar a una tcnica u otra, slo
necesita elegir el enfoque ms natural o con el que se sienta ms cmodo.
Claramente, esta tcnica puede constituir un modo de meterse en problemas. Es
fcil crear una funcin recursiva que no llegue a devolver nunca un resultado definitivo
y no pueda llegar a un punto de finalizacin. Este tipo de recursividad hace que el
sistema ejecute lo que se conoce como bucle "infinito".
Ejemplo: Secuencia de nmeros de Fibonacci.
Para entender mejor lo que en realidad es el concepto de recursin veremos un poco lo
referente a la secuencia de Fibonacci.
Principalmente habra que aclarar que es un ejemplo menos familiar que el del factorial,
que consiste en la secuencia de enteros.
0,1,1,2,3,5,8,13,21,34,...,
Cada elemento en esta secuencia es la suma de los precedentes (por ejemplo 0 + 1 = 0, 1
+ 1 = 2, 1 + 2 = 3, 2 + 3 = 5, ...) sean fib(0) = 0, fib (1) = 1 y as sucesivamente,
entonces puede definirse la secuencia de Fibonacci mediante la definicin recursiva
(define un objeto en trminos de un caso mas simple de si mismo):
fib (n) = n if n = = 0 or n = = 1
fib (n) = fib (n - 2) + fib (n - 1) if n >= 2
Por ejemplo, para calcular fib (6), puede aplicarse la definicin de manera recursiva
para obtener:
Fib (6) = fib (4) + fib (5) = fib (2) + fib (3) + fib (5) = fib (0) + fib (1) + fib (3) + fib (5)
= 0 + 1 fib (3) + fib (5)
1. + fib (1) + fib (2) + fib(5) =
1. + 1 + fib(0) + fib (1) + fib (5) =
2. + 0 + 1 + fib(5) = 3 + fib (3) + fib (4) =
5
3. + fib (1) + fib (2) + fib (4) =
3 + 1 + fib (0) + fib (1) + fib (4) =
4. + 0 + 1 + fib (2) + fib (3) = 5 + fib (0) + fib (1) + fib (3) =
5. + 0 + 1 + fib (1) + fib (2) = 6 + 1 + fib (0) + fib (1) =
6. + 0 + 1 = 8
Obsrvese que la definicin recursiva de los nmeros de Fibonacci difiere de las
definiciones recursivas de la funcin factorial y de la multiplicacin . La definicin
recursiva de fib se refiere dos veces a s misma . Por ejemplo, fib (6) = fib (4) + fib (5),
de tal manera que al calcular fib (6), fib tiene que aplicarse de manera recursiva dos
veces. Sin embargo calcular fib (5) tambin implica calcular fib (4), as que al aplicar la
definicin hay mucha redundancia de clculo. En ejemplo anterior, fib(3) se calcula tres
veces por separado. Sera mucho ms eficiente "recordar" el valor de fib(3) la primera
vez que se calcula y volver a usarlo cada vez que se necesite. Es mucho mas eficiente un
mtodo iterativo como el que sigue parar calcular fib (n).
If (n < = 1)
return (n);
lofib = 0 ;
hifib = 1 ;
for (i = 2; i < = n; i ++)
{
x = lofib ;
lofib = hifib ;
hifib = x + lofib ;
} /* fin del for*/
return (hifib) ;
Comprese el numero de adiciones (sin incluir los incrementos de la variable
ndice, i) que se ejecutan para calcular fib (6) mediante este algoritmo al usar la
definicin recursiva. En el caso de la funcin factorial, tienen que ejecutarse el mismo
nmero de multiplicaciones para calcular n! Mediante ambos mtodos: recursivo e
iterativo. Lo mismo ocurre con el nmero de sumas en los dos mtodos al calcular la
multiplicacin. Sin embargo, en el caso de los nmeros de Fibonacci, el mtodo
recursivo es mucho ms costoso que el iterativo.
2.iii. Propiedades de las definiciones o algoritmos recursivos:
Un requisito importante para que sea correcto un algoritmo recursivo es que no
genere una secuencia infinita de llamadas as mismo. Claro que cualquier algoritmo que
genere tal secuencia no termina nunca. Una funcin recursiva f debe definirse en
6
trminos que no impliquen a f al menos en un argumento o grupo de argumentos. Debe
existir una "salida" de la secuencia de llamadas recursivas.
Si en esta salida no puede calcularse ninguna funcin recursiva. Cualquier caso
de definicin recursiva o invocacin de un algoritmo recursivo tiene que reducirse a la
larga a alguna manipulacin de uno o casos ms simples no recursivos.
2.iv. Programacin Recursiva:
Es mucho mas difcil desarrollar una solucin recursiva en un lenguaje para
resolver un problema especfico cuando no se tiene un algoritmo. No es solo el
programa sino las definiciones originales y los algoritmos los que deben desarrollarse.
En general, cuando encaramos la tarea de escribir un programa para resolver un
problema no hay razn para buscar una solucin recursiva. La mayora de los problemas
pueden resolverse de una manera directa usando mtodos no recursivos. Sin embargo,
otros pueden resolverse de una manera ms lgica y elegante mediante la recursin.
Volviendo a examinar la funcin factorial. El factor es, probablemente, un
ejemplo fundamental de un problema que no debe resolverse de manera recursiva, dado
que su solucin iterativa es directa y simple. Sin embargo, examinaremos los elementos
que permiten dar una solucin recursiva. Antes que nada, puede reconocerse un gran
nmero de casos distintos que se deben resolver. Es decir, quiere escribirse un programa
para calcular 0!, 1!, 2! Y as sucesivamente. Puede identificarse un caso "trivial" para el
cual la solucin no recursiva pueda obtenerse en forma directa. Es el caso de 0!, que se
define como 1. El siguiente paso es encontrar un mtodo para resolver un caso
"complejo" en trminos de uno ms "simple", lo cual permite la reduccin de un
problema complejo a uno ms simple. La transformacin del caso complejo al simple
resultara al final en el caso trivial. Esto significara que el caso complejo se define, en
lo fundamental, en trminos del ms simple.
Examinaremos que significa lo anterior cuando se aplica la funcin factorial. 4!
Es un caso ms complejo que 3!. La transformacin que se aplica al numero a para
obtener 3 es sencillamente restar 1. Si restamos 1 de 4 de manera sucesiva llegamos a 0,
que es el caso trivial. As, si se puede definir 4! en trminos de 3! y, en general, n! en
trminos de (n 1)!, se podr calcular 4! mediante la definicin de n! en trminos de (n
1)! al trabajar, primero hasta llegar a 0! y luego al regresar a 4!. En el caso de la
funcin factorial se tiene una definicin de ese tipo, dado que:
n! = n * (n 1)!
As, 4! = 4 * 3! = 4 * 3 * 2! = 4 * 3 * 2 * 1! = 4 * 3 * 2 * 1 * 0! = 4 * 3 * 2] * ] = 24
Estos son los ingredientes esenciales de una rutina recursiva: poder definir un
caso "complejo" en trminos de uno ms "simple" y tener un caso "trivial" (no
recursivo) que pueda resolverse de manera directa. Al hacerlo, puede desarrollarse una
solucin si se supone que se ha resuelto el caso ms simple. La versin C de la funcin
factorial supone que esta definido (n 1)! y usa esa cantidad al calcular n!.
7
Otra forma de aplicar estas ideas a otros ejemplos antes explicados. En la
definicin de a * b, es trivial el caso de b = 1, pues a * b es igual a a. En general, a + b
puede definirse en trminos de a * (b 1) mediante la definicin a * b = a * (b 1) + a.
De nuevo, el caso complejo se transforma en un caso mas simple al restar 1, lo que
lleva, al final, al caso trivial de b = 1. Aqu la recursin se basa nicamente en el
segundo parmetro, b.
Con respecto al ejemplo de la funcin de Fibonacci, se definieron dos casos
triviales: fib(0) = 0 y fib(1) = 1. Un caso complejo fib(n) se reduce entonces a dos ms
simples: fib(n 1) y fib(n 2). Esto se debe a la definicin de fib(n) como fib(n 1) +
fib(n 2), donde se requiere de dos casos triviales definidos de manera directa. Fib(1)
no puede definirse como fib(0) + fib(-1) porque la funcin de Fibonacci no est definida
para nmeros negativos.
2.v. Diseo de algoritmos recursivos.
Para resolver un problema, el primer paso ser la identificacin de un algoritmo
recursivo, es decir, descomponer el problema en subproblemas de menor tamao
(aunque de la misma naturaleza del problema original) y componer la solucin final a
partir de las subsoluciones obtenidas.
Tendremos que disear: casos base, casos generales y la solucin en trminos de ellos.
Casos base: Son los casos del problema que se resuelve con un segmento de cdigos sin
recursividad.
Siempre debe existir al menos un caso base el numero y forma de los casos base son
hasta
Cierto punto arbitrario. La solucin ser mejor cuanto mas simple y eficiente resulte el
conjunto
De casos seleccionados.
Casos generales: Si el problema es suficientemente complejo, la solucin se expresa, de
forma recursiva, como la unin de
1. La solucin de uno o ms subproblemas (de igual naturaleza pero menor
tamao).
2. Un conjunto de pasos adicionales. Estos pasos junto con las soluciones a los
subproblemas
Componen la solucin al problema general que queremos resolver.
Los casos generales siempre deben avanzar hacia un caso base. Es decir, la llamada
recursiva se hace a un subproblema ms pequeo y, en ltima instancia, los casos
generales alcanzaran un caso base.
8
2.vi. Recursividad directa e indirecta.
En recursin directa el cdigo del subprograma recursivo F contiene una
sentencia que invoca a F, mientras que en recursin indirecta el subprograma F
invoca al subprograma P, y as sucesivamente hasta que se invoca de nuevo al
subprograma F
Si una funcin, procedimiento o mtodo se invoca a si misma, el proceso se denomina
recursin directa; si una funcin, procedimiento o mtodo puede invocar a una
segunda funcin, procedimiento o mtodo que a su vez invoca a la primera, este
proceso se conoce como recursin indirecta o mutua.
Un requisito para que un algoritmo sea correcto es que no genere una secuencia
infinita de llamadas sobre si mismo. Cualquier algoritmo que genere una secuencia de
este tipo no puede terminar nunca. En consecuencia, la definicin cursiva debe incluir
un componente base (condicin de salida) en el que f(n) se define directamente (es
decir, no recursivamente) para uno o mas valores de n.
Debe existir una <<forma de salir>> de la secuencia de llamadas recursivas. As
en la funcin f(n)=n! para n entero.
La recursividad indirecta se produce cuando un subprograma llama a otro, que
eventualmente terminara llamando de nuevo al primero.
2.vii. Recursividad Vs Iteracin.
El las secciones anteriores se han estudiado varias funciones que se puede
implementar fcilmente o de modo recursivo o bien de modo iterativo. En esta parte
compararemos los dos enfoques y examinaremos las razones por las que el programador
puede elegir u enfoque u otro segn la situacin especifica.
Tanto la iteracin como la recursin se basan en una estructura de control: la
iteracin utiliza una estructura repetitiva y la recursin utiliza una estructura de
seleccin. La iteracin y la recursin implican ambas repeticin: la iteracin utiliza
explcitamente una estructura repetitiva mientras que la recursin consume la repeticin
mediante llamadas repetidas. La iteracin y la recursin implican cada una un test
mientras que la recursin termina cuando se reconoce un caso base o la condicin de
salida se alcanza.
La recursin tiene muchas desventajas. Se invoca repetidamente al mecanismo
de recursividad y en consecuencia se necesita tiempo suplementario para realizar las
mencionadas llamadas.
Esta caracterstica puede resultar cara en tiempo de procesador y espacio de
memoria. Cada llamada de una funcin recursiva produce otra copia de la funcin
(realmente solo las variables de funcin) sea creada; esto puede consumir memoria
considerable. Por el contrario, la iteracin se produce dentro de una funcin, de modo
que las operaciones suplementarias de las llamadas a la funcin y asignacin de
memoria adicional son omitidas.
9
En consecuencia, Cules son las razones para elegir la recursin? La razn
fundamental es que existen numerosos problemas complejos que poseen naturaleza
recursiva y, en consecuencia, son ms fciles de implementar con algoritmos de este
tipo. Sin embargo, en condiciones crticas de tiempo y de memoria, es decir, cuando el
consumo de tiempo y memoria sean decisivos o concluyentes para la resolucin del
problema, la solucin a elegir debe ser, normalmente la iterativa.
3. PROGRAMACION DINMICA.
3.i. Introduccin a la programacin dinmica.
Existe una serie de problemas cuyas soluciones pueden ser expresadas
recursivamente en trminos matemticos, y posiblemente la manera ms natural de
resolverlos es mediante un algoritmo recursivo. Sin embargo, el tiempo de ejecucin de
la solucin recursiva, normalmente de orden exponencial y por tanto impracticable,
puede mejorarse substancialmente mediante la programacin Dinmica.
Frecuentemente para resolver un problema complejo se tiende a dividir este en
subproblemas, ms pequeos, resolver estos ltimos (recurriendo posiblemente a nuevas
subdivisiones) y combinar las soluciones obtenidas para calcular la solucin del
problema inicial. Puede ocurrir que la divisin natural del problema conduzca a un gran
nmero de subejemplares idnticos. Si se resuelve cada uno de ellos sin tener en cuenta
las posibles repeticiones, resulta un algoritmo ineficiente; en cambio si se resuelve cada
ejemplar distinto una sola vez y se conserva el resultado, el algoritmo obtenido es
mucho mejor.
La programacin dinmica es un mtodo ascendente. Se resuelven primero los
subejemplares ms pequeos y por tanto ms simples. Combinando las soluciones se
obtienen las soluciones de ejemplares sucesivamente ms grandes hasta llegar al
ejemplar original.
La idea de la tcnica de "dividir y vencer" es llevada al extremo en la
programacin dinmica. Si en el proceso de resolucin del problema resolvemos un
subproblema, almacenamos la solucin, por si esta puede ser necesaria de nuevo para la
resolucin del problema. Estas soluciones parciales de todos los subproblemas se
almacenan en una tabla, sin tener en cuenta si va a ser realmente necesarias
posteriormente en la solucin total.
Con el uso de esta tabla se evitan hacer clculos idnticos reiteradamente, mejorando as
la eficiencia en la obtencin de la solucin. Tambin sirve para convertir ciertas
funciones recursivas en iterativas.
Ejemplo: Clculo de los 100 primeros ns primos, donde almacenamos cada primo
encontrado en una tabla y dividimos cada nuevo nmero slo por los que hay en la tabla
(y no por todos los menores que l) para saber si es primo:
10
void primos( int n )
{
int tabla[N];
int i, j, nprimos = 0;
for( i=2; i<=n; i++ )
{
j = 0;
while( (j<nprimos) &amp;&amp; (i % tabla[j]!=0 )
j++;
if( j == nprimos )
{
tabla[nprimos] = 1;
nprimos++;
printf("...");
}
}
}
La programacin dinmica se emplea a menudo para resolver problemas de
optimizacin que satisfacen el principio de optimalidad: en una secuencia ptima de
decisiones toda subsecuencia ha de ser tambin ptima.
La Programacin Dinmica no slo tiene sentido aplicarla por razones de
eficiencia, sino porque adems presenta un mtodo capaz de resolver de manera
eficiente problemas cuya solucin ha sido abordada por otras tcnicas y ha fracasado.
Donde tiene mayor aplicacin la Programacin Dinmica es en la resolucin de
problemas de optimizacin. En este tipo de problemas se pueden presentar distintas
soluciones, cada una con un valor, y lo que se desea es encontrar la solucin de valor
ptimo (mximo o mnimo).
La solucin de problemas mediante esta tcnica se basa en el llamado principio
de ptimo enunciado por Bellman en 1957 y que dice:
En una secuencia de decisiones ptima toda subsecuencia ha de ser tambin
ptima.
Hemos de observar que aunque este principio parece evidente no siempre es
aplicable y por tanto es necesario verificar que se cumple para el problema en cuestin.
Un ejemplo claro para el que no se verifica este principio aparece al tratar de encontrar
el camino de coste mximo entre dos vrtices de un grafo ponderado.
3.ii. Concepto de la Programacin dinmica
La estrategia algotrmica conocida como programacin dinmica es una tcnica
de resolucin que encuentra aplicacin en numerosos problemas de optimizacin. El
tipo de problemas abordables es, principalmente, aquel en el que las soluciones factibles
se pueden descomponer en una secuencia de elementos (caminos en un grafo, series de
decisiones, etc.), y cuya funcin objetivo satisface cierta condicin de separabilidad y
montona. No obstante, la programacin dinmica tambin encuentra aplicacin en la
bsqueda de otras estructuras ptima (rboles ptimos) y en la realizacin eficiente de
ciertos clculos de naturaleza recursiva.
11
La programacin dinmica guarda relacin con divide y vencers. Divide y
vencers basa su eficiencia en la divisin de un problema en dos o ms subproblemas de
igual o parecida talla e inferior a la del original cuyas soluciones se combinan. La
divisin de un problema en subproblemas de talla inferior conduce de forma
natural a un planteamiento recursivo. Divide y vencers permite disear algoritmos
eficientes cuando la divisin proporciona instancias de talla similar (como en mergesort,
donde el vector se parte en dos vectores de talla similar) y, adems, no hay llamadas
repetidas en el rbol de las llamadas recursivas (recordemos el problema del calculo de
la potencia entera de un numero).
El mtodo de programacin dinmica se aplica, precisamente, en problemas que
adolecen de estos inconvenientes. Para ellos, la programacin dinmica ofrece un
repertorio de tcnicas que permiten reducir la complejidad computacional propia de una
resolucin puramente recursiva. La fundamental consiste en evitar la repeticin de
clculos en las llamadas recursivas mediante el almacenamiento de los resultados que ya
han sido calculados para su posterior reutilizacin. Esta tcnica se conoce como
(memorizacin).
Por otra parte, una transformacin recursivo-iterativa permite, en ocasiones,
reducciones adicionales de complejidad espacial: no solo ahorra la memoria que ocupa
la pila de llamadas a funcin, sino que permite reducir el propio tamao de la tabla de
soluciones precalculadas.
La programacin dinmica consiste en una tcnica que permite determinar de
manera eficiente las decisiones que optimizan el comportamiento de un sistema que
evoluciona a lo largo de una serie de etapas. En otras palabras, trata de encontrar la
secuencia de decisiones que optimiza el comportamiento de un proceso polietapico.
La naturaleza del razonamiento que se debe realizar en programacin dinmica
es muy diferente al de la programacin lineal, intenta describir una determinada
situacin en trminos de un modelo matemtico determinado; una vez conocida la
naturaleza de las variables de decisin, y expresadas la funcin objetivo y las
restricciones en funcin de esas variables, la programacin dinmica no admite una
resolucin sistemtica de este tipo; mas que un modelo concreto, es una estrategia de
resolucin comn a muchas situaciones en principio diferentes entre si.
Adems, es frecuentemente que la resolucin del modelo este muy relacionada
con la situacin que se ha de modelizar. En contrapartida las simplificaciones que en
ocasiones deben realizarse en programacin lineal para poder resolver el modelo no son
necesarias en programacin dinmica, que admite gran variedad de relaciones entre
variables.
Existen dos tipos generales de programacin dinmica:
Programacin dinmica no homognea, frente a programacin dinmica
homognea en el tiempo. Para este ultimo caso, podremos plantearnos encontrar
la solucin para horizonte finito o para horizonte infinito.
Programacin dinmica determinista, frente a programacin dinmica aleatoria,
en este caso, es interesante destacar que las cadenas de Harkov con
remuneracin y decisin son un caso particular de programacin dinmica
aleatoria homognea en el tiempo.
12
Para que un problema pueda ser abordado por esta tcnica ha de cumplir dos
condiciones:
La solucin al problema ha de ser alcanzada a travs de una secuencia de
decisiones, una en cada etapa.
Dicha secuencia de decisiones ha de cumplir el principio de ptimo.
En grandes lneas, el diseo de un algoritmo de Programacin Dinmica consta de los
siguientes pasos:
1. Planteamiento de la solucin como una sucesin de decisiones y verificacin
de que sta cumple el principio de ptimo.
2. Definicin recursiva de la solucin.
3. Clculo del valor de la solucin ptima mediante una tabla en donde
se almacenan soluciones a problemas parciales para reutilizar los clculos.
4. Construccin de la solucin ptima haciendo uso de la informacin contenida
en la tabla anterior.
3.iii. Procesos polietapicos de decisin.
Las situaciones susceptibles de ser representadas mediante programacin
dinmica pueden describirse como procesos polietapicos de decisin. Seguidamente se
exponen algunas caractersticas propias de este tipo de procesos.
El problema puede dividirse en etapas. En cada una de esas etapas, debe
tomarse una decisin. Tendremos la solucin del problema cuando conozcamos
la decisin ptima para cualquier situacin que pueda presentarse en la
evolucin del sistema.
La programacin dinmica va asociada a situaciones de evolucin de un sistema
que va evolucionando a lo largo de varias etapas (de ah su carcter dinmico). En la
mayora de las ocasiones, se tratara de representar el comportamiento de un sistema que
evoluciona a lo largo del tiempo. En otros casos, se trata de situaciones en las que las
decisiones se toman de manera simultnea en el tiempo, pero en las que se evalan las
decisiones de manera secuencial. Ntese la diferencia con la programacin lineal, en las
que las decisiones se toman de manera simultanea (aunque en ocasiones representemos
sistemas que evolucionaran a lo largo del tiempo, como los planes de produccin).
Una vez tomada la decisin en el estado correspondiente, el sistema
evolucionara hacia alguno de los estados posibles para la etapa siguiente.
Por lo tanto, el comportamiento del sistema puede percibirse como una
secuencia de decisiones y evoluciones. Dicha evolucin puede ser conocida con certeza,
una vez tomada la decisin (tendremos una situacin de programacin dinmica
determinista), o bien el sistema puede evolucionar hacia diferentes estados, segn una
ley de probabilidad conocida (siendo entonces programacin dinmica aleatoria).
El objetivo de la programacin dinmica es de encontrar cual es la poltica
optima para cada una de las etapas de la evolucin del sistema. La poltica para
13
una determinada etapa es la decisin ptima en cada uno de los posibles
estados del sistema en dicha etapa.
Ntese que, para cada etapa, debe definirse una variable de decisin Xn. Si el
sistema tiene k estados en esa etapa, una poltica ser un vector de k componentes,
cuyas componentes e-sima es el valor de las variables de decisin para el estado e en la
etapa n.
La esencia de la estrategia de la programacin dinmica se expresa mediante el
principio de la optimalidad:
En un modelo de programacin dinmica, la poltica ptima para las etapas que
faltan hasta la finalizacin del proceso es independiente de las polticas
adoptadas en las etapas anteriores.
Ejemplo :CLCULO DE LOS NMEROS DE FIBONACCI
El siguiente problema trata del clculo de los trminos de la sucesin de nmeros de
Fibonacci, mediante la programacin dinmica. Dicha sucesin podemos expresarla
recursivamente en trminos matemticos de la siguiente manera:
Si n=0.1
Fib(n)
Fib(n- 1)+Fib(n- 2) si n>1
Por tanto, la forma ms natural de calcular los trminos de esa sucesin es mediante un
programa recursivo:
Funcion FibRec(n:CARDINAL):CARDINAL;
IF n<=1 THEN RETURN 1
ELSE
RETURN FibRec(n-1) + FibRec(n-2)
END END FibRec;
El inconveniente es que el algoritmo resultante es poco eficiente ya que su
tiempo de ejecucin es de orden exponencial, como se vio en el primer captulo.
Como podemos observar, la falta de eficiencia del algoritmo se debe a que se producen
llamadas recursivas repetidas para calcular valores de la sucesin, que habindose
calculado previamente, no se conserva el resultado y por tanto es necesario volver a
calcular cada vez.
Para este problema es posible disear un algoritmo que en tiempo lineal lo
resuelva mediante la construccin de una tabla que permita ir almacenando los
clculos realizados hasta el momento para poder reutilizarlos:
El algoritmo iterativo que calcula la sucesin de Fibonacci utilizando tal tabla es:
TYPE TABLA = ARRAY [0..n] OF CARDINAL
PROCEDURE FibIter(VAR T:TABLA;n:CARDINAL):CARDINAL;
VAR i:CARDINAL; BEGIN
14
IF n<=1 THEN RETURN 1
ELSE
T[0]:=1;
T[1]:=1:
FOR i:=2 TO n DO
T[i]:=T[i-1]+T[i-2]
END;
RETURN T[n]
END
END FibIter;
Existe an otra mejora a este algoritmo, que aparece al fijarnos que nicamente
son necesarios los dos ltimos valores calculados para determinar cada trmino, lo que
permite eliminar la tabla entera y quedarnos solamente con dos variables para almacenar
los dos ltimos trminos:
Funcion FibIter2(n: CARDINAL):CARDINAL;
VAR i,suma,x,y:CARDINAL; (* x e y son los 2 ultimos trminos *)
IF n<=1 THEN RETURN 1
ELSE
x:=1; y:=1;
FOR i:=2 TO n DO
suma:=x+y; y:=x; x:=suma;
END;
RETURN suma
END
END FibIter2;
Aunque esta funcin sea de la misma complejidad temporal que la anterior
(lineal), consigue una complejidad espacial menor, pues de ser de orden O(n) pasa a ser
O(1) ya que hemos eliminado la tabla.
El uso de estructuras (vectores o tablas) para eliminar la repeticin de los
clculos, pieza clave de los algoritmos de Programacin Dinmica, hace que en este
captulo nos fijemos no slo en la complejidad temporal de los algoritmos estudiados,
sino tambin en su complejidad espacial.
En general, los algoritmos obtenidos mediante la aplicacin de esta tcnica
consiguen tener complejidades (espacio y tiempo) bastante razonables, pero debemos
evitar que el tratar de obtener una complejidad temporal de orden polinomio conduzca a
una complejidad espacial demasiado elevada.
15
3. CONCLUSIONES.
Bueno, al terminar de desarrollar este trabajo, espero que el lector, comprenda la
importancia de la programacin dinmica, quizs me haya sobrepasado en lo que se
refiere a la descripcin de la programacin recursiva, pero como habr ido leyendo, esta
forma base de la programacin dinmica, ya que esta no es mas que una mejora de la
recursividad, para aumentar su eficiencia. Tambin pienso que quizs no se si habr
quedado demasiado claro mis explicaciones, pero es con el material que e contando, ya
que aunque es una de las tcnicas mas utilizadas, ya que sirve para optimizar, se
aprende mas a utilizarla en su propia aplicacin, e puesto el mismo ejemplo en las dos
tcnicas de programacin, la sucesin de Fibonacci, ya que es un ejemplo muy genrico
y fcil de ver, amen de otros pequeos ejemplos, que explican partes y aplicaciones de
la teora.
16
4. Bibliografa.
Libros:
Fundamentos de programacin. Algoritmos. Estructuras de datos y
objetos. Editorial Mc Graw Hill. Luis Joyanes Aguilar
Tcnicas de Diseo de Algoritmos. Servicio de Publicaciones de la
Universidad de Mlaga. 1998 Rosa Guerequeta y Antonio Vallecillo
Webs:
www.tumaster.com/programacion_dinamica-res495.htm
www.udlap.mx/~is110493/seminario/algoritmos/
thales.cica.es/rd/Recursos/ rd99/ed99-0033-04/din_introd.html
aulavirtual.uji.es/mod/resource/view.php?id=4017
www.lcc.uma.es/~av/Libro/CAP5.pdf
www.lcc.uma.es/~lopez/apuntes/ progdec/apuntes/basicas/basicas4pp.pdf
www.infor.uva.es/~belar/Archivos%20Ampliacion/
www.dlsi.ua.es/~carrasco/aa/ Algoritmia avanzada
Recursividad, ManualesDelWeb.com
www.manualesdelweb.com/manual-114-Recursividad.html - 60k
www2.ing.puc.cl/~jabaier/iic2552/progdin.pdf -

Vous aimerez peut-être aussi