:- lib( kvs_k_increases_v/3 ). mlu_sample_defaults( repeats(false) ). /** mlu_sample( +Goal, +Times, -Yield, -Pairs ). mlu_sample( +Goal, +Times, -Yield, -Pairs, +Opts ). Run Goal Times number of times, at each run observing Yield. The results are the Yield-Count paired list Pairs. Currently the predicate: copy_terms Goal and Yield, and requires that Yield's copy will be ground after Goal's copy is called. Opts * repeats(R=false) if integer(R), the V in Pairs is a list of results (length(V) = R) == ?- lib(pepl). ?- sload_pe( coin ). ?- mlu_sample( scall(coin(Side)), 100, Side, Freqs ). Freqs = [head-47, tail-53]. ?- mlu_sample( scall(coin(Side)), 100, Side, Freqs ). Freqs = [head-49, tail-51]. == @author nicos angelopoulos @version 0.1 2016/8/31 */ mlu_sample( GoalPrv, N, Yield, Pairs ) :- mlu_sample( GoalPrv, N, Yield, Pairs, [] ). mlu_sample( GoalPrv, N, Yield, Pairs, Args ) :- options_append( mlu_sample, Args, Opts ), N > 0, ( GoalPrv = _:_ -> Goal = GoalPrv; Goal = user:GoalPrv ), options( repeats(R), Opts ), mlu_sample_repeats( R, N, Goal, Yield, Pairs ). mlu_sample_repeats( false, N, Goal, Yield, Pairs ) :- !, mlu_sample_n( N, Goal, Yield, [], Pairs ). mlu_sample_repeats( R, N, Goal, Yield, Pairs ) :- integer( R ), % fixme add error messages R > 0, mlu_sample_r_repeats( R, N, Goal, Yield, [], 0, Pairs ). mlu_sample_r_repeats( 0, _N, _Goal, _Yield, KVs, _NofSeen, Pairs ) :- !, Pairs = KVs. mlu_sample_r_repeats( R, N, Goal, Yield, AccKVs, NofSeen, Pairs ) :- mlu_sample_n( N, Goal, Yield, [], DisPairs ), keysort( DisPairs, Ord ), mlu_sample_repeat_fold_in( Ord, AccKVs, NofSeen, NxtKVs ), P is R - 1, NxtOfSeen is NofSeen + 1, mlu_sample_r_repeats( P, N, Goal, Yield, NxtKVs, NxtOfSeen, Pairs ). mlu_sample_repeat_fold_in( [], KVs, _NofSeen, KVs ) :- !. mlu_sample_repeat_fold_in( NewKVs, [], _NofSeen, NewKVSs ) :- !, findall( K-[V], member(K-V,NewKVs), NewKVSs ). mlu_sample_repeat_fold_in( [K1-V1|T1], [K2-V2|T2], NofSeen, KVs ) :- compare( Op, K1, K2 ), mlu_sample_repeat_fold_in_op( Op, K1, V1, T1, K2, V2, T2, NofSeen, KVs ). mlu_sample_repeat_fold_in_op( =, K1, V1, T1, _K2, V2, T2, NofSeen, [K1-Vs|T] ) :- append( V2, [V1], Vs ), mlu_sample_repeat_fold_in( T1, T2, NofSeen, T ). mlu_sample_repeat_fold_in_op( <, K1, V1, T1, K2, V2, T2, NofSeen, [K1-Vs|T] ) :- % unseen value findall( 0, between(1,NofSeen,_), Zeros ), append( Zeros, [V1], Vs ), mlu_sample_repeat_fold_in( T1, [K2-V2|T2], NofSeen, T ). mlu_sample_repeat_fold_in_op( <, K1, V1, T1, K2, V2, T2, NofSeen, [K2-Vs|T] ) :- % missing value append( V2, [0], Vs ), mlu_sample_repeat_fold_in( [K1-V1|T1], T2, NofSeen, T ). mlu_sample_n( 0, _Goal, _Yield, Pairs, Pairs ) :- !. mlu_sample_n( N, Goal, Yield, Acc, Pairs ) :- N > 0, debug( mlu(sample), 'Doing N: ~d', N ), copy_term( Goal-Yield, G1-Y1 ), call( G1 ), ground( Y1 ), !, kvs_k_increases_v( Acc, Y1, Next ), M is N - 1, mlu_sample_n( M, Goal, Yield, Next, Pairs ). mlu_sample_n( N, Goal, Yield, Acc, Pairs ) :- % fixme make behaviour here dependent to an option? N > 0, kvs_k_increases_v( Acc, fail, Next ), M is N - 1, mlu_sample_n( M, Goal, Yield, Next, Pairs ).