ESCUELA POLIT ECNICA NACIONAL´ - Escuela Politécnica...
Transcript of ESCUELA POLIT ECNICA NACIONAL´ - Escuela Politécnica...
ESCUELA POLITECNICA NACIONAL
FACULTAD DE CIENCIAS
ALGORITMOS DE SOLUCION PARA UNA VERSION DINAMICA
DEL PROBLEMA DE LA MOCHILA
PROYECTO PREVIO A LA OBTENCION DEL TITULO DE INGENIERIA
MATEMATICA
BRUNO SILVA BASTIDAS
Director: LUIS MIGUEL TORRES CARVAJAL
2014
DECLARACION
Yo BRUNO SILVA BASTIDAS, declaro bajo juramento que el trabajo aquı escrito es
de mi autorıa; que no ha sido previamente presentado para ningun grado o calificacion
profesional; y que he consultado las referencias bibliograficas que se incluyen en este
documento.
A traves de la presente declaracion cedo mis derechos de propiedad intelectual, corres-
pondientes a este trabajo, a la Escuela Politecnica Nacional, segun lo establecido por
la Ley de Propiedad Intelectual, por su reglamento y por la normatividad institucional
vigente.
Bruno Silva Bastidas
.
CERTIFICACION
Certifico que el presente trabajo fue desarrollado por BRUNO SILVA BASTIDAS, bajo
mi supervision.
Luis Miguel Torres Carvajal
Director del Proyecto
AGRADECIMIENTOS
A mis padres, por haberme regalado una vida llena de felicidad ası como demostrado
lo importante que es la union en una familia y la entrega para sacarla adelante, son
los mejores padres que un hijo haya podido tener.
A mis hermanos, por haber sido mis companeros de vida desde el principio y espero
que hasta el final, me siento orgulloso de ser su hermano.
A Elsita y Tatti, por haber sido un gran apoyo cuando lo necesite.
A toda mi familia, por ser el pilar mas importante para conseguir lo que he conseguido
hasta ahora.
A Luis Miguel, por haber sido no solo tutor sino un amigo al haber invertido gran parte
de su tiempo en este proyecto.
A Jaimillo, mi mejor amigo sin mas palabras una gran persona tal como Don Jaimito.
A Pablo, mejores amigos desde ninos bro debıas estar aquı.
A Ruben, Diego y Angelito, la clase de amigos que no se pueden encontrar con facilidad
en ningun lugar.
A los Turus (Patrulla Cerebro), hicieron interesante el transcurso por la Poli y al
parecer me hicieron parte de su grupo, gracias.
Al resto de mis amigos, igual de importantes por haber estado conmigo en las buenas
y en las malas, les agradezco en verdad a todos por igual.
DEDICATORIA
A mi padre, a pesar de que no puede estar aquı conmigo para verme alcanzar esta
meta se que estarıa orgulloso como mi madre, no puedo expresar toda la gratitud y
orgullo que siento al haber sido su hijo.
Bruno
Indice de contenido
Indice de figuras viii
Indice de cuadros ix
Resumen 1
Abstract 2
1 Introduccion 1
1.1 El problema clasico de la mochila . . . . . . . . . . . . . . . . . . . . . 1
1.2 Algoritmos de Solucion . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2.1 Algoritmo del item crıtico . . . . . . . . . . . . . . . . . . . . . 3
1.2.2 Algoritmo Gloton . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2.3 Algoritmo de Horowitz-Sahni . . . . . . . . . . . . . . . . . . . 7
1.2.4 Algoritmo de programacion dinamica . . . . . . . . . . . . . . . 9
1.2.5 Esquemas de aproximacion . . . . . . . . . . . . . . . . . . . . . 10
1.3 Versiones dinamicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.3.1 Problema de la mochila con duracion (KP-DUR) . . . . . . . . 13
1.3.2 Problema de la mochila dinamico y estocastico (DSKP) . . . . . 13
1.3.3 Problema temporal de la mochila (TKP) . . . . . . . . . . . . . 14
2 El Problema KP-DUR 15
2.1 Modelo de programacion entera . . . . . . . . . . . . . . . . . . . . . . 15
2.2 Cotas Superiores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.2.1 El problema KP-CT . . . . . . . . . . . . . . . . . . . . . . . . 25
2.2.2 El problema KP-PD . . . . . . . . . . . . . . . . . . . . . . . . 27
2.2.3 Algoritmo Critical Item Dinamico . . . . . . . . . . . . . . . . . 28
2.2.4 Algoritmo Horowitz-Sahni Dinamico . . . . . . . . . . . . . . . 31
2.3 Heurıstica primal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.4 Algoritmo branch-and-bound . . . . . . . . . . . . . . . . . . . . . . . . 33
vi
3 Implementacion Computacional 43
3.1 Modelo general . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.2 Algoritmos Critical Item y Horowitz-Sahni . . . . . . . . . . . . . . . . 45
3.2.1 Algoritmo Critical Item . . . . . . . . . . . . . . . . . . . . . . 45
3.2.2 Algoritmo Horowitz-Sahni . . . . . . . . . . . . . . . . . . . . . 48
3.3 Calculo de soluciones factibles . . . . . . . . . . . . . . . . . . . . . . . 54
3.4 Calculo de cotas superiores . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.5 Algoritmo KPD-BB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4 Resultados Numericos 72
4.1 Construccion de instancias de prueba . . . . . . . . . . . . . . . . . . . 72
4.2 Evaluacion de las cotas KP-PD vs. CKP-CT . . . . . . . . . . . . . . . 73
4.3 Resultados computacionales esquema KPD-BB . . . . . . . . . . . . . . 74
4.4 Combinando SCIP y KP-PD . . . . . . . . . . . . . . . . . . . . . . . . 86
Referencias 89
Indice de figuras
4.1 Comportamiento de los algoritmos para la instancia 14, heurıstica de
ramificacion 1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
4.2 Comportamiento de los algoritmos para la instancia 14, heurıstica de
ramificacion 2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
4.3 Comportamiento de los algoritmos para la instancia 14, heurıstica de
ramificacion 3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
4.4 Comportamiento de los algoritmos para la instancia 15, heurıstica de
ramificacion 1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
4.5 Comportamiento de los algoritmos para la instancia 15, heurıstica de
ramificacion 2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
4.6 Comportamiento de los algoritmos para la instancia 15, heurıstica de
ramificacion 3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
4.7 Comportamiento de los algoritmos para la instancia 24, heurıstica de
ramificacion 1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
4.8 Comportamiento de los algoritmos para la instancia 24, heurıstica de
ramificacion 2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
4.9 Comportamiento de los algoritmos para la instancia 24, heurıstica de
ramificacion 3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
4.10 Comportamiento de los algoritmos para la instancia 25, heurıstica de
ramificacion 1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
4.11 Comportamiento de los algoritmos para la instancia 25, heurıstica de
ramificacion 2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
4.12 Comportamiento de los algoritmos para la instancia 25, heurıstica de
ramificacion 3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
4.13 Comportamiento de los algoritmos para la instancia 27, heurıstica de
ramificacion 1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
4.14 Comportamiento de los algoritmos para la instancia 27, heurıstica de
ramificacion 2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
4.15 Comportamiento de los algoritmos para la instancia 27, heurıstica de
ramificacion 3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
viii
Indice de cuadros
4.1 Instancias de prueba para KP-DUR. . . . . . . . . . . . . . . . . . . . 73
4.2 Comparacion de eficiencia y tiempos de calculo Cotas KP-PD vs. CKP-CT. 74
4.3 Comparacion de resultados y tiempos de calculo de KPD-BB vs. SCIP
en las 27 instancias de prueba. . . . . . . . . . . . . . . . . . . . . . . . 75
4.4 Comparacion de eficiencia y tiempos de calculo SCIP vs. SCIP con so-
lucion inicial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
ix
Resumen
El problema de la mochila (Knapsack Problem, KP) es un problema de optimiza-
cion combinatoria que ha sido ampliamente estudiado por mas de 100 anos (ver, por
ejemplo,[14, pp. 24–44]). Es uno de los problemas de programacion lineal entera mas
simples, aparece como subproblema en otros problemas mas complejos y tiene muchas
aplicaciones practicas, tales como encontrar patrones de corte de material que generen
el menor desperdicio posible [7]; en la seleccion de inversiones de capital y portafolios
financieros [12]; en la correcta administracion de recursos de memoria RAM de una
computadora, del ancho de banda de una conexion, del espacio en disco [16], etc.
En el problema clasico de la mochila, se tienen n objetos y una mochila de capacidad
de almacenamiento C. Cada objeto tiene un valor y peso asignados y, se pide encontrar
un subconjunto de objetos cuya suma de valores sea maxima y cuya suma de pesos no
sobrepase la capacidad C. Variantes dinamicas de este problema clasico de optimizacion
combinatoria han sido estudiadas por sus aplicaciones practicas, aunque no en gran
extension y con pocos resultados obtenidos hasta el presente. Una de estas variantes
es la de agregar una dimension temporal (discreta) al problema clasico: a cada objeto
se le asigna una duracion, que indica el intervalo de tiempo que este debe permanecer
dentro de la mochila cada vez que es seleccionado. Se considera un horizonte temporal
T y se pide maximizar el valor total almacenado en la mochila en el intervalo [0,T].
Esta variante del problema clasico tiene diversas aplicaciones practicas, tales como la
asignacion de recursos compartidos [3], seleccion de inversiones en bienes raıces, y como
se menciono antes en la seleccion de inversiones de capital y portafolios financieros [12].
Se formulo un modelo de programacion lineal entero para este problema, se desa-
rrollaron e implementaron algoritmos de solucion y se estudio su comportamiento y
desempeno computacional.
1
Abstract
The Knapsack Problem (KP) is a combinatorial optimization problem that has been
widely studied for more than a hundred years (see, for a example,[14, pp. 24–44]). It is
one of the simplest integer linear programming problems, and appears as a subproblem
in other more complex problems. It has many practical applications such as finding
material cut patterns which generate the less possible waste [7]; investment selection
of capital and financial portfolios [12]; the correct administration of a computer RAM
memory, band width of a connection, disk space [16], etc.
In the classic Knapsack Problem, we have n objects and a knapsack with storage
capacity C. Every object has a value and a weight associated to it and the objective
is to find a subset of objects which have a maximum sum value and whose weight sum
does not exceed the storage capacity C. Dynamic variants of this classic combinatorial
optimization problem have been studied for their practical applications, although not
in a wide extension and with few results reported up to the present. One of these
variants is to add a (discrete) temporal dimension to the classic problem: a duration
is assigned to each object indicating the interval of time that it has to remain inside
on the knapsack whenever it is chosen. The objective is to maximize the total value
stored in the knapsack within a certain temporal horizon T.
This variant of the classic problem has many practical applications, such as in the
assignment of shared resources [3], in real state investment selection, and, as mentioned
before, in investment selection of capital and financial portfolios [12].
In this work we formulate an integer programming model for this problem and develop
solution algorithms for it. We study their behavior and computational performance.
2
Capıtulo 1
Introduccion
1.1 El problema clasico de la mochila
Dados una mochila con capacidad C y un conjunto de n objetos, con valores p1, ...pn y
tamanos w1, ..., wn, el problema clasico de la mochila (Knapsack Problem - KP) consiste
en seleccionar un subconjunto de objetos (para almacenarlos en la mochila) cuya suma
de tamanos no supere C y cuya suma de valores sea la mayor posible. Introduciendo
para cada objeto una variable binaria xi, 1 ≤ i ≤ n, que indique si el mismo debe
ser incluido o no en la seleccion, el problema puede formularse como un programa de
optimizacion entera:
(KP)
maxn∑
i=1
pixi
s.t
n∑
i=1
wixi ≤ C,
xi ∈ {0, 1}, ∀i ∈ {1, ..., n}.
El problema de la mochila es un problema clasico en la optimizacion combinatoria.
Constituye uno de los problemas mas simples de programacion lineal entera, aparece
como subproblema en muchos otros problemas mas complejos y tiene diversas aplica-
ciones practicas. Diferentes tecnicas de solucion han sido abordadas durante las ultimas
decadas. En 1957, Dantzig [5] presento un metodo eficiente para determinar la solucion
de la relajacion continua del problema CKP, y por lo tanto, una cota superior para el
problema discreto. En 1967, Kolesar experimento con el primer algoritmo tipo branch-
and-bound para KP. Durante los anos 70’s, los metodos tipo branch-and-bound se
desarrollaron mas, gracias a lo cual fue posible resolver problemas con un gran numero
de variables. El algoritmo mas conocido de este perıodo se debe a Horowitz y Sahni
[9]. En 1977 Martello y Toth [13] propusieron la primera cota superior que mejora el
1
valor de la relajacion continua CKP. En la decada de los 80’s los resultados tienen que
ver con la solucion de problemas de gran tamano. Balas y Zemel [2] presentaron un
nuevo enfoque para resolver el problema clasificando, en muchos casos, solo un subcon-
junto pequeno de las variables. Desde esta epoca en adelante se empezaron a estudiar
variantes de este problema tales como su version acotada, no-acotada y el problema
de la mochila de eleccion multiple. Martello y Toth publicaron en 1990 una revision
exhaustiva de los diferentes resultados teoricos y metodos de solucion existentes hasta
ese momento [14]. En esta tesis hemos seguido en gran parte la notacion empleada por
estos autores, sobre todo en lo que respecta a la formulacion del pseudocodigo de los
algoritmos.
El problema de la mochila pertenece a la clase de problemas NP-difıciles [6, p. 247],
para los cuales suele asumirse que no existen algoritmos polinomiales de solucion (a
menos que P=NP). Para demostrar esto, basta notar que KP es una generalizacion del
problema SUBSET-SUM (que es uno de los problemas NP-completos estandares [11]):
dados un conjunto finito A = {a1, ..., an} de numeros enteros, y un numero B ∈ Z,
determinar si existe un subconjunto A′ ⊆ A tal que∑
ai∈A′
ai = B. En efecto, puede verse
que toda instancia de SUBSET-SUM puede transformarse en una instancia de KP con
n objetos, cuyos pesos y valores estan dados por wi = pi = ai, y donde la capacidad
de la mochila es igual a B. Por otra parte, puede considerarse a KP como uno de los
problemas “mas faciles” dentro de la clase NP-difıcil pues, como veremos mas adelante,
existen para este problema esquemas de aproximacion en tiempo polinomial (PTAS) e
incluso esquemas de aproximacion en tiempo completamente polinomial.
El KP aparece en aplicaciones practicas en procesos de toma de decisiones del mundo
real, tales como la busqueda de patrones de corte para materias primas que generen el
menor desperdicio posible [7], la seleccion de inversiones de capital y portafolios finan-
cieros [12]. De las diversas generalizaciones del problema clasico existentes, destacamos
una debido a que la emplearemos posteriormente:
Problema de la mochila acotado (Bounded Knapsack Problem, BKP): Este
problema contiene todos los elementos de la version clasica del KP, con la diferencia que
se tienen disponibles ui copias de cada objeto (ver [14, pp. 81–82]). Puede formularse
como el siguiente programa entero:
(BKP)
maxn∑
i=1
pixi
s.t
n∑
i=1
wixi ≤ C,
0 ≤ xi ≤ ui, xi ∈ N, ∀i ∈ {1, ..., n}.
2
1.2 Algoritmos de Solucion
1.2.1 Algoritmo del item crıtico
Historicamente, la primera relajacion estudiada para el problema de la mochila es la
relajacion lineal de la formulacion (KP). El Continuous Knapsack Problem (CKP) es
el problema lineal obtenido al remover la condicion de integralidad sobre xi en este
programa entero:
(CKP)
maxn∑
i=1
pixi
s.t
n∑
i=1
wixi ≤ C,
0 ≤ xi ≤ 1, ∀i ∈ {1, ..., n}.
(1.1)
Es facil encontrar una solucion optima para CKP. Supongamos que los objetos estan or-
denados decrecientemente de acuerdo a su valor por unidad de peso, lo que llamaremos
en adelante su densidad :p1w1
≥p2w2
≥ ... ≥pnwn
. (1.2)
Los objetos son introducidos consecutivamente en la mochila hasta encontrar el primer
objeto s que no cabe en el espacio restante. A este objeto lo llamamos el ıtem crıtico.
Su ındice esta dado por:
s = mın
{
j :
j∑
i=1
wi > C
}
. (1.3)
Dantzig [5] observo lo siguiente:
Teorema 1.1. Una solucion optima x de CKP esta dada por:
xj = 1 para j = 1, ..., s− 1,
xj = 0 para j = s+ 1, ..., n,
xs =c
ws
,
donde c = C −s−1∑
j=1
wj.
Demostracion. Observar que cualquier solucion optima x de CKP debe ser maximal
para la restriccion de capacidad, es decir∑n
j=1wjxj = C. Ademas, como siempre es
posible perturbar infinitesimalmente los parametros de un programa lineal sin alterar
su solucion optima asumimos, sin perdida de generalidad, quepjwj
>pj+1
wj+1para todo
j, y sea x∗ la solucion optima de CKP. Supongamos, por reduccion al absurdo, que
x∗k < 1 para algun k < s. Entonces debemos tener x∗q > 0 para al menos un ıtem
3
q ≥ s. Dado un ǫ > 0 suficientemente pequeno, podrıamos incrementar el valor de
x∗k en ǫ y disminuir el de x∗q en ǫ(wk
wq) respetando la no negatividad de la variable. De
esta manera, el valor de la funcion objetivo aumentarıa en ǫ(pk − pqwk
wq) (que es una
cantidad positiva, puesto que pkwk
> pqwq), lo que contradice la optimalidad de x∗. De la
misma forma, se puede demostrar que x∗k > 0 para k > s implica que x∗ no es optima.
Finalmente, xs =cws, para que se cumpla
∑n
j=1wjxj = C.
Del teorema anterior se sigue que el valor de la solucion optima de CKP es:
z(CKP) =s−1∑
j=1
pj + cpsws
.
Sea z(KP) el valor de la solucion optima para KP. Cuando los valores pj de los objetos
son enteros, se obtiene a partir de la integralidad de xj , la siguiente cota superior para
z(KP):
U1 = ⌊z(CKP)⌋ =s−1∑
j=1
pj +
⌊
cpsws
⌋
. (1.4)
Algoritmo para encontrar el item crıtico
La aplicacion del teorema anterior es directa, si asumimos que los objetos de una instan-
cia del CKP han sido previamente ordenados de manera decreciente por su densidad.
Para el caso general, Balas y Zemel [2] propusieron un algoritmo eficiente para deter-
minar el ıtem crıtico y z(CKP).
Para cada j ∈ N , se define rj = pj/wj. La densidad crıtica rs puede ser obtenida
determinando una particion del conjunto de objetos N en J1 ∪ JC ∪ J0 tal que,
rj > rs para j ∈ J1,
rj = rs para j ∈ JC ,
rj < rs para j ∈ J0,
y
∑
j∈J1
wj ≤ C <∑
j∈J1∪JC
wj .
Cuando esta particion ha sido encontrada, el ıtem crıtico s puede determinarse llenando
la capacidad residual C −∑
j∈J1wj con objetos de JC , en cualquier orden.
procedure CRITICAL ITEM:
input: n, C, (p), (w);
output: s;
4
begin
J1 = ∅;
J0 = ∅;
JC = {1, ..., N};
c = C;
particion = “no”;
while particion = “no” do
begin
determinar la mediana λ de los valores en R = { pjwj
: j ∈ JC};
G = {j ∈ JC :pjwj
> λ};
L = {j ∈ JC :pjwj
< λ};
E = {j ∈ JC :pjwj
= λ};
c′ =∑
j∈Gwj ;
c′′ = c′ +∑
j∈E wj ;
if c′ ≤ c < c′′ then particion := “sı”;
else if c′ > c then [λ < rs]
begin
J0 = J0 ∪ L ∪ E;
JC = G;
end
else [λ > rs]
begin
J1 = J1 ∪G ∪ E;
JC = L;
c = c− c′′;
end
end
J1 = J1 ∪G;
J0 = J0 ∪ L;
JC = E;
c = c− c′;
s = mın{j :∑
i∈Ei≤j
wi > c}
end.
Al terminar el algoritmo, una solucion optima de CKP esta dada por:
xj = 1 para j ∈ J1 ∪ {j ∈ E : j < s},
xj = 0 para j ∈ J0 ∪ {j ∈ E : j > s},
5
xs = c/ws.
1.2.2 Algoritmo Gloton
Una manera simple de aprovechar la solucion optima x de CKP para aproximar una so-
lucion factible de KP es usando el hecho de que x tiene solo una variable con valor frac-
cionario, la variable xs correspondiente al ıtem crıtico (ver Teorema 1.1). Asignandole
a esta variable el valor de 0 tenemos una solucion factible para KP, cuyo valor es:
z′ =s−1∑
j=1
pj.
Sin embargo, este metodo puede producir soluciones cuyos valores sean arbitrariamente
malos con relacion al optimo. Esto se puede observar, por ejemplo, en la familia de
problemas donde n = 2, p1 = w1 = 1, p2 = w2 = k y C = k, para los cuales z′ = 1 y
z = k, de donde se sigue que la razon z′/z tiende a 0, para k suficientemente grande.
Una mejor alternativa consiste en determinar una solucion con valor igual a:
zg = max(z′,maxi∈N
pi)
Este valor es calculado por la heurıstica de aproximacion mas popular para KP, usual-
mente conocida como algoritmo gloton (greedy algorithm). En el pseudocodigo a con-
tinuacion asumimos que los objetos estan ordenados de acuerdo a (1.2).
procedure GLOTON:
input: n, C, (p), (w);
output: zg, (x);
begin
c = C;
zg = 0;
j∗ = 1;
for j = 1 to n do
begin
if wj > c then xj = 0;
else
begin
xj = 1;
c = c− wj;
zg = zg + pj ;
end
if pj > pj∗ then j∗ = j
end;
6
if pj∗ > zg then
begin
zg = pj∗ ;
for j = 1 to n do xj = 0;
xj∗ = 1
end
end.
1.2.3 Algoritmo de Horowitz-Sahni
Existen muchos esquemas tipo branch-and-bound para la solucion de KP. De entre
estos, uno de los mas conocidos es el propuesto por Horowitz-Sahni en 1974 [9].
El arbol de busqueda representa todas las posibilidades para insertar objetos en la
mochila. Nuevamente, asumimos que los objetos estan ordenados de acuerdo a (1.2).
Un movimiento hacia adelante (forward move) consiste en insertar sucesivamente tantos
objetos consecutivos como sea posible, a partir de la solucion actual. Un movimiento
hacia atras (backtracking move) consiste en retirar de la solucion actual el ultimo objeto
insertado. Antes de realizar un movimiento hacia adelante, se emplea (1.4) para acotar
el valor de la mejor solucion que puede obtenerse a partir de la solucion actual (es decir
sin retirar objetos de la mochila). Este valor es comparado con la mejor solucion factible
obtenida hasta ese momento, para chequear si movimientos hacia adelante adicionales
pueden producir una mejor solucion. Si es ası, un nuevo movimiento hacia adelante es
realizado; caso contrario, un movimiento hacia atras sigue. Cuando el ultimo objeto es
considerado, la solucion actual esta completa y se verifica si la misma puede emplearse
para actualizar la mejor solucion, luego de lo cual se realiza un movimiento hacia atras.
El algoritmo termina cuando no son posibles mas movimientos hacia atras.
Para la descripcion del pseudocodigo del algoritmo emplearemos la siguiente notacion:
xj = solucion actual;
z =n∑
j=1
pjxj , valor de la solucion actual;
c = C −n∑
j=1
wjxj , capacidad residual actual;
xj = mejor solucion factible encontrada hasta el momento;
z =n∑
j=1
pjxj , valor de la mejor solucion factible encontrada hasta el momento.
procedure HS:
input: n, C, (p), (w);
7
output: z, (x);
begin
1. [inicializar]
z := 0;
z := 0;
c := C;
pn+1 := 0;
wn+1 := +∞;
j := 1;
2. [calcular la cota superior U1]
encontrar r = mın{i :∑i
k=j wk > c};
u :=∑r−1
k=j pk +⌊(
c−∑r−1
k=j wk
)
pr/wr
⌋
;
if z ≥ z + u then go to 5;
3. [realizar un movimiento hacia adelante]
while wj ≤ c do
begin
c := c− wj;
z := z + pj;
xj := 1;
j := j + 1;
end;
if j ≤ n then;
begin
xj := 0;
j := j + 1;
end;
if j < n then go to 2;
if j = n then go to 3;
4. [actualizar la mejor solucion hasta el momento]
if z > z then
begin
z := z;
for k = 1 to n do xk := xk
end;
j := n;
if xn = 1 then
begin
c := c+ wn;
8
z := z − pn;
xn := 0
end;
5. [movimiento hacia atras]
encontrar i = max{k < j : xk = 1};
if no existe i then return; [finaliza la busqueda]
c := c+ wi;
z := z − pi;
xi := 0;
j := i+ 1;
go to 2;
end.
1.2.4 Algoritmo de programacion dinamica
Un algoritmo de programacion dinamica es una tecnica utilizada para resolver proble-
mas de optimizacion combinatoria cuya solucion puede ser definida como una secuencia
recursiva de decisiones (tomadas una a la vez) y que cumplen con el principio del opti-
mo enunciado en 1957 por Bellman [4]: “En una secuencia optima de decisiones toda
subsecuencia ha de ser tambien optima”. Generalmente, cada subsecuencia de deci-
siones esta asociada a un subproblema del problema general, y las soluciones a estos
subproblemas son calculadas recursivamente y registradas en una tabla de soluciones.
La solucion optima para el problema original se calcula finalmente a partir de los valo-
res de esta tabla. Para el problema de la mochila, se considera el valor maximo V (i, c)
que puede almacenarse en una mochila con capacidad c, si unicamente estan disponi-
bles los i primeros objetos, con i ∈ {1, .., n}, 0 ≤ c ≤ C. Luego, el valor de la solucion
optima al problema original esta dado por V (n, C). Se designan por d1, d2, ..., dn a la
secuencia de decisiones que conducen a obtener V (n, C), donde cada di es elemento de
{0, 1}, dependiendo si el i-esimo objeto es introducido o no en la mochila. Existen dos
casos posibles:
Si dn = 1, entonces la subsecuencia d1, ..., dn−1 esta asociada al valor optimo
V (n − 1, C − wn), pues caso contrario existirıa una subsecuencia e1, ..., en−1 tal
que el valor asociado de e1, ..., en−1, dn supere V (n, C) lo que es una contradiccion.
Si dn = 0, entonces la subsecuencia d1, ..., dn−1 permite alcanzar el valor optimo
V (n− 1, C).
9
Repitiendo esta idea, se obtiene la siguiente expresion recursiva para los valores de las
soluciones optimas de los sub-problemas,
V (i, c) =
0, si i = 0 y c ≥ 0
−∞, si c < 0
max{V (i− 1, c), V (i− 1, c− wi) + pi}, en cualquier otro caso.
Para resolver el problema general, basta con determinar recursivamente el valor V (n, C),
manteniendo un registro de las decisiones tomadas. La complejidad del algoritmo viene
determinada por la construccion de la tabla con los valores V (i, c) de las soluciones
parciales, la misma que contiene nC entradas. Por lo tanto, el tiempo de ejecucion de
este algoritmo es del orden de O(nC). Observar que este algoritmo no es polinomial,
pues la longitud de codificacion de una instancia del problema de la mochila es de
O(nlog(CP )), donde P = max{p1, ..., pn}.
1.2.5 Esquemas de aproximacion
Sea π un problema de optimizacion con funcion objetivo fπ : I ×XI → R, donde I es
el conjunto de las instancias de π, y XI el conjunto de soluciones factibles para cada
instancia. Un algoritmo A es un esquema de aproximacion para π si para los datos de
entrada (I, ǫ), donde I ∈ I y ǫ > 0 es un parametro de error, el algoritmo encuentra
una solucion s tal que:
fπ(I, s) ≤ (1 + ǫ).fπ(I, S∗) si π es un problema de minimizacion,
fπ(I, s) ≥ (1− ǫ).fπ(I, S∗) si π es un problema de maximizacion,
donde S∗ ∈ XI es una solucion optima para I.
Un esquema de aproximacion A se dice de tiempo polinomial, o PTAS, si para cada
ǫ > 0, su tiempo de ejecucion esta acotado por un polinomio en la longitud de codi-
ficacion de la instancia I. Sin embargo, el tiempo de ejecucion podrıa ser exponencial
con respecto a 1/ǫ, en cuyo caso acercarse a la solucion optima puede ser computacio-
nalmente muy costoso. Por otra parte, un esquema de aproximacion se denomina de
tiempo completamente polinomial, o FPTAS, si su tiempo de ejecucion esta acotado
por un polinomio en la longitud de codificacion de la instancia I y en 1/ǫ.
Esquema de aproximacion de tiempo polinomial para KP
Una aproximacion inteligente para resolver el problema de la mochila consiste en enu-
merar, para un entero k fijo, todos los subconjuntos de objetos que contengan maxi-
mo k elementos, y considerar las soluciones que puenden obtenerse a partir de estos,
10
empleando un algoritmo gloton para asignar la capacidad residual de la mochila. El
pseudocodigo de este algoritmo se describe a continuacion. Asumimos que los objetos
estan ordenados de acuerdo a (1.2).
procedure KP-PTAS:
input: n, C, (p), (w), k;
output: xmax;
begin
zmax = −∞;
xmax = 0;
for S ⊆ {1, ..., n}, |S| ≤ k do
for i ∈ S do xi = 1;
c = C −∑
i∈S wi;
if c ≥ 0 then
for i = 1 to n do
if i /∈ S then
if wi ≤ c then
xi = 1;
c := c− wi;
else
xi = 0;
end
end
end
z :=n∑
i=1
pixi;
if z > zmax then
zmax := z;
xmax := x;
end
end
end
end.
Cada iteracion del lazo principal puede implementarse empleando O(n) operaciones.
Por otra parte, el numero de iteraciones del lazo principal es igual al numero de sub-
conjuntos de objetos con cardinalidad menor o igual a k. Este valor esta acotado por
k.nk, lo que permite concluir que el algoritmo tiene un tiempo de ejecucion del orden de
O(knk+1). Es posible demostrar que, para cualquier instancia de KP con valor optimo
11
zopt, el valor de zmax de la solucion encontrada por KP-PTAS satisface [8, pp. 9]:
zmax ≥k
k + 1zopt =
(
1−1
k + 1
)
zopt.
Es decir, KP-PTAS es un esquema de aproximacion para KP, con ǫ = 1k+1
. De las obser-
vaciones anteriores, se tiene ademas que se trata de un esquema de tiempo polinomial,
aunque no completamente polinomial, pues el tiempo de ejecucion crece exponencial-
mente en funcion de 1/ǫ = k + 1.
Esquema de aproximacion de tiempo completamente polinomial para KP
Considerar el siguiente algoritmo de programacion dinamica para el problema de la
mochila. Sea P el valor del objeto con mayor valor, i.e. P = maxi∈1,...,n
pi. Notar que, podemos
acotar por arriba el valor optimo de una instancia de KP por nP . Para i ∈ {1, ..., n} y
p ∈ {1, ..., nP}, sea S(i, p) un subconjunto de los objetos {1, ..., i} que tiene un valor
total∑
j∈S(i,p)
pj exactamente igual a p y que ocupa la menor cantidad posible de espacio
en la mochila. Si tal conjunto no existe, definimos S(i, p) = ∅. Sea A(i, p) el tamano
total∑
j∈S(i,p)
wj del conjunto S(i, p), con A(i, p) = ∞ para denotar que S(i, p) no existe.
Tenemos que A(1, p1) = w1 y A(1, p) = ∞, si p 6= p1. Se puede usar la siguiente
expresion recursiva para calcular los valores restantes de A(i, p):
A(i+ 1, p) =
mın{A(i, p), A(i, p− pi+1) + wi+1}, si pi+1 ≤ p
A(i, p), caso contrario.
La solucion optima a KP esta dada por el conjunto S(n, p) donde p se define mediante
p = max{p : A(n, p) ≤ C}.
Puesto que este algoritmo requiere O(n) operaciones para construir cada conjunto
S(i, p), tenemos un tiempo de ejecucion total de O(n2P ). Nuevamente, observar que el
algoritmo no es polinomial, debido a que la longitud de codificacion de una instancia
de KP es de O(nlog(CP )).
Por otra parte, podemos ver que si los valores pi de los objetos fueran todos pequenos,
i.e. acotados polinomialmente en n, entonces el algoritmo alcanzarıa un tiempo de
ejecucion polinomial. Esto motiva la siguiente idea: se pueden escalar los valores de
los objetos para que estos queden acotados polinomialmente por n, entonces se usa
el algoritmo de programacion dinamica sobre esta nueva instancia, y se calcula el
conjunto optimo. Empleando un factor de escala ǫ adecuado, podremos obtener una
12
solucion cuyo valor sea al menos (1− ǫ)zopt en tiempo polinomial con respecto a n y a
1/ǫ, lo que da como resultado un FPTAS.
El algoritmo es el siguiente:
1. Dado ǫ > 0, sea K =ǫP
n.
2. Para cada objeto i, definimos p′i =⌊ piK
⌋
.
3. Con estos nuevos valores p′i, usando el algoritmo de programacion dinamica, en-
contrar el subconjunto de mayor valor S ′.
Se puede demostrar que el conjunto obtenido mediante este algoritmo satisface∑
i∈S′
pi ≥
(1 − ǫ)zopt. Ademas el tiempo de ejecucion del algoritmo es de O(n2⌊
PK
⌋
) que por
construccion es igual a O(n2⌊
nǫ
⌋
), polinomial en n y 1/ǫ.
1.3 Versiones dinamicas
Algunas variantes dinamicas del problema de la mochila han sido estudiadas por sus
aplicaciones practicas, aunque no en gran extension y con pocos resultados obtenidos
hasta el presente. Papastavrou [15] estudia una variante donde los objetos arriban
de acuerdo a un proceso estocastico en el tiempo, y sus valores y tamanos siguen
una determinada distribucion de probabilidad. Al arribar cada objeto, debe decidirse
inmediatamente si el mismo debe ser incluido en la mochila o no (en caso de que
la capacidad libre ası lo permita). Otras variantes consisten en asociar una duracion
di dentro de la mochila a cada uno de los objetos. El objetivo en todos los casos es
maximizar el valor total almacenado dentro de un horizonte de tiempo.
1.3.1 Problema de la mochila con duracion (KP-DUR)
Al igual que en el KP clasico se tienen dados una mochila con capacidad C, un conjunto
de n objetos con valores p1, ..., pn y tamanos w1, ..., wn. Pero ademas, consideramos que
los n objetos tienen asociadas duraciones d1, ..., dn. Esto significa que si el objeto i
es agregado a la mochila en el perıodo t, el mismo permanecera dentro de la misma
hasta el perıodo t + di − 1. El objetivo de este problema es maximizar el valor total
almacenado en la mochila dentro de un horizonte de tiempo T. Estudiaremos esta
variante del problema con mas detalle en el Capıtulo 2.
1.3.2 Problema de la mochila dinamico y estocastico (DSKP)
Papastavrou [15] estudia una version dinamica del KP, en la cual los objetos arriban
de acuerdo a un proceso de Poisson en el tiempo. Cada objeto tiene una demanda
13
(tamano) de un recurso limitado (expresado por la capacidad de la mochila) y un
valor asociado. Estas demandas y valores asociados estan conjuntamente distribuidos
de acuerdo a una distribucion de probabilidad dada y son conocidos al momento en
el que los objetos arriban. Cuando un objeto arriba, debe decidirse si el mismo es
“aceptado”(es decir, colocado en la mochila) o “rechazado”. Si un objeto es aceptado
se recibe el valor asociado a este, y si un objeto es rechazado entonces un valor es
devengado por penalizacion. Dentro de este contexto; dados un horizonte de tiempo y
costos sobre los tiempos de espera, el objetivo es determinar una tactica optima que
maximice el valor acumulado esperado (valores recibidos menos costos). Este problema
tiene algunas aplicaciones en el ambito de la optimizacion combinatoria, por ejemplo,
en ciertas tareas de planificacion dentro de la industria de la transportacion [15], en las
cuales los objetos a ser transportados tienen algun valor por su entrega, y tienen que ser
enviados a clientes que hacen sus pedidos estocasticamente en el tiempo. Si un objeto
es aceptado, se percibe una cierta utilidad por el mismo; si un objeto es descartado,
se puede incurrir en costos de penalizacion por incumplimiento con los clientes. Otra
aplicacion puede darse en el ambito de los bienes raıces, donde un agente vendiendo
nuevos condominios recibe ofertas estocasticamente en el tiempo y quiere garantizar
sus ganancias en un horizonte de tiempo, considerando un valor residual por los bienes
no vendidos. Tambien existen costos de oportunidad asociados con el capital invertido
en los activos no vendidos, y los impuestos de propiedad los que pueden generar costos
por unidad de tiempo de espera [15].
1.3.3 Problema temporal de la mochila (TKP)
El problema temporal de la mochila TKP es definido de la siguiente manera: un admi-
nistrador debe decidir acerca del uso de un recurso compartido, bien sea en el tiempo
(tiempo de CPU, ancho de banda), o en el espacio (espacio en disco, memoria de la
computadora o habitaciones equivalentes en un hotel que maneja bloques de reserva).
El administrador recibe ofertas por el uso del recurso, cada una de las cuales especifica
la cantidad del recurso necesitado, un intervalo de tiempo en el que el recurso se necesi-
ta, y un valor ofrecido por el recurso. El asignador de recursos, en general, tendra mas
demanda que capacidad, ası que tiene el problema de escoger un subconjunto de las
ofertas que maximice la utilidad total obtenida. En este caso, la capacidad de la mochi-
la representa la cantidad disponible del recurso compartido, y cada una de las ofertas
corresponde a un objeto. El valor del objeto es el valor de la oferta y su tamano indi-
ca la cantidad solicitada del recurso. A diferencia de KP-DUR, los objetos no tienen
asociadas duraciones, sino tiempos especıficos para el ingreso y salida de la mochila,
en caso de ser seleccionados. La definicion formal del problema, algunos algoritmos de
solucion y resultados computacionales estan descritos en [3].
14
Capıtulo 2
El Problema KP-DUR
En este capıtulo se formula un modelo de programacion lineal entera para KP-DUR.
Se estudian heurısticas de solucion y cotas superiores, y las mismas son combinadas en
un algoritmo tipo branch-and-bound.
2.1 Modelo de programacion entera
Tal como se definio en la Subseccion 1.3.1 del Capıtulo 1, en esta variante del problema
de la mochila se tienen dados una mochila con capacidad C y un conjunto de n objetos
que pueden ser insertados mas de una vez en la mochila. Los objetos tienen asociados
valores p1, ..., pn, tamanosw1, ..., wn y duraciones d1, ..., dn. Esto significa que si el objeto
i es agregado a la mochila en el instante t, el mismo permanecera dentro de la misma
hasta el instante t + di − 1. El objetivo de este problema es maximizar el valor total
almacenado en la mochila dentro de un horizonte de tiempo T , el mismo que hemos
discretizado en perıodos {1, 2, ..., T}. Asumimos que todos los parametros C, T, pi, wi
y di son enteros.
Definimos variables binarias xit, i ∈ {1, ..., n}, t ∈ {1, ..., T}, que nos indican si el
objeto i ingresa en la mochila en el perıodo t; y variables binarias zit, i ∈ {1, ..., n}, t ∈
{1, ..., T}, que nos indican si el objeto i se encuentra presente en la mochila en el
perıodo t. De esta manera, el problema puede formularse como el siguiente programa
15
de optimizacion entera:
(KP-DUR*)
max
n∑
i=1
T∑
t=1
pixit
s.tn∑
i=1
wizit ≤ C, ∀t ∈ {1, ..., T},
xit = 0, ∀i ∈ {1, ..., n}, ∀t ∈ {T − di + 2, ..., T},
xit = 1⇒ zi,t+l = 1, ∀i ∈ {1, ..., n}, ∀l ∈ {0, ..., di − 1},
xit = 1⇒ xi,t+l = 0, ∀i ∈ {1, ..., n}, ∀l ∈ {1, ..., di − 1},
zit ≤
mın{di−1,t−1}∑
l=0
xi,t−l, ∀i ∈ {1, ..., n}, ∀t ∈ {1, ..., T},
xit, zit ∈ {0, 1}, ∀i ∈ {1, ..., n}, ∀t ∈ {1, ..., T}.
(2.1)
(2.2)
(2.3)
(2.4)
(2.5)
(2.6)
La funcion objetivo (2.1) mide el valor total de los objetos ingresados en la mochila
dentro del horizonte de tiempo {1, ..., T}. La restriccion (2.2) sirve para asegurar que
en cada perıodo la capacidad de la mochila sea respetada. La restriccion (2.4) establece
que si el objeto i ingresa a la mochila, entonces este objeto permanece en la misma
durante di unidades de tiempo. La restriccion (2.5) asegura que ningun objeto pueda
volver a entrar hasta que no haya salido de la mochila. La restriccion (2.3) impide que
un objeto ingrese en la mochila demasiado tarde, es decir, si su tiempo de permanencia
previsto excede el horizonte de tiempo T . Finalmente, la restriccion (2.6) expresa que
un objeto no puede estar en la mochila en un perıodo t sin haber ingresado a esta en
ninguno de los perıodos anteriores {t, t− 1, ..., t− di + 1}.
Esta formulacion del problema es simple y directa, pero no es adecuada para el desarro-
llo de algoritmos de solucion. Entre otras dificultades, no todas las familias de restric-
ciones son lineales, pues en el caso de (2.4) y (2.5) se trata de implicaciones logicas. Por
este motivo, hemos considerado una formulacion alternativa, la misma que se describe
a continuacion.
Nuevamente, definimos variables binarias xit, i ∈ {1, ..., n}, t ∈ {1, ..., T}, que nos in-
dican si el objeto i ingresa en la mochila en el perıodo t y variables binarias zit, i ∈
{1, ..., n}, t ∈ {1, ..., T}, que nos indican si el objeto i esta en la mochila en el perıodo
t. Ademas, introducimos variables binarias yit, i ∈ {1, ..., n}, t ∈ {1, ..., T}, que nos
16
indican si el objeto i sale de la mochila en el perıodo t.
(KP-DUR)
max
n∑
i=1
T∑
t=1
pixit
s.tn∑
i=1
wizit ≤ C, ∀t ∈ {1, ..., T},
yi,t+di = xit, ∀i ∈ {1, ..., n}, ∀t ∈ {1, ..., T − di},
xit = 0, ∀i ∈ {1, ..., n}, ∀t ∈ {T − di + 2, ..., T},
yit = 0, ∀i ∈ {1, ..., n}, ∀t ∈ {1, ..., di},
zi1 = xi1, ∀i ∈ {1, ..., n},
zit = zi,t−1 + xit − yit, ∀i ∈ {1, ..., n}, ∀t ∈ {2, ..., T},
xit, yit, zit ∈ {0, 1}, ∀i ∈ {1, ..., n}, ∀t ∈ {1, ..., T}.
(2.7)
(2.8)
(2.9)
(2.10)
(2.11)
(2.12)
(2.13)
La funcion objetivo (2.7) mide el valor total de los objetos ingresados en la mochila
dentro del horizonte de tiempo {1, ..., T}. La restriccion (2.8) sirve para asegurar que
en cada perıodo la capacidad de la mochila sea respetada, la restriccion (2.9) establece
que si el objeto i ingresa a la mochila, entonces este objeto debe salir de la misma
luego de di unidades de tiempo. Las restricciones (2.12) y (2.13) especifican la relacion
entre las variables zit, xit, yit y (2.13) puede verse como una restriccion de balance: si
el objeto i entra en la mochila en el perıodo t entonces el valor de zit aumenta (con
relacion al valor de zi,t−1). Si el objeto sale de la mochila, el valor de zit disminuye.
En todos los demas casos, el valor de zit permanece inalterado. La restriccion (2.10)
impide que un objeto ingrese en la mochila si su duracion prevista excede el horizonte
de tiempo T . De manera recıproca, la restriccion (2.11) impide que un objeto salga de
la mochila en los di perıodos iniciales ya que esto es imposible.
Vamos a demostrar que las formulaciones KP-DUR y KP-DUR* son equivalentes entre
sı. En adelante notaremos como FIP al conjunto de todas las soluciones factibles de un
problema de optimizacion IP. Para los dos problemas anteriores, tenemos los conjuntos
FKP-DUR∗ y FKP-DUR, cuyas propiedades estudiaremos a continuacion.
Se establecen primero los siguientes resultados auxiliares para KP-DUR:
Lema 2.1. Sea (x, y, z) ∈ FKP-DUR.
∀i ∈ {1, ..., n}, t ∈ {1, ..., T − di + 1} si xit = 1⇒ zi,t+l = 1, ∀l ∈ {0, ..., di − 1}.
∀i ∈ {1, ..., n}, t ∈ {1, ..., T − di + 1} si xit = 1⇒ xi,t+l = 0, ∀l ∈ {1, ..., di − 1}.
Demostracion. Sea i ∈ {1, ..., n}, y sea t el primer perıodo en el que el objeto i ingresa
en la mochila.
17
Entonces
xit = 0, ∀t < t, (2.14)
yit = 0, ∀t < t + di, por (2.9) y por (2.11). (2.15)
Luego, de (2.12) y (2.13) se sigue:
zit = 0, ∀t < t.
Por otra parte,
zit = zi,t−1 + xit − yit,
= 0 + 1− 0,
= 1.
(2.16)
Sea l ∈ {1, ..., di − 1}. Como zi,t+l y xi,t+l ∈ {0, 1}, tenemos por (2.13) que
zi,t+l = zi,t+l−1 + xi,t+l − yi,t+l ≤ 1,
zi,t+l = zi,t+l−1 + xi,t+l − 0 ≤ 1, por (2.15). (2.17)
En particular, para l = 1, obtenemos:
zi,t+1 = zi,t + xi,t+1 ≤ 1,
zi,t+1 = 1 + xi,t+1 ≤ 1, por (2.16),
⇒ zi,t+1 = 1 y xi,t+1 = 0.
Aplicando recursivamente (2.17) y el razonamiento anterior, obtenemos zi,t+l = 1 y
xi,t+l = 0, para 1 ≤ l ≤ di − 1, de donde, junto con (2.16), se concluyen la primera
y segunda proposiciones. Para los posteriores ingresos del objeto i en la mochila, em-
plearemos una demostracion por induccion. Sea t1 un perıodo tal que xit1 = 1 y sea t0
el perıodo en el cual i entro por ultima vez en la mochila (antes de t1): Por hipotesis
de induccion:
zi,t0+l = 1, ∀l ∈ {0, ..., di − 1}, (2.18)
xi,t0+l = 0, ∀l ∈ {1, ..., di − 1}. (2.19)
Se sigue entonces que t1 > t0+di−1⇔ t1 ≥ t0+di, ya que t0 y t1 son numeros enteros.
Se consideran dos casos posibles:
Caso I: t1 = t0 + di
18
Por (2.13) se tiene:
zi,t1 = zi,t0+di = zi,t0+di−1 + xi,t0+di − yi,t0+di ,
= zi,t0+di−1 + xit1 − yi,t0+di,
= zi,t0+di−1 + xit1 − xit0 , por (2.9),
= zi,t0+di−1 + 1− 1,
= zi,t0+di−1,
= 1. por (2.18).
(2.20)
Por otra parte, de (2.9) y la hipotesis de induccion tenemos que:
yi,t1+l = yi,t0+di+l = xi,t0+l = 0, ∀l ∈ {1, ..., di − 1}. (2.21)
Sea l ∈ {1, ..., di − 1}. Al igual que para el caso de t, como zi,t1+l, xi,t1+l ∈ {0, 1}, se
sigue de (2.13):
zi,t1+l = zi,t1+l−1 + xi,t1+l − yi,t1+l ≤ 1,
zi,t1+l = zi,t1+l−1 + xi,t1+l − 0 ≤ 1, por (2.21). (2.22)
Para l = 1, concluimos:
zi,t1+1 = zit1 + xi,t1+1 ≤ 1,
zi,t1+1 = 1 + xi,t1+1 ≤ 1, por (2.20),
⇒ zi,t1+1 = 1 y xi,t1+1 = 0.
Nuevamente, aplicando recursivamente (2.22) y este argumento, obtenemos zi,t1+l = 1 y
xi,t1+l = 0, para 1 ≤ l ≤ di−1, lo que demuestra, junto con (2.20), las dos proposiciones.
Caso II: t1 > t0 + di
En este caso, notar que
xit = 0, ∀t0 < t < t1, (2.23)
yit = 0, ∀t0 + di < t < t1 + di, por (2.9). (2.24)
19
Luego, por (2.13) se tiene:
zi,t0+di = zi,t0+di−1 + xi,t0+di − yi,t0+di,
= zi,t0+di−1 + xi,t0+di − xit0 , por (2.9)
= zi,t0+di−1 + 0− 1, por (2.23)
= 1− 1, por (2.18),
= 0.
Ademas, como zit ≤ zi,t−1 + xit, de (2.23) se sigue
zit = 0, ∀t0 + di ≤ t < t1. (2.25)
Por otra parte de (2.13) tenemos que:
zit1 = zi,t1−1 + xit1 − yit1 ,
= zi,t1−1 + 1− yit1,
= zi,t1−1 + 1− 0, por (2.24),
= 0 + 1, por (2.25),
= 1.
(2.26)
Sea l ∈ {1, ..., di − 1}. Al igual que para el caso de t, de zi,t1+l y xi,t1+l ∈ {0, 1} y
aplicando recursivamente (2.13) junto con (2.26) y (2.24) se sigue que se cumplen las
dos proposiciones del enunciado.
Lema 2.2. Sea (x, y, z) ∈ FKP-DUR. Entonces,
zi,t ≤
mın{di−1,t−1}∑
l=0
xi,t−l, ∀i ∈ {1, ..., n}, ∀t ∈ {1, ..., T}.
Demostracion. Por reduccion al absurdo, supongamos que existen i ∈ {1, ..., n}, t ∈
{1, ..., T} tales que:
zit >
mın{di−1,t−1}∑
l=0
xi,t−l.
Asumamos primero que t > di, es decir, zit >di−1∑
l=0
xi,t−l. Como zit y xi,t−l ∈ {0, 1} se
sigue que:
zit = 1 y xi,t−l = 0, ∀l ∈ {0, ..., di − 1}. (2.27)
20
De (2.13) obtenemos ahora:
zit = zi,t−1 + xit − yit, ∀t ∈ {2, ..., t}
⇒t∑
t=2
(zit − zi,t−1) =
t∑
t=2
(xit − yit)
zit − zi1 =
t∑
t=2
xit −t∑
t=2
yit
=
t∑
t=2
xit −di∑
t=2
yit −t∑
t=di+1
yit
=t∑
t=2
xit −t∑
t=di+1
yit, por (2.11)
=t∑
t=2
xit −t−di∑
t=1
xit, por (2.9)
=
t∑
t=t−di+1
xit − xi1,
= −xi1, por (2.27).
Pero de aquı se sigue que zi1 = 1 y xi1 = 0, lo que contradice (2.12).
Por otra parte, si t ≤ di tenemos
zit >t−1∑
t=1
xit,
de donde zit = 1 y xit = 0, ∀t ∈ {1, ..., t}. Al igual que en el caso anterior, sumando
(2.13) para t ∈ {2, ..., t}, obtenemos
t∑
t=2
(zit − zi,t−1) =t∑
t=2
(xit − yit)
zit − zi1 =t∑
t=2
xit −t∑
t=2
yit
= −t∑
t=2
yit
= 0, por (2.11).
Pero entonces, llegamos nuevamente a la contradiccion zi1 = 1 y xi1 = 0.
21
De los dos lemas anteriores podemos concluir el siguiente corolario.
Corolario 2.3. Si (x, y, z) ∈ FKP-DUR, entonces (x, z) ∈ FKP-DUR∗. Ademas, notar que
ambas soluciones alcanzan el mismo valor en la funcion objetivo.
Lema 2.4. Sea (x, z) ∈ FKP-DUR∗. Entonces se cumple que
zit =
mın{di−1,t−1}∑
l=0
xi,t−l, ∀i ∈ {1, ..., n}, ∀t ∈ {1, ..., T}.
Demostracion. Asumimos, sin perdida de generalidad, que t > di. La demostracion
para el caso t ≤ di emplea el mismo argumento.
Por (2.5) sabemos que: 0 ≤di−1∑
l=0
xi,t−l ≤ 1,
Ademas de (2.4) tenemos,
xit = 1⇒ zit = 1,
xi,t−1 = 1⇒ zit = 1,
xi,t−2 = 1⇒ zit = 1,
...
xi,t−di+1 = 1⇒ zit = 1,
Por lo tanto,di−1∑
l=0
xi,t−l = 1⇒ zit = 1.
Pero comodi−1∑
l=0
xi,t−l ∈ {0, 1}, se sigue de lo anterior que,
di−1∑
l=0
xi,t−l ≤ zit,
Conjuntamente con (2.6), obtenemos,
zit =
di−1∑
l=0
xi,t−l.
Lema 2.5. Sea (x, z) ∈ FKP-DUR∗. Entonces existe y ∈ {0, 1}n×T tal que (x, y, z) ∈
FKP-DUR. Notar ademas que los valores de las funciones objetivo para ambas soluciones
coinciden.
22
Demostracion. Para todo i ∈ {1, ..., n} definimos,
yit =
0, si t = 1,
zi,t−1 + xit − zit, si t ∈ {2, ..., T}.
Notar que esta definicion satisface (2.13). Por otra parte, (2.12) se sigue de (2.4) y
(2.6). Resta por demostrar que (2.9) y (2.11) tambien se verifican.
Supongamos primero que 2 ≤ t ≤ di, tenemos entonces,
yit = zi,t−1 + xit − zit,
=
t−2∑
l=0
xi,t−l−1 + xit −t−1∑
l=0
xi,t−l,
=
t−1∑
t=1
xit + xit −t∑
t=1
xit,
= xit − xit,
= 0,
lo que demuestra (2.11).
Por otra parte, si t > di tenemos
yit = zi,t−1 + xit − zit,
=
di−1∑
l=0
xi,t−l−1 + xit −di−1∑
l=0
xi,t−l,
=
di∑
l=1
xi,t−l + xit −di−1∑
l=0
xi,t−l,
= xi,t−di + xit − xit,
= xi,t−di ,
y se concluye (2.9).
En el Corolario 2.3 y el Lema 2.5 hemos demostrado que KP-DUR y KP-DUR* son dos
formulaciones equivalentes del mismo problema. Se tiene ademas el siguiente resultado
para KP-DUR*, que emplearemos posteriormente.
Lema 2.6. Sea (x, z) ∈ FKP-DUR∗. Entonces,
T∑
t=1
zit = di
T∑
t=1
xit, ∀i ∈ {1, ..., n}.
23
Demostracion. Sea (x, z) ∈ FKP-DUR∗ . Sean t1, t2, ...., tk los tiempos en los cuales xit =
1. Notar queT∑
t=1
xit = k. (2.28)
Por otra parte, de (2.5) se sigue que
tj+1 ≥ tj + di, ∀j ∈ {1, ..., k − 1},
y de (2.3) tenemos tambien que
tk ≤ T − di + 1.
Ademas, para j ∈ {1, ..., k}, l ∈ {0, ..., di − 1}, se tiene de (2.4) que zi,tj+l = 1 y por
tantodi−1∑
l=0
zi,tj+l =
di−1∑
l=0
1 = di. (2.29)
Por ultimo, supongamos que para algun j ∈ {1, ..., k − 1} se tiene
tj+1 > tj + di.
En este caso, como
xi,tj+1 = xi,tj+2 = ... = xi,tj+di = ... = xi,tj+1−1 = 0,
se sigue de (2.6) que
zi,tj+di = ... = zi,tj+1−1 = 0.
Con esto, concluimos que
T∑
t=1
zit =
k∑
j=1
(
di−1∑
l=0
zi,tj+l
)
,
=
k∑
j=1
di, por (2.29),
= kdi,
= di
T∑
t=1
xit, por (2.28).
Del Lema 2.5 se sigue ademas que:
24
Corolario 2.7. Sea (x, y, z) ∈ FKP-DUR. Entonces,
T∑
t=1
zit = di
T∑
t=1
xit, ∀i ∈ {1, ..., n}.
2.2 Cotas Superiores
En esta seccion presentaremos dos relajaciones posibles del problema KP-DUR, al
que tambien denotaremos en adelante simplemente como “knapsack dinamico”. Como
veremos, estas relajaciones reducen el problema a un problema clasico del Knapsack
(KP). Haremos uso de esta propiedad para obtener cotas superiores para KP-DUR a
partir de la modificacion de algoritmos de solucion para KP.
2.2.1 El problema KP-CT
(KP-CT)
max
n∑
i=1
piyi
s.tn∑
i=1
(widi)yi ≤ CT,
0 ≤ yi ≤
⌊
T
di
⌋
, yi ∈ N, ∀i ∈ {1, ..., n}.
(2.30)
(2.31)
(2.32)
Este problema tiene la forma de una de las generalizaciones del problema clasico de la
mochila, especıficamente de la version acotada BKP (ver Seccion 1.1).
La capacidad de la mochila es igual a CT , el tamano de objeto i es widi y la cantidad
disponible del mismo es⌊
Tdi
⌋
. Demostremos que KP-CT es una relajacion de KP-DUR.
Lema 2.8. Dada una solucion factible (x, y, z) ∈ FKP-DUR, es posible definir una so-
lucion y ∈ FKP−CT tal que los valores objetivos de ambas soluciones coincidan.
Demostracion. Sea (x, y, z) ∈ FKP-DUR, de (2.8) se tiene:
n∑
i=1
wizit ≤ C, ∀t ∈ {1, ..., T},
Definimos yi =
T∑
t=1
xit, Notar que yi ∈ N ya que xit ∈ {0, 1}. (2.33)
Ademas,
T∑
t=1
n∑
i=1
wizit ≤T∑
t=1
C,
25
⇔n∑
i=1
T∑
t=1
wizit ≤ CT,
⇔n∑
i=1
wi
T∑
t=1
zit ≤ CT.
Por otra parte, del Corolario 2.7 tenemos que
T∑
t=1
zit = di
T∑
t=1
xit,
y sustituyendo esto en la expresion anterior,
n∑
i=1
(widi)T∑
t=1
xit ≤ CT,
n∑
i=1
(widi)yi ≤ CT, por (2.33).
Por ultimo, observar que
diyi =T∑
t=1
zit ≤ T ⇔ yi ≤T
di⇔ yi ≤
⌊
T
di
⌋
.
Resta por demostrar que los valores de ambas soluciones en las funciones objetivos de
sus respectivos programas coinciden:
n∑
i=1
T∑
t=1
pixit =
n∑
i=1
pi
T∑
t=1
xit =
n∑
i=1
piyi, por (2.33).
Del teorema anterior concluimos que el valor de toda solucion optima de KP-CT es
cota superior para KP-DUR.
26
2.2.2 El problema KP-PD
El siguiente problema tiene la forma de la version clasica del problema de la mochila
(KP):
(KP-PD)
max
n∑
i=1
pidixi
s.t
n∑
i=1
wixi ≤ C,
xi ∈ {0, 1}, ∀i ∈ {1, ..., n}.
(2.34)
(2.35)
(2.36)
En el siguiente lema se demuestra que KP-PD puede usarse para obtener una cota
superior para KP-DUR.
Lema 2.9. Sea (x, y, z) ∈ FKP-DUR, y sean x1, ..., xT ∈ {0, 1}n definidos por xti = zit,
para todo t ∈ {1, ..., T}, i ∈ {1, ..., n}. Entonces xt ∈ FKP−PD, ∀t ∈ {1, ..., T}.
Demostracion. Basta ver que para t ∈ {1, ..., T} se cumple por (2.8) que
n∑
i=1
wixti =
n∑
i=1
wizit ≤ C, ∀t ∈ {1, ..., T}.
En otras palabras, para cada perıodo t ∈ {1, ..., T}, la solucion de KP-DUR restringida
a t es una solucion factible para KP-PD.
Sean (x, y, z) ∈ FKP-DUR una solucion optima para una instancia de KP-DUR y x∗ ∈
FKP−PD una solucion optima para la instancia correspondiente de KP-PD. Tenemos
entonces que para el valor objetivo de estas soluciones se cumple,
n∑
i=1
T∑
t=1
pixit =n∑
i=1
pi
T∑
t=1
xit,
=n∑
i=1
pi
T∑
t=1
zit
di
, por el Corolario 2.7
=
n∑
i=1
pidi
T∑
t=1
zit,
=
n∑
i=1
pidi
T∑
t=1
xti,
≤T∑
t=1
n∑
i=1
pidix∗i = T
n∑
i=1
pidix∗i ,
27
donde xt son las soluciones factibles para KP-PD definidas en el Lema 2.9.
Por lo tanto, hemos demostrado el siguiente resultado:
Lema 2.10. Una solucion optima x∗ de una instancia de KP-PD permite definir la
siguiente cota superior para la instancia asociada de KP-DUR:
U4 :=
⌊
Tn∑
i=1
pidix∗i
⌋
. (2.37)
2.2.3 Algoritmo Critical Item Dinamico
Tal como fue descrito en la Seccion 1.2.1, una cota superior para el problema clasico
puede obtenerse a partir de la solucion de su relajacion lineal, aplicando el Teorema
1.1. Generalizando la idea de la ecuacion (1.2), podemos ordenar los n objetos no solo
de acuerdo al valor de ganancia por unidad de peso sino segun el valor de ganancia por
unidad combinada de peso-duracion. De manera mas precisa, tenemos:
p1w1d1
≥p2
w2d2≥ ... ≥
pnwndn
. (2.38)
Y podrıamos utilizar una estrategia similar para encontrar una cota superior de KP-CT
al resolver su relajacion lineal, CKP-CT:
(CKP-CT)
max
n∑
i=1
piyi
s.t
n∑
i=1
(widi)yi ≤ CT,
0 ≤ yi ≤
⌊
T
di
⌋
, ∀i ∈ {1, ..., n}.
(2.39)
(2.40)
(2.41)
Considerar ahora la definicion del ıtem crıtico (1.3) en el problema clasico:
s = mın
{
j :
j∑
i=1
wi > C
}
.
Para el caso del CKP-CT, tenemos que tomar en cuenta que la variable yi puede al-
canzar un valor maximo de⌊
Tdi
⌋
, y ocupar por tanto⌊
Tdi
⌋
(widi) unidades de capacidad
de la mochila. Esto motiva la definicion:
s = mın
{
j :
j∑
i=1
⌊
T
di
⌋
(widi) > CT
}
.
28
De la observacion anterior, asumiendo que los objetos estan ordenados de acuerdo a
(2.38), puede caracterizarse la solucion optima de CKP-CT.
Teorema 2.11. La solucion optima y de CKP-CT esta dada por:
yj =
⌊
T
dj
⌋
para j = 1, ..., s− 1,
yj = 0 para j = s+ 1, ..., n,
ys =C
wsds,
donde C = CT −s−1∑
j=1
yj(wjdj).
Demostracion. De manera similar que para la demostracion del Teorema 1.1 de CKP
se tiene que cualquier solucion optima y∗ para CKP-CT tiene que ser maximal en el
sentido de su restriccion de capacidad, es decirn∑
j=1
y∗j (wjdj) = CT . Sin perdida de
generalidad, asumimos que:
pjwjdj
>pj+1
wj+1dj+1, ∀j ∈ {1, ..., n− 1}.
Supongamos, por reduccion al absurdo, que existe y∗k <⌊
Tdj
⌋
para algun k < s. Entonces
tendrıamos que y∗q > yq = 0 para al menos un objeto q ≥ s. Dado ǫ > 0 suficientemente
pequeno podemos incrementar el valor de y∗k en ǫ y disminuir el valor de y∗q en ǫwkdkwqdq
,
y obtenemos ası una nueva solucion factible cuya variacion en el valor de la funcion
objetivo es igual a ǫ
(
pk − pqwkdkwqdq
)
. Comopk
wkdk>
pqwqdq
, entoncespk
wkdk−
pqwqdq
> 0
y pk −pqwkdkwqdq
> 0, lo que contradice la optimalidad de y∗. De la misma forma, puede
demostrarse que y∗k = 0 para k > s. Por ultimo, ys =C
wsdsse sigue de
n∑
j=1
y∗j (wjdj) =
CT .
Como CKP-CT es la relajacion lineal de KP-CT, de lo expuesto en la Seccion 2.2.1
se concluye que toda solucion optima de CKP-CT es cota superior para KP-DUR. En
particular, del Teorema 2.11 obtenemos la cota superior Critical Item,
U3 = ⌊z(CKP-CT)⌋ =
⌊
s−1∑
j=1
⌊
T
dj
⌋
pj +C
wsdsps
⌋
,
donde C = CT −s−1∑
j=1
⌊
Tdj
⌋
(wjdj).
29
Es posible encontrar el ıtem crıtico de una instancia de CKP-CT empleando la siguiente
version modificada del algoritmo CRITICAL ITEM:
procedure CRITICAL ITEM DINAMICO:
input: n, C, (p), (w), (d);
output: s;
begin
J1 := ∅;
J0 := ∅;
JC := {1, ..., N};
c := CT ;
particion = “no”;
while particion = “no” do
begin
determinar la mediana λ de los valores en R =
{
pjwjdj
: j ∈ JC
}
;
G :=
{
j ∈ JC :pj
wjdj> λ
}
;
L :=
{
j ∈ JC :pj
wjdj< λ
}
;
E :=
{
j ∈ JC :pj
wjdj= λ
}
;
c′ :=∑
j∈G
⌊
T
dj
⌋
(wjdj);
c′′ := c′ +∑
j∈E
⌊
T
dj
⌋
(wjdj);
if c′ ≤ c < c′′ then particion = “sı”;
else if c′ > c then [λ < rs]
begin
J0 = J0 ∪ L ∪ E;
JC = G;
end
else [λ > rs]
begin
J1 = J1 ∪G ∪ E;
JC = L;
c = c− c′′;
end
end;
J1 = J1 ∪G;
J0 = J0 ∪ L;
30
JC = E;
c = c− c′;
s = mın{j :∑
i∈Ei≤j
⌊
Tdi
⌋
(widi) > c}
end
2.2.4 Algoritmo Horowitz-Sahni Dinamico
Como vimos en la Seccion 1.2.3, el algoritmo de Horowitz-Sahni es un esquema tipo
branch-and-bound eficiente para KP, que utiliza la cota superior propuesta por Dantzig
(1.4) para tomar las decisiones sobre los objetos a ser incluidos en la mochila y podar el
arbol de busqueda. Es posible resolver una instancia de KP-PD empleando la siguiente
version modificada del algoritmo de Horowitz-Sahni. Asumimos que los objetos estan
ordenados de acuerdo a (2.38).
En la descripcion del algoritmo se emplea la siguiente notacion:
xj : solucion actual;
z :=
n∑
j=1
(pj/dj)xj , valor de la solucion actual;
c := C −n∑
j=1
wjxj , capacidad residual actual;
xj : mejor solucion factible encontrada hasta el momento;
z :=n∑
j=1
(pj/dj)xj , valor de la mejor solucion factible encontrada hasta el momento.
procedure HSD:
input: n, C, (p), (w), (d);
output: z, (x);
begin
1. [inicializar]
z := 0;
z := 0;
c := C;
pn+1 := 0;
wn+1 := +∞;
j := 1;
2. [calcular la cota superior U2]
encontrar r = mın{i :∑i
k=jwk > c};
u2 :=∑r−1
k=jpk/dk +
(
c−∑r−1
k=jwk
)
pr/wrdr;
if z ≥ z + u2 then go to 5;
31
3. [realizar un movimiento hacia adelante]
while wj ≤ c do
begin
c := c− wj;
z := z + pj/dj;
xj := 1;
j := j + 1;
end;
if j ≤ n then;
begin
xj := 0;
j := j + 1;
end;
if j < n then go to 2;
if j = n then go to 3;
4. [actualizar la mejor solucion hasta el momento]
if z > z then
begin
z := z;
for k := 1 to n do xk := xk
end;
j := n;
if xn = 1 then
begin
c := c+ wn;
z := z − pn/dn;
xn := 0
end;
5. [movimiento hacia atras]
encontrar i = max{k < j : xk = 1};
if no existe i then return; [finaliza la busqueda]
else
c := c+ wi;
z := z − pi/di;
xi := 0;
j := i+ 1;
go to 2;
end;
32
end.
2.3 Heurıstica primal
Ademas de la cota superior indicada en el Lema 2.10, una solucion optima x∗ para
KP-PD puede emplearse para definir una solucion factible para KP-DUR, al repetir
x∗ de manera periodica dentro del horizonte de tiempo T , seleccionando cada objeto i
para el cual x∗i = 1,⌊
Tdi
⌋
veces consecutivas, conforme se indica a continuacion:
1. ∀i ∈ {1, ..., n}, si x∗i = 1, entonces fijar
Ti :=
{
kdi + 1 : 0 ≤ k <
⌊
T
di
⌋}
,
xit := 1, ∀t ∈ Ti,
yi,t+di := 1, ∀t ∈ Ti/{T − di + 1},
zi,t+l := 1, ∀t ∈ Ti, 0 ≤ l < di.
2. Fijar xit = yit = zit = 0 en todos los demas casos.
Es facil comprobar que (x, y, z) es una solucion factible para KP-DUR. Utilizaremos
esta heurıstica primal dentro del esquema tipo branch-and-bound para la solucion de
KP-DUR que describimos en la siguiente seccion.
2.4 Algoritmo branch-and-bound
Tenemos todos los componentes necesarios para formular un esquema tipo branch-
and-bound para KP-DUR. Emplearemos la heurıstica descrita en la Seccion 2.3 para
construir una solucion factible y el algoritmo HSD propuesto en la Seccion 2.2.4 para
obtener cotas superiores al problema.
La decision de emplear el modelo KP-PD y el algoritmo HSD para el calculo de cotas
superiores frente a la alternativa del algoritmo Critical Item dinamico basado en el
modelo CKP-CT fue tomada luego de comparar la calidad de las cotas obtenidas por
ambos modelos, y los tiempos de ejecucion sobre ciertas instancias de prueba. Los
resultados estan detallados en el Cuadro 4.2 de la Seccion 4.1. Puede observarse que la
calidad de las cotas obtenidas por el modelo KP-PD es significativamente mejor que la
de las cotas CKP-CT, con tiempos de calculo similares. Por otra parte, el modelo KP-
PD puede ser extendido de manera natural para incorporar restricciones adicionales
33
que aparecen a partir de las decisiones de ramificacion, como veremos mas adelante.
Las decisiones de ramificacion (branching) consisten en forzar o prohibir que un objeto i
ingrese a la mochila en un perıodo t. Representaremos estas decisiones mediante ternas
de la forma
(i, t, k), con k =
1, si el objeto i ingresa en la mochila en el perıodo t;
0, caso contrario.
Cada nodo del arbol de busqueda tiene asociada una lista de ternas que representan las
decisiones tomadas previamente. Al iniciar el procesamiento del nodo, la informacion
de esta lista se emplea para calcular, para cada perıodo t ∈ {1, ..., T}, el conjunto
de objetos At que pueden ser seleccionados para ingresar en la mochila (a los que
llamamos objetos disponibles), ademas de la capacidad residual de la misma Ct. Se
emplea luego una version modificada del algoritmo HSD para determinar una cota
superior: se resuelven, por medio del metodo HS, T problemas clasicos de la mochila,
cada uno sobre un conjunto At de objetos, y considerando una mochila con capacidad
Ct. La suma de los valores optimos sobre todos los perıodos es una cota superior al
valor optimo de KP-DUR para el nodo actual. El algoritmo completo esta descrito en
el siguiente pseudocodigo.
Sean:
B = {0, 1};
X ∈ Bn×T la matriz solucion para el nodo actual;
z =
T∑
t=1
n∑
i=1
pidiXit el valor de la solucion asociada a X;
X ∈ Bn×T la matriz con la mejor solucion factible encontrada hasta el momento;
z =
T∑
t=1
n∑
i=1
pidiXit el valor de la mejor solucion factible encontrada hasta el momento;
L la lista de ternas que representan las decisiones de ramificacion tomadas hasta llegar
al nodo actual;
Q la cola de nodos por procesar, cada uno representado por su lista de ternas asociada;
A ∈ Zn×T la matriz de disponibilidad de objetos para el nodo actual;
Ct = C −∑
i:Ait=1
wi, capacidad residual de la mochila en el perıodo t, para el nodo
actual.
Es importante senalar que los elementos de las matrices solucion Xit,Xit indican la
presencia o no del objeto i dentro de la mochila en el perıodo t. Es decir,
corresponden realmente a las variables zit del modelo KP-DUR.
procedure KPD-BB:
input: n, C, T, (p), (w), (d);
34
output: z, (X);
begin
1. [inicializar]
z := 0;
z := 0;
Ct := C, ∀t ∈ {1, ..., T};
L := ∅;
2. [calcular una solucion factible empleando la heurıstica primal]
encontrar una solucion optima x de la instancia asociada KP-PD;
z :=
n∑
i=1
⌊
T
di
⌋
pixi; Xit :=
xi, si t ≤⌊
Tdi
⌋
di,
0, caso contrario.
3. [incluir en L algunas decisiones de ramificacion forzadas por el modelo]
agregar a L las ternas (i, t, 0), ∀i ∈ {1, ..., n}, ∀t ∈ {T − di + 2, ..., T}, forzadas
por (2.10);
4. Q := {L};
5. [lazo principal del esquema branch-and-bound]
while Q 6= ∅ do;
retirar la primera lista L de Q;
6. [inicio del procesamiento de un nodo]
obtener la matriz de disponibilidades A y las capacidades residuales Ct a partir
de las ternas de L;
7. [calcular la cota superior KP-PD]
for t := 1 to T do
begin
encontrar una solucion optima xt de KP-PD con los objetos disponibles
en cada columna At de A, empleando la capacidad residual Ct;
almacenar xt en la columna t de la matriz solucion para el nodo actual:
Xit :=
1, si Ait = 1 o xti = 1,
0, caso contrario;
end;
z :=
⌊
T∑
t=1
n∑
i=1
pidiXit
⌋
;
8. [podado del arbol de busqueda]
if z ≤ z then go to 5;
9. [comprobar si la solucion actual es factible]
if X es factible para KP-DUR
begin
35
[actualizar la mejor solucion obtenida hasta el momento]
z := z;
Xit := Xit, ∀i ∈ {1, ..., n}, ∀t ∈ {1, ..., T};
end;
go to 5;
else
begin
[ramificacion]
generar dos ternas nuevas t1 := (i, t, 1), t2 := (i, t, 0);
L1 := L ∪ {t1}, L2 := L ∪ {t2};
agregar las dos nuevas listas L1, L2 al inicio de la cola Q;
end;
go to 5;
end.
Para cada objeto identificamos cuatro posibles estados en los que este puede encontrarse
en un perıodo de tiempo determinado:
libre, si el objeto puede ser seleccionado para ingresar en la mochila;
posible, si el objeto no puede ingresar en la mochila en el perıodo actual, pero
puede estar presente en la misma debido a que podrıa ingresar en un perıodo
anterior;
presente, si el objeto forzosamente esta presente en la mochila en el perıodo actual,
por alguna decision de ramificacion tomada previamente durante la exploracion
del arbol de busqueda.
prohibido, si el objeto no puede estar en la mochila en el perıodo actual.
Decimos que un objeto i esta disponible en un perıodo t ∈ {1, ..., T}, si el estado de
i para este perıodo es de “libre” o “posible”. Para calcular una cota superior al valor
de la solucion optima en el nodo actual, resolvemos T instancias de KP-PD, cada una
restringida a los objetos disponibles en un perıodo de tiempo especıfico t ∈ {1, ..., T}.
La idea expuesta en los Lemas 2.9 y 2.10, puede extenderse para demostrar que la suma
de los valores optimos de estos problemas estaticos es una cota superior valida para el
problema dinamico KP-DUR sujeto a las restricciones de ramificacion.
El primer paso en el procesamiento de un nodo consiste en construir la matriz A de
disponibilidades de objetos a partir de la lista L = {(i1, t1, k1), (i2, t2, k2), ..., (ir, tr, kr)}
de decisiones de ramificacion tomadas previamente durante la exploracion del arbol de
36
busqueda. Esta matriz A contiene elementos de la forma:
Ait =
−1, si el objeto i esta libre en el perıodo t,
−2, si el objeto i es posible en el perıodo t,
1, si el objeto i esta presente en el perıodo t,
0, si el objeto i esta prohibido en el perıodo t.
Para construir A, se inicializan primero todos sus elementos en −1 (objetos libres) y
se realizan luego las siguientes sustituciones:
for j := 1, ..., r do
if kj = 1 then
Aij t= 1, ∀t ∈ {tj, ..., tj + dij − 1},
Aij t= −2, ∀t ∈ {tj − dij + 1, ..., tj − 1} que satisfaga Aij t
= −1,
else
Aijtj = −2.
Si se ha tomado la decision de que el objeto ij ingrese en el tiempo tj , entonces este
objeto estara presente en la mochila en los tiempos tj , tj + 1, ..., tj + dij − 1, lo que
se indica marcando con 1 las entradas correspondientes de A. Ademas el objeto no
podra ingresar en la mochila en los tiempos tj − dij + 1, ..., tj − 1 aunque podrıa estar
presente en la misma, debido a que ingreso en un tiempo anterior. Indicamos esto
marcando con −2 las entradas correspondientes de A. Por otra parte, si una terna
indica que se ha tomado la decision de que el objeto ij no entra en la mochila en el
tiempo tj , marcamos la entrada correspondiente de A con −2. Nuevamente, esto se
debe a que el objeto aun podrıa estar presente en la mochila en tj , debido a haber
ingresado en un tiempo anterior.
Una vez consideradas todas las decisiones de la lista L, se prosigue a restringir las
disponibilidades de los objetos considerando la capacidad residual Ct de la mochila
para cada perıodo t:
for t := 1, ..., T
for i := 1, ..., n doif Ait ∈ {−1,−2} and wi > Ct then
Ait := 0,
Ait:= −2, ∀t ∈ {t− di + 1, t− di + 2, ..., t− 1} que satisfaga A
it= −1.
37
Si un objeto i tiene un tamano mayor al de la capacidad residual de la mochila en un
perıodo t, entonces i no puede estar dentro la mochila en este perıodo. Las capacida-
des residuales Ct se calculan restando, para cada perıodo t, el tamano de los objetos
presentes en la mochila (aquellos para los cuales Ait = 1) de su capacidad total. Notar
ademas que si Ait = 0, entonces i no pudo haber ingresado en la mochila en los di − 1
tiempos anteriores, lo que se indica colocando −2 en las entradas correspondientes de
A.
Por otra parte, si un objeto i no puede ingresar a la mochila durante di perıodos con-
secutivos, entonces no podra estar en ella al final de este intervalo:
for i := 1, ..., n do
for t := 1, ..., T − di + 1 do
if Ait ∈ {−2, 0, 1}, ∀t ∈ {t, t+ 1, ..., t+ di − 1} then
Ai,t+di−1 := 0.
Por ultimo, se prohibe la presencia en la mochila de un objeto durante intervalos de
tiempo inferiores a su duracion:
for i := 1, ..., n do
while existan t ∈ {1, ..., T − di + 1} and δ < di such that
Ait ∈ {0, 1}, Ai,t+l ∈ {−1,−2}, ∀l ∈ {1, ..., δ}, and Ai,t+δ+1 ∈ {0, 1} do
Ai,t+l := 0, ∀l ∈ {1, ..., δ}.
Una vez construida la matriz de disponibilidades de objetos A, las columnas de la
misma se usan para construir T instancias del problema clasico de la mochila KP-PD,
cada una de ellas sobre el conjunto de objetos disponibles en un perıodo t ∈ {1, ..., T}.
At := { i | Ait ∈ {−1,−2}},
y con la mochila restringida a su capacidad residual,
Ct := C −∑
i:Ait=1
wi.
A partir de las soluciones xt a cada una de estas instancias se construye una cota
superior para KP-DUR:
for i := 1, ..., n
for t := 1, ..., T do
if Ait = 1 or xti = 1 then
Xit := 1,
else
Xit := 0.
Si el valor de esta cota es inferior o igual al de la mejor solucion factible hasta el
38
momento, se realiza una “poda” en el arbol de busqueda: la solucion es desechada y se
prosigue con el procesamiento de un nuevo nodo en Q. Si, por el contrario, el valor de
la cota supera al valor de la mejor solucion factible X encontrada hasta el momento,
se examina la factibilidad de la solucion asociada X . Si X es factible, se actualizan
X := X , z = z, y el procesamiento termina. Si X no es factible, se procede a realizar
una ramificacion, para lo cual hemos investigado tres posibles tecnicas:
La primera tecnica de ramificacion busca en las matrices A y en la solucion actual
X el primer elemento libre que haya sido seleccionado por la cota superior:
for i := 1, ..., n do
for t := T, ..., 1 do
if Ait = −1 and Xit = 1, then
t1 := (i, t, 1),
t2 := (i, t, 0).
break;
La segunda tecnica de ramificacion busca simplemente el primer objeto libre:
for i := 1, ..., n do
for t := T, ..., 1 do
if Ait = −1 then
t1 := (i, t, 1),
t2 := (i, t, 0).
break;
La tercera tecnica de ramificacion ordena las filas de las matricesA y X en sentido
descendente de los valores de los objetos, siendo i = 1 la fila que corresponde al
objeto de mayor valor e i = n la fila asociada al de menor valor (originalmente,
las filas estan ordenadas descendentemente por la densidad p/wd de los objetos).
Luego se emplea el mismo criterio que en la primera tecnica:
ordenar filas de A y X descendentemente segun valor de los objetos
for i := 1, ..., n do
for t := T, ..., 1 do
39
if Ait = −1 and Xit = 1, then
t1 := (i, t, 1),
t2 := (i, t, 0).
break;
En los tres casos, el elemento (i, t) seleccionado es empleado para construir dos ternas
t1, t2 que representan las decisiones de forzar la entrada del objeto i en la mochila en
el perıodo t, o de prohibir su ingreso. Con estas ternas, se definen las nuevas listas
L1 := L ∪ {t1} y L2 := L ∪ {t2}, las mismas que se anaden a la cola Q de listas por
procesar, y la iteracion termina.
El algoritmo termina cuando todas las listas de ternas pendientes en Q han sido pro-
cesadas, y devuelve como resultado el valor optimo del problema.
Ejemplo
Veamos el funcionamiento general del esquema para la siguiente instancia de KP-DUR:
Se tiene una mochila con capacidad C = 5, y 4 objetos con las siguientes caracterısticas:
valores : 2 11 6 3
pesos : 1 4 4 2
duraciones : 2 3 2 3
ındices : 1 2 3 4
Se quiere maximizar el valor total almacenado en la mochila en un horizonte temporal
T = 4, y los objetos estan ordenados de acuerdo a (2.38). La primera solucion obtenida
mediante la heurıstica primal viene dada por:
X =
1 1 1 1
1 1 1 0
0 0 0 0
0 0 0 0
donde Xit tiene el valor de 1 cuando el objeto i ∈ {1, ..., 4} esta presente en la mochila
en el perıodo t ∈ {1, ..., 4}. En este caso, la solucion consiste en ingresar a la mochila
el primer objeto en los tiempos t = 1 y t = 3, e ingresar el segundo objeto en el tiempo
t = 1. El valor de esta solucion inicial es z = 2 + 2 + 11 = 15. Se generan entonces las
ternas forzadas por el modelo y se construye la lista inicial L. Luego entramos en el
lazo principal del esquema branch-and-bound. A partir de L se construye la primera
40
matriz de disponibilidades:
A =
-1 -1 -1 -2
-1 -1 -2 -2
-1 -1 -1 -2
-1 -1 -2 -2
Con la matriz A se construyen T instancias de KP-PD independientes, cada una con
los objetos disponibles y la capacidad residual existente en cada perıodo de tiempo.
En este caso, para las 4 instancias todos los objetos estan disponibles y la capacidad
residual es la capacidad total de la mochila. Al resolver cada instancia empleando el
algoritmo HSD, la solucion encontrada es:
X =
1 1 1 1
1 1 1 1
0 0 0 0
0 0 0 0
con un valor de z = 18, que es mayor que el valor de la mejor solucion z. Se comprueba
entonces si esta solucion es factible o no, en nuestro caso es infactible. Se procede a
crear dos ternas de ramificacion, empleando para este ejemplo la primera tecnica, que
selecciona i = 1, t = 3 y t1 := (1, 3, 1), t2 := (1, 3, 0). Con estas ternas se crean las
nuevas listas L1 = L ∪ {t1}, L2 = L ∪ {t2} y se las agrega al inicio de la cola Q, con lo
que termina la primera iteracion del lazo principal. En la segunda iteracion, se retira
la primera lista L1 de la cola, la matriz de disponibilidades para esta es:
A =
-1 -2 1 1
-1 -1 -2 -2
-1 -1 -1 -2
-1 -1 -2 -2
Para esta nueva matriz de disponibilidades se crean las T instancias de KP-PD y se
resuelve independientemente cada una de ellas. Las instancias para t ∈ {1, 2} tienen
nuevamente los cuatro objetos y toda la capacidad de la mochila disponibles. Para
t ∈ {3, 4}, estan disponibles los objetos 2,3,4 y la capacidad residual es Ct = C−w1 = 4.
Aun ası, el resultado obtenido sigue siendo el mismo:
X =
1 1 1 1
1 1 1 1
0 0 0 0
0 0 0 0
41
Nuevamente, tenemos que el valor z es mayor que el de la solucion actual z. Ademas,
la solucion es infactible y volvemos a generar dos nuevas ternas de ramificacion t3 :=
(1, 1, 1), t4 := (1, 1, 0), junto con las nuevas listas L3 = L1∪{t3}, L4 = L1∪{t4}, que son
agregadas a la cola Q. Algunas iteraciones mas adelante, se llega a la solucion factible:
X =
1 1 1 1
0 0 0 0
1 1 1 1
0 0 0 0
con un valor de z = 16. Como este valor supera al de la mejor solucion encontrada
hasta el momento, se actualiza esta ultima:
X =
1 1 1 1
0 0 0 0
1 1 1 1
0 0 0 0
Al terminar la exploracion de todas las listas pendientes en Q, resulta ser que esta
solucion es la solucion optima de la instancia.
42
Capıtulo 3
Implementacion Computacional
La implementacion computacional del algoritmo KPD-BB descrito en el capıtulo an-
terior se realizo en el lenguaje C++. Para poder comparar la eficiencia computacional
del metodo, se programo el modelo entero en SCIP, que es un solver general para
programas enteros.
3.1 Modelo general
El modelo recibe como entrada tres enteros positivos que representan el numero de
objetos n, la capacidad de la mochila C, y, el horizonte temporal T ; y tres vectores de
dimension n: el primero con los valores de los objetos, el segundo con sus pesos y el
tercero con sus duraciones.
Los datos de entrada se guardan en la clase objetos mochila dinamico, en la parteprivada se declaran vectores para los valores de los objetos p, sus pesos w, duracionesdur, densidades r, ındices ind; ademas de las variables enteras c para la capacidad dela mochila y T para el horizonte temporal. En la parte publica de la clase estan algunasfunciones importantes para calcular la cota superior en base al algoritmo Critical ItemDinamico, ası como funciones que retornan los vectores p, w, dur, r e ind y los enterosc y T , para ser usados por otras funciones no pertenecientes a la clase.
class ob je to s moch i l a d inamico
{
private :
v e c to r <double> p ;
vec to r <double> w;
vec to r <double> r ;
v e c to r <double> dur ;
v e c to r <double> ind ;
int c ;
int T;
43
public :
const vec to r <double>& p ( ) const {return p ;}
const vec to r <double>& w () const {return w;}
const vec to r <double>& r ( ) const {return r ;}
const vec to r <double>& dur ( ) const {return dur ;}
const vec to r <double>& ind ( ) const {return ind ;}
const int& c ( ) const {return c ;}
const int& T () const {return T;}
void a s i g n a r v a l o r e s ( vector<double>, vector<double>,
vector<double>, vector<double>, int , int ) ;
void cambiar pw ( ) ;
void quickSor t ( int , int ) ;
void mostrar ( ) const ;
void intercambiar ( int , int ) ;
void mayores menores igua le s ( int&, int&, int , int ) ;
void mediana( int , int&, int&, int , int ) ;
int c r i t i c a l i t em ( int , int , int ) ;
double co ta supe r i o rCI ( int , int ) ;
} ;
Para almacenar las decisiones tomadas por el algoritmo KPD-BB se creo una clasellamada terna, que consta de cuatro elementos publicos: un constructor para el objetoterna, y tres variables enteras. La variable i indica el objeto sobre el cual se va a tomarla decision, j indica el perıodo de tiempo asociado a la decision y k ∈ {0, 1} toma elvalor de 0 si la decision es que el objeto i no ingrese en la mochila en el perıodo j, y 1caso contrario.
class te rna
{
public :
t e rna (unsigned int i1 , unsigned int j1 , unsigned int k1 ) ;
unsigned int i ; // marca el ındice del objeto
unsigned int j ; // marca el ındice del tiempo
unsigned int k ; // marca el valor de la variable, en 0, 1
} ;
Finalmente, una clase llamada algoritmos posee ciertas funciones en su parte privaday publica que se usan en el algoritmo KPD-BB.
class a lgo r i tmos
{
private :
static double upper bound ( const ob je to s moch i l a d inamico&, int , int ) ;
static void forward ( const ob je to s moch i l a d inamico&,vector<int>&,
int&,double&,unsigned int&);
static bool backtrack ( const ob je to s moch i l a d inamico&,vector<int>&,
int&,double&,unsigned int&);
44
static void update ( const ob je to s moch i l a d inamico&,vector<int>&,
vector<int>&,int&,double&,double&);
static bool e s f a c t i b l e ( const ob je to s moch i l a d inamico&,
const vector<vector<int>>&,
const vector<vector<unsigned>>&,
const vector<double>&,bool&, terna&, terna &);
public :
static double HS( ob je to s moch i l a d inamico&,vector<int>&);
static double c o t a s up e r i o r i n f e r i o rHS ( ob je to s moch i l a d inamico&,
int&);
static void p r o c e s a r l i s t a t e r n a s ( const l i s t <terna>&,
const ob je to s moch i l a d inamico&,
vector<vector<int>>&);
static double cota super io rBB ( const ob je to s moch i l a d inamico&,
vector<vector<int>>&,
vector<vector<unsigned>>&,unsigned ) ;
static double branch and bound (unsigned int , unsigned int ,
const vector<double>&,
const vector<double>&,
const vector<double>&,
double , double&);
} ;
3.2 Algoritmos Critical Item y Horowitz-Sahni
3.2.1 Algoritmo Critical Item
El algoritmo Critical Item utiliza algunas funciones para calcular el ıtem crıtico, lasmas importantes son las funciones recursivas mediana y critical item.
void ob je to s moch i l a d inamico : : mediana ( int med1 , int&a , int&b , int i , int j )
{
mayores menores igua le s (med1 , a , b , i , j ) ;
i f ( a<=med1)
{
i f (med1<=b−1)
{
return ;
}
else
{
mediana (med1 , a , b , b , j ) ;
}
}
else
45
{
mediana (med1 , a , b , i , a−1);
}
}
mediana ordena parcialmente una porcion del vector r y en forma sincronizada tam-
bien las porciones de los vectores p, w, dur e ind. La funcion recibe como parametros
un entero med1 que es el ındice de la mediana en la porcion del vector a ordenar,
los enteros i y j que nos indican los ındices del principio y el final de la porcion de
vector a ordenar, y los enteros por referencia a y b que seran empleados para retor-
nar la respuesta. Los objetos a ingresar en la mochila son ordenados parcialmente por
sus radios r =pj
wjdjde manera descendente de acuerdo a (2.38) mediante la funcion
mayores menores iguales. La funcion termina cuando encuentra una particion del
vector de radios r talque (a ≤ med1 ≤ b− 1) donde,
r[k] > r[med1], ∀k ∈ {i, ..., a− 1},
r[k] = r[med1], ∀k ∈ {a, ..., b− 1},
r[k] < r[med1], ∀k ∈ {b, ..., j}.
Los valores de a y b son retornados para su uso en la funcion critical item.
int ob je to s moch i l a d inamico : : c r i t i c a l i t em ( int i , int j , int cact )
{
int h ;
int k ;
int s1=0;
int s2=0;
int s3=0;
int med=(int ) ( j−i )/2 + i ;
for (unsigned int n=0;n<=w. s i z e ()−1;n++)
{
s3=s3+(( int )\ f r a c {T}{dur [ n ] } )w[ n ] dur [ n ] ;
}
i f ( s3<=cact )
{
return w. s i z e ()−1;
}
else
{
mediana (med , h , k , i , j ) ;
for ( int d=i ; d<=h−1; d++)
{
s1=s1+(( int )\ f r a c {T}{dur [ d ] } )w[ d ] dur [ d ] ;
46
}
s2=s1 ;
for ( int d=h ; d<=k−1; d++)
{
s2=s2+(( int )\ f r a c {T}{dur [ d ] } )w[ d ] dur [ d ] ;
}
i f ( s1<=cact )
{
i f ( cact<s2 )
{
int l=h ;
cact=cact−s1 ;
while ( ( ( int )\ f r a c {T}{dur [ l ] } )w[ l ] dur [ l ]<=cact )
{
cact=cact −(( int )\ f r a c {T}{dur [ l ] } )w[ l ] dur [ l ] ;
l++;
}
return ( l ) ;
}
else
{
cact=cact−s2 ;
return c r i t i c a l i t em (k , j , cact ) ;
}
}
else
{
return c r i t i c a l i t em ( i , h−1, cact ) ;
}
}
}
critical item recibe como parametros un entero cact que es la capacidad actual de la
mochila y dos ındices i y j que delimitan la porcion del vector r que se va a considerar.
Esta funcion calcula una particion del vector de radios r por medio de la funcion
mediana, de manera que se cumpla la condicion de parada (h ≤ med1 ≤ k−1) tal que,
r[t] > r[med1], ∀t ∈ {i, ..., h− 1},
r[t] = r[med1], ∀t ∈ {h, ..., k − 1},
r[t] < r[med1], ∀t ∈ {k, ..., j}.
47
Posteriormente, la funcion calcula los valores
s(1) =h−1∑
i=1
⌊
T
dur[i]
⌋
w[i]dur[i],
s(2) = s(1) +k−1∑
i=h
⌊
T
dur[i]
⌋
w[i]dur[i].
Si la particion encontrada por mediana satisface la condicion s(1) ≤ cact < s(2),
entonces
cact = cact− s(1),
critical item termina y retorna como solucion el menor ındice l del objeto tal que,
mın
{
l :
l∑
i=h
⌊
T
dur[i]
⌋
w[i]dur[i] > cact
}
.
Caso contrario, critical item es invocado recursivamente sobre la porcion del vector
[k; j] pero con una capacidad actual reducida a cact = cact − s(2), si s(2) ≤ cact, o
sobre la porcion [i; h− 1] con la capacidad actual cact, si s(1) > cact.
3.2.2 Algoritmo Horowitz-Sahni
El algoritmo Horowitz-Sahni, HS, es un esquema tipo brach-and-bound que resuelveel problema clasico de la mochila KP. Este algoritmo fue modificado para resolver elproblema KP-PD y hemos llamado HSD al nuevo algoritmo. Todas las funciones deHSD estan implementadas en la clase algoritmos.
double a lgo r i tmos : : upper bound ( const ob je to s moch i l a d inamico& R, int c ,
int k )
{
int cact=c ;
int in=k ;
int s=0;
int s1=0;
int d=0;
double up1=0;
double up2=0;
while ( s<=cact )
{
s1=s ;
s=s+(R. w ( ) ) [ k ] ;
d=k ;
k++;
}
48
for ( int j=in ; j<=d−1; j++)
{
up1=up1+((R. p ( ) ) [ j ] / (R. dur ( ) ) [ j ] ) ;
}
up2=up1+(( cact−s1 ) ( (R. p ( ) ) [ d ] / ( (R. w ( ) ) [ d ] (R. dur ( ) ) [ d ] ) ) ) ;
return up2 ;
}
La funcion upper bound, recibe como parametros un objeto mochila dinamico R, la
capacidad de la mochila actual c y un entero k que es el ındice de la posicion en el vector
de objetos desde la que se va a calcular la cota superior U2 definida en la Seccion 2.2.4.
Para calcular esta cota son necesarias algunas variables locales. La funcion encuentra
el primer objeto (a partir de la posicion k) que ya no podrıa entrar en la mochila con
la capacidad actual c. Esta posicion es almacenada en el entero d, y con el mismo se
calcula el valor de la cota U2,
U2 =
d−1∑
j=k
p[j]
dur[j]+ c
p[d]
w[d]dur[d],
Donde c = c− s1, y s1 =d−1∑
j=k
w[j].
void a lgo r i tmos : : forward ( const ob je to s moch i l a d inamico& R, vector<int>&x ,
int&c , double&z , unsigned int&k)
{
while ( (R. w ( ) ) [ k]<=c )
{
c=c−(R. w ( ) ) [ k ] ;
z=z+((R. p ( ) ) [ k ] / (R. dur ( ) ) [ k ] ) ;
x [ k ]=1;
k++;
}
i f (k<=(R. p ( ) ) . s i z e ()−2)
{
x [ k ]=0;
k++;
}
}
La funcion forward implementa la parte 3 del algoritmo HSD, es decir, lo que se conoce
como “movimiento hacia adelante”. Recibe como parametros un objeto mochila dinamico
49
R, un vector por referencia x en el que se guardan las decisiones tomadas por el al-
goritmo, un entero por referencia c que es la capacidad actual de la mochila, un valor
de punto flotante por referencia z que es el valor de la solucion actual, y un entero
sin signo por referencia k que es el ındice de la posicion en el vector desde el cual se
va a realizar el movimiento. El movimiento hacia adelante consiste en introducir en la
mochila tantos objetos consecutivos como sea posible, respetando la capacidad actual
c de la mochila. Para cada objeto i que ingresa se asigna al vector x en la posicion i
el valor 1, (x[i] = 1), y en caso contrario 0. Ademas, el valor de la solucion actual y la
capacidad de la mochila se recalculan como se indica a continuacion.
Sea l definido como
mın
{
l :
l∑
i=k
w[i] > c
}
,
entonces,
c = c−l−1∑
i=k
w[i],
z = z +
l−1∑
i=k
p[i]
dur[i].
El entero k se actualiza a k = l + 1.
bool a lgo r i tmos : : backtrack ( const ob je to s moch i l a d inamico& R, vector<int>&x ,
int&c , double&z , unsigned int&k)
{
int e=−1;
for (unsigned int j =0; j<k ; j++)
{
i f ( x [ j ]==1)
{
e=j ;
}
}
i f ( e==−1)
{
return fa l se ;
}
else
{
c=c+(R. w ( ) ) [ e ] ;
z=z−((R. p ( ) ) [ e ] / (R. dur ( ) ) [ e ] ) ;
x [ e ]=0;
k=e+1;
return true ;
50
}
}
La funcion backtrack es una funcion tipo bool que implementa la parte 5 del algoritmo
HSD, la que se conoce como “movimiento hacia atras”. Recibe como parametros un
objeto mochila dinamico R, un vector por referencia x en el que se guardan las
decisiones tomadas, un entero por referencia c que es la capacidad actual de la mochila,
un valor de punto flotante por referencia z que es el valor de la solucion actual, y un
entero sin signo por referencia k que es el ındice de la posicion en el vector desde el
cual se va a realizar el movimiento. El movimiento hacia atras consiste en retirar el
ultimo objeto insertado de la solucion actual. De no existir ningun objeto para retirar,
entonces la funcion retorna el valor “falso”. Caso contrario, se determina el ındice e del
ultimo objeto insertado, se recalculan el valor de la solucion actual y la capacidad de
la mochila como se indica a continuacion, se le asigna a x[e] el valor de 0, y por ultimo
se actualiza k a su nueva posicion. La funcion retorna el valor de “verdadero”.
e = max{e < k : x[e] = 1},
c = c+ w[e],
z = z −p[e]
dur[e],
k = e+ 1.
void a lgo r i tmos : : update ( const ob je to s moch i l a d inamico&R,
vector<int>&so l opt , vector<int>&so l a c t ,
int&cact , double&zopt , double&zact )
{
i f ( zact>zopt )
{
zopt=zact ;
for (unsigned int k=0; k<=s o l a c t . s i z e ()−1; k++)
{
s o l o p t [ k]= s o l a c t [ k ] ;
}
}
int i=s o l a c t . s i z e ()−1;
i f ( s o l a c t [ i ]==1)
{
cact=cact+(R. w ( ) ) [ i ] ;
zact=zact −((R. p ( ) ) [ i ] / (R. dur ( ) ) [ i ] ) ;
s o l a c t [ i ]=0;
}
}
51
La funcion update recibe como parametros un objeto mochila dinamico R, un vector
por referencia sol opt en el que se guarda la mejor solucion encontrada hasta el momen-
to, un vector por referencia sol act que almacena la solucion actual del algoritmo, un
entero por referencia cact que es la capacidad actual de la mochila, un valor de punto
flotante por referencia zopt que es el valor de la mejor solucion sol opt y un valor de
punto flotante por referencia zact que es el valor de la solucion actual. Esta funcion
actualiza la mejor solucion cada vez que encuentra una solucion actual de mayor valor.
Es decir, si zact > zopt,
zopt = zact,
sol opt[i] = sol act[i], ∀i ∈ {1, ..., n}.
Luego se actualiza el valor de la solucion actual solo si sol act[n] = 1. En este caso,
cact = cact + w[n],
zact = zact−p[n]
dur[n],
sol act[n] = 0.
double a lgo r i tmos : : HS( ob j e to s moch i l a d inamico& R, vector<int>&so l 1 )
{
.
.
.
while ( true ){
i f ( zopt<zact+upper bound (R, cact , i ) )
{
forward (R, s o l a c t , cact , zact , i ) ;
i f ( i>(R. p ( ) ) . s i z e ()−2)
{
update (R, so l opt , s o l a c t , cact , zopt , zact ) ;
i =(R. p ( ) ) . s i z e ()−2;
f=backtrack (R, s o l a c t , cact , zact , i ) ;
i f ( f )
continue ;
else
{
break ;
}
}
else
{
52
i f ( i<(R. p ( ) ) . s i z e ()−2)
{
continue ;
}
else
{
forward (R, s o l a c t , cact , zact , i ) ;
update (R, so l opt , s o l a c t , cact , zopt , zact ) ;
i =(R. p ( ) ) . s i z e ()−2;
f=backtrack (R, s o l a c t , cact , zact , i ) ;
i f ( f )
continue ;
else
{
break ;
}
}
}
}
else
{
f=backtrack (R, s o l a c t , cact , zact , i ) ;
i f ( f )
continue ;
else
{
break ;
}
}
}
for (unsigned int j =0; j<=so l o p t . s i z e ()−1; j++)
{
s o l 1 [ j ]= s o l o p t [ j ] ;
}
return zopt ;
}
La funcion HS es una funcion con tipo de retorno de punto flotante, recibe como parame-
tros un objeto mochila dinamico R con todos los datos del problema, y un vector
por referencia sol1 que es el vector donde se guardara la solucion optima. Esta funcion
ejecuta el lazo principal del algoritmo HSD, llamando a todas las funciones antes men-
cionadas. Primero inicializa algunas variables locales zopt = 0, zact = 0, como variables
de tipo de punto flotante para guardar el valor de la solucion actual y el de la mejor
solucion encontrada hasta el momento; los vectores de tipo entero sol opt, sol act se
utilizaran para guardar la mejor solucion encontrada hasta el momento y la solucion
53
actual, respectivamente; un entero sin signo i = 0 indica la posicion inicial desde la
que empezara el movimiento hacia adelante; y una variable tipo bool f guarda el valor
retornado por la funcion backtrack. El lazo principal es un lazo infinito que se repite
hasta alcanzar una condicion de parada: dentro de este se ejecuta primero el punto 2
del algoritmo HSD que consite en calcular la cota superior U2 a partir de la posicion
actual i y sumarla con el valor de la solucion actual zact. Entonces se comprueba si
la rama del arbol de decision que se esta explorando tiene la posibilidad de superar el
valor de la mejor solucion encontrada hasta el momento (zopt < zact + U2), en cuyo
caso se ejecuta un movimiento hacia adelante con la funcion forward. De no ser ası,
la solucion es desechada (poda del arbol) y se intenta un movimiento hacia atras con
la funcion backtrack. La solucion encontrada durante la exploracion de una rama del
arbol de decisiones se compara con la mejor solucion encontrada hasta el momento
mediante un llamado a la funcion update y de ser necesario se actualiza esta ultima.
El algoritmo termina cuando no son posibles mas movimientos hacia atras y devuelve
como resultado el valor optimo zopt y su solucion asociada sol1.
3.3 Calculo de soluciones factibles
Las soluciones factibles para KP-DUR se calculan empleando el metodo descrito enla Seccion 2.3: Se resuelve la version modificada KP-PD del problema clasico queconsidera en la funcion objetivo el tiempo de duracion de cada objeto, y a partirde la solucion optima se construye una solucion factible para KP-DUR repitiendo cadaobjeto seleccionado i el maximo numero de veces que este puede estar en la mochila
durante el horizonte temporal T , es decir,⌊
Tdi
⌋
.
double a lgo r i tmos : : c o t a s up e r i o r i n f e r i o rHS ( ob je to s moch i l a d inamico& R,
int&CI )
{
vector<int>s o l 1 ;
s o l 1 . r e s i z e ( (R. r ( ) ) . s i z e ( ) ) ;
for (unsigned int j =0; j<=so l 1 . s i z e ()−1; j++)
{
s o l 1 [ j ]=0;
}
HS(R, s o l 1 ) ;
.
.
.
for (unsigned int j =0; j<=so l 1 . s i z e ()−1; j++)
{
i f ( s o l 1 [ j ]==1)
54
{
CI=CI+(( int ) ( (R. T ( ) ) / (R. dur ( ) ) [ j ] ) ) (R. p ( ) ) [ j ] ;
}
}
.
.
}
La funcion cota superior inferiorHS retorna un valor de punto flotante y recibe
como parametros un objeto mochila dinamico R, y un entero por referencia CI en el
que guarda el valor de la solucion factible descrita en el parrafo anterior. Con los objetos
ordenados de acuerdo a (2.38), se crea un vector local sol1 para guardar la solucion de
KP-PD que se calcula llamando a la funcion HS. A partir de esta solucion el valor de
la solucion factible para KP-DUR se calcula, como lo hemos indicado, repitiendo los
objetos i tales que sol1[i] = 1 el maximo numero de veces que su duracion lo permita
en el horizonte de tiempo. Es decir,
CI =
n∑
i=1
⌊
T
dur[i]
⌋
p[i]sol1[i].
3.4 Calculo de cotas superiores
Las cotas superiores CKP-CT y KP-PD se calculan con las funciones cota superiorCI
y cota superior inferiorHS, en la forma descrita en la Seccion 2.2.
double ob je to s moch i l a d inamico : : c o ta supe r i o rCI ( int l , int cact )
{
double s1 =0.0 ;
int s2=0;
double s3 =0.0 ;
for ( int i =0; i<l ; i++)
{
s1=s1+(( int ) (T/dur [ i ] ) ) p [ i ] ;
s2=s2+(( int ) (T/dur [ i ] ) ) w[ i ] dur [ i ] ;
}
s3=s1+(( cact−s2 ) ( p [ l ] /w[ l ] dur [ l ] ) ) ;
return s3 ;
}
La funcion cota superiorCI pertenece a la clase objetos mochila dinamico y retor-
na un valor de punto flotante. Recibe como parametros un entero l que es ındice del
ıtem crıtico calculado mediante la funcion critical item, y un entero cact que es la
capacidad de la mochila. La funcion calcula la cota definida en el Teorema (2.11). Para
ello, se crean tres variables locales: una variable de punto flotante s1 almacena el valor
(de la funcion objetivo modificada) aportado por todos los objetos hasta el anterior al
55
ıtem crıtico;
s1 =
l−1∑
i=1
⌊
T
dur[i]
⌋
p[i],
una variable entera s2 indica la capacidad de la mochila ocupada por estos objetos,
s2 =l−1∑
i=1
⌊
T
dur[i]
⌋
w[i]dur[i],
finalmente, el valor de la cota superior a retornar se almacena en la variable de punto
flotante s3,
s3 = s1 +
(
(cact− s2)p[l]
w[l]dur[l]
)
.
double a lgo r i tmos : : c o t a s up e r i o r i n f e r i o rHS ( ob je to s moch i l a d inamico& R,
int&CI )
{
vector<int>s o l 1 ;
s o l 1 . r e s i z e ( (R. r ( ) ) . s i z e ( ) ) ;
for (unsigned int j =0; j<=so l 1 . s i z e ()−1; j++)
{
s o l 1 [ j ]=0;
}
HS(R, s o l 1 ) ;
double cota =0.0 ;
for (unsigned int j =0; j<=so l 1 . s i z e ()−1; j++)
{
i f ( s o l 1 [ j ]==1)
{
cota=cota+((R. T ( ) ) / (R. dur ( ) ) [ j ] ) (R. p ( ) ) [ j ] ;
}
}
.
.
.
return cota ;
}
La funcion cota superior inferiorHS calcula la cota superior obtenida a partir de la
solucion optima de KP-PD. La funcion calcula una solucion de KP-PD llamando a la
funcion HS y almacena la respuesta en el vector sol1. Con esta solucion, se calcula una
56
cota superior para KP-DUR, empleando la formula:
cota =
n∑
i=1
T
dur[i]p[i]sol1[i].
3.5 Algoritmo KPD-BB
Describiremos a continuacion la implementacion del esquema branch-and-bound ex-puesto en la Seccion 2.4.
void a lgo r i tmos : : p r o c e s a r l i s t a t e r n a s ( const l i s t <terna>&L,
const ob je to s moch i l a d inamico& R,
vector< vector<int> >&obj s )
{
unsigned int tam=(R. r ( ) ) . s i z e ( ) ; // Cantidad total de objetos
unsigned int T=(R. T ( ) ) ; // Horizonte de tiempo
ob j s . c l e a r ( ) ;
ob j s . r e s i z e (tam ) ;
for (unsigned i =0; i<ob j s . s i z e ( ) ; i++)
{
ob j s [ i ] . r e s i z e (T,−1);
}
Al iniciar el procesamiento de cada nodo del arbol branch-and-bound, la funcion
procesar lista ternas se encarga de calcular la matriz de disponibilidades A a partir
de la lista de ternas que almacenan las decisiones tomadas previamente. Esta funcion
recibe como parametros una lista de ternas L, un objetos mochila dinamico R, y una
matriz por referencia objs en la que se guardaran las disponibilidades de los n objetos
en cada uno de los T perıodos de tiempo. Primero se redimensiona la matriz objs a
n× T y se inicializan sus elementos,
objs[i][t] = −1, ∀i ∈ {1, ..., n}, ∀t ∈ {1, ..., T}.
(En el codigo se usa la variable entera local tam para almacenar el numero n de objetos).Luego se ejecutan secuencialmente los procesos de preprocesamiento expuestos en laSeccion 2.4. Primero se registran en la matriz objs todas las decisiones tomadas deacuerdo a las ternas de la lista L.
//(1)Registrar en la matriz las decisiones tomadas
for ( l i s t <terna > : : c o n s t i t e r a t o r i t=L . begin ( ) ; i t !=L . end ( ) ; i t++)
{
int veces1=0;
i f ( ( i t ) . k==1)
{
while ( veces1<(R. dur ( ) ) [ ( i t ) . i −1])
{
57
i f ( ( int ( ( i t ) . j−1)−veces1>=0) &&
( ob j s [ ( i t ) . i −1] [ int ( ( i t ) . j−1)−veces1 ]==−1))
{
ob j s [ ( i t ) . i −1] [ int ( ( i t ) . j−1)−veces1 ]=−2;
}
ob j s [ ( i t ) . i −1] [ int ( ( i t ) . j−1)+veces1 ]=1;
veces1++;
}
}
else
{
i f ( ( i t ) . k==0)
{
ob j s [ ( i t ) . i −1 ] [ ( i t ) . j−1]=−2;
}
}
}
La variable local tipo entero veces1 sirve como contador para determinar los perıodosafectados por la duracion del objeto (antes y despues de su insercion en la mochila).A continuacion, se aplica la segunda regla y se prohibe la presencia en la mochila deobjetos que no pueden caber debido a la restriccion de la capacidad a consecuencia delas decisiones tomadas anteriormente,
//(2)Prohibir presencia de objetos que ya no puedan estar en la
// mochila debido a la capacidad en cada perıodo de tiempo
int k=1;
while (k<=int (T) )
{
int cob j s=(R. c ( ) ) ;
for (unsigned int i =0; i<ob j s . s i z e ( ) ; i++)
{
i f ( ob j s [ i ] [ k−1]==1)
{
cob j s=cobjs −(R. w ( ) ) [ i ] ;
}
}
for (unsigned int i =0; i<ob j s . s i z e ( ) ; i++)
{
i f ( ( (R. w ( ) ) [ i ]> cob j s ) &&
( ( ob j s [ i ] [ k−1]==−1) | | ( ob j s [ i ] [ k−1]==−2)))
{
ob j s [ i ] [ k−1]=0;
int veces3=1;
while ( ( veces3<(R. dur ( ) ) [ i ] ) && ( ( k − 1)−veces3>=0))
{
58
i f ( ob j s [ i ] [ ( k−1)−veces3 ]==−1)
{
ob j s [ i ] [ ( k−1)−veces3 ]=−2;
}
veces3++;
}
}
}
k++;
}
Para cada perıodo k se calcula la capacidad residual de la mochila, descontando elespacio utilizado por los objetos ya seleccionados. Esta capacidad residual se almacenaen la variable local cobjs y se emplea para revisar entre el resto de objetos libres(aquellos con valores −1 o −2 en la matriz de disponibilidad), si para algun objeto i supeso w[i] es mayor que la capacidad disponible. En este caso, se prohibe la presenciadel objeto en la mochila en el perıodo k(objs[i][k − 1] = 0), y se fija su valor dedisponibilidad a -2 durante los di − 1 perıodos anteriores.La siguiente etapa en el procesamiento de las disponibilidades consiste en restringir a 0la disponibilidad de todos los objetos que no tienen la posibilidad de ingresar los di−1perıodos anteriores.
//(3)De no haber posibilidad de ingreso en di − 1 perıodos, transformar los -2 en ceros
unsigned int i ;
unsigned int j ;
for ( i =0; i<ob j s . s i z e ( ) ; i++)
{
for ( j =0; j<ob j s [ i ] . s i z e ( ) ; j++)
{
i f ( ( ob j s [ i ] [ j ]==−2) &&
( ( j==0) | | ( ob j s [ i ] [ int ( j )−1]==1) | | ( ob j s [ i ] [ int ( j )−1]==0)))
{
while ( ob j s [ i ] [ j ]==−2 && j<ob j s [ i ] . s i z e ( ) )
{
ob j s [ i ] [ j ]=0;
j++;
}
}
}
}
En la primera etapa, se busca para cada objeto i el primer perıodo t en el cual i puede
estar presente en la mochila, pero no ingresar a esta (disponibilidad igual a -2). Si en
el perıodo t− 1 el objeto estaba prohibido (disponibilidad igual a 0) o estaba presente
en la mochila (disponibilidad igual a 1) entonces es seguro prohibir a i mientras su
59
disponibilidad sea -2:
objs[i][t] := 0, ∀t ≥ t mientras objs[i][t] = −2.
//(4)Prohibir la presencia de un objeto si no puede ingresar en
// los di − 1 perıodos anteriores
for (unsigned int i =0; i<ob j s . s i z e ( ) ; i++)
{
int veces2=0;
for (unsigned int j =0; j<ob j s [ i ] . s i z e ( ) ; j++)
{
i f ( ob j s [ i ] [ j ]==−2)
{
veces2++;
i f ( veces2>=(R. dur ( ) ) [ i ] )
{
ob j s [ i ] [ j ]=0;
}
}
else
{
veces2=0;
}
}
}
En la segunda etapa, se restringen a 0 las disponibilidades de un objeto i en todos
los perıodos t en los que i ha acumulado mas de di − 1 perıodos sucesivos con valor
de disponibilidad igual a -2 (puede estar en la mochila, pero no puede ingresar). Para
esto, se utiliza una variable local tipo entero veces2 en la que se almacena el numero
consecutivo de entradas iguales a −2 en la fila i de la matriz objs. Si este numero es
mayor o igual que la duracion del objeto i entonces,
objs[i][t] := 0, ∀t ≥ t mientras objs[i][t] = −2,
ya que objs[i][t1] 6= −1, ∀t1 ∈ {t− di + 1, ..., t− 1}.
//(5)Restringir a cero los espacios libres donde un objeto no puede
// entrar debido a su duracion
for (unsigned int i =0; i<ob j s . s i z e ( ) ; i++)
{
int veces =0;
for (unsigned int j =0; j<ob j s [ i ] . s i z e ( ) ; j++)
{
i f ( ( ob j s [ i ] [ j ]==−1) | | ( ob j s [ i ] [ j ]==−2))
60
{
veces++;
i f ( j==ob j s [ i ] . s i z e ()−1)
{
i f ( veces<(R. dur ( ) ) [ i ] )
{
while ( veces>0)
{
ob j s [ i ] [ j−(veces −1)]=0;
veces−−;
}
}
}
}
else
{
i f ( veces<(R. dur ( ) ) [ i ] )
{
while ( veces>0)
{
ob j s [ i ] [ j−veces ]=0;
veces−−;
}
}
else
{
veces =0;
}
}
}
}
En el ultimo paso del procesamiento de la matriz de disponibilidades, se restringena 0 todos los intervalos con entradas en {−1,−2} cuya longitud sea menor que laduracion del objeto. Para esto se emplea una variable local tipo entero veces en laque se almacena el numero consecutivo de entradas iguales a −1 o −2 para un objetodeterminado i. Cuando se produce un cambio de estado, es decir, cuando se encuentraun perıodo con un valor de disponibilidad distinto, se verifica el valor de veces. Sies mayor o igual que la duracion del objeto i entonces veces se reinicia veces := 0,caso contrario se restringen a 0 los valores de disponibilidad de todos los perıodos delintervalo.Terminado el preprocesamiento de la matriz objs, se procede con el calculo de la cotasuperior.
double a lgo r i tmos : : co ta super io rBB ( const ob je to s moch i l a d inamico&R,
vector<vector<int>>&objs ,
vector<vector<unsigned>>&X)
61
{
unsigned int tam=(R. r ( ) ) . s i z e ( ) ; // Cantidad total de objetos
unsigned int T=(R. T ( ) ) ; // Horizonte de tiempo
unsigned int p=1;
while (p<=T)
{
vector<unsigned>objHS ;
vector<int>usados ;
vector<double>a1 ; // valores
vector<double>a2 ; // pesos
vector<double>a3 ; // duraciones
vector<double>a4 ; // ındices de los objetos “activos”
objHS . r e s i z e (tam , 1 ) ;
usados . r e s i z e (tam , 0 ) ;
unsigned int num=0;
int cact=(R. c ( ) ) ;
for (unsigned int i =0; i<ob j s . s i z e ( ) ; i++)
{
i f ( ob j s [ i ] [ p−1]==1)
{
usados [ i ]=1;
objHS [ i ]=0;
cact=cact−(R. w ( ) ) [ i ] ;
num++;
}
else
{
i f ( ob j s [ i ] [ p−1]==0)
{
objHS [ i ]=0;
num++;
}
}
}
i f ( tam−num>0)
{
a1 . r e s i z e (tam−num) ;
a2 . r e s i z e (tam−num) ;
a3 . r e s i z e (tam−num) ;
a4 . r e s i z e (tam−num) ;
int w=0;
for (unsigned int i =0; i<objHS . s i z e ( ) ; i++)
{
i f ( objHS [ i ]==1)
{
a1 [w]=(R. p ( ) ) [ i ] ;
62
a2 [w]=(R. w ( ) ) [ i ] ;
a3 [w]=(R. dur ( ) ) [ i ] ;
a4 [w]= i +1;
w++;
}
}
ob je to s moch i l a d inamico A;
vector<int>s o l ;
s o l . r e s i z e ( tam−num, 0 ) ;
A. a s i g n a r v a l o r e s ( a1 , a2 , a3 , a4 , cact ,T) ;
double Valmax=0.0 ;
Valmax=HS(A, cact , s o l ) ;
for (unsigned int i =0; i<s o l . s i z e ( ) ; i++)
{
usados [ (A. ind ( ) ) [ i ]−1]= s o l [ i ] ;
}
}
for (unsigned int i =0; i<X. s i z e ( ) ; i++)
{
X[ i ] [ p−1]=usados [ i ] ;
}
p++;
}
double s1 =0.0 ;
for (unsigned int i =0; i<X. s i z e ( ) ; i++)
{
for (unsigned int j =0; j<X[ i ] . s i z e ( ) ; j++)
{
i f (X[ i ] [ j ]==1)
{
s1=s1+((R. p ( ) ) [ i ] / (R. dur ( ) ) [ i ] ) ;
}
}
}
return s1 ; // calcular y retornar el valor de la cota
}
La funcion cota superiorBB recibe como parametros los datos del problema en unobjeto tipo objetos mochila dinamico R, la matriz de disponibilidades objs y unamatriz por referencia X de enteros sin signo para retornar la solucion. Esta funcionverifica para cada perıodo dentro del horizonte de tiempo cuales son los objetos libres,es decir, aquellos con valores de disponibilidad {−1,−2}; y con estos calcula la cotasuperior U3. Para esto, la funcion HS es llamada T veces y se resuelve un problemaclasico de la mochila de manera independiente en cada perıodo de tiempo. Inicialmente,se crea una variable entera p que va a servir como contador de los perıodos desde 1hasta T, y se crean algunos vectores locales: uno de tipo entero sin signo objHS quese inicializa en 1 y que indica cuales objetos estan disponibles para ser usados en la
63
funcion HS; uno de tipo entero usados que se inicializa en 0 y registra cuales objetosestan en la mochila por decisiones tomadas anteriormente; y un entero local num quecuenta el numero total de objetos que no estan libres en el perıodo p. Los valores deestos vectores se inicializan a partir de los valores de la matriz de disponibilidades objs:cuando un objeto i esta en la mochila en algun perıodo t (objs[i][t] = 1), en el vectorobjHS se restringe el valor de este a 0, y en el vector usados se restringe su valor a 1.Ademas, se resta su peso w[i] de la capacidad actual de la mochila cact y se incrementael valor del contador de objetos no disponibles num. Cuando un objeto esta excluido(objs[i][t] = 0) entonces objsHS[i] = 0 y se incrementa tambien el valor de num.Luego, se crean cuatro vectores locales de tamano (n − num) para almacenar todoslos datos de los objetos disponibles para calcular la cota superior (objsHS[i] = 1).Se crea un objetos mochila dinamico A con estos vectores, la capacidad actual cacty el horizonte temporal T para calcular la solucion optima de KP-PD mediante unallamada a la funcion HS. Esta solucion se almacena en un vector local entero sol detamano (n − num). Finalmente, se registran los objetos seleccionados en el vectorusados, en sus posiciones originales, y se guarda esta solucion en la columna p de lamatriz solucion X. Al terminar la funcion, se calcula a partir de X el valor de la funcionobjetivo y se lo retorna como resultado de cota superiorBB.
bool a lgo r i tmos : : e s f a c t i b l e ( const ob je to s moch i l a d inamico& R,
const vector< vector<int> >& objs ,
const vector< vector<unsigned> >& X ,
const vector<double>&ind ,
bool& hubo branching , te rna& t1 , te rna& t2 )
{
bool i n f a c t i b l e= fa l se ;
unsigned int i ;
unsigned int j ;
for ( i =0; i<X. s i z e ( ) ; i++)
{
int veces =0;
for ( j =0; j<X[ i ] . s i z e ( ) ; j++)
{
i f (X[ i ] [ j ]==1)
{
veces++;
i f ( veces==(R. dur ( ) ) [ i ] )
{
veces =0;
}
i f ( j==X[ i ] . s i z e ()−1 && veces>0)
{
veces=veces −1;
i n f a c t i b l e=true ;
break ;
}
}
64
else i f ( veces>0)
{
i n f a c t i b l e=true ;
break ;
}
}
i f ( i n f a c t i b l e )
{
break ;
}
}
i f ( ! i n f a c t i b l e )
{
return true ;
}
// Si no es factible, buscar si es posible ramificar
.
.
.
La funcion es factible es de tipo binaria (retorna verdadero o falso) y recibe lossiguientes parametros: una variable R del tipo objetos mochila dinamico con losdatos del problema, la matriz de disponibilidades objs, la matriz solucion X calculadapor la funcion cota superiorBB, un vector de ındices ind que guarda el ordenamientode los objetos por valor para la tercera heurıstica de ramificacion, una variable detipo binaria hubo branching que servira para saber si fueron creadas nuevas ternas deramificacion y dos ternas por referencia t1 y t2 en las que se guardaran las decisionesde ramificacion. Se define una variable local tipo binaria infactible que se inicializa conel valor de “falso”. Luego se verifica para cada objeto i en la matriz solucion X que lasentradas iguales a 1 formen intervalos consecutivos de longitudes iguales a la duraciondur[i] del objeto. Si para algun objeto esto no se cumple entonces se fija el valor deinfactible a “verdadero” y se sigue con el proceso de ramificacion, caso contrario, lafuncion es factible retorna como solucion “verdadero”. Si la solucion X es infactiblese crean las ternas de ramificacion empleando las tecnicas explicadas en la Seccion 2.4.
// Si no es factible, buscar si es posible ramificar
for ( i =0; i<X. s i z e ( ) ; i++)
{
// Asignar las ternas t1 y t2
// Heurıstica de Ramificacion (1)
for ( int j 2=X[ i ] . s i z e ()−1; j2>=0; j2−−)
{
j=unsigned ( j 2 ) ;
i f ( ob j s [ i ] [ j ]==−1 && X[ i ] [ j ]==1)
{
65
t1 . i=i +1;
t1 . j=j +1;
t1 . k=1;
t2 . i=i +1;
t2 . j=j +1;
t2 . k=0;
hubo branching=true ;
return fa l se ;
}
}
// Heurıstica de Ramificacion (2)
/ f o r ( i n t j2=X[ i ] . s i z e ()−1; j2>=0; j2−−)
{
j=unsigned ( j2 ) ;
i f ( o b j s [ i ] [ j ]==−1)
{
t1 . i=i +1;
t1 . j=j +1;
t1 . k=1;
t2 . i=i +1;
t2 . j=j +1;
t2 . k=0;
hubo branching=t rue ;
re turn f a l s e ;
}
} /
// Heurıstica de Ramificacion (3)
/ f o r ( i n t j2=X[ i ] . s i z e ()−1; j2>=0; j2−−)
{
j=unsigned ( j2 ) ;
i f ( o b j s [ ind [ i ] −1][ j ]==−1 && X[ ind [ i ] −1][ j ]==1)
{
t1 . i=ind [ i ] ;
t 1 . j=j +1;
t1 . k=1;
t2 . i=ind [ i ] ;
t 2 . j=j +1;
t2 . k=0;
hubo branching=t rue ;
re turn f a l s e ;
}
} /
}
hubo branching=fa l se ;
return fa l se ;
}
66
La primera heurıstica de ramificacion examina las matrices objs y X desde arriba haciaabajo y de derecha a izquierda hasta encontrar el primer objeto i y el primer perıodo jpara los cuales objs[i][j] = −1 y X [i][j] = 1, entonces se generan las ternas t1(i, j, 1) yt2(i, j, 0). La segunda heurıstica busca el primer objeto y el primer perıodo desde arribahacia abajo y de derecha a izquierda, para los cuales objs[i][j] = −1, y se generan lasternas de decision t1(i, j, 1) y t2(i, j, 0). Finalmente, la tercera heurıstica emplea elvector ind que ordena a los objetos por su valor, y busca el primer objeto y el primerperıodo para los cuales objs[i][j] = −1 y X[i][j] = 1 desde el objeto con mas valorhasta el de menor valor y de derecha a izquierda los perıodos temporales. Cuando seencuentra la condicion entonces se generan de igual manera las ternas de ramificacion.
double a lgo r i tmos : : branch and bound (unsigned int C, unsigned int T,
const vector<double>&va lo r e s ,
const vector<double>&pesos ,
const vector<double>&durac iones )
{
vec to r < vec to r <unsigned> > X, X best ; // Mejor Solucion Entera
vec to r < vec to r <int> > ob j s ;
X best . r e s i z e ( v a l o r e s . s i z e ( ) ) ;
for (unsigned int i =0; i<X best . s i z e ( ) ; i++)
{
X best [ i ] . r e s i z e (T, 0 ) ;
}
X. r e s i z e ( v a l o r e s . s i z e ( ) ) ;
for (unsigned int i =0; i<X. s i z e ( ) ; i++)
{
X[ i ] . r e s i z e (T) ;
}
vector<double>i n d i c e s ;
i n d i c e s . r e s i z e ( v a l o r e s . s i z e ( ) , 0 ) ;
for (unsigned int i =0; i<va l o r e s . s i z e ( ) ; i++)
{
i n d i c e s [ i ]= i +1;
}
ob je to s moch i l a d inamico R;
R. a s i g n a r v a l o r e s ( va l o r e s , pesos , durac iones , i nd i c e s ,C,T) ;
R. qu ickSor t (0 , v a l o r e s . s i z e ()−1);
vector<double>m, n ;
m. r e s i z e ( v a l o r e s . s i z e ( ) , 0 ) ;
n . r e s i z e ( v a l o r e s . s i z e ( ) , 0 ) ;
for (unsigned int i =0; i<va l o r e s . s i z e ( ) ; i++)
{
m[ i ]=(R. p ( ) ) [ i ] ;
n [ i ]= i +1;
}
quickSor t (m, n , 0 , v a l o r e s . s i z e ()−1);
67
// Llamar a HS modificado para construir una solucion factible
// Calcular la mejor solucion estatica
vector<int>s o l 1 ;
s o l 1 . r e s i z e ( v a l o r e s . s i z e ( ) , 0 ) ;
HS(R,C, s o l 1 ) ;
// Poner la primera mejor solucion en X best
for (unsigned int i =0; i<X best . s i z e ( ) ; i++)
{
i f ( s o l 1 [ i ]==1)
{
unsigned int veces ;
veces =(( int ) (T/(R. dur ( ) ) [ i ] ) ) (R. dur ( ) ) [ i ] ;
for (unsigned int j =0; j<X best [ i ] . s i z e ( ) ; j++)
{
i f ( j<veces )
{
X best [ i ] [ j ]= s o l 1 [ i ] ;
}
}
}
}
// Calcular el valor de X best y ponerlo en z max
double z max=0.0 ;
for (unsigned int i =0; i<=so l 1 . s i z e ()−1; i++)
{
i f ( s o l 1 [ i ]==1)
{
z max=z max+(( int ) ( (R. T ( ) ) / (R. dur ( ) ) [ i ] ) ) (R. p ( ) ) [ i ] ;
}
}
l i s t < l i s t <terna> > Q;
// Crear lista inicial
l i s t <terna> L ;
// ... Llenar L ...
for (unsigned int i =0; i<X best . s i z e ( ) ; i++)
{
for (unsigned int j=T−(R. dur ( ) ) [ i ]+1; j<X best [ i ] . s i z e ( ) ; j++)
{
te rna dec ( i +1, j +1 ,0) ;
L . push back ( dec ) ;
}
}
Q. push f r ont (L ) ;
68
// Lazo principal B&B
while ( !Q. empty ( ) )
{
l i s t <terna> L nodo ;
L nodo=Q. f r o n t ( ) ;
Q. pop f r ont ( ) ;
// Procesar nodo, usando L nodo, llamar a cota superior
double z =0.0 ;
z=cota super io rBB (L nodo ,R, objs ,X) ;
// Si el nodo no tiene posibilidad de mejorar la solucion, desecharlo (poda)
i f ( int ( z)<=z max )
{
continue ;
}
// Caso contrario, verificar si la solucion es factible
te rna t1 ( 0 , 0 , 0 ) , t2 ( 0 , 0 , 0 ) ;
// La funcion es factible retorna true si X es factible y false caso contrario
// En el segundo caso retorna ademas dos ternas para la ramificacion
bool hubo branching ;
i f ( e s f a c t i b l e (R, objs ,X, n , hubo branching , t1 , t2 ) )
{
// Actualizar la mejor solucion
z max=z ;
for (unsigned int i =0; i<X best . s i z e ( ) ; i++)
{
for (unsigned int j =0; j<X best [ i ] . s i z e ( ) ; j++)
{
X best [ i ] [ j ]=X[ i ] [ j ] ;
}
}
}
else
{
i f ( ! hubo branching )
{
continue ;
}
// Si es necesario ramificar, generar dos listas L1 y L2
// Hacer dos copias de L nodo en nuevas listas L1 y L2
l i s t <terna> L1 , L2 ;
// Llenar L1 y L2 con las decisiones de ramificacion (copiar elementos de L nodo)
for ( l i s t <terna > : : c o n s t i t e r a t o r i t=L nodo . beg in ( ) ;
i t !=L nodo . end ( ) ; i t++)
{
L1 . push back ( i t ) ;
L2 . push back ( i t ) ;
69
}
// Luego poner cada una de las ternas nuevas al final de L1 y L2
L1 . push back ( t1 ) ;
L2 . push back ( t2 ) ;
// Agregar las nuevas listas a la cola
Q. push f r ont (L2 ) ;
Q. push f r ont (L1 ) ;
}
}
return z max ;
}
La funcion branch and bound implementa el esquema KPD-BB creado para el proble-
ma KP-DUR y descrito en la Seccion 2.4. Esta funcion recibe como parametros todos
los datos del problema: un entero sin signo C que es la capacidad de la mochila, un en-
tero sin signo T que es el horizonte temporal sobre el que se va a maximizar el valor de
la funcion objetivo, un vector de elementos de tipo flotante valores que almacena todos
los valores de los objetos, un vector de elementos de tipo flotante pesos que almacena
todos los pesos de los objetos y un vector de elementos de tipo flotante duraciones
con todos las duraciones de los objetos. El numero de objetos n esta implicitamente
dado por la dimension de los tres vectores anteriores. Como primer paso, se crean e
inicializan las matrices X y X best ∈ {0, 1}n×T donde X best[i][j] = 0, ∀i, j, que seran
las matrices de la solucion actual y de la mejor solucion obtenida hasta el momento
respectivamente. Ademas, se crean un vector local de indices que guardara el ordena-
miento inicial de los objetos, y una variable tipo objetos mochila dinamico R para
almacenar en esta todos los datos del problema. Luego se realiza el primer ordena-
miento de los objetos llamando a la funcion quickSort, la misma que ordena todos los
vectores del objetos mochila dinamico R de acuerdo a (2.38).
Posteriormente, se crean dos vectores m y n. En m se almacenan todos los valores de
los objetos y en n se guardan nuevos ındices de posicionamiento. Mediante una llama-
da a la funcion global quickSort se ordena el vector m en forma descendente, y se
almacenan los ındices de este ordenamiento en n, los mismos que seran utilizados por
la funcion es factible en la heurıstica de ramificacion 3.
Como paso siguiente, se calcula la mejor solucion inicial de acuerdo al procedimiento
explicado en la Subseccion 2.2.4. Tras una llamada a la funcion HS, la solucion obte-
nida para el problema estatico KP-PD se guarda en el vector sol1. Luego cada objeto
escogido en sol1 se repite el numero de veces que su duracion lo permita dentro del ho-
rizonte temporal T y se obtiene ası una solucion factible para KP-DUR. Esta solucion
se guarda en X best y su valor en zmax, una variable local de tipo punto flotante. Por
ultimo, se crea la lista de listas de ternas Q y una primera lista de ternas L que alma-
cena todas las decisiones triviales dadas por (2.11). Luego de agregar L a Q empieza
70
el lazo principal del esquema KPD-BB.
Mientras la lista de listas Q no este vacıa, el algoritmo retira la primera lista de Q y
la almacena en la variable L nodo, la lista de desiciones asociadas al nodo actual del
esquema branch-and-bound. Se calcula la cota superior asociada a esta lista llaman-
do a la funcion cota superiorBB. El valor de la solucion actual se almacena en una
variable local de tipo de punto flotante z. Entonces, se verifica si el valor entero de la
solucion actual es menor al de la mejor solucion hasta el momento, (⌊z⌋ ≤ z max). Si
se cumple esta condicion, se desecha la lista actual y la iteracion termina. Caso con-
trario, se verifica que la matriz solucion X obtenida en cota superiorBB sea factible
mediante la funcion es factible. De ser ası, se actualiza el valor de la mejor solucion
obtenida hasta el momento ası como su matriz solucion asociada (z max,X best) y la
iteracion termina. Caso contrario, la funcion es factible retorna las nuevas ternas de
ramificacion (t1, t2) y se crean dos nuevas listas de ternas L1, L2 que contienen todas
las decisiones de la lista actual L nodo, ademas de cada una de las nuevas ternas, t1
y t2, respectivamente. Estas listas se agregan al inicio de Q (exploracion primero en
profundidad), y la iteracion termina. La funcion termina cuando no existen listas de
ternas por procesar y retorna el valor de la mejor solucion encontrada.
71
Capıtulo 4
Resultados Numericos
4.1 Construccion de instancias de prueba
Para analizar el desempeno practico del algoritmo propuesto en este proyecto de titu-
lacion, se utilizaron instancias construidas mediante la modificacion de un algoritmo
de generacion de instancias para la version clasica de KP elaborado por David Pisinger
[17]. Se realizaron cambios al mismo para que construya instancias para KP-DUR agre-
gando duraciones a los objetos y un horizonte temporal T . El algoritmo de generacion
utiliza dos parametros: un entero n que indica el numero de objetos y un entero R en
funcion del cual se definen todas las demas variables del problema; la capacidad de la
mochila C, el horizonte temporal T , y los valores, pesos y duraciones de los objetos.
Este algoritmo genera tres tipos de instancias:
1. No correlacionadas, en las cuales C = 3R, T = R, y los valores, pesos y dura-
ciones son generados independentemente simulando distribuciones uniformes de
probabilidad:
pj U[1,R], ∀j ∈ {1, ..., n},
wj U[1,R], ∀j ∈ {1, ..., n},
dj U[1,R], ∀j ∈ {1, ..., n}.
2. Debilmente correlacionadas, en las cuales C = 3R, T = ⌈1,1R⌉, y los valores,
pesos y duraciones son generados como se indica a continuacion:
pj U[1,R], ∀j ∈ {1, ..., n},
wj U[pj− R10
,pj+R10 ]
, ∀j ∈ {1, ..., n},
dj U[pj− R10
,pj+R10 ]
, ∀j ∈ {1, ..., n}.
72
3. Fuertemente correlacionadas, en las cuales C = 3R, T = ⌈2,1R⌉, y los valores,
pesos y duraciones se generan por medio de:
pj U[1,R], ∀j ∈ {1, ..., n},
wj pj +R
10, ∀j ∈ {1, ..., n},
dj 2pj +R
10, ∀j ∈ {1, ..., n}.
Con este generador se construyeron 27 instancias de prueba para KP-DUR, las cuales
se detallan en el Cuadro 4.1.
R
n Tipo 10 20 50
Instan
cias
20
1 Instancia 1 Instancia 4 Instancia 7
2 Instancia 2 Instancia 5 Instancia 8
3 Instancia 3 Instancia 6 Instancia 9
50
1 Instancia 10 Instancia 13 Instancia 16
2 Instancia 11 Instancia 14 Instancia 17
3 Instancia 12 Instancia 15 Instancia 18
100
1 Instancia 19 Instancia 22 Instancia 25
2 Instancia 20 Instancia 23 Instancia 26
3 Instancia 21 Instancia 24 Instancia 27
Cuadro 4.1: Instancias de prueba para KP-DUR.
4.2 Evaluacion de las cotas KP-PD vs. CKP-CT
En el capıtulo anterior se estudio la implementacion del algoritmo branch-and-bound
KPD-BB contruido para resolver instancias del problema KP-DUR. Para el mismo, las
cotas superiores en cada nodo del arbol de busqueda pueden construirse a partir del
problema KP-PD o del problema CKP-CT, como se indico en el Capitulo 2. Luego
de comparar las cotas obtenidas sobre las 27 instancias, se decidio utilizar las cotas
construidas a partir del problema KP-PD, ya que los resultados alcanzados fueron de
mayor calidad para un tiempo de calculo similar. En el Cuadro 4.2 se detallan los re-
sultados comparativos. Estos resultados se obtuvieron en una maquina con procesador
AMD Athlon(tm) X2 Dual-Core QL-64 2.10 GHz con memoria RAM de 4.00 GB y
un sistema operativo Windows 7 de 64 bits. El codigo fue compilado empleando el
compilador GNU GCC version 4.5.2.
73
Instancia Cota KP-PD Tiempo HSD Cota CKP-CT Tiempo CID
1 193 0 193 0
2 99 0 101 0
3 123 0 132 0
4 644 0 645 0
5 302 0 310 0
6 310 0 321 0
7 1406 0 1419 0
8 626 0 653 0
9 646 0 676 0
10 364 0 364 0
11 210 0 212 0
12 180 0 186 0
13 1172 0 1185 0
14 596 0 599 0
15 422 0.005 428 0
16 2417 0 2452 0
17 1830 0 1843 0
18 927 0.001 979 0.001
19 615 0 619 0
20 275 0 275 0
21 298 0 304 0
22 1792 0 1795 0
23 899 0 899 0
24 645 0.001 655 0
25 3600 0 3603 0
26 2458 0 2462 0
27 1491 0.001 1543 0
Cuadro 4.2: Comparacion de eficiencia y tiempos de calculo Cotas KP-PD vs. CKP-CT.
4.3 Resultados computacionales esquema KPD-BB
En esta seccion estudiaremos el comportamiento del algoritmo KPD-BB en las ins-
tancias anteriormente mencionadas. Comparamos el tiempo de calculo y los resultados
obtenidos por nuestro algoritmo frente a los de la implementacion del modelo KP-
DUR en el solver para programas enteros SCIP version 2.01, configurado en su forma
estandar [1].
74
Instancia
Solu
cion
KPD-B
BCotaKPD-B
BGap
KPD-B
BTiem
po
KPD-B
BSolu
cion
SCIP
CotaSCIP
Gap
SCIP
Tiem
po
SCIP
1181
193
0.06
1181
181
01
295
99
0.04
670
95
95
00
3119
123
0.03
3600
120
120
05
4631
644
0.02
6631
631
01
5284
302
0.06
3600
287
287
03
6289
310
0.07
3600
294
294
032
71332
1406
0.05
3600
1332
1332
046
8569
626
0.1
3600
585
585
0103
9598
646
0.08
3600
630
630
045
10
349
364
0.04
57
349
349
03
11
204
210
0.02
3600
206
206
05
12
178
180
0.01
3600
178
178
06
13
1163
1172
0.007
3167
1163
1163
08
14
579
596
0.02
3600
585
585
0260
15
395
422
0.06
3600
403
403
01124
16
2274
2417
0.06
3600
2282
2282
0326
17
1767
1830
0.03
3600
1798
1811
0.007
3600
18
860
927
0.07
3600
905
919
0.01
3600
19
606
615
0.01
3600
609
609
04
20
274
275
0.003
183
274
274
04
21
294
298
0.01
3600
295
295
027
22
1768
1792
0.01
3600
1771
1771
021
23
885
899
0.01
3600
894
894
0159
24
616
645
0.04
3600
624
624
0575
25
3488
3600
0.03
3600
3489
3512
0.006
3600
26
2415
2458
0.01
3600
2424
2443
0.008
3600
27
1406
1491
0.06
3600
1416
1493
0.05
3600
Cuad
ro4.3:
Com
paracionderesultad
osytiem
pos
decalculo
deKPD-B
Bvs.SCIP
enlas27
instan
cias
deprueba.
75
En el Cuadro 4.3 se presentan los resultados generales comparativos entre los resultados
del algoritmo KPD-BB con los obtenidos por SCIP. Las primeras cuatro columnas indi-
can, en este orden, la mejor solucion alcanzada por el algoritmo KPD-BB, la mejor cota
superior, la brecha de optimalidad (gap) y el tiempo requerido por este algoritmo. Las
ultimas cuatro columnas reportan los valores correspondientes para la implementacion
de SCIP. La brecha de optimalidad se define como:
gap =cota superior - mejor solucion alcanzada
mejor solucion alcanzada.
Discutiremos a continuacion en mas detalle algunas instancias relevantes.
El comportamiento de los algoritmos para la instancia 14 esta detallado en la Figura
4.1. Esta instancia es del tipo debilmente correlacionada, con n = 50 y R = 20. Pode-
mos notar que el valor de la cota superior KP-PD es de 596, encontrada en t = 0s y
es muy cercano al valor de la cota obtenida por SCIP, cuyo valor es de 589 en t = 1s.
La primera solucion factible encontrada mediante la heurıstica primal tuvo un valor de
566 obtenida en el tiempo t = 0s mientras que la primera solucion factible encontrada
por SCIP en el tiempo t = 10s tiene un valor de 580. Dentro del perıodo de 1 hora
KPD-BB encontro una solucion factible con un valor de 579, que es un 1% menor al
valor 585 de la solucion optima encontrada por SCIP en t = 260s. Para esta prueba,
en el algoritmo KPD-BB se uso la primera heurıstica en la toma de decisiones de ra-
mificacion.
Al resolver la misma instancia 14 con la heurıstica de ramificacion 2 (Figura 4.2), se
encuentra una mejor solucion a la de la heurıstica primal de manera instantanea con
un valor de 568 en t = 0s. En el resto del tiempo de calculo se encontraron soluciones
similares a las obtenidas con la heurıstica de ramificacion 1 en tiempos similares, la
solucion final encontrada tiene tambien el valor de 579.
La Figura 4.3 muestra el comportamiento de nuestro algoritmo en la instancia 14
con la heurıstica de ramificacion 3. Podemos observar que el rendimiento del esquema
disminuye de manera substancial: despues de la primera solucion encontrada mediante
la heurıstica primal el esquema encuentra la siguiente solucion factible en el tiempo
t = 1117s con un valor de 567, y esta solucion no consigue ser mejorada dentro del
tiempo restante de calculo.
En la Figura 4.4 se reportan los resultados obtenidos por los algoritmos SCIP y KPD-
BB para la instancia 15. Para KPD-BB se emplea la primera heurıstica de ramificacion.
Esta instancia es del tipo fuertemente correlacionada con n = 50 y R = 20. Podemos
observar que el valor de la cota superior KP-PD fue de 422 encontrada en t = 0s que
es un 2% mayor a la obtenida por SCIP, con un valor de 408 en t = 6s. La primera
solucion factible encontrada mediante la heurıstica primal tuvo un valor de 391 obteni-
76
Figura 4.1: Comportamiento de los algoritmos para la instancia 14, heurıstica de ra-mificacion 1.
Figura 4.2: Comportamiento de los algoritmos para la instancia 14, heurıstica de ra-mificacion 2.
77
Figura 4.3: Comportamiento de los algoritmos para la instancia 14, heurıstica de ra-mificacion 3.
Figura 4.4: Comportamiento de los algoritmos para la instancia 15, heurıstica de ra-mificacion 1.
78
Figura 4.5: Comportamiento de los algoritmos para la instancia 15, heurıstica de ra-mificacion 2.
da en el tiempo t = 0s mientras que la primera solucion factible encontrada por SCIP
en el tiempo t = 8s tuvo un valor de 391. KPD-BB encontro una solucion factible con
un valor de 395 en el tiempo t = 23s la misma que no pudo ser mejorada en todo el
perıodo de calculo. Esta solucion es un 1% menor que la solucion optima encontrada
por el SCIP en t = 20s, de valor 403, que fue verificada como optima en t = 1124s.
Puede notarse que los primeros resultados obtenidos mediante la heurıstica primal y la
cota superior de KPD-BB son competitivos con aquellos obtenidos por SCIP, tomando
en cuenta su valor y su tiempo de calculo. Sin embargo, el esquema tiene problemas
para “cubrir el ultimo tramo” de la brecha de optimalidad (por lo general, menor al
5%). Esto puede deberse a la simetrıa de las soluciones factibles, la misma que fuerza
a KPD-BB a desperdiciar tiempo de calculo explorando soluciones de igual valor. Esto
ocurre sobre todo en las instancias del tipo fuertemente correlacionadas.
Al resolver la instancia 15 utilizando en KPD-BB la heurıstica de ramificacion 2 (Fi-
gura 4.5), se consigue encontrar la solucion de valor 395 en t = 21s, y esta fue la mejor
solucion encontrada durante el resto del tiempo de calculo.
Al resolver la instancia 15 utilizando en KPD-BB la heurıstica de ramificacion 3 (Fi-
gura 4.6), se observa nuevamente que el rendimiento del esquema disminuye de manera
substancial. Despues de la primera solucion encontrada mediante la heurıstica primal,
79
Figura 4.6: Comportamiento de los algoritmos para la instancia 15, heurıstica de ra-mificacion 3.
el esquema no encontro ninguna solucion de mejor valor en todo el tiempo de calculo
permitido.
En la Figura 4.7 se muestran los resultados de SCIP y KPD-BB con la primera
heurıstica de ramificacion para la instancia 24. Esta instancia es del tipo fuertemente
correlacionada con n = 100 y R = 20. El valor de la cota superior KP-PD encontrada
en t = 0s es de 645, que es mayor al de la obtenida por el algoritmo del SCIP con un
valor de 626 en t = 19s. La primera solucion factible encontrada mediante la heurıstica
primal tuvo un valor de 612, obtenida en el tiempo t = 0s, mientras que la primera
solucion factible encontrada por el SCIP tuvo un valor de 615 en el tiempo t = 64s.
KPD-BB encontro algunas soluciones factibles de mejor valor, pero la ultima solucion
encontrada tuvo un valor de 616 en t = 560s. Por otra parte, SCIP encontro una so-
lucion factible de valor 624 en t = 493s que fue verificada como solucion optima en
t = 575s. Podemos notar que, conforme aumenta el tamano de la instancia (numero
de objetos y horizonte temporal), SCIP tarda mas tiempo en encontrar una primera
solucion factible y una cota superior para la misma. En contraste, KPD-BB mantiene
su propiedad de encontrar cotas y soluciones factibles de forma casi instantanea.
Al resolver la instancia 24 con la heurıstica de ramificacion 2 (Figura 4.8), se consigue
encontrar una solucion de valor 614 en t = 7s, y una solucion de valor igual a 616 en
80
Figura 4.7: Comportamiento de los algoritmos para la instancia 24, heurıstica de ra-mificacion 1.
Figura 4.8: Comportamiento de los algoritmos para la instancia 24, heurıstica de ra-mificacion 2.
81
Figura 4.9: Comportamiento de los algoritmos para la instancia 24, heurıstica de ra-mificacion 3.
t = 781s, la cual no puede ser mejorada en el tiempo restante de calculo. Podemos
ver una tendencia particular entre la heurıstica 1 y 2: la primera encuentra las mismas
soluciones en menor tiempo de calculo.
Al resolver la misma instancia 24 con la heurıstica de ramificacion 3 (Figura 4.9), se
sigue observando el mismo comportamiento anteriormente mencionado en cuanto a la
disminucion del rendimiento del esquema. Despues de la primera solucion encontrada
mediante la heurıstica primal el esquema no encontro ninguna mejor solucion en todo
el tiempo de calculo permitido.
En la Figura 4.10 se presentan los resultados de los algoritmos obtenidos para la ins-
tancia 25. Esta instancia es del tipo no correlacionada con n = 100 y R = 50. El valor
de la cota superior KP-PD encontrada en t = 0s fue 3600 que es mayor al de la obte-
nida por el algoritmo del SCIP en t = 31s con un valor de 3512. La primera solucion
factible encontrada mediante la heurıstica primal tuvo un valor de 3423, obtenida en el
tiempo t = 0s mientras que la primera solucion factible encontrada por el SCIP tuvo
un valor de 3266 en el tiempo t = 463s. KPD-BB encontro mejores soluciones factibles
de valores 3485 en t = 2s, y 3488, en t = 59s. SCIP encontro algunas soluciones du-
rante el tiempo de calculo permitido; en t = 1453s encontro una solucion factible de
valor 3469, y en t = 3379 encontro una solucion con valor 3489 que al cabo de todo el
82
Figura 4.10: Comportamiento de los algoritmos para la instancia 25, heurıstica deramificacion 1.
tiempo de calculo permitido se reporto como la mejor solucion encontrada. Se vuelve a
observar que conforme la complejidad del problema aumenta, SCIP tarda mas tiempo
en encontrar soluciones factibles y cotas superiores para el mismo. En este caso, la
primera cota superior encontrada no se pudo mejorar y se mantuvo constante durante
todo el tiempo de calculo. La mejor solucion encontrada tomo en comparacion con la
de KPD-BB una gran cantidad de tiempo de calculo. KPD-BB encuentra una solucion
primal y una cota superior competitivas con las encontradas por SCIP de manera casi
instantanea.
Al resolver la instancia 25 con la heurıstica de ramificacion 2 (Figura 4.11), se encon-
traron dos soluciones factibles mas y la ultima solucion encontrada dentro del tiempo
de calculo tuvo un valor de 3488, obtenida en t = 83s. Corroboramos que la primera
heurıstica de ramificacion encuentra la misma solucion que la segunda heurıstica en
menor tiempo de calculo, y se consolida la tendencia observada de que entre las tres
heurısticas la primera conduce a un esquema mas eficiente.
Al resolver la misma instancia 25 con la heurıstica de ramificacion 3 (Figura 4.12),
el rendimiento del esquema disminuye nuevamente. Luego de la primera solucion en-
contrada mediante la heurıstica primal con valor 3423 el esquema no encontro ninguna
mejor solucion en todo el tiempo de calculo permitido.
83
Figura 4.11: Comportamiento de los algoritmos para la instancia 25, heurıstica deramificacion 2.
Figura 4.12: Comportamiento de los algoritmos para la instancia 25, heurıstica deramificacion 3.
84
Figura 4.13: Comportamiento de los algoritmos para la instancia 27, heurıstica deramificacion 1.
En la Figura 4.13 se presentan los resultados para la instancia 27, que es del tipo
fuertemente correlacionada con n = 100 y R = 50. El valor de la cota superior KP-PD
encontrada en t = 0s es de 1491, que es menor al de la ultima cota obtenida por SCIP,
cuyo valor es de 1493 en t = 1411s. La primera cota superior obtenida por SCIP tuvo
un valor de 1504 en t = 135s. La primera solucion factible encontrada mediante la
heurıstica primal tiene un valor de 1400 obtenida en el tiempo t = 1s mientras que
la primera solucion factible encontrada por SCIP tiene un valor de 1400 en el tiempo
t = 1411s. KPD-BB encontro una solucion factible de mejor valor 1406 en t = 47s y
esta no pudo ser mejorada dentro del tiempo de calculo permitido. SCIP encontro una
solucion factible mas durante todo el tiempo de calculo permitido cuyo valor es de 1416,
obtenida en t = 2627s. Se corrobora nuevamente que para instancias de gran tamano,
KPD-BB encuentra de forma eficiente soluciones factibles y cotas superiores de valores
similares a aquellas obtenidas por SCIP en un tiempo de calculo considerablemente
mayor. La simetrıa de soluciones sigue demostrando ser un problema para el esquema
planteado ya que no permite explorar el arbol de decisiones de manera mas eficiente.
Al resolver la instancia 27 con la heurıstica de ramificacion 2 (Figura 4.14), KPD-BB
encontro dos soluciones factibles de mayor valor al de la solucion inicial. La solucion
final encontrada tuvo un valor de 1406 en t = 36s, en este caso la segunda heurıstica
85
Figura 4.14: Comportamiento de los algoritmos para la instancia 27, heurıstica deramificacion 2.
de ramificacion encontro la solucion en menor tiempo que la primera.
Al resolver la misma instancia 27 con la heurıstica de ramificacion 3 (Figura 4.15),
el rendimiento del esquema disminuye otra vez notoriamente. No se pudo mejorar el
valor de la solucion factible inicial en todo el tiempo de calculo permitido. De los ex-
perimentos conducidos, se puede concluir que la tercera heurıstica de ramificacion al
parecer siempre presenta desventajas para el esquema KPD-BB.
4.4 Combinando SCIP y KP-PD
Los experimentos computacionales de la seccion precendente permiten concluir que el
esquema KPD-BB encuentra rapidamente cotas superiores y soluciones primales de un
valor aceptable, pero que generalmente no consigue cerrar la brecha de optimalidad
dentro de un tiempo de calculo razonable. Por el contrario, SCIP es mas eficiente
reduciendo la brecha de optimalidad pero requiere de un mayor tiempo de calculo para
encontrar la primera solucion factible, sobre todo en instancias grandes (por ejemplo, en
las instancias 22 a la 27). En este sentido, es natural preguntarse si el comportamiento
de SCIP puede ser mejorado al utilizar nuestra heurıstica primal para crear una solucion
inicial.
86
Figura 4.15: Comportamiento de los algoritmos para la instancia 27, heurıstica deramificacion 3.
En esta seccion estudiaremos el comportamiento del modelo KP-DUR implementado
en SCIP agregando una solucion inicial al mismo en las 27 instancias del Cuadro 4.1.
Comparamos el tiempo de calculo y los resultados obtenidos por SCIP cuando parte de
una solucion inicial obtenida mediante la heurıstica primal KP-PD, frente al modelo
general implementado en la seccion anterior. En ambos casos utilizamos la version 3.1
de SCIP, debido a que la interfaz C++ de la version 2.01 presento problemas tecnicos
que impidieron la integracion con nuestro codigo.
En el Cuadro 4.4 se muestran los resultados comparativos entre SCIP con solucion
inicial vs. SCIP. En algunas instancias se registro un notable mejoramiento en el tiempo
de calculo y soluciones obtenidas. Por ejemplo, para la instancia 21 el tiempo de calculo
se redujo de 1093s a 2s. Sin embargo, en la mayorıa de instancias el comportamiento
fue similar y existen algunas instancias (por ejemplo, las instancias 15 y 24) para las
cuales el uso de la heurıstica primal solo empeoro el comportamiento de SCIP. Son
necesarias nuevas investigaciones para explicar este comportamiento.
87
Instancia SCIP Tiempo SCIP SCIP SOL. INI Tiempo SCIP SOL. INI
1 181 0 181 02 95 0 95 03 120 0 120 04 631 0 631 05 287 1 287 16 294 2 294 27 1332 10 1332 138 585 16 585 169 630 5 630 310 349 1 349 111 206 0 206 012 178 1 178 113 1163 1 1163 114 585 29 585 2715 403 558 403 68816 2282 26 2282 2917 1801 3600 1802 360018 911 1333 911 106219 609 0 609 020 274 0 274 021 295 1093 295 222 1771 2 1771 423 894 17 894 3624 624 24 624 5025 3505 3600 3505 360026 2435 3600 2431 360027 1452 3600 1472 3600
Cuadro 4.4: Comparacion de eficiencia y tiempos de calculo SCIP vs. SCIP con solucioninicial.
88
Referencias
[1] Tobias Achterberg. Scip: Solving constraint integer programs. Mathematical Pro-
gramming Computation, 1(1):1–41, 2009. http://mpc.zib.de/index.php/MPC/
article/view/4.
[2] E. Balas and E. Zemel. An algorithm for large zero-one knapsack problems. Math.
Oper. Res., 28(5):1130–1154, 1980.
[3] Mark Bartlett, Alan Frisch, Youssef Hamadi, Ian Miguel, S. Tarim, and Chris
Unsworth. The temporal knapsack problem and its solution. In Roman Bartak
and Michela Milano, editors, Integration of AI and OR Techniques in Constraint
Programming for Combinatorial Optimization Problems, volume 3524 of Lecture
Notes in Computer Science, pages 34–48. Springer Berlin / Heidelberg, 2005.
[4] Richard Bellman. Dynamic Programming. Princeton University Press, Princeton,
NJ, USA, 1 edition, 1957.
[5] G. Dantzig. Discrete variable extremum problems. Math. Oper. Res., 5(2):266–
277, April 1957.
[6] Michael R. Garey and David S. Johnson. Computers and Intractability: A Guide
to the Theory of NP-Completeness. W. H. Freeman & Co., New York, NY, USA,
1979.
[7] P. Gilmore and R. Gomory. A linear programming approach to the cutting stock
problem. Math. Oper. Res., 9(6):849–859, November 1999.
[8] Teofilo F. Gonzalez. Handbook of Approximation Algorithms and Metaheuristics.
Chapman & Hall/Crc Computer & Information Science Series. Chapman & Ha-
ll/CRC, Boca Raton, 2007.
[9] Ellis Horowitz and Sartaj Sahni. Computing partitions with applications to the
knapsack problem. J. ACM, 21:277–292, April 1974.
[10] Oscar H. Ibarra and Chul E. Kim. Fast approximation algorithms for the knapsack
and sum of subset problems. J. ACM, 22(4):463–468, October 1975.
89
[11] Richard M. Karp. Reducibility among combinatorial problems. In Raymond E.
Miller and James W. Thatcher, editors, Complexity of Computer Computations,
The IBM Research Symposia Series, pages 85–103. Plenum Press, New York, 1972.
[12] H. Kellerer, U. Pferschy, and D. Pisinger. Knapsack Problems. Springer, Germany,
2004.
[13] S. Martello and P. Toth. An upper bound for the zero-one knapsack problem
and a branch and bound algorithm. European Journal of Operational Research,
1(3):169–175, May 1977.
[14] S. Martello and P. Toth. Knapsack Problems: Algorithms and Computer Imple-
mentations. Wiley, New York, NY, USA, 1990.
[15] J. D. Papastavrou, S. Rajagopalan, and A. J. Kleywegt. The dynamic and sto-
chastic knapsack problem with deadlines. Management Science, 42:1706–1718,
December 1996.
[16] R. Parra-Hernandez, D. Vanderster, and N. J. Dimopoulos. Resource management
and knapsack formulations on the grid. In Proceedings of the 5th IEEE/ACM In-
ternational Workshop on Grid Computing, GRID ’04, pages 94–101, Washington,
DC, USA, 2004. IEEE Computer Society.
[17] David Pisinger. David pisinger’s optimization codes. http://www.diku.dk/
~pisinger/codes.html.
[18] Vijay V Vazirani. Approximation algorithms. Springer, Berlin, 2001.
90