Download
%-----------------------------------------------------------------------------%
% Copyright (C) 2013 National ICT Australia and Monahsh University 2017
% Licenced under CC-BY-4.0 : http://creativecommons.org/licenses/by/4.0/
%-----------------------------------------------------------------------------%
%
% Author(s):
% Original model, Flexible Job Shop Scheduling:
% Andreas Schutt <andreas.schutt@nicta.com.au>
% Changes, Stochastic Assignment and Scheduling Problem:
% David Hemmi <david.hemmi@monash.edu>
%
%-----------------------------------------------------------------------------%
% Stochastic General Assignment Problem
% First stage:
% assign task to machines
% Second stage:
% based on observed processign times, schedule taks on respective machines
% Objective:
% minimise expected makespan
%-----------------------------------------------------------------------------%
% Including files
include "globals.mzn";
%-----------------------------------------------------------------------------%
% Parameters
int: no_mach; % Number of machines
int: no_jobs; % Number of jobs
int: no_task; % Number of total tasks
int: no_optt; % Number of total optional tasks
set of int: Mach = 1..no_mach;
set of int: Jobs = 1..no_jobs;
set of int: Tasks = 1..no_task;
set of int: OptTs = 1..no_optt;
array [Jobs] of set of int: tasks;
array [Tasks] of set of int: optts;
array [OptTs] of int: optt_mach;
array [SCENARIOS1,OptTs] of int: optt_dur;
array [Jobs] of int: last_task = [ max(tasks[j]) | j in Jobs ];
%---------implications for multi scenarion solving ---------------
int: nbScenarios;
set of int: SCENARIOS1 = 1..nbScenarios;
int: first_scen;
int: last_scen;
set of int: SCENARIOS = first_scen..last_scen;
array[SCENARIOS1] of int: weights;
%-------end of multi scenario addons ----------------
array [Tasks] of int: task_job =
[ min(j in Jobs where t in tasks[j])(j) | t in Tasks ];
array [SCENARIOS,Tasks] of int: task_mins =
array2d(SCENARIOS,Tasks,[ sum(k in tasks[task_job[t]])(if k < t then task_mind[s,k] else 0 endif)
| s in SCENARIOS, t in Tasks ]);
array [SCENARIOS,Tasks] of int: task_maxs =
array2d(SCENARIOS,Tasks,[ t_max[s] -
sum(k in tasks[task_job[t]])(if k < t then 0 else task_mind[s,k] endif)
| s in SCENARIOS, t in Tasks ]);
array [SCENARIOS,Tasks] of int: task_mind =
array2d(SCENARIOS,Tasks,[ min(o in optts[t])(optt_dur[s,o]) | s in SCENARIOS,t in Tasks ]);
array [SCENARIOS,Tasks] of int: task_maxd =
array2d(SCENARIOS,Tasks,[ max(o in optts[t])(optt_dur[s,o]) | s in SCENARIOS, t in Tasks ]);
% Additional deirved parameters for optional tasks
%
array [OptTs] of int: optt_task =
[ min(t in Tasks where o in optts[t])(t) | o in OptTs ];
array[SCENARIOS1] of int: min_dur = [ min([optt_dur[s,t] | t in OptTs]) | s in SCENARIOS1];
array[SCENARIOS1] of int: max_dur = [ max([optt_dur[s,t] | t in OptTs]) | s in SCENARIOS1];
set of int: Durs = min(min_dur)..max(max_dur);
% Parameters related to the planning horizon
%
array[SCENARIOS1] of int: t_max = [sum(t in Tasks)(max(o in optts[t])(optt_dur[s,o])) | s in SCENARIOS1];
set of int: Times = 0..max(t_max);
%-----------------------------------------------------------------------------%
% Variables
% Start time variables for tasks
%
array [SCENARIOS,Tasks] of var Times: start =
array2d(SCENARIOS,Tasks,[ let { var task_mins[s,t]..task_maxs[s,t]: k } in k | s in SCENARIOS, t in Tasks ]);
% Duration variables for tasks
%
array [SCENARIOS,Tasks] of var Durs: dur =
array2d(SCENARIOS,Tasks,[ if task_mind[s,t] = task_maxd[s,t] then task_mind[s,t] else
let { var task_mind[s,t]..task_maxd[s,t]: d } in d endif
| s in SCENARIOS,t in Tasks ]);
% Variables whether an optional task is executed
%
array [OptTs] of var bool: b;
array[SCENARIOS] of var Times: de_objective;
set of int: StochTimes = 0..sum(t_max);
var StochTimes: objective;
%-----------------------------------------------------------------------------%
% Constraints
% Precedence relations
%
constraint
forall(s in SCENARIOS)(
forall(j in Jobs, i in tasks[j] where i < last_task[j])(
start[s,i] + dur[s,i] <= start[s,i + 1]
)
);
% Duration constraints
%
constraint
forall(o in OptTs,s in SCENARIOS)(
let { int: t = optt_task[o] } in (
if card(optts[t]) = 1 then
b[o] = true
else
b[o] -> dur[s,t] = optt_dur[s,o]
endif
)
);
% Optional tasks' constraints
%
constraint
forall(t in Tasks where card(optts[t]) > 1)(
( sum(o in optts[t])(bool2int(b[o])) <= 1 )
/\ ( exists(o in optts[t])(b[o]) )
);
constraint
forall(t in Tasks where card(optts[t]) = 2)(
let {
int: o1 = min(optts[t]),
int: o2 = max(optts[t])
} in ( b[o1] <-> not(b[o2]) )
);
% Resource constraints
%
constraint
forall(m in Mach,s in SCENARIOS)(
let {
set of int: MTasks = { o | o in OptTs where optt_mach[o] = m }
} in (
cumulative(
[ start[s,optt_task[o]] | o in MTasks ],
[ optt_dur[s,o] | o in MTasks ],
[ bool2int(b[o]) | o in MTasks ],
1
)
)
);
% Objective constraint
constraint
forall(s in SCENARIOS)(
forall(j in Jobs)(start[s,last_task[j]] + dur[s,last_task[j]] <= de_objective[s])
);
constraint
objective = sum(s in SCENARIOS)(weights[s]*de_objective[s]);
%-----------------------------------------------------------------------------%
% Solve item
solve
:: search
minimize objective;
%------------------------------------------------------------------------------%
% Searches
ann: s_mindur = int_search([dur[s,t] |s in SCENARIOS, t in Tasks], smallest, indomain_min, complete);
ann: s_minstart = int_search([start[s,t] |s in SCENARIOS, t in Tasks], smallest, indomain_min, complete);
ann: s_bool = bool_search(b, input_order, indomain_max, complete);
ann: s_obj = int_search(de_objective, input_order, indomain_min, complete);
ann: search = seq_search([s_mindur, s_bool, s_minstart, s_obj]);
%-----------------------------------------------------------------------------%
% Output
output
[ "objective = ", show(de_objective), ";\n",
"stoch obj = ", show(objective), ";\n",
"start = ", show(start), ";\n",
"dur = ", show(dur), ";\n",
"b = ", show(b), ";\n",
];