Está en la página 1de 16

“UNIVERSIDAD NACIONAL

MAYOR DE SAN MARCOS”

 Tema: Programación Dinámica

 Curso: Matemática Discreta

 Turno: martes 2-7 pm

1
Contenido

Programación Dinámica ............................................................................................................... 3


1) Introducción: ........................................................................................................................ 3
2) Naturaleza del problema y su aplicación:............................................................................ 3
2.1) Naturaleza del problema: ............................................................................................. 3
2.2) Aplicaciones: .................................................................................................................. 4
3)Desarrollo y naturaleza del algoritmo: ................................................................................. 5
3.1)Calculo de los números de Fibonacci:............................................................................ 5
3.2) Problema del cambio de las monedas: ......................................................................... 6
3.3) Problema de la mochila: ............................................................................................... 7
3.4) Coeficientes binomiales: ............................................................................................... 9
3.5) INTERESES BANCARIOS: .............................................................................................. 11
4)Tipos de enfoque de la programación dinámica: ............................................................... 15
4.1) Programación Dinámica Determinística ..................................................................... 15
4.2) Programación Dinámica Probabilística ....................................................................... 15
5)Ventajas y desventajas:....................................................................................................... 16
5.1) VENTAJAS..................................................................................................................... 16
5.2) DESVENTAJAS: ............................................................................................................. 16

2
Programación Dinámica

1) Introducción:

 La Programación Dinámica fue desarrollada por Richard Bellman y G B Dantzing. Sus


importantes contribuciones sobre esta técnica cuantitativa de toma de decisiones se
publicaron en 1957 en un libro del primer autor denominado “Dynamic Programming”
(Princeton University Press. Princeton, New Jersey).
 Inicialmente a la programación dinámica se le denominó programación lineal estocástica o
problemas de programación lineal con incertidumbre. La programación dinámica (PD)
determina la solución óptima de un problema de n variables descomponiéndola en n
etapas, con cada etapa incluyendo un subproblema de una sola variable. La principal
contribución de la PD es el principio de optimalidad, el cual establece que una política
óptima consiste de subpolíticas óptimas, un marco de referencia para descomponer el
problema en etapas.
 La programación dinámica es una técnica que se puede aplicar para resolver muchos
problemas de optimización. La mayor parte de las veces, la programación dinámica obtiene
soluciones con un avance en reversa, desde el final de un problema hacia el principio con
lo que un problema grande y engorroso se convierte en una serie de problemas más
pequeños y más tratables.
 La programación dinámica se podría definir como una técnica matemática que resuelve una
serie de decisiones secuenciales, cada una de las cuales afecta las decisiones futuras. Nos
brinda un procedimiento sistemático para determinar la combinación de decisiones que
maximiza la efectividad total.

2) Naturaleza del problema y su aplicación:

2.1) Naturaleza del problema:


Las características de la programación dinámica se emplean para formular e identificar la
estructura de los problemas de este tipo.
A continuación, se presentarán estas características básicas que distinguen a los problemas de
programación dinámica.

1. El problema se puede dividir en etapas que requieren una política de decisión en cada
una de ellas. En muchos problemas de programación dinámica, la etapa es la cantidad
de tiempo que pasa desde el inicio del problema, en ciertos casos no se necesitan
decisiones en cada etapa.
2. Cada etapa tiene un cierto número de estados asociados a ella. Por estado se entiende
la información que se necesita en cualquier etapa para tomar una decisión óptima.
3. El efecto de la política de decisión en cada etapa es transformar el estado actual en un
estado asociado con la siguiente etapa (tal vez de acuerdo a una distribución de
probabilidad).
4. El procedimiento de solución está diseñado para encontrar una política óptima para el
problema completo, es decir, una receta para las decisiones de la política óptima en
cada etapa para cada uno de los estados posibles.

3
5. Dado el estado actual, una política óptima para las etapas restantes es independiente
de la política adoptada en etapas anteriores. (este es el principio de óptimalidad para la
programación dinámica). En general en los problemas de PD, el conocimiento del estado
actual del sistema expresa toda la información sobre su comportamiento anterior, y esta
información es necesario para determinar la política óptima de ahí en adelante.
6. El procedimiento de solución se inicia al encontrar la política óptima para la última
etapa. La política óptima para la última etapa prescribe la política óptima de decisión
para cada estado posible en esa etapa.
7. Se dispone de una relación recursiva que indica la política óptima para la etapa dada la
política óptima para la etapa (n+1) .

