You are on page 1of 18

UNIVERSIDAD NACIONAL DE SAN AGUSTIN

FACULTAD DE INGENIERIA DE PRODUCCION Y SERVICIOS


ESCUELA PROFESIONAL DE INGENIERIA DE SISTEMAS

CURSO: Análisis y Diseño de Algoritmos

TEMA: Informe de investigación Rod Cutting

DOCENTE: Mgter. Carlo Corrales Delgado

ALUMNOS: Herencia Castro Nicolas

Suma Paucara Miguel Angel

Ticona Bejarano Alex Daniel

GRUPO: “A”

AREQUIPA – PERU
2017

ADA Página 1
INDICE

1. RESUMEN
2. INTRODUCCION
3. DESARROLLO
4. RESULTADOS
5. CONCLUSIONES
6. BIBLIOGRAFIA
7. ANEXOS

ADA Página 2
1. RESUMEN

El problema de Rod Cutting se basa en que dada una varilla de cierta longitud (entera) y una tabla
de precios para cada posible tamaño de corte, se debe determinar la ganancia máxima que se
puede obtener al cortar la varilla y vender las piezas, además debemos recordar que una solución
óptima podría ser al no realizar ningún corte.

Para dar solución a este problema se hace uso de la técnica de programación dinámica, donde se
utiliza la recursión para poder hallar la ganancia máxima a través de una ganancia optima parcial.

Este informe describe el uso de la técnica de programación dinámica para la solución del problema
de Rod Cutting.

ADA Página 3
2. INTRODUCCION

En el diseño Divide y Vencerás veíamos cómo para resolver un problema lo dividíamos en


subproblemas independientes, los cuales se resolvían de manera recursiva para combinar
finalmente las soluciones y así resolver el problema original. El inconveniente se presenta cuando
los subproblemas obtenidos no son independientes, sino que existe solapamiento entre ellos;
entonces es cuando una solución recursiva no resulta eficiente por la repetición de cálculos que
conlleva. En estos casos es cuando la Programación Dinámica nos puede ofrecer una solución
aceptable. La eficiencia de esta técnica consiste en resolver los subproblemas una sola vez,
guardando sus soluciones en una tabla para su futura utilización.

La Programación Dinámica no sólo tiene sentido aplicarla por razones de eficiencia, sino porque
además presenta un método capaz de resolver de manera eficiente problemas cuya solución ha
sido abordada por otras técnicas y ha fracasado.

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”. 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 cuestión.

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 óptimo.

En grandes líneas, el diseño de un algoritmo de Programación Dinámica consta de los siguientes


pasos:

1. Planteamiento de la solución como una sucesión de decisiones y verificación de que ésta


cumple el principio de óptimo.
2. Definición recursiva de la solución.
3. Cálculo del valor de la solución óptima mediante una tabla en donde se almacenan soluciones
a problemas parciales para reutilizar los cálculos.
4. Construcción de la solución óptima haciendo uso de la información contenida en la tabla
anterior.

ADA Página 4
3. DESARROLLO

Serling Enterprises compra varillas largas de acero y las corta en varillas más pequeñas, las cuales
posteriormente las vende obteniendo ingresos. Se desea saber la mejor forma de cortar las
varillas.

Asumimos que sabemos el precio pi que la empresa cobra por una varilla de longitud i pulgadas.

Longitud i 1 2 3 4 5 6 7

Precio pi 1 5 8 9 10 16 17

Enunciado del problema

Dada una varilla de longitud n pulgadas y una tabla de precios pi (donde i = 1, 2, ..., n), determinar
el máximo ingreso rn que se puede obtener cortando la varilla y vendiendo las piezas.

Con varillas de longitud: 5-1-1

r = 10+1+1= 12

10 1 1
0

rn = 12

ADA Página 5
Con varillas de longitud: 1-3-1-1

r = 1+8+1+5 =15

1 8 1 5

rn = 15
Con una varilla de longitud: 7

r = 17

1
7

rn = 17
Solución óptima:

Con 3 varillas de longitud: 2-2-3

r max= 5+5+8= 18

5 5 8

rn = 18
En cuántas formas distintas podemos cortar una varilla de longitud n

En primer lugar, debemos saber que para toda varilla de longitud n, se puede realizar un número
máximo de n-1 cortes.

Luego podemos tomar la decisión de realizar o no el corte según nos sea conveniente, por lo tanto
para una varilla de longitud n donde se pueden realizar n-1 cortes hay la posibilidad de realizar o
el corte esto lo podemos tomar como un (0 o 1), por ejemplo si la varilla es de longitud 3 ,se
pueden realizar n-1= 2 cortes, así podemos calcular la variedad de posibilidades mediante la

ADA Página 6
combinación 00,01,10,11, donde 00 significa que la varilla no ha sido cortada, 01 que se ha
realizado un corte en la posición 2, 10 que se ha realizado un corte en la posición 1 y así
sucesivamente.

Mediante esta demostración nos damos percatamos que en número total de combinaciones que
podemos realizar es: 2n-1

Ejemplo: para n=4

a) b) c) d)

e) f) g) h)
Hay 𝑛 − 1 posiciones de corte, y se debe escoger 0 ≤ 𝑘 ≤ 𝑛 − 1 cortes

Entonces 2n-1 = 23 = 8 posibles combinaciones.

Algoritmo de fuerza bruta

Al aplicar este algoritmo debemos calcular todas las posibles combinaciones y retornar la que de la
mayor suma, este algoritmo resuelve el problema, pero no es eficiente porque si calculamos su
tiempo de ejecución éste es de orden exponencial T(n)= Θ (2n) que es bastante caro.

Con lo cual queda demostrado que debemos utilizar otro algoritmo para resolver el problema.

(ver implementación en el anexo N0 1)

Utilizando Programación Dinámica

Notación Aditiva:

7=2+2+3

Si una solución óptima corta la varilla en k piezas, donde 1 ≤ 𝑘 ≤ 𝑛, entonces su descomposición


sería:

𝑛 = 𝑖1 + 𝑖2 + ⋯ + 𝑖𝑘

𝑟𝑛 = 𝑝𝑖1 + 𝑝𝑖2 + ⋯ + 𝑝𝑖𝑘

ADA Página 7
La solución óptima final estaría compuesta por una solución óptima parcial anterior más la varilla
(i) seleccionada. El máximo ingreso rn que se podrá obtener después de encontrar el mayor valor
entre todas las posibles soluciones compuestas por el precio de la varilla de tamaño i (pi) más una
solución óptima anterior.

𝑝1 + 𝑟𝑛−1
𝑝2 + 𝑟𝑛−2

𝒎𝒂𝒙
𝑝𝑛−1 + 𝑟1 𝑟𝑛 = (𝑝 + 𝑟𝑛−𝑖 )
1≤𝑖≤𝑛 𝑖

𝑝𝑛

Hallmark #1 Subestructura Optima: La solución óptima global contiene soluciones optimas


parciales

Demostración: Sea 𝑟𝑛 el ingreso máximo obtenido, es decir:

𝑟𝑛 = 𝑝𝑖 + 𝑎 con a = 𝑟𝑛−𝑖

𝑟𝑛−𝑖 debe ser óptimo?

Supongamos que existe un b > a, entonces: 𝑟 = 𝑝𝑖 + 𝑏

→ 𝑟 > 𝑟𝑛 , pero esto es contradictorio.

Implementación

ADA Página 8
¿Por qué es ineficiente?

Porque como vemos en el grafico existen muchos subárboles que vuelven a ser calculados varias
veces, lo cual no sería necesario si utilizamos un arreglo auxiliar para almacenar los valores
calculados.

Cut-Rod(p, n) → Cut-Rod(p, n-i) , i = 1,2, ... n

n–1 n-2 ... 1 0

n–2 n-3 ... 1 0 n–3 n-4 ... 1 0 0

... ... 0 ... ... 0

