Knapsack Problem Optimization: LP Relaxation, Greedy, and Local Search Implementation

Classified in Spanish

Written on in English with a size of 4.42 KB

Knapsack Problem Solution Methods

This implementation demonstrates several methods for solving the Knapsack Problem, including Linear Programming (LP) relaxation, the Dantzig heuristic, the standard Greedy algorithm, and a Local Search approach (Exchange Problem).

1. Initialization and Data Loading


uses "mmsystem"

declarations
    n, cap: integer
    archivo_datos = "gen300_5.txt"
end-declarations

fopen(archivo_datos, F_INPUT)
readln(n)
readln(cap)

declarations
    objetos = 1..n
    p, w, candidato: array(objetos) of integer
    t1: real
    x: array(objetos) of mpvar
    xp: array(objetos) of integer
    g: array(objetos) of real
    sol: array(objetos) of integer
    zgreedy, carga, final: integer
    ind0: array(objetos) of integer
    ind1: array(objetos) of integer
end-declarations

forall(j in objetos) read(j, p(j), w(j))
fclose(F_INPUT)

writeln("n = ", n)
writeln("Archivo: ", archivo_datos)

2. Linear Programming (LP) Formulation

The objective function and constraints define the LP relaxation of the Knapsack Problem:


valor_total := sum(j in objetos) p(j) * x(j)
r1 := sum(j in objetos) w(j) * x(j) <= cap
forall(j in objetos) x(j) is_binary

3. Dantzig Heuristic (Linear Relaxation)

We maximize the LP relaxation and use the solution to derive a heuristic integer solution.


writeln("\nHeurística de Dantzig (Relajación Lineal)\n")
maximize(XPRS_LIN, valor_total)

! Loop that indicates index k
ind := 0
forall(j in objetos) do
    if(x(j).sol <> 0) then
        ind := ind + 1
        writeln(x(j).sol, " ", ind)
    end-if
end-do

forall(j in objetos) xp(j) := floor(x(j).sol)

zLP := getobjval
zdantzig := sum(j in objetos) p(j) * xp(j)

! For checking integer values of p(j) (Commented out)
! forall(j in objetos) do
!     write(" ", p(j), " ", j)
! end-do

writeln("zdantzig = ", zdantzig, " <= z <= floor(zLP) = ", floor(zLP))

4. Optimal Integer Solution


maximize(valor_total)
z := getobjval
writeln("\nValor óptimo entero, z = ", z)

5. Greedy Algorithm Implementation

The Greedy algorithm selects items based on the highest profit-to-weight ratio $g(j) = p(j)/w(j)$ until the capacity is reached.


! ALGORITMO GREEDY
t1 := gettime
writeln("\nMétodo Greedy")

forall(j in objetos) g(j) := p(j) / w(j)
forall(j in objetos) sol(j) := 0

carga := 0
ncand := 0

forall(j in objetos | carga + w(j) <= cap) do
    candidato(j) := 1
    ncand := ncand + 1
end-do

zgreedy := 0
final := 0

while(final = 0) do
    aux := -99.
    
    ! Find the best candidate item (jmax)
    forall(j in objetos | candidato(j) = 1) do
        if(g(j) > aux) then
            aux := g(j)
            jmax := j
        end-if
    end-do
    
    sol(jmax) := 1
    carga := carga + w(jmax)
    zgreedy := zgreedy + p(jmax)
    candidato(jmax) := 0
    ncand := ncand - 1
    
    ! Update candidates: remove items that no longer fit
    forall(j in objetos | candidato(j) = 1) do
        if(carga + w(j) > cap) then
            candidato(j) := 0
            ncand := ncand - 1
        end-if
    end-do
    
    if(ncand = 0) then
        final := 1
    end-if
end-do

writeln("Solución greedy z = ", zgreedy)
writeln("tiempo = ", gettime - t1)

6. Local Search (Exchange Problem)

A local search heuristic attempts to improve the current solution (starting from the Greedy result) by exchanging one item currently in the knapsack with one item currently out, provided the capacity constraint is maintained and the profit improves.


! BÚSQUEDA LOCAL (PROBLEMA DE INTERCAMBIOS)
tiempo := gettime
writeln("\nBúsqueda Local")

zheur := zgreedy
iter := 0
final := 0

while(final = 0) do
    mejor_max := -999
    iter := iter + 1
    
    forall(j, k in objetos | sol(j) = 0 and sol(k) = 1) do
        if(carga - w(k) + w(j) <= cap) then
            mejora := p(j) - p(k)
        end-if
        
        if(mejora > mejor_max) then
            mejor_max := mejora
            jmax := j
            kmax := k
        end-if
    end-do
    
    if(mejor_max <= 0) then
        final := 1 ! Maximum local reached
        writeln("Iteración ", iter, ", z = ", zheur)
    else
        sol(jmax) := 1
        sol(kmax) := 0
        carga := carga - w(kmax) + w(jmax)
        zheur := zheur + p(jmax) - p(kmax)
    end-if
end-do

end-model

Related entries: