I have a Constraint Programming model in Minizinc 2.7.5 (with Gecode 6.3.0) and I want to use the Cumulative constraint on a subset of variables. It seems like the constraint does not work when the subset of variables can be of variable size. Can someone help me ?
Here is the model (not working) :
% Data variables
enum tasks;
array[tasks] of int: D;
int: num_steps;
set of int: steps = 1..num_steps;
int: num_dimensional_groups;
array[1..num_dimensional_groups] of set of tasks: dimensional_groups;
% Decision variables
array[tasks] of var 1..num_steps+1: X;
array[tasks] of var 1..2*num_steps: Z;
array[1..num_dimensional_groups] of var int: N;
array[1..num_dimensional_groups] of var set of tasks: cumul_tasks;
% Constraints
include "globals.mzn";
constraint forall(t in tasks)(Z[t] = X[t] + D[t] - 1);
% Definition of a subset of tasks
constraint forall(i in 1..num_dimensional_groups)(
cumul_tasks[i] = {t | t in (
(tasks diff dimensional_groups[i]) union {arg_min([X[t] | t in dimensional_groups[i]])} union {arg_max([Z[t] | t in dimensional_groups[i]])}
)}
);
constraint forall(i in 1..num_dimensional_groups)(
cumulative(
[X[t] | t in cumul_tasks[i]],
[D[t] | t in cumul_tasks[i]],
[1 | t in cumul_tasks[i]],
N[i]
)
);
Here is a sample data :
num_steps=25;
% Tasks
tasks = {T1, T2, T3, T4, T5, T6, T7, T8, T9, T10};
D = [2, 2, 2, 2, 2, 2, 1, 1, 1, 1];
% Tasks grouped by dimension
num_dimensional_groups = 3;
dimensional_groups = [
{T1, T2, T3},
{T4, T5, T6, T7, T8},
{T9, T10}
];
The idea behind the opt
version of cumulative is that a task might or might not be run, but that all tasks exists (or at least have some definition). This translates to that the start times might be opt
, but the duration and resource consumption must be actual variables.
This works for your model al well. Instead of iterating over the var set of tasks
for the duration and consumption, you instead iterate over the upper bound of the set. These are all the the possible tasks in the set.
constraint forall(i in 1..num_dimensional_groups)(
let { set of tasks: all_tasks = to_enum(tasks, ub(cumul_tasks[i])); } in
cumulative(
[X[t] | t in cumul_tasks[i]],
[D[t] | t in all_tasks],
[1 | t in all_tasks],
N[i]
)
);
Note that I had to add to_enum
in the definition of all_tasks
. This is because of a bug in the current definition of ub
that erases the enum type. This will hopefully be resolved in the next version of MiniZinc.