1:- use_module(library(lists)).    2
    3
    4shrink(any, X, X).
    5
    6shrink(atom, Atom, Shrunk) :-
    7    atom_codes(Atom, Codes0),
    8    shrink(codes, Codes0, Codes),
    9    atom_codes(Shrunk, Codes).
   10
   11shrink(code, _, 0'a).
   12shrink(code, _, 0'b).
   13shrink(code, _, 0'c).
   14shrink(code, _, 0' ).
   15
   16shrink(codes, Codes0, Codes) :-
   17    shrink(list(code), Codes0, Codes).
   18
   19shrink(integer, _, 0).  % zero often triggers bugs
   20shrink(integer, X, Y) :-
   21    % bisect from 1 towards the integer
   22    X > 0,
   23    MaxExponent is floor(log(abs(X))),
   24    between(0,MaxExponent,Exponent),
   25    Y is sign(X) * round(exp(Exponent)).
   26shrink(integer, X, Y) :-
   27    % try a positive version of a negative integer
   28    X < 0,
   29    Y is -X.
   30
   31shrink(list, L0, L) :-
   32    shrink(list(any), L0, L).
   33
   34shrink(list(_), L0, L) :-
   35    shrink_list_bisect(L0, L).
   36shrink(list(Type), L0, L) :-
   37    shrink_list_one(Type, L0, L).
   38
   39shrink(string, String, Shrunk) :-
   40    string_codes(String, Codes),
   41    subset_gen(ShrunkCodes, Codes),
   42    string_codes(Shrunk, ShrunkCodes).
   43
   44
   45% help shrink lists with bisection
   46shrink_list_bisect(L0, L) :-
   47    length(L0, Len),
   48    Len > 0,
   49    MaxExponent is ceiling(log(Len)),
   50    between(0,MaxExponent,Exponent),
   51    N is round(exp(MaxExponent-Exponent)),
   52    shrink_list_bisect_(L0, Len, N, L).
   53
   54% shrink by removing large pieces of a list
   55shrink_list_bisect_([], _, _, []).
   56shrink_list_bisect_(_, Len, N, []) :-
   57    N > Len.
   58shrink_list_bisect_(L0, Len, N, L) :-
   59    length(Front, N),
   60    append(Front, Back, L0),
   61    ( L = Back
   62    ; BackLen is Len - N,
   63      shrink_list_bisect_(Back, BackLen, N, NewBack),
   64      append(Front, NewBack, L)
   65    ).
   66
   67% shrink by removing or shrinking individual list elements
   68shrink_list_one(_, [], []).
   69shrink_list_one(Type, [H0|T], [H|T]) :-
   70    shrink(Type, H0, H).
   71shrink_list_one(Type, [H|T0], [H|T]) :-
   72    shrink_list_one(Type, T0, T).
 subset_gen(-Subset, +Set) is det
Generates subsets for the given set.

base case

   80subset_gen([], []).
   81% inductive case
   82subset_gen(Subset, [_ | Set]) :- subset_gen(Subset, Set).
   83subset_gen([H |Subset], [H | Set]) :- subset_gen(Subset, Set)