fbpx
Wikipedia

Programación dinámica

En informática, la programación dinámica es un método para reducir el tiempo de ejecución de un algoritmo mediante la utilización de subproblemas superpuestos y subestructuras óptimas, como se describe a continuación.

El matemático Richard Bellman inventó la programación dinámica en 1953 que se utiliza para optimizar problemas complejos que pueden ser discretizados y secuencializados.

Introducción

Una «subestructura óptima» significa que se pueden usar soluciones óptimas de subproblemas para encontrar la solución óptima del problema en su conjunto. Por ejemplo, el camino más corto entre dos vértices de un grafo se puede encontrar calculando primero el camino más corto al objetivo desde todos los vértices adyacentes al de partida, y después usando estas soluciones para elegir el mejor camino de todos ellos. En general, se pueden resolver problemas con subestructuras óptimas siguiendo estos tres pasos:

  1. Dividir el problema en subproblemas más pequeños.
  2. Resolver estos problemas de manera óptima usando este proceso de tres pasos recursivamente.
  3. Usar estas soluciones óptimas para construir una solución óptima al problema original.

Los subproblemas se resuelven a su vez dividiéndolos en subproblemas más pequeños hasta que se alcance el caso fácil, donde la solución al problema es trivial.

Decir que un problema tiene subproblemas superpuestos es decir que se usa un mismo subproblema para resolver diferentes problemas mayores. Por ejemplo, en la sucesión de Fibonacci (F3 = F1 + F2 y F4 = F2 + F3) calcular cada término supone calcular F2. Como para calcular F5 hacen falta tanto F3 como F4, una mala implementación para calcular F5 acabará calculando F2 dos o más veces. Esto sucede siempre que haya subproblemas superpuestos: una mala implementación puede acabar desperdiciando tiempo recalculando las soluciones óptimas a problemas que ya han sido resueltos anteriormente.

Esto se puede evitar guardando las soluciones que ya hemos calculado. Entonces, si necesitamos resolver el mismo problema más tarde, podemos obtener la solución de la lista de soluciones calculadas y reutilizarla. Este acercamiento al problema se llama memoización (no confundir con memorización; en inglés es llamado memoization, véase en). Si estamos seguros de que no volveremos a necesitar una solución en concreto, la podemos descartar para ahorrar espacio. En algunos casos, podemos calcular las soluciones a problemas que de antemano sabemos que vamos a necesitar.

En resumen, la programación hace uso de:

  • Subproblemas superpuestos
  • Subestructuras óptimas
  • Memoización

La programación toma normalmente uno de los dos siguientes enfoques:

  • Top-down: El problema se divide en subproblemas, y estos se resuelven recordando las soluciones por si fueran necesarias nuevamente. Es una combinación de memoización y recursión.
  • Bottom-up: Todos los problemas que puedan ser necesarios se resuelven de antemano y después se usan para resolver las soluciones a problemas mayores. Este enfoque es ligeramente mejor en consumo de espacio y llamadas a funciones, pero a veces resulta poco intuitivo encontrar todos los subproblemas necesarios para resolver un problema dado.

Originalmente, el término de programación dinámica se refería a la resolución de ciertos problemas y operaciones fuera del ámbito de la Ingeniería Informática, al igual que hacía la programación lineal. Aquel contexto no tiene relación con la programación en absoluto; el nombre es una coincidencia. El término también lo usó en los años 40 Richard Bellman, un matemático norteamericano, para describir el proceso de resolución de problemas donde hace falta calcular la mejor solución consecutivamente.

Algunos lenguajes de programación funcionales, sobre todo Haskell, pueden usar la memoización automáticamente sobre funciones con un conjunto concreto de argumentos, para acelerar su proceso de evaluación. Esto sólo es posible en funciones que no tengan efectos secundarios, algo que ocurre en Haskell pero no tanto en otros lenguajes.

Origen y definición

La programación dinámica es un método cuantitativo desarrollado por Richard Bellman alrededor de la década de los años 50, con la finalidad de optimizar procesos, ya que en ese momento esa era su función como trabajador de RAND Corporation. Bellman decidió emplear la palabra dinámica a esta técnica, ya que deseaba analizar las variables de los problemas con respecto al tiempo. Siendo así Dasgupta, Papadimitriou y Vazirani (2006), entendieron a la programación dinámica como “optimización de procesos con etapa múltiples”. La idea de Bellman sobre la teoría de programación dinámica se basa en una estructura de optimización, la cual consiste en descomponer el problema en subproblemas (más manejables). Los cálculos se realizan entonces recursivamente donde la solución óptima de un subproblema se utiliza como dato de entrada al siguiente problema. Por lo cual, se entiende que el problema es solucionado en su totalidad, una vez se haya solucionado el último subproblema. Dentro de esta teoría, Bellman desarrolla el Principio de Optimalidad, el cual es fundamental para la resolución adecuada de los cálculos recursivos. Lo cual quiere decir que las etapas futuras desarrollan una política óptima independiente de las decisiones de las etapas predecesoras. Es por ello, que se define a la programación dinámica como una técnica matemática que ayuda a resolver decisiones secuenciales interrelacionadas, combinándolas para obtener de la solución óptima.

