minizinc

Computing wasted hours in MiniZinc (how many 0 in an array of var 0..1 between first and last 1)


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?


Solution

  • 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: