include "flatzinc_builtins.mzn"; include "mzncc_builtins.mzn"; /*** @groupdef builtins Builtins These functions and predicates define built-in operations of the MiniZinc language. */ /*** @groupdef builtins.compare Comparison Builtins These builtins implement comparison operations. */ /** @group builtins.compare Return if \a x is less than \a y */ function bool: '<'( $T: x, $T: y); /** @group builtins.compare Return if \a x is less than \a y */ function var bool: '<'(var $T: x,var $T: y); /** @group builtins.compare Return if \a x is greater than \a y */ function bool: '>'( $T: x, $T: y); /** @group builtins.compare Return if \a x is greater than \a y */ function var bool: '>'(var $T: x,var $T: y); /** @group builtins.compare Return if \a x is less than or equal to \a y */ function bool: '<='( $T: x, $T: y); /** @group builtins.compare Return if \a x is less than or equal to \a y */ function var bool: '<='(var $T: x, var $T: y); /** @group builtins.compare Return if \a x is greater than or equal to \a y */ function bool: '>='( $T: x, $T: y); /** @group builtins.compare Return if \a x is greater than or equal to \a y */ function var bool: '>='(var $T: x,var $T: y); /** @group builtins.compare Return if \a x is equal to \a y */ function bool: '='( $T: x, $T: y); /** @group builtins.compare Return if \a x is equal to \a y */ function bool: '='(opt $T: x, opt $T: y); /** @group builtins.compare Return if \a x is equal to \a y */ function var bool: '='(var $T: x,var $T: y); /** @group builtins.compare Return if \a x is equal to \a y */ function var bool: '='(var opt $T: x,var opt $T: y); /** @group builtins.compare Return if \a x is not equal to \a y */ function bool: '!='( $T: x, $T: y); /** @group builtins.compare Return if \a x is not equal to \a y */ function var bool: '!='(var $T: x, var $T: y); % Special case comparison operators for integer variable and float constant function var bool: '<='(var int: x, float: y) = (x <= floor(y)); function var bool: '>='(var int: x, float: y) = (x >= ceil(y)); function var bool: '<='(float: x, var int: y) = (y >= ceil(x)); function var bool: '>='(float: x, var int: y) = (y <= floor(x)); function var bool: '<'(var int: x, float: y) = (x <= ceil(y)-1); function var bool: '>'(float: x, var int: y) = (y <= ceil(x)-1); function var bool: '>'(var int: x, float: y) = (x >= floor(y)+1); function var bool: '<'(float: x, var int: y) = (y >= floor(x)+1); function var bool: '='(var int: x, float: y) = if ceil(y)=floor(y) then x=ceil(y) else false endif; function var bool: '='(float: x, var int: y) = if ceil(x)=floor(x) then y=ceil(x) else false endif; function var bool: '!='(var int: x, float: y) = if ceil(y)=floor(y) then x != ceil(y) else true endif; function var bool: '!='(float: x, var int: y) = if ceil(x)=floor(x) then y != ceil(x) else true endif; function bool: '<='(int: x, float: y) = (x <= floor(y)); function bool: '>='(int: x, float: y) = (x >= ceil(y)); function bool: '<='(float: x, int: y) = (y >= ceil(x)); function bool: '>='(float: x, int: y) = (y <= floor(x)); function bool: '<'(int: x, float: y) = (x <= ceil(y)-1); function bool: '>'(float: x, int: y) = (y <= ceil(x)-1); function bool: '>'(int: x, float: y) = (x >= floor(y)+1); function bool: '<'(float: x, int: y) = (y >= floor(x)+1); function bool: '='(int: x, float: y) = if ceil(y)=floor(y) then x=ceil(y) else false endif; function bool: '='(float: x, int: y) = if ceil(x)=floor(x) then y=ceil(x) else false endif; function bool: '!='(int: x, float: y) = if ceil(y)=floor(y) then x != ceil(y) else true endif; function bool: '!='(float: x, int: y) = if ceil(x)=floor(x) then y != ceil(x) else true endif; /** @group builtins.compare Return if array \a x is lexicographically smaller than array \a y */ function bool: '<'(array[$U] of $T: x,array[$U] of $T: y); /** @group builtins.compare Return if array \a x is lexicographically smaller than array \a y */ function var bool: '<'(array[$U] of var $T: x,array[$U] of var $T: y); /** @group builtins.compare Return if array \a x is lexicographically greater than array \a y */ function bool: '>'(array[$U] of $T: x,array[$U] of $T: y); /** @group builtins.compare Return if array \a x is lexicographically greater than array \a y */ function var bool: '>'(array[$U] of var $T: x,array[$U] of var $T: y); /** @group builtins.compare Return if array \a x is lexicographically smaller than or equal to array \a y */ function bool: '<='(array[$U] of $T: x,array[$U] of $T: y); /** @group builtins.compare Return if array \a x is lexicographically smaller than or equal to array \a y */ function var bool: '<='(array[$U] of var $T: x,array[$U] of var $T: y); /** @group builtins.compare Return if array \a x is lexicographically greater than or equal to array \a y */ function bool: '>='(array[$U] of $T: x,array[$U] of $T: y); function var bool: '>='(array[$U] of var $T: x,array[$U] of var $T: y); /** @group builtins.compare Return if array \a x is equal to array \a y */ function bool: '='(array[$T] of int: x,array[$T] of int: y) = let { array[int] of int: xx = array1d(x); array[int] of int: yy = array1d(y); } in assert(index_sets_agree(x,y), "array index sets do not match", forall (i in index_set(xx)) (xx[i]=yy[i]) ); /** @group builtins.compare Return if array \a x is equal to array \a y */ function var bool: '='(array[$T] of var int: x,array[$T] of var int: y) = let { array[int] of var int: xx = array1d(x); array[int] of var int: yy = array1d(y); } in assert(index_sets_agree(x,y), "array index sets do not match", forall (i in index_set(xx)) (xx[i]=yy[i]) ); /** @group builtins.compare Return if array \a x is equal to array \a y */ function bool: '='(array[$T] of bool: x,array[$T] of bool: y) = let { array[int] of bool: xx = array1d(x); array[int] of bool: yy = array1d(y); } in assert(index_sets_agree(x,y), "array index sets do not match", forall (i in index_set(xx)) (xx[i]=yy[i]) ); /** @group builtins.compare Return if array \a x is equal to array \a y */ function var bool: '='(array[$T] of var bool: x,array[$T] of var bool: y) = let { array[int] of var bool: xx = array1d(x); array[int] of var bool: yy = array1d(y); } in assert(index_sets_agree(x,y), "array index sets do not match", forall (i in index_set(xx)) (xx[i]=yy[i]) ); /** @group builtins.compare Return if array \a x is equal to array \a y */ function bool: '='(array[$T] of set of int: x,array[$T] of set of int: y) = let { array[int] of set of int: xx = array1d(x); array[int] of set of int: yy = array1d(y); } in assert(index_sets_agree(x,y), "array index sets do not match", forall (i in index_set(xx)) (xx[i]=yy[i]) ); /** @group builtins.compare Return if array \a x is equal to array \a y */ function var bool: '='(array[$T] of var set of int: x,array[$T] of var set of int: y) = let { array[int] of var set of int: xx = array1d(x); array[int] of var set of int: yy = array1d(y); } in assert(index_sets_agree(x,y), "array index sets do not match", forall (i in index_set(xx)) (xx[i]=yy[i]) ); /** @group builtins.compare Return if array \a x is equal to array \a y */ function bool: '='(array[$T] of float: x,array[$T] of float: y) = let { array[int] of float: xx = array1d(x); array[int] of float: yy = array1d(y); } in assert(index_sets_agree(x,y), "array index sets do not match", forall (i in index_set(xx)) (xx[i]=yy[i]) ); /** @group builtins.compare Return if array \a x is equal to array \a y */ function var bool: '='(array[$T] of var float: x,array[$T] of var float: y) = let { array[int] of var float: xx = array1d(x); array[int] of var float: yy = array1d(y); } in assert(index_sets_agree(x,y), "array index sets do not match", forall (i in index_set(xx)) (xx[i]=yy[i]) ); /** @group builtins.compare Return if array \a x is not equal to array \a y */ function bool: '!='(array[$U] of $T: x,array[$U] of $T: y); /** @group builtins.compare Return if array \a x is not equal to array \a y */ function var bool: '!='(array[$U] of var $T: x,array[$U] of var $T: y); /*** @groupdef builtins.arithmetic Arithmetic Builtins These builtins implement arithmetic operations. */ /** @group builtins.arithmetic Return \a x + \a y */ function int: '+'( int: x, int: y); /** @group builtins.arithmetic Return \a x + \a y */ function var int: '+'(var int: x, var int: y); /** @group builtins.arithmetic Return \a x + \a y */ function float: '+'( float: x, float: y); /** @group builtins.arithmetic Return \a x + \a y */ function var float: '+'(var float: x,var float: y); /** @group builtins.arithmetic Return \a x - \a y */ function int: '-'( int: x, int: y); /** @group builtins.arithmetic Return \a x - \a y */ function var int: '-'(var int: x, var int: y); /** @group builtins.arithmetic Return \a x - \a y */ function float: '-'( float: x, float: y); /** @group builtins.arithmetic Return \a x - \a y */ function var float: '-'(var float: x,var float: y); /** @group builtins.arithmetic Return \a x * \a y */ function int: '*'( int: x, int: y); /** @group builtins.arithmetic Return \a x * \a y */ function var int: '*'(var int: x, var int: y); /** @group builtins.arithmetic Return \a x ^ \a y */ function int: '^'( int: x, int: y); /** @group builtins.arithmetic Return \a x ^ \a y */ function var int: '^'(var int: x, var int: y); /** @group builtins.arithmetic Return \a x * \a y */ function float: '*'( float: x, float: y); /** @group builtins.arithmetic Return \a x * \a y */ function var float: '*'(var float: x,var float: y); /** @group builtins.arithmetic Return \a x ^ \a y */ function float: '^'( float: x, float: y); /** @group builtins.arithmetic Return \a x ^ \a y */ function var float: '^'(var float: x,var float: y); /** @group builtins.arithmetic Return negative \a x */ function int: '-'( int: x); /** @group builtins.arithmetic Return negative \a x */ function var int: '-'(var int: x); /** @group builtins.arithmetic Return negative \a x */ function float: '-'( float: x); /** @group builtins.arithmetic Return negative \a x */ function var float: '-'(var float: x); /** @group builtins.arithmetic Return result of integer division \a x / \a y */ function int: 'div'(int: x,int: y); /** @group builtins.arithmetic Return result of integer division \a x / \a y */ function var int: 'div'(var int: x,var int: y) = if mzn_in_root_context(y) \/ not (0 in dom(y)) then div_t(x,y) else let { constraint y != 0 } in div_mt(x,y) endif; /** @group builtins.arithmetic Return remainder of integer division \a x % \a y */ function int: 'mod'(int: x,int: y); /** @group builtins.arithmetic Return remainder of integer division \a x % \a y */ function var int: 'mod'(var int: x,var int: y) = if mzn_in_root_context(y) \/ not (0 in dom(y)) then mod_t(x,y) else let { constraint y != 0 } in mod_mt(x,y) endif; /** @group builtins.arithmetic Return result of floating point division \a x / \a y */ function float: '/'( float: x, float: y); /** @group builtins.arithmetic Return result of floating point division \a x / \a y */ function var float: '/'(var float: x,var float: y) = if mzn_in_root_context(y) \/ lb(y) > 0.0 \/ ub(y) < 0.0 then fldiv_t(x,y) else let { constraint y != 0.0 } in fldiv_mt(x,y) endif; /** @group builtins.arithmetic Return sum of elements in array \a x */ function int: sum(array[$T] of int: x); /** @group builtins.arithmetic Return sum of elements in array \a x */ function var int: sum(array[$T] of var int: x); /** @group builtins.arithmetic Return sum of elements in array \a x */ function float: sum(array[$T] of float: x); /** @group builtins.arithmetic Return sum of elements in array \a x */ function var float: sum(array[$T] of var float: x); /** @group builtins.arithmetic Return product of elements in array \a x */ function int: product(array[$T] of int: x); /** @group builtins.arithmetic Return product of elements in array \a x */ function var int: product(array[$T] of var int: x) = product_rec(array1d(x)); /** @group builtins.arithmetic Return product of elements in array \a x */ function float: product(array[$T] of float: x); /** @group builtins.arithmetic Return product of elements in array \a x */ function var float: product(array[$T] of var float: x) = product_rec(array1d(x)); % /** @group builtins.arithmetic Return minimum of \a x and \a y */ % function $T: min( $T: x, $T: y); % /** @group builtins.arithmetic Return minimum of elements in array \a x */ % function $T: min(array[$U] of par $T: x); % /** @group builtins.arithmetic Return maximum of \a x and \a y */ % function $T: max( $T: x, $T: y); % /** @group builtins.arithmetic Return maximum of elements in array \a x */ % function $T: max(array[$U] of $T: x); % /** @group builtins.arithmetic Return minimum of elements in set \a x */ % function $$E: min(set of $$E: x); % /** @group builtins.arithmetic Return maximum of elements in set \a x */ % function $$E: max(set of $$E: x); /** @group builtins.arithmetic Return maximum of \a x and \a y */ function var int: max(var int: x, var int: y) :: promise_total = let { var max(lb(x),lb(y))..max(ub(x),ub(y)): m ::is_defined_var; constraint int_max(x,y,m) ::defines_var(m); } in m; /** @group builtins.arithmetic Return maximum of elements in array \a x */ function var int: max(array[$U] of var int: x) = let { array[int] of var int: xx = array1d(x); constraint length(x) >= 1; } in max_t(xx); /** @group builtins.arithmetic Return minimum of \a x and \a y */ function var int: min(var int: x, var int: y) :: promise_total = let { var min(lb(x),lb(y))..min(ub(x),ub(y)): m ::is_defined_var; constraint int_min(x,y,m) ::defines_var(m); } in m; /** @group builtins.arithmetic Return minimum of elements in array \a x */ function var int: min(array[$U] of var int: x) = let { array[int] of var int: xx = array1d(x); constraint length(x) >= 1; } in min_t(xx); % Floating point min and max % TODO: add bounds reasoning /** @group builtins.arithmetic Return maximum of \a x and \a y */ function var float: max(var float: x, var float: y) :: promise_total = let { var float: m ::is_defined_var; constraint float_max(x,y,m) ::defines_var(m); } in m; /** @group builtins.arithmetic Return maximum of elements in array \a x */ function var float: max(array[$U] of var float: x) = let { array[int] of var float: xx = array1d(x); constraint length(x) >= 1; } in max_t(xx); /** @group builtins.arithmetic Return minimum of \a x and \a y */ function var float: min(var float: x, var float: y) :: promise_total = let { var float: m ::is_defined_var; constraint float_min(x,y,m) ::defines_var(m); } in m; /** @group builtins.arithmetic Return minimum of elements in array \a x */ function var float: min(array[$U] of var float: x) = let { array[int] of var float: xx = array1d(x); constraint length(x) >= 1; } in min_t(xx); /** @group builtins.arithmetic Return index of minimum of elements in array \a x */ function $$E: arg_min(array[$$E] of int: x); /** @group builtins.arithmetic Return index of minimum of elements in array \a x */ function $$E: arg_min(array[$$E] of float: x); /** @group builtins.arithmetic Return index of maximum of elements in array \a x */ function $$E: arg_max(array[$$E] of int: x); /** @group builtins.arithmetic Return index of maximum of elements in array \a x */ function $$E: arg_max(array[$$E] of float: x); /** @group builtins.arithmetic Return absolute value of \a x */ function int: abs(int: x); /** @group builtins.arithmetic Return absolute value of \a x */ function var int: abs(var int: x) :: promise_total = if has_bounds(x) /\ lb(x) >= 0 then x elseif has_bounds(x) /\ ub(x) < 0 then -x else let { var 0..max(-lb(x),ub(x)): m ::is_defined_var; constraint int_abs(x,m) ::defines_var(m); } in m endif; /** @group builtins.arithmetic Return absolute value of \a x */ function float: abs(float: x); /** @group builtins.arithmetic Return absolute value of \a x */ function var float: abs(var float: x) :: promise_total = if has_bounds(x) then if lb(x) >= 0.0 then x else let { var 0.0..max(-lb(x),ub(x)): m ::is_defined_var; constraint float_abs(x,m) ::defines_var(m); } in m endif else let { var float: m ::is_defined_var; constraint m >= 0.0; constraint float_abs(x,m) ::defines_var(m); } in m endif; /** @group builtins.arithmetic Return \(\sqrt{\a x}\) */ function float: sqrt(float: x); /** @group builtins.arithmetic Return \(\sqrt{\a x}\) */ function var float: sqrt(var float: x) = let { constraint x >= 0.0; } in sqrt_t(x); function var float: sqrt_t(var float: x) ::promise_total = let { var float: r; var float: xx; constraint x < 0.0 -> xx = 1.0; constraint x < 0.0 \/ xx = x; constraint float_sqrt(xx,r); } in r; /** @group builtins.arithmetic Return \(\a x ^ {\a y}\) */ function int: pow(int: x, int: y); /** @group builtins.arithmetic Return \(\a x ^ {\a y}\) */ function var int: pow(var int: x, var int: y) = let { int: yy = if is_fixed(y) then fix(y) else -1 endif; } in if yy = 0 then 1 elseif yy = 1 then x else let { var int: r ::is_defined_var; constraint if is_fixed(y) then int_pow_fixed(x,fix(y),r) ::defines_var(r) else int_pow(x,y,r) ::defines_var(r) endif; } in r endif; /** @group builtins.arithmetic Return \(\a x ^ {\a y}\) */ function float: pow(float: x, float: y); /** @group builtins.arithmetic Return \(\a x ^ {\a y}\) */ function var float: pow(var float: x, var float: y) = let { float: yy = if is_fixed(y) then fix(y) else -1.0 endif } in if yy = 0.0 then 1.0 elseif yy = 1.0 then x else let { var float: r ::is_defined_var; constraint float_pow(x,y,r) ::defines_var(r); } in r endif; /*** @groupdef builtins.explog Exponential and logarithmic builtins These builtins implement exponential and logarithmic functions. */ /** @group builtins.explog Return \(e ^ {\a x}\) */ function float: exp(float: x); /** @group builtins.explog Return \(e ^ {\a x}\) */ function var float: exp(var float: x) ::promise_total = let { var float: r ::is_defined_var; constraint float_exp(x,r) ::defines_var(r); } in r; /** @group builtins.explog Return \(\ln \a x\) */ function float: ln(float: x); /** @group builtins.explog Return \(\ln \a x\) */ function var float: ln(var float: x) ::promise_total = let { var float: r ::is_defined_var; constraint float_ln(x,r) ::defines_var(r); } in r; /** @group builtins.explog Return \(\log_{10} \a x\) */ function float: log10(float: x); /** @group builtins.explog Return \(\log_{10} \a x\) */ function var float: log10(var float: x) ::promise_total = let { var float: r ::is_defined_var; constraint float_log10(x,r) ::defines_var(r); } in r; /** @group builtins.explog Return \(\log_{2} \a x\) */ function float: log2(float: x); /** @group builtins.explog Return \(\log_{2} \a x\) */ function var float: log2(var float: x) ::promise_total = let { var float: r ::is_defined_var; constraint float_log2(x,r) ::defines_var(r); } in r; /** @group builtins.explog Return \(\log_{\a x} \a y\) */ function float: log(float: x, float: y); /*** @groupdef builtins.trigonometric Trigonometric functions These builtins implement the standard trigonometric functions. */ /** @group builtins.trigonometric Return \(\sin \a x\) */ function float: sin(float: x); /** @group builtins.trigonometric Return \(\sin \a x\) */ function var float: sin(var float: x) ::promise_total = let { var -1.0..1.0: r ::is_defined_var; constraint float_sin(x,r) ::defines_var(r); } in r; /** @group builtins.trigonometric Return \(\cos \a x\) */ function float: cos(float: x); /** @group builtins.trigonometric Return \(\cos \a x\) */ function var float: cos(var float: x) ::promise_total = let { var -1.0..1.0: r ::is_defined_var; constraint float_cos(x,r) ::defines_var(r); } in r; /** @group builtins.trigonometric Return \(\tan \a x\) */ function float: tan(float: x); /** @group builtins.trigonometric Return \(\tan \a x\) */ function var float: tan(var float: x) ::promise_total = let { var float: r ::is_defined_var; constraint float_tan(x,r) ::defines_var(r); } in r; /** @group builtins.trigonometric Return \(\mbox{asin}\ \a x\) */ function float: asin(float: x); /** @group builtins.trigonometric Return \(\mbox{asin}\ \a x\) */ function var float: asin(var float: x) ::promise_total = let { var float: r ::is_defined_var; constraint float_asin(x,r) ::defines_var(r); } in r; /** @group builtins.trigonometric Return \(\mbox{acos}\ \a x\) */ function float: acos(float: x); /** @group builtins.trigonometric Return \(\mbox{acos}\ \a x\) */ function var float: acos(var float: x) ::promise_total = let { var float: r ::is_defined_var; constraint float_acos(x,r) ::defines_var(r); } in r; /** @group builtins.trigonometric Return \(\mbox{atan}\ \a x\) */ function float: atan(float: x); /** @group builtins.trigonometric Return \(\mbox{atan}\ \a x\) */ function var float: atan(var float: x) ::promise_total = let { var float: r ::is_defined_var; constraint float_atan(x,r) ::defines_var(r); } in r; /** @group builtins.trigonometric Return \(\sinh \a x\) */ function float: sinh(float: x); /** @group builtins.trigonometric Return \(\sinh \a x\) */ function var float: sinh(var float: x) ::promise_total = let { var float: r ::is_defined_var; constraint float_sinh(x,r) ::defines_var(r); } in r; /** @group builtins.trigonometric Return \(\cosh \a x\) */ function float: cosh(float: x); /** @group builtins.trigonometric Return \(\cosh \a x\) */ function var float: cosh(var float: x) ::promise_total = let { var float: r ::is_defined_var; constraint float_cosh(x,r) ::defines_var(r); } in r; /** @group builtins.trigonometric Return \(\tanh \a x\) */ function float: tanh(float: x); /** @group builtins.trigonometric Return \(\tanh \a x\) */ function var float: tanh(var float: x) ::promise_total = let { var float: r ::is_defined_var; constraint float_tanh(x,r) ::defines_var(r); } in r; /** @group builtins.trigonometric Return \(\mbox{asinh}\ \a x\) */ function float: asinh(float: x); /** @group builtins.trigonometric Return \(\mbox{asinh}\ \a x\) */ function var float: asinh(var float: x) ::promise_total = let { var float: r ::is_defined_var; constraint float_asinh(x,r) ::defines_var(r); } in r; /** @group builtins.trigonometric Return \(\mbox{acosh}\ \a x\) */ function float: acosh(float: x); /** @group builtins.trigonometric Return \(\mbox{acosh}\ \a x\) */ function var float: acosh(var float: x) ::promise_total = let { var float: r ::is_defined_var; constraint float_acosh(x,r) ::defines_var(r); } in r; /** @group builtins.trigonometric Return \(\mbox{atanh}\ \a x\) */ function float: atanh(float: x); /** @group builtins.trigonometric Return \(\mbox{atanh}\ \a x\) */ function var float: atanh(var float: x) ::promise_total = let { var float: r ::is_defined_var; constraint float_atanh(x,r) ::defines_var(r); } in r; /*** @groupdef builtins.logic Logical operations Logical operations are the standard operators of Boolean logic. */ /** @group builtins.logic Return truth value of \a x ∧ \a y */ function bool: '/\'( bool: x, bool: y); /** @group builtins.logic Return truth value of \a x ∧ \a y */ function var bool: '/\'(var bool: x, var bool: y); /** @group builtins.logic Return truth value of \a x ∨ \a y */ function bool: '\/'( bool: x, bool: y); /** @group builtins.logic Return truth value of \a x ∨ \a y */ function var bool: '\/'(var bool: x, var bool: y); /** @group builtins.logic Return truth value of \a x implies \a y */ function bool: '->'( bool: x, bool: y); /** @group builtins.logic Return truth value of \a x implies \a y */ function var bool: '->'(var bool: x, var bool: y); /** @group builtins.logic Return truth value of \a y implies \a x */ function bool: '<-'( bool: x, bool: y); /** @group builtins.logic Return truth value of \a y implies \a x */ function var bool: '<-'(var bool: x, var bool: y); /** @group builtins.logic Return truth value of \a x if-and-only-if \a y */ function bool: '<->'( bool: x, bool: y); /** @group builtins.logic Return truth value of \a x if-and-only-if \a y */ function var bool: '<->'(var bool: x, var bool: y); /** @group builtins.logic Return truth value of \a x xor \a y */ function bool: 'xor'( bool: x, bool: y); /** @group builtins.logic Return truth value of \a x xor \a y */ function var bool: 'xor'(var bool: x, var bool: y); /** @group builtins.logic Return truth value of the negation of \a x */ function bool: 'not'( bool: x); /** @group builtins.logic Return truth value of the negation of \a x */ function var bool: 'not'(var bool: x); /** @group builtins.logic Return truth value of \(\bigwedge_i \a x[i]\) */ function bool: forall(array[$T] of bool: x); /** @group builtins.logic Return truth value of \(\bigwedge_i \a x[i]\) */ function var bool: forall(array[$T] of var bool: x); /** @group builtins.logic Return truth value of \(\bigvee_i \a x[i]\) */ function bool: exists(array[$T] of bool: x); /** @group builtins.logic Return truth value of \(\bigvee_i \a x[i]\) */ function var bool: exists(array[$T] of var bool: x); /** @group builtins.logic Return truth value of \(\oplus_i \a x[i]\) */ function bool: xorall(array[$T] of bool: x); /** @group builtins.logic Return truth value of \(\oplus_i \a x[i]\) */ function var bool: xorall(array[$T] of var bool: x) = array_bool_xor(array1d(x)); /** @group builtins.logic Return truth value of \(\text{true}\oplus (\oplus_i \a x[i])\) */ function bool: iffall(array[$T] of bool: x); /** @group builtins.logic Return truth value of \(\text{true}\oplus (\oplus_i \a x[i])\) */ function var bool: iffall(array[$T] of var bool: x) = array_bool_xor(array1d(x)++[true]); /** @group builtins.logic Return truth value of \((\bigvee_i \a x[i]) \lor (\bigvee_j \lnot \a y[j])\) */ function var bool: clause(array[$T] of var bool: x, array[$T] of var bool: y); /** @group builtins.logic Return truth value of \((\bigvee_i \a x[i]) \lor (\bigvee_j \lnot \a y[j])\) */ function var bool: clause(array[$T] of bool: x, array[$T] of bool: y); /*** @groupdef builtins.set Set operations These functions implement the basic operations on sets. */ /** @group builtins.set Test if \a x is an element of the set \a y */ function bool: 'in'( int: x, set of int: y); /** @group builtins.set \a x is an element of the set \a y */ function var bool: 'in'(var int: x, var set of int: y); /** @group builtins.set Test if \a x is an element of the set \a y */ function bool: 'in'( float: x, set of float: y); /** @group builtins.set Test if \a x is an element of the set \a y */ function var bool: 'in'(var float: x, set of float: y); /** @group builtins.set Test if \a x is a subset of \a y */ function bool: 'subset'( set of $T: x, set of $T: y); /** @group builtins.set \a x is a subset of \a y */ function var bool: 'subset'(var set of int: x, var set of int: y); /** @group builtins.set Test if \a x is a superset of \a y */ function bool: 'superset'( set of $T: x, set of $T: y); /** @group builtins.set \a x is a superset of \a y */ function var bool: 'superset'(var set of int: x, var set of int: y); /** @group builtins.set Return the union of sets \a x and \a y */ function set of $T: 'union'( set of $T: x, set of $T: y); /** @group builtins.set Return the union of sets \a x and \a y */ function var set of $$T: 'union'(var set of $$T: x, var set of $$T: y); /** @group builtins.set Return the intersection of sets \a x and \a y */ function set of $T: 'intersect'( set of $T: x, set of $T: y); /** @group builtins.set Return the intersection of sets \a x and \a y */ function var set of $$T: 'intersect'(var set of $$T: x, var set of $$T: y); /** @group builtins.set Return the set difference of sets \a x − \a y */ function set of $T: 'diff'( set of $T: x, set of $T: y); /** @group builtins.set Return the set difference of sets \a x − \a y */ function var set of $$T: 'diff'(var set of $$T: x, var set of $$T: y); /** @group builtins.set Return the symmetric set difference of sets \a x and \a y */ function set of $T: 'symdiff'( set of $T: x, set of $T: y); /** @group builtins.set Return the symmetric set difference of sets \a x and \a y */ function var set of $$T: 'symdiff'(var set of $$T: x, var set of $$T: y); /** @group builtins.set Return the set \(\{\a a,\ldots,\a b\}\) */ function set of $$E: '..'($$E: a,$$E: b); /** @group builtins.set Return the set \(\{\a a,\ldots,\a b\}\) */ function set of float: '..'(float: a,float: b); function var set of int: '..'(var int: a, var int: b) ::promise_total = let { var set of min(lb(a),lb(b))..max(ub(a),ub(b)): s; constraint forall (i in ub(s)) (i in s <-> (a <= i /\ i <= b)); } in s; /** @group builtins.set Return the cardinality of the set \a x */ function int: card( set of $T: x); /** @group builtins.set Return the cardinality of the set \a x */ function var int: card(var set of int: x); /** @group builtins.set Return the union of the sets in array \a x */ function set of $U: array_union(array[$T] of set of $U: x); /** @group builtins.set Return the union of the sets in array \a x */ function var set of int: array_union(array[int] of var set of int: x) ::promise_total = if length(x)=0 then {} elseif length(x)=1 then x[min(index_set(x))] else let { int: l=min(index_set(x)); int: u=max(index_set(x)); array[l..u-1] of var set of ub_array(x): y; constraint y[l]=x[l] union x[l+1]; constraint forall (i in l+2..u) (y[i-1]=y[i-2] union x[i]); } in y[u-1] endif; /** @group builtins.set Return the intersection of the sets in array \a x */ function set of $U: array_intersect(array[$T] of set of $U: x); /** @group builtins.set Return the intersection of the sets in array \a x */ function var set of int: array_intersect(array[int] of var set of int: x) ::promise_total = if length(x)=0 then assert(false,"can't be!",-infinity..infinity) elseif length(x)=1 then x[min(index_set(x))] else let { int: l=min(index_set(x)); int: u=max(index_set(x)); array[l..u-1] of var set of ub_array(x): y; constraint y[l]=x[l] intersect x[l+1]; constraint forall (i in l+2..u) (y[i-1]=y[i-2] intersect x[i]); } in y[u-1] endif; /** @group builtins.set Return the minimum of the set \a s */ function var $$E: min(var set of $$E: s); /** @group builtins.set Return the maximum of the set \a s */ function var $$E: max(var set of $$E: s); /*** @groupdef builtins.array Array operations These functions implement the basic operations on arrays. */ /** @group builtins.array Return the concatenation of arrays \a x and \a y */ function array[int] of $T: '++'(array[int] of $T: x, array[int] of $T: y); /** @group builtins.array Return the concatenation of arrays \a x and \a y */ function array[int] of opt $T: '++'(array[int] of opt $T: x, array[int] of opt $T: y); /** @group builtins.array Return the concatenation of arrays \a x and \a y */ function array[int] of var $T: '++'(array[int] of var $T: x, array[int] of var $T: y); /** @group builtins.array Return the concatenation of arrays \a x and \a y */ function array[int] of var opt $T: '++'(array[int] of var opt $T: x, array[int] of var opt $T: y); /** @group builtins.array Return the length of array \a x Note that the length is defined as the number of elements in the array, regardless of its dimensionality. */ function int: length(array[$T] of var opt $U: x); /** @group builtins.array Return the array \a x in reverse order The resulting array has the same index set as \a x. */ function array[$$E] of $T: reverse(array[$$E] of $T: x) = let { int: l = max(index_set(x))+min(index_set(x)) } in array1d(index_set(x),[x[l-i] | i in index_set(x)]); /** @group builtins.array Return the array \a x in reverse order The resulting array has the same index set as \a x. */ function array[$$E] of opt $T: reverse(array[$$E] of opt $T: x) = let { int: l = max(index_set(x))+min(index_set(x)) } in array1d(index_set(x),[x[l-i] | i in index_set(x)]); /** @group builtins.array Return the array \a x in reverse order The resulting array has the same index set as \a x. */ function array[$$E] of var $T: reverse(array[$$E] of var $T: x) = let { int: l = max(index_set(x))+min(index_set(x)) } in array1d(index_set(x),[x[l-i] | i in index_set(x)]); /** @group builtins.array Return the array \a x in reverse order The resulting array has the same index set as \a x. */ function array[$$E] of var opt $T: reverse(array[$$E] of var opt $T: x) = let { int: l = max(index_set(x))+min(index_set(x)) } in array1d(index_set(x),[x[l-i] | i in index_set(x)]); /** @group builtins.array Test if \a x and \a y have the same index sets */ test index_sets_agree(array[$T] of var opt $U: x, array[$T] of var opt $W: y); /** @group builtins.array Return index set of one-dimensional array \a x */ function set of $$E: index_set(array[$$E] of var opt $U: x); /** @group builtins.array Return index set of first dimension of two-dimensional array \a x */ function set of $$E: index_set_1of2(array[$$E,int] of var opt $U: x); /** @group builtins.array Return index set of second dimension of two-dimensional array \a x */ function set of $$E: index_set_2of2(array[int,$$E] of var opt $U: x); /** @group builtins.array Return index set of first dimension of 3-dimensional array \a x */ function set of $$E: index_set_1of3(array[$$E,int,int] of var opt $U: x); /** @group builtins.array Return index set of second dimension of 3-dimensional array \a x */ function set of $$E: index_set_2of3(array[int,$$E,int] of var opt $U: x); /** @group builtins.array Return index set of third dimension of 3-dimensional array \a x */ function set of $$E: index_set_3of3(array[int,int,$$E] of var opt $U: x); /** @group builtins.array Return index set of first dimension of 4-dimensional array \a x */ function set of $$E: index_set_1of4(array[$$E,int,int,int] of var opt $U: x); /** @group builtins.array Return index set of second dimension of 4-dimensional array \a x */ function set of $$E: index_set_2of4(array[int,$$E,int,int] of var opt $U: x); /** @group builtins.array Return index set of third dimension of 4-dimensional array \a x */ function set of $$E: index_set_3of4(array[int,int,$$E,int] of var opt $U: x); /** @group builtins.array Return index set of fourth dimension of 4-dimensional array \a x */ function set of $$E: index_set_4of4(array[int,int,int,$$E] of var opt $U: x); /** @group builtins.array Return index set of first dimension of 5-dimensional array \a x */ function set of $$E: index_set_1of5(array[$$E,int,int,int,int] of var opt $U: x); /** @group builtins.array Return index set of second dimension of 5-dimensional array \a x */ function set of $$E: index_set_2of5(array[int,$$E,int,int,int] of var opt $U: x); /** @group builtins.array Return index set of third dimension of 5-dimensional array \a x */ function set of $$E: index_set_3of5(array[int,int,$$E,int,int] of var opt $U: x); /** @group builtins.array Return index set of fourth dimension of 5-dimensional array \a x */ function set of $$E: index_set_4of5(array[int,int,int,$$E,int] of var opt $U: x); /** @group builtins.array Return index set of fifth dimension of 5-dimensional array \a x */ function set of $$E: index_set_5of5(array[int,int,int,int,$$E] of var opt $U: x); /** @group builtins.array Return index set of first dimension of 6-dimensional array \a x */ function set of $$E: index_set_1of6(array[$$E,int,int,int,int,int] of var opt $U: x); /** @group builtins.array Return index set of second dimension of 6-dimensional array \a x */ function set of $$E: index_set_2of6(array[int,$$E,int,int,int,int] of var opt $U: x); /** @group builtins.array Return index set of third dimension of 6-dimensional array \a x */ function set of $$E: index_set_3of6(array[int,int,$$E,int,int,int] of var opt $U: x); /** @group builtins.array Return index set of fourth dimension of 6-dimensional array \a x */ function set of $$E: index_set_4of6(array[int,int,int,$$E,int,int] of var opt $U: x); /** @group builtins.array Return index set of fifth dimension of 6-dimensional array \a x */ function set of $$E: index_set_5of6(array[int,int,int,int,$$E,int] of var opt $U: x); /** @group builtins.array Return index set of sixth dimension of 6-dimensional array \a x */ function set of $$E: index_set_6of6(array[int,int,int,int,int,$$E] of var opt $U: x); /** @group builtins.array Return array \a x coerced to index set 1..length(\a x). Coercions are perfomed by considering the array \a x in row-major order. */ function array[int] of $V: array1d(array[$U] of $V: x); /** @group builtins.array Return array \a x coerced to index set 1..length(\a x). Coercions are perfomed by considering the array \a x in row-major order. */ function array[int] of opt $V: array1d(array[$U] of opt $V: x); /** @group builtins.array Return array \a x coerced to index set 1..length(\a x). Coercions are perfomed by considering the array \a x in row-major order. */ function array[int] of var $V: array1d(array[$U] of var $V: x); /** @group builtins.array Return array \a x coerced to index set 1..length(\a x). Coercions are perfomed by considering the array \a x in row-major order. */ function array[int] of var opt $V: array1d(array[$U] of var opt $V: x); /** @group builtins.array Return array \a x coerced to one-dimensional array with index set \a S. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E] of $V: array1d(set of $$E: S, array[$U] of $V: x); /** @group builtins.array Return array \a x coerced to one-dimensional array with index set \a S. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E] of opt $V: array1d(set of $$E: S, array[$U] of opt $V: x); /** @group builtins.array Return array \a x coerced to one-dimensional array with index set \a S. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E] of var $V: array1d(set of $$E: S, array[$U] of var $V: x); /** @group builtins.array Return array \a x coerced to one-dimensional array with index set \a S. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E] of var opt $V: array1d(set of $$E: S, array[$U] of var opt $V: x); /** @group builtins.array Return array \a x coerced to two-dimensional array with index sets \a S1 and \a S2. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F] of $V: array2d(set of $$E: S1, set of $$F: S2, array[$U] of $V: x); /** @group builtins.array Return array \a x coerced to two-dimensional array with index sets \a S1 and \a S2. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F] of opt $V: array2d(set of $$E: S1, set of $$F: S2, array[$U] of opt $V: x); /** @group builtins.array Return array \a x coerced to two-dimensional array with index sets \a S1 and \a S2. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F] of var $V: array2d(set of $$E: S1, set of $$F: S2, array[$U] of var $V: x); /** @group builtins.array Return array \a x coerced to two-dimensional array with index sets \a S1 and \a S2. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F] of var opt $V: array2d(set of $$E: S1, set of $$F: S2, array[$U] of var opt $V: x); /** @group builtins.array Return array \a x coerced to three-dimensional array with index sets \a S1, \a S2 and \a S3. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F,$$G] of $V: array3d(set of $$E: S1, set of $$F: S2, set of $$G: S3, array[$U] of $V: x); /** @group builtins.array Return array \a x coerced to three-dimensional array with index sets \a S1, \a S2 and \a S3. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F,$$G] of opt $V: array3d(set of $$E: S1, set of $$F: S2, set of $$G: S3, array[$U] of opt $V: x); /** @group builtins.array Return array \a x coerced to three-dimensional array with index sets \a S1, \a S2 and \a S3. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F,$$G] of var $V: array3d(set of $$E: S1, set of $$F: S2, set of $$G: S3, array[$U] of var $V: x); /** @group builtins.array Return array \a x coerced to three-dimensional array with index sets \a S1, \a S2 and \a S3. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F,$$G] of var opt $V: array3d(set of $$E: S1, set of $$F: S2, set of $$G: S3, array[$U] of var opt $V: x); /** @group builtins.array Return array \a x coerced to 4-dimensional array with index sets \a S1, \a S2, \a S3 and \a S4. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F,$$G,$$H] of $V: array4d(set of $$E: S1, set of $$F: S2, set of $$G: S3, set of $$H: S4, array[$U] of $V: x); /** @group builtins.array Return array \a x coerced to 4-dimensional array with index sets \a S1, \a S2, \a S3 and \a S4. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F,$$G,$$H] of opt $V: array4d(set of $$E: S1, set of $$F: S2, set of $$G: S3, set of $$H: S4, array[$U] of opt $V: x); /** @group builtins.array Return array \a x coerced to 4-dimensional array with index sets \a S1, \a S2, \a S3 and \a S4. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F,$$G,$$H] of var $V: array4d(set of $$E: S1, set of $$F: S2, set of $$G: S3, set of $$H: S4, array[$U] of var $V: x); /** @group builtins.array Return array \a x coerced to 4-dimensional array with index sets \a S1, \a S2, \a S3 and \a S4. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F,$$G,$$H] of var opt $V: array4d(set of $$E: S1, set of $$F: S2, set of $$G: S3, set of $$H: S4, array[$U] of var opt $V: x); /** @group builtins.array Return array \a x coerced to 5-dimensional array with index sets \a S1, \a S2, \a S3, \a S4 and \a S5. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F,$$G,$$H,$$I] of $V: array5d(set of $$E: S1, set of $$F: S2, set of $$G: S3, set of $$H: S4, set of $$I: S5, array[$U] of $V: x); /** @group builtins.array Return array \a x coerced to 5-dimensional array with index sets \a S1, \a S2, \a S3, \a S4 and \a S5. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F,$$G,$$H,$$I] of opt $V: array5d(set of $$E: S1, set of $$F: S2, set of $$G: S3, set of $$H: S4, set of $$I: S5, array[$U] of opt $V: x); /** @group builtins.array Return array \a x coerced to 5-dimensional array with index sets \a S1, \a S2, \a S3, \a S4 and \a S5. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F,$$G,$$H,$$I] of var $V: array5d(set of $$E: S1, set of $$F: S2, set of $$G: S3, set of $$H: S4, set of $$I: S5, array[$U] of var $V: x); /** @group builtins.array Return array \a x coerced to 5-dimensional array with index sets \a S1, \a S2, \a S3, \a S4 and \a S5. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F,$$G,$$H,$$I] of var opt $V: array5d(set of $$E: S1, set of $$F: S2, set of $$G: S3, set of $$H: S4, set of $$I: S5, array[$U] of var opt $V: x); /** @group builtins.array Return array \a x coerced to 6-dimensional array with index sets \a S1, \a S2, \a S3, \a S4, \a S5 and \a S6. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F,$$G,$$H,$$I,$$J] of $V: array6d(set of $$E: S1, set of $$F: S2, set of $$G: S3, set of $$H: S4, set of $$I: S5, set of $$J: S6, array[$U] of $V: x); /** @group builtins.array Return array \a x coerced to 6-dimensional array with index sets \a S1, \a S2, \a S3, \a S4, \a S5 and \a S6. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F,$$G,$$H,$$I,$$J] of opt $V: array6d(set of $$E: S1, set of $$F: S2, set of $$G: S3, set of $$H: S4, set of $$I: S5, set of $$J: S6, array[$U] of opt $V: x); /** @group builtins.array Return array \a x coerced to 6-dimensional array with index sets \a S1, \a S2, \a S3, \a S4, \a S5 and \a S6. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F,$$G,$$H,$$I,$$J] of var $V: array6d(set of $$E: S1, set of $$F: S2, set of $$G: S3, set of $$H: S4, set of $$I: S5, set of $$J: S6, array[$U] of var $V: x); /** @group builtins.array Return array \a x coerced to 6-dimensional array with index sets \a S1, \a S2, \a S3, \a S4, \a S5 and \a S6. Coercions are perfomed by considering the array \a x in row-major order. */ function array[$$E,$$F,$$G,$$H,$$I,$$J] of var opt $V: array6d(set of $$E: S1, set of $$F: S2, set of $$G: S3, set of $$H: S4, set of $$I: S5, set of $$J: S6, array[$U] of var opt $V: x); /** @group builtins.array Return array \a y coerced to array with same number of dimensions and same index sets as array \a x. Coercions are perfomed by considering the array \a y in row-major order. */ function array[$T] of $V: arrayXd(array[$T] of var opt $X: x, array[$U] of $V: y); /** @group builtins.array Return array \a y coerced to array with same number of dimensions and same index sets as array \a x. Coercions are perfomed by considering the array \a y in row-major order. */ function array[$T] of opt $V: arrayXd(array[$T] of var opt $X: x, array[$U] of opt $V: y); /** @group builtins.array Return array \a y coerced to array with same number of dimensions and same index sets as array \a x. Coercions are perfomed by considering the array \a y in row-major order. */ function array[$T] of var $V: arrayXd(array[$T] of var opt $X: x, array[$U] of var $V: y); /** @group builtins.array Return array \a y coerced to array with same number of dimensions and same index sets as array \a x. Coercions are perfomed by considering the array \a y in row-major order. */ function array[$T] of var opt $V: arrayXd(array[$T] of var opt $X: x, array[$U] of var opt $V: y); /** @group builtins.array Return row \a r of array \a x */ function array[$$E] of $T: row(array[int, $$E] of $T: x, int: r) = x[r,..]; /** @group builtins.array Return row \a r of array \a x */ function array[$$E] of opt $T: row(array[int, $$E] of opt $T: x, int: r) = x[r,..]; /** @group builtins.array Return row \a r of array \a x */ function array[$$E] of var $T: row(array[int, $$E] of var $T: x, int: r) = x[r,..]; /** @group builtins.array Return row \a r of array \a x */ function array[$$E] of var opt $T: row(array[int, $$E] of var opt $T: x, int: r) = x[r,..]; /** @group builtins.array Return column \a c of array \a x */ function array[$$E] of $T: col(array[$$E,int] of $T: x, int: c) = x[..,c]; /** @group builtins.array Return column \a c of array \a x */ function array[$$E] of opt $T: col(array[$$E,int] of opt $T: x, int: c) = x[..,c]; /** @group builtins.array Return column \a c of array \a x */ function array[$$E] of var $T: col(array[$$E,int] of var $T: x, int: c) = x[..,c]; /** @group builtins.array Return column \a c of array \a x */ function array[$$E] of var opt $T: col(array[$$E,int] of var opt $T: x, int: c) = x[..,c]; /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new array with index sets \a dims */ function array[int] of $T: slice_Xd(array[$E] of $T: x, array[int] of set of int: s, array[int] of set of int: dims); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 1d array with index set \a dims1 */ function array[int] of $T: slice_1d(array[$E] of $T: x, array[int] of set of int: s, set of int: dims1); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 2d array with index sets \a dims1 and \a dims2 */ function array[int,int] of $T: slice_2d(array[$E] of $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 3d array with index sets \a dims1, \a dims2 and \a dims3 */ function array[int,int,int] of $T: slice_3d(array[$E] of $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2, set of int: dims3); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 3d array with index sets \a dims1, \a dims2, \a dims3, \a dims4 */ function array[int,int,int] of $T: slice_4d(array[$E] of $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2, set of int: dims3, set of int: dims4); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 3d array with index sets \a dims1, \a dims2, \a dims3, \a dims4, \a dims5 */ function array[int,int,int] of $T: slice_5d(array[$E] of $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2, set of int: dims3, set of int: dims4, set of int: dims5); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 3d array with index sets \a dims1, \a dims2, \a dims3, \a dims4, \a dims5, \a dims6 */ function array[int,int,int] of $T: slice_6d(array[$E] of $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2, set of int: dims3, set of int: dims4, set of int: dims5, set of int: dims6); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new array with index sets \a dims */ function array[int] of opt $T: slice_Xd(array[$E] of opt $T: x, array[int] of set of int: s, array[int] of set of int: dims); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 1d array with index set \a dims1 */ function array[int] of opt $T: slice_1d(array[$E] of opt $T: x, array[int] of set of int: s, set of int: dims1); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 2d array with index sets \a dims1 and \a dims2 */ function array[int,int] of opt $T: slice_2d(array[$E] of opt $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 3d array with index sets \a dims1, \a dims2 and \a dims3 */ function array[int,int,int] of opt $T: slice_3d(array[$E] of opt $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2, set of int: dims3); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 3d array with index sets \a dims1, \a dims2, \a dims3, \a dims4 */ function array[int,int,int] of opt $T: slice_4d(array[$E] of opt $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2, set of int: dims3, set of int: dims4); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 3d array with index sets \a dims1, \a dims2, \a dims3, \a dims4, \a dims5 */ function array[int,int,int] of opt $T: slice_5d(array[$E] of opt $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2, set of int: dims3, set of int: dims4, set of int: dims5); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 3d array with index sets \a dims1, \a dims2, \a dims3, \a dims4, \a dims5, \a dims6 */ function array[int,int,int] of opt $T: slice_6d(array[$E] of opt $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2, set of int: dims3, set of int: dims4, set of int: dims5, set of int: dims6); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new array with index sets \a dims */ function array[int] of var $T: slice_Xd(array[$E] of var $T: x, array[int] of set of int: s, array[int] of set of int: dims); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 1d array with index set \a dims1 */ function array[int] of var $T: slice_1d(array[$E] of var $T: x, array[int] of set of int: s, set of int: dims1); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 2d array with index sets \a dims1 and \a dims2 */ function array[int,int] of var $T: slice_2d(array[$E] of var $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 3d array with index sets \a dims1, \a dims2 and \a dims3 */ function array[int,int,int] of var $T: slice_3d(array[$E] of var $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2, set of int: dims3); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 3d array with index sets \a dims1, \a dims2, \a dims3, \a dims4 */ function array[int,int,int] of var $T: slice_4d(array[$E] of var $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2, set of int: dims3, set of int: dims4); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 3d array with index sets \a dims1, \a dims2, \a dims3, \a dims4, \a dims5 */ function array[int,int,int] of var $T: slice_5d(array[$E] of var $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2, set of int: dims3, set of int: dims4, set of int: dims5); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 3d array with index sets \a dims1, \a dims2, \a dims3, \a dims4, \a dims5, \a dims6 */ function array[int,int,int] of var $T: slice_6d(array[$E] of var $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2, set of int: dims3, set of int: dims4, set of int: dims5, set of int: dims6); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new array with index sets \a dims */ function array[int] of var opt $T: slice_Xd(array[$E] of var opt $T: x, array[int] of set of int: s, array[int] of set of int: dims); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 1d array with index set \a dims1 */ function array[int] of var opt $T: slice_1d(array[$E] of var opt $T: x, array[int] of set of int: s, set of int: dims1); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 2d array with index sets \a dims1 and \a dims2 */ function array[int,int] of var opt $T: slice_2d(array[$E] of var opt $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 3d array with index sets \a dims1, \a dims2 and \a dims3 */ function array[int,int,int] of var opt $T: slice_3d(array[$E] of var opt $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2, set of int: dims3); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 3d array with index sets \a dims1, \a dims2, \a dims3, \a dims4 */ function array[int,int,int] of var opt $T: slice_4d(array[$E] of var opt $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2, set of int: dims3, set of int: dims4); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 3d array with index sets \a dims1, \a dims2, \a dims3, \a dims4, \a dims5 */ function array[int,int,int] of var opt $T: slice_5d(array[$E] of var opt $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2, set of int: dims3, set of int: dims4, set of int: dims5); /** @group builtins.array Return slice of array \a x specified by sets \a s, coerced to new 3d array with index sets \a dims1, \a dims2, \a dims3, \a dims4, \a dims5, \a dims6 */ function array[int,int,int] of var opt $T: slice_6d(array[$E] of var opt $T: x, array[int] of set of int: s, set of int: dims1, set of int: dims2, set of int: dims3, set of int: dims4, set of int: dims5, set of int: dims6); /** @group builtins.array Test if \a i is in the index set of \a x */ test has_index(int: i, array[int] of var opt $T: x) = i in index_set(x); /** @group builtins.array Test if \a e is an element of array \a x */ test has_element($T: e, array[int] of $T: x) = exists (i in index_set(x)) (x[i]=e); /** @group builtins.array Test if \a e is an element of array \a x */ test has_element($T: e, array[int] of opt $T: x) = exists (i in index_set(x)) (x[i]=e); /** @group builtins.array Test if \a e is an element of array \a x */ predicate has_element($T: e, array[$$E] of var opt $T: x) = exists (i in index_set(x)) (x[i]=e); /*** @groupdef builtins.sort Array sorting operations */ /** @group builtins.sort Return array \a x sorted by the values in \a y in non-decreasing order The sort is stable, i.e. if \a y[\p i] = \a y[\p j] with \p i < \p j, then \a x[\p i] will appear in the output before \a x[\p j]. */ function array[$$E] of var opt $T: sort_by(array[$$E] of var opt $T: x, array[$$E] of int: y); /** @group builtins.sort Return array \a x sorted by the values in \a y in non-decreasing order The sort is stable, i.e. if \a y[\p i] = \a y[\p j] with \p i < \p j, then \a x[\p i] will appear in the output before \a x[\p j]. */ function array[$$E] of var $T: sort_by(array[$$E] of var $T: x, array[$$E] of int: y); /** @group builtins.sort Return array \a x sorted by the values in \a y in non-decreasing order The sort is stable, i.e. if \a y[\p i] = \a y[\p j] with \p i < \p j, then \a x[\p i] will appear in the output before \a x[\p j]. */ function array[$$E] of $T: sort_by(array[$$E] of $T: x, array[$$E] of int: y); /** @group builtins.sort Return array \a x sorted by the values in \a y in non-decreasing order The sort is stable, i.e. if \a y[\p i] = \a y[\p j] with \p i < \p j, then \a x[\p i] will appear in the output before \a x[\p j]. */ function array[$$E] of var opt $T: sort_by(array[$$E] of var opt $T: x, array[$$E] of float: y); /** @group builtins.sort Return array \a x sorted by the values in \a y in non-decreasing order The sort is stable, i.e. if \a y[\p i] = \a y[\p j] with \p i < \p j, then \a x[\p i] will appear in the output before \a x[\p j]. */ function array[$$E] of var $T: sort_by(array[$$E] of var $T: x, array[$$E] of float: y); /** @group builtins.sort Return array \a x sorted by the values in \a y in non-decreasing order The sort is stable, i.e. if \a y[\p i] = \a y[\p j] with \p i < \p j, then \a x[\p i] will appear in the output before \a x[\p j]. */ function array[$$E] of $T: sort_by(array[$$E] of $T: x, array[$$E] of float: y); function array[$$E] of bool: internal_sort(array[$$E] of bool: x); function array[$$E] of int: internal_sort(array[$$E] of int: x); /** @group builtins.sort Return values from array \a x sorted in non-decreasing order */ function array[$$E] of int: sort(array[$$E] of int: x) = internal_sort(x); /** @group builtins.sort Return values from array \a x sorted in non-decreasing order */ function array[$$E] of float: sort(array[$$E] of float: x); /** @group builtins.sort Return values from array \a x sorted in non-decreasing order */ function array[$$E] of bool: sort(array[$$E] of bool: x) = internal_sort(x); /** @group builtins.sort Returns the permutation \a p which causes \a x to be in sorted order hence \a x[\a p[\p i]] <= \a x[\a p[\p i+1]]. The permutation is the stable sort hence \a x[\a p[\p i]] = \a x[\a p[\p i+1]] \(\rightarrow\) \a p[\p i] < \a p[\p i+1]. */ function array[int] of $$E: arg_sort(array[$$E] of int:x) = sort_by([i | i in index_set(x)], x); /** @group builtins.sort Returns the permutation \a p which causes \a x to be in sorted order hence \a x[\a p[\p i]] <= \a x[\a p[\p i+1]]. The permutation is the stable sort hence \a x[\a p[\p i]] = \a x[\a p[\p i+1]] \(\rightarrow\) \a p[\p i] < \a p[\p i+1]. */ function array[int] of $$E: arg_sort(array[$$E] of float:x) = sort_by([i | i in index_set(x)], x); /*** @groupdef builtins.coercion Coercions These functions implement coercions, or channeling, between different types. */ /** @group builtins.coercion Return \( \lceil{ \a x} \rceil \) */ function int: ceil(float: x); /** @group builtins.coercion Return \( \lfloor{ \a x} \rfloor \) */ function int: floor(float: x); /** @group builtins.coercion Return \a x rounded to nearest integer */ function int: round(float: x); /** @group builtins.coercion Return Boolean \a b coerced to an integer */ function int: bool2int(bool: b); /** @group builtins.coercion Return Boolean \a b coerced to a float */ function float: bool2float(bool: b) = if b then 1.0 else 0.0 endif; /** @group builtins.coercion Return array of Booleans \a x coerced to an array of floats */ function array[$T] of float: bool2float(array[$T] of bool: x) ::promise_total = let { array[int] of bool: xx = array1d(x) } in arrayXd(x,[bool2float(xx[i]) | i in index_set(xx)]); /** @group builtins.coercion Return array of Booleans \a x coerced to an array of floats */ function array[$T] of var float: bool2float(array[$T] of var bool: x) ::promise_total = let { array[int] of var bool: xx = array1d(x) } in arrayXd(x,[bool2float(xx[i]) | i in index_set(xx)]); /** @group builtins.coercion Return Boolean \a b coerced to an integer */ function var int: bool2int(var bool: b); /** @group builtins.coercion Return array of Booleans \a b coerced to an array of integers */ function array[$$E] of var int: bool2int(array[$$E] of var bool: b); /** @group builtins.coercion Return Boolean \a b coerced to a float */ function var float: bool2float(var bool: b) = int2float(bool2int(b)); /** @group builtins.coercion Return integer \a x coerced to a float */ function float: int2float(int: x); /** @group builtins.coercion Return integer \a x coerced to a float */ function var float: int2float(var int: x) ::promise_total; function set of int: bool2int(set of bool: b) = if b={false,true} then {0,1} elseif b={false} then {0} elseif b={true} then {1} else {} endif; /** @group builtins.coercion Return array of Booleans \a x coerced to an array of integers */ function array[$T] of int: bool2int(array[$T] of bool: x) ::promise_total = let { array[int] of bool: xx = array1d(x) } in arrayXd(x,[bool2int(xx[i]) | i in index_set(xx)]); /** @group builtins.coercion Return array of sets of Booleans \a x coerced to an array of sets of integers */ function array[$T] of set of int: bool2int(array[$T] of set of bool: x) ::promise_total = let { array[int] of set of bool: xx = array1d(x) } in arrayXd(x,[bool2int(xx[i]) | i in index_set(xx)]); /** @group builtins.coercion Return array of Booleans \a x coerced to an array of integers */ function array[$T] of var int: bool2int(array[$T] of var bool: x) ::promise_total = let { array[int] of var bool: xx = array1d(x) } in arrayXd(x,[bool2int(xx[i]) | i in index_set(xx)]); /** @group builtins.coercion Return array of Booleans \a x coerced to an array of integers */ function array[$T] of var opt int: bool2int(array[$T] of var opt bool: x) ::promise_total = let { array[int] of var opt bool: xx = array1d(x) } in arrayXd(x,[bool2int(xx[i]) | i in index_set(xx)]); /** @group builtins.coercion Return array of integers \a x coerced to an array of floats */ function array[$T] of float: int2float(array[$T] of int: x) ::promise_total = let { array[int] of int: xx = array1d(x) } in arrayXd(x,[int2float(xx[i]) | i in index_set(xx)]); /** @group builtins.coercion Return array of integers \a x coerced to an array of floats */ function array[$T] of var float: int2float(array[$T] of var int: x) ::promise_total = let { array[int] of var int: xx = array1d(x) } in arrayXd(x,[int2float(xx[i]) | i in index_set(xx)]); % Only supported for set of int: % function array[int] of $T: set2array(set of $T); /** @group builtins.coercion Return a set of integers \a x coerced to an array of integers */ function array[int] of $$E: set2array(set of $$E: x); /*** @groupdef builtins.string String operations These functions implement operations on strings. */ /** @group builtins.string Convert \a x into a string */ function string: show(var opt set of $T: x); /** @group builtins.string Convert \a x into a string */ function string: show(var opt $T: x); /** @group builtins.string Convert \a x into a string */ function string: show(array[$U] of var opt $T: x); function string: showDzn(var opt set of $T: x); function string: showDzn(var opt $T: x); function string: showDzn(array[$U] of var opt $T: x); function string: showDznId(string: x); /** @group builtins.string Formatted to-string conversion for integers Converts the integer \a x into a string right justified by the number of characters given by \a w, or left justified if \a w is negative. */ function string: show_int(int: w, var int: x); /** @group builtins.string Formatted to-string conversion for floats. Converts the float \a x into a string right justified by the number of characters given by \a w, or left justified if \a w is negative. The number of digits to appear after the decimal point is given by \a p. It is a run-time error for \a p to be negative. */ function string: show_float(int: w, int: p, var float: x); /** @group builtins.string Convert two-dimensional array \a x into a string */ function string: show2d(array[int,int] of var opt $T: x) = let { int: rows=card(index_set_1of2(x)); int: cols=card(index_set_2of2(x)); array[int] of string: s = [show(x[i,j]) | i in index_set_1of2(x), j in index_set_2of2(x)]; int: max_length = max([string_length(s[i]) | i in index_set(s)]) } in "[| "++ concat([format_justify_string(max_length,s[(i-1)*cols+j])++ if j min(e) } in x-1; /** @group builtins.enum Convert \a x to enum type \a X */ function $$E: to_enum(set of $$E: X, int: x); /** @group builtins.enum Convert \a x to enum type \a X */ function var $$E: to_enum(set of $$E: X, var int: x) = let { constraint x in X } in x; /** @group builtins.enum Convert \a x to enum type \a X */ function array[$U] of $$E: to_enum(set of $$E: X, array[$U] of int: x) = let { array[int] of int: xx = array1d(x) } in arrayXd(x, [ to_enum(X,xx[i]) | i in index_set(xx)]); /** @group builtins.enum Convert \a x to enum type \a X */ function array[$U] of var $$E: to_enum(set of $$E: X, array[$U] of var int: x) = let { array[int] of var int: xx = array1d(x) } in arrayXd(x, [ to_enum(X,xx[i]) | i in index_set(xx)]); /** @group builtins.enum Convert \a x to enum type \a X */ function set of $$E: to_enum(set of $$E: X, set of int: x) = { to_enum(X,i) | i in x }; %/** @group builtins.enum Convert \a x to enum type \a X */ function var set of $$E: to_enum(set of $$E: X, var set of int: x) = let { var set of X: y; constraint x subset X; constraint forall (i in X) (i in x <-> i in y); } in y; %-----------------------------------------------------------------------------% % % Internal compiler functions % % These functions are used internally by the compiler. % % domain constraints predicate var_dom(var int:x, set of int: s) = if has_bounds(x) /\ dom(x) subset s then true else x in s endif; predicate var_dom(var set of int: x, set of int: s) = if has_ub_set(x) /\ ub(x) subset s then true else set_subset(x,s) endif; predicate var_dom(var float:x, float: l, float: u) = if has_bounds(x) /\ lb(x) >= l /\ ub(x) <= u then true else x >= l /\ x <= u endif; predicate var_dom(var float:x, set of float: d) = x in d; test var_dom(float:x, float: l, float: u) = x >= l /\ x <= u; test var_dom(float:x, set of float: d) = x in d; predicate var_dom(array[$T] of var set of int: x, set of int: d) = let { array[int] of var set of int: xx = array1d(x) } in forall (i in index_set(xx)) (var_dom(xx[i],d)); predicate var_dom(array[$T] of var int: x, set of int: d) = let { array[int] of var int: xx = array1d(x) } in forall (i in index_set(xx)) (var_dom(xx[i],d)); predicate var_dom(array[$T] of var float: x, float: l, float: u) = let { array[int] of var float: xx = array1d(x) } in forall (i in index_set(xx)) (var_dom(xx[i],l,u)); predicate var_dom(array[$T] of var float: x, set of float: d) = let { array[int] of var float: xx = array1d(x) } in forall (i in index_set(xx)) (var_dom(xx[i],d)); test var_dom(array[$T] of set of int: x, set of int: d) = let { array[int] of set of int: xx = array1d(x) } in forall (i in index_set(xx)) (xx[i] subset d); test var_dom(array[$T] of int: x, set of int: d) = let { array[int] of int: xx = array1d(x) } in forall (i in index_set(xx)) (xx[i] in d); test var_dom(array[$T] of float: x, float: l, float: u) = let { array[int] of float: xx = array1d(x) } in forall (i in index_set(xx)) (var_dom(xx[i],l,u)); test var_dom(array[$T] of float: x, set of float: d) = let { array[int] of float: xx = array1d(x) } in forall (i in index_set(xx)) (var_dom(xx[i],d)); function var set of int: array2set(array[int] of var int: x) ::promise_total = let { var set of int: y = array_union([ let { var set of dom(x[i]): s; constraint x[i] in s /\ card(s)=1; } in s | i in index_set(x)]); } in y; function set of $$T: array2set(array[int] of $$T: x) = { x[i] | i in index_set(x) }; predicate array_var_int_element(var int: x, array[int] of int: y, var int: z) = array_int_element(x,y,z); predicate array_var_bool_element(var int: x, array[int] of bool: y, var bool: z) = array_bool_element(x,y,z); predicate array_var_float_element(var int: x, array[int] of float: y, var float: z) = array_float_element(x,y,z); predicate array_var_set_element(var int: x, array[int] of set of int: y, var set of int: z) = array_set_element(x,y,z); predicate bool_xor_reif(var bool: a, var bool: b, var bool: c) = bool_xor(a,b,c); predicate xorall_reif(array[int] of var bool: b, var bool: c) = let { var bool: nc ::is_defined_var; constraint xorall([nc]++b) ::defines_var(nc); } in c = not nc; function var int: lin_exp(array[int] of int, array[int] of var int, int); function var float: lin_exp(array[int] of float, array[int] of var float, float); test mzn_in_root_context(var $T); test mzn_in_redundant_constraint(); %-----------------------------------------------------------------------------% % % Element constraint implementations % % MiniZinc compiles element constraints using a series of intermediate % functions that test whether the constraint is total and perform array slicing % for multi-dimensional element constraints. % %%%%%%%%%%%%%%%%%%% % Element on ints function var int: element_t(var int: idx, array[int] of var int: x) :: promise_total = let { var dom_bounds_array(x): r ::is_defined_var; constraint idx in index_set(x); constraint array_var_int_element_nonshifted(idx,x,r) ::defines_var(r); } in r; function var int: element_mt(var int: idx, array[int] of var int: x) :: promise_total = let { var lb_array(x)..ub_array(x): r ::is_defined_var; var min(index_set(x))..max(index_set(x)): idx2; constraint idx in index_set(x) -> idx2=idx; constraint idx in index_set(x) \/ idx2=min(index_set(x)); constraint array_var_int_element_nonshifted(idx2,x,r) ::defines_var(r); } in r; function var int: element(var int: idx, array[int] of var int: x) = if is_fixed(idx) then x[fix(idx)] elseif mzn_in_root_context(idx) then let { constraint idx in index_set(x) } in element_t(idx,x) elseif (has_bounds(idx) /\ lb(idx) >= min(index_set(x)) /\ ub(idx) <= max(index_set(x))) then element_t(idx,x) else let { constraint idx in index_set(x) } in element_mt(idx,x) endif; function var int: element(var int: idx1, var int: idx2, array[int,int] of var int: x) = if is_fixed(idx1) /\ is_fixed(idx2) then x[fix(idx1), fix(idx2)] elseif is_fixed(idx1) then element(idx2, x[fix(idx1),..]) elseif is_fixed(idx2) then element(idx1, x[.., fix(idx2)]) else let { int: dim = card(index_set_2of2(x)); int: min_flat = min(index_set_1of2(x))*dim+min(index_set_2of2(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of2(x); constraint idx2 in index_set_2of2(x); } in element_t( (idx1*dim+idx2-min_flat)::domain, array1d(x)) elseif ((has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of2(x)) /\ ub(idx1) <= max(index_set_1of2(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of2(x)) /\ ub(idx2) <= max(index_set_2of2(x)))) then element_t( (idx1*dim+idx2-min_flat)::domain, array1d(x)) else let { constraint idx1 in index_set_1of2(x); constraint idx2 in index_set_2of2(x); } in element_mt( (idx1*dim+idx2-min_flat)::domain, array1d(x)) endif endif; function var int: element(var int: idx1, var int: idx2, var int: idx3, array[int,int,int] of var int: x) = let { int: dim2 = card(index_set_2of3(x)); int: dim3 = card(index_set_3of3(x)); int: min = min(index_set_1of3(x))*dim2*dim3+ min(index_set_2of3(x))*dim3+ min(index_set_3of3(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of3(x); constraint idx2 in index_set_2of3(x); constraint idx3 in index_set_3of3(x); } in element_t( (idx1*(dim2*dim3)+idx2*dim3+idx3-min)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of3(x)) /\ ub(idx1) <= max(index_set_1of3(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of3(x)) /\ ub(idx2) <= max(index_set_2of3(x))) /\ (has_bounds(idx3) /\ lb(idx3) >= min(index_set_3of3(x)) /\ ub(idx3) <= max(index_set_3of3(x)))) then element_t( (idx1*(dim2*dim3)+idx2*dim3+idx3-min)::domain, array1d(x)) else let { constraint idx1 in index_set_1of3(x); constraint idx2 in index_set_2of3(x); constraint idx3 in index_set_3of3(x); } in element_mt( (idx1*(dim2*dim3)+idx2*dim3+idx3-min)::domain, array1d(x)) endif; function var int: element(var int: idx1, var int: idx2, var int: idx3, var int: idx4, array[int,int,int,int] of var int: x) = let { int: dim2 = card(index_set_2of4(x)); int: dim3 = card(index_set_3of4(x)); int: dim4 = card(index_set_4of4(x)); int: min = min(index_set_1of4(x))*dim2*dim3*dim4+ min(index_set_2of4(x))*dim3*dim4+ min(index_set_3of4(x))*dim4+ min(index_set_4of4(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of4(x); constraint idx2 in index_set_2of4(x); constraint idx3 in index_set_3of4(x); constraint idx4 in index_set_4of4(x); } in element_t( (idx1*(dim2*dim3*dim4)+idx2*(dim3*dim4)+idx3*dim4+idx4-min)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of4(x)) /\ ub(idx1) <= max(index_set_1of4(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of4(x)) /\ ub(idx2) <= max(index_set_2of4(x))) /\ (has_bounds(idx3) /\ lb(idx3) >= min(index_set_3of4(x)) /\ ub(idx3) <= max(index_set_3of4(x))) /\ (has_bounds(idx4) /\ lb(idx4) >= min(index_set_4of4(x)) /\ ub(idx4) <= max(index_set_4of4(x))) ) then element_t( (idx1*(dim2*dim3*dim4)+idx2*(dim3*dim4)+idx3*dim4+idx4-min)::domain, array1d(x)) else let { constraint idx1 in index_set_1of4(x); constraint idx2 in index_set_2of4(x); constraint idx3 in index_set_3of4(x); constraint idx4 in index_set_4of4(x); } in element_mt( (idx1*(dim2*dim3*dim4)+idx2*(dim3*dim4)+idx3*dim4+idx4-min)::domain, array1d(x)) endif; function var int: element(var int: idx1, var int: idx2, var int: idx3, var int: idx4, var int: idx5, array[int,int,int,int,int] of var int: x) = let { int: dim2 = card(index_set_2of5(x)); int: dim3 = card(index_set_3of5(x)); int: dim4 = card(index_set_4of5(x)); int: dim5 = card(index_set_5of5(x)); int: min = min(index_set_1of5(x))*dim2*dim3*dim4*dim5+ min(index_set_2of5(x))*dim3*dim4*dim5+ min(index_set_3of5(x))*dim4*dim5+ min(index_set_4of5(x))*dim5+ min(index_set_5of5(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of5(x); constraint idx2 in index_set_2of5(x); constraint idx3 in index_set_3of5(x); constraint idx4 in index_set_4of5(x); constraint idx5 in index_set_5of5(x); } in element_t( (idx1*(dim2*dim3*dim4*dim5)+idx2*(dim3*dim4*dim5)+idx3*(dim4*dim5)+idx4*dim5+idx5-min)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of5(x)) /\ ub(idx1) <= max(index_set_1of5(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of5(x)) /\ ub(idx2) <= max(index_set_2of5(x))) /\ (has_bounds(idx3) /\ lb(idx3) >= min(index_set_3of5(x)) /\ ub(idx3) <= max(index_set_3of5(x))) /\ (has_bounds(idx4) /\ lb(idx4) >= min(index_set_4of5(x)) /\ ub(idx4) <= max(index_set_4of5(x))) /\ (has_bounds(idx5) /\ lb(idx5) >= min(index_set_5of5(x)) /\ ub(idx5) <= max(index_set_5of5(x))) ) then element_t( (idx1*(dim2*dim3*dim4*dim5)+idx2*(dim3*dim4*dim5)+idx3*(dim4*dim5)+idx4*dim5+idx5-min)::domain, array1d(x)) else let { constraint idx1 in index_set_1of5(x); constraint idx2 in index_set_2of5(x); constraint idx3 in index_set_3of5(x); constraint idx4 in index_set_4of5(x); constraint idx5 in index_set_5of5(x); } in element_mt( (idx1*(dim2*dim3*dim4*dim5)+idx2*(dim3*dim4*dim5)+idx3*(dim4*dim5)+idx4*dim5+idx5-min)::domain, array1d(x)) endif; function var int: element(var int: idx1, var int: idx2, var int: idx3, var int: idx4, var int: idx5, var int: idx6, array[int,int,int,int,int,int] of var int: x) = let { int: dim2 = card(index_set_2of6(x)); int: dim3 = card(index_set_3of6(x)); int: dim4 = card(index_set_4of6(x)); int: dim5 = card(index_set_5of6(x)); int: dim6 = card(index_set_6of6(x)); int: min = min(index_set_1of6(x))*dim2*dim3*dim4*dim5*dim6+ min(index_set_2of6(x))*dim3*dim4*dim5*dim6+ min(index_set_3of6(x))*dim4*dim5*dim6+ min(index_set_4of6(x))*dim5*dim6+ min(index_set_5of6(x))*dim6+ min(index_set_6of6(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of6(x); constraint idx2 in index_set_2of6(x); constraint idx3 in index_set_3of6(x); constraint idx4 in index_set_4of6(x); constraint idx5 in index_set_5of6(x); constraint idx6 in index_set_6of6(x); } in element_t( (idx1*(dim2*dim3*dim4*dim5*dim6)+idx2*(dim3*dim4*dim5*dim6)+idx3*(dim4*dim5*dim6)+idx4*(dim5*dim6)+idx5*dim6+idx6-min)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of6(x)) /\ ub(idx1) <= max(index_set_1of6(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of6(x)) /\ ub(idx2) <= max(index_set_2of6(x))) /\ (has_bounds(idx3) /\ lb(idx3) >= min(index_set_3of6(x)) /\ ub(idx3) <= max(index_set_3of6(x))) /\ (has_bounds(idx4) /\ lb(idx4) >= min(index_set_4of6(x)) /\ ub(idx4) <= max(index_set_4of6(x))) /\ (has_bounds(idx5) /\ lb(idx5) >= min(index_set_5of6(x)) /\ ub(idx5) <= max(index_set_5of6(x))) /\ (has_bounds(idx6) /\ lb(idx6) >= min(index_set_6of6(x)) /\ ub(idx6) <= max(index_set_6of6(x))) ) then element_t( (idx1*(dim2*dim3*dim4*dim5*dim6)+idx2*(dim3*dim4*dim5*dim6)+idx3*(dim4*dim5*dim6)+idx4*(dim5*dim6)+idx5*dim6+idx6-min)::domain, array1d(x)) else let { constraint idx1 in index_set_1of6(x); constraint idx2 in index_set_2of6(x); constraint idx3 in index_set_3of6(x); constraint idx4 in index_set_4of6(x); constraint idx5 in index_set_5of6(x); constraint idx6 in index_set_6of6(x); } in element_mt( (idx1*(dim2*dim3*dim4*dim5*dim6)+idx2*(dim3*dim4*dim5*dim6)+idx3*(dim4*dim5*dim6)+idx4*(dim5*dim6)+idx5*dim6+idx6-min)::domain, array1d(x)) endif; %%%%%%%%%%%%%%%%%%% % Element on floats function var float: element_t(var int: idx, array[int] of var float: x) :: promise_total = let { var lb_array(x)..ub_array(x): r ::is_defined_var; constraint idx in index_set(x); constraint array_var_float_element_nonshifted(idx,x,r) ::defines_var(r); } in r; function var float: element_mt(var int: idx, array[int] of var float: x) :: promise_total = let { var lb_array(x)..ub_array(x): r ::is_defined_var; var min(index_set(x))..max(index_set(x)): idx2; constraint idx in index_set(x) -> idx2=idx; constraint idx in index_set(x) \/ idx2=min(index_set(x)); constraint array_var_float_element_nonshifted(idx2,x,r) ::defines_var(r); } in r; function var float: element(var int: idx, array[int] of var float: x) = if mzn_in_root_context(idx) then let { constraint idx in index_set(x) } in element_t(idx,x) elseif (has_bounds(idx) /\ lb(idx) >= min(index_set(x)) /\ ub(idx) <= max(index_set(x))) then element_t(idx,x) else let { constraint idx in index_set(x) } in element_mt(idx,x) endif; function var float: element(var int: idx1, var int: idx2, array[int,int] of var float: x) = let { int: dim = card(index_set_2of2(x)); int: min_flat = min(index_set_1of2(x))*dim+min(index_set_2of2(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of2(x); constraint idx2 in index_set_2of2(x); } in element_t( (idx1*dim+idx2-min_flat)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of2(x)) /\ ub(idx1) <= max(index_set_1of2(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of2(x)) /\ ub(idx2) <= max(index_set_2of2(x))) ) then element_t( (idx1*dim+idx2-min_flat)::domain, array1d(x)) else let { constraint idx1 in index_set_1of2(x); constraint idx2 in index_set_2of2(x); } in element_mt( (idx1*dim+idx2-min_flat)::domain, array1d(x)) endif; function var float: element(var int: idx1, var int: idx2, var int: idx3, array[int,int,int] of var float: x) = let { int: dim2 = card(index_set_2of3(x)); int: dim3 = card(index_set_3of3(x)); int: min = min(index_set_1of3(x))*dim2*dim3+ min(index_set_2of3(x))*dim3+ min(index_set_3of3(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of3(x); constraint idx2 in index_set_2of3(x); constraint idx3 in index_set_3of3(x); } in element_t( (idx1*(dim2*dim3)+idx2*dim3+idx3-min)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of3(x)) /\ ub(idx1) <= max(index_set_1of3(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of3(x)) /\ ub(idx2) <= max(index_set_2of3(x))) /\ (has_bounds(idx3) /\ lb(idx3) >= min(index_set_3of3(x)) /\ ub(idx3) <= max(index_set_3of3(x))) ) then element_t( (idx1*(dim2*dim3)+idx2*dim3+idx3-min)::domain, array1d(x)) else let { constraint idx1 in index_set_1of3(x); constraint idx2 in index_set_2of3(x); constraint idx3 in index_set_3of3(x); } in element_mt( (idx1*(dim2*dim3)+idx2*dim3+idx3-min)::domain, array1d(x)) endif; function var float: element(var int: idx1, var int: idx2, var int: idx3, var int: idx4, array[int,int,int,int] of var float: x) = let { int: dim2 = card(index_set_2of4(x)); int: dim3 = card(index_set_3of4(x)); int: dim4 = card(index_set_4of4(x)); int: min = min(index_set_1of4(x))*dim2*dim3*dim4+ min(index_set_2of4(x))*dim3*dim4+ min(index_set_3of4(x))*dim4+ min(index_set_4of4(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of4(x); constraint idx2 in index_set_2of4(x); constraint idx3 in index_set_3of4(x); constraint idx4 in index_set_4of4(x); } in element_t( (idx1*(dim2*dim3*dim4)+idx2*(dim3*dim4)+idx3*dim4+idx4-min)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of4(x)) /\ ub(idx1) <= max(index_set_1of4(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of4(x)) /\ ub(idx2) <= max(index_set_2of4(x))) /\ (has_bounds(idx3) /\ lb(idx3) >= min(index_set_3of4(x)) /\ ub(idx3) <= max(index_set_3of4(x))) /\ (has_bounds(idx4) /\ lb(idx4) >= min(index_set_4of4(x)) /\ ub(idx4) <= max(index_set_4of4(x))) ) then element_t( (idx1*(dim2*dim3*dim4)+idx2*(dim3*dim4)+idx3*dim4+idx4-min)::domain, array1d(x)) else let { constraint idx1 in index_set_1of4(x); constraint idx2 in index_set_2of4(x); constraint idx3 in index_set_3of4(x); constraint idx4 in index_set_4of4(x); } in element_mt( (idx1*(dim2*dim3*dim4)+idx2*(dim3*dim4)+idx3*dim4+idx4-min)::domain, array1d(x)) endif; function var float: element(var int: idx1, var int: idx2, var int: idx3, var int: idx4, var int: idx5, array[int,int,int,int,int] of var float: x) = let { int: dim2 = card(index_set_2of5(x)); int: dim3 = card(index_set_3of5(x)); int: dim4 = card(index_set_4of5(x)); int: dim5 = card(index_set_5of5(x)); int: min = min(index_set_1of5(x))*dim2*dim3*dim4*dim5+ min(index_set_2of5(x))*dim3*dim4*dim5+ min(index_set_3of5(x))*dim4*dim5+ min(index_set_4of5(x))*dim5+ min(index_set_5of5(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of5(x); constraint idx2 in index_set_2of5(x); constraint idx3 in index_set_3of5(x); constraint idx4 in index_set_4of5(x); constraint idx5 in index_set_5of5(x); } in element_t( (idx1*(dim2*dim3*dim4*dim5)+idx2*(dim3*dim4*dim5)+idx3*(dim4*dim5)+idx4*dim5+idx5-min)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of5(x)) /\ ub(idx1) <= max(index_set_1of5(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of5(x)) /\ ub(idx2) <= max(index_set_2of5(x))) /\ (has_bounds(idx3) /\ lb(idx3) >= min(index_set_3of5(x)) /\ ub(idx3) <= max(index_set_3of5(x))) /\ (has_bounds(idx4) /\ lb(idx4) >= min(index_set_4of5(x)) /\ ub(idx4) <= max(index_set_4of5(x))) /\ (has_bounds(idx5) /\ lb(idx5) >= min(index_set_5of5(x)) /\ ub(idx5) <= max(index_set_5of5(x))) ) then element_t( (idx1*(dim2*dim3*dim4*dim5)+idx2*(dim3*dim4*dim5)+idx3*(dim4*dim5)+idx4*dim5+idx5-min)::domain, array1d(x)) else let { constraint idx1 in index_set_1of5(x); constraint idx2 in index_set_2of5(x); constraint idx3 in index_set_3of5(x); constraint idx4 in index_set_4of5(x); constraint idx5 in index_set_5of5(x); } in element_mt( (idx1*(dim2*dim3*dim4*dim5)+idx2*(dim3*dim4*dim5)+idx3*(dim4*dim5)+idx4*dim5+idx5-min)::domain, array1d(x)) endif; function var float: element(var int: idx1, var int: idx2, var int: idx3, var int: idx4, var int: idx5, var int: idx6, array[int,int,int,int,int,int] of var float: x) = let { int: dim2 = card(index_set_2of6(x)); int: dim3 = card(index_set_3of6(x)); int: dim4 = card(index_set_4of6(x)); int: dim5 = card(index_set_5of6(x)); int: dim6 = card(index_set_6of6(x)); int: min = min(index_set_1of6(x))*dim2*dim3*dim4*dim5*dim6+ min(index_set_2of6(x))*dim3*dim4*dim5*dim6+ min(index_set_3of6(x))*dim4*dim5*dim6+ min(index_set_4of6(x))*dim5*dim6+ min(index_set_5of6(x))*dim6+ min(index_set_6of6(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of6(x); constraint idx2 in index_set_2of6(x); constraint idx3 in index_set_3of6(x); constraint idx4 in index_set_4of6(x); constraint idx5 in index_set_5of6(x); constraint idx6 in index_set_6of6(x); } in element_t( (idx1*(dim2*dim3*dim4*dim5*dim6)+idx2*(dim3*dim4*dim5*dim6)+idx3*(dim4*dim5*dim6)+idx4*(dim5*dim6)+idx5*dim6+idx6-min)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of6(x)) /\ ub(idx1) <= max(index_set_1of6(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of6(x)) /\ ub(idx2) <= max(index_set_2of6(x))) /\ (has_bounds(idx3) /\ lb(idx3) >= min(index_set_3of6(x)) /\ ub(idx3) <= max(index_set_3of6(x))) /\ (has_bounds(idx4) /\ lb(idx4) >= min(index_set_4of6(x)) /\ ub(idx4) <= max(index_set_4of6(x))) /\ (has_bounds(idx5) /\ lb(idx5) >= min(index_set_5of6(x)) /\ ub(idx5) <= max(index_set_5of6(x))) /\ (has_bounds(idx6) /\ lb(idx6) >= min(index_set_6of6(x)) /\ ub(idx6) <= max(index_set_6of6(x))) ) then element_t( (idx1*(dim2*dim3*dim4*dim5*dim6)+idx2*(dim3*dim4*dim5*dim6)+idx3*(dim4*dim5*dim6)+idx4*(dim5*dim6)+idx5*dim6+idx6-min)::domain, array1d(x)) else let { constraint idx1 in index_set_1of6(x); constraint idx2 in index_set_2of6(x); constraint idx3 in index_set_3of6(x); constraint idx4 in index_set_4of6(x); constraint idx5 in index_set_5of6(x); constraint idx6 in index_set_6of6(x); } in element_mt( (idx1*(dim2*dim3*dim4*dim5*dim6)+idx2*(dim3*dim4*dim5*dim6)+idx3*(dim4*dim5*dim6)+idx4*(dim5*dim6)+idx5*dim6+idx6-min)::domain, array1d(x)) endif; %%%%%%%%%%%%%%%%% % Element on sets function var set of int: element_t(var int: idx, array[int] of var set of int: x) :: promise_total = let { var set of min(ub_array(x))..max(ub_array(x)): r ::is_defined_var; constraint idx in index_set(x); constraint array_var_set_element_nonshifted(idx,x,r) ::defines_var(r); } in r; function var set of int: element_mt(var int: idx, array[int] of var set of int: x) :: promise_total = let { var set of min(ub_array(x))..max(ub_array(x)): r ::is_defined_var; var min(index_set(x))..max(index_set(x)): idx2; constraint idx in index_set(x) -> idx2=idx; constraint idx in index_set(x) \/ idx2=min(index_set(x)); constraint array_var_set_element_nonshifted(idx2,x,r) ::defines_var(r); } in r; function var set of int: element(var int: idx, array[int] of var set of int: x) = if mzn_in_root_context(idx) then let { constraint idx in index_set(x) } in element_t(idx,x) elseif (has_bounds(idx) /\ lb(idx) >= min(index_set(x)) /\ ub(idx) <= max(index_set(x))) then element_t(idx,x) else let { constraint idx in index_set(x) } in element_mt(idx,x) endif; function var set of int: element(var int: idx1, var int: idx2, array[int,int] of var set of int: x) = let { int: dim = card(index_set_2of2(x)); int: min_flat = min(index_set_1of2(x))*dim+min(index_set_2of2(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of2(x); constraint idx2 in index_set_2of2(x); } in element_t( (idx1*dim+idx2-min_flat)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of2(x)) /\ ub(idx1) <= max(index_set_1of2(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of2(x)) /\ ub(idx2) <= max(index_set_2of2(x))) ) then element_t( (idx1*dim+idx2-min_flat)::domain, array1d(x)) else let { constraint idx1 in index_set_1of2(x); constraint idx2 in index_set_2of2(x); } in element_mt( (idx1*dim+idx2-min_flat)::domain, array1d(x)) endif; function var set of int: element(var int: idx1, var int: idx2, var int: idx3, array[int,int,int] of var set of int: x) = let { int: dim2 = card(index_set_2of3(x)); int: dim3 = card(index_set_3of3(x)); int: min = min(index_set_1of3(x))*dim2*dim3+ min(index_set_2of3(x))*dim3+ min(index_set_3of3(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of3(x); constraint idx2 in index_set_2of3(x); constraint idx3 in index_set_3of3(x); } in element_t( (idx1*(dim2*dim3)+idx2*dim3+idx3-min)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of3(x)) /\ ub(idx1) <= max(index_set_1of3(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of3(x)) /\ ub(idx2) <= max(index_set_2of3(x))) /\ (has_bounds(idx3) /\ lb(idx3) >= min(index_set_3of3(x)) /\ ub(idx3) <= max(index_set_3of3(x))) ) then element_t( (idx1*(dim2*dim3)+idx2*dim3+idx3-min)::domain, array1d(x)) else let { constraint idx1 in index_set_1of3(x); constraint idx2 in index_set_2of3(x); constraint idx3 in index_set_3of3(x); } in element_mt( (idx1*(dim2*dim3)+idx2*dim3+idx3-min)::domain, array1d(x)) endif; function var set of int: element(var int: idx1, var int: idx2, var int: idx3, var int: idx4, array[int,int,int,int] of var set of int: x) = let { int: dim2 = card(index_set_2of4(x)); int: dim3 = card(index_set_3of4(x)); int: dim4 = card(index_set_4of4(x)); int: min = min(index_set_1of4(x))*dim2*dim3*dim4+ min(index_set_2of4(x))*dim3*dim4+ min(index_set_3of4(x))*dim4+ min(index_set_4of4(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of4(x); constraint idx2 in index_set_2of4(x); constraint idx3 in index_set_3of4(x); constraint idx4 in index_set_4of4(x); } in element_t( (idx1*(dim2*dim3*dim4)+idx2*(dim3*dim4)+idx3*dim4+idx4-min)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of4(x)) /\ ub(idx1) <= max(index_set_1of4(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of4(x)) /\ ub(idx2) <= max(index_set_2of4(x))) /\ (has_bounds(idx3) /\ lb(idx3) >= min(index_set_3of4(x)) /\ ub(idx3) <= max(index_set_3of4(x))) /\ (has_bounds(idx4) /\ lb(idx4) >= min(index_set_4of4(x)) /\ ub(idx4) <= max(index_set_4of4(x))) ) then element_t( (idx1*(dim2*dim3*dim4)+idx2*(dim3*dim4)+idx3*dim4+idx4-min)::domain, array1d(x)) else let { constraint idx1 in index_set_1of4(x); constraint idx2 in index_set_2of4(x); constraint idx3 in index_set_3of4(x); constraint idx4 in index_set_4of4(x); } in element_mt( (idx1*(dim2*dim3*dim4)+idx2*(dim3*dim4)+idx3*dim4+idx4-min)::domain, array1d(x)) endif; function var set of int: element(var int: idx1, var int: idx2, var int: idx3, var int: idx4, var int: idx5, array[int,int,int,int,int] of var set of int: x) = let { int: dim2 = card(index_set_2of5(x)); int: dim3 = card(index_set_3of5(x)); int: dim4 = card(index_set_4of5(x)); int: dim5 = card(index_set_5of5(x)); int: min = min(index_set_1of5(x))*dim2*dim3*dim4*dim5+ min(index_set_2of5(x))*dim3*dim4*dim5+ min(index_set_3of5(x))*dim4*dim5+ min(index_set_4of5(x))*dim5+ min(index_set_5of5(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of5(x); constraint idx2 in index_set_2of5(x); constraint idx3 in index_set_3of5(x); constraint idx4 in index_set_4of5(x); constraint idx5 in index_set_5of5(x); } in element_t( (idx1*(dim2*dim3*dim4*dim5)+idx2*(dim3*dim4*dim5)+idx3*(dim4*dim5)+idx4*dim5+idx5-min)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of5(x)) /\ ub(idx1) <= max(index_set_1of5(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of5(x)) /\ ub(idx2) <= max(index_set_2of5(x))) /\ (has_bounds(idx3) /\ lb(idx3) >= min(index_set_3of5(x)) /\ ub(idx3) <= max(index_set_3of5(x))) /\ (has_bounds(idx4) /\ lb(idx4) >= min(index_set_4of5(x)) /\ ub(idx4) <= max(index_set_4of5(x))) /\ (has_bounds(idx5) /\ lb(idx5) >= min(index_set_5of5(x)) /\ ub(idx5) <= max(index_set_5of5(x))) ) then element_t( (idx1*(dim2*dim3*dim4*dim5)+idx2*(dim3*dim4*dim5)+idx3*(dim4*dim5)+idx4*dim5+idx5-min)::domain, array1d(x)) else let { constraint idx1 in index_set_1of5(x); constraint idx2 in index_set_2of5(x); constraint idx3 in index_set_3of5(x); constraint idx4 in index_set_4of5(x); constraint idx5 in index_set_5of5(x); } in element_mt( (idx1*(dim2*dim3*dim4*dim5)+idx2*(dim3*dim4*dim5)+idx3*(dim4*dim5)+idx4*dim5+idx5-min)::domain, array1d(x)) endif; function var set of int: element(var int: idx1, var int: idx2, var int: idx3, var int: idx4, var int: idx5, var int: idx6, array[int,int,int,int,int,int] of var set of int: x) = let { int: dim2 = card(index_set_2of6(x)); int: dim3 = card(index_set_3of6(x)); int: dim4 = card(index_set_4of6(x)); int: dim5 = card(index_set_5of6(x)); int: dim6 = card(index_set_6of6(x)); int: min = min(index_set_1of6(x))*dim2*dim3*dim4*dim5*dim6+ min(index_set_2of6(x))*dim3*dim4*dim5*dim6+ min(index_set_3of6(x))*dim4*dim5*dim6+ min(index_set_4of6(x))*dim5*dim6+ min(index_set_5of6(x))*dim6+ min(index_set_6of6(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of6(x); constraint idx2 in index_set_2of6(x); constraint idx3 in index_set_3of6(x); constraint idx4 in index_set_4of6(x); constraint idx5 in index_set_5of6(x); constraint idx6 in index_set_6of6(x); } in element_t( (idx1*(dim2*dim3*dim4*dim5*dim6)+idx2*(dim3*dim4*dim5*dim6)+idx3*(dim4*dim5*dim6)+idx4*(dim5*dim6)+idx5*dim6+idx6-min)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of6(x)) /\ ub(idx1) <= max(index_set_1of6(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of6(x)) /\ ub(idx2) <= max(index_set_2of6(x))) /\ (has_bounds(idx3) /\ lb(idx3) >= min(index_set_3of6(x)) /\ ub(idx3) <= max(index_set_3of6(x))) /\ (has_bounds(idx4) /\ lb(idx4) >= min(index_set_4of6(x)) /\ ub(idx4) <= max(index_set_4of6(x))) /\ (has_bounds(idx5) /\ lb(idx5) >= min(index_set_5of6(x)) /\ ub(idx5) <= max(index_set_5of6(x))) /\ (has_bounds(idx6) /\ lb(idx6) >= min(index_set_6of6(x)) /\ ub(idx6) <= max(index_set_6of6(x))) ) then element_t( (idx1*(dim2*dim3*dim4*dim5*dim6)+idx2*(dim3*dim4*dim5*dim6)+idx3*(dim4*dim5*dim6)+idx4*(dim5*dim6)+idx5*dim6+idx6-min)::domain, array1d(x)) else let { constraint idx1 in index_set_1of6(x); constraint idx2 in index_set_2of6(x); constraint idx3 in index_set_3of6(x); constraint idx4 in index_set_4of6(x); constraint idx5 in index_set_5of6(x); constraint idx6 in index_set_6of6(x); } in element_mt( (idx1*(dim2*dim3*dim4*dim5*dim6)+idx2*(dim3*dim4*dim5*dim6)+idx3*(dim4*dim5*dim6)+idx4*(dim5*dim6)+idx5*dim6+idx6-min)::domain, array1d(x)) endif; %%%%%%%%%%%%%%%%%% % Element on bools function var bool: element_t(var int: idx, array[int] of var bool: x) :: promise_total = let { var bool: r ::is_defined_var; constraint idx in index_set(x); constraint array_var_bool_element_nonshifted(idx,x,r) ::defines_var(r); } in r; function var bool: element_mt(var int: idx, array[int] of var bool: x) :: promise_total = let { var bool: r ::is_defined_var; var min(index_set(x))..max(index_set(x)): idx2; constraint idx in index_set(x) -> idx2=idx; constraint idx in index_set(x) \/ idx2=min(index_set(x)); constraint array_var_bool_element_nonshifted(idx2,x,r) ::defines_var(r); } in r; function var bool: element(var int: idx, array[int] of var bool: x) = if mzn_in_root_context(idx) then idx in index_set(x) /\ element_t(idx,x) elseif (has_bounds(idx) /\ lb(idx) >= min(index_set(x)) /\ ub(idx) <= max(index_set(x))) then element_t(idx,x) else idx in index_set(x) /\ element_mt(idx,x) endif; function var bool: element(var int: idx1, var int: idx2, array[int,int] of var bool: x) = let { int: dim = card(index_set_2of2(x)); int: min_flat = min(index_set_1of2(x))*dim+min(index_set_2of2(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of2(x); constraint idx2 in index_set_2of2(x); } in element_t( (idx1*dim+idx2-min_flat)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of2(x)) /\ ub(idx1) <= max(index_set_1of2(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of2(x)) /\ ub(idx2) <= max(index_set_2of2(x))) ) then element_t( (idx1*dim+idx2-min_flat)::domain, array1d(x)) else let { constraint idx1 in index_set_1of2(x); constraint idx2 in index_set_2of2(x); } in element_mt( (idx1*dim+idx2-min_flat)::domain, array1d(x)) endif; function var bool: element(var int: idx1, var int: idx2, var int: idx3, array[int,int,int] of var bool: x) = let { int: dim2 = card(index_set_2of3(x)); int: dim3 = card(index_set_3of3(x)); int: min = min(index_set_1of3(x))*dim2*dim3+ min(index_set_2of3(x))*dim3+ min(index_set_3of3(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of3(x); constraint idx2 in index_set_2of3(x); constraint idx3 in index_set_3of3(x); } in element_t( (idx1*(dim2*dim3)+idx2*dim3+idx3-min)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of3(x)) /\ ub(idx1) <= max(index_set_1of3(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of3(x)) /\ ub(idx2) <= max(index_set_2of3(x))) /\ (has_bounds(idx3) /\ lb(idx3) >= min(index_set_3of3(x)) /\ ub(idx3) <= max(index_set_3of3(x))) ) then element_t( (idx1*(dim2*dim3)+idx2*dim3+idx3-min)::domain, array1d(x)) else let { constraint idx1 in index_set_1of3(x); constraint idx2 in index_set_2of3(x); constraint idx3 in index_set_3of3(x); } in element_mt( (idx1*(dim2*dim3)+idx2*dim3+idx3-min)::domain, array1d(x)) endif; function var bool: element(var int: idx1, var int: idx2, var int: idx3, var int: idx4, array[int,int,int,int] of var bool: x) = let { int: dim2 = card(index_set_2of4(x)); int: dim3 = card(index_set_3of4(x)); int: dim4 = card(index_set_4of4(x)); int: min = min(index_set_1of4(x))*dim2*dim3*dim4+ min(index_set_2of4(x))*dim3*dim4+ min(index_set_3of4(x))*dim4+ min(index_set_4of4(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of4(x); constraint idx2 in index_set_2of4(x); constraint idx3 in index_set_3of4(x); constraint idx4 in index_set_4of4(x); } in element_t( (idx1*(dim2*dim3*dim4)+idx2*(dim3*dim4)+idx3*dim4+idx4-min)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of4(x)) /\ ub(idx1) <= max(index_set_1of4(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of4(x)) /\ ub(idx2) <= max(index_set_2of4(x))) /\ (has_bounds(idx3) /\ lb(idx3) >= min(index_set_3of4(x)) /\ ub(idx3) <= max(index_set_3of4(x))) /\ (has_bounds(idx4) /\ lb(idx4) >= min(index_set_4of4(x)) /\ ub(idx4) <= max(index_set_4of4(x))) ) then element_t( (idx1*(dim2*dim3*dim4)+idx2*(dim3*dim4)+idx3*dim4+idx4-min)::domain, array1d(x)) else let { constraint idx1 in index_set_1of4(x); constraint idx2 in index_set_2of4(x); constraint idx3 in index_set_3of4(x); constraint idx4 in index_set_4of4(x); } in element_mt( (idx1*(dim2*dim3*dim4)+idx2*(dim3*dim4)+idx3*dim4+idx4-min)::domain, array1d(x)) endif; function var bool: element(var int: idx1, var int: idx2, var int: idx3, var int: idx4, var int: idx5, array[int,int,int,int,int] of var bool: x) = let { int: dim2 = card(index_set_2of5(x)); int: dim3 = card(index_set_3of5(x)); int: dim4 = card(index_set_4of5(x)); int: dim5 = card(index_set_5of5(x)); int: min = min(index_set_1of5(x))*dim2*dim3*dim4*dim5+ min(index_set_2of5(x))*dim3*dim4*dim5+ min(index_set_3of5(x))*dim4*dim5+ min(index_set_4of5(x))*dim5+ min(index_set_5of5(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of5(x); constraint idx2 in index_set_2of5(x); constraint idx3 in index_set_3of5(x); constraint idx4 in index_set_4of5(x); constraint idx5 in index_set_5of5(x); } in element_t( (idx1*(dim2*dim3*dim4*dim5)+idx2*(dim3*dim4*dim5)+idx3*(dim4*dim5)+idx4*dim5+idx5-min)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of5(x)) /\ ub(idx1) <= max(index_set_1of5(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of5(x)) /\ ub(idx2) <= max(index_set_2of5(x))) /\ (has_bounds(idx3) /\ lb(idx3) >= min(index_set_3of5(x)) /\ ub(idx3) <= max(index_set_3of5(x))) /\ (has_bounds(idx4) /\ lb(idx4) >= min(index_set_4of5(x)) /\ ub(idx4) <= max(index_set_4of5(x))) /\ (has_bounds(idx5) /\ lb(idx5) >= min(index_set_5of5(x)) /\ ub(idx5) <= max(index_set_5of5(x))) ) then element_t( (idx1*(dim2*dim3*dim4*dim5)+idx2*(dim3*dim4*dim5)+idx3*(dim4*dim5)+idx4*dim5+idx5-min)::domain, array1d(x)) else let { constraint idx1 in index_set_1of5(x); constraint idx2 in index_set_2of5(x); constraint idx3 in index_set_3of5(x); constraint idx4 in index_set_4of5(x); constraint idx5 in index_set_5of5(x); } in element_mt( (idx1*(dim2*dim3*dim4*dim5)+idx2*(dim3*dim4*dim5)+idx3*(dim4*dim5)+idx4*dim5+idx5-min)::domain, array1d(x)) endif; function var bool: element(var int: idx1, var int: idx2, var int: idx3, var int: idx4, var int: idx5, var int: idx6, array[int,int,int,int,int,int] of var bool: x) = let { int: dim2 = card(index_set_2of6(x)); int: dim3 = card(index_set_3of6(x)); int: dim4 = card(index_set_4of6(x)); int: dim5 = card(index_set_5of6(x)); int: dim6 = card(index_set_6of6(x)); int: min = min(index_set_1of6(x))*dim2*dim3*dim4*dim5*dim6+ min(index_set_2of6(x))*dim3*dim4*dim5*dim6+ min(index_set_3of6(x))*dim4*dim5*dim6+ min(index_set_4of6(x))*dim5*dim6+ min(index_set_5of6(x))*dim6+ min(index_set_6of6(x))-1; } in if mzn_in_root_context(idx1) then let { constraint idx1 in index_set_1of6(x); constraint idx2 in index_set_2of6(x); constraint idx3 in index_set_3of6(x); constraint idx4 in index_set_4of6(x); constraint idx5 in index_set_5of6(x); constraint idx6 in index_set_6of6(x); } in element_t( (idx1*(dim2*dim3*dim4*dim5*dim6)+idx2*(dim3*dim4*dim5*dim6)+idx3*(dim4*dim5*dim6)+idx4*(dim5*dim6)+idx5*dim6+idx6-min)::domain, array1d(x)) elseif ( (has_bounds(idx1) /\ lb(idx1) >= min(index_set_1of6(x)) /\ ub(idx1) <= max(index_set_1of6(x))) /\ (has_bounds(idx2) /\ lb(idx2) >= min(index_set_2of6(x)) /\ ub(idx2) <= max(index_set_2of6(x))) /\ (has_bounds(idx3) /\ lb(idx3) >= min(index_set_3of6(x)) /\ ub(idx3) <= max(index_set_3of6(x))) /\ (has_bounds(idx4) /\ lb(idx4) >= min(index_set_4of6(x)) /\ ub(idx4) <= max(index_set_4of6(x))) /\ (has_bounds(idx5) /\ lb(idx5) >= min(index_set_5of6(x)) /\ ub(idx5) <= max(index_set_5of6(x))) /\ (has_bounds(idx6) /\ lb(idx6) >= min(index_set_6of6(x)) /\ ub(idx6) <= max(index_set_6of6(x))) ) then element_t( (idx1*(dim2*dim3*dim4*dim5*dim6)+idx2*(dim3*dim4*dim5*dim6)+idx3*(dim4*dim5*dim6)+idx4*(dim5*dim6)+idx5*dim6+idx6-min)::domain, array1d(x)) else let { constraint idx1 in index_set_1of6(x); constraint idx2 in index_set_2of6(x); constraint idx3 in index_set_3of6(x); constraint idx4 in index_set_4of6(x); constraint idx5 in index_set_5of6(x); constraint idx6 in index_set_6of6(x); } in element_mt( (idx1*(dim2*dim3*dim4*dim5*dim6)+idx2*(dim3*dim4*dim5*dim6)+idx3*(dim4*dim5*dim6)+idx4*(dim5*dim6)+idx5*dim6+idx6-min)::domain, array1d(x)) endif; %-----------------------------------------------------------------------------% % % Internal functions for implementing div, mod etc function set of int:compute_div_bounds(var int: x, var int: y); function var int: div_t(var int: x, var int: y) :: promise_total = let { var (compute_div_bounds(x,y)): z ::is_defined_var; constraint y != 0; constraint int_div(x,y,z) ::defines_var(z); } in z; function var int: div_mt(var int: x, var int: y) :: promise_total = let { var ((dom(y) diff {0}) union {1}): yy = if y=0 then 1 else y endif; } in div_t(x,yy); function var float: fldiv_t(var float: x, var float: y) :: promise_total = let { var float: z ::is_defined_var; % TODO: Compute division boundaries constraint y != 0.0; constraint float_div(x, y, z) ::defines_var(z); } in z; function var float: fldiv_mt(var float: x, var float: y) :: promise_total = let { var (lb(y)..ub(y) diff {0.0}) union {1.0}: yy = if (y = 0.0) then 1.0 else y endif; } in fldiv_t(x, yy); function var int: mod_t(var int: x, var int: y) :: promise_total = let { var -(max(ub(y),-lb(y)))..max(ub(y),-lb(y)): z; constraint y != 0; constraint int_mod(x,y,z); } in z; function var int: mod_mt(var int: x, var int: y) :: promise_total = let { var {1} union dom(y): yy = if y=0 then 1 else y endif; } in mod_t(x,yy); function var int: product_rec(array[int] of var int: x) = if length(x)=0 then 1 elseif length(x)=1 then x[min(index_set(x))] else x[min(index_set(x))]* product_rec([x[i] | i in min(index_set(x))+1..max(index_set(x))]) endif; function var float: product_rec(array[int] of var float: x) = if length(x)=0 then 1.0 elseif length(x)=1 then x[min(index_set(x))] else x[min(index_set(x))]* product_rec([x[i] | i in min(index_set(x))+1..max(index_set(x))]) endif; function var int: max_t(array[int] of var int: x) :: promise_total = if length(x)=0 then 0 elseif length(x)=1 then x[min(index_set(x))] elseif length(x)=2 then max(x[1],x[2]) else let { var lb_array(x)..ub_array(x): m ::is_defined_var; constraint array_int_maximum(m,x) ::defines_var(m); } in m endif; function var int: min_t(array[int] of var int: x) :: promise_total = if length(x)=0 then 0 elseif length(x)=1 then x[1] elseif length(x)=2 then min(x[1],x[2]) else let { var lb_array(x)..ub_array(x): m ::is_defined_var; constraint array_int_minimum(m,x) ::defines_var(m); } in m endif; function var float: max_t(array[int] of var float: x) :: promise_total = if length(x)=0 then 0.0 elseif length(x)=1 then x[min(index_set(x))] elseif length(x)=2 then max(x[1],x[2]) else let { var lb_array(x)..ub_array(x): m ::is_defined_var; constraint array_float_maximum(m,x) ::defines_var(m); } in m endif; function var float: min_t(array[int] of var float: x) :: promise_total = if length(x)=0 then 0.0 elseif length(x)=1 then x[1] elseif length(x)=2 then min(x[1],x[2]) else let { var lb_array(x)..ub_array(x): m ::is_defined_var; constraint array_float_minimum(m,x) ::defines_var(m); } in m endif; /*** @groupdef builtins.random Random Number Generator builtins These functions implement random number generators from different probability distributions. */ /** @group builtins.random Return a sample from the normal distribution defined by \(\a mean, \a std\) */ function float: normal(float: mean, float: std); /** @group builtins.random Return a sample from the normal distribution defined by \(\a mean, \a std\) */ function float: normal(int: mean, float: std); /** @group builtins.random Return a sample from the uniform distribution defined by \(\a lowerbound, \a upperbound\) */ function float: uniform(float: lowerbound, float: upperbound); /** @group builtins.random Return a sample from the uniform distribution defined by \(\a lowerbound, \a upperbound\) */ function int: uniform(int: lowerbound, int: upperbound); /** @group builtins.random Return a sample from the poisson distribution defined by \a mean */ function int: poisson(float: mean); /** @group builtins.random Return a sample from the poisson distribution defined by an integer \a mean */ function int: poisson(int: mean); /** @group builtins.random Return a sample from the gamma distribution defined by \(\a alpha, \a beta\) */ function float: gamma(float: alpha, float: beta); /** @group builtins.random Return a sample from the gamma distribution defined by \(\a alpha, \a beta\) */ function float: gamma(int: alpha, float: beta); /** @group builtins.random Return a sample from the Weibull distribution defined by \(\a shape, \a scale\) */ function float: weibull(float: shape, float: scale); /** @group builtins.random Return a sample from the Weibull distribution defined by \(\a shape, \a scale\) */ function float: weibull(int: shape, float: scale); /** @group builtins.random Return a sample from the exponential distribution defined by \(\a lambda\) */ function float: exponential(int: lambda); /** @group builtins.random Return a sample from the exponential distribution defined by \(\a lambda\) */ function float: exponential(float: lambda); /** @group builtins.random Return a sample from the lognormal distribution defined by \(\a mean, \a std\) */ function float: lognormal(float: mean, float: std); /** @group builtins.random Return a sample from the lognormal distribution defined by \(\a mean, \a std\) */ function float: lognormal(int: mean, float: std); /** @group builtins.random Return a sample from the chi-squared distribution defined by the degree of freedom \(\a n\) */ function float: chisquared(int: n); /** @group builtins.random Return a sample from the chi-squared distribution defined by the degree of freedom \(\a n\) */ function float: chisquared(float: n); /** @group builtins.random Return a sample from the cauchy distribution defined by \(\a mean, \a scale\) */ function float: cauchy(float: mean, float: scale); /** @group builtins.random Return a sample from the cauchy distribution defined by \(\a mean, \a scale\) */ function float: cauchy(int: mean, float: scale); /** @group builtins.random Return a sample from the Fisher-Snedecor F-distribution defined by the degrees of freedom \(\a d1, \a d2\) */ function float: fdistribution(float: d1, float: d2); /** @group builtins.random Return a sample from the Fisher-Snedecor F-distribution defined by the degrees of freedom \(\a d1, \a d2\) */ function float: fdistribution(int: d1, int: d2); /** @group builtins.random Return a sample from the student's t-distribution defined by the sample size \(\a n\) */ function float: tdistribution(float: n); /** @group builtins.random Return a sample from the student's t-distribution defined by the sample size \(\a n\) */ function float: tdistribution(int: n); /** @group builtins.random Return a sample from the discrete distribution defined by the array of weights \(\a weights\) that assigns a weight to each integer starting from zero */ function int: discrete_distribution(array[int] of int: weights); /** @group builtins.random Return a boolean sample from the Bernoulli distribution defined by probability \(\a p\) */ function bool: bernoulli(float: p); /** @group builtins.random Return a sample from the binomial distribution defined by sample number \a t and probability \a p */ function int: binomial(int: t, float: p); /*** @groupdef builtins.special Special constraints These predicates allow users to mark constraints as e.g. symmetry breaking or redundant, so that solvers can choose to implement them differently. We cannot easily use annotations for this purpose, since annotations are propagated to all constraints in a decomposition, which may be incorrect for redundant or symmetry breaking constraints in the presence of common subexpression elimination (CSE). */ /** @group builtins.special Mark \a b as a symmetry breaking constraint */ predicate symmetry_breaking_constraint(var bool: b); /** @group builtins.special Mark \a b as a redundant constraint */ predicate redundant_constraint(var bool: b); /** @group builtins.special Mark \a b as an implied constraint (synonym for redundant_constraint) */ predicate implied_constraint(var bool: b) = redundant_constraint(b); function set of int: anon_enum(int: n) = 1..n; function set of int: anon_enum(array[int] of string: x); /*** @groupdef builtins.language Language information These functions return information about the MiniZinc system. */ /** @group builtins.language Return MiniZinc version encoded as an integer (major*10000+minor*1000+patch). */ function int: mzn_compiler_version(); /** @group builtins.language Return string representation of \a v given an integer major*10000+minor*1000+patch */ function string: mzn_version_to_string(int: v) = show(v div 10000)++"."++show((v div 1000) mod 10)++"."++show(v mod 100); %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% % Include solver-specific redefinitions for any FlatZinc built-ins. % include "redefinitions.mzn"; include "redefinitions-2.0.mzn"; include "redefinitions-2.0.2.mzn"; include "redefinitions-2.1.mzn"; include "redefinitions-2.1.1.mzn"; include "redefinitions-2.2.1.mzn"; %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------%