% ================================================================= :- pred constr(bool). :- mode constr(in). :- ignore constr/1. :- type bintree_int ---> leaf ; node(int,bintree_int,bintree_int). % This is a binary tree supporting a heap. % leaf is the EMPTY bintree_int. Nodes may have DUPLICATE integer values. % ================================================================ % Program: descending sorting. :- pred heapsort(list(int),list(int)). :- mode heapsort(in,out). heapsort(L,SL) :- list_to_heap(L,H), heap_to_list(H,SL). % =============================================================== % making a heap out of a list. % Program predicate: not be a catamorphism. :- pred list_to_heap(list(int),bintree_int). :- mode list_to_heap(in,out). list_to_heap([],leaf). list_to_heap([X|Xs], Heap) :- list_to_heap(Xs, HeapXs), insert_heap(X, HeapXs, Heap). % ------- :- pred insert_heap(int,bintree_int,bintree_int). :- mode insert_heap(in,in,out). insert_heap(X, leaf, node(X,leaf,leaf)). insert_heap(X, node(Top,L,R), node(Top,R,L1)) :- % Torsion! node(Top,R,L1), not node(Top,L1,R), and constr(X=Top), insert_heap(Top,L,L1). % X on top. Insert Top in the left son-node. % ---------------------------------- :- pred mkbtree(int,bintree_int,bintree_int,bintree_int). :- mode mkbtree(in,in,in,out). mkbtree(Top,Left,Right, node(Top,Left,Right)). % ---------------------------------- % Making a weakly-descending list out of a heap. % Program predicate: need not be a catamorphism. :- pred heap_to_list(bintree_int,list(int)). :- mode heap_to_list(in,out). heap_to_list(leaf,[]). heap_to_list(node(Top,leaf,leaf), [Top]). heap_to_list(node(Top,node(LTop,LL,LR),leaf), [Top|Tail]) :- mkbtree(LTop,LL,LR,NewHeap), heap_to_list(NewHeap,Tail). heap_to_list(node(Top,leaf,node(RTop,RL,RR)), [Top|Tail]) :- mkbtree(RTop,RL,RR,NewHeap), heap_to_list(NewHeap,Tail). heap_to_list(node(Top,node(LT,LL,LR),node(RT,RL,RR)), [Top|Tail]) :- mkbtree(LT,LL,LR,NewLHeap), mkbtree(RT,RL,RR,NewRHeap), heap_merge(NewLHeap,NewRHeap,MergedHeap), heap_to_list(MergedHeap,Tail). :- pred heap_merge(bintree_int,bintree_int,bintree_int). :- mode heap_merge(in,in,out). % heap_merge is a total function heap_merge(leaf,leaf, leaf). heap_merge(node(LTop,LL,LR),leaf, node(LTop,LL,LR)). heap_merge(leaf,node(RTop,RL,RR), node(RTop,RL,RR)). heap_merge(node(LTop,LL,LR),node(RTop,RL,RR), node(RTop,node(LTop,LL,LR),MergedHeap)) :- LTop =< RTop, heap_merge(RL,RR,MergedHeap). heap_merge(node(LTop,LL,LR),node(RTop,RL,RR), node(LTop,MergedHeap,node(RTop,RL,RR))) :- LTop > RTop, heap_merge(LL,LR,MergedHeap). % =============================================================== % Catamorphisms. :- pred listmember(int,list(int),bool). :- mode listmember(in,in,out). :- cata listmember/3-2. listmember(X,[],Res) :- constr(~Res). listmember(X,[Y|Ys],B) :- constr( B=ite(X=Y,true,B1) ) , listmember(X,Ys,B1). %----- treemember --- is there X in the given binary tree? :- pred treemember(int,bintree_int,bool). :- mode treemember(in,in,out). :- cata treemember/3-2. treemember(X,leaf,Res) :- constr(~Res). treemember(X,node(A,L,R),Res) :- constr( Res=ite(X=A,true,(ResL v ResR)) ), treemember(X,L,ResL), treemember(X,R,ResR). % =============================================================== %ff1. Contract on heapsort :- pred ff1. ff1 :- constr(~(LB=SB)), listmember(X,L,LB), listmember(X,S,SB), heapsort(L,S). %%% --------------- %% Contract on list_to_heap: (postcondition: true) %:- spec list_to_heap(L,H) ==> % listmember(X,L,NL), treemember(X,H,NH). % %% ------------------ %% Contract on heap_to_list: (postcondition: true) %:- spec heap_to_list(H,L) ==> % treemember(X,H,SH), listmember(X,L,LL). % %% ------------------ %% Contract on insert_heap: (postcondition: true) %:- spec insert_heap(X,H,H1) ==> % treemember(Y,H,SH), treemember(Y,H1,SH1). % %% ---------------------------------------------------------------- %% Contract on heap_merge: (postcondition: true) %:- spec heap_merge(HL,HR,H1) ==> % treemember(X,HL,SHL), treemember(X,HR,SHR), treemember(X,H1,SH1). %%---------------------------------------------------------------- %% Contract on mkbtree: (postcondition: true) %:- spec mkbtree(T,HL,HR,H1) ==> % treemember(X,HL,BHL), treemember(X,HR,BHR), treemember(X,H1,BH1). % =============================================================== :- query ff1/0. % =============================================================== % Catamorphic abstraction :- cata_abs list(int) ==> listmember(X,L,NL). :- cata_abs bintree_int ==> treemember(X,HL,BHL). % ================================================================