1
0
This repository has been archived on 2025-03-06. You can view files and clone it, but cannot push or open issues or pull requests.

173 lines
5.7 KiB
MiniZinc

%-----------------------------------------------------------------------------%
% vim: ts=4 sw=4 et wm=0 tw=0
%-----------------------------------------------------------------------------%
% Copyright (C) 2009-2016 The University of Melbourne and NICTA.
% See the file COPYING for license information.
%-----------------------------------------------------------------------------%
% Model example for Resource-Constrained Project Scheduling Problems with
% Weighted Earliness/Tardiness objective (RCPSP/WET)
%
% A RCPSP consists of resources, tasks, and precedences between some tasks
% where resources have of a specific capacity and tasks need some capacity of
% some resource to be executed.
% Here, we consider resources with a constant discrete capacity over time and
% tasks with a constant discrete duration and resource requirements.
% The objective is to find a optimal schedule so that tasks start as close as
% possible to the given start time for each task, penalizing earliness or
% tardiness according to the given weight for earliness and tardiness per task.
%
%-----------------------------------------------------------------------------%
include "cumulative.mzn";
%-----------------------------------------------------------------------------%
% Model parameters.
% Resources
%
int: n_res; % The number of resources
set of int: Res = 1..n_res; % The set of all resources
array [Res] of int: rc; % The resource capabilities
% Tasks
%
int: n_tasks; % The number of tasks
set of int: Tasks = 1..n_tasks; % The set of all tasks
array [Tasks] of int : d ; % The task durations
array [Res, Tasks] of int : rr ; % The resource requirements
array [Tasks] of set of int: suc; % The task successors
% Deadlines
%
% deadline[i, 1] is the desired start time for task i,
% deadline[i, 2] is the earliness cost per time unit of earliness,
% deadline[i, 3] is the tardiness cost per time unit of tardiness.
array [Tasks, 1..3] of int: deadline;
% Planning horizon
%
% Note that our RCPSP/WET instance generator requires a solution to the
% equivalent RCPSP problem in order to generate the instances, so it gives
% us a planning horizon = the makespan of the RCPSP problem, plus 20% slop
int: t_max; %= sum(i in Tasks)(d[i]); % End time of the planning horizon
set of int: Times = 0..(t_max - 1); % Possible start times
function array[int] of var int: model(int: instance) =
let {
%-----------------------------------------------------------------------------%
% Model variables.
% array [Tasks] of var Times: s; % The start times
%-----------------------------------------------------------------------------%
% Constraints.
% Precedence constraints
%
constraint
forall ( i in Tasks, j in suc[i] )
(
st[instance,i] + d[i] <= st[instance,j]
);
% Redundant non-overlapping constraints
%
constraint
redundant_constraint(
forall ( i, j in Tasks where i < j )
(
if exists(r in Res)(rr[r, i] + rr[r, j] > rc[r]) then
st[instance,i] + d[i] <= st[instance,j] \/ st[instance,j] + d[j] <= st[instance,i]
else
true
endif
)
);
% Cumulative resource constraints
%
constraint
forall ( r in Res )
(
let {
set of int: RTasks =
{ i | i in Tasks
where rr[r, i] > 0 /\ d[i] > 0 },
int: sum_rr = sum(i in RTasks)(rr[r, i])
} in (
if RTasks != {} /\ sum_rr > rc[r] then
cumulative(
[ st[instance,i] | i in RTasks ],
[ d[i] | i in RTasks ],
[ rr[r, i] | i in RTasks ],
rc[r]
)
else
true
endif
)
);
% Earliness
var 0..sum(i in Tasks) (
deadline[i, 2] * deadline[i, 1]
): earliness = sum (i in Tasks) (deadline[i, 2] * max(0, deadline[i, 1] - st[instance,i]));
% Tardiness
var 0..sum(i in Tasks) (
deadline[i, 3] * (t_max - deadline[i, 1])
): tardiness = sum (i in Tasks) (deadline[i, 3] * max(0, st[instance,i] - deadline[i, 1]));
} in [earliness, tardiness];
%-----------------------------------------------------------------------------%
% Diversity.
% Number of solutions
int: nsols;
set of int: Solutions = 1..nsols;
% Decisions global
array[Solutions,Tasks] of var Times: st;
% Objectives for all solutions
array[1..2, Solutions] of var int: objectives :: add_to_output;
constraint forall (s in Solutions) (objectives[..,s] = model(s));
% Extreme points
int: emin;
int: emax;
int: tmin;
int: tmax;
constraint objectives[1,1] = emin;
constraint objectives[2,1] = tmax;
constraint objectives[1,2] = emax;
constraint objectives[2,2] = tmin;
% Check for dominance
predicate is_dominated(int: e, int: t, int: sol) =
(objectives[1,sol] <= e) /\ (objectives[2,sol] <= t);
% Whether a point is dominated by a solution or not
array[emin..emax, tmin..tmax] of var bool: dominated;
constraint
forall (e in emin..emax, t in tmin..tmax) (
dominated[e,t] = exists (s in Solutions) (is_dominated(e,t,s)));
% A solution must not be dominated by any other solution
constraint
forall (s1, s2 in Solutions where s1 != s2) (
(objectives[1,s1] < objectives[1,s2]) \/ (objectives[2,s1] < objectives[2,s2]));
var 0..emax*tmax: objective = sum(dominated);
% Maximize the hypervolume: the number of dominated points
solve
:: int_search(array1d(st), smallest, indomain_min)
maximize objective;
output [
"st = array2d(\(Solutions), \(Tasks), \(st));\n",
"objective = \(objective);\n"
];