Descargar la presentación
La descarga está en progreso. Por favor, espere
1
Tema 08: Programación dinámica
Instituto Politécnico Nacional Escuela Superior de Cómputo Análisis de algoritmos Tema 08: Programación dinámica M. en C. Edgardo Adrián Franco Martínez @edfrancom edgardoadrianfrancom
2
Contenido Introducción Programación dinámica
Enfoques de la programación dinámica Principio de optimalidad Diseño de un algoritmo de programación dinámica Ejemplos Fibonacci Cálculo del coeficiente binomial Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
3
Introducción La técnica divide y vencerás señala que es posible dividir un problema en subproblemas y combinar las soluciones para resolver el problema original. En ocasiones resolver subproblemas nos lleva a considerar subproblemas idénticos. Si aprovechamos la duplicación, resolviendo cada problema una sola vez, guardando la solución para su uso posterior entonces tendremos un algoritmo más eficiente. Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
4
La idea de la programación dinámica es evitar repetición de cálculos.
La base de la programación dinámica es el razonamiento inductivo: ¿Como resolver un problema combinando soluciones para problemas más pequeños? Se resuelven primero los subproblemas más pequeños y por tanto más simples. Combinando las soluciones se obtienen las soluciones de ejemplares sucesivamente más grandes hasta llegar al ejemplar original. Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
5
Programación dinámica
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. Una subestructura óptima significa que se pueden usar soluciones óptimas de subproblemas para encontrar la solución óptima del problema en su conjunto. Un problema tiene subproblemas superpuestos si se usa un mismo subproblema para resolver diferentes problemas mayores. Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
6
La programación dinámica por el contrario, es un método ascendente:
Los algoritmos divide y vencerás están dentro de los métodos descendentes. Empezar con el problema original y descomponerlo en pasos sucesivos en problemas de menor tamaño. La programación dinámica por el contrario, es un método ascendente: Resolver primero los problemas pequeños (guardando las soluciones) y después combinarlas para resolver problemas más grandes. La programación dinámica hace uso de: Subproblemas superpuestos Subestructuras óptimas Memoizacion Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
7
En general, se pueden resolver problemas con subestructuras óptimas siguiendo estos tres pasos:
Dividir el problema en subproblemas más pequeños. Resolver estos problemas de manera óptima usando este proceso de tres pasos recursivamente. 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. Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
8
Ejemplo: Fibonacci (Problemas
𝚶( 𝒄 𝒏 ) Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
9
Si se llama a fib(5), se produce un árbol de llamadas que contendrá funciones con los mismos parámetros 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)) Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
10
Cuando se llega en el árbol a los casos base (señalados en la imagen) evidentemente las llamadas a la función se detienen. Pero también podemos notar que existen varios casos en donde se llama recursivamente a números que ya fueron calculados, por ejemplo el 3. Entonces para subsecuentes llamadas la cantidad de operaciones a calcular se volverían exponenciales y la complejidad aproximada sería 𝑂(𝑐 𝑛 ) lo cuál para un n=20 ya es mucho que calcular (𝑂 ( ) 𝑛 ≈15,127 llamadas a la función). Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
11
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 memorizació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. Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
12
Memoizacion Los subproblemas superpuestos provocan resolver varias veces el mismo problema, ya que la solución de un subproblema requiere calcular soluciones que otro subproblema también tenga que calcular. Perder tiempo calculando varias veces la solución al mismo subproblema 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 (Memoization en inglés) o memorización se diferencia de 'memorización' puesto que el término ya era usado en matemáticas). Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
13
Se puede resolver el problema, utilizando el enfoque de memorizació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. Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
14
En programación dinámica comúnmente se utilizan tablas de resultados conocidos que se va generando a medida que se resuelven los subcasos. Function Fibonacci (n:int): int; if (n=0) return 0; else if (n=1) return 1; else if (Fib[n]!=NONE) return Fib[n]; else Fib[n]=Fibonacci(n-1)+fibonacci(n-2); Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez f(4) f(3) f(2) f(1) f(0) f(4) f(3) f(2) f(1) f(0)
15
Subestructuras óptimas
Donde tiene mayor aplicación la Programación Dinámica es en la resolución de problemas de optimización. En este tipo de problemas se pueden presentar distintas soluciones, cada una con un valor, y lo que se desea es encontrar la solución de valor óptimo (máximo o mínimo). La solución de problemas mediante esta técnica 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 también óptima”. Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
16
Enfoques de la programación dinámica
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. Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
17
Fibonacci utilizando (Programación dinámica -Top-down)
int tabla[n]; // tabla {-1,-1,…,-1} int fibonacci(int n) { if (n<2) return n; if(tabla[n-1] == -1) tabla[n-1] = fibonacci(n-1); if(tabla[n-2] == -1) tabla[n-2] = fibonacci(n-2); tabla[n] = tabla[n-1] + tabla[n-2]; return tabla[n]; } 𝚶(𝒏) Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
18
Fibonacci utilizando (Programación dinámica - Buttom-up)
int fibonacci(int n) { int i; if (n<2) return n; } else tabla[0] = 0; tabla[1] = 1; for(i = 2; i < n; i++) tabla[i] = tabla[i-1] + tabla[i-2]; return tabla[n-1]; 𝚶(𝒏) Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
19
Principio de optimalidad
Cuando hablamos de optimizar nos referimos a buscar alguna de las mejores soluciones (solución optima) de entre muchas alternativas posibles. Dicho proceso de optimización puede ser visto como una secuencia de decisiones que nos proporcionan la solución optima. 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. Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
20
“En una secuencia de decisiones óptima toda subsecuencia ha de ser también óptima”
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. 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. Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
21
Diseño de un algoritmo de programación dinámica
Para que un problema pueda ser abordado por esta técnica ha de cumplir dos condiciones: La solución al problema ha de ser alcanzada a través de una secuencia de decisiones, una en cada etapa. Dicha secuencia de decisiones ha de cumplir el principio de optimalizad. Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
22
El diseño de un algoritmo de Programación Dinámica consta de los siguientes pasos:
Planteamiento de la solución como una sucesión de decisiones y verificación de que ésta cumple el principio de óptimo. Definición recursiva* o iterativa de la solución. Cálculo del valor de la solución óptima mediante una estructura de datos en donde se almacenan soluciones a problemas parciales para reutilizar los cálculos. Construcción de la solución óptima haciendo uso de la información contenida en la estructura de datos. Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
23
Cálculo del coeficiente binomial
Los coeficientes binomiales o números combinatorios son una serie de números estudiados en combinatoria que indican el número de formas en que se pueden extraer subconjuntos a partir de un conjunto dado. P.g. Se tiene un conjunto con 6 objetos diferentes {A,B,C,D,E,F}, de los cuales se desea escoger 2 (sin importar el orden de elección). ¿Cuántas formas de elección existen? Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez A B C D E F A,B A,C A,D A,E A,F B,C B,D B,E B,F C,D C,E C,F D,E D,F E,F
24
El coeficiente binomial 𝑛 𝑘 está dado por la fórmula 𝑛 𝑘 = 𝑛! 𝑘! 𝑛−𝑘 !
El número de formas de escoger k elementos a partir de un conjunto de n, puede denotarse de varias formas: 𝐶 𝑛, 𝑘 , 𝑛 𝐶 𝑘, 𝑛 𝑘 𝐶 6,2 =6 𝐶 2= =15 Los números C(n,k) se conocen como “coeficientes binomiales”, pero es frecuente referirse a ellos como “combinaciones de n en k”, o simplemente “n en k”. Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez El coeficiente binomial 𝑛 𝑘 es el número de subconjuntos de k elementos escogidos de un conjunto con n elementos El coeficiente binomial 𝑛 𝑘 está dado por la fórmula 𝑛 𝑘 = 𝑛! 𝑘! 𝑛−𝑘 !
25
Forma recursiva del coeficiente binomial
Si se desea calcular C(5,3), ¿Cuáles son los casos que se repiten? 𝑛 𝑘 = 1 𝑛−1 𝑘−1 + 𝑛−1 𝑘 𝑠𝑖 𝑘=0 𝑜 𝑘=𝑛 𝑠𝑖 0<𝑘<𝑛 𝑒𝑛 𝑐𝑎𝑠𝑜 𝑐𝑜𝑛𝑡𝑟𝑎𝑟𝑖𝑜 Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez funcion C(n,k) { Si k = 0 o k = n entonces devolver 1 sino si 0 < k< n devolver C(n-1,k-1) + C(n-1,k) sino devolver 0 }
26
Coeficiente binomial (Top-down)
int tabla[n] [n]; // tabla[][] {-1,-1,…,-1} int coef_bino (int n) { if (k==0||k==n) return 1; else if(k>0&&k<n) if(tabla[n-1][k-1]==-1) tabla[n-1][k-1]=coef_bino(n-1,k-1); if(tabla[n-1][k]==-1) tabla[n-1][k]=coef_bino(n-1,k); return tabla[n-1][k-1]+tabla[n-1][k]; } else return 0; Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
27
El algoritmo recursivo que los calcula 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. Para ello es necesario la creación de una tabla bidimensional en la que ir almacenando los valores intermedios que se utilizan posteriormente. Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
28
Coeficiente binomial (Bottom-up)
Se ira construyendo la tabla por filas de arriba hacia abajo y de izquierda a derecha mediante el siguiente algoritmo de complejidad polinómica (Bottom-up). int coef_bino(int n, int k) { int i, j; for(i = 0; i <= n; i++) tabla[i][0] = 1; for(i = 1; i<= n; i++) tabla[i][1] = i; for(i = 2; i<= k; i++) tabla[i][i] = 1; for(i = 3; i <= n; i++) for(j = 2; j <= i-1; j++) if(j <= k) tabla[i][j] = tabla[i-1][j-1] + tabla[i-1][j]; return tabla[n][k]; } Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
29
Resultado Triangulo de Pascal
Análisis de algoritmos 08 Programación dinámica Prof. Edgardo Adrián Franco Martínez
Presentaciones similares
© 2025 SlidePlayer.es Inc.
All rights reserved.