View source with formatted comments or as raw
    1/*  Part of SWI-Prolog
    2
    3    Author:        Vitor Santos Costa
    4    E-mail:        vscosta@gmail.com
    5    WWW:           http://www.swi-prolog.org
    6    Copyright (c)  2007-2017, Vitor Santos Costa
    7    All rights reserved.
    8
    9    Redistribution and use in source and binary forms, with or without
   10    modification, are permitted provided that the following conditions
   11    are met:
   12
   13    1. Redistributions of source code must retain the above copyright
   14       notice, this list of conditions and the following disclaimer.
   15
   16    2. Redistributions in binary form must reproduce the above copyright
   17       notice, this list of conditions and the following disclaimer in
   18       the documentation and/or other materials provided with the
   19       distribution.
   20
   21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   22    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   24    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   25    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   26    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   27    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   28    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   29    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   31    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   32    POSSIBILITY OF SUCH DAMAGE.
   33*/
   34
   35:- module(rbtrees,
   36          [ rb_new/1,                   % -Tree
   37            rb_empty/1,                 % ?Tree
   38            rb_lookup/3,                % +Key, -Value, +T
   39            rb_update/4,                % +Tree, +Key, +NewVal, -NewTree
   40            rb_update/5,                % +Tree, +Key, ?OldVal, +NewVal, -NewTree
   41            rb_apply/4,                 % +Tree, +Key, :G, -NewTree
   42            rb_insert/4,                % +T0, +Key, ?Value, -NewTree
   43            rb_insert_new/4,            % +T0, +Key, ?Value, -NewTree
   44            rb_delete/3,                % +Tree, +Key, -NewTree
   45            rb_delete/4,                % +Tree, +Key, -Val, -NewTree
   46            rb_visit/2,                 % +Tree, -Pairs
   47            rb_keys/2,                  % +Tree, +Keys
   48            rb_map/2,                   % +Tree, :Goal
   49            rb_map/3,                   % +Tree, :Goal, -MappedTree
   50            rb_partial_map/4,           % +Tree, +Keys, :Goal, -MappedTree
   51            rb_fold/4,                  % :Goal, +Tree, +State0, -State
   52            rb_clone/3,                 % +TreeIn, -TreeOut, -Pairs
   53            rb_min/3,                   % +Tree, -Key, -Value
   54            rb_max/3,                   % +Tree, -Key, -Value
   55            rb_del_min/4,               % +Tree, -Key, -Val, -TreeDel
   56            rb_del_max/4,               % +Tree, -Key, -Val, -TreeDel
   57            rb_next/4,                  % +Tree, +Key, -Next, -Value
   58            rb_previous/4,              % +Tree, +Key, -Next, -Value
   59            list_to_rbtree/2,           % +Pairs, -Tree
   60            ord_list_to_rbtree/2,       % +Pairs, -Tree
   61            is_rbtree/1,                % @Tree
   62            rb_size/2,                  % +Tree, -Size
   63            rb_in/3                     % ?Key, ?Value, +Tree
   64          ]).   65
   66/** <module> Red black trees
   67
   68Red-Black trees are balanced search binary trees. They are named because
   69nodes can be classified as either red or   black. The code we include is
   70based on "Introduction  to  Algorithms",   second  edition,  by  Cormen,
   71Leiserson, Rivest and Stein. The library   includes  routines to insert,
   72lookup and delete elements in the tree.
   73
   74A Red black tree is represented as a term t(Nil, Tree), where Nil is the
   75Nil-node, a node shared for each nil-node in  the tree. Any node has the
   76form colour(Left, Key, Value, Right), where _colour_  is one of =red= or
   77=black=.
   78
   79@author Vitor Santos Costa, Jan Wielemaker, Samer Abdallah
   80@see "Introduction to Algorithms", Second Edition Cormen, Leiserson,
   81     Rivest, and Stein, MIT Press
   82*/
   83
   84:- meta_predicate
   85    rb_map(+,:,-),
   86    rb_partial_map(+,+,:,-),
   87    rb_apply(+,+,:,-),
   88    rb_fold(3,+,+,-).   89
   90/*
   91:- use_module(library(type_check)).
   92
   93:- type rbtree(K,V) ---> t(tree(K,V),tree(K,V)).
   94:- type tree(K,V)   ---> black(tree(K,V),K,V,tree(K,V))
   95                       ; red(tree(K,V),K,V,tree(K,V))
   96                       ; ''.
   97:- type cmp ---> (=) ; (<) ; (>).
   98
   99
  100:- pred rb_new(rbtree(_K,_V)).
  101:- pred rb_empty(rbtree(_K,_V)).
  102:- pred rb_lookup(K,V,rbtree(K,V)).
  103:- pred lookup(K,V, tree(K,V)).
  104:- pred lookup(cmp, K, V, tree(K,V)).
  105:- pred rb_min(rbtree(K,V),K,V).
  106:- pred min(tree(K,V),K,V).
  107:- pred rb_max(rbtree(K,V),K,V).
  108:- pred max(tree(K,V),K,V).
  109:- pred rb_next(rbtree(K,V),K,pair(K,V),V).
  110:- pred next(tree(K,V),K,pair(K,V),V,tree(K,V)).
  111*/
  112
  113%!  rb_new(-Tree) is det.
  114%
  115%   Create a new Red-Black tree Tree.
  116%
  117%   @deprecated     Use rb_empty/1.
  118
  119rb_new(t(Nil,Nil)) :-
  120    Nil = black('',_,_,'').
  121
  122%!  rb_empty(?Tree) is semidet.
  123%
  124%   Succeeds if Tree is an empty Red-Black tree.
  125
  126rb_empty(t(Nil,Nil)) :-
  127    Nil = black('',_,_,'').
  128
  129%!  rb_lookup(+Key, -Value, +Tree) is semidet.
  130%
  131%   True when Value is associated with Key   in the Red-Black tree Tree.
  132%   The given Key may include variables, in   which  case the RB tree is
  133%   searched for a key with equivalent,   as  in (==)/2, variables. Time
  134%   complexity is O(log N) in the number of elements in the tree.
  135
  136rb_lookup(Key, Val, t(_,Tree)) :-
  137    lookup(Key, Val, Tree).
  138
  139lookup(_, _, black('',_,_,'')) :- !, fail.
  140lookup(Key, Val, Tree) :-
  141    arg(2,Tree,KA),
  142    compare(Cmp,KA,Key),
  143    lookup(Cmp,Key,Val,Tree).
  144
  145lookup(>, K, V, Tree) :-
  146    arg(1,Tree,NTree),
  147    lookup(K, V, NTree).
  148lookup(<, K, V, Tree) :-
  149    arg(4,Tree,NTree),
  150    lookup(K, V, NTree).
  151lookup(=, _, V, Tree) :-
  152    arg(3,Tree,V).
  153
  154%!  rb_min(+Tree, -Key, -Value) is semidet.
  155%
  156%   Key is the minimum key in Tree, and is associated with Val.
  157
  158rb_min(t(_,Tree), Key, Val) :-
  159    min(Tree, Key, Val).
  160
  161min(red(black('',_,_,_),Key,Val,_), Key, Val) :- !.
  162min(black(black('',_,_,_),Key,Val,_), Key, Val) :- !.
  163min(red(Right,_,_,_), Key, Val) :-
  164    min(Right,Key,Val).
  165min(black(Right,_,_,_), Key, Val) :-
  166    min(Right,Key,Val).
  167
  168%!  rb_max(+Tree, -Key, -Value) is semidet.
  169%
  170%   Key is the maximal key in Tree, and is associated with Val.
  171
  172rb_max(t(_,Tree), Key, Val) :-
  173    max(Tree, Key, Val).
  174
  175max(red(_,Key,Val,black('',_,_,_)), Key, Val) :- !.
  176max(black(_,Key,Val,black('',_,_,_)), Key, Val) :- !.
  177max(red(_,_,_,Left), Key, Val) :-
  178    max(Left,Key,Val).
  179max(black(_,_,_,Left), Key, Val) :-
  180    max(Left,Key,Val).
  181
  182%!  rb_next(+Tree, +Key, -Next, -Value) is semidet.
  183%
  184%   Next is the next element after Key   in Tree, and is associated with
  185%   Val.
  186
  187rb_next(t(_,Tree), Key, Next, Val) :-
  188    next(Tree, Key, Next, Val, []).
  189
  190next(black('',_,_,''), _, _, _, _) :- !, fail.
  191next(Tree, Key, Next, Val, Candidate) :-
  192    arg(2,Tree,KA),
  193    arg(3,Tree,VA),
  194    compare(Cmp,KA,Key),
  195    next(Cmp, Key, KA, VA, Next, Val, Tree, Candidate).
  196
  197next(>, K, KA, VA, NK, V, Tree, _) :-
  198    arg(1,Tree,NTree),
  199    next(NTree,K,NK,V,KA-VA).
  200next(<, K, _, _, NK, V, Tree, Candidate) :-
  201    arg(4,Tree,NTree),
  202    next(NTree,K,NK,V,Candidate).
  203next(=, _, _, _, NK, Val, Tree, Candidate) :-
  204    arg(4,Tree,NTree),
  205    (   min(NTree, NK, Val)
  206    ->  true
  207    ;   Candidate = (NK-Val)
  208    ).
  209
  210%!  rb_previous(+Tree, +Key, -Previous, -Value) is semidet.
  211%
  212%   Previous  is  the  previous  element  after  Key  in  Tree,  and  is
  213%   associated with Val.
  214
  215rb_previous(t(_,Tree), Key, Previous, Val) :-
  216    previous(Tree, Key, Previous, Val, []).
  217
  218previous(black('',_,_,''), _, _, _, _) :- !, fail.
  219previous(Tree, Key, Previous, Val, Candidate) :-
  220    arg(2,Tree,KA),
  221    arg(3,Tree,VA),
  222    compare(Cmp,KA,Key),
  223    previous(Cmp, Key, KA, VA, Previous, Val, Tree, Candidate).
  224
  225previous(>, K, _, _, NK, V, Tree, Candidate) :-
  226    arg(1,Tree,NTree),
  227    previous(NTree,K,NK,V,Candidate).
  228previous(<, K, KA, VA, NK, V, Tree, _) :-
  229    arg(4,Tree,NTree),
  230    previous(NTree,K,NK,V,KA-VA).
  231previous(=, _, _, _, K, Val, Tree, Candidate) :-
  232    arg(1,Tree,NTree),
  233    (   max(NTree, K, Val)
  234    ->  true
  235    ;   Candidate = (K-Val)
  236    ).
  237
  238%!  rb_update(+Tree, +Key, +NewVal, -NewTree) is semidet.
  239%!  rb_update(+Tree, +Key, ?OldVal, +NewVal, -NewTree) is semidet.
  240%
  241%   Tree NewTree is tree Tree, but with   value  for Key associated with
  242%   NewVal. Fails if it cannot find Key in Tree.
  243
  244rb_update(t(Nil,OldTree), Key, OldVal, Val, t(Nil,NewTree)) :-
  245    update(OldTree, Key, OldVal, Val, NewTree).
  246
  247rb_update(t(Nil,OldTree), Key, Val, t(Nil,NewTree)) :-
  248    update(OldTree, Key, _, Val, NewTree).
  249
  250update(black(Left,Key0,Val0,Right), Key, OldVal, Val, NewTree) :-
  251    Left \= [],
  252    compare(Cmp,Key0,Key),
  253    (   Cmp == (=)
  254    ->  OldVal = Val0,
  255        NewTree = black(Left,Key0,Val,Right)
  256    ;   Cmp == (>)
  257    ->  NewTree = black(NewLeft,Key0,Val0,Right),
  258        update(Left, Key, OldVal, Val, NewLeft)
  259    ;   NewTree = black(Left,Key0,Val0,NewRight),
  260        update(Right, Key, OldVal, Val, NewRight)
  261    ).
  262update(red(Left,Key0,Val0,Right), Key, OldVal, Val, NewTree) :-
  263    compare(Cmp,Key0,Key),
  264    (   Cmp == (=)
  265    ->  OldVal = Val0,
  266        NewTree = red(Left,Key0,Val,Right)
  267    ;   Cmp == (>)
  268    ->  NewTree = red(NewLeft,Key0,Val0,Right),
  269        update(Left, Key, OldVal, Val, NewLeft)
  270    ;   NewTree = red(Left,Key0,Val0,NewRight),
  271        update(Right, Key, OldVal, Val, NewRight)
  272    ).
  273
  274%!  rb_apply(+Tree, +Key, :G, -NewTree) is semidet.
  275%
  276%   If the value associated  with  key  Key   is  Val0  in  Tree, and if
  277%   call(G,Val0,ValF) holds, then NewTree differs from Tree only in that
  278%   Key is associated with value  ValF  in   tree  NewTree.  Fails if it
  279%   cannot find Key in Tree, or if call(G,Val0,ValF) is not satisfiable.
  280
  281rb_apply(t(Nil,OldTree), Key, Goal, t(Nil,NewTree)) :-
  282    apply(OldTree, Key, Goal, NewTree).
  283
  284%apply(black('',_,_,''), _, _, _) :- !, fail.
  285apply(black(Left,Key0,Val0,Right), Key, Goal,
  286      black(NewLeft,Key0,Val,NewRight)) :-
  287    Left \= [],
  288    compare(Cmp,Key0,Key),
  289    (   Cmp == (=)
  290    ->  NewLeft = Left,
  291        NewRight = Right,
  292        call(Goal,Val0,Val)
  293    ;   Cmp == (>)
  294    ->  NewRight = Right,
  295        Val = Val0,
  296        apply(Left, Key, Goal, NewLeft)
  297    ;   NewLeft = Left,
  298        Val = Val0,
  299        apply(Right, Key, Goal, NewRight)
  300    ).
  301apply(red(Left,Key0,Val0,Right), Key, Goal,
  302      red(NewLeft,Key0,Val,NewRight)) :-
  303    compare(Cmp,Key0,Key),
  304    (   Cmp == (=)
  305    ->  NewLeft = Left,
  306        NewRight = Right,
  307        call(Goal,Val0,Val)
  308    ;   Cmp == (>)
  309    ->  NewRight = Right,
  310        Val = Val0,
  311        apply(Left, Key, Goal, NewLeft)
  312    ;   NewLeft = Left,
  313        Val = Val0,
  314        apply(Right, Key, Goal, NewRight)
  315    ).
  316
  317%!  rb_in(?Key, ?Value, +Tree) is nondet.
  318%
  319%   True when Key-Value is a key-value pair in red-black tree Tree. Same
  320%   as below, but does not materialize the pairs.
  321%
  322%        rb_visit(Tree, Pairs), member(Key-Value, Pairs)
  323
  324rb_in(Key, Val, t(_,T)) :-
  325    enum(Key, Val, T).
  326
  327enum(Key, Val, black(L,K,V,R)) :-
  328    L \= '',
  329    enum_cases(Key, Val, L, K, V, R).
  330enum(Key, Val, red(L,K,V,R)) :-
  331    enum_cases(Key, Val, L, K, V, R).
  332
  333enum_cases(Key, Val, L, _, _, _) :-
  334    enum(Key, Val, L).
  335enum_cases(Key, Val, _, Key, Val, _).
  336enum_cases(Key, Val, _, _, _, R) :-
  337    enum(Key, Val, R).
  338
  339
  340
  341                 /*******************************
  342                 *       TREE INSERTION         *
  343                 *******************************/
  344
  345% We don't use parent nodes, so we may have to fix the root.
  346
  347%!  rb_insert(+Tree, +Key, ?Value, -NewTree) is det.
  348%
  349%   Add an element with key Key and Value   to  the tree Tree creating a
  350%   new red-black tree NewTree. If Key is  a key in Tree, the associated
  351%   value is replaced by Value. See also rb_insert_new/4.
  352
  353rb_insert(t(Nil,Tree0),Key,Val,t(Nil,Tree)) :-
  354    insert(Tree0,Key,Val,Nil,Tree).
  355
  356
  357insert(Tree0,Key,Val,Nil,Tree) :-
  358    insert2(Tree0,Key,Val,Nil,TreeI,_),
  359    fix_root(TreeI,Tree).
  360
  361%
  362% Cormen et al present the algorithm as
  363% (1) standard tree insertion;
  364% (2) from the viewpoint of the newly inserted node:
  365%     partially fix the tree;
  366%     move upwards
  367% until reaching the root.
  368%
  369% We do it a little bit different:
  370%
  371% (1) standard tree insertion;
  372% (2) move upwards:
  373%      when reaching a black node;
  374%        if the tree below may be broken, fix it.
  375% We take advantage of Prolog unification
  376% to do several operations in a single go.
  377%
  378
  379
  380
  381%
  382% actual insertion
  383%
  384insert2(black('',_,_,''), K, V, Nil, T, Status) :-
  385    !,
  386    T = red(Nil,K,V,Nil),
  387    Status = not_done.
  388insert2(red(L,K0,V0,R), K, V, Nil, NT, Flag) :-
  389    (   K @< K0
  390    ->  NT = red(NL,K0,V0,R),
  391        insert2(L, K, V, Nil, NL, Flag)
  392    ;   K == K0
  393    ->  NT = red(L,K0,V,R),
  394        Flag = done
  395    ;   NT = red(L,K0,V0,NR),
  396        insert2(R, K, V, Nil, NR, Flag)
  397    ).
  398insert2(black(L,K0,V0,R), K, V, Nil, NT, Flag) :-
  399    (   K @< K0
  400    ->  insert2(L, K, V, Nil, IL, Flag0),
  401        fix_left(Flag0, black(IL,K0,V0,R), NT, Flag)
  402    ;   K == K0
  403    ->  NT = black(L,K0,V,R),
  404        Flag = done
  405    ;   insert2(R, K, V, Nil, IR, Flag0),
  406        fix_right(Flag0, black(L,K0,V0,IR), NT, Flag)
  407    ).
  408
  409% We don't use parent nodes, so we may have to fix the root.
  410
  411%!  rb_insert_new(+Tree, +Key, ?Value, -NewTree) is semidet.
  412%
  413%   Add a new element with key Key and Value to the tree Tree creating a
  414%   new red-black tree NewTree. Fails if Key is a key in Tree.
  415
  416rb_insert_new(t(Nil,Tree0),Key,Val,t(Nil,Tree)) :-
  417    insert_new(Tree0,Key,Val,Nil,Tree).
  418
  419insert_new(Tree0,Key,Val,Nil,Tree) :-
  420    insert_new_2(Tree0,Key,Val,Nil,TreeI,_),
  421    fix_root(TreeI,Tree).
  422
  423%
  424% actual insertion, copied from insert2
  425%
  426insert_new_2(black('',_,_,''), K, V, Nil, T, Status) :-
  427    !,
  428    T = red(Nil,K,V,Nil),
  429    Status = not_done.
  430insert_new_2(red(L,K0,V0,R), K, V, Nil, NT, Flag) :-
  431    (   K @< K0
  432    ->  NT = red(NL,K0,V0,R),
  433        insert_new_2(L, K, V, Nil, NL, Flag)
  434    ;   K == K0
  435    ->  fail
  436    ;   NT = red(L,K0,V0,NR),
  437        insert_new_2(R, K, V, Nil, NR, Flag)
  438    ).
  439insert_new_2(black(L,K0,V0,R), K, V, Nil, NT, Flag) :-
  440    (   K @< K0
  441    ->  insert_new_2(L, K, V, Nil, IL, Flag0),
  442        fix_left(Flag0, black(IL,K0,V0,R), NT, Flag)
  443    ;   K == K0
  444    ->  fail
  445    ;   insert_new_2(R, K, V, Nil, IR, Flag0),
  446        fix_right(Flag0, black(L,K0,V0,IR), NT, Flag)
  447    ).
  448
  449%
  450% make sure the root is always black.
  451%
  452fix_root(black(L,K,V,R),black(L,K,V,R)).
  453fix_root(red(L,K,V,R),black(L,K,V,R)).
  454
  455%
  456% How to fix if we have inserted on the left
  457%
  458fix_left(done,T,T,done) :- !.
  459fix_left(not_done,Tmp,Final,Done) :-
  460    fix_left(Tmp,Final,Done).
  461
  462%
  463% case 1 of RB: just need to change colors.
  464%
  465fix_left(black(red(Al,AK,AV,red(Be,BK,BV,Ga)),KC,VC,red(De,KD,VD,Ep)),
  466        red(black(Al,AK,AV,red(Be,BK,BV,Ga)),KC,VC,black(De,KD,VD,Ep)),
  467        not_done) :- !.
  468fix_left(black(red(red(Al,KA,VA,Be),KB,VB,Ga),KC,VC,red(De,KD,VD,Ep)),
  469        red(black(red(Al,KA,VA,Be),KB,VB,Ga),KC,VC,black(De,KD,VD,Ep)),
  470        not_done) :- !.
  471%
  472% case 2 of RB: got a knee so need to do rotations
  473%
  474fix_left(black(red(Al,KA,VA,red(Be,KB,VB,Ga)),KC,VC,De),
  475        black(red(Al,KA,VA,Be),KB,VB,red(Ga,KC,VC,De)),
  476        done) :- !.
  477%
  478% case 3 of RB: got a line
  479%
  480fix_left(black(red(red(Al,KA,VA,Be),KB,VB,Ga),KC,VC,De),
  481        black(red(Al,KA,VA,Be),KB,VB,red(Ga,KC,VC,De)),
  482        done) :- !.
  483%
  484% case 4 of RB: nothing to do
  485%
  486fix_left(T,T,done).
  487
  488%
  489% How to fix if we have inserted on the right
  490%
  491fix_right(done,T,T,done) :- !.
  492fix_right(not_done,Tmp,Final,Done) :-
  493    fix_right(Tmp,Final,Done).
  494
  495%
  496% case 1 of RB: just need to change colors.
  497%
  498fix_right(black(red(Ep,KD,VD,De),KC,VC,red(red(Ga,KB,VB,Be),KA,VA,Al)),
  499          red(black(Ep,KD,VD,De),KC,VC,black(red(Ga,KB,VB,Be),KA,VA,Al)),
  500          not_done) :- !.
  501fix_right(black(red(Ep,KD,VD,De),KC,VC,red(Ga,Ka,Va,red(Be,KB,VB,Al))),
  502          red(black(Ep,KD,VD,De),KC,VC,black(Ga,Ka,Va,red(Be,KB,VB,Al))),
  503          not_done) :- !.
  504%
  505% case 2 of RB: got a knee so need to do rotations
  506%
  507fix_right(black(De,KC,VC,red(red(Ga,KB,VB,Be),KA,VA,Al)),
  508          black(red(De,KC,VC,Ga),KB,VB,red(Be,KA,VA,Al)),
  509          done) :- !.
  510%
  511% case 3 of RB: got a line
  512%
  513fix_right(black(De,KC,VC,red(Ga,KB,VB,red(Be,KA,VA,Al))),
  514          black(red(De,KC,VC,Ga),KB,VB,red(Be,KA,VA,Al)),
  515          done) :- !.
  516%
  517% case 4 of RB: nothing to do.
  518%
  519fix_right(T,T,done).
  520
  521
  522%!  rb_delete(+Tree, +Key, -NewTree).
  523%!  rb_delete(+Tree, +Key, -Val, -NewTree).
  524%
  525%   Delete element with key Key from the  tree Tree, returning the value
  526%   Val associated with the key and a new tree NewTree.
  527
  528rb_delete(t(Nil,T), K, t(Nil,NT)) :-
  529    delete(T, K, _, NT, _).
  530
  531rb_delete(t(Nil,T), K, V, t(Nil,NT)) :-
  532    delete(T, K, V0, NT, _),
  533    V = V0.
  534
  535%
  536% I am afraid our representation is not as nice for delete
  537%
  538delete(red(L,K0,V0,R), K, V, NT, Flag) :-
  539    K @< K0,
  540    !,
  541    delete(L, K, V, NL, Flag0),
  542    fixup_left(Flag0,red(NL,K0,V0,R),NT, Flag).
  543delete(red(L,K0,V0,R), K, V, NT, Flag) :-
  544    K @> K0,
  545    !,
  546    delete(R, K, V, NR, Flag0),
  547    fixup_right(Flag0,red(L,K0,V0,NR),NT, Flag).
  548delete(red(L,_,V,R), _, V, OUT, Flag) :-
  549    % K == K0,
  550    delete_red_node(L,R,OUT,Flag).
  551delete(black(L,K0,V0,R), K, V, NT, Flag) :-
  552    K @< K0,
  553    !,
  554    delete(L, K, V, NL, Flag0),
  555    fixup_left(Flag0,black(NL,K0,V0,R),NT, Flag).
  556delete(black(L,K0,V0,R), K, V, NT, Flag) :-
  557    K @> K0,
  558    !,
  559    delete(R, K, V, NR, Flag0),
  560    fixup_right(Flag0,black(L,K0,V0,NR),NT, Flag).
  561delete(black(L,_,V,R), _, V, OUT, Flag) :-
  562    % K == K0,
  563    delete_black_node(L,R,OUT,Flag).
  564
  565%!  rb_del_min(+Tree, -Key, -Val, -NewTree)
  566%
  567%   Delete the least element from the tree  Tree, returning the key Key,
  568%   the value Val associated with the key and a new tree NewTree.
  569
  570rb_del_min(t(Nil,T), K, Val, t(Nil,NT)) :-
  571    del_min(T, K, Val, Nil, NT, _).
  572
  573del_min(red(black('',_,_,_),K,V,R), K, V, Nil, OUT, Flag) :-
  574    !,
  575    delete_red_node(Nil,R,OUT,Flag).
  576del_min(red(L,K0,V0,R), K, V, Nil, NT, Flag) :-
  577    del_min(L, K, V, Nil, NL, Flag0),
  578    fixup_left(Flag0,red(NL,K0,V0,R), NT, Flag).
  579del_min(black(black('',_,_,_),K,V,R), K, V, Nil, OUT, Flag) :-
  580    !,
  581    delete_black_node(Nil,R,OUT,Flag).
  582del_min(black(L,K0,V0,R), K, V, Nil, NT, Flag) :-
  583    del_min(L, K, V, Nil, NL, Flag0),
  584    fixup_left(Flag0,black(NL,K0,V0,R),NT, Flag).
  585
  586
  587%!  rb_del_max(+Tree, -Key, -Val, -NewTree)
  588%
  589%   Delete the largest element from  the   tree  Tree, returning the key
  590%   Key, the value Val associated with the key and a new tree NewTree.
  591
  592rb_del_max(t(Nil,T), K, Val, t(Nil,NT)) :-
  593    del_max(T, K, Val, Nil, NT, _).
  594
  595del_max(red(L,K,V,black('',_,_,_)), K, V, Nil, OUT, Flag) :-
  596    !,
  597    delete_red_node(L,Nil,OUT,Flag).
  598del_max(red(L,K0,V0,R), K, V, Nil, NT, Flag) :-
  599    del_max(R, K, V, Nil, NR, Flag0),
  600    fixup_right(Flag0,red(L,K0,V0,NR),NT, Flag).
  601del_max(black(L,K,V,black('',_,_,_)), K, V, Nil, OUT, Flag) :-
  602    !,
  603    delete_black_node(L,Nil,OUT,Flag).
  604del_max(black(L,K0,V0,R), K, V, Nil, NT, Flag) :-
  605    del_max(R, K, V, Nil, NR, Flag0),
  606    fixup_right(Flag0,black(L,K0,V0,NR), NT, Flag).
  607
  608delete_red_node(L1,L2,L1,done) :- L1 == L2, !.
  609delete_red_node(black('',_,_,''),R,R,done) :-  !.
  610delete_red_node(L,black('',_,_,''),L,done) :-  !.
  611delete_red_node(L,R,OUT,Done) :-
  612    delete_next(R,NK,NV,NR,Done0),
  613    fixup_right(Done0,red(L,NK,NV,NR),OUT,Done).
  614
  615delete_black_node(L1,L2,L1,not_done) :-         L1 == L2, !.
  616delete_black_node(black('',_,_,''),red(L,K,V,R),black(L,K,V,R),done) :- !.
  617delete_black_node(black('',_,_,''),R,R,not_done) :- !.
  618delete_black_node(red(L,K,V,R),black('',_,_,''),black(L,K,V,R),done) :- !.
  619delete_black_node(L,black('',_,_,''),L,not_done) :- !.
  620delete_black_node(L,R,OUT,Done) :-
  621    delete_next(R,NK,NV,NR,Done0),
  622    fixup_right(Done0,black(L,NK,NV,NR),OUT,Done).
  623
  624delete_next(red(black('',_,_,''),K,V,R),K,V,R,done) :-  !.
  625delete_next(black(black('',_,_,''),K,V,red(L1,K1,V1,R1)),
  626        K,V,black(L1,K1,V1,R1),done) :- !.
  627delete_next(black(black('',_,_,''),K,V,R),K,V,R,not_done) :- !.
  628delete_next(red(L,K,V,R),K0,V0,OUT,Done) :-
  629    delete_next(L,K0,V0,NL,Done0),
  630    fixup_left(Done0,red(NL,K,V,R),OUT,Done).
  631delete_next(black(L,K,V,R),K0,V0,OUT,Done) :-
  632    delete_next(L,K0,V0,NL,Done0),
  633    fixup_left(Done0,black(NL,K,V,R),OUT,Done).
  634
  635fixup_left(done,T,T,done).
  636fixup_left(not_done,T,NT,Done) :-
  637    fixup2(T,NT,Done).
  638
  639%
  640% case 1: x moves down, so we have to try to fix it again.
  641% case 1 -> 2,3,4 -> done
  642%
  643fixup2(black(black(Al,KA,VA,Be),KB,VB,
  644             red(black(Ga,KC,VC,De),KD,VD,
  645                 black(Ep,KE,VE,Fi))),
  646        black(T1,KD,VD,black(Ep,KE,VE,Fi)),done) :-
  647    !,
  648    fixup2(red(black(Al,KA,VA,Be),KB,VB,black(Ga,KC,VC,De)),
  649            T1,
  650            _).
  651%
  652% case 2: x moves up, change one to red
  653%
  654fixup2(red(black(Al,KA,VA,Be),KB,VB,
  655           black(black(Ga,KC,VC,De),KD,VD,
  656                 black(Ep,KE,VE,Fi))),
  657        black(black(Al,KA,VA,Be),KB,VB,
  658              red(black(Ga,KC,VC,De),KD,VD,
  659                  black(Ep,KE,VE,Fi))),done) :- !.
  660fixup2(black(black(Al,KA,VA,Be),KB,VB,
  661             black(black(Ga,KC,VC,De),KD,VD,
  662                   black(Ep,KE,VE,Fi))),
  663        black(black(Al,KA,VA,Be),KB,VB,
  664              red(black(Ga,KC,VC,De),KD,VD,
  665                  black(Ep,KE,VE,Fi))),not_done) :- !.
  666%
  667% case 3: x stays put, shift left and do a 4
  668%
  669fixup2(red(black(Al,KA,VA,Be),KB,VB,
  670           black(red(Ga,KC,VC,De),KD,VD,
  671                 black(Ep,KE,VE,Fi))),
  672        red(black(black(Al,KA,VA,Be),KB,VB,Ga),KC,VC,
  673            black(De,KD,VD,black(Ep,KE,VE,Fi))),
  674        done) :- !.
  675fixup2(black(black(Al,KA,VA,Be),KB,VB,
  676             black(red(Ga,KC,VC,De),KD,VD,
  677                   black(Ep,KE,VE,Fi))),
  678        black(black(black(Al,KA,VA,Be),KB,VB,Ga),KC,VC,
  679              black(De,KD,VD,black(Ep,KE,VE,Fi))),
  680        done) :- !.
  681%
  682% case 4: rotate left, get rid of red
  683%
  684fixup2(red(black(Al,KA,VA,Be),KB,VB,
  685           black(C,KD,VD,red(Ep,KE,VE,Fi))),
  686        red(black(black(Al,KA,VA,Be),KB,VB,C),KD,VD,
  687            black(Ep,KE,VE,Fi)),
  688        done).
  689fixup2(black(black(Al,KA,VA,Be),KB,VB,
  690             black(C,KD,VD,red(Ep,KE,VE,Fi))),
  691       black(black(black(Al,KA,VA,Be),KB,VB,C),KD,VD,
  692             black(Ep,KE,VE,Fi)),
  693       done).
  694
  695fixup_right(done,T,T,done).
  696fixup_right(not_done,T,NT,Done) :-
  697    fixup3(T,NT,Done).
  698
  699% case 1: x moves down, so we have to try to fix it again.
  700% case 1 -> 2,3,4 -> done
  701%
  702fixup3(black(red(black(Fi,KE,VE,Ep),KD,VD,
  703                 black(De,KC,VC,Ga)),KB,VB,
  704             black(Be,KA,VA,Al)),
  705        black(black(Fi,KE,VE,Ep),KD,VD,T1),done) :-
  706    !,
  707    fixup3(red(black(De,KC,VC,Ga),KB,VB,
  708               black(Be,KA,VA,Al)),T1,_).
  709
  710%
  711% case 2: x moves up, change one to red
  712%
  713fixup3(red(black(black(Fi,KE,VE,Ep),KD,VD,
  714                 black(De,KC,VC,Ga)),KB,VB,
  715           black(Be,KA,VA,Al)),
  716       black(red(black(Fi,KE,VE,Ep),KD,VD,
  717                 black(De,KC,VC,Ga)),KB,VB,
  718             black(Be,KA,VA,Al)),
  719       done) :- !.
  720fixup3(black(black(black(Fi,KE,VE,Ep),KD,VD,
  721                   black(De,KC,VC,Ga)),KB,VB,
  722             black(Be,KA,VA,Al)),
  723       black(red(black(Fi,KE,VE,Ep),KD,VD,
  724                 black(De,KC,VC,Ga)),KB,VB,
  725             black(Be,KA,VA,Al)),
  726       not_done):- !.
  727%
  728% case 3: x stays put, shift left and do a 4
  729%
  730fixup3(red(black(black(Fi,KE,VE,Ep),KD,VD,
  731                 red(De,KC,VC,Ga)),KB,VB,
  732           black(Be,KA,VA,Al)),
  733       red(black(black(Fi,KE,VE,Ep),KD,VD,De),KC,VC,
  734           black(Ga,KB,VB,black(Be,KA,VA,Al))),
  735       done) :- !.
  736fixup3(black(black(black(Fi,KE,VE,Ep),KD,VD,
  737                   red(De,KC,VC,Ga)),KB,VB,
  738             black(Be,KA,VA,Al)),
  739       black(black(black(Fi,KE,VE,Ep),KD,VD,De),KC,VC,
  740             black(Ga,KB,VB,black(Be,KA,VA,Al))),
  741       done) :- !.
  742%
  743% case 4: rotate right, get rid of red
  744%
  745fixup3(red(black(red(Fi,KE,VE,Ep),KD,VD,C),KB,VB,black(Be,KA,VA,Al)),
  746       red(black(Fi,KE,VE,Ep),KD,VD,black(C,KB,VB,black(Be,KA,VA,Al))),
  747       done).
  748fixup3(black(black(red(Fi,KE,VE,Ep),KD,VD,C),KB,VB,black(Be,KA,VA,Al)),
  749       black(black(Fi,KE,VE,Ep),KD,VD,black(C,KB,VB,black(Be,KA,VA,Al))),
  750       done).
  751
  752%!  rb_visit(+Tree, -Pairs)
  753%
  754%   Pairs is an infix visit of tree Tree, where each element of Pairs is
  755%   of the form Key-Value.
  756
  757rb_visit(t(_,T),Lf) :-
  758    visit(T,[],Lf).
  759
  760visit(black('',_,_,_),L,L) :- !.
  761visit(red(L,K,V,R),L0,Lf) :-
  762    visit(L,[K-V|L1],Lf),
  763    visit(R,L0,L1).
  764visit(black(L,K,V,R),L0,Lf) :-
  765    visit(L,[K-V|L1],Lf),
  766    visit(R,L0,L1).
  767
  768:- meta_predicate rb_map(?,:,?). % this is not strictly required
  769:- meta_predicate map(?,:,?,?).  % this is required.
  770
  771%!  rb_map(+T, :Goal) is semidet.
  772%
  773%   True if call(Goal, Value) is true for all nodes in T.
  774
  775rb_map(t(Nil,Tree),Goal,t(Nil,NewTree)) :-
  776    map(Tree,Goal,NewTree,Nil).
  777
  778
  779map(black('',_,_,''),_,Nil,Nil) :- !.
  780map(red(L,K,V,R),Goal,red(NL,K,NV,NR),Nil) :-
  781    call(Goal,V,NV),
  782    !,
  783    map(L,Goal,NL,Nil),
  784    map(R,Goal,NR,Nil).
  785map(black(L,K,V,R),Goal,black(NL,K,NV,NR),Nil) :-
  786    call(Goal,V,NV),
  787    !,
  788    map(L,Goal,NL,Nil),
  789    map(R,Goal,NR,Nil).
  790
  791:- meta_predicate rb_map(?,:). % this is not strictly required
  792:- meta_predicate map(?,:).  % this is required.
  793
  794%!  rb_map(+Tree, :G, -NewTree) is semidet.
  795%
  796%   For all nodes Key in the tree Tree, if the value associated with key
  797%   Key is Val0 in tree Tree, and   if call(G,Val0,ValF) holds, then the
  798%   value  associated  with  Key  in   NewTree    is   ValF.   Fails  if
  799%   call(G,Val0,ValF) is not satisfiable for all Val0.
  800
  801rb_map(t(_,Tree),Goal) :-
  802    map(Tree,Goal).
  803
  804
  805map(black('',_,_,''),_) :- !.
  806map(red(L,_,V,R),Goal) :-
  807    call(Goal,V),
  808    !,
  809    map(L,Goal),
  810    map(R,Goal).
  811map(black(L,_,V,R),Goal) :-
  812    call(Goal,V),
  813    !,
  814    map(L,Goal),
  815    map(R,Goal).
  816
  817%!  rb_fold(:Goal, +Tree, +State0, -State) is det.
  818%
  819%   Fold the given predicate  over  all   the  key-value  pairs in Tree,
  820%   starting with initial state State0  and   returning  the final state
  821%   State. Pred is called as
  822%
  823%       call(Pred, Key-Value, State1, State2)
  824
  825rb_fold(Pred, t(_,T), S1, S2) :-
  826    fold(T, Pred, S1, S2).
  827
  828fold(black(L,K,V,R), Pred) -->
  829    (   {L == ''}
  830    ->  []
  831    ;   fold_parts(Pred, L, K-V, R)
  832    ).
  833fold(red(L,K,V,R), Pred) -->
  834    fold_parts(Pred, L, K-V, R).
  835
  836fold_parts(Pred, L, KV, R) -->
  837    fold(L, Pred),
  838    call(Pred, KV),
  839    fold(R, Pred).
  840
  841%!  rb_clone(+TreeIn, -TreeOut, -Pairs) is det.
  842%
  843%   `Clone' the red-back tree TreeIn into a   new  tree TreeOut with the
  844%   same keys as the original but with all values set to unbound values.
  845%   Pairs is a list containing all new nodes as pairs K-V.
  846
  847rb_clone(t(Nil,T),t(Nil,NT),Ns) :-
  848    clone(T,Nil,NT,Ns,[]).
  849
  850clone(black('',_,_,''),Nil,Nil,Ns,Ns) :- !.
  851clone(red(L,K,_,R),Nil,red(NL,K,NV,NR),NsF,Ns0) :-
  852    clone(L,Nil,NL,NsF,[K-NV|Ns1]),
  853    clone(R,Nil,NR,Ns1,Ns0).
  854clone(black(L,K,_,R),Nil,black(NL,K,NV,NR),NsF,Ns0) :-
  855    clone(L,Nil,NL,NsF,[K-NV|Ns1]),
  856    clone(R,Nil,NR,Ns1,Ns0).
  857
  858%!  rb_partial_map(+Tree, +Keys, :G, -NewTree)
  859%
  860%   For all nodes Key in Keys, if the   value associated with key Key is
  861%   Val0 in tree Tree, and if   call(G,Val0,ValF)  holds, then the value
  862%   associated  with  Key  in  NewTree   is    ValF.   Fails  if  or  if
  863%   call(G,Val0,ValF) is not satisfiable for all  Val0. Assumes keys are
  864%   not repeated.
  865
  866rb_partial_map(t(Nil,T0), Map, Goal, t(Nil,TF)) :-
  867    partial_map(T0, Map, [], Nil, Goal, TF).
  868
  869partial_map(T,[],[],_,_,T) :- !.
  870partial_map(black('',_,_,_),Map,Map,Nil,_,Nil) :- !.
  871partial_map(red(L,K,V,R),Map,MapF,Nil,Goal,red(NL,K,NV,NR)) :-
  872    partial_map(L,Map,MapI,Nil,Goal,NL),
  873    (   MapI == []
  874    ->  NR = R, NV = V, MapF = []
  875    ;   MapI = [K1|MapR],
  876        (   K == K1
  877        ->  (   call(Goal,V,NV)
  878            ->  true
  879            ;   NV = V
  880            ),
  881            MapN = MapR
  882        ;   NV = V,
  883            MapN = MapI
  884        ),
  885        partial_map(R,MapN,MapF,Nil,Goal,NR)
  886    ).
  887partial_map(black(L,K,V,R),Map,MapF,Nil,Goal,black(NL,K,NV,NR)) :-
  888    partial_map(L,Map,MapI,Nil,Goal,NL),
  889    (   MapI == []
  890    ->  NR = R, NV = V, MapF = []
  891    ;   MapI = [K1|MapR],
  892        (   K == K1
  893        ->  (   call(Goal,V,NV)
  894            ->  true
  895            ;   NV = V
  896            ),
  897            MapN = MapR
  898        ;   NV = V,
  899            MapN = MapI
  900        ),
  901        partial_map(R,MapN,MapF,Nil,Goal,NR)
  902    ).
  903
  904
  905%!  rb_keys(+Tree, -Keys)
  906%
  907%   Keys is unified with an ordered list   of  all keys in the Red-Black
  908%   tree Tree.
  909
  910rb_keys(t(_,T),Lf) :-
  911    keys(T,[],Lf).
  912
  913keys(black('',_,_,''),L,L) :- !.
  914keys(red(L,K,_,R),L0,Lf) :-
  915    keys(L,[K|L1],Lf),
  916    keys(R,L0,L1).
  917keys(black(L,K,_,R),L0,Lf) :-
  918    keys(L,[K|L1],Lf),
  919    keys(R,L0,L1).
  920
  921
  922%!  list_to_rbtree(+List, -Tree) is det.
  923%
  924%   Tree is the red-black tree  corresponding   to  the mapping in List,
  925%   which should be a list of Key-Value   pairs. List should not contain
  926%   more than one entry for each distinct key.
  927
  928list_to_rbtree(List, T) :-
  929    sort(List,Sorted),
  930    ord_list_to_rbtree(Sorted, T).
  931
  932%!  ord_list_to_rbtree(+List, -Tree) is det.
  933%
  934%   Tree is the red-black tree  corresponding   to  the  mapping in list
  935%   List, which should be a list  of   Key-Value  pairs. List should not
  936%   contain more than one entry for each   distinct key. List is assumed
  937%   to be sorted according to the standard order of terms.
  938
  939ord_list_to_rbtree([], t(Nil,Nil)) :-
  940    !,
  941    Nil = black('', _, _, '').
  942ord_list_to_rbtree([K-V], t(Nil,black(Nil,K,V,Nil))) :-
  943    !,
  944    Nil = black('', _, _, '').
  945ord_list_to_rbtree(List, t(Nil,Tree)) :-
  946    Nil = black('', _, _, ''),
  947    Ar =.. [seq|List],
  948    functor(Ar,_,L),
  949    Height is truncate(log(L)/log(2)),
  950    construct_rbtree(1, L, Ar, Height, Nil, Tree).
  951
  952construct_rbtree(L, M, _, _, Nil, Nil) :- M < L, !.
  953construct_rbtree(L, L, Ar, Depth, Nil, Node) :-
  954    !,
  955    arg(L, Ar, K-Val),
  956    build_node(Depth, Nil, K, Val, Nil, Node).
  957construct_rbtree(I0, Max, Ar, Depth, Nil, Node) :-
  958    I is (I0+Max)//2,
  959    arg(I, Ar, K-Val),
  960    build_node(Depth, Left, K, Val, Right, Node),
  961    I1 is I-1,
  962    NewDepth is Depth-1,
  963    construct_rbtree(I0, I1, Ar, NewDepth, Nil, Left),
  964    I2 is I+1,
  965    construct_rbtree(I2, Max, Ar, NewDepth, Nil, Right).
  966
  967build_node( 0, Left, K, Val, Right, red(Left, K, Val, Right)) :- !.
  968build_node( _, Left, K, Val, Right, black(Left, K, Val, Right)).
  969
  970
  971%!  rb_size(+Tree, -Size) is det.
  972%
  973%   Size is the number of elements in Tree.
  974
  975rb_size(t(_,T),Size) :-
  976    size(T,0,Size).
  977
  978size(black('',_,_,_),Sz,Sz) :- !.
  979size(red(L,_,_,R),Sz0,Szf) :-
  980    Sz1 is Sz0+1,
  981    size(L,Sz1,Sz2),
  982    size(R,Sz2,Szf).
  983size(black(L,_,_,R),Sz0,Szf) :-
  984    Sz1 is Sz0+1,
  985    size(L,Sz1,Sz2),
  986    size(R,Sz2,Szf).
  987
  988%!  is_rbtree(@Term) is semidet.
  989%
  990%   True if Term is a valide Red-Black tree.
  991%
  992%   @tbd    Catch variables.
  993
  994is_rbtree(X) :-
  995    var(X), !, fail.
  996is_rbtree(t(Nil,Nil)) :- !.
  997is_rbtree(t(_,T)) :-
  998    catch(rbtree1(T), msg(_,_), fail).
  999
 1000%
 1001% This code checks if a tree is ordered and a rbtree
 1002%
 1003
 1004rbtree1(black(L,K,_,R)) :-
 1005    find_path_blacks(L, 0, Bls),
 1006    check_rbtree(L,-inf,K,Bls),
 1007    check_rbtree(R,K,+inf,Bls).
 1008rbtree1(red(_,_,_,_)) :-
 1009    throw(msg("root should be black",[])).
 1010
 1011
 1012find_path_blacks(black('',_,_,''), Bls, Bls) :- !.
 1013find_path_blacks(black(L,_,_,_), Bls0, Bls) :-
 1014    Bls1 is Bls0+1,
 1015    find_path_blacks(L, Bls1, Bls).
 1016find_path_blacks(red(L,_,_,_), Bls0, Bls) :-
 1017    find_path_blacks(L, Bls0, Bls).
 1018
 1019check_rbtree(black('',_,_,''),Min,Max,Bls0) :-
 1020    !,
 1021    check_height(Bls0,Min,Max).
 1022check_rbtree(red(L,K,_,R),Min,Max,Bls) :-
 1023    check_val(K,Min,Max),
 1024    check_red_child(L),
 1025    check_red_child(R),
 1026    check_rbtree(L,Min,K,Bls),
 1027    check_rbtree(R,K,Max,Bls).
 1028check_rbtree(black(L,K,_,R),Min,Max,Bls0) :-
 1029    check_val(K,Min,Max),
 1030    Bls is Bls0-1,
 1031    check_rbtree(L,Min,K,Bls),
 1032    check_rbtree(R,K,Max,Bls).
 1033
 1034check_height(0,_,_) :- !.
 1035check_height(Bls0,Min,Max) :-
 1036    throw(msg("Unbalance ~d between ~w and ~w~n",[Bls0,Min,Max])).
 1037
 1038check_val(K, Min, Max) :- ( K @> Min ; Min == -inf), (K @< Max ; Max == +inf), !.
 1039check_val(K, Min, Max) :-
 1040    throw(msg("not ordered: ~w not between ~w and ~w~n",[K,Min,Max])).
 1041
 1042check_red_child(black(_,_,_,_)).
 1043check_red_child(red(_,K,_,_)) :-
 1044    throw(msg("must be red: ~w~n",[K]))