(!**************************************************************** CP example problems =================== file sched_mainpd.mos ````````````````````` Scheduling with resource dependent durations and cost, subject to given release dates and due dates. -- Parallel solving of CP subproblems -- -- Distributed computing version -- Combined MIP-CP problem solving: cut generation for MIP model by solving CP subproblems at nodes in the MIP branching tree. Before running this model, you need to set up the list NODES with machine names/addresses of your local network. All nodes that are used need to have the same version of Xpress installed and suitably licensed, and the server "xprmsrv" must have been started on these machines. All files are local to the root node, no write access is required at remote nodes. *** This model cannot be run with a Community Licence for the provided data instance *** (c) 2010 Fair Isaac Corporation author: S. Heipcke, May 2010, rev. Nov. 2019 *****************************************************************!) model "Schedule (MIP + CP) master problem" uses "mmsystem", "mmxprs", "mmjobs" parameters DATAFILE = "Data/sched_3_12.dat" VERBOSE = 1 end-parameters forward procedure define_MIP_model forward procedure setup_cutmanager forward public function generate_cuts: boolean forward public procedure print_solution declarations NP: integer ! Number of products NM: integer ! Number of machines end-declarations initializations from DATAFILE NP NM end-initializations declarations PRODS = 1..NP ! Set of products MACH = 1..NM ! Set of machines REL: array(PRODS) of integer ! Release dates of orders DUE: array(PRODS) of integer ! Due dates of orders MAX_LOAD: integer ! max_p DUE(p) - min_p REL(p) COST: array(PRODS,MACH) of integer ! Processing cost of products DUR: array(PRODS,MACH) of integer ! Processing times of products starttime: real ! Measure program execution time ctcut: integer ! Counter for cuts solstart: array(PRODS) of integer ! CP solution values OpMach: array(MACH,PRODS) of integer ! Tasks assigned to machines NumOp: array(MACH) of integer ! Number of tasks assigned to mach.s ! **** MIP model: use: array(PRODS,MACH) of mpvar ! 1 if p uses machine m, otherwise 0 Cost: linctr ! Objective function totsolve,totCP,solveM: real ! Time measurement ctrun: integer ! Iteration counter (CP) CPmodel: array(MACH) of Model ! References to the CP models ev: Event ! Event EVENT_SOLVED=2 ! Event codes sent by submodels EVENT_FAILED=3 NODES: list of string ! Set of available nodes nodeInst: dynamic array(set of string) of Mosel ! Mosel instances on remote nodes end-declarations ! Read data from file initializations from DATAFILE REL DUE COST DUR end-initializations !**** Setting up remote Mosel instances **** sethostalias("thiscomp","rcmd:") NODES:= ["","thiscomp"] !!! This list must have at least 1 element. !!! Use machine names within your local network, IP addresses, or !!! empty string for the current node running this model. forall(n in NODES, nct as counter) do create(nodeInst(n)) if connect(nodeInst(n), n)<>0 then exit(1); end-if if nct>= NM then break; end-if ! Stop when started enough end-do ! **** Problem definition **** define_MIP_model ! Definition of the MIP model res:=compile("sched_subpd.mos") ! Compile the CP model if res<>0 then exit(2); end-if ct:=0 forall(m in MACH) do ct:= if(ct1 then writeln("Node ", getparam("XPRS_NODES"), ": ", ctcut-ctcutold, " cut(s) added") end-if end-function !----------------------------------------------------------------- ! Solution callback function public procedure print_solution declarations sol: dynamic array(range) of integer end-declarations writeln("(",gettime-starttime, "sec) Solution ", getparam("XPRS_MIPSOLS"), ": Cost: ", getsol(Cost)) if VERBOSE > 1 then forall(p in PRODS) do forall(m in MACH) write(getsol(use(p,m))," ") writeln end-do end-if if VERBOSE > 0 then ! Collect the operations assigned to machines forall(m in MACH) do products_on_machine(m) if NumOp(m) > 1 then ToSolve += {m} elif NumOp(m) = 1 then solstart(OpMach(m,1)):= REL(OpMach(m,1)) end-if end-do ! Start solving the CP sequencing models startsolve:= gettime forall(m in ToSolve) start_CP_model(m, 2) ! Retrieve all results/termination messages ctend:= 0 repeat wait ! Wait for the next event ev:= getnextevent ! Get the event case getclass(ev) of ! Get the event class EVENT_END: ctend+=1 ! Submodel run terminated EVENT_SOLVED: do M:=ev.fromuid ! UID of model sending the event initializations from "sol_"+M+".dat" sol end-initializations fdelete("sol_"+M+".dat") forall(p in 1..NumOp(M)) solstart(OpMach(M,p)):=sol(OpMach(M,p)) end-do EVENT_FAILED: do M:=ev.fromuid ! UID of model sending the event writeln("Something wrong here: ", M, OpMach, NumOp) end-do else writeln("Problem with Kalis") exit(2) end-case until ctend=getsize(ToSolve) ! All models have finished ! Print out the result forall(p in PRODS) do msol:=sum(m in MACH) m*getsol(use(p,m)) writeln(p, " -> ", msol,": ", strfmt(solstart(p),2), " - ", strfmt(DUR(p,round(msol))+solstart(p),2), " [", REL(p), ", ", DUE(p), "]") end-do writeln("Time: ", gettime - starttime, "sec") writeln fflush end-if end-procedure end-model