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_T
predicates are internally mapped onto the family ofelement
/element_T
functions.In
MiniZinc
version2.0.2
and above, these functions are mapped on the following predicates:The best solution is to override these predicates instead of messing with
element
/element_T
ones.