𝑛 = 0, 1
𝑛
𝑇(𝑛) = {
𝑛 ≥ 1, 1 + ∑ 𝑇(𝑛 − 𝑖)
𝑖=1

𝑇(𝑛) = 2𝑛

Hallmark #2 Subestructura Optima: La solución recursiva contiene pequeños subproblemas


repetidos

La solución óptima se calcula a través de ir calculando el mayor precio de las pequeñas soluciones.

ADA Página 9
Solución aplicar memorización para subárboles ya calculados:

Se llena una tabla con números negativos puesto que la ganancia no puede ser negativa y siempre
va a ser mayor a 0, luego cada vez que se calcula un valor, éste se guarda en la tabla para ser
posteriormente utilizado si vuelve a ser evocado.

Donde:

T(n)=θ(n2)

ADA Página 10
Ejemplo: Hallar el máximo ingreso con una varilla de tamaño 4

Longitud i 1 2 3 4

Precio pi 1 5 8 9

1. El problema principal se divide en n-1 subproblemas

Cut-Rod(p, 4,r) → p[i] + Cut-Rod(p, n-i,r) , i = 1,2, ... n

C-r(p,4)

1+C-r(p,3) 5+C-r(p,2) 8+C-r(p,1) 9+C-r(p,0)

2. Se desarrolla la recursión hasta llegar al caso base (n=0) luego se empieza a resolver la recursión
y se guarda el mayor valor obtenido entre las opciones que se tenga.
C-r(p,4)

1+C-r(p,3) 5+C-r(p,2) 8+C-r(p,1) 9+C-r(p,0)

1+C-r(p,2) 5+C-r(p,1) 8+C-r(p,0)

1+C-r(p,1) 5+C-r(p,0) 1+C-r(p,0) 0

1+C-r(p,0) 0 0

ADA Página 11
3. Se utiliza la memorizacion para guardar los valores de subproblemas ya calculados, siempre
guardando el valor maximo.

C-r(p,4)

1+C-r(p,3) 5+C-r(p,2) 8+C-r(p,1) 9+C-r(p,0)

1+C-r(p,2) 5+C-r(p,1) 8+C-r(p,0)

Max( )

1+1 5+0 1+C-r(p,0) 0

i 0 1 2 3 4

r[n] 0 1 -inf -inf -inf

4. Finalmente tomamos como solucion el mayor valor de todas las opciones calculadas

Solución óptima:
C-r(p,4)

Max( )

1+8 5+5 8+1 9+0

i 0 1 2 3 4

r[n] 0 1 5 8 10

Solución: El máximo ingreso que se puede obtener para la varilla de tamaño 4 es 10$.

ADA Página 12
4. RESULTADOS

Como resultado hemos comprobado que, al aplicar la técnica de programación dinámica con
memorización, ésta nos ayuda a reducir el tiempo de ejecución en comparación con la solución
iterativa (algoritmo de fuerza bruta) y la solución de programación dinámica sin memorización.

El tiempo calculado se reduce bastante y si es posible de ser ejecutado en un computador con un


procesador estándar, pues las otras soluciones demoran demasiado tiempo en ser resueltas y
consumen más recursos como tiempo y espacio.

Al realizar el análisis del tiempo de ejecución de los algoritmos que solucionan este problema
podemos verificar que el algoritmo de fuerza bruta es más caro θ(2n) luego está el de top down
θ(n2) y finalmente el de botton up 0(n2).

Implementación Anexo N0 1, 2,3

ADA Página 13
5. CONCLUSIONES

En conclusión, un algoritmo de programación dinámica es utilizado sólo si el problema exhibe las


características adecuadas para ser resuelto.

Los algoritmos de programación dinámica hacen uso de memoria auxiliar para guardar valores pre
calculados.

Aplicar la técnica de programación dinámica es la mejor solución que reduce el tiempo de


ejecución para el problema de Rod Cutting.

ADA Página 14
6. BIBLIOGRAFIA

7. Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein (2009)


Introduction to Algorithms, Third Edition.
8. Taller de Programación Dinámica Pablo Haramburu - Cristian Martinez Departamento de
Computación Facultad de Ciencias Exactas y Naturales Universidad de Buenos Aires
9. http://www.lcc.uma.es/~av/Libro/CAP5.pdf

ADA Página 15
7. ANEXOS
1. Implementación fuerza bruta

1. import java.util.Scanner;
2.
3. public class RODCUTTINGFUERZABRUTA {
4. public RODCUTTINGFUERZABRUTA(){
5.
6. }
7. public void procesarporfuerzabruta(){
8. int longitud=0;
9. Scanner scaner=new Scanner(System.in);
10. System.out.println("ingresa la longitud: " );
11. longitud=scaner.nextInt();
12. int precio[]=new int[longitud+1];
13. precio[0]=0;
14. for(int i=1;i<=longitud;++i){
15. System.out.println("ingresa el precio de corte para longitud: "+i+" :" );
16. precio[i]=scaner.nextInt();
17.
18. }
19. System.out.println("la ganancia es : "+rdfuerzabruta( precio,longitud));
20. }
21. public int rdfuerzabruta(int precio[],int l){
22. if(l==0)return 0;
23. int q=0;
24. for(int i=1;i<=l;++i){
25. int x=precio[i]+rdfuerzabruta(precio,l-i);
26. if(x>q)q=x;
27. }
28. return q;
29. }
30. public static void main(String[]args){
31. RODCUTTINGFUERZABRUTA test= new RODCUTTINGFUERZABRUTA();
32. test.procesarporfuerzabruta();
33. }
34. }

2. Implementación Top down, programación dinámica

1. import java.util.Scanner;
2.
3. public class RODCUTTINGtopdown {
4. public RODCUTTINGtopdown(){}
5.
6. public int rodcuttingtopdown(int precio[],int longitud){
7. if(longitud==0)return 0;
8. int ganancia[]=new int[longitud+1];
9. for(int i=0;i<ganancia.length;++i){
10. ganancia[i]=-1;
11. }
12. return rodcuttingtopdown( ganancia,precio, longitud);
13. }
14. public int rodcuttingtopdown(int ganancia[],int precio[],int longitud){
15. if(ganancia[longitud]>=0)return ganancia[longitud];
16. if(longitud==0)return 0;

ADA Página 16
17. int q=0;
18. for(int i=1;i<=longitud;++i){
19. int x=precio[i]+rodcuttingtopdown(ganancia, precio,longitud-i);
20. if(x>q)q=x;
21. }
22. return q;
23. }
24. public void procesarportopdown(){
25. int longitud=0;
26. Scanner scaner=new Scanner(System.in);
27. System.out.println("ingresa la longitud: " );
28. longitud=scaner.nextInt();
29. int precio[]=new int[longitud+1];
30. precio[0]=0;
31. for(int i=1;i<=longitud;++i){
32. System.out.println("ingresa el precio de corte para longitud: "+i+" :" );
33. precio[i]=scaner.nextInt();
34.
35. }
36. System.out.println("la ganancia es : "+rodcuttingtopdown( precio,longitud));
37. }
38. public static void main(String[]args){
39. RODCUTTINGtopdown test= new RODCUTTINGtopdown();
40. test.procesarportopdown();
41. }
42. }

3. Implementación Botton up, programación dinámica

1. import java.util.Scanner;
2.
3. public class RODCUTTINGbottomup {
4. public int longitud;
5. public int costo[];
6. public int resultado[];
7. public int f[];
8. public RODCUTTINGbottomup(int n){
9. longitud=n;
10. costo =new int[n+1];
11. resultado =new int[n+1];
12. f=new int[n+1];
13. }
14. public void llena(){
15. Scanner s=new Scanner(System.in);
16. costo[0]=0;
17. for(int i=1;i<costo.length;++i){
18.
19.
20. System.out.println("ingrese costo para el tronco de longitud:"+ i+" :");
21. costo[i]=s.nextInt();
22. }
23.
24.
25. }
26. public int calcula(){
27. int n=longitud;
28. f[0]=0;

ADA Página 17
29.
30. for(int i=1;i<=n;++i){
31. f[i]=-1;
32. for(int j=1;j<=i;++j){
33. int c=costo[j]+f[i-j];
34. if(c>f[i]){
35. f[i]=c;
36. resultado[i]=j;
37.
38. }
39. }
40.
41. }
42. return f[longitud];
43. }
44. public void resultado(){
45. int n=longitud;
46. /* for(int j=0;j<=n;++j)
47. System.out.println(f[j]);
48. System.out.println("matriz resultado");
49. for(int v=0;v<=n;++v)
50. System.out.println(resultado[v]);*/
51. while(n>0){
52. System.out.println("en la fase: "+n+" se corto una longitud de "+resultado[n] );
53. n-=resultado[n];
54.
55. }
56. }
57.
58. public static void main(String[]args){
59. System.out.println("ingrese la longitud de la varilla:");
60. Scanner s=new Scanner(System.in);
61. int n=s.nextInt();
62. RODCUTTINGbottomup test=new RODCUTTINGbottomup(n);
63. test.llena();
64. int r=test.calcula();
65. System.out.println("la ganancia maxima es :"+r);
66. test.resultado();
67.
68. }
69. }

ADA Página 18

You might also like