(!****************************************************** Mosel Example Problems ====================== file d1wagon2.mos ````````````````` Load balancing of train wagons (second version, using heuristic solution as start solution for MIP via 'addmipsol') (c) 2008 Fair Isaac Corporation author: S. Heipcke, Sep. 2007, rev. Feb. 2013 *******************************************************!) model "D-1 Wagon load balancing (2)" uses "mmxprs", "mmsystem" forward function solve_heur:real declarations BOXES = 1..16 ! Set of boxes WAGONS = 1..3 ! Set of wagons WEIGHT: array(BOXES) of integer ! Box weights WMAX: integer ! Weight limit per wagon load: array(BOXES,WAGONS) of mpvar ! 1 if box loaded on wagon, 0 otherwise maxweight: mpvar ! Weight of the heaviest wagon load MaxWeight: linctr ! Objective function HeurSol: array(BOXES) of integer ! Heuristic solution AllSol: array(mpvar) of real ! Start solution for MIP end-declarations initializations from 'd1wagon.dat' WEIGHT WMAX end-initializations ! Solve the problem heuristically and terminate the program if the ! heuristic solution is good enough, otherwise, load heuristic solution ! as start solution into the Optimizer if solve_heur<=WMAX then writeln("Heuristic solution fits capacity limits") exit(0) end-if ! Every box into one wagon forall(b in BOXES) sum(w in WAGONS) load(b,w) = 1 ! Limit the weight loaded into every wagon forall(w in WAGONS) sum(b in BOXES) WEIGHT(b)*load(b,w) <= maxweight ! Lower bound on maximum weight maxweight >= ceil((sum(b in BOXES) WEIGHT(b))/3) forall(b in BOXES,w in WAGONS) load(b,w) is_binary ! Alternative to lower bound on maxweight: adapt the optimizer cutoff value ! setparam("XPRS_MIPADDCUTOFF",-1) ! Uncomment the following line to see the optimizer log ! setparam("XPRS_VERBOSE",true) ! Set the solution values for all discrete variables that are non-zero forall(b in BOXES) AllSol(load(b,HeurSol(b))):= 1 ! Minimize the heaviest load MaxWeight:= maxweight ! Objective must be a constraint ! otherwise 'minimize' reloads problem loadprob(MaxWeight) ! Load problem into the Optimizer addmipsol("HeurSol", AllSol) ! Load the heuristic solution setcallback(XPRS_CB_SOLNOTIFY,"solnotify") ! Reporting use of user solution ! Re-inforce use of user solution in local search heuristics setparam("XPRS_USERSOLHEURISTIC",3) minimize(MaxWeight) ! Start optimization ! Solution printing writeln("Optimal solution:\n Max weight: ", getobjval) forall(w in WAGONS) do write(" ", w, ":") forall(b in BOXES) write(if(getsol(load(b,w))=1, " "+b, "")) writeln(" (total weight: ", getsol(sum(b in BOXES) WEIGHT(b)*load(b,w)), ")") end-do !----------------------------------------------------------------- (! LPT (Longest processing time) heuristic: One at a time place the heaviest unassigned box onto the wagon with the least load !) function solve_heur:real declarations ORDERW: array(BOXES) of integer ! Box indices in decreasing weight order Load: array(WAGONS,range) of integer ! Boxes loaded onto the wagons CurWeight: array(WAGONS) of integer ! Current weight of wagon loads CurNum: array(WAGONS) of integer ! Current number of boxes per wagon end-declarations ! Copy the box indices into array ORDERW and sort them in decreasing ! order of box weights (the sorted indices are returned in array ORDERW) forall(b in BOXES) ORDERW(b):=b qsort(SYS_DOWN, WEIGHT,ORDERW) ! Distribute the loads to the wagons using the LPT heuristic forall(b in BOXES) do v:=1 ! Find wagon with the smallest load forall(w in WAGONS) v:=if(CurWeight(v)