Search code examples
minizinc

Minizinc: optimal ordering on table feature


I have a table with features = {A,B}. B is a column of integers. Scanning the table, when I have a value change in B column, I increment a variable "changes" of 1:

if data[i,B]!=data[i-1,B]
then changes=changes+1

I want to find an order that minimizes changes and at the same time keep the repetition of a value in B in [0,upper_bound]. I'm thinking to use an array as a decision variable where save the position j for the element i:

order[i]=j means i element in data is the j-th element in ordering.

How can I model with constraint? This is what I do until now:

array[1..n, Features] of int: data;
int: changes=0;
constraint
   forall(i in 1..n) (
      if data[i,B] != data[i-1,B] then
        changes=changes+1
      endif
   )
;
minimize changes;

I think I'm wrong using changes as a constant variable, right? Thank you in advance.


Solution

  • In MiniZinc (and in constraint programming in general) you cannot increment a variable as changes=changes+1).

    If changes is a variable used only for the total count of changes you can use sum instead, something like:

    % ...
    var 0..n: num_changes;
    constraint
       changes = sum([data[i,B] != data[i-1,B] | i in 2..n])
    ;
    % ...
    

    However, if you want to use the number of accumulated changes for each i then you have to create a changes array to collect the values for each step, e.g.

    var[1..n-1] of var 0..n: changes;
    % the total number of changes (to minimize)
    var 0..n-1: total_changes = changes[n-1]; 
    constraint
    forall(i in 1..n-1) (
        if data[i,B] != data[i-1,B] then
           changes[i] = changes[i-1]+1
         else
           changes[i] = changes[i-1]    
        endif
    )
    ;