% ================================================================= :- pred constr(bool). :- mode constr(in). :- ignore constr/1. % ================================================================= % Program :- pred quicksort(list(int),list(int)). :- mode quicksort(in,out). quicksort([], []). quicksort([X | Xs], ResL) :- partition(X, Xs, Smalls, Bigs), % partition of the tail Xs quicksort(Smalls, Ls), % with respect to the pivot X. quicksort(Bigs, Bs), % X is NOT in Xs. cons(X,Bs,XBs), append(Ls, XBs, ResL). :- pred partition(int,list(int),list(int),list(int)). :- mode partition(in,in,out,out). partition(X, [], [], []). partition(X, [Y | Ys], [Y | Ls], Bs) :- constr( (X>Y) ), partition(X, Ys, Ls, Bs). partition(X, [Y | Xs], Ls, [Y | Bs]) :- constr( (X= sum(L,SL), sum(S,SS) => constr(SL=SS). % Contract on partition: :- spec partition(P,Ls,Smalls,Bigs) ==> sum(Smalls,SSmalls), sum(Bigs,SBigs), sum(Ls,SLs) => constr( (SLs = (SSmalls+SBigs)) ). % Contract on append: :- spec append(Xs,Ys,Zs) ==> sum(Xs,SXs), sum(Ys,SYs), sum(Zs,SZs) => constr( (SZs = (SXs+SYs)) ). % ================================================================= % Verification. % Property: :- pred ff1. ff1 :- constr(~(SL=SS)), sum(L,SL), sum(S,SS), quicksort(L,S). :- pred ff2. ff2 :- constr( ~(SLs = (SSmalls+SBigs)) ), sum(Smalls,SSmalls), sum(Bigs,SBigs), sum(Ls,SLs), partition(P,Ls,Smalls,Bigs). :- pred ff3. ff3 :- constr( ~(SZs = (SXs+SYs)) ), sum(Xs,SXs), sum(Ys,SYs), sum(Zs,SZs), append(Xs,Ys,Zs). % =================================================================% NON-CATA predicates: append cons constr partition quicksort