1%---------------------------------------------------------------------- 2% BEGIN LICENSE BLOCK 3% Version: CMPL 1.1 4% 5% The contents of this file are subject to the Cisco-style Mozilla Public 6% License Version 1.1 (the "License"); you may not use this file except 7% in compliance with the License. You may obtain a copy of the License 8% at www.eclipse-clp.org/license. 9% 10% Software distributed under the License is distributed on an "AS IS" 11% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 12% the License for the specific language governing rights and limitations 13% under the License. 14% 15% The Original Code is The Zinc Modelling Interface for ECLiPSe 16% The Initial Developer of the Original Code is Joachim Schimpf 17% Portions created by the Initial Developer are 18% Copyright (C) 2007 Cisco Systems, Inc. All Rights Reserved. 19% 20% Contributor(s): Joachim Schimpf 21% 22% END LICENSE BLOCK 23% 24% 25% TODO: 26% X+Y#=C should be done as ac_eq(X,Y,C) if ac is wanted, X#=Y+c for bc 27% 28%---------------------------------------------------------------------- 29 30:- module(fzn_ic). 31 32:- comment(categories, ["Interfacing","Constraints"]). 33:- comment(summary, "Mapping from FlatZinc to lib(ic) and lib(ic_sets)"). 34:- comment(author, "Joachim Schimpf, supported by Cisco Systems and NICTA Victoria"). 35:- comment(copyright, "Cisco Systems Inc, licensed under CMPL"). 36:- comment(date, "$Date: 2015/01/14 01:31:09 $"). 37:- comment(see_also, [library(flatzinc), 38 library(ic),library(ic_sets),library(ic_global), 39 library(propia),library(branch_and_bound)]). 40:- comment(desc, html(" 41This module defines a mapping from FlatZinc operations to lib(ic), 42lib(ic_sets) and lib(ic_global), and is intended to be used in 43conjunction with lib(flatzinc). It uses lib(propia) to implement 44variants of the element constraint that are not supported by lib(ic). 45Moreover, lib(branch_and_bound) is used to provide optimization. 46</P><P> 47This mapping supports bool, integer, float and set variables. 48It does currently not support all constraints in reified form, 49in particular set constraints, according to the limitations of 50the underlying solvers. 51</P><P> 52The following extra annotations are supported by this mapping: 53<DL> 54<DT>annotation strategy(string:s)</DT> 55 <DD>the branch-and-bound strategy (default: \"continue\"). Valid names 56 are \"continue\", \"restart\", \"dichotomic\", See bb_min/3.</DD> 57<DT>annotation delta(float:f)</DT> 58 <DD>minimal absolute improvement for branch-and-bound steps (default 1.0). 59 See bb_min/3.</DD> 60<DT>annotation factor(float:f)</DT> 61 <DD>minimal improvement ratio (with respect to the lower cost bound) 62 for strategies 'continue' and 'restart' (default 1.0), or split factor 63 for strategy 'dichotomic' (default 0.5). See bb_min/3.</DD> 64<DT>annotation timeout(float:f)</DT> 65 <DD>timeout for branch-and-bound in seconds (default: unlimited). 66 See bb_min/3.</DD> 67</DL> 68You must include \"eclipse.mzn\" in your MiniZinc model to use these 69annotations. 70<P> 71")). 72 73 74% Lazy person's way of exporting (almost) all locally defined predicates: 75:- local initialization( 76 ( 77 current_module_predicate(local, Pred), 78 get_flag(Pred, auxiliary, off), 79 nonmember(Pred, [ 80 arg_nd/3, 81 array_any_element/3, 82 vector_sum/3, 83 search_ann/1, 84 set_choice/3, 85 termify/2 86 ]), 87 export(Pred), 88 fail 89 ; 90 true 91 )). 92 93:- lib(ic). % the actual solver libraries 94:- lib(ic_sets). 95:- lib(propia). 96:- lib(branch_and_bound). 97 98:- import % resolve ambiguous imports 99 (::)/2, 100 intersection/3, 101 subset/2, 102 union/3 103 from ic_sets. 104 105:- import 106 fzn_write/2, 107 fzn_error/2 108 from flatzinc. 109 110 111% Declarations ----------------------------------------------- 112 113% Single variable declarations 114bool_declare(X) :- X #:: 0..1. 115int_declare(X) :- integers(X). 116float_declare(X) :- reals(X). 117int_declare(X, Min, Max) :- X #:: Min..Max. 118int_declare(X, Elems) :- X #:: Elems. 119float_declare(X, Min, Max) :- X $:: Min..Max. 120set_declare(X, Min, Max) :- intset(X, Min, Max). 121set_declare(X, Elems) :- X :: Elems. 122 123% Variable array declarations 124% Unfortunately not all primitives can handle arrays 125bool_declare_array(Xs) :- Xs #:: 0..1. 126int_declare_array(Xs) :- ( foreacharg(X,Xs) do integers(X) ). 127float_declare_array(Xs) :- ( foreacharg(X,Xs) do reals(X) ). 128int_declare_array(Xs, Min, Max) :- Xs #:: Min..Max. 129int_declare_array(Xs, Elems) :- Xs #:: Elems. 130float_declare_array(Xs, Min, Max) :- Xs $:: Min..Max. 131set_declare_array(Xs, Min, Max) :- 132 ( foreacharg(X,Xs), param(Min,Max) do intset(X, Min, Max) ). 133set_declare_array(Xs, Elems) :- 134 ( foreacharg(X,Xs), param(Elems) do X :: Elems ). 135 136 137% Comparisons ----------------------------------------------- 138 139% int_??(var int, var int) 140int_eq(X, Y) :- X = Y. 141int_ne(X, Y) :- X #\= Y. 142int_le(X, Y) :- X #=< Y. 143int_ge(X, Y) :- X #>= Y. % OBSOLETE 1.2 144int_lt(X, Y) :- X #< Y. 145int_gt(X, Y) :- X #> Y. % OBSOLETE 1.2 146 147% float_??(var float, var float) 148float_eq(X, Y) :- X = Y. 149float_ne(X, Y) :- X $\= Y. 150float_le(X, Y) :- X $=< Y. 151float_ge(X, Y) :- X $>= Y. % OBSOLETE 1.2 152float_lt(X, Y) :- X $< Y. 153float_gt(X, Y) :- X $> Y. % OBSOLETE 1.2 154 155% bool_??(var bool, var bool) 156bool_eq(X, Y) :- X = Y. 157bool_ne(X, Y) :- X #\= Y. % OBSOLETE 1.2 158bool_le(X, Y) :- X #=< Y. 159bool_ge(X, Y) :- X #>= Y. % OBSOLETE 1.2 160bool_lt(X, Y) :- X #< Y. 161bool_gt(X, Y) :- X #> Y. % OBSOLETE 1.2 162 163% set_??(var set, var set) 164set_eq(X, Y) :- X = Y. 165%set_ne(X, Y) :- 166%set_le(X, Y) :- 167%set_ge(X, Y) :- % OBSOLETE 1.2 168%set_lt(X, Y) :- 169%set_gt(X, Y) :- % OBSOLETE 1.2 170 171% int_lin_??(array[int] of int, array[int] of var int, int) 172int_lin_eq(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) #= Rhs. 173int_lin_ne(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) #\= Rhs. 174int_lin_le(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) #=< Rhs. 175int_lin_ge(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) #>= Rhs. % OBSOLETE 1.2 176int_lin_lt(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) #< Rhs. % OBSOLETE 1.2 177int_lin_gt(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) #> Rhs. % OBSOLETE 1.2 178 179% float_lin_??(array[int] of float, array[int] of var float, float) 180float_lin_eq(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) $= Rhs. 181float_lin_ne(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) $\= Rhs. 182float_lin_le(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) $=< Rhs. 183float_lin_ge(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) $>= Rhs. % OBSOLETE 1.2 184float_lin_lt(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) $< Rhs. 185float_lin_gt(Cs, Xs, Rhs) :- vector_sum(Cs, Xs, CXs), sum(CXs) $> Rhs. % OBSOLETE 1.2 186 187 188% int_??(var int, var int, var bool) 189int_eq_reif(X, Y, B) :- #=(X, Y, B). 190int_ne_reif(X, Y, B) :- #\=(X, Y, B). 191int_le_reif(X, Y, B) :- #=<(X, Y, B). 192int_ge_reif(X, Y, B) :- #>=(X, Y, B). % OBSOLETE 1.2 193int_lt_reif(X, Y, B) :- #<(X, Y, B). 194int_gt_reif(X, Y, B) :- #>(X, Y, B). % OBSOLETE 1.2 195 196% float_??(var float, var float, B) 197float_eq_reif(X, Y, B) :- $=(X, Y, B). 198float_ne_reif(X, Y, B) :- $\=(X, Y, B). 199float_le_reif(X, Y, B) :- $=<(X, Y, B). 200float_ge_reif(X, Y, B) :- $>=(X, Y, B). % OBSOLETE 1.2 201float_lt_reif(X, Y, B) :- $<(X, Y, B). 202float_gt_reif(X, Y, B) :- $>(X, Y, B). % OBSOLETE 1.2 203 204% bool_??(var bool, var bool) 205bool_eq_reif(X, Y, B) :- #=(X, Y, B). 206bool_ne_reif(X, Y, B) :- #\=(X, Y, B). % OBSOLETE 1.2 207bool_le_reif(X, Y, B) :- #=<(X, Y, B). 208bool_ge_reif(X, Y, B) :- #>=(X, Y, B). % OBSOLETE 1.2 209bool_lt_reif(X, Y, B) :- #<(X, Y, B). 210bool_gt_reif(X, Y, B) :- #>(X, Y, B). % OBSOLETE 1.2 211 212% set_??(var set, var set, B) 213%set_eq_reif(X, Y, B) :- 214%set_ne_reif(X, Y, B) :- 215%set_le_reif(X, Y, B) :- % OBSOLETE? 216%set_ge_reif(X, Y, B) :- % OBSOLETE 1.2 217%set_lt_reif(X, Y, B) :- % OBSOLETE? 218%set_gt_reif(X, Y, B) :- % OBSOLETE 1.2 219 220% int_lin_??(array[int] of int, array[int] of var int, int, var bool) 221int_lin_eq_reif(Cs, Xs, Rhs, B) :- vector_sum(Cs, Xs, CXs), #=(sum(CXs), Rhs, B). 222int_lin_ne_reif(Cs, Xs, Rhs, B) :- vector_sum(Cs, Xs, CXs), #\=(sum(CXs), Rhs, B). 223int_lin_le_reif(Cs, Xs, Rhs, B) :- vector_sum(Cs, Xs, CXs), #=<(sum(CXs), Rhs, B). 224int_lin_ge_reif(Cs, Xs, Rhs, B) :- vector_sum(Cs, Xs, CXs), #>=(sum(CXs), Rhs, B). % OBSOLETE 1.2 225int_lin_lt_reif(Cs, Xs, Rhs, B) :- vector_sum(Cs, Xs, CXs), #<(sum(CXs), Rhs, B). % OBSOLETE 1.2 226int_lin_gt_reif(Cs, Xs, Rhs, B) :- vector_sum(Cs, Xs, CXs), #>(sum(CXs), Rhs, B). % OBSOLETE 1.2 227 228% float_lin_??(array[int] of float, array[int] of var float, float, B) 229float_lin_eq_reif(Cs, Xs, Rhs, B) :- vector_sum(Cs, Xs, CXs), $=(sum(CXs), Rhs, B). 230float_lin_ne_reif(Cs, Xs, Rhs, B) :- vector_sum(Cs, Xs, CXs), $\=(sum(CXs), Rhs, B). 231float_lin_le_reif(Cs, Xs, Rhs, B) :- vector_sum(Cs, Xs, CXs), $=<(sum(CXs), Rhs, B). 232float_lin_ge_reif(Cs, Xs, Rhs, B) :- vector_sum(Cs, Xs, CXs), $>=(sum(CXs), Rhs, B). % OBSOLETE 1.2 233float_lin_lt_reif(Cs, Xs, Rhs, B) :- vector_sum(Cs, Xs, CXs), $<(sum(CXs), Rhs, B). 234float_lin_gt_reif(Cs, Xs, Rhs, B) :- vector_sum(Cs, Xs, CXs), $>(sum(CXs), Rhs, B). % OBSOLETE 1.2 235 236 vector_sum(Cs, Xs, CXs) :- 237 arity(Cs, N), 238 ( arity(Xs, N) -> 239 ( for(I,1,N), foreach(C*X,CXs), param(Cs,Xs) do 240 arg(I, Cs, C), arg(I, Xs, X) 241 ) 242 ; 243 fzn_error("Mismatched vector product %w %w", [Cs, Xs]) 244 ). 245 246 247% Arithmetic operations ----------------------------------------------- 248 249% int_???(var int, var int, var int) 250int_negate(X, Z) :- Z #= -X. % OBSOLETE 1.2 251int_plus(X, Y, Z) :- Z #= X+Y. 252int_minus(X, Y, Z) :- Z #= X-Y. % OBSOLETE 1.2 253int_times(X, Y, Z) :- Z #= X*Y. 254int_div(Dividend, Divisor, Quotient) :- 255 Remainder #>=0, Remainder #< abs(Divisor), 256 Dividend #= Quotient*Divisor + Remainder. 257int_mod(Dividend, Divisor, Remainder) :- 258 Remainder #>=0, Remainder #< abs(Divisor), 259 Dividend #= _Quotient*Divisor + Remainder. 260int_min(X, Y, Z) :- Z #= min(X,Y). 261int_max(X, Y, Z) :- Z #= max(X,Y). 262int_abs(X, Z) :- Z #= abs(X). 263 264% float_???(var float, var float, var float) 265float_negate(X, Z) :- Z $= -X. % OBSOLETE 1.2 266float_plus(X, Y, Z) :- Z $= X+Y. 267float_minus(X, Y, Z) :- Z $= X-Y. % OBSOLETE 1.2 268float_times(X, Y, Z) :- Z $= X*Y. % OBSOLETE? 269float_div(X, Y, Z) :- Z $= X/Y. % OBSOLETE? 270float_min(X, Y, Z) :- Z $= min(X,Y). 271float_max(X, Y, Z) :- Z $= max(X,Y). 272float_abs(X, Z) :- Z $= abs(X). 273float_cos(X, Z) :- Z $= cos(X). 274float_sin(X, Z) :- Z $= sin(X). 275float_atan(X, Z) :- Z $= atan(X). 276float_sqrt(X, Z) :- Z $= sqrt(X). 277float_exp(X, Z) :- Z $= exp(X). 278float_ln(X, Z) :- Z $= ln(X). 279 280 281% Logical operations ----------------------------------------------- 282 283% bool_???(var bool, var bool, var bool) 284bool_and(X, Y, Z) :- and(X, Y, Z). 285bool_or(X, Y, Z) :- or(X, Y, Z). 286bool_left_imp(X, Y, Z) :- =>(Y, X, Z). % OBSOLETE 1.2 287bool_right_imp(X, Y, Z) :- =>(X, Y, Z). % OBSOLETE 1.2 288bool_xor(X, Y, Z) :- #\=(X, Y, Z). 289bool_not(X, Z) :- neg(X, Z). 290 291% array_bool_???(array[int] of var bool, var bool) 292array_bool_and(Xs, B) :- ic_global:minlist(Xs, B). 293array_bool_or(Xs, B) :- ic_global:maxlist(Xs, B). 294 295% bool_clause(array[int] of var bool, array[int] of var bool) 296bool_clause(Ps, Ns) :- 297 bool_clause_reif(Ps, Ns, 1). 298bool_clause_reif(Ps, Ns, B) :- % OBSOLETE 1.2 299 ic_global:maxlist(Ps, B1), 300 ic_global:minlist(Ns, B2), 301 #>=(B1,B2,B). 302 303 304% Set operations ----------------------------------------------- 305 306% set_???(... var set of int ...) 307set_in(I, S) :- I in S. 308%set_in_reif(I, S, B) :- 309set_subset(Sub, Super) :- subset(Sub, Super). 310%set_subset_reif(Sub, Super, B) :- 311set_intersect(X, Y, Z) :- intersection(X, Y, Z). 312set_union(X, Y, Z) :- union(X, Y, Z). 313set_diff(X, Y, Z) :- difference(X, Y, Z). 314set_symdiff(X, Y, Z) :- symdiff(X, Y, Z). 315set_card(S, I) :- #(S, I). 316 317set_in_reif(I, S, B) :- in(I, S, B). 318 319 320% Array operations ----------------------------------------------- 321 322% array_xx_yy_element(var int, array[int] of xx yy, var yy) 323array_bool_element(I, Array, E) :- element(I, Array, E). 324array_int_element(I, Array, E) :- element(I, Array, E). 325array_float_element(I, Array, E) :- array_any_element(I, Array, E). 326%array_set_element(I, Array, E) :- array_any_element(I, Array, E). 327array_var_bool_element(I, Array, E) :- array_any_element(I, Array, E). 328array_var_int_element(I, Array, E) :- array_any_element(I, Array, E). 329array_var_float_element(I, Array, E) :- array_any_element(I, Array, E). 330%array_var_set_element(I, Array, E) :- array_any_element(I, Array, E). 331 332 array_any_element(I, Array, E) :- 333 arity(Array, N), 334 I #:: 1..N, 335 arg_nd(I, Array, E) infers ic. 336 337 arg_nd(I, Array, E) :- 338 indomain(I), 339 arg(I, Array, E). 340 341 342% Coercion operations ----------------------------------------------- 343 344% Caution: this needs to correctly handle various combinations 345% of variables and constants of different types (was bug 741). 346int2float(I, F) :- I $= F. 347 348bool2int(X, X). 349 350 351% FZN data <-> ECLiPSe data ----------------------------------------------- 352 353bool_fzn_to_solver(false, 0). 354bool_fzn_to_solver(true, 1). 355 356bool_solver_to_fzn(0, false). 357bool_solver_to_fzn(1, true). 358 359% convert FlatZinc floats to breals for lib(ic) 360float_fzn_to_solver(X, Real) :- Real is breal(X). 361 362% IC real variables may be instantiated to integers, floats or breals. 363% Convert integers to floats so the type is obvious for the Zinc user. 364float_solver_to_fzn(X, X) :- real(X). 365float_solver_to_fzn(X, F) :- integer(X), F is float(X). 366 367% Set constants are ordered lists in ic_sets 368set_fzn_to_solver(List, Set) :- eclipse_language:sort(List, Set). 369 370set_solver_to_fzn(List, List) :- is_list(List). 371 372% Set constants are ordered lists in ic_sets 373range_fzn_to_solver(Min, Max, Set) :- 374 ( for(I,Min,Max), foreach(I,Set) do true ). 375 376 377% Search ----------------------------------------------- 378 379satisfy(Anns) :- 380 ( foreach(Ann,Anns) do 381 termify(Ann, Ann1), % for Flatzinc<1.0 compatibility 382 search_ann(Ann1) 383 ). 384 385:- export minimize/3. % silence redefinition warning 386minimize(Expr, Anns, Cost) :- 387 extract_bb_anns(Anns, Anns1, BbOptions), 388 Cost $= Expr, 389 bb_min(satisfy(Anns1), Cost, BbOptions). 390 391maximize(Expr, Anns, ObjVal) :- 392 extract_bb_anns(Anns, Anns1, BbOptions), 393 Cost $= -Expr, 394 bb_min(satisfy(Anns1), Cost, BbOptions), 395 ObjVal is -Cost. 396 397 termify(In, Out) :- 398 functor(In, F, N), functor(Out, F, N), 399 ( for(I,1,N),param(In,Out) do 400 arg(I,In,InI), arg(I,Out,OutI), 401 ( string(InI) -> term_string(OutI,InI) ; OutI=InI ) 402 ). 403 404 405 % CAUTION: these must accept both arrays and lists! 406 search_ann(seq_search(Searches)) :- !, 407 ( foreacharg(Search,Searches) do search_ann(Search) ). 408 409 search_ann(bool_search(Vars, Select, Choice, Explore)) :- !, 410 search(Vars, 0, Select, Choice, Explore, []). 411 412 search_ann(int_search(Vars, Select, Choice, Explore)) :- !, 413 search(Vars, 0, Select, Choice, Explore, []). 414 415 search_ann(float_search(Vars, Prec, input_order, indomain_split, complete)) :- 416 real(Prec), !, 417 FPrec is float(Prec), 418 locate(Vars, Vars, FPrec, log), 419 % instantiate variables atomically 420 call_priority( 421 ( functor(Vars, [], _) -> 422 ( foreacharg(X,Vars) do 423 ( nonvar(X) -> true ; 424 X is breal_from_bounds(get_min(X),get_max(X)) 425 ) 426 ) 427 ; 428 ( foreach(X,Vars) do 429 ( nonvar(X) -> true ; 430 X is breal_from_bounds(get_min(X),get_max(X)) 431 ) 432 ) 433 ), 2). 434 435 search_ann(set_search(Sets, input_order, Choice, complete)) :- 436 set_choice(Choice, ElemSel, Order), !, 437 ( functor(Sets, [], _) -> 438 ( foreacharg(Set,Sets), param(ElemSel,Order) do 439 insetdomain(Set, any, ElemSel, Order) 440 ) 441 ; 442 ( foreach(Set,Sets), param(ElemSel,Order) do 443 insetdomain(Set, any, ElemSel, Order) 444 ) 445 ). 446 447 search_ann(Ann) :- 448 fzn_error("Unsupported search annotation: %w", [Ann]). 449 450 451 :- mode set_choice(+,-,-). 452 set_choice(indomain_min, small_first, in_notin). 453 set_choice(indomain_max, big_first, in_notin). 454 set_choice(outdomain_min, small_first, notin_in). 455 set_choice(outdomain_max, big_first, notin_in). 456 457 458 extract_bb_anns(Anns, RestAnns, BbOptions) :- 459 ( 460 foreach(Ann,Anns), 461 fromto(RestAnns,Anns2,Anns1,[]), 462 param(BbOptions) 463 do 464 ( bb_ann(Ann, BbOptions) -> Anns2 = Anns1 ; Anns2 = [Ann|Anns1] ) 465 ). 466 467 % Corresponding annotation-declarations are in eclipse.mzn 468 bb_ann(delta(R), bb_options{delta:F}) :- float(R, F). 469 bb_ann(factor(R), bb_options{factor:F}) :- float(R, F). 470 bb_ann(timeout(R), bb_options{timeout:F}) :- float(R, F). 471 bb_ann(strategy(S), bb_options{strategy:A}) :- atom_string(A, S). 472 473 474% Global Constraints (see fzn_ic/globals.mzn) ------------------- 475 476all_different_int(Xs) :- ic_global:alldifferent(Xs). 477 478at_most_int(N,Xs,V) :- ic_global:atmost(N, Xs, V). 479%at_most(N,Xs,V) :- Count #=< N, ic_global:occurrences(V, Xs, Count). 480 481at_least_int(N,Xs,V) :- Count #>= N, ic_global:occurrences(V, Xs, Count). 482 483exactly_int(N,Xs,V) :- ic_global:occurrences(V, Xs, N). 484 485count_avint_int_int(Xs,V,N) :- ic_global:occurrences(V, Xs, N). 486 487minimum_int(M, Xs) :- ic:min(Xs, M). 488minimum_float(M, Xs) :- ic:min(Xs, M). 489 490maximum_int(M, Xs) :- ic:max(Xs, M). 491maximum_float(M, Xs) :- ic:max(Xs, M). 492 493%cumulative_avint_aint_aint_vint(Ss,Ds,Rs,B) :- ic_cumulative:cumulative(Ss,Ds,Rs,B). 494cumulative_avint_aint_aint_vint(Ss,Ds,Rs,B) :- ic_edge_finder:cumulative(Ss,Ds,Rs,B). 495%cumulative_avint_aint_aint_vint(Ss,Ds,Rs,B) :- ic_edge_finder3:cumulative(Ss,Ds,Rs,B). 496 497:- export sort/2. % to resolve ambiguity with sort/2 builtin 498sort(Xs,Ss) :- ic_global:sorted(Xs, _Ps, Ss). 499 500 501:- reexport disjoint/2 from ic_sets. 502 503:- export all_disjoint/1. 504all_disjoint(Array) :- Array =.. [[]|List], ic_sets:all_disjoint(List). 505 506link_set_to_booleans(Set, Bools) :- ic_sets:membership_booleans(Set, Bools). 507 508