0

I'm having trouble with an implementation of the following CP formulation (full formulation of the problem can be found here (page 4/16))

CP formulation of the problem

My implementation seems like code below, but I'm having struggle with following error: MiniZinc: type error: no function or predicate with this signature found: 'comulative(array[int] of var opt int,array[int] of var opt int,array[int] of var opt int,int)'.

This is because array comprehension is affected by some var, in this case variable x.

Do you have any suggestions how to make cumulative constraint working with option variables or any possible workaround?

include "cumulative.mzn";
include "element.mzn";

int: numJ; % number of tasks
int: numI; % number of facilities

% Tasks
set of int: Tasks = 1..numJ;

% Facilities
set of int: Facilities = 1..numI;

% Max consumptions of facilities
array[Facilities] of int: C;

array[Tasks] of int: d; % due times
array[Tasks] of int: r; % release times
array[Facilities, Tasks] of int: c; % c[i,j] = consumption of task j at facility i
array[Facilities, Tasks] of int: p; % p[i,j] = processing time of task i at facility j
array[Facilities, Tasks] of int: F; % F[i,j] = fixed cost paid when task j is assigned to facility i

% start time's domain is an interval <0, maximum of due times>
array[Tasks] of var 0..max(d): s;

% assign task to a facility
% x[3] = 1 --> task 3 is assigned to facility 1
array[Tasks] of var 1..numI: x;

% something like a temporary processing time
% im not really sure about this
array[Tasks] of var 0..max(p): u;

constraint forall(j in Tasks)(
  element(
    x[j],
    [p[i,j] | i in Facilities],
    u[j]
  )
);


constraint forall(i in Facilities)(
  comulative(
    [s[j] | j in Tasks where x[j] == i],
    [p[i,j] | j in Tasks where x[j] == i],
    [c[i,j] | j in Tasks where x[j] == i],
    C[i]
  )
);




% A task cant start before its release time
constraint forall(j in Tasks)(s[j] >= r[j]);
% A task cant run longer than its due time
constraint forall(j in Tasks)(s[j] <= d[j] - u[j]);

% Minimize total cost
solve minimize sum(j in Tasks)(F[x[j],j]);

output [ "start: ", "\n", show(s), "\n", "facility: ", "\n" , show(x) , "\n"];

Simple data set:

C = [8, 8, 6, 5];

numJ = 12;
numI = 4;
r = [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2];

d = [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3];

c = [|8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, |8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, |6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, |5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, |];

p = [|1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |];

F = [|0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, |1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, |1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, |1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, |];
desertnaut
  • 57,590
  • 26
  • 140
  • 166
mrtn
  • 331
  • 2
  • 12
  • 2
    Just a note: the constraint is called "cumulative" (not "comulative"). However, changing to the correct name still yield the same type of error since the slices such as "[s[j] | j in Tasks where x[j] == i]" in cumulative is translated to "var opt int" (which is not supported in the cumulative constraint). I'll see if I can come up with some working model. – hakank May 01 '16 at 16:39
  • Another thing: Do you have a full example with the fixed parameters, e.g. numJ, numI, C, d, r, c, p, and F? – hakank May 01 '16 at 16:43
  • @hakank I've came up with a more straight forward solution which is not using cumulative nor element constraints but just mimics them. Going to answer this question by myself in a moment. – mrtn May 01 '16 at 17:09
  • That's great. Note that there exists a cumulative that supports opts in the file "cumulative_opt.mzn" (so you should include this instead), but then both the slices of "p" and "s" must be without the "where x[j] == i", i.e.. "[p[i,j] | j in Tasks]". – hakank May 01 '16 at 17:15
  • I understand, I've found your answer [here](http://stackoverflow.com/questions/34477453/constraint-programming-scheduling-with-multiple-workers?rq=1), thank you for this. My current solution is heavily inspired by yours. – mrtn May 01 '16 at 17:20

2 Answers2

2

Even though you mentioned that you've found a solution, here's a version that use cumulative (opt version in "cumulative_opt.mzn").

include "globals.mzn"; % includes the file "cumulative_opt.mzn"
% ....

constraint forall(i in Facilities)(
    cumulative(
    % [s[j] | j in Tasks where x[j] == i], % original
    % [p[i,j] | j in Tasks where x[j] == i], % original
    % [c[i,j] | j in Tasks where x[j] == i], % original

    [s[j] | j in Tasks where x[j] == i],
    [p[i,j] | j in Tasks], % <-- no condition clause here
    [c[i,j] | j in Tasks], % <-- no condition clause here
    C[i]
 )
);
hakank
  • 6,629
  • 1
  • 17
  • 27
  • I spent like 7 hours searching for an answer how to get 'cumulative' constraint working with opt values and didnt notice the cumulative_opt at all. Thank you for your help :) – mrtn May 01 '16 at 17:26
  • :-) I tend to browse the directory of global constraint files (*.mzn) in the directory "share/minizinc/std" to see if there is a corresponding constraint. And sometimes look at the listing at http://www.minizinc.org/2.0/doc-lib/doc.html . – hakank May 01 '16 at 17:31
1

I came up with this solution and I hope it is easier to understand than the one with cumulative constraint.

array[Facilities, 0..max(d)] of var 0..max(C): facilityUsageAtTime;

constraint forall(i in Facilities) (
     forall(tt in 0..max(d)) (
        facilityUsageAtTime[i,tt] = sum(j in Tasks where x[j] == i /\ s[j] <= tt /\ tt < s[j] + p[x[j], j])(c[x[j],j]) /\
        facilityUsageAtTime[i,tt] <= C[i]
     )
);

It is heavily inspired by @hakank answer posted here

Community
  • 1
  • 1
mrtn
  • 331
  • 2
  • 12