A pesar de esta característica, los problemas que pueden ser atacados con la PD tienen otras
dos propiedades adicionales:

 Sólo un número reducido de variables se debe conocer en cualquier etapa con el fin de
describir al problema. En efecto, los problemas de la PD se caracterizan por la
dependencia de los resultados derivados de decisiones sobre un número reducido de
variables.
 El resultado de una decisión en cualquier etapa altera los valores numéricos de un
número reducido de variables relevantes al problema. La decisión actual ni incrementa
ni decrementa el número de factores sobre los cuales depende el resultado. Así, para la
siguiente decisión en la secuencia, el mismo número de variables se considera (Hillier,
1991).

NOTA:

En un problema de PD una serie de decisiones se deben tomar en una secuencia dada.


Cuando esto se cumple, una política óptima se debe perseguir. No importa cuáles fueron los
estados y decisiones iniciales, las decisiones restantes constituirán una política óptima con
respecto al estado resultante de la primera decisión.

2.2) Aplicaciones:
Algunas de las aplicaciones de programación dinámica determinística son:

 Modelo de Volumen-Carga “mochila”.


 Modelo del tamaño de la fuerza de trabajo.
 Modelo de reposición de equipos.
 Modelo de inversión.
 Modelos de inventarios.

A continuación, se presentarán algunas de estas aplicaciones, cada una de las cuales muestra
una nueva idea en la puesta en práctica de la PD.

i=1, 2,3…n

A medida que se presente cada aplicación, es importante prestar atención a los tres elementos
básicos de un modelo de PD:

4
Definición de las etapas.

Definición de las políticas o alternativas.

Definición de los estados para cada etapa De los tres elementos, la definición del estado por lo
común es la más sutil. Las aplicaciones que se presentan a continuación muestran que la
definición de estado varía dependiendo de la situación que se está modelando.

3)Desarrollo y naturaleza del algoritmo:

La programación dinámica se suele utilizar en problemas de optimización, donde una


solución está formada por una serie de decisiones
Se resuelve el problema original combinando las soluciones para subproblemas más
pequeños
Sin embargo, la programación dinámica no utiliza recursividad, sino que almacena los
resultados de los subproblemas en una tabla, calculando primero las soluciones para los
problemas más pequeños, con esto se pretende evitar la repetición de cálculos para
problemas más pequeños.

3.1)Calculo de los números de Fibonacci:

Con método recursivo:

Fibonacci (n: interger)

Si (n<2)
Devolver 1

Sino
Devolver Fibonacci(n-1) + Fibonacci (n-2)

Problema: Muchos cálculos están repetidos, tiempo de ejecución exponencial


Solución: Calcular los valores de menor a mayor empezando por 0 ,e ir guardando los
resultados en una tabla

Con programación dinámica:

Fibonacci (n: interger)

5
T [0] = 0 T [1] = 1
Para i = 2, 3, 4…n
T [i] = T [i-1] +T [i-2]

Devolver T [n]
Se utiliza la misma fórmula que la versión anterior, pero de forma más inteligente. El
tiempo de ejecución es mínimo

3.2) Problema del cambio de las monedas:

Dado un conjunto de n tipos de monedas cada un valor 𝑐𝑖 y dado una cantidad P,


encontrar el número mínimo de monedas que tenemos que usar para obtener esa
cantidad
Utilizando programación dinámica:

1. Definimos el problema en función de problemas más pequeños.


2. Determinar los valores de los casos base.
3. Determinar las tablas necesarias para almacenar los resultados de los subproblemas.
4. Establecemos una forma de rellenar las tablas y de obtener el resultado.

Definición de la ecuación recurrente:


Cambio (i, Q): el problema de calcular el número de monedas mínimos necesarios
Para devolver una cantidad Q usando los i primeros tipos de monedas.
La solución de Cambio (i, Q) puede que utilice k monedas de tipo i o puede que no
utilice ninguna.
Si no usa ninguna moneda de ese tipo: Cambio (i, Q) = Cambio (i-1, Q)
Si se usa k monedas de tipo i: Cambio (i, Q) = Cambio (i, Q- k*𝒄𝒊 ) +k

En cualquier caso, el valor será el mínimo:

Cambio (i, Q) = 𝒌 = 𝟎, 𝟏, 𝟐. . 𝑸𝒎𝒊𝒏 {Cambio (i, Q) = Cambio (i-1, Q- k*𝒄𝒊 ) +k}


Caso base: Cambio (i, Q)

Si (i<=0) o (Q<0) entonces no existe ninguna solución al problema y


Cambio (i, Q) =∞
En otro cualquier otro caso para (i>0), Cambio (i, 0) = 0

Definición de las tablas utilizadas


 Necesitamos almacenar los resultados de todos los subproblemas
 El problema a resolver será: Cambio (n, P)

6
 Por lo tanto necesitamos una tabla de n *P, de enteros, que llamaremos D
siendo D[i,j] =Cambio (i,j)
 Ejemplo:
n=3, P=8, c= (1,4,6)

D Cantidad a devolver
Monedas 0 1 2 3 4 5 6 7 8
𝐶1
𝐶2
𝐶3

Formas de rellenar las tablas:


De arriba hacia abajo y de izquierda a derecha, aplicar la ecuación de recurrencia
D [i, j]= 𝒌 = 𝟎, 𝟏, 𝟐. . 𝑸𝒎𝒊𝒏 {Cambio (i, Q) = Cambio (i-1, Q- k*𝒄𝒊 ) +k}

Algoritmo:

Devolver_cambio( P : int ; C : array[ 1…n] of int ; var D :[ 1..n ,0….P ]of int)
Para i = 1, 2,3……n
D [i, 0] =0
Para i = 1, 2,3……n
Para j = 1, 2,3……P
D [i, j]= 𝑘 = 0,1,2. . 𝑄 𝑚𝑖𝑛 {Cambio (i, Q) = Cambio (i-1, Q- k*𝑐𝑖 ) +k}
Fin

Tener en cuenta si el valor cae fuera de la tabla

Ejemplo: n=3, P=8, c= (1, 4,6)

D Cantidad a devolver
Monedas 0 1 2 3 4 5 6 7 8
𝐶1 0 1 2 3 4 5 6 7 8
𝐶2 0 1 2 3 1 2 3 4 2
𝐶3 0 1 2 3 1 2 1 2 2

3.3) Problema de la mochila:

7
Parecido al problema anterior, pero los objetos no se pueden fragmentar en problemas
más pequeños.

Problema: Tenemos n objetos cada uno con un peso 𝑤𝑖 y un beneficio 𝑉𝑖 y una mochila
en lo que podemos meter objetos con una capacidad de peso máximo M .El objetivo es
maximizar el beneficio de los objetos transportados donde cada objeto se puede coger
entero 𝑥𝑖 =1 o 𝑥0 = 0 .

Definición de la ecuación recurrente:


Sea Mochila (i, m) el problema de la mochila, considerando los i primeros objetos (de
los n originales) con una capacidad de peso m .Supondremos que devuelve el valor del
beneficio total: ∑ 𝑥𝑎 ∗ 𝑉𝑎
Podremos definir el problema de forma recurrente en función de que se use o no el
objeto i
Si no se usa el objeto i: Mochila (i, m) = Mochila (i-1, m)
Si se usa Mochila (i, m) = 𝑣𝑖 + Mochila (i-1, m-𝑤𝑖 )

Caso base:
Si ((i<0) o (m<0)) entonces no hay solución: Mochila (i, m) = -∞
En otro caso, si (i=0 o m=0) la solución es no incluir ningún objeto: Mochila (i, m) =0
Definición de las tablas

La solución del problema original será Mochila (n, M). Por lo tanto necesitamos una tabla
V: Array [0…n, 0….m] of interger
V [i, j] =Beneficio máximo usando los i primeros objetos y peso j

Formas de rellenar las tablas


Inicializar los casos bases
Para toda i, para 1 hasta n y j desde 1 hasta M aplicar la ecuación de recurrencia

