git-subtree-dir: software/minizinc git-subtree-split: 4f10c82056ffcb1041d7ffef29d77a7eef92cf76
268 lines
12 KiB
MiniZinc
268 lines
12 KiB
MiniZinc
/***
|
|
@groupdef stdlib.optiontypes Option type support
|
|
|
|
These functions and predicates implement the standard library for working
|
|
with option types. Note that option type support is still incomplete.
|
|
*/
|
|
|
|
/** @group stdlib.optiontypes Return value of \a x if \a x is not absent. Aborts
|
|
when evaluated on absent value. */
|
|
function $T: deopt(opt $T: x);
|
|
/** @group stdlib.optiontypes Return value of \a x if \a x is not absent. Aborts
|
|
when evaluated on absent value. */
|
|
function $$T: deopt(opt $$T: x);
|
|
|
|
/** @group stdlib.optiontypes Return value \a x unchanged (since \a x is guaranteed
|
|
to be non-optional). */
|
|
function var $T: deopt(var $T: x) = x;
|
|
|
|
/** @group optiontypes Test if \a x is not absent (always returns true) */
|
|
test occurs(var $T: x) = true;
|
|
/** @group optiontypes Test if \a x is not absent */
|
|
test occurs(opt $T: x);
|
|
/** @group optiontypes Test if \a x is absent (always returns false) */
|
|
test absent(var $T: x) = false;
|
|
/** @group optiontypes Test if \a x is absent */
|
|
test absent(opt $T: x) = not occurs(x);
|
|
|
|
/***
|
|
@groupdef stdlib.optiontypes.bool Option type support for Booleans
|
|
*/
|
|
|
|
/** @group stdlib.optiontypes.bool True iff \a x is not absent */
|
|
function var bool : occurs(var opt bool: x) ::promise_total = occurs_bool(x);
|
|
|
|
function bool : occurs_bool(opt bool: x) ::promise_total = occurs(x);
|
|
function bool : occurs_bool(var bool: x) ::promise_total = true;
|
|
function var bool : occurs_bool(var opt bool: x) ::promise_total =
|
|
let {
|
|
var bool : b = occurs_internal_bool(x);
|
|
var bool : dx = deopt_internal_bool(x);
|
|
constraint (x = reverse_map_var_opt_bool(b,dx)) :: is_reverse_map;
|
|
} in b;
|
|
|
|
/** @group stdlib.optiontypes.bool Return value of \a x (assumes that \a x is not absent) */
|
|
function var bool : deopt(var opt bool : x) ::promise_total = deopt_bool(x);
|
|
|
|
function bool : deopt_bool(opt bool : x) ::promise_total = deopt(x);
|
|
function var bool : deopt_bool(var bool : x) ::promise_total = x;
|
|
function var bool : deopt_bool(var opt bool : x) ::promise_total =
|
|
let {
|
|
var bool : b = occurs_internal_bool(x);
|
|
var bool : dx = deopt_internal_bool(x);
|
|
constraint (x = reverse_map_var_opt_bool(b,dx)) :: is_reverse_map;
|
|
} in dx;
|
|
|
|
/** @group stdlib.optiontypes.bool True iff \a x is absent */
|
|
predicate absent(var opt bool: x) = not occurs(x);
|
|
|
|
function var bool: occurs_internal_bool(var opt bool: x) ::promise_total =
|
|
let { var bool : b; } in b;
|
|
function var bool : deopt_internal_bool(var opt bool : x) ::promise_total =
|
|
let { var bool: y } in y;
|
|
|
|
function var opt bool: reverse_map_var_opt_bool(var bool: occ, var bool: d);
|
|
function opt bool: reverse_map_var_opt_bool(bool: occ, bool: d) ::promise_total =
|
|
if occ then d else <> endif;
|
|
|
|
predicate mzn_reverse_map_var(var opt bool: x) =
|
|
let {
|
|
var bool : b = occurs_internal_bool(x);
|
|
var bool : dx = deopt_internal_bool(x);
|
|
constraint (x = reverse_map_var_opt_bool(b,dx)) :: is_reverse_map;
|
|
} in true;
|
|
|
|
/** @group stdlib.optiontypes.bool Weak equality. True if either \a x or \a y are absent, or
|
|
present and equal.*/
|
|
function var bool: '~='(var opt bool: x, var opt bool: y) ::promise_total =
|
|
absent(x) \/ absent(y) \/ deopt(x)=deopt(y);
|
|
|
|
/***
|
|
@groupdef stdlib.optiontypes.int Option type support for integers
|
|
*/
|
|
|
|
/** @group stdlib.optiontypes.int True iff \a x is not absent */
|
|
function var bool : occurs(var opt int : x) ::promise_total = occurs_int(x);
|
|
|
|
function bool : occurs_int(opt int : x) ::promise_total = occurs(x);
|
|
function bool : occurs_int(var int : x) ::promise_total = true;
|
|
function var bool : occurs_int(var opt int : x) ::promise_total =
|
|
let {
|
|
var bool : b = occurs_internal_int(x);
|
|
var int : dx = deopt_internal_int(x);
|
|
constraint (x = reverse_map_var_opt_int(b,dx)) :: is_reverse_map;
|
|
} in b;
|
|
function var bool : occurs_int(var opt bool : x) ::promise_total = occurs(x);
|
|
function bool : occurs_int(opt bool : x) ::promise_total = occurs(x);
|
|
function bool : occurs_int(var bool : x) ::promise_total = true;
|
|
|
|
/** @group stdlib.optiontypes.int Return value of \a x (assumes that \a x is not absent) */
|
|
function var $$E : deopt(var opt $$E : x) ::promise_total = deopt_int(x);
|
|
|
|
function int : deopt_int(opt int : x) ::promise_total = deopt(x);
|
|
function var int : deopt_int(var int : x) ::promise_total = x;
|
|
function var int : deopt_int(var opt int : x) ::promise_total =
|
|
let {
|
|
var bool : b = occurs_internal_int(x);
|
|
var int : dx = deopt_internal_int(x);
|
|
constraint (x = reverse_map_var_opt_int(b,dx)) :: is_reverse_map;
|
|
} in dx;
|
|
function var bool : deopt_int(var opt bool : x) ::promise_total = deopt(x);
|
|
function var bool : deopt_int(var bool : x) ::promise_total = x;
|
|
function bool : deopt_int(opt bool : x) ::promise_total = deopt(x);
|
|
|
|
|
|
/** @group stdlib.optiontypes.int True iff \a x is absent */
|
|
function var bool: absent(var opt int: x) ::promise_total = not occurs(x);
|
|
|
|
function var bool: occurs_internal_int(var opt int: x) ::promise_total =
|
|
let { var bool : b; } in b;
|
|
function var int : deopt_internal_int(var opt int : x) ::promise_total =
|
|
let { var dom(x): y } in y;
|
|
|
|
function var opt int: reverse_map_var_opt_int(var bool: occ, var int: d);
|
|
function opt int: reverse_map_var_opt_int(bool: occ, int: d) ::promise_total =
|
|
if occ then d else <> endif;
|
|
|
|
predicate mzn_reverse_map_var(var opt int: x) =
|
|
let {
|
|
var bool : b = occurs_internal_int(x);
|
|
var int : dx = deopt_internal_int(x);
|
|
constraint (x = reverse_map_var_opt_int(b,dx)) :: is_reverse_map;
|
|
} in true;
|
|
|
|
|
|
/** @group stdlib.optiontypes.int Weak addition. Return sum of \a x and \a y if both
|
|
are present, otherwise return absent. */
|
|
function var opt int: '~+'(var opt int: x, var opt int: y) ::promise_total =
|
|
let {
|
|
int: l = if lb(x)=-infinity \/ lb(y)=-infinity then -infinity else lb(x)+lb(y) endif;
|
|
int: u = if ub(x)=infinity \/ ub(y)=infinity then infinity else ub(x)+ub(y) endif;
|
|
var opt l..u: result;
|
|
constraint absent(x) \/ absent(y) -> result = <>;
|
|
constraint absent(x) \/ absent(y) \/ result = deopt(x)+deopt(y);
|
|
} in result;
|
|
|
|
/** @group stdlib.optiontypes.int Weak subtraction. Return difference of \a x and \a y if both
|
|
are present, otherwise return absent. */
|
|
function var opt int: '~-'(var opt int: x, var opt int: y) ::promise_total =
|
|
let {
|
|
int: l = if lb(x)=-infinity \/ ub(y)=infinity then -infinity else lb(x)-ub(y) endif;
|
|
int: u = if ub(x)=infinity \/ lb(y)=-infinity then infinity else ub(x)-lb(y) endif;
|
|
var opt l..u: result;
|
|
constraint absent(x) \/ absent(y) -> result = <>;
|
|
constraint absent(x) \/ absent(y) \/ result = deopt(x)-deopt(y);
|
|
} in result;
|
|
|
|
/** @group stdlib.optiontypes.int Weak multiplication. Return product of \a x and \a y if both
|
|
are present, otherwise return absent. */
|
|
function var opt int: '~*'(var opt int: x, var opt int: y) ::promise_total =
|
|
if absent(x) \/ absent(y) then <>
|
|
else deopt(x)*deopt(y) endif;
|
|
|
|
/** @group stdlib.optiontypes.int Weak equality. True if either \a x or \a y are absent, or
|
|
present and equal.*/
|
|
function var bool: '~='(var opt int: x, var opt int: y) ::promise_total =
|
|
absent(x) \/ absent(y) \/ deopt(x)=deopt(y);
|
|
|
|
/* Internal function used to optimize over option type objective */
|
|
|
|
function var int: objective_deopt_(var opt int: x, bool: direction) =
|
|
let {
|
|
int: worst = if direction then lb(x)-1 else ub(x)+1 endif;
|
|
} in if occurs(x) then deopt(x) else worst endif;
|
|
|
|
/***
|
|
@groupdef stdlib.optiontypes.float Option type support for floats
|
|
*/
|
|
|
|
/** @group stdlib.optiontypes.float True iff \a x is not absent */
|
|
function var bool : occurs(var opt float : x) ::promise_total = occurs_float(x);
|
|
|
|
function bool : occurs_float(opt float : x) ::promise_total = occurs(x);
|
|
function bool : occurs_float(opt int : x) ::promise_total = occurs(x);
|
|
function bool : occurs_float(opt bool : x) ::promise_total = occurs(x);
|
|
function bool : occurs_float(var float : x) ::promise_total = true;
|
|
function var bool : occurs_float(var opt float : x) ::promise_total =
|
|
let {
|
|
var bool : b = occurs_internal_float(x);
|
|
var float : dx = deopt_internal_float(x);
|
|
constraint (x = reverse_map_var_opt_float(b,dx)) :: is_reverse_map;
|
|
} in b;
|
|
function var bool : occurs_float(var opt int : x) ::promise_total = occurs_int(x);
|
|
function bool : occurs_float(var int : x) ::promise_total = true;
|
|
function var bool : occurs_float(var opt bool : x) ::promise_total = occurs_bool(x);
|
|
function bool : occurs_float(var bool : x) ::promise_total = true;
|
|
|
|
|
|
/** @group stdlib.optiontypes.float Return value of \a x (assumes that \a x is not absent) */
|
|
function var float : deopt(var opt float : x) ::promise_total = deopt_float(x);
|
|
|
|
function var float : deopt_float(var float : x) ::promise_total = x;
|
|
function var float : deopt_float(var opt float : x) ::promise_total =
|
|
let {
|
|
var bool : b = occurs_internal_float(x);
|
|
var float : dx = deopt_internal_float(x);
|
|
constraint (x = reverse_map_var_opt_float(b,dx)) :: is_reverse_map;
|
|
} in dx;
|
|
function var int : deopt_float(var opt int : x) ::promise_total = deopt_int(x);
|
|
function var int : deopt_float(var int : x) ::promise_total = x;
|
|
function var bool : deopt_float(var opt bool : x) ::promise_total = deopt_bool(x);
|
|
function var bool : deopt_float(var bool : x) ::promise_total = x;
|
|
function float : deopt_float(opt float : x) ::promise_total = deopt(x);
|
|
function int : deopt_float(opt int : x) ::promise_total = deopt(x);
|
|
function bool : deopt_float(opt bool : x) ::promise_total = deopt(x);
|
|
|
|
/** @group stdlib.optiontypes.float True iff \a x is absent */
|
|
function var bool: absent(var opt float: x) ::promise_total = not occurs(x);
|
|
|
|
function var bool: occurs_internal_float(var opt float: x) ::promise_total =
|
|
let { var bool : b; } in b;
|
|
function var float : deopt_internal_float(var opt float : x) ::promise_total =
|
|
let { var lb(x)..ub(x): y } in y;
|
|
|
|
function var opt float: reverse_map_var_opt_float(var bool: occ, var float: d); % :NOTE: Must define in cpp?
|
|
function opt float: reverse_map_var_opt_float(bool: occ, float: d) ::promise_total =
|
|
if occ then d else <> endif;
|
|
|
|
predicate mzn_reverse_map_var(var opt float: x) =
|
|
let {
|
|
var bool : b = occurs_internal_float(x);
|
|
var float : dx = deopt_internal_float(x);
|
|
constraint (x = reverse_map_var_opt_float(b,dx)) :: is_reverse_map;
|
|
} in true;
|
|
|
|
/** @group stdlib.optiontypes.float Weak addition. Return sum of \a x and \a y if both
|
|
are present, otherwise return absent. */
|
|
function var opt float: '~+'(var opt float: x, var opt float: y) ::promise_total =
|
|
let {
|
|
float: l = if lb(x)=-infinity \/ lb(y)=-infinity then -infinity else lb(x)+lb(y) endif;
|
|
float: u = if ub(x)=infinity \/ ub(y)=infinity then infinity else ub(x)+ub(y) endif;
|
|
var opt l..u: result;
|
|
constraint absent(x) \/ absent(y) -> result = <>;
|
|
constraint absent(x) \/ absent(y) \/ result = deopt(x)+deopt(y);
|
|
} in result;
|
|
|
|
/** @group stdlib.optiontypes.float Weak subtraction. Return difference of \a x and \a y if both
|
|
are present, otherwise return absent. */
|
|
function var opt float: '~-'(var opt float: x, var opt float: y) ::promise_total =
|
|
let {
|
|
float: l = if lb(x)=-infinity \/ ub(y)=infinity then -infinity else lb(x)-ub(y) endif;
|
|
float: u = if ub(x)=infinity \/ lb(y)=-infinity then infinity else ub(x)-lb(y) endif;
|
|
var opt l..u: result;
|
|
constraint absent(x) \/ absent(y) -> result = <>;
|
|
constraint absent(x) \/ absent(y) \/ result = deopt(x)-deopt(y);
|
|
} in result;
|
|
|
|
/** @group stdlib.optiontypes.float Weak multiplication. Return product of \a x and \a y if both
|
|
are present, otherwise return absent. */
|
|
function var opt float: '~*'(var opt float: x, var opt float: y) ::promise_total =
|
|
if absent(x) \/ absent(y) then <>
|
|
else deopt(x)*deopt(y) endif;
|
|
|
|
/** @group stdlib.optiontypes.float Weak equality. True if either \a x or \a y are absent, or
|
|
present and equal.*/
|
|
function var bool: '~='(var opt float: x, var opt float: y) ::promise_total =
|
|
absent(x) \/ absent(y) \/ deopt(x)=deopt(y);
|
|
|