Implementation
The following Mosel model roadworks.mos implements the robust optimization model from the previous section. Notice the use of cardinality on the uncertains delay to limit the total number of occurrences of roadworks to at most NWORK (the parameter for N) with a default value of 2. The uncertains that are used in such a cardinality constraint need to have explicit lower and upper bounds set. The solution reporting displays the selected arcs and the values of the uncertains for which a nonzero delay is chosen by the opponent.
model "road network"
uses "mmxprs", "mmrobust"
parameters
DATAFILE="roads_9.dat"
NWORK = 2 ! Number of roadworks
end-parameters
declarations
Nodes: range ! Set of nodes
ARC: array(Arcs:range,1..2) of integer ! Arc origins/destinations
LEN,MAXDELAY: array(Arcs) of real ! Length and max delay per arc
Source,Sink: integer ! Source and sink node numbers
use: array(Arcs) of mpvar ! 1 iff arc is used
TotalLength: robctr ! Objective function
delay: array(Arcs) of uncertain ! Uncertain delay
end-declarations
!**** Input datafile ****
initializations from DATAFILE
Nodes Arcs Source Sink ARC
[LEN,MAXDELAY] as "ArcData"
end-initializations
!**** Robust problem formulation ****
forall(a in Arcs) use(a) is_binary
! Sink and source of flow
sum(a in Arcs | ARC(a,1)=Source) use(a)=1
sum(a in Arcs | ARC(a,2)=Sink) use(a)=1
sum(a in Arcs | ARC(a,2)=Source) use(a)=0
sum(a in Arcs | ARC(a,1)=Sink) use(a)=0
! Flow balance in intermediate nodes
forall(n in Nodes-{Source,Sink})
sum(a in Arcs | ARC(a,2)=n) use(a) = sum(a in Arcs | ARC(a,1)=n) use(a)
! Random construction work on NWORK arcs
forall(a in Arcs) delay(a) <= MAXDELAY(a)
forall(a in Arcs) delay(a) >= 0
cardinality(union(a in Arcs) {delay(a)}, NWORK)
! Shortest path length
TotalLength:= sum(a in Arcs) (LEN(a)+delay(a))*use(a)
!**** Solving ****
minimize(TotalLength)
! Solution reporting
if getprobstat=XPRS_OPT then
writeln("Robust shortest path: ", getobjval)
writeln("Delay: ", sum(a in Arcs | use(a).sol>0) delay(a).sol)
forall(a in Arcs | use(a).sol>0)
writeln(if(ARC(a,1)=Source, "Source", string(ARC(a,1))), " -> ",
if(ARC(a,2)=Sink, "Sink", string(ARC(a,2))), "; ")
forall(a in Arcs | delay(a).sol>0)
writeln("Delay on (", ARC(a,1), ",", ARC(a,2), "): ", delay(a).sol)
else
writeln("No solution")
end-if
end-model