V [i,j] = Max ( V[i-1 ,j ] ,V[ i-1 ,j - 𝑤𝑖 ] +𝑣𝑖 )

Si j es negativo entonces V [i, j] = -∞ y el máximo será el otro termino

Ejemplo: n=3, M=6, w= (2, 3,4), v= (1, 2,5)

0 1 2 3 4 5 6
0 0 0 0 0 0 0 0
1 0 0 1 1 1 1 1
2 0 0 1 2 2 3 3
3 0 0 1 2 5 5 6

8
3.4) Coeficientes binomiales:
El algoritmo recursivo que calcula los coeficientes binomiales resulta ser de complejidad
exponencial por la repetición de los cálculos que realiza. No obstante, es posible diseñar
un algoritmo con un tiempo de ejecución de orden O (nk) basado en la idea del Triángulo
de Pascal, idea claramente aplicable mediante programación dinámica. Para ello es
necesaria la creación de una tabla bidimensional en la que ir almacenando los valores
intermedios que se utilizan posteriormente.

La idea recursiva de los coeficientes binomiales es la siguiente:

(𝑛𝑘) = (𝑛−1
𝑘−1
) + ( 𝑛−1
𝑘
) si 0<k<n

(𝑛0) = (𝑛𝑛) = 1

La idea para construir la tabla de manera eficiente y sin valores inútiles es la


siguiente:

0 1 2 3 …… k-1 k

….. …. …… …… …..

…. ….. ……. …… …… ……

n-1 C(n-1,k- C(n-1 ,k)


1)

n C(n,k)

9
El siguiente algoritmo memorizado de estrategia Bottom-up tiene complejidad polinómica y
va rellenando la tabla de izquierda a derecha y de arriba abajo:

FUNC CoeficientesPolinomiales (n, k: NATURAL): NATURAL


Variables
tabla: TABLA DE NATURALES
i, j: NATURAL
Inicio
PARA i = 0 HASTA n HACER
tabla[i][0] := 1
FIN PARA
PARA i = 1 HASTA n HACER
tabla[i][1]:= i
FIN PARA
PARA i = 2 HASTA k HACER
tabla[i][i]:= 1
FIN PARA
PARA i = 3 HASTA n HACER
PARA j = 2 HASTA i-1 HACER
SI j <= k ENTONCES
tabla[i][j] := tabla[i-1][j-1] + tabla[i-1][j]
FIN SI
FIN PARA
FIN PARA
devolver tabla[n][k]
Fin

10
3.5) INTERESES BANCARIOS:
Dadas n funciones f1, f2, ..., fn y un entero positivo M, deseamos maximizar la función
f1(x1) + f2(x2) + ... + fn(xn) sujeta a la restricción x1 +x2 + ... + xn = M, donde fi(0) = 0
(i=1,..,n), xi son números naturales, y todas las funciones son monótonas crecientes, es
decir, x ≥ y implica que fi(x) > fi(y). Supóngase que los valores de cada función se
almacenan en un vector.
Este problema tiene una aplicación real muy interesante, en donde fi representa la
función de interés que proporciona el banco i, y lo que deseamos es maximizar el interés
total al invertir una cantidad determinada de dinero M. Los valores xi van a representar
la cantidad a invertir en cada uno de los n bancos.
Solución
Sea fi un vector que almacena el interés del banco i (1 ≤ i ≤ n) para una inversión de 1,
2, 3,..., M soles. Esto es, fi (j) indicará el interés que ofrece el banco i para j soles, con 0
< i ≤ n, 0 < j ≤ M. Para poder plantear el problema como una sucesión de decisiones,
llamaremos In(M) al interés máximo al invertir M soles en n bancos,
In(M) = f1(x1) + f2(x2) + ... + fn(xn)
que es la función a maximizar, sujeta a la restricción x1 +x2 + ... + xn = M. Veamos cómo
aplicar el principio de óptimo. Si In(M) es el resultado de una secuencia de decisiones y
resulta ser óptima para el problema de invertir una cantidad M en n bancos, cualquiera
de sus subsecuencias de decisiones ha de ser también óptima y así la cantidad I n–1(M –
xn) = f1(x1) + f2(x2) + ... + fn–1(xn–1) será también óptima para el subproblema de
invertir (M – xn) soles en n – 1 bancos.
Y por tanto el principio de óptimo nos lleva a plantear la siguiente relación en
recurrencia:

