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