MiniZinc: how to sum equal-length subarrays? - minizinc

The problem I encountered is how to add variables in a[0..9] to b[10..19].
My code is:
array[0..19] of int: a=array1d(0..19,[0,1,2,3,4,5,6,7,8,9,9,8,7,6,5,4,3,2,1,0]);
array[0..19] of int: b=array1d(0..19,[9,8,7,6,5,4,3,2,1,0,0,1,2,3,4,5,6,7,8,9]);
array[0..9] of var int: c;
constraint
forall(i in 0..9, j in 10..19)
(
c[i]=a[i]+b[j]
);
solve satisfy;
output[show(c[i]) | i in 0..9];
However, MiniZinc gives me the warning "model inconsistency detected, in call 'forall' in array comprehension expressionwith i = 0 with j = 11" and outputs "=====UNSATISFIABLE=====".
How do I get this to work?

(Extracts the answer from my comments.)
Your forall loop tries to assign c[i] many times with different values, which is not allowed. In MiniZinc, unlike traditional programming languages, a decision variables cannot be reassigned.
I guess that you mean addition in a parallel loop:
constraint
forall(i in 0..9) ( c[i]=a[i]+b[i+10])
;

Related

Difference between similar MiniZinc constraints

In the solution of the Zebra puzzle (http://rosettacode.org/wiki/Zebra_puzzle#MiniZinc) there's a constraint stating that one of the pets must be a zebra:
var 1..5: n;
constraint Gz[n]=Zebra;
Has the expression below a different meaning? They yield different results.
constraint exists(n in 1..5)(Gz[n]=Zebra);
These constraints are indeed equivalent. There is however a different in the way MiniZinc will translate these constraint for the solver.
The first option will be translated as a element constraint:
var 1..5: n;
constraint array_int_element(n, Gz, Zebra);
While the second one will result in an big clause constraint:
constraint bool_clause([Gz[1]=Zebra, Gz[2]=Zebra, Gz[3]=Zebra, Gz[3]=Zebra, Gz[5]=Zebra], [])
Although the constraints are equivalent it might depend on the solver which form will be more efficient during solving.
A better approach is to use the global count_leq(array [int] of var int: x, int: y, int: c) which enforces c to be less or equal to the number of occurences of y in x. Expressing the constraint as:
include "count_leq.mzn";
constraint count_leq(Gz, Zebra, 1);
directly conveys the meaning of the constraint and allows the solver used to use whichever form of the constraint would be best suited for its solving mechanism
If the declaration var 1..5: n is removed, then there is no global n that can be used in the output section, and this will yield an error: MiniZinc: type error: undefined identifier n'`.
It you keep var 1..5: n then the variable n in the exists loop don't have any effect of the global defined variable n, with the result that (the global) n will take any of the values 1..5 (which is shown if all solutions are printed).

Minizinc: declare explicit set in decision variable

I'm trying to implement the 'Sport Scheduling Problem' (with a Round-Robin approach to break symmetries). The actual problem is of no importance. I simply want to declare the value at x[1,1] to be the set {1,2} and base the sets in the same column upon the first set. This is modelled as in the code below. The output is included in a screenshot below it. The problem is that the first set is not printed as a set but rather some sort of range while the values at x[2,1] and x[3,1] are indeed printed as sets and x[4,1] again as a range. Why is this? I assume that in the declaration of x that set of 1..n is treated as an integer but if it is not, how to declare it as integers?
EDIT: ONLY the first column of the output is of importance.
int: n = 8;
int: nw = n-1;
int: np = n div 2;
array[1..np, 1..nw] of var set of 1..n: x;
% BEGIN FIX FIRST WEEK $
constraint(
x[1,1] = {1, 2}
);
constraint(
forall(t in 2..np) (x[t,1] = {t+1, n+2-t} )
);
solve satisfy;
output[
"\(x[p,w])" ++ if w == nw then "\n" else "\t" endif | p in 1..np, w in 1..nw
]
Backend solver: Gecode
(Here's a summarize of my comments above.)
The range syntax is simply a shorthand for contiguous values in a set: 1..8 is a shorthand of the set {1,2,3,4,5,6,7,8}, and 5..6 is a shorthand for the set {5,6}.
The reason for this shorthand is probably since it's often - and arguably - easier to read the shorthand version than the full list, especially if it's a long list of integers, e.g. 1..1024. It also save space in the output of solutions.
For the two set versions, e.g. {1,2}, this explicit enumeration might be clearer to read than 1..2, though I tend to prefer the shorthand version in all cases.

Conditional output minizinc

I'm messing arround with minizinc and I'm trying to achieve a conditional output where, if an array element has value 'true', the program outputs information concerning these element's array indexes. This is what I have:
include "globals.mzn";
int: time=5;
int: n=3;
int: l=n*n;
array[1..4,0..time,1..l] of var bool: X;
constraint X[1,5,7]=true;
constraint X[2,5,3]=true;
constraint X[3,5,9]=true;
constraint X[4,5,7]=true;
solve satisfy;
I attempted to solve this problem using concat, like so:
output ["X_"++concat(["\(r)_\(t)_\(pos)"
| pos in 1..l, r in 1..4, t in 0..time, where X[r,t,pos]==true])++"\n"];
However I am not allowed,
"MiniZinc: type error: no function or predicate with this signature found: `concat(array[int] of var opt string)'"
What I want is something like,
for pos in 1..l, r in 1..4, t in 0..time
if X[r,t,pos]==true
output ["X_\(r)_\(pos)_\(t)"]
How can I achieve it?
Try using fix(...) around the decision variable in the where clause, e.g.
output ["X_"++concat(["\(r)_\(t)_\(pos)"
| pos in 1..l, r in 1..4, t in 0..time, where fix(X[r,t,pos])==true])++"\n"];
fix is (often) needed when one use the actual values of decision variables, e.g. for comparing its values etc.
(The message about var opt string is perhaps misleading in this context.)

Confused by the `m..n` notation in MiniZinc

I have seen the "dot-dot" notation (..) in different places. In the following example, 0..n tells us the domain of the decision variable (which in this case, are the entries of the array s).
int: n;
array[0..n-1] of var 0..n: s;
Another example would be in the for-loop:
constraint forall(i in 0..sequence_length)(
t[i] = sum(k in 0..sequence_length)((bool2int(t[k] == i)))
);
In fact, we can even do something like
par var 1..5: x
My feeling is that the expression m..n is generally used when we define a variable (instead of a parameter), and we want to specify the domain of the variable. But in the second case, we are not defining any variable. So when do we use m..n? What is it exactly (e.g. does it have a type?)?
m..n denotes the set of (consecutive) integers from m to n. It could also be written explicitly as {m,m+1,m+2,...,n-1,n}.
Using a set as the domain, e.g.
var 0..5: x;
could be written as
var {0,1,2,3,4,5}: x;
or (which is probably a weird style):
var {1,5,2,3,0,4}: x;
but both represents the set 0..5.
When using m..n in a forall(i in m..n) ( .... ) loop it means that i is assigned from m to n.
A set is always ordered as this little model shows:
solve satisfy;
constraint
forall(i in {0,4,3,1,2,5}) (
trace("i: \(i)\n")
)
;
The trace function prints the following, i.e. ordered:
i: 0
i: 1
i: 2
i: 3
i: 4
i: 5

MiniZinc: type error: expected `array[int] of int', actual `array[int] of var opt int

I am trying to write a predicate that performs the same operation as circuit, but ignores zeros in the array, and I keep getting the following error:
MiniZinc: type error: initialisation value for 'x_without_0' has invalid type-inst: expected 'array[int] of int', actual 'array[int] of var opt int'
in the code:
% [0,5,2,0,7,0,3,0] -> true
% [0,5,2,0,4,0,3,0] -> false (no circuit)
% [0,5,2,0,3,0,8,7] -> false (two circuits)
predicate circuit_ignoring_0(array[int] of var int: x) =
let {
array[int] of int: x_without_0 = [x[i] | i in 1..length(x) where x[i] != 0],
int: lbx = min(x_without_0),
int: ubx = max(x_without_0),
int: len = length(x_without_0),
array[1..len] of var lbx..ubx: order
} in
alldifferent(x_without_0) /\
alldifferent(order) /\
order[1] = x_without_0[1] /\
forall(i in 2..len) (
order[i] = x_without_0[order[i-1]]
)
/\ % last value is the minimum (symmetry breaking)
order[ubx] = lbx
;
I am using MiniZinc v2.0.11
Edit
Per Kobbe's suggestion that it was an issue with having a variable length array, I used "the usual workaround" of keeping the order array the same size as the original array x, and using a parameter, nnonzeros, to keep track of the part of the array I care about:
set of int: S = index_set(x),
int: u = max(S),
var int: nnonzeros = among(x, S),
array[S] of var 0..u: order
This kind of answers your question:
The problem you are experiencing is that your array size is dependent on a var. This means that MiniZinc can not really know the size of the array is should create and the opt type is used. I would suggest that you stay away from the opt type if you do not know how to handle it.
Generally the solution is to make some workaround where your arrays are not dependent of the size of an var. My solution is most often to pad the array, i.e [2,0,5,0,8] -> [2,2,5,5,8], if the application allows it, or
var int : a;
[i * bool2int(i == a) in 1..5]
if you are okay with zeroes in your answer (I guess not in this case).
Furthermore, the alldifferent_except_0 could be in interest for you, or at least you can look how alldifferent_except_0 solves the problem with zeroes in the answer.
predicate alldifferent_except_0(array [int] of var int: vs) =
forall ( i, j in index_set(vs) where i < j ) (
vs[i]!=0 /\ vs[j]!=0 -> vs[i]!=vs[j]
)
from MiniZinc documentation