Problema de La Mochila
Short Description
Download Problema de La Mochila...
Description
PROBLEMA DE LA MOCHILA (KNAPSACK PROBLEM)
1. INTRODUCCIÓN El problema de la mochila es un problema simple de entender: hay una persona que tiene una mochila con una cierta capacidad y tiene que elegir qué elementos pondrá en ella. Cada uno de los elementos tiene un peso y aporta un beneficio. El objetivo de la persona es elegir los elementos que le permitan maximizar el beneficio sin excederse de la capacidad permitida. A la vez es un problema complejo, si por complejidad nos referimos a la computacional. “Un problema se cataloga como inherentemente difícil si su solución requiere de una cantidad significativa de recursos computacionales, sin importar el algoritmo utilizado.” El problema de la mochila forma parte de una lista histórica de problemas NP − Completos elaborada por Richard Karp en 1972. En el caso del problema de la mochila, si contáramos con 4 productos, para saber cuál es la mejor solución podríamos probar las 24 = 16 posibilidades. El 2 se desprende del hecho de que cada decisión es incluir o no al producto y el 4 de la cantidad de productos. 16 posibilidades es un número manejable, sin embargo, si la cantidad de elementos por ejemplo ascendiera a 20, tendríamos que analizar nada más y nada menos que 220 = 1,048,576 posibilidades.
2. DEFINICIÓN FORMAL DEL PROBLEMA Supongamos que tenemos n distintos tipos de ítems, que van del 1 al n. De cada tipo de ítem se tienen qi ítems disponibles, donde qi es un entero positivo que cumple: Cada tipo de ítem i tiene un beneficio asociado dado por vi y un peso (o volumen) wi. Usualmente se asume que el beneficio y el peso no son negativos. Para simplificar la representación, se suele asumir que los ítems están listados en orden creciente según el peso (o volumen). Por otro lado se tiene una mochila, donde se pueden introducir los ítems, que soporta un peso máximo (o volumen máximo) W.
El problema consiste en meter en la mochila ítems de tal forma que se maximice el valor de los ítems que contiene y siempre que no se supere el peso máximo que puede soportar la misma. La solución al problema vendrá dado por la secuencia de variables x1, x2, ..., xn donde el valor de xi indica cuantas copias se meterán en la mochila del tipo de ítem i. El problema se puede siguiente programa lineal:
expresar
Maximizar
∑
Tal que
∑
matemáticamente
por
medio
del
Y Si para i=1,2,...,n se dice que se trata del problema de la mochilla 01. Si uno o más es infinito entonces se dice que se trata del problema de la mochila no acotado también llamado a veces problema de la mochila entera. En otro caso se dice que se trata del problema de la mochila acotado. 3. ALGORITMO (PARADIGMA: DIVIDE AND CONQUER) Para que el algoritmo propuesto funcione correctamente los elementos a insertar en la mochila se han de ordenar en función de la relación peso/beneficio:
El Quicksort trabaja particionando el conjunto a ordenar en dos partes, para después ordenar dichas partes independientemente. El punto clave del algoritmo está en el procedimiento que divide el conjunto. El proceso de división del conjunto debe cumplir las siguientes tres condiciones: a. El elemento pivote=a[i] está en su posición final en el array para algún índice i. b. Todos los elementos en a[first], ..., a[i-1] son menores o iguales a a[i]. c. Todos los elementos en a[i+1], ..., a[last] son mayores que a[i]. En este punto se aplica el mismo método recursivamente a los dos subproblemas generados: a[first], ... , a[i-1] y a[i+1], ... , a[last]. El resultado final será una matriz completamente ordenada, y por tanto no hace falta un paso subsiguiente de combinación.
4. EL ALGORITMO A. ANÁLISIS DEL PROBLEMA Para el análisis tomaremos un caso en particular. Sea el conjunto de elementos (6) con las siguientes características:
VALOR PESO
0 50 60
1 40 40
2 30 20
3 66 30
4 20 10
5 60 50
Y una mochila con capacidad de 100. a. VORAZ SIN ORDENAMIENTO Si tomamos los elementos tal cual son ingresados (sin ordenamiento previo). Tomaríamos los 2 primeros: VALOR 50 40
PESO 60 40
FRACCIÓN 1 1
Valor máximo obtenido: 90 b. MAYOR VALOR Si consideramos como parámetro de decisión el valor de los objetos a escoger, tomaríamos los siguientes elementos: VALOR 66 60 50
PESO 30 50 60
FRACCIÓN 1 1 1/3
Para el caso de MOCHILA FRACCIONARIA debemos tomar solo una porción del último elemento para no excedernos en el peso. Valor máximo obtenido: 142.667 VALOR 66
PESO 30
60 30
50 20
Para el caso de MOCHILA NO FRACCIONARIA tomamos el siguiente elemento con mayor valor cuyo peso sea menor o igual al peso restante antes de sobrepasar la capacidad de la mochila. Valor máximo obtenido: 156
Observamos mejores resultados respecto del caso anterior. c. MENOR PESO Si consideramos como parámetro de decisión el menor peso de los objetos a escoger, tendríamos la siguiente solución VALOR 20 30 66 40
PESO 10 20 30 40
FRACCIÓN 1 1 1 1
Valor máximo obtenido: 156 Observamos mejores resultados respecto del caso anterior.
d. MEJOR RENTABILIDAD Concluimos que si tomamos en cuenta algún parámetro de ordenación previa de los vectores PESO y VALOR obtenemos mejores soluciones para el problema. Sin embargo, aún podemos optimizar la solución si consideramos los dos parámetros a la vez. ¿Cómo? Relacionándolos. ¿Cómo los relacionamos? Con un nuevo parámetro al que llamaremos: RENTABILIDAD, que viene a ser la relación inversa entre VALOR y PESO.
De esta manera generamos un nuevo vector RENTA a partir de los 2 iniciales:
VALOR PESO RENTA
0 50 60 0.83
1 40 40 1
2 30 20 1.5
3 66 30 2.2
4 20 10 2
5 60 50 1.2
Para el caso de MOCHILA FRACCIONARIA tomaremos los elementos siguientes: RENTA VALOR 2.2 66 2 20 1.5 30 1.2 60
PESO 30 10 20 50
FRACCIÓN 1 1 1 4/5
Valor máximo obtenido: 164
Para el caso de MOCHILA NO FRACCIONARIA tomaremos los elementos siguientes: RENTA VALOR 2.2 66 2 20 1.5 30 1 40
PESO 30 10 20 40
Valor máximo obtenido: 156 B. IMPLEMENTACIÓN DEL ALGORITMO a. ORDENAMIENTO Realizamos el ordenamiento mediante el algoritmo de ordenamiento Quicksort basado en el paradigma DnC (Divide y Conquer).
void quicksort(float v[], float w[],int inf,int sup) { int i,j,div; double pivote, tmp, tmp2, a, b; div=(inf+sup)/2;
pivote=v[div]/w[div]; i=inf; j=sup; do { while((v[i]/w[i])>pivote)i++; while((v[j]/w[j])
View more...
Comments