Search code examples
arraysconstraintsminizinc

Minizinc: given array of results, ensure indexes with matching value also match according to an additional value


A random 1..7 options for 1..13 positions model below produces an example output

[3,2,2,3,6,7,1,4,2,4,5,2,3]

I want to constrain it so that if the value is the same, then another value stated within another associated parameter array must also match.

set of int: optA = 1..7;
set of int: position = 1..13;
enum optB = {A,B,C,D};

array[position] of optB: opts = [A,A,A,B,B,B,B,C,C,C,D,D,D];
array[position] of var optA: result;

constraint forall(i in positions)(
  forall(j in optA)(
    % NO IDEA HOW TO FORMULATE EQUALITY HERE, IF THIS IS EVEN THE RIGHT IDEA
  )
);

In other words, if result[1], result[3], result[8] and result[9] are each assigned a 4 from optA, and second constraint looks at whether they have matching values from optB, which in this case they don't, so the result is invalid.

Any of A,A,A cannot have the same optA values as any of C,C,C, while within their set they can all be the same or different.

So, with this additional constraint, a valid solution could be

[1,2,2, 3,3,4,4, 5,5,5, 6,6,7]


Solution

  • Here's a solution that might be what you want. I understand this as the As is a chunk (set) that can take any value, but not the values that are in the chunks of B, C or D.

    The approach here is to simply check that if opts[i] != opts[j] then result[i] != result[j]. It that what you want?

    set of int: optA = 1..7;
    set of int: position = 1..13;
    enum optB = {A,B,C,D};
    
    array[position] of optB: opts = [A,A,A,B,B,B,B,C,C,C,D,D,D];
    array[position] of var optA: result;
    
    constraint
       % ensure that the "chunks" are different
       forall(i,j in position where i < j) (
          if opts[i] != opts[j] then
             result[i] != result[j]
           else
             true
           endif
       )
    ;
    solve satisfy;
    
    output [
    "result: \(result)\n",
    ];
    
    

    There's a lot of solutions (namely 2102520 solutions). Here are some of them:

    result: [3, 3, 3, 4, 4, 4, 4, 2, 2, 2, 1, 1, 1]
    ----------
    result: [3, 3, 3, 5, 4, 4, 4, 2, 2, 2, 1, 1, 1]
    ----------
    result: [3, 3, 3, 6, 4, 4, 4, 2, 2, 2, 1, 1, 1]
    ----------
    result: [3, 3, 3, 7, 4, 4, 4, 2, 2, 2, 1, 1, 1]
    ----------
    result: [3, 3, 3, 4, 5, 4, 4, 2, 2, 2, 1, 1, 1]
    ----------