git-subtree-dir: software/mza git-subtree-split: f970a59b177c13ca3dd8aaef8cc6681d83b7e813
2751 lines
134 KiB
MiniZinc
2751 lines
134 KiB
MiniZinc
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<cols then ", "
|
|
elseif i<rows then " |\n " else " |]\n"
|
|
endif | i in 1..rows, j in 1..cols
|
|
])++if rows=0 then "|]" else "" endif;
|
|
|
|
/** @group builtins.string Convert three-dimensional array \a x into a string */
|
|
function string: show3d(array[int,int,int] of var opt $T: x) =
|
|
let { int: len1=card(index_set_1of3(x));
|
|
int: len2=card(index_set_2of3(x));
|
|
int: len3=card(index_set_3of3(x));
|
|
array[int] of string: s = [show(x[i,j,k]) | i in index_set_1of3(x),
|
|
j in index_set_2of3(x),
|
|
k in index_set_3of3(x)];
|
|
int: max_length = max([string_length(s[i]) | i in index_set(s)])
|
|
} in
|
|
"[| | "++
|
|
concat([format_justify_string(max_length,s[(i-1)*len2*len3+(j-1)*len3+k])++
|
|
if k<len3 then ", "
|
|
elseif j<len2 then " |\n "
|
|
elseif i<len1 then " |,\n\n | "
|
|
else " | |]\n"
|
|
endif | i in 1..len1, j in 1..len2, k in 1..len3
|
|
])++if len1=0 then "| |]" else "" endif;
|
|
|
|
/** @group builtins.string Convert \a x into JSON string */
|
|
function string: showJSON(var opt $T: x);
|
|
|
|
/** @group builtins.string Convert \a x into JSON string */
|
|
function string: showJSON(array[$U] of var opt $T: x);
|
|
|
|
/** @group builtins.string Return length of \a s */
|
|
function int: string_length(string: s);
|
|
|
|
/** @group builtins.string Return concatenation of \a s1 and \a s2 */
|
|
function string: '++'(string: s1, string: s2);
|
|
/** @group builtins.string Return concatenation of strings in array \a s */
|
|
function string: concat(array[$T] of string: s);
|
|
/** @group builtins.string Join string in array \a s using delimiter \a d */
|
|
function string: join(string: d, array[$T] of string: s);
|
|
|
|
/** @group builtins.string Convert \a x into a string */
|
|
function string: format(var opt $T: x) = show(x);
|
|
/** @group builtins.string Convert \a x into a string */
|
|
function string: format(var opt set of $T: x) = show(x);
|
|
/** @group builtins.string Convert \a x into a string */
|
|
function string: format(array[$U] of var opt $T: x) = show(x);
|
|
|
|
/** @group builtins.string Return array for output of all variables in JSON format */
|
|
function array[int] of string: outputJSON();
|
|
/** @group builtins.string Return array for output of all parameters in JSON format */
|
|
function array[int] of string: outputJSONParameters();
|
|
|
|
/** @group builtins.string Formatted to-string conversion
|
|
|
|
Converts the value \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 maximum length of the string representation of \a x is given by
|
|
\a p, or the maximum number of digits after the decimal point for floating
|
|
point numbers. It is a run-time error for \a p to be negative.
|
|
*/
|
|
function string: format(int: w, int: p, var opt $T: x);
|
|
/** @group builtins.string Formatted to-string conversion
|
|
|
|
Converts the value \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 maximum length of the string representation of \a x is given by
|
|
\a p. It is a run-time error for \a p to be negative.
|
|
*/
|
|
function string: format(int: w, int: p, var opt set of $T: x);
|
|
/** @group builtins.string Formatted to-string conversion
|
|
|
|
Converts the value \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 maximum length of the string representation of \a x is given by
|
|
\a p. It is a run-time error for \a p to be negative.
|
|
*/
|
|
function string: format(int: w, int: p, array[$U] of var opt $T: x);
|
|
|
|
/** @group builtins.string Formatted to-string conversion
|
|
|
|
Converts the value \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: format(int: w, var opt $T: x);
|
|
/** @group builtins.string Formatted to-string conversion
|
|
|
|
Converts the value \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: format(int: w, var opt set of $T: x);
|
|
/** @group builtins.string Formatted to-string conversion
|
|
|
|
Converts the value \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: format(int: w, array[$U] of var opt $T: x);
|
|
/** @group builtins.string String justification
|
|
|
|
Returns the string \a x right
|
|
justified by the number of characters given by \a w, or left
|
|
justified if \a w is negative.
|
|
*/
|
|
function string: format_justify_string(int: w, string: x);
|
|
|
|
/** @group builtins.string Return path of file where this function is called */
|
|
function string: file_path();
|
|
|
|
/***
|
|
@groupdef builtins.reflect Reflection operations
|
|
|
|
These functions return information about declared or inferred variable
|
|
bounds and domains.
|
|
*/
|
|
|
|
/** @group builtins.reflect Return lower bound of \a x */
|
|
function int: lb(var int: x);
|
|
/** @group builtins.reflect Return upper bound of \a x */
|
|
function int: ub(var int: x);
|
|
/** @group builtins.reflect Return lower bound of \a x */
|
|
function int: lb(var opt int: x);
|
|
/** @group builtins.reflect Return upper bound of \a x */
|
|
function int: ub(var opt int: x);
|
|
/** @group builtins.reflect Return lower bound of \a x */
|
|
function float: lb(var float: x);
|
|
/** @group builtins.reflect Return upper bound of \a x */
|
|
function float: ub(var float: x);
|
|
/** @group builtins.reflect Return lower bound of \a x */
|
|
function set of int: lb(var set of int: x);
|
|
/** @group builtins.reflect Return upper bound of \a x */
|
|
function set of int: ub(var set of int: x);
|
|
/** @group builtins.reflect Return array of lower bounds of the elements in array \a x */
|
|
function array[$U] of int: lb(array[$U] of var int: x) =
|
|
arrayXd(x,[lb(xx) | xx in array1d(x)]);
|
|
/** @group builtins.reflect Return array of upper bounds of the elements in array \a x */
|
|
function array[$U] of int: ub(array[$U] of var int: x) =
|
|
arrayXd(x,[ub(xx) | xx in array1d(x)]);
|
|
/** @group builtins.reflect Return array of lower bounds of the elements in array \a x */
|
|
function array[$U] of float: lb(array[$U] of var float: x) =
|
|
arrayXd(x,[lb(xx) | xx in array1d(x)]);
|
|
/** @group builtins.reflect Return array of upper bounds of the elements in array \a x */
|
|
function array[$U] of float: ub(array[$U] of var float: x) =
|
|
arrayXd(x,[ub(xx) | xx in array1d(x)]);
|
|
/** @group builtins.reflect Return array of lower bounds of the elements in array \a x */
|
|
function array[$U] of set of int: lb(array[$U] of var set of int: x) =
|
|
arrayXd(x,[lb(xx) | xx in array1d(x)]);
|
|
/** @group builtins.reflect Return array of upper bounds of the elements in array \a x */
|
|
function array[$U] of set of int: ub(array[$U] of var set of int: x) =
|
|
arrayXd(x,[ub(xx) | xx in array1d(x)]);
|
|
/** @group builtins.reflect Return minimum of all lower bounds of the elements in array \a x */
|
|
function int: lb_array(array[$U] of var opt int: x);
|
|
/** @group builtins.reflect Return maximum of all upper bounds of the elements in array \a x */
|
|
function int: ub_array(array[$U] of var opt int: x);
|
|
/** @group builtins.reflect Return minimum of all lower bounds of the elements in array \a x */
|
|
function float: lb_array(array[$U] of var float: x);
|
|
/** @group builtins.reflect Return maximum of all upper bounds of the elements in array \a x */
|
|
function float: ub_array(array[$U] of var float: x);
|
|
/** @group builtins.reflect Return intersection of all lower bounds of the elements in array \a x */
|
|
function set of int: lb_array(array[$U] of var set of int: x);
|
|
/** @group builtins.reflect Return union of all upper bounds of the elements in array \a x */
|
|
function set of int: ub_array(array[$U] of var set of int: x);
|
|
/** @group builtins.reflect Return domain of \a x */
|
|
function set of int: dom(var int: x);
|
|
function set of int: dom(var bool: b) =
|
|
if is_fixed(b) then if fix(b) then {1} else {0} endif else {0,1} endif;
|
|
|
|
/** @group builtins.reflect Return union of all domains of the elements in array \a x */
|
|
function set of int: dom_array(array[$T] of var int: x);
|
|
/** @group builtins.reflect Return approximation of union of all domains of the elements in array \a x */
|
|
function set of int: dom_bounds_array(array[$T] of var int: x);
|
|
/** @group builtins.reflect Return cardinality of the domain of \a x */
|
|
function int: dom_size(var int: x) = card(dom(x));
|
|
|
|
/** @group builtins.reflect Test if variable \a x has declared, finite bounds */
|
|
function par bool: has_bounds(var int: x);
|
|
/** @group builtins.reflect Test if variable \a x has declared, finite bounds */
|
|
function par bool: has_bounds(var float: x);
|
|
/** @group builtins.reflect Test if variable \a x has a declared, finite upper bound */
|
|
function par bool: has_ub_set(var set of int: x);
|
|
|
|
/** @group builtins.reflect Check if the value of \a x is fixed at this point
|
|
in evaluation. If it is fixed, return its value, otherwise abort. */
|
|
function $T: fix(var opt $T: x);
|
|
/** @group builtins.reflect Check if the value of every element of the array \a x is fixed
|
|
at this point in evaluation. If all are fixed, return an array of their values, otherwise abort. */
|
|
function array[$U] of $T: fix(array[$U] of var opt $T: x);
|
|
/** @group builtins.reflect Test if \a x is fixed */
|
|
function bool: is_fixed(var opt $T: x);
|
|
/** @group builtins.reflect Test if every element of array \a x is fixed */
|
|
function bool: is_fixed(array[$U] of var opt $T: x);
|
|
|
|
/***
|
|
@groupdef builtins.debug Assertions and debugging functions
|
|
|
|
These functions help debug models and check that input data conforms to
|
|
the expectations.
|
|
*/
|
|
|
|
/** @group builtins.debug If \a b is true, return \a x, otherwise abort with message \a msg. */
|
|
function $T: assert(bool: b, string: msg, $T: x);
|
|
/** @group builtins.debug If \a b is true, return \a x, otherwise abort with message \a msg. */
|
|
function var $T: assert(bool: b, string: msg, var $T: x);
|
|
/** @group builtins.debug If \a b is true, return \a x, otherwise abort with message \a msg. */
|
|
function var opt $T: assert(bool: b, string: msg, var opt $T: x);
|
|
|
|
/** @group builtins.debug If \a b is true, return \a x, otherwise abort with message \a msg. */
|
|
function array[$U] of $T: assert(bool: b, string: msg, array[$U] of $T: x);
|
|
/** @group builtins.debug If \a b is true, return \a x, otherwise abort with message \a msg. */
|
|
function array[$U] of var $T: assert(bool: b, string: msg, array[$U] of var $T: x);
|
|
/** @group builtins.debug If \a b is true, return \a x, otherwise abort with message \a msg. */
|
|
function array[$U] of var opt $T: assert(bool: b, string: msg, array[$U] of var opt $T: x);
|
|
|
|
/** @group builtins.debug If \a b is true, return true, otherwise abort with message \a msg. */
|
|
function bool: assert(bool: b, string: msg);
|
|
/** @group builtins.debug Return \a x, and print message \a msg. */
|
|
function $T: trace(string: msg, $T: x);
|
|
/** @group builtins.debug Return \a x, and print message \a msg. */
|
|
function var $T: trace(string: msg, var $T: x);
|
|
/** @group builtins.debug Return \a x, and print message \a msg. */
|
|
function var opt $T: trace(string: msg, var opt $T: x);
|
|
/** @group builtins.debug Return true, and print message \a msg. */
|
|
function bool: trace(string: msg);
|
|
|
|
/** @group builtins.debug Return \a x, and print message \a msg. */
|
|
function $T: trace_stdout(string: msg, $T: x);
|
|
/** @group builtins.debug Return \a x, and print message \a msg. */
|
|
function var $T: trace_stdout(string: msg, var $T: x);
|
|
/** @group builtins.debug Return \a x, and print message \a msg. */
|
|
function var opt $T: trace_stdout(string: msg, var opt $T: x);
|
|
/** @group builtins.debug Return true, and print message \a msg. */
|
|
function bool: trace_stdout(string: msg);
|
|
|
|
/** @group builtins.debug Abort evaluation and print message \a msg. */
|
|
function bool: abort(string: msg);
|
|
|
|
/***
|
|
@groupdef builtins.enum Functions for enums
|
|
|
|
*/
|
|
|
|
/** @group builtins.enum Return next greater enum value of \a x in enum \a e */
|
|
function $$E: enum_next(set of $$E: e, $$E: x);
|
|
/** @group builtins.enum Return next greater enum value of \a x in enum \a e */
|
|
function var $$E: enum_next(set of $$E: e, var $$E: x) =
|
|
let { constraint x < max(e) } in x+1;
|
|
|
|
/** @group builtins.enum Return next smaller enum value of \a x in enum \a e */
|
|
function $$E: enum_prev(set of $$E: e, $$E: x);
|
|
/** @group builtins.enum Return next smaller enum value of \a x in enum \a e */
|
|
function var $$E: enum_prev(set of $$E: e, var $$E: x) =
|
|
let { constraint x > 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";
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|