Search code examples
constraint-programmingminizinc

Increment variable array elements in Minizinc


I would like to perform a simple increment operation on specific array elements:

Minimal Not-Working Example:

array[1..2] of var 0..1: a = [0, 0];

constraint forall (i in 1..2) (
    a[i] = a[i] + 1
);

output ["\(a)"];

solve satisfy;

This produces the minizinc output

  WARNING: model inconsistency detected
  stack.mzn:3:
  in call 'forall'
  in array comprehension expression
    with i = 1
  stack.mzn:4:
  in binary '=' operator expression
=====UNSATISFIABLE=====
% stack.fzn:1: warning: model inconsistency detected before search.

Why is this an inconsistency in the model -- why can't I reference the old value of the current array element? Is there some other way to increase the current array element by 1?

I'm new to constraint solving, so I hope this is not a terribly stupid question.


Solution

  • It is important to know that MiniZinc is a declarative language. In a constraint you're not stating an instruction, but you're stating the "truth" as know to the solvers.

    That means that an instruction like a = a + 1 will not work because you are stating that we're looking for a value for a that is its own value + 1. Since no such value exist we call the model inconsistent since no solutions can be found.

    The idea of the constraint items is to express relations between different variables and parameters. You could for example write: constraint forall(i in N) (a[i] = a[i-1] + 1). This will mean we will look for a value a[i] which is 1 more than a[i-1] for all i in N. (Note that we should probably add an if-statement to make sure i-1 stays within the given bounds)

    As a general rule: if there is a literal on one side of an equals signs, using that literal on the other side will create an inconsistent model.

    If you still wanted to create a MiniZinc model that increases the values of a given array by one, you could use the following model:

    set of int: N = 1..2
    array[N] of int: a = [0,1];
    array[N] of var int: b;
    
    constraint forall(i in N) (
        b[i] = a[i] + 1
    );
    

    Since the variables a are now expressed in terms of b, this doesn't violate our rule.