% ================================================================= :- 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. concat(Ls,X,Bs,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=MaxT,H,MaxT), H )) ), listMax(T,IsDefT,MaxT). % ================================================================= % Contract on quicksort: :- spec quicksort(L,S) ==> listMax(L,IsDefL,MaxL), listMax(S,IsDefS,MaxS) => constr( ( (IsDefL = IsDefS) & (IsDefL => (MaxL=MaxS)) ) ). % Contract on partition: :- spec partition(P,Ls,Smalls,Bigs) ==> listMax(Smalls,IsDefS,MSmalls), listMax(Bigs,IsDefB,MBigs), listMax(Ls,IsDefL,MLs), constr( Max = ite(MSmalls>MBigs,MSmalls,MBigs) ) % max(MSmalls,MBigs,Max) => constr( (((( IsDefS & IsDefB ) => ( IsDefL & ( MLs=Max ) )) & (( IsDefS & ~IsDefB ) => ( IsDefL & ( MLs=MSmalls ) ))) & (( ~IsDefS & IsDefB ) => ( IsDefL & ( MLs=MBigs ) ))) & (( ~IsDefS & ~IsDefB ) = ( ~IsDefL )) ). % Contract on concat: :- spec concat(Xs,Y,Ys,Zs) ==> listMax(Xs,IsDefXs,MaxXs), listMax(Ys,IsDefYs,MaxYs), listMax(Zs,IsDefZs,MaxZs), constr( Max2=ite(MaxXs>MaxYs,MaxXs,MaxYs) & Max3=ite(Max2>Y,Max2,Y) ) => constr( (((( IsDefXs & IsDefYs ) => ( IsDefZs & ( MaxZs=Max3 ) )) & (( IsDefXs & ~IsDefYs ) => ( IsDefZs & ( MaxZs=ite(MaxXs>Y,MaxXs,Y) ) ))) & (( ~IsDefXs & IsDefYs ) => ( IsDefZs & ( MaxZs=ite(MaxYs>Y,MaxYs,Y) ) ))) & (( ~IsDefXs & ~IsDefYs ) => ( IsDefZs & ( MaxZs=Y ))) ). % ================================================================= % Verification. % Property: :- pred ff1. ff1 :- constr(~( (IsDefL = IsDefS) & (IsDefL => (MaxL=MaxS)) )), listMax(L,IsDefL,MaxL), listMax(S,IsDefS,MaxS), quicksort(L,S). :- pred ff2. ff2 :- constr( ~((((( IsDefS & IsDefB ) => ( IsDefL & ( MLs=Max ) )) & (( IsDefS & ~IsDefB ) => ( IsDefL & ( MLs=MSmalls ) ))) & (( ~IsDefS & IsDefB ) => ( IsDefL & ( MLs=MBigs ) ))) & (( ~IsDefS & ~IsDefB ) = ( ~IsDefL )) ) ), listMax(Smalls,IsDefS,MSmalls), listMax(Bigs,IsDefB,MBigs), listMax(Ls,IsDefL,MLs), constr( Max = ite(MSmalls>MBigs,MSmalls,MBigs) ), % max(MSmalls,MBigs,Max), partition(X,Ls,Smalls,Bigs). :- pred ff3. ff3 :- constr( ~( (((( IsDefXs & IsDefYs ) => ( IsDefZs & ( MaxZs=Max3 ) )) & (( IsDefXs & ~IsDefYs ) => ( IsDefZs & ( MaxZs=ite(MaxXs>Y,MaxXs,Y) ) ))) & (( ~IsDefXs & IsDefYs ) => ( IsDefZs & ( MaxZs=ite(MaxYs>Y,MaxYs,Y) ) ))) & (( ~IsDefXs & ~IsDefYs ) => ( IsDefZs & ( MaxZs=Y ))) ) ), listMax(Xs,IsDefXs,MaxXs), listMax(Ys,IsDefYs,MaxYs), listMax(Zs,IsDefZs,MaxZs), constr( Max2=ite(MaxXs>MaxYs,MaxXs,MaxYs) & Max3=ite(Max2>Y,Max2,Y) ), concat(Xs,Y,Ys,Zs). % ================================================================= % NON-CATA predicates: concat constr partition quicksort