Implementation
Below is the implementation in Mosel: note that the option ROBUST_OVERLAP_UNCERTAIN is used since the capacity constraints at each arc use a subset of the uncertain demands.
model "Robust Network"
uses "mmrobust", "mmxprs"
parameters
vpn_data="vpn_data.dat"
end-parameters
declarations
NODES: range ! Set of nodes
ARCCOST: dynamic array(NODES, NODES) of real ! Per-unit cost of arc (i,j)
DEM_IN: array(NODES) of real ! Total INCOMING demand at each node
DEM_OUT: array(NODES) of real ! Total OUTGOING demand at each node
UNITCAP: integer ! Per-unit capacity (independent of arc)
NETCOST: linctr ! Objective function
! Decision variables
flow: dynamic array(NODES, NODES, NODES, NODES) of mpvar
! flow(i,j,h,k) is 1 iff demand h->k uses arc (i,j)
capacity: dynamic array(NODES, NODES) of mpvar ! Capacity to install on arc (i,j)
! Uncertain parameters
demand: array(NODES, NODES) of uncertain ! Uncertain traffic demand
RobustCap: array(NODES, NODES) of robustctr ! Uncertain traffic demand, formulated at each arc
end-declarations
! The following option is necessary to allow uncertain demands to be
! used across multiple capacity constraints
setparam("robust_uncertain_overlap", true)
! Set verbosity level
setparam("xprs_verbose", true)
!**** Data input ****
initializations from vpn_data
NODES ARCCOST
DEM_IN DEM_OUT
UNITCAP
end-initializations
!**** Model formulation ****
forall(i in NODES, j in NODES, h in NODES, k in NODES |
exists(ARCCOST(i,j)) and ARCCOST(i,j) > 0 and h <> k) do
create(flow(i,j,h,k))
flow(i,j,h,k) is_binary
end-do
forall(i in NODES, j in NODES | exists(ARCCOST(i,j)) and ARCCOST(i,j) > 0) do
create(capacity(i,j))
capacity(i,j) is_integer
end-do
! Flow balance at intermediate nodes for each demand(h,k)
forall(i in NODES, h in NODES, k in NODES | i <> h and i <> k and k <> h)
sum(j in NODES | exists(flow(i,j,h,k))) flow(i,j,h,k) -
sum(j in NODES | exists(flow(j,i,h,k))) flow(j,i,h,k) = 0
! Flow balance at source nodes (unnecessary for sink nodes)
forall(i in NODES, h=i, k in NODES | k <> h)
sum(j in NODES | exists(flow(i,j,h,k)) ) flow(i,j,h,k) -
sum(j in NODES | exists(flow(j,i,h,k)) ) flow(j,i,h,k) = 1
! Capacity (robust) constraint
forall(i in NODES, j in NODES | exists(ARCCOST(i,j)) and ARCCOST(i,j) > 0)
RobustCap(i,j) :=
sum(h in NODES, k in NODES | h <> k) demand(h,k) * flow(i,j,h,k) <=
UNITCAP * capacity(i,j)
! Uncertainty set: all demands are nonnegative and constrained by
! total outgoing and incoming demand
forall(h in NODES, k in NODES | h <> k) demand(h,k) >= 0
forall(h in NODES) sum(k in NODES | h <> k) demand(h,k) <= DEM_OUT(h)
forall(h in NODES) sum(k in NODES | h <> k) demand(k,h) <= DEM_IN(h)
! Shortest path length
NetCost := sum(i in NODES, j in NODES | exists(ARCCOST(i,j)) and ARCCOST(i,j) > 0)
ARCCOST(i,j) * capacity(i,j)
!**** Solving ****
minimize(NetCost)
declarations
curNode: integer ! Local variable used in following the path of each demand
end-declarations
! Printing capacities
writeln("Robust solution has total cost ", getobjval)
forall(i in NODES, j in NODES | exists(capacity(i,j)) and capacity(i,j).sol > 0)
writeln("arc ", i, " -- ", j, ": ", capacity(i,j).sol, " units")
writeln("Paths:")
forall(h in NODES, k in NODES | h <> k) do
write("Demand ", h, " --> ", k, ": ")
curNode := h
write(h)
while(curNode <> k) do
forall(j in NODES | flow(curNode, j, h, k).sol > 0.5) do
write(" -- ", j)
curNode := j
end-do
end-do
writeln
end-do
writeln("Active demands at each arc:")
forall(i in NODES, j in NODES | exists(ARCCOST(i,j)) and ARCCOST(i,j) > 0 and
sum(h in NODES, k in NODES) getsol(demand(h,k), RobustCap(i,j)) > 0) do
write("Arc (", i, ",", j, "): ")
forall(h in NODES, k in NODES | getsol(demand(h,k), RobustCap(i,j)) > 0)
write(h, "-->", k, " (", getsol(demand(h,k), RobustCap(i,j)), "); ")
writeln
end-do
end-model
© 2001-2020 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.
