I have the following MiniZinc code sample:
include "globals.mzn";
var int: i;
array[-3..3] of var set of 1..10: x;
var set of 1..100: y;
constraint element(i, x, y);
solve satisfy;
output [
show(i), "\n",
show(x), "\n",
show(y), "\n",
];
The mzn2fzn command, executed with the standard library, outputs the following FlatZinc code:
var set of 1..10: X_INTRODUCED_0_;
var set of 1..10: X_INTRODUCED_1_;
var set of 1..10: X_INTRODUCED_2_;
var set of 1..10: X_INTRODUCED_3_;
var set of 1..10: X_INTRODUCED_4_;
var set of 1..10: X_INTRODUCED_5_;
var set of 1..10: X_INTRODUCED_6_;
var -3..3: i:: output_var;
var set of 1..10: y:: output_var;
var 1..7: X_INTRODUCED_9_ ::var_is_introduced :: is_defined_var;
array [1..7] of var set of int: x:: output_array([-3..3]) = [X_INTRODUCED_0_,X_INTRODUCED_1_,X_INTRODUCED_2_,X_INTRODUCED_3_,X_INTRODUCED_4_,X_INTRODUCED_5_,X_INTRODUCED_6_];
constraint array_var_set_element(X_INTRODUCED_9_,[X_INTRODUCED_0_,X_INTRODUCED_1_,X_INTRODUCED_2_,X_INTRODUCED_3_,X_INTRODUCED_4_,X_INTRODUCED_5_,X_INTRODUCED_6_],y):: defines_var(y);
constraint int_lin_eq([1,-1],[i,X_INTRODUCED_9_],-4):: defines_var(X_INTRODUCED_9_):: domain;
solve satisfy;
Here, notice that originally y was declared to be a set of 1..100 in the MiniZinc model, but mzn2fzn correctly propagates the bounds on the elements of array x onto y, so that the FlatZinc model declares y to be a set of 1..10.
Now, I want to customize the content of element_set.mzn so that my own predicate is called when element_set is used, so I changed it to be as follows:
predicate element_set(var int: i, array[int] of var set of int: x,
var set of int: y) =
min(index_set(x)) <= i /\ i <= max(index_set(x)) /\
optimathsat_element_set(i, x, y, index_set(x));
predicate optimathsat_element_set(var int: i,
array[int] of var set of int: x,
var set of int: y,
set of int: xdom);
However, this code will not propagate the bounds on the elements of array x onto y, so the resulting FlatZinc file has y still declared to be a set of 1..100:
predicate optimathsat_element_set(var int: i,array [int] of var set of int: x,var set of int: y,set of int: xdom);
var set of 1..10: X_INTRODUCED_0_;
var set of 1..10: X_INTRODUCED_1_;
var set of 1..10: X_INTRODUCED_2_;
var set of 1..10: X_INTRODUCED_3_;
var set of 1..10: X_INTRODUCED_4_;
var set of 1..10: X_INTRODUCED_5_;
var set of 1..10: X_INTRODUCED_6_;
var -3..3: i:: output_var;
var set of 1..100: y:: output_var; %%% OFFENSIVE LINE %%%
array [1..7] of var set of int: x:: output_array([-3..3]) = [X_INTRODUCED_0_,X_INTRODUCED_1_,X_INTRODUCED_2_,X_INTRODUCED_3_,X_INTRODUCED_4_,X_INTRODUCED_5_,X_INTRODUCED_6_];
constraint optimathsat_element_set(i,x,y,-3..3);
solve satisfy;
I would like to know if anyone knows what is the correct encoding for propagating the domain of x over y. I managed to do this for other element_T constraints, but I am unable to find an elegant solution for element_set, because I can't find the proper builtins for doing this.
In other words, I would like to get
var set of 1..10: y:: output_var;
instead of
var set of 1..100: y:: output_var;
How would I do that?
The family of
element/element_Tpredicates are internally mapped onto the family ofelement/element_Tfunctions.In
MiniZincversion2.0.2and above, these functions are mapped on the following predicates:The best solution is to override these predicates instead of messing with
element/element_Tones.