% % Global constraint sliding_time_window in MiniZinc. % % From Global Constraint Catalogue % http://www.emn.fr/x-info/sdemasse/gccat/sec4.255.html % """ % sliding_time_window​(WINDOW_SIZE,​LIMIT,​TASKS)​ % % Purpose % % For any time window of size WINDOW_SIZE, the intersection of all the tasks % of the collection TASKS with this time window is less than or equal to a % given limit LIMIT. % % Example % ( % 9,​6, < % id-1 origin-10 duration-3, % id-2 origin-5 duration-1, % id-3 origin-6 duration-2, % id-4 origin-14 duration-2, % id-5 origin-2 duration-2 % > % ) % % The lower part of Figure 4.255.1 indicates the different tasks on the % time axis. Each task is drawn as a rectangle with its corresponding % identifier in the middle. Finally the upper part of Figure 4.255.1 shows % the different time windows and the respective contribution of the tasks % in these time windows. A line with two arrows depicts each time window. % The two arrows indicate the start and the end of the time window. At the % right of each time window we give its occupation. Since this occupation % is always less than or equal to the limit 6, the sliding_time_window % constraint holds. % % % """ % % This MiniZinc model was created by Hakan Kjellerstrand, hakank@bonetmail.com % See also my MiniZinc page: http://www.hakank.org/minizinc % % include "globals.mzn"; int: n; int: max_time; int: window_size; var int: limit; array[1..n, 1..2] of var 1..max_time: tasks; array[1..max_time] of var int: sums; % % I added max_time % predicate sliding_time_window(int: window_size, var int: limit, array[int, 1..2] of var int: tasks, int: max_time) = let { array[1..max_time] of var 0..n: occupied } in % how many tasks occupies this time entry forall(i in 1..max_time) ( occupied[i] = sum(j in 1..n) ( bool2int( i >= tasks[j, 1] /\ i < tasks[j, 1] + tasks[j, 2] ) ) ) /\ % sliding sum over occupied forall(i in 1..max_time) ( sums[i] = sum(j in i..i+window_size-1 where j <= max_time) ( occupied[j] ) /\ sums[i] <= limit ) /\ % all sums must be less or equal the limit forall(i in index_set_1of2(tasks)) ( tasks[i, 1] + tasks[i,2] <= max_time ) ; solve satisfy; % solve :: int_search([tasks[i,j] | i in 1..n, j in 1..2] ++ [limit] ++ sums, "first_fail", "indomain", "complete") satisfy; constraint limit = 6 /\ tasks = array2d(1..n, 1..2, [ 10, 3, 5, 1, 6, 2, 14, 2, 2, 2, ]) /\ sliding_time_window(window_size, limit, tasks, max_time) % /\ % 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 % sums = [_,6,_,_,6,6,_,_,_,5,_,_,_,2,_,_] % the sums of the example ; % % data % n = 5; max_time = 16; window_size = 9; output [ "tasks:" ] ++ [ if j = 1 then "\n " else " " endif ++ show(tasks[i,j]) | i in 1..n, j in 1..2 ] ++ [ "\nsums: ", show(sums), "\n", "limit: ", show(limit), "\n" ] ;