I'm working on a model about timetables and i have to minimize the total wasted hours. For every day from Monday to Saturday i have an array of var, for example [0, 1, 0, 0, 1, 1], meaning than a worker is at work on second, 5th and 6th time slot (tipically one hour). I need to count how many 0 there are between the first 1 and the last 1 in the array (2 in the example above).
If i use the following code:
array[1..6] of var 0..1: arr = [0, 1, 0, 0, 1, 1];
function int: waste(array[int] of var 0..1: x) = if (sum(x)==0) then 0 else count(x[arg_max(x)+1..length(x)-arg_max(reverse(x))],0) endif;
output ["wasted hours = \(waste(arr ))"];
i get the error: MiniZinc: type error: no function or predicate with this signature found: `arg_max(array[int] of var int)'
If i add the line include "arg_max.mzn":
include "arg_max.mzn";
array[1..6] of var 0..1: arr = [0, 1, 0, 0, 1, 1];
function int: waste(array[int] of var 0..1: x) = if (sum(x)==0) then 0 else count(x[arg_max(x)+1..length(x)-arg_max(reverse(x))],0) endif;
output ["wasted hours = \(waste(arr))"];
then i get another error: MiniZinc: type error: array slicing with variable range or index not supported
Is there a way to fix the error and compute the wasted hours?
Here is a version which outputs wasted hours = 2
as expected.
include "globals.mzn";
array[1..6] of var 0..1: arr = [0, 1, 0, 0, 1, 1];
function var int: waste(array[int] of var 0..1: x) =
if (sum(x)==0) then
0
else
sum([ x[i] == 0 | i in arg_max(x)+1..length(x)-arg_max(reverse(x))])
endif;
output ["wasted hours = \(fix(waste(arr )))"];
There are some changes to your version:
var int
(not just int
)sum
over a list comprehension