Para resolverla y calcular In(M), vamos a utilizar una matriz I de dimensión nxM en donde
iremos almacenando los resultados parciales y así eliminar la repetición de los cálculos.
El valor de I[i,j] va a representar el interés de j soles cuando se dispone de i bancos, por
tanto la solución buscada se encontrará en I[n,M]. Para guardar los datos iniciales del
problema vamos a utilizar otra matriz F, de la misma dimensión, y donde F[i,j] representa
el interés del banco i para j soles. En consecuencia, para calcular el valor pedido de I[n,M]
rellenaremos la tabla por filas, empezando por los valores iniciales de la ecuación en
recurrencia, y según el siguiente algoritmo:

11
CONST n =...; (* número de bancos *)
M =...; (* cantidad a invertir *)
TYPE MATRIZ = ARRAY [1...n], [0...M] OF CARDINAL;
PROCEDURE Intereses (VAR F: MATRIZ; VAR I: MATRIZ): CARDINAL;
VAR i,j: CARDINAL;
BEGIN
FOR i:=1 TO n DO I [i, 0]:=0 END;
FOR j:=1 TO M DO I [1, j]:=F [1, j] END;
FOR i:=2 TO n DO
FOR j:=1 TO M DO
I [i,j]:=Max(I,F,i,j)
END
END;
RETURN I [n,M]
END Intereses;
La función Max es la que calcula el máximo que aparece en la expresión [5.1]::
PROCEDURE Max (VAR I,F:MATRIZ;i,j:CARDINAL):CARDINAL;
VAR max,t:CARDINAL;
BEGIN
max:= I[i-1,j] + F[i,0];
FOR t:=1 TO j DO
max:=Max2(max,I[i-1,j-t]+F[i,t])
END;
RETURN max
END Max;

La función Max2 es la que calcula el máximo de dos números naturales. La complejidad


del algoritmo completo es de orden O (nM2 ), puesto que la complejidad de Max es
O(j) y se invoca dentro de dos bucles anidados que se desarrollan desde 1 hasta M.

12
Es importante hacer notar el uso de parámetros por referencia en lugar de por valor
para evitar la copia de las matrices en la pila de ejecución del programa. Por otro lado,
la complejidad espacial del algoritmo es del orden O(nM), pues de este orden son las
dos matrices que se utilizan para almacenar los resultados intermedios.
En este ejemplo queda de manifiesto la efectividad del uso de estructuras en los
algoritmos de Programación Dinámica para conseguir obtener tiempos de ejecución de
orden polinómico, frente a los tiempos exponenciales de los algoritmos recursivos
iniciales.

3.6) EL VIAJE MÁS BARATO POR RÍO:


Sobre el río hay n embarcaderos. En cada uno de ellos se puede alquilar un bote que
permite ir a cualquier otro embarcadero río abajo (es imposible ir río arriba). Existe una
tabla de tarifas que indica el coste del viaje del embarcadero i al j para cualquier
embarcadero de partida i y cualquier embarcadero de llegada j más abajo en el río (i <
j). Puede suceder que un viaje de i a j sea más caro que una sucesión de viajes más
cortos, en cuyo caso se tomaría un primer bote hasta un embarcadero k y un segundo
bote para continuar a partir de k. No hay coste adicional por cambiar de bote. Nuestro
problema consiste en diseñar un algoritmo eficiente que determine el coste mínimo
para cada par de puntos i,j (i < j) y determinar, en función de n, el tiempo empleado por
el algoritmo.
Solución
Llamaremos T[i,j] a la tarifa para ir del embarcadero i al j (directo). Estos valores se
almacenarán en una matriz triangular superior de orden n, siendo n el número de
embarcaderos.
El problema puede resolverse mediante Programación Dinámica ya que para calcular el
coste óptimo para ir del embarcadero i al j podemos hacerlo de forma recurrente,
suponiendo que la primera parada la realizamos en un embarcadero intermedio k (i < k
≤ j):
C(i,j) = T(i,k) + C(k,j).
En esta ecuación se contempla el viaje directo, que corresponde al caso en el que k
coincide con j. Esta ecuación verifica también que la solución buscada C(i,j) satisface el
principio del óptimo, pues el coste C(k,j), que forma parte de la solución, ha de ser, a su
vez, óptimo. Podemos plantear entonces la siguiente expresión de la solución:

