View source with raw comments or as raw
   1/*  Part of SWI-Prolog
   2
   3    Author:        Jan Wielemaker
   4    E-mail:        J.Wielemaker@vu.nl
   5    WWW:           http://www.swi-prolog.org
   6    Copyright (c)  2001-2014, University of Amsterdam
   7                              VU University Amsterdam
   8    All rights reserved.
   9
  10    Redistribution and use in source and binary forms, with or without
  11    modification, are permitted provided that the following conditions
  12    are met:
  13
  14    1. Redistributions of source code must retain the above copyright
  15       notice, this list of conditions and the following disclaimer.
  16
  17    2. Redistributions in binary form must reproduce the above copyright
  18       notice, this list of conditions and the following disclaimer in
  19       the documentation and/or other materials provided with the
  20       distribution.
  21
  22    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  25    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  26    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  27    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  28    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  29    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  30    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  32    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33    POSSIBILITY OF SUCH DAMAGE.
  34*/
  35
  36:- module(ordsets,
  37          [ is_ordset/1,                % @Term
  38            list_to_ord_set/2,          % +List, -OrdSet
  39            ord_add_element/3,          % +Set, +Element, -NewSet
  40            ord_del_element/3,          % +Set, +Element, -NewSet
  41            ord_selectchk/3,            % +Item, ?Set1, ?Set2
  42            ord_intersect/2,            % +Set1, +Set2 (test non-empty)
  43            ord_intersect/3,            % +Set1, +Set2, -Intersection
  44            ord_intersection/3,         % +Set1, +Set2, -Intersection
  45            ord_intersection/4,         % +Set1, +Set2, -Intersection, -Diff
  46            ord_disjoint/2,             % +Set1, +Set2
  47            ord_subtract/3,             % +Set, +Delete, -Remaining
  48            ord_union/2,                % +SetOfOrdSets, -Set
  49            ord_union/3,                % +Set1, +Set2, -Union
  50            ord_union/4,                % +Set1, +Set2, -Union, -New
  51            ord_subset/2,               % +Sub, +Super (test Sub is in Super)
  52                                        % Non-Quintus extensions
  53            ord_empty/1,                % ?Set
  54            ord_memberchk/2,            % +Element, +Set,
  55            ord_symdiff/3,              % +Set1, +Set2, ?Diff
  56                                        % SICSTus extensions
  57            ord_seteq/2,                % +Set1, +Set2
  58            ord_intersection/2          % +PowerSet, -Intersection
  59          ]).
  60:- use_module(library(oset)).
  61:- set_prolog_flag(generate_debug_info, false).
  62
  63/** <module> Ordered set manipulation
  64
  65Ordered sets are lists with unique elements sorted to the standard order
  66of terms (see sort/2). Exploiting ordering,   many of the set operations
  67can be expressed in order N rather  than N^2 when dealing with unordered
  68sets that may contain duplicates. The library(ordsets) is available in a
  69number of Prolog implementations. Our  predicates   are  designed  to be
  70compatible  with  common  practice   in    the   Prolog  community.  The
  71implementation is incomplete and  relies   partly  on  library(oset), an
  72older ordered set library distributed  with SWI-Prolog. New applications
  73are advised to use library(ordsets).
  74
  75Some  of  these  predicates  match    directly   to  corresponding  list
  76operations. It is advised to use the  versions from this library to make
  77clear you are operating on ordered sets.   An exception is member/2. See
  78ord_memberchk/2.
  79
  80The ordsets library is based  on  the   standard  order  of  terms. This
  81implies it can handle  all  Prolog   terms,  including  variables.  Note
  82however, that the ordering is not stable  if   a  term inside the set is
  83further instantiated. Also  note  that   variable  ordering  changes  if
  84variables in the set are unified with each   other  or a variable in the
  85set is unified with a variable that  is `older' than the newest variable
  86in the set. In  practice,  this  implies   that  it  is  allowed  to use
  87member(X, OrdSet) on an ordered set that holds  variables only if X is a
  88fresh variable. In other cases one should   cease  using it as an ordset
  89because the order it relies on may have been changed.
  90*/
  91
  92%!  is_ordset(@Term) is semidet.
  93%
  94%   True if Term is an ordered set.   All predicates in this library
  95%   expect ordered sets as input arguments.  Failing to fullfil this
  96%   assumption results in undefined   behaviour.  Typically, ordered
  97%   sets are created by predicates  from   this  library,  sort/2 or
  98%   setof/3.
  99
 100is_ordset(Term) :-
 101    is_list(Term),
 102    is_ordset2(Term).
 103
 104is_ordset2([]).
 105is_ordset2([H|T]) :-
 106    is_ordset3(T, H).
 107
 108is_ordset3([], _).
 109is_ordset3([H2|T], H) :-
 110    H2 @> H,
 111    is_ordset3(T, H2).
 112
 113
 114%!  ord_empty(?List) is semidet.
 115%
 116%   True when List is the  empty   ordered  set. Simply unifies list
 117%   with the empty list. Not part of Quintus.
 118
 119ord_empty([]).
 120
 121
 122%!  ord_seteq(+Set1, +Set2) is semidet.
 123%
 124%   True if Set1 and Set2  have  the   same  elements.  As  both are
 125%   canonical sorted lists, this is the same as ==/2.
 126%
 127%   @compat sicstus
 128
 129ord_seteq(Set1, Set2) :-
 130    Set1 == Set2.
 131
 132
 133%!  list_to_ord_set(+List, -OrdSet) is det.
 134%
 135%   Transform a list into an ordered set.  This is the same as
 136%   sorting the list.
 137
 138list_to_ord_set(List, Set) :-
 139    sort(List, Set).
 140
 141
 142%!  ord_intersect(+Set1, +Set2) is semidet.
 143%
 144%   True if both ordered sets have a non-empty intersection.
 145
 146ord_intersect([H1|T1], L2) :-
 147    ord_intersect_(L2, H1, T1).
 148
 149ord_intersect_([H2|T2], H1, T1) :-
 150    compare(Order, H1, H2),
 151    ord_intersect__(Order, H1, T1, H2, T2).
 152
 153ord_intersect__(<, _H1, T1,  H2, T2) :-
 154    ord_intersect_(T1, H2, T2).
 155ord_intersect__(=, _H1, _T1, _H2, _T2).
 156ord_intersect__(>, H1, T1,  _H2, T2) :-
 157    ord_intersect_(T2, H1, T1).
 158
 159
 160%!  ord_disjoint(+Set1, +Set2) is semidet.
 161%
 162%   True if Set1 and Set2  have  no   common  elements.  This is the
 163%   negation of ord_intersect/2.
 164
 165ord_disjoint(Set1, Set2) :-
 166    \+ ord_intersect(Set1, Set2).
 167
 168
 169%!  ord_intersect(+Set1, +Set2, -Intersection)
 170%
 171%   Intersection  holds  the  common  elements  of  Set1  and  Set2.
 172%
 173%   @deprecated Use ord_intersection/3
 174
 175ord_intersect(Set1, Set2, Intersection) :-
 176    oset_int(Set1, Set2, Intersection).
 177
 178
 179%!  ord_intersection(+PowerSet, -Intersection)
 180%
 181%   Intersection of a powerset. True when Intersection is an ordered
 182%   set holding all elements common to all sets in PowerSet.
 183%
 184%   @compat sicstus
 185
 186ord_intersection(PowerSet, Intersection) :-
 187    key_by_length(PowerSet, Pairs),
 188    keysort(Pairs, [_-S|Sorted]),
 189    l_int(Sorted, S, Intersection).
 190
 191key_by_length([], []).
 192key_by_length([H|T0], [L-H|T]) :-
 193    length(H, L),
 194    key_by_length(T0, T).
 195
 196l_int([], S, S).
 197l_int([_-H|T], S0, S) :-
 198    ord_intersection(S0, H, S1),
 199    l_int(T, S1, S).
 200
 201
 202%!  ord_intersection(+Set1, +Set2, -Intersection) is det.
 203%
 204%   Intersection holds the common elements of Set1 and Set2.
 205
 206ord_intersection(Set1, Set2, Intersection) :-
 207    oset_int(Set1, Set2, Intersection).
 208
 209
 210%!  ord_intersection(+Set1, +Set2, ?Intersection, ?Difference) is det.
 211%
 212%   Intersection  and  difference   between    two   ordered   sets.
 213%   Intersection is the intersection between   Set1  and Set2, while
 214%   Difference is defined by ord_subtract(Set2, Set1, Difference).
 215%
 216%   @see ord_intersection/3 and ord_subtract/3.
 217
 218ord_intersection([], L, [], L) :- !.
 219ord_intersection([_|_], [], [], []) :- !.
 220ord_intersection([H1|T1], [H2|T2], Intersection, Difference) :-
 221    compare(Diff, H1, H2),
 222    ord_intersection2(Diff, H1, T1, H2, T2, Intersection, Difference).
 223
 224ord_intersection2(=, H1, T1, _H2, T2, [H1|T], Difference) :-
 225    ord_intersection(T1, T2, T, Difference).
 226ord_intersection2(<, _, T1, H2, T2, Intersection, Difference) :-
 227    ord_intersection(T1, [H2|T2], Intersection, Difference).
 228ord_intersection2(>, H1, T1, H2, T2, Intersection, [H2|HDiff]) :-
 229    ord_intersection([H1|T1], T2, Intersection, HDiff).
 230
 231
 232%!  ord_add_element(+Set1, +Element, ?Set2) is det.
 233%
 234%   Insert  an  element  into  the  set.    This   is  the  same  as
 235%   ord_union(Set1, [Element], Set2).
 236
 237ord_add_element(Set1, Element, Set2) :-
 238    oset_addel(Set1, Element, Set2).
 239
 240
 241%!  ord_del_element(+Set, +Element, -NewSet) is det.
 242%
 243%   Delete an element from an  ordered  set.   This  is  the same as
 244%   ord_subtract(Set, [Element], NewSet).
 245
 246ord_del_element(Set, Element, NewSet) :-
 247    oset_delel(Set, Element, NewSet).
 248
 249
 250%!  ord_selectchk(+Item, ?Set1, ?Set2) is semidet.
 251%
 252%   Selectchk/3,  specialised  for  ordered  sets.    Is  true  when
 253%   select(Item, Set1, Set2) and Set1, Set2   are  both sorted lists
 254%   without duplicates. This implementation is only expected to work
 255%   for Item ground and either Set1 or Set2 ground. The "chk" suffix
 256%   is meant to remind you of   memberchk/2,  which also expects its
 257%   first  argument  to  be  ground.    ord_selectchk(X,  S,  T)  =>
 258%   ord_memberchk(X, S) & \+ ord_memberchk(X, T).
 259%
 260%   @author Richard O'Keefe
 261
 262ord_selectchk(Item, [X|Set1], [X|Set2]) :-
 263    X @< Item,
 264    !,
 265    ord_selectchk(Item, Set1, Set2).
 266ord_selectchk(Item, [Item|Set1], Set1) :-
 267    (   Set1 == []
 268    ->  true
 269    ;   Set1 = [Y|_]
 270    ->  Item @< Y
 271    ).
 272
 273
 274%!  ord_memberchk(+Element, +OrdSet) is semidet.
 275%
 276%   True if Element is a member of   OrdSet, compared using ==. Note
 277%   that _enumerating_ elements of an ordered  set can be done using
 278%   member/2.
 279%
 280%   Some Prolog implementations also provide  ord_member/2, with the
 281%   same semantics as ord_memberchk/2.  We   believe  that  having a
 282%   semidet ord_member/2 is unacceptably inconsistent with the *_chk
 283%   convention.  Portable  code  should    use   ord_memberchk/2  or
 284%   member/2.
 285%
 286%   @author Richard O'Keefe
 287
 288ord_memberchk(Item, [X1,X2,X3,X4|Xs]) :-
 289    !,
 290    compare(R4, Item, X4),
 291    (   R4 = (>) -> ord_memberchk(Item, Xs)
 292    ;   R4 = (<) ->
 293        compare(R2, Item, X2),
 294        (   R2 = (>) -> Item == X3
 295        ;   R2 = (<) -> Item == X1
 296        ;/* R2 = (=),   Item == X2 */ true
 297        )
 298    ;/* R4 = (=) */ true
 299    ).
 300ord_memberchk(Item, [X1,X2|Xs]) :-
 301    !,
 302    compare(R2, Item, X2),
 303    (   R2 = (>) -> ord_memberchk(Item, Xs)
 304    ;   R2 = (<) -> Item == X1
 305    ;/* R2 = (=) */ true
 306    ).
 307ord_memberchk(Item, [X1]) :-
 308    Item == X1.
 309
 310
 311%!  ord_subset(+Sub, +Super) is semidet.
 312%
 313%   Is true if all elements of Sub are in Super
 314
 315ord_subset([], _).
 316ord_subset([H1|T1], [H2|T2]) :-
 317    compare(Order, H1, H2),
 318    ord_subset_(Order, H1, T1, T2).
 319
 320ord_subset_(>, H1, T1, [H2|T2]) :-
 321    compare(Order, H1, H2),
 322    ord_subset_(Order, H1, T1, T2).
 323ord_subset_(=, _, T1, T2) :-
 324    ord_subset(T1, T2).
 325
 326
 327%!  ord_subtract(+InOSet, +NotInOSet, -Diff) is det.
 328%
 329%   Diff is the set holding all elements of InOSet that are not in
 330%   NotInOSet.
 331
 332ord_subtract(InOSet, NotInOSet, Diff) :-
 333    oset_diff(InOSet, NotInOSet, Diff).
 334
 335
 336%!  ord_union(+SetOfSets, -Union) is det.
 337%
 338%   True if Union is the  union  of   all  elements  in the superset
 339%   SetOfSets. Each member of SetOfSets must  be an ordered set, the
 340%   sets need not be ordered in any way.
 341%
 342%   @author Copied from YAP, probably originally by Richard O'Keefe.
 343
 344ord_union([], []).
 345ord_union([Set|Sets], Union) :-
 346    length([Set|Sets], NumberOfSets),
 347    ord_union_all(NumberOfSets, [Set|Sets], Union, []).
 348
 349ord_union_all(N, Sets0, Union, Sets) :-
 350    (   N =:= 1
 351    ->  Sets0 = [Union|Sets]
 352    ;   N =:= 2
 353    ->  Sets0 = [Set1,Set2|Sets],
 354        ord_union(Set1,Set2,Union)
 355    ;   A is N>>1,
 356        Z is N-A,
 357        ord_union_all(A, Sets0, X, Sets1),
 358        ord_union_all(Z, Sets1, Y, Sets),
 359        ord_union(X, Y, Union)
 360    ).
 361
 362
 363%!  ord_union(+Set1, +Set2, ?Union) is det.
 364%
 365%   Union is the union of Set1 and Set2
 366
 367ord_union(Set1, Set2, Union) :-
 368    oset_union(Set1, Set2, Union).
 369
 370
 371%!  ord_union(+Set1, +Set2, -Union, -New) is det.
 372%
 373%   True iff ord_union(Set1, Set2, Union) and
 374%   ord_subtract(Set2, Set1, New).
 375
 376ord_union([], Set2, Set2, Set2).
 377ord_union([H|T], Set2, Union, New) :-
 378    ord_union_1(Set2, H, T, Union, New).
 379
 380ord_union_1([], H, T, [H|T], []).
 381ord_union_1([H2|T2], H, T, Union, New) :-
 382    compare(Order, H, H2),
 383    ord_union(Order, H, T, H2, T2, Union, New).
 384
 385ord_union(<, H, T, H2, T2, [H|Union], New) :-
 386    ord_union_2(T, H2, T2, Union, New).
 387ord_union(>, H, T, H2, T2, [H2|Union], [H2|New]) :-
 388    ord_union_1(T2, H, T, Union, New).
 389ord_union(=, H, T, _, T2, [H|Union], New) :-
 390    ord_union(T, T2, Union, New).
 391
 392ord_union_2([], H2, T2, [H2|T2], [H2|T2]).
 393ord_union_2([H|T], H2, T2, Union, New) :-
 394    compare(Order, H, H2),
 395    ord_union(Order, H, T, H2, T2, Union, New).
 396
 397
 398%!  ord_symdiff(+Set1, +Set2, ?Difference) is det.
 399%
 400%   Is true when Difference is the  symmetric difference of Set1 and
 401%   Set2. I.e., Difference contains all elements that are not in the
 402%   intersection of Set1 and Set2. The semantics  is the same as the
 403%   sequence below (but the actual   implementation  requires only a
 404%   single scan).
 405%
 406%     ==
 407%           ord_union(Set1, Set2, Union),
 408%           ord_intersection(Set1, Set2, Intersection),
 409%           ord_subtract(Union, Intersection, Difference).
 410%     ==
 411%
 412%   For example:
 413%
 414%     ==
 415%     ?- ord_symdiff([1,2], [2,3], X).
 416%     X = [1,3].
 417%     ==
 418
 419ord_symdiff([], Set2, Set2).
 420ord_symdiff([H1|T1], Set2, Difference) :-
 421    ord_symdiff(Set2, H1, T1, Difference).
 422
 423ord_symdiff([], H1, T1, [H1|T1]).
 424ord_symdiff([H2|T2], H1, T1, Difference) :-
 425    compare(Order, H1, H2),
 426    ord_symdiff(Order, H1, T1, H2, T2, Difference).
 427
 428ord_symdiff(<, H1, Set1, H2, T2, [H1|Difference]) :-
 429    ord_symdiff(Set1, H2, T2, Difference).
 430ord_symdiff(=, _, T1, _, T2, Difference) :-
 431    ord_symdiff(T1, T2, Difference).
 432ord_symdiff(>, H1, T1, H2, Set2, [H2|Difference]) :-
 433    ord_symdiff(Set2, H1, T1, Difference).