Características

El problema se puede dividir por etapas, y cada una de las etapas requiere de una política de decisión.

Cada etapa tiene cierto número de estados, los estados son las distintas condiciones posibles en las que se puede encontrar el sistema en cada etapa.

El efecto de la política de decisión en cada etapa es transformar el estado actual en un estado asociado con el inicio de la siguiente etapa, entonces podemos decir que un estado es una columna de nodos, cada nodo representa un estado y cada rama una política de decisión.

El procedimiento de resolución de la programación dinámica está diseñado para encontrar una política óptima para cada etapa logrando así la política óptima general.

Dado el estado actual, una política óptima para las etapas restantes es independiente de la política adoptada en etapas anteriores, por ende, la decisión inmediata óptima solo depende del estado actual y no de cómo se llegó ahí, esto es el principio de optimalidad de la programación dinámica.

Se dispone de una relación recursiva que identifica la política óptima para la etapa n, dada la política óptima para la etapa n+1.

Cuando se hace uso de la relación recursiva, el procedimiento de solución comienza al final se mueve hacia atrás etapa por etapa hasta encontrar la política óptima en cada etapa hasta la etapa inicial.

Tipos de Enfoque

Existen dos tipos de programación dinámica: La programación Dinámica determinística se utilizan datos que se conocen con certeza y la programación dinámica probabilística donde se usan datos que no se conocen con certeza pero que se determinan a través de distribuciones de probabilidad.

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. En la etapa n el proceso se encontrará en algún estado Sn. Al tomar la decisión xn se mueve a algún estado Sn+1 en la etapa n+1. El valor de la función objetiva para la política óptima de ese punto en adelante se calculó previamente como f*n+1(Sn+1). La política de decisión también hace una contribución a la función objetivo. Al combinar estas dos cantidades en la forma apropiada se proporciona a la función objetivo fn(Sn,xn) la contribución de la etapa n en adelante. La optimización respecto a xn proporciona entonces f*n(Sn)= fn(Sn,xn). Una vez encontrados xn y fn*(Sn) para cada valor posible de Sn, el procedimiento de solución se mueve hacia atrás una etapa.

Los problemas de programación dinámica determinística se pueden clasificar según su función objetivo (minimizar la suma de las contribuciones de cada una de las etapas individuales, maximizar esa suma, minimizar el producto de los términos, etc.) y según la naturaleza del conjunto de estados (variables discretas o variables continuas).

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. Sea S el número de estados posibles en la etapa n+1 y etiquete estos estados al lado derecho por 1,2…,S. El sistema cambia al estado i con probabilidad pi (i=1,2…,S) dados el estado Sn y la decisión xn en la etapa n. Si el sistema cambia al estado i, Ci es la contribución de la etapa n a la función objetivo.


Cuando se expande el diagrama para incluir todos los estados y las decisiones posibles en todas las etapas, se obtiene lo que con frecuencia se conoce como un árbol de decisión. Si este árbol de decisión no es muy grande, proporciona una forma útil de resumir estas posibilidades. La programación dinámica probabilística difiere de la determinística, en que el estado de la siguiente etapa no está completamente determinado por el estado y la política de decisión de la etapa actual. En este caso, existe una distribución de probabilidad para determinar cuál será el estado en la siguiente etapa. Debido a la estructura probabilística, la relación entre fn(Sn,xn) y fn+1*(Sn+1) dependerá de la forma global de la función objetivo.

Principio de optimalidad

Cuando hablamos de optimizar nos referimos a buscar la mejor solución de entre muchas alternativas posibles. Dicho proceso de optimización puede ser visto como una secuencia de decisiones que nos proporcionan la solución correcta. Si, dada una subsecuencia de decisiones, siempre se conoce cuál es la decisión que debe tomarse a continuación para obtener la secuencia óptima, el problema es elemental y se resuelve trivialmente tomando una decisión detrás de otra, lo que se conoce como estrategia voraz. En otros casos, aunque no sea posible aplicar la estrategia voraz, se cumple el principio de optimalidad de Bellman que dicta que «dada una secuencia óptima de decisiones, toda subsecuencia de ella es, a su vez, óptima». En este caso sigue siendo posible el ir tomando decisiones elementales, en la confianza de que la combinación de ellas seguirá siendo óptima, pero será entonces necesario explorar muchas secuencias de decisiones para dar con la correcta, siendo aquí donde interviene la programación dinámica.

