1:- discontiguous random_element/2.    2
    3type(int).
    4type(float).
    5generator(int).
    6generator(pos_int).
    7generator(pos_int_no_zero).
    8generator(neg_int).
    9generator(neg_int_no_zero).
   10generator(float).
   11generator(pos_float).
   12generator(neg_float).
   13generator(number).
   14generator(list).
   15generator(atom).
   16generator(string).
   17% generator(nonempty_list). % TODO?
   18generator(any).
   19generator(var). % variable
   20
   21provided_composite_generators([int(_,_), float(_,_), number(_,_), list(_), list(_,_), atom(_,_), string(_,_)]).
   22
   23% valid_generator(Generator): check whether Generator is a valid generator
   24valid_generator(Generator):-
   25    generator(Generator), !.
   26valid_generator(int(L,U)):-
   27    maplist(integer,[L,U]),
   28    U > L, !.
   29valid_generator(float(L,U)):-
   30    maplist(float,[L,U]),
   31    U > L, !.
   32valid_generator(number(L,U)):-
   33    maplist(number,[L,U]),
   34    U > L, !.
   35valid_generator(list(A)):-
   36    integer(A), !.
   37valid_generator(list(L)):- 
   38    is_list(L),
   39    maplist(valid_generator,L), !.
   40valid_generator(list(N,L)):-
   41    ((integer(N), N > 0) ; N = any),
   42    maplist(valid_generator,L), !.
   43valid_generator(atom(L,U)):-
   44    integer(L), L >= 1,
   45    integer(U), U >= L, !.
   46valid_generator(string(L,U)):-
   47    integer(L), L >= 1,
   48    integer(U), U >= L, !.
   49% user defined generator
   50valid_generator(G):-
   51    ground(G),
   52    G =.. [Name|Args],
   53    append([_],Args,ArgsTrue),
   54    G1 =.. [Name|ArgsTrue],
   55    clause(G1,_), !.
   56
   57% variable
   58random_element(var,_).
   59
   60% any element: number or list
   61random_element(any,V):-
   62    random_member(T,[number,list,atom,string]),
   63    random_element(T,V).
   64
   65% for integers
   66% random_element(int,V): V is a random integer between -2**31 and 2**31 
   67% random_element(pos_int,V): V is a random integer between 0 and 2**31 
   68% random_element(neg_int,V): V is a random integer between -2**31 and 0 
   69% random_element(int(L,U),V): V is a random integer between L and U 
   70random_element(int,V):-
   71    setting(min_val,MinV),
   72    setting(max_val,MaxV),
   73    random_element(int(MinV,MaxV),V).
   74random_element(pos_int,V):-
   75    setting(max_val,MaxV),
   76    random_element(int(0,MaxV),V).
   77random_element(pos_int_no_zero,V):-
   78    setting(max_val,MaxV),
   79    random_element(int(1,MaxV),V).
   80random_element(neg_int,V):-
   81    setting(min_val,MinV),
   82    random_element(int(MinV,0),V).
   83random_element(neg_int_no_zero,V):-
   84    setting(min_val,MinV),
   85    random_element(int(MinV,-1),V).
   86random_element(int(Lower,Upper),V):-
   87    random_between(Lower, Upper, V).
   88
   89% for floats
   90% random_element(float,V): V is a random float between -2**31 and 2**31 
   91% random_element(pos_float,V): V is a random float between 0 and 2**31 
   92% random_element(neg_float,V): V is a random float between -2**31 and 0 
   93% random_element(float,L,U,V): V is a random float between L and U 
   94random_element(float,V):-
   95    setting(min_val,MinV),
   96    setting(max_val,MaxV),
   97    random_element(float(MinV,MaxV),V).
   98random_element(pos_float,V):-
   99    setting(max_val,MaxV),
  100    random_element(float(0,MaxV),V).
  101random_element(neg_float,V):-
  102    setting(min_val,MinV),
  103    random_element(float(MinV,0),V).
  104random_element(float(Lower,Upper),V):-
  105    random(R),
  106    V is R*(Upper - Lower) + Lower.
  107
  108% for number (int or float)
  109% Check: when float, I allow integers as arguments, explicitly
  110% not allowed by the initial float check. That is,
  111% number(2,3) may call float(2,3) while a direct call to
  112% float(2,3) raises an error in the generator checking phase.
  113random_element(number,V):-
  114    random_member(T,[int,float]),
  115    random_element(T,V).
  116random_element(number(L,U),V):-
  117    random_member(T,[int,float]),
  118    RE =.. [T,L,U],
  119    random_element(RE,V).
  120
  121% pick_random_type(V): V is a random type among all possible types
  122% pick_random_type(Allowed,V): V is a random type among the allowed
  123pick_random_type(V):-
  124    findall(T,type(T),LT),
  125    random_member(Type,LT),
  126    random_element(Type,V).
  127pick_random_type(Allowed,V):-
  128    random_member(Type,Allowed),
  129    random_element(Type,V).
  130
  131% for lists
  132% random_element(list,L): L is a list of random length of any type
  133% random_element(list(N), L): L is a list of fixed length N of random types
  134% random_element(list(N,LT),L): L is a list of length N (possibly random, *) of types LT
  135% random_element(list(LT),L): L is a list of the same length of LT where each element of LT
  136%   denotes a type in that specific position
  137random_element(list,L):-
  138    setting(max_len_list, MaxLen),
  139    random_between(0, MaxLen, Len), % ok empty list
  140    length(L, Len),
  141    maplist(pick_random_type,L).
  142% list of fixed length of random types
  143random_element(list(N), L):-
  144    integer(N), !,
  145    length(L, N),
  146    maplist(pick_random_type, L).
  147% list of fixed types LT of length N
  148random_element(list(N,LT),L):-
  149    ( N = any -> % any length
  150        setting(max_len_list, MaxLen),
  151        random_between(0, MaxLen, Len) ;
  152        Len = N
  153    ),
  154    length(L, Len),
  155    maplist(pick_random_type(LT), L).
  156% list of the same length of LT where each element of LT
  157% denotes a type
  158random_element(list(LT),L):-
  159    length(LT,N), !,
  160    length(L,N),
  161    maplist(random_element, LT, L).
  162
  163% atoms
  164random_element(atom,AT):-
  165    setting(max_len_list, MaxLen),
  166    random_element(atom(1,MaxLen),AT).
  167random_element(atom(L,U),AT):-
  168    random_between(L,U,Len),
  169    length(LAtom,Len),
  170    maplist(random_between(0x20, 0x7e),LAtom),
  171    atom_codes(AT,LAtom).
  172random_element(string,String):-
  173    random_element(atom,Atom),
  174    atom_string(Atom,String).
  175random_element(string(L,U),String):-
  176    random_element(atom(L,U),Atom),
  177    atom_string(Atom,String).
  178    
  179
  180% user defined random element
  181random_element(G,El):-
  182    \+ generator(G),
  183    provided_composite_generators(CG),
  184    \+ member(G,CG), !,
  185    G =.. [Name|Args],
  186    append([El],Args,ArgsTrue),
  187    G1 =.. [Name|ArgsTrue],
  188    catch(G1, _Error, (
  189        format("Error in generating custom values from ~w~n",[G1]),
  190        false
  191    )), !