int: nr; % number of reclaimers % number of rails = nr for stages A,B,C,D,E % number of rails = (nr + 1) div 2 for stage F set of int: RECLAIMER = 1..nr; bool: stageF; % is this stage F data int: ns; % number of stockpiles set of int: STOCKPILE = 1..ns; array[STOCKPILE] of int: size; % size in 10000 tonnes array[STOCKPILE] of SHIP: ship; % which ship carries stockpile int: maxtime; % time considered set of int: TIME = 0..maxtime; int: nsh; % number of ships set of int: SHIP = 1..nsh; array[SHIP] of TIME: arrival; % when ship arrives in port int: len; % length of pad set of int: POSITION = 0..len; int: stack_time; int: reclaim_time; int: reclaim_speed; array[STOCKPILE] of var POSITION: westend; array[STOCKPILE] of var POSITION: eastend; array[STOCKPILE] of var TIME: stack; array[STOCKPILE] of var TIME: endstack; array[STOCKPILE] of var TIME: reclaim; array[STOCKPILE] of var TIME: finished; array[STOCKPILE] of var RECLAIMER: which; % Go crazy here % Stage A - Packing Problem % Two stockpiles can't overlap in "spacetime" % 1) what's the relation between endstack and stack times constraint forall(s in STOCKPILE)(stack[s] + stack_time*size[s] = endstack[s]); % 2) what's the relation between finished and stack times constraint forall(s in STOCKPILE)(stack[s] < finished[s]); % 3) what's the relation between reclaim and endstack times constraint forall(s in STOCKPILE)(endstack[s] <= reclaim[s]); % 4) what's the relation between finished and reclam times constraint forall(s in STOCKPILE)(reclaim[s] + reclaim_time*size[s] = finished[s]); % constraint forall(s in STOCKPILE)(reclaim[s] + reclaim_time*size[s] + reclaim_speed*(size[s]-1) = finished[s]); % 5) what's the relation between eastend and westend offsets constraint forall(s in STOCKPILE)(westend[s] + size[s]= eastend[s]); % 6) packing problem % a) stockpiles should not overlap in "spacetime", treat them as rectangles % b) stockpiles can't use more space than there is available % c) we can't go beyond the time limit % constraint diffn(westend, stack, size, [stack_time*i|i in size ]); constraint forall(s1, s2 in STOCKPILE where s1= eastend[s2] \/ stack[s1]>=finished[s2]); constraint forall(s in STOCKPILE)(eastend[s]<=len); constraint forall(s in STOCKPILE)(finished[s]<=maxtime); % Stage B % Two stockpiles reclaimed by the same reclaimer do not overlap in time % % Tip: write your first custom predicate, i.e. predicate not_overlap(var STOCKPILE: s1, var STOCKPILE: s2) = finished[s1] <= reclaim[s2] \/ reclaim[s1] >= finished[s2]; constraint forall(s1, s2 in STOCKPILE where (s1 % } in constraint forall(s1, s2 in STOCKPILE where s1= dif) else (reclaim[s1] - finished[s2] >= dif) endif); % Stage E % Add a definition of the objective to your model and change the model to minimize this value. % You may well need to significantly change your search strategy to get good solutions for the objective. % TIP: definetely change the line below function var int: getSumShipStay() = sum([ '-'( max([ finished[s] | s in STOCKPILE where ship[s] = sh ]), arrival[sh]) | sh in SHIP]); var int: obj = getSumShipStay(); % Stage F % Add constraints in your model so that the two reclaimers on rail i numbered 2i − 1 and 2i for i ∈ 1..nr div 2 remain so the western one 2i − 1 is never east of the eastern one 2i. Note they can legitimately be in the same position (this is for simplicity, its not very real). Note that if there are % an odd number of reclaimers the last reclaimer is on its own rail and has no further constraints. % TIP: do some "channeling" and model reclaimers' positions explicitely with a new array of variables. % set of int: DOUBLE_RAILS = 0..nr div 2-1; constraint stageF -> ( let { int: rails = nr div 2 } in forall(rail in 1..rails)( let { int: r1 = 2 * rail - 1, int: r2 = 2 * rail} in forall(s1, s2 in STOCKPILE where which[s1]=r1 /\ which[s2]=r2)(eastend[s1] <= westend[s2]))); % solve minimize obj; solve :: int_search(finished, input_order, indomain_min, complete) minimize obj; % don't change the output output ["westend = ", show(westend), ";\n"] ++ ["eastend = ", show(eastend), ";\n"] ++ ["stack = ", show(stack), ";\n"] ++ ["endstack = ", show(endstack), ";\n"] ++ ["reclaim = ", show(reclaim), ";\n"] ++ ["finish = ", show(finished) , ";\n"] ++ ["which = ", show(which), ";\n"] ++ ["obj = ",show(obj),";\n"] ;