I’m relatively new to programming in MOSEL and I’m encountering an issue with a specific problem. Despite my efforts, the code I’ve written to solve the problem consistently returns a solution of zero.
The problem I’m working on is an Uncapacitated Location Routing problem. In this problem, there are multiple customers, each with a specific demand, and a number of potential locations where warehouses can be built. The goal is to determine the optimal placement of warehouses and assign customers to these warehouses in such a way that minimizes the total cost of construction and service.
Despite following the problem description closely, my code always returns a solution value of zero for the integer linear programming solution. I’m having trouble identifying where the error might be occurring.
I would greatly appreciate any insights or suggestions on how to troubleshoot this issue and improve my code.
I ask for someone who is much more knowledgeable than me to fix the code or help me understand where the issue lies.
Thanks in advance!
Description of Problem:
Consider a capacitated location problem, where there are n customers N={1..n} each with demand qi>0, and f possible locations F={1..f} to build warehouses with capacity Q. The task is to decide where to build the warehouses given gh, the construction cost of the warehouse in location h, which customers to serve with each warehouse knowing that the service cost is given by the minimum-cost Hamiltonian cycle that visits warehouse h and all nodes associated with the customers assigned to that warehouse. The objective is to minimize the sum of construction costs and service costs to the customers.
My Xpress Mosel Code:
!@encoding CP1252
model uncapacitated_location_routing
uses "mmxprs", "mmive"; !gain access to the Xpress-Optimizer solver
setparam("XPRS_CUTSTRATEGY", 0) ! inibiamo il presolve
forward procedure PrintInstance(DoIt: boolean)
forward procedure draw_sol
declarations
n, f: integer ! numero totale di clienti e magazzini
BigM, CostRange : integer
Quanti: integer ! rhs vincolo di cardinalita'
Verb : boolean ! controlla le stampe
CardVariant : boolean ! abilita vincolo cardinalitÃ
end-declarations
f := 6 ! facility da 1 a f1
n := 14 ! clients i da 1 a n
BigM := 7500 ! costante del modello
CostRange := 5000 ! costante del modello
!Quanti := floor(f/5) ! numero di facility da aprire
Verb := true
CardVariant := true
declarations
CLIENTI = 1..n ! da 1 a 50
FACILITIES = 1..f ! da 1 a 16
Y : array(FACILITIES) of mpvar ! Variabile Y: quali facilities apro
Z : array(FACILITIES, CLIENTI) of mpvar ! Variabile Z: come si servono i clienti
X : array(FACILITIES, CLIENTI, CLIENTI) of mpvar ! Variabile X: veicolo del magazzino h serve due clienti (i,j)
X_IN : array(FACILITIES, CLIENTI, FACILITIES) of mpvar ! Variabile X_IN (arco entrante nel magazzino --> uscente dal ultimo cliente)
X_OUT : array(FACILITIES, FACILITIES, CLIENTI) of mpvar ! Variabile X_OUT (arco uscente dal magazzino --> entrante nel primo cliente)
! matrice dei costi operativi tra cliente i --> cliente j
COST : array(CLIENTI, CLIENTI) of real
! matrice dei costi operativi tra magazzino - cliente
COST_1 : array(FACILITIES, CLIENTI) of real
FXCOST : array(FACILITIES) of real !vettore dei costi fissi
FLcost:linctr ! funzione obiettivo
MyEps = 0.01 ! tolleranza numerica
end-declarations
! Genero i costi di costruzione dei magazzini in modo random
forall(h in FACILITIES)
FXCOST(h):= real(floor(BigM*random))
! Dichiarazione delle coordinate delle facility e dei clienti
declarations
MySpaceX, MySpaceY : integer ! Le dimensioni dello spazio cartesiano
Dot = record ! Definizione di un tipo di dato per le coordinate
Xdot : integer
Ydot : integer
end-record
FacCoord: array (FACILITIES) of Dot ! Le coordinate nello spazio x,y di ogni facility
ClientCoor: array (CLIENTI) of Dot ! Le coordinate nello spazio x,y di ogni cliente
MinXCl, MinXFac, MinX, MaxXCl, MaxXFac, MaxX : integer
MinYCl, MinYFac, MinY, MaxYCl, MaxYFac, MaxY : integer
end-declarations
MySpaceX := integer(floor(CostRange*random))
MySpaceY := integer(floor(CostRange*random))
forall(h in FACILITIES) do
FacCoord(h).Xdot := integer(floor(MySpaceX*random))
FacCoord(h).Ydot := integer(floor(MySpaceY*random))
end-do
MinXFac := min(h in FACILITIES)FacCoord(h).Xdot
MinYFac := min(h in FACILITIES)FacCoord(h).Ydot
MaxXFac := max(h in FACILITIES)FacCoord(h).Xdot
MaxYFac := max(h in FACILITIES)FacCoord(h).Ydot
forall(i in CLIENTI) do
ClientCoor(i).Xdot := integer(floor(MySpaceX*random))
ClientCoor(i).Ydot := integer(floor(MySpaceY*random))
end-do
MinXCl := min(i in CLIENTI)ClientCoor(i).Xdot
MinYCl := min(i in CLIENTI)ClientCoor(i).Ydot
MaxXCl := max(i in CLIENTI)ClientCoor(i).Xdot
MaxYCl := max(i in CLIENTI)ClientCoor(i).Ydot
if (MinXCl <= MinXFac)
then MinX := MinXCl
else MinX := MinXFac
end-if
if (MinYCl <= MinYFac)
then MinY := MinYCl
else MinY := MinYFac
end-if
if (MaxXCl >= MaxXFac)
then MaxX := MaxXCl
else MaxX := MaxXFac
end-if
if (MaxYCl >= MaxYFac)
then MaxY := MaxYCl
else MaxY := MaxYFac
end-if
forall(i in CLIENTI, j in CLIENTI)
COST(i,j):= integer(floor (sqrt((ClientCoor(i).Xdot - ClientCoor(j).Xdot)^2 +
(ClientCoor(i).Ydot - ClientCoor(j).Ydot)^2)))
forall(h in FACILITIES, i in CLIENTI)
COST_1(h,i):= integer(floor (sqrt((FacCoord(h).Xdot - ClientCoor(i).Xdot)^2 +
(FacCoord(h).Ydot - ClientCoor(i).Ydot)^2)))
PrintInstance(true)
forall(h in FACILITIES) Y(h) is_binary
forall(h in FACILITIES, i in CLIENTI) Z(h,i) is_binary
forall(h in FACILITIES, i in CLIENTI, j in CLIENTI) X(h,i,j) is_binary
forall(h in FACILITIES, i in CLIENTI) X_IN(h,i,h) is_binary
forall(h in FACILITIES, i in CLIENTI) X_OUT(h,h,i) is_binary
forall(i in CLIENTI)
sum(h in FACILITIES) Z(h,i) = 1
forall(h in FACILITIES, j in CLIENTI)
sum(i in CLIENTI) (X(h,i,j) + X_OUT(h,h,j)) = sum(i in CLIENTI) (X(h,j,i) + X_IN(h,j,h))
forall(h in FACILITIES)
sum(i in CLIENTI) Z(h,i) <= Y(h)
forall(h in FACILITIES, j in CLIENTI)
sum(i in CLIENTI) X(h,i,j) + X_OUT(h,h,j) = Z(h,j)
forall(h in FACILITIES, i in CLIENTI, j in CLIENTI)
X(h,i,j) <= Z(h,i)
forall(h in FACILITIES, j in CLIENTI, i in CLIENTI)
X(h,i,j) <= Z(h,j)
forall(h in FACILITIES)
sum(i in CLIENTI) X_OUT(h,h,i) = Y(h)
FLcost := sum(h in FACILITIES) Y(h) * FXCOST(h) +
sum(h in FACILITIES, i in CLIENTI, j in CLIENTI)
(X(h,i,j) * COST(i,j)) +
sum(h in FACILITIES, i in CLIENTI)
(X_OUT(h,h,i) * COST_1(h,i) + X_IN(h,i,h) * COST_1(h,i))
minimize(FLcost)! Programmazione intera
writeln("nnCONTROLLO VINCOLO 1")
forall(i in CLIENTI)
writeln("Vincolo 1 per cliente ", i, ": ", sum(h in FACILITIES) getsol(Z(h,i)))
writeln("nnCONTROLLO VINCOLO 2")
forall(h in FACILITIES, j in CLIENTI)
writeln("Vincolo 2 per facility ", h, ", cliente ", j, ": ",
sum(i in CLIENTI) getsol(X(h,i,j)) + getsol(X_OUT(h,h,j)), " = ",
sum(i in CLIENTI) getsol(X(h,j,i)) + getsol(X_IN(h,j,h)))
writeln("nnCONTROLLO VINCOLO 3")
forall(h in FACILITIES)
writeln("Vincolo 3 per facility ", h, ": ", sum(i in CLIENTI) getsol(Z(h,i)), " <= ", getsol(Y(h)))
writeln("nnCONTROLLO VINCOLO 4")
forall(h in FACILITIES, j in CLIENTI) do
writeln("h=", h, " j=", j, ": lhs=",
sum(i in CLIENTI) getsol(X(h, i, j)) + getsol(X_OUT(h, h, j)),
" rhs=", getsol(Z(h, j)))
end-do
write("nnCONTROLLO VINCOLO 5.1")
forall(h in FACILITIES, i in CLIENTI, j in CLIENTI)
writeln("nVincolo 5.1 per facility ", h, ", clienti ", i, ", ", j, ": ", getsol(X(h,i,j)), " <= ", getsol(Z(h,i)))
write("nnCONTROLLO VINCOLO 5.2")
forall(h in FACILITIES, j in CLIENTI, i in CLIENTI)
writeln("nVincolo 5.2 per facility ", h, ", clienti ", j, ", ", i, ": ", getsol(X(h,i,j)), " <= ", getsol(Z(h,j)))
write("nnCONTROLLO VINCOLO 7")
forall(h in FACILITIES) do
writeln("nh=", h, ": lhs=", sum(i in CLIENTI) getsol(X_OUT(h, h, i)), " rhs=", getsol(Y(h)))
end-do
draw_sol
writeln("Ottimo intero: ",strfmt(getobjval,6,2))
procedure draw_sol
! Pulisce la finestra grafica
IVEerase
! Imposta lo zoom per la visualizzazione
IVEzoom( MinX-10, MinY-10, MaxX+10, MaxY+10)
! Aggiunge i punti e le linee per rappresentare la soluzione
plot1 := IVEaddplot("Partially Open Fac", IVE_RED) ! Legenda per le facility parzialmente aperte
plot2 := IVEaddplot("Open Fac", IVE_GREEN) ! Legenda per le facility aperte
plot3 := IVEaddplot("Closed Fac", IVE_YELLOW) ! Legenda per le facility chiuse
plot4 := IVEaddplot("Client", IVE_BLACK) ! Legenda per i clienti
plot5 := IVEaddplot("Arc", IVE_BLUE) ! Legenda per gli archi
forall(h in FACILITIES | getsol(Y(h))=0) IVEdrawpoint(plot3, FacCoord(h).Xdot,FacCoord(h).Ydot) ! Facility chiuse
forall(h in FACILITIES | getsol(Y(h))=1) IVEdrawpoint(plot2, FacCoord(h).Xdot,FacCoord(h).Ydot) ! Facility aperte
forall(h in FACILITIES | getsol(Y(h))>0 and getsol(Y(h))<1) IVEdrawpoint(plot1, FacCoord(h).Xdot,FacCoord(h).Ydot) ! Facility parzialmente aperte
forall(i in CLIENTI)IVEdrawpoint(plot4,ClientCoor(i).Xdot,ClientCoor(i).Ydot ) ! Clienti
forall(h in FACILITIES, i in CLIENTI | getsol(Z(h,i))>0 ) IVEdrawline(plot5, ClientCoor(i).Xdot,ClientCoor(i).Ydot, FacCoord(h).Xdot,FacCoord(h).Ydot) ! Collegamenti
forall(i in CLIENTI) IVEdrawlabel(plot4, ClientCoor(i).Xdot, ClientCoor(i).Ydot, string(i)) ! Etichette dei clienti
end-procedure
procedure PrintInstance(DoIt: boolean)
if DoIt then
writeln("facilities da aprire ",Quanti)
writeln("facilities:",f,",tclients:", n,
",nmaxcostofisso:", BigM,",tmaxcosto:", CostRange,"n")
writeln("ncosti fissi")
forall(h in FACILITIES)
writeln(h,": ", strfmt(FXCOST(h),2,2))
writeln("nCoordinate delle facilities:")
forall(h in FACILITIES)
writeln("Facility ", h, ": X = ", FacCoord(h).Xdot, ", Y = ", FacCoord(h).Ydot)
writeln("nCoordinate dei clienti:")
forall(i in CLIENTI)
writeln("Cliente ", i, ": X = ", ClientCoor(i).Xdot, ", Y = ", ClientCoor(i).Ydot)
writeln("nMatrice dei costi Cliente i --> Cliente j")
writeln("-------------------------------------------------")
write(" ")
forall (i in CLIENTI) write(strfmt(i,7))
forall(i in CLIENTI) do
write("nrow",strfmt(i,3),": ")
forall (j in CLIENTI)
write(strfmt(COST(i,j),5)," ")
end-do
write("nn")
writeln("nMatrice dei costi Facility h --> Cliente i")
writeln("-------------------------------------------------")
write(" ")
forall (i in CLIENTI) write(strfmt(i,7))
forall(h in FACILITIES) do
write("nrow",strfmt(h,3),": ")
forall (i in CLIENTI)
write(strfmt(COST_1(h,i),5)," ")
end-do
write("nn")
end-if
end-procedure
end-model