1
0
This repository has been archived on 2025-03-06. You can view files and clone it, but cannot push or open issues or pull requests.
Jip J. Dekker fad1b07018 Squashed 'software/minizinc/' content from commit 4f10c8205
git-subtree-dir: software/minizinc
git-subtree-split: 4f10c82056ffcb1041d7ffef29d77a7eef92cf76
2021-06-16 14:06:46 +10:00

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);