La idea de esta segunda expresión surge al observar que en cualquiera de los trayectos
siempre existe un primer salto inicial óptimo.

13
Para resolverla según la técnica de Programación Dinámica, hace falta utilizar una
estructura para almacenar resultados intermedios y evitar la repetición de los cálculos.
La estructura que usaremos es una matriz triangular de costes C [i,j], que iremos
rellenando por diagonales mediante el procedimiento que hemos denominado Costes.
La solución al problema es la propia tabla, y sus valores C [i,j] indican el coste óptimo
para ir del embarcadero i al j.
CONST MAXEMBARCADEROS =...;
TYPE MATRIZ=ARRAY [1...MAXEMBARCADEROS], [1...MAXEMBARCADEROS] OF
CARDINAL;
PROCEDURE Costes (VAR C: MATRIZ; n: CARDINAL);
VAR i, diagonal: CARDINAL;
BEGIN
FOR i:=1 TO n DO C[i,i]:=0 END; (* condiciones iniciales *)
FOR diagonal:=1 TO n-1 DO
FOR i:=1 TO n-diagonal DO
C[i,i+diagonal]:=Min(C,i,i+diagonal)
END
END
END Costes;
Dicho procedimiento utiliza la siguiente función, que permite calcular la expresión del
mínimo que aparece en la ecuación en recurrencia [5.2]:
PROCEDURE Min(VAR C:MATRIZ; i,j:CARDINAL):CARDINAL;
VAR k,min:CARDINAL;
BEGIN
min:=MAX(CARDINAL);
FOR k:=i+1 TO j DO
min:=Min2(min,T[i,k] + C[k,j])
END;
RETURN min
END Min;
La función Min2 es la que calcula el mínimo de dos números naturales. Es importante
observar que esta función, por la forma en que se va rellenando la matriz C, sólo hace

14
uso de los elementos calculados hasta el momento. La complejidad del algoritmo es de
orden O (n3), pues está compuesto por dos bucles anidados de tamaño n, que contienen
la llamada a una función de orden O(n), la que calcula el mínimo.

4)Tipos de enfoque de la programación dinámica:


4.1) Programación Dinámica Determinística
El enfoque determinístico consiste en que el estado de la siguiente etapa se encuentra
determinado por completo con respecto al estado y la decisión que posee la etapa actual. A
continuación, un diagrama que representa la estructura básica de la programación dinámica
determinística. Estructura básica de la programación dinámica determinística. Los problemas de
programación dinámica determinística se pueden clasificar según su función objetivo: como, por
ejemplo, maximizar ingresos o reducir costos; según la naturaleza del conjunto de estados:
variables discretas o variables continuas. (Hillier, 2010, p.399)

Fuente: Hiller, 2010

4.2) Programación Dinámica Probabilística


En este enfoque, el valor del estado de la siguiente etapa y política de decisión queda
completamente determinado mediante una distribución probabilística. A continuación, un
diagrama que representa la estructura básica de la programación dinámica probabilística.

Fuente: Hiller, 2010

15
5)Ventajas y desventajas:
5.1) VENTAJAS
No se requiere de una formulación matemática compleja.
Los cálculos son sencillos.
Reduce un problema inmanejable a una serie de problemas más pequeños y manejables.
Es un método eficiente.

5.2) DESVENTAJAS:
No siempre se puede aplicar a todos los problemas.

Conclusiones: (va al último) <-


∞ El razonamiento inductivo es una herramienta potente en resolución de problemas.
∞ Aplicable no solo en problemas de optimización.
∞ ¿Cómo obtener la formula? Interpretar el problema como una serie de toma de decisiones.
∞ Descomposición recursiva no necesariamente implica implementación recursiva.

REFERENCIAS: (va al ultimo) 

 Unidad V, programación dinámica, Chan Pech Elmer Gabriel, 2012


 Xumari, G.L. Introduction to dynamic programming. Wilwy & Sons Inc., New York. 1967.
 Libro Hillier, 2010.

16