Contemplar un problema como una secuencia de decisiones equivale a dividirlo en problemas más pequeños y por lo tanto más fáciles de resolver como hacemos en Divide y Vencerás, técnica similar a la de programación dinámica. La programación dinámica se aplica cuando la subdivisión de un problema conduce a:

  • Una enorme cantidad de problemas.
  • Problemas cuyas soluciones parciales se solapan.
  • Grupos de problemas de muy distinta complejidad.

Ejemplos

Sucesión de Fibonacci

Esta sucesión puede expresarse mediante la siguiente recurrencia:

 

Una implementación de una función que encuentre el n-ésimo término de la sucesión de Fibonacci basada directamente en la definición matemática de la sucesión realizando llamadas recursivas hace mucho trabajo redundante, obteniéndose una complejidad exponencial:

 FUNC fib(↓n: NATURAL): NATURAL INICIO SI n = 0 ENTONCES DEVOLVER 0 SI NO, SI n = 1 ENTONCES DEVOLVER 1 SI NO devolver fib(n-1) + fib(n-2) FIN SI FIN 

Si llamamos, por ejemplo, a fib(5), produciremos un árbol de llamadas que contendrá funciones con los mismos parámetros varias veces:

  1. fib(5)
  2. fib(4) + fib(3)
  3. (fib(3) + fib(2)) + (fib(2) + fib(1))
  4. ((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
  5. (((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))

En particular, fib(2) se ha calculado tres veces desde cero. En ejemplos mayores, se recalculan muchos otros valores de fib, o subproblemas.

Para evitar este inconveniente, podemos resolver el problema mediante programación dinámica, y en particular, utilizando el enfoque de memoización (guardar los valores que ya han sido calculados para utilizarlos posteriormente). Así, rellenaríamos una tabla con los resultados de los distintos subproblemas, para reutilizarlos cuando haga falta en lugar de volver a calcularlos. La tabla resultante sería una tabla unidimensional con los resultados desde 0 hasta n.

Un programa que calculase esto, usando Bottom-up, tendría la siguiente estructura:

 FUNC Fibonacci (↓n: NATURAL): NATURAL VARIABLES tabla: ARRAY [0..n] DE NATURALES i: NATURAL INICIO tabla[0] := 0 tabla[1] := 1 PARA i = 2 HASTA n HACER tabla[i] := tabla[i-1] + tabla[i-2] FIN PARA DEVOLVER tabla[n] FIN 

La función resultante tiene complejidad O(n), en lugar de 2 a la n (puesto que genera un árbol binaria en memoria, donde el último nivel de hojas es de la forma 2 a la n). En otras palabras la programación dinámica, en este caso, permite disminuir la complejidad computacional del algoritmo.

Otro nivel de refinamiento que optimizaría la solución sería quedarnos tan sólo con los dos últimos valores calculados en lugar de toda la tabla, que son realmente los que nos resultan útiles para calcular la solución a los subproblemas.

El mismo problema usando Top-down tendría la siguiente estructura:

 FUNC Fibonacci (↓n: NATURAL, ↨tabla: ARRAY [0..n] DE NATURALES): NATURAL VARIABLES i: NATURAL INICIO SI n <= 1 ENTONCES devolver n FIN SI SI tabla[n-1] = -1 ENTONCES tabla[n-1] := Fibonacci(n-1, tabla) FIN SI SI tabla[n-2] = -1 ENTONCES tabla[n-2] := Fibonacci(n-2, tabla) FIN SI tabla[n] := tabla[n-1] + tabla[n-2] devolver tabla[n] FIN 

Suponemos que la tabla se introduce por primera vez correctamente inicializada, con todas las posiciones con un valor inválido, como por ejemplo -1, que se distingue por no ser uno de los valores que computa la función.

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:

  =   +   si 0 < k < n

  =   = 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
0 1
1 1 1
2 1 2 1
3 1 3 3 1
... ... ... ... ... ...
... ... ... ... ... ... ...
n-1 C(n-1,k-1) C(n-1,k)
n C(n,k)

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 

Por supuesto, el problema de los Coeficientes Binomiales también puede resolverse mediante un enfoque Top-down.

El viaje más barato por el río

En un río hay n embarcaderos, en cada uno de los cuales se puede alquilar un bote para ir a otro embarcadero que esté más abajo en el río. Suponemos que no se puede remontar el río. Una tabla de tarifas indica los costes de viajar entre los distintos embarcaderos. Se supone que puede ocurrir que un viaje entre i y j salga más barato haciendo escala en k embarcaderos que yendo directamente.

El problema consistirá en determinar el coste mínimo para un par de embarcaderos.

Vamos a llamar a la tabla de tarifas, T. Así, T[i,j] será el coste de ir del embarcadero i al j. La matriz será triangular superior de orden n, donde n es el número de embarcaderos.

La idea recursiva es que el coste se calcula de la siguiente manera:

C(i, j) = T[i, k] + C(k, j)

A partir de esta idea, podemos elaborar una expresión recurrente para la solución:

 0 si i = j C(i, j)= Min(T(i,k) + C(k,j), T(i,j)) si i < k <= j 

Un algoritmo que resuelve este problema es el siguiente, donde T es la matriz de tarifas, origen y destino los embarcaderos del que se parte y al que se llega respectivamente, y C la matriz en la que almacenaremos los resultados de los costes. La función MenorDeLosCandidatos devuelve el menor coste entre dos puntos, utilizando como base la recurrencia anteriormente expuesta.

 FUNC Embarcaderos ( ↓ origen, destino, n: NATURAL, ↓ T: MATRIZ DE NATURALES): NATURAL Variables C: MATRIZ DE NATURALES i, j: NATURAL Inicio PARA i = 1 HASTA n HACER C[i][i] := 0 FIN PARA PARA i = 1 HASTA n HACER PARA j = 1 HASTA n HACER C[i][j] := menorDeLosCandidatos(i, j, n, T, C) FIN PARA FIN PARA devolver C[n] [n] Fin 


 FUNC menorDeLosCandidatos ( ↓ origen, destino, n: NATURAL, ↓ T, C: MATRIZ DE NATURALES): NATURAL Variables temp: NATURAL Inicio temp := MAX_NATURAL PARA i = origen+1 HASTA n HACER temp := min(temp, T[origen][i] + C[i][destino]) FIN PARA devolver temp Fin 

Ejercicios resueltos con programación dinámica

  • Ejecución de n tareas en tiempo mínimo en un sistema de dos procesadores A y B
  • Programas en disco
  • Problema de los sellos con programación dinámica
  • Problema de la mochila
  • Problema del producto de una secuencia de matrices con programación dinámica
  • Problema de las monedas con programación dinámica
  • Camino de coste mínimo entre dos nodos de un grafo dirigido
  • Problema de la división de peso
  • Problema de las vacas con programación dinámica
  • Problema del Cambio de Palabra Programación Dinámica en JAVA
  • Problema de buscar la subsecuencia común más larga entre dos cadenas

Referencias

  • G. Vásquez, S. Fiorella L. Moreno, M. A. M. Casallo, J. Carlos. (2016). “Aplicación de modelo de programación dinámica para la asignación de recursos del área de fuerza de ventas de la empresa” [Online]. Available: http://hdl.handle.net/10757/621494
  • R. Bellman, «On the Theory of Dynamic Programming», Proceedings of the National Academy of Sciences 38(8):716-719, 1952
  • L.L. Cooper, M.W. Cooper, Introduction to dynamic programming, Pergamon Press, Elmsford NY, 1981
  • C. Cotta, Programación dinámica. Introducción y ejercicios resueltos, UMA Editorial, Málaga, 2018
  • G.L. Nemhauser, Introduction to dynamic programming, Wiley & Sons, New York NY, 1967.

Enlaces externos

  • Arquimedex - Investigación de Operaciones en la práctica
  • Investigación Programación Dinámica y su relación con los sistemas distribuidos
  •   Datos: Q380679

programación, dinámica, este, artículo, sección, necesita, referencias, aparezcan, publicación, acreditada, este, aviso, puesto, junio, 2010, informática, programación, dinámica, método, para, reducir, tiempo, ejecución, algoritmo, mediante, utilización, subpr. Este articulo o seccion necesita referencias que aparezcan en una publicacion acreditada Este aviso fue puesto el 25 de junio de 2010 En informatica la programacion dinamica es un metodo para reducir el tiempo de ejecucion de un algoritmo mediante la utilizacion de subproblemas superpuestos y subestructuras optimas como se describe a continuacion El matematico Richard Bellman invento la programacion dinamica en 1953 que se utiliza para optimizar problemas complejos que pueden ser discretizados y secuencializados Indice 1 Introduccion 2 Origen y definicion 3 Caracteristicas 4 Tipos de Enfoque 5 Principio de optimalidad 6 Ejemplos 6 1 Sucesion de Fibonacci 6 2 Coeficientes binomiales 6 3 El viaje mas barato por el rio 7 Ejercicios resueltos con programacion dinamica 8 Referencias 9 Enlaces externosIntroduccion EditarUna subestructura optima significa que se pueden usar soluciones optimas de subproblemas para encontrar la solucion optima del problema en su conjunto Por ejemplo el camino mas corto entre dos vertices de un grafo se puede encontrar calculando primero el camino mas corto al objetivo desde todos los vertices adyacentes al de partida y despues usando estas soluciones para elegir el mejor camino de todos ellos En general se pueden resolver problemas con subestructuras optimas siguiendo estos tres pasos Dividir el problema en subproblemas mas pequenos Resolver estos problemas de manera optima usando este proceso de tres pasos recursivamente Usar estas soluciones optimas para construir una solucion optima al problema original Los subproblemas se resuelven a su vez dividiendolos en subproblemas mas pequenos hasta que se alcance el caso facil donde la solucion al problema es trivial Decir que un problema tiene subproblemas superpuestos es decir que se usa un mismo subproblema para resolver diferentes problemas mayores Por ejemplo en la sucesion de Fibonacci F3 F1 F2 y F4 F2 F3 calcular cada termino supone calcular F2 Como para calcular F5 hacen falta tanto F3 como F4 una mala implementacion para calcular F5 acabara calculando F2 dos o mas veces Esto sucede siempre que haya subproblemas superpuestos una mala implementacion puede acabar desperdiciando tiempo recalculando las soluciones optimas a problemas que ya han sido resueltos anteriormente Esto se puede evitar guardando las soluciones que ya hemos calculado Entonces si necesitamos resolver el mismo problema mas tarde podemos obtener la solucion de la lista de soluciones calculadas y reutilizarla Este acercamiento al problema se llama memoizacion no confundir con memorizacion en ingles es llamado memoization vease en Si estamos seguros de que no volveremos a necesitar una solucion en concreto la podemos descartar para ahorrar espacio En algunos casos podemos calcular las soluciones a problemas que de antemano sabemos que vamos a necesitar En resumen la programacion hace uso de Subproblemas superpuestos Subestructuras optimas MemoizacionLa programacion toma normalmente uno de los dos siguientes enfoques Top down El problema se divide en subproblemas y estos se resuelven recordando las soluciones por si fueran necesarias nuevamente Es una combinacion de memoizacion y recursion Bottom up Todos los problemas que puedan ser necesarios se resuelven de antemano y despues se usan para resolver las soluciones a problemas mayores Este enfoque es ligeramente mejor en consumo de espacio y llamadas a funciones pero a veces resulta poco intuitivo encontrar todos los subproblemas necesarios para resolver un problema dado Originalmente el termino de programacion dinamica se referia a la resolucion de ciertos problemas y operaciones fuera del ambito de la Ingenieria Informatica al igual que hacia la programacion lineal Aquel contexto no tiene relacion con la programacion en absoluto el nombre es una coincidencia El termino tambien lo uso en los anos 40 Richard Bellman un matematico norteamericano para describir el proceso de resolucion de problemas donde hace falta calcular la mejor solucion consecutivamente Algunos lenguajes de programacion funcionales sobre todo Haskell pueden usar la memoizacion automaticamente sobre funciones con un conjunto concreto de argumentos para acelerar su proceso de evaluacion Esto solo es posible en funciones que no tengan efectos secundarios algo que ocurre en Haskell pero no tanto en otros lenguajes Origen y definicion EditarLa programacion dinamica es un metodo cuantitativo desarrollado por Richard Bellman alrededor de la decada de los anos 50 con la finalidad de optimizar procesos ya que en ese momento esa era su funcion como trabajador de RAND Corporation Bellman decidio emplear la palabra dinamica a esta tecnica ya que deseaba analizar las variables de los problemas con respecto al tiempo Siendo asi Dasgupta Papadimitriou y Vazirani 2006 entendieron a la programacion dinamica como optimizacion de procesos con etapa multiples La idea de Bellman sobre la teoria de programacion dinamica se basa en una estructura de optimizacion la cual consiste en descomponer el problema en subproblemas mas manejables Los calculos se realizan entonces recursivamente donde la solucion optima de un subproblema se utiliza como dato de entrada al siguiente problema Por lo cual se entiende que el problema es solucionado en su totalidad una vez se haya solucionado el ultimo subproblema Dentro de esta teoria Bellman desarrolla el Principio de Optimalidad el cual es fundamental para la resolucion adecuada de los calculos recursivos Lo cual quiere decir que las etapas futuras desarrollan una politica optima independiente de las decisiones de las etapas predecesoras Es por ello que se define a la programacion dinamica como una tecnica matematica que ayuda a resolver decisiones secuenciales interrelacionadas combinandolas para obtener de la solucion optima Caracteristicas EditarEl problema se puede dividir por etapas y cada una de las etapas requiere de una politica de decision Cada etapa tiene cierto numero de estados los estados son las distintas condiciones posibles en las que se puede encontrar el sistema en cada etapa El efecto de la politica de decision en cada etapa es transformar el estado actual en un estado asociado con el inicio de la siguiente etapa entonces podemos decir que un estado es una columna de nodos cada nodo representa un estado y cada rama una politica de decision El procedimiento de resolucion de la programacion dinamica esta disenado para encontrar una politica optima para cada etapa logrando asi la politica optima general Dado el estado actual una politica optima para las etapas restantes es independiente de la politica adoptada en etapas anteriores por ende la decision inmediata optima solo depende del estado actual y no de como se llego ahi esto es el principio de optimalidad de la programacion dinamica Se dispone de una relacion recursiva que identifica la politica optima para la etapa n dada la politica optima para la etapa n 1 Cuando se hace uso de la relacion recursiva el procedimiento de solucion comienza al final se mueve hacia atras etapa por etapa hasta encontrar la politica optima en cada etapa hasta la etapa inicial Tipos de Enfoque EditarExisten dos tipos de programacion dinamica La programacion Dinamica deterministica se utilizan datos que se conocen con certeza y la programacion dinamica probabilistica donde se usan datos que no se conocen con certeza pero que se determinan a traves de distribuciones de probabilidad 1 Programacion Dinamica Deterministica El enfoque deterministico consiste en que el estado de la siguiente etapa se encuentra determinado por completo con respecto al estado y la decision que posee la etapa actual En la etapa n el proceso se encontrara en algun estado Sn Al tomar la decision xn se mueve a algun estado Sn 1 en la etapa n 1 El valor de la funcion objetiva para la politica optima de ese punto en adelante se calculo previamente como f n 1 Sn 1 La politica de decision tambien hace una contribucion a la funcion objetivo Al combinar estas dos cantidades en la forma apropiada se proporciona a la funcion objetivo fn Sn xn la contribucion de la etapa n en adelante La optimizacion respecto a xn proporciona entonces f n Sn fn Sn xn Una vez encontrados xn y fn Sn para cada valor posible de Sn el procedimiento de solucion se mueve hacia atras una etapa Los problemas de programacion dinamica deterministica se pueden clasificar segun su funcion objetivo minimizar la suma de las contribuciones de cada una de las etapas individuales maximizar esa suma minimizar el producto de los terminos etc y segun la naturaleza del conjunto de estados variables discretas o variables continuas 2 Programacion Dinamica Probabilistica En este enfoque el valor del estado de la siguiente etapa y politica de decision queda completamente determinado mediante una distribucion probabilistica Sea S el numero de estados posibles en la etapa n 1 y etiquete estos estados al lado derecho por 1 2 S El sistema cambia al estado i con probabilidad pi i 1 2 S dados el estado Sn y la decision xn en la etapa n Si el sistema cambia al estado i Ci es la contribucion de la etapa n a la funcion objetivo Cuando se expande el diagrama para incluir todos los estados y las decisiones posibles en todas las etapas se obtiene lo que con frecuencia se conoce como un arbol de decision Si este arbol de decision no es muy grande proporciona una forma util de resumir estas posibilidades La programacion dinamica probabilistica difiere de la deterministica en que el estado de la siguiente etapa no esta completamente determinado por el estado y la politica de decision de la etapa actual En este caso existe una distribucion de probabilidad para determinar cual sera el estado en la siguiente etapa Debido a la estructura probabilistica la relacion entre fn Sn xn y fn 1 Sn 1 dependera de la forma global de la funcion objetivo Principio de optimalidad EditarCuando hablamos de optimizar nos referimos a buscar la mejor solucion de entre muchas alternativas posibles Dicho proceso de optimizacion puede ser visto como una secuencia de decisiones que nos proporcionan la solucion correcta Si dada una subsecuencia de decisiones siempre se conoce cual es la decision que debe tomarse a continuacion para obtener la secuencia optima el problema es elemental y se resuelve trivialmente tomando una decision detras de otra lo que se conoce como estrategia voraz En otros casos aunque no sea posible aplicar la estrategia voraz se cumple el principio de optimalidad de Bellman que dicta que dada una secuencia optima de decisiones toda subsecuencia de ella es a su vez optima En este caso sigue siendo posible el ir tomando decisiones elementales en la confianza de que la combinacion de ellas seguira siendo optima pero sera entonces necesario explorar muchas secuencias de decisiones para dar con la correcta siendo aqui donde interviene la programacion dinamica Contemplar un problema como una secuencia de decisiones equivale a dividirlo en problemas mas pequenos y por lo tanto mas faciles de resolver como hacemos en Divide y Venceras tecnica similar a la de programacion dinamica La programacion dinamica se aplica cuando la subdivision de un problema conduce a Una enorme cantidad de problemas Problemas cuyas soluciones parciales se solapan Grupos de problemas de muy distinta complejidad Ejemplos EditarSucesion de Fibonacci Editar Esta sucesion puede expresarse mediante la siguiente recurrencia F i b n 0 si n 0 1 si n 1 F i b n 1 F i b n 2 si n gt 1 displaystyle Fib n begin cases 0 amp textrm si n 0 1 amp textrm si n 1 Fib n 1 Fib n 2 amp textrm si n gt 1 end cases Una implementacion de una funcion que encuentre el n esimo termino de la sucesion de Fibonacci basada directamente en la definicion matematica de la sucesion realizando llamadas recursivas hace mucho trabajo redundante obteniendose una complejidad exponencial FUNC fib n NATURAL NATURAL INICIO SI n 0 ENTONCES DEVOLVER 0 SI NO SI n 1 ENTONCES DEVOLVER 1 SI NO devolver fib n 1 fib n 2 FIN SI FIN Si llamamos por ejemplo a fib 5 produciremos un arbol de llamadas que contendra funciones con los mismos parametros varias veces fib 5 fib 4 fib 3 fib 3 fib 2 fib 2 fib 1 fib 2 fib 1 fib 1 fib 0 fib 1 fib 0 fib 1 fib 1 fib 0 fib 1 fib 1 fib 0 fib 1 fib 0 fib 1 En particular fib 2 se ha calculado tres veces desde cero En ejemplos mayores se recalculan muchos otros valores de fib o subproblemas Para evitar este inconveniente podemos resolver el problema mediante programacion dinamica y en particular utilizando el enfoque de memoizacion guardar los valores que ya han sido calculados para utilizarlos posteriormente Asi rellenariamos una tabla con los resultados de los distintos subproblemas para reutilizarlos cuando haga falta en lugar de volver a calcularlos La tabla resultante seria una tabla unidimensional con los resultados desde 0 hasta n Un programa que calculase esto usando Bottom up tendria la siguiente estructura FUNC Fibonacci n NATURAL NATURAL VARIABLES tabla ARRAY 0 n DE NATURALES i NATURAL INICIO tabla 0 0 tabla 1 1 PARA i 2 HASTA n HACER tabla i tabla i 1 tabla i 2 FIN PARA DEVOLVER tabla n FIN La funcion resultante tiene complejidad O n en lugar de 2 a la n puesto que genera un arbol binaria en memoria donde el ultimo nivel de hojas es de la forma 2 a la n En otras palabras la programacion dinamica en este caso permite disminuir la complejidad computacional del algoritmo Otro nivel de refinamiento que optimizaria la solucion seria quedarnos tan solo con los dos ultimos valores calculados en lugar de toda la tabla que son realmente los que nos resultan utiles para calcular la solucion a los subproblemas El mismo problema usando Top down tendria la siguiente estructura FUNC Fibonacci n NATURAL tabla ARRAY 0 n DE NATURALES NATURAL VARIABLES i NATURAL INICIO SI n lt 1 ENTONCES devolver n FIN SI SI tabla n 1 1 ENTONCES tabla n 1 Fibonacci n 1 tabla FIN SI SI tabla n 2 1 ENTONCES tabla n 2 Fibonacci n 2 tabla FIN SI tabla n tabla n 1 tabla n 2 devolver tabla n FIN Suponemos que la tabla se introduce por primera vez correctamente inicializada con todas las posiciones con un valor invalido como por ejemplo 1 que se distingue por no ser uno de los valores que computa la funcion Coeficientes binomiales Editar El algoritmo recursivo que calcula los coeficientes binomiales resulta ser de complejidad exponencial por la repeticion de los calculos que realiza No obstante es posible disenar un algoritmo con un tiempo de ejecucion de orden O nk basado en la idea del Triangulo de Pascal idea claramente aplicable mediante programacion dinamica Para ello es necesaria la creacion 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 n k displaystyle n choose k n 1 k 1 displaystyle n 1 choose k 1 n 1 k displaystyle n 1 choose k si 0 lt k lt n n 0 displaystyle n choose 0 n n displaystyle n choose n 1La idea para construir la tabla de manera eficiente y sin valores inutiles es la siguiente 0 1 2 3 k 1 k0 11 1 12 1 2 13 1 3 3 1 n 1 C n 1 k 1 C n 1 k n C n k El siguiente algoritmo memorizado de estrategia Bottom up tiene complejidad polinomica 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 lt 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 Por supuesto el problema de los Coeficientes Binomiales tambien puede resolverse mediante un enfoque Top down El viaje mas barato por el rio Editar En un rio hay n embarcaderos en cada uno de los cuales se puede alquilar un bote para ir a otro embarcadero que este mas abajo en el rio Suponemos que no se puede remontar el rio Una tabla de tarifas indica los costes de viajar entre los distintos embarcaderos Se supone que puede ocurrir que un viaje entre i y j salga mas barato haciendo escala en k embarcaderos que yendo directamente El problema consistira en determinar el coste minimo para un par de embarcaderos Vamos a llamar a la tabla de tarifas T Asi T i j sera el coste de ir del embarcadero i al j La matriz sera triangular superior de orden n donde n es el numero de embarcaderos La idea recursiva es que el coste se calcula de la siguiente manera C i j T i k C k j A partir de esta idea podemos elaborar una expresion recurrente para la solucion 0 si i j C i j Min T i k C k j T i j si i lt k lt j Un algoritmo que resuelve este problema es el siguiente donde T es la matriz de tarifas origen y destino los embarcaderos del que se parte y al que se llega respectivamente y C la matriz en la que almacenaremos los resultados de los costes La funcion MenorDeLosCandidatos devuelve el menor coste entre dos puntos utilizando como base la recurrencia anteriormente expuesta FUNC Embarcaderos origen destino n NATURAL T MATRIZ DE NATURALES NATURAL Variables C MATRIZ DE NATURALES i j NATURAL Inicio PARA i 1 HASTA n HACER C i i 0 FIN PARA PARA i 1 HASTA n HACER PARA j 1 HASTA n HACER C i j menorDeLosCandidatos i j n T C FIN PARA FIN PARA devolver C n n Fin FUNC menorDeLosCandidatos origen destino n NATURAL T C MATRIZ DE NATURALES NATURAL Variables temp NATURAL Inicio temp MAX NATURAL PARA i origen 1 HASTA n HACER temp min temp T origen i C i destino FIN PARA devolver temp FinEjercicios resueltos con programacion dinamica EditarEjecucion de n tareas en tiempo minimo en un sistema de dos procesadores A y B Programas en disco Problema de los sellos con programacion dinamica Problema de la mochila Problema del producto de una secuencia de matrices con programacion dinamica Problema de las monedas con programacion dinamica Camino de coste minimo entre dos nodos de un grafo dirigido Problema de la division de peso Problema de las vacas con programacion dinamica Problema del Cambio de Palabra Programacion Dinamica en JAVA Problema de buscar la subsecuencia comun mas larga entre dos cadenasReferencias EditarG Vasquez S Fiorella L Moreno M A M Casallo J Carlos 2016 Aplicacion de modelo de programacion dinamica para la asignacion de recursos del area de fuerza de ventas de la empresa Online Available http hdl handle net 10757 621494 R Bellman On the Theory of Dynamic Programming Proceedings of the National Academy of Sciences 38 8 716 719 1952 L L Cooper M W Cooper Introduction to dynamic programming Pergamon Press Elmsford NY 1981 C Cotta Programacion dinamica Introduccion y ejercicios resueltos UMA Editorial Malaga 2018G L Nemhauser Introduction to dynamic programming Wiley amp Sons New York NY 1967 Enlaces externos EditarInvestigacion Operativa El Sitio de Investigacion Operativa en Espanol del Ing Santiago Javez Valladares Peru Arquimedex Investigacion de Operaciones en la practica Investigacion Programacion Dinamica y su relacion con los sistemas distribuidos Datos Q380679 Obtenido de https es wikipedia org w index php title Programacion dinamica amp oldid 142756257, wikipedia, wiki, leyendo, leer, libro, biblioteca,

español

, española, descargar, gratis, descargar gratis, mp3, video, mp4, 3gp, jpg, jpeg, gif, png, imagen, música, canción, película, libro, juego, juegos