| 1 | :- module(external_functions_statistics_library, | |
| 2 | ['MEAN'/3, 'GEOMETRIC_MEAN'/3, 'HARMONIC_MEAN'/3, | |
| 3 | 'MEDIAN'/3, 'SKEWNESS'/3, 'KURTOSIS'/3, 'RANGE'/3, | |
| 4 | 'POPULATION_STANDARD_DEVIATION'/3, 'SAMPLE_STANDARD_DEVIATION'/3, | |
| 5 | 'FRACTILE'/4, 'CENTRAL_MOMENT'/4, | |
| 6 | 'COVARIANCE'/4, 'CORRELATION'/4, | |
| 7 | 'WEIGHTED_MEAN'/4, 'WEIGHTED_VARIANCE'/4, 'WEIGHTED_STANDARD_DEVIATION'/4, | |
| 8 | 'NORMALIZE'/3, 'MODE'/3]). | |
| 9 | ||
| 10 | %:- discontiguous external_fun_type/3, expects_spaninfo/1. | |
| 11 | % external_fun_type(FUN,ListOfTypeParameters,ListOfArgTypes) | |
| 12 | ||
| 13 | :- multifile external_functions:external_fun_type/3, external_functions:expects_spaninfo/1. | |
| 14 | ||
| 15 | external_functions:external_fun_type('MEAN',[T],[set(T),real]). | |
| 16 | external_functions:external_fun_type('GEOMETRIC_MEAN',[T],[set(T),real]). | |
| 17 | external_functions:external_fun_type('HARMONIC_MEAN',[T],[set(T),real]). | |
| 18 | external_functions:external_fun_type('MEDIAN',[T],[set(T),real]). | |
| 19 | external_functions:external_fun_type('SKEWNESS',[T],[set(T),real]). | |
| 20 | external_functions:external_fun_type('KURTOSIS',[T],[set(T),real]). | |
| 21 | external_functions:external_fun_type('RANGE',[T],[set(T),real]). | |
| 22 | external_functions:external_fun_type('POPULATION_STANDARD_DEVIATION',[T],[set(T),real]). | |
| 23 | external_functions:external_fun_type('SAMPLE_STANDARD_DEVIATION',[T],[set(T),real]). | |
| 24 | external_functions:external_fun_type('FRACTILE',[T],[real,set(T),real]). | |
| 25 | external_functions:external_fun_type('CENTRAL_MOMENT',[T],[integer,set(T),real]). | |
| 26 | external_functions:external_fun_type('COVARIANCE',[T],[set(T),set(T),real]). | |
| 27 | external_functions:external_fun_type('CORRELATION',[T],[set(T),set(T),real]). | |
| 28 | external_functions:external_fun_type('WEIGHTED_MEAN',[T1,T2],[set(T1),set(T2),real]). | |
| 29 | external_functions:external_fun_type('WEIGHTED_VARIANCE',[T1,T2],[set(T1),set(T2),real]). | |
| 30 | external_functions:external_fun_type('WEIGHTED_STANDARD_DEVIATION',[T1,T2],[set(T1),set(T2),real]). | |
| 31 | external_functions:external_fun_type('NORMALIZE',[T],[set(T),seq(real)]). | |
| 32 | external_functions:external_fun_type('MODE',[T],[set(T),seq(real)]). | |
| 33 | external_functions:expects_spaninfo('MEAN'). | |
| 34 | external_functions:expects_spaninfo('GEOMETRIC_MEAN'). | |
| 35 | external_functions:expects_spaninfo('HARMONIC_MEAN'). | |
| 36 | external_functions:expects_spaninfo('MEDIAN'). | |
| 37 | external_functions:expects_spaninfo('SKEWNESS'). | |
| 38 | external_functions:expects_spaninfo('KURTOSIS'). | |
| 39 | external_functions:expects_spaninfo('RANGE'). | |
| 40 | external_functions:expects_spaninfo('POPULATION_STANDARD_DEVIATION'). | |
| 41 | external_functions:expects_spaninfo('SAMPLE_STANDARD_DEVIATION'). | |
| 42 | external_functions:expects_spaninfo('FRACTILE'). | |
| 43 | external_functions:expects_spaninfo('CENTRAL_MOMENT'). | |
| 44 | external_functions:expects_spaninfo('COVARIANCE'). | |
| 45 | external_functions:expects_spaninfo('CORRELATION'). | |
| 46 | external_functions:expects_spaninfo('WEIGHTED_MEAN'). | |
| 47 | external_functions:expects_spaninfo('WEIGHTED_VARIANCE'). | |
| 48 | external_functions:expects_spaninfo('WEIGHTED_STANDARD_DEVIATION'). | |
| 49 | external_functions:expects_spaninfo('NORMALIZE'). | |
| 50 | external_functions:expects_spaninfo('MODE'). | |
| 51 | ||
| 52 | % This use_module only works when running ProB from source at the moment: | |
| 53 | :- use_module(library(statistics),[arithmetic_mean/2, geometric_mean/2, harmonic_mean/2, | |
| 54 | median/2, skewness/2, kurtosis/2, range/2, | |
| 55 | population_standard_deviation/2, sample_standard_deviation/2, | |
| 56 | fractile/3, central_moment/3, | |
| 57 | correlation/3, covariance/3, | |
| 58 | weighted_mean/3, weighted_variance/3, weighted_standard_deviation/3, | |
| 59 | normalize/2, mode/2]). | |
| 60 | ||
| 61 | :- use_module(library(lists),[maplist/3, same_length/2]). | |
| 62 | ||
| 63 | %:- use_module(kernel_tools,[ground_value_check/2]). | |
| 64 | ||
| 65 | % ------------------------------- | |
| 66 | % functions which take one sample and return a float: | |
| 67 | ||
| 68 | 'MEAN'(SetOrSequenceOfValues,Mean,Span) :- one_sample_call(SetOrSequenceOfValues,arithmetic_mean,Mean,Span). | |
| 69 | 'GEOMETRIC_MEAN'(SetOrSequenceOfValues,Mean,Span) :- one_sample_call(SetOrSequenceOfValues,geometric_mean,Mean,Span). | |
| 70 | 'HARMONIC_MEAN'(SetOrSequenceOfValues,Mean,Span) :- one_sample_call(SetOrSequenceOfValues,harmonic_mean,Mean,Span). | |
| 71 | 'MEDIAN'(SetOrSequenceOfValues,Res,Span) :- one_sample_call(SetOrSequenceOfValues,median,Res,Span). | |
| 72 | 'SKEWNESS'(SetOrSequenceOfValues,Res,Span) :- one_sample_call(SetOrSequenceOfValues,skewness,Res,Span). | |
| 73 | 'KURTOSIS'(SetOrSequenceOfValues,Res,Span) :- one_sample_call(SetOrSequenceOfValues,kurtosis,Res,Span). | |
| 74 | 'RANGE'(SetOrSequenceOfValues,Res,Span) :- one_sample_call(SetOrSequenceOfValues,range,Res,Span). | |
| 75 | 'POPULATION_STANDARD_DEVIATION'(SetOrSequenceOfValues,Res,Span) :- | |
| 76 | one_sample_call(SetOrSequenceOfValues,population_standard_deviation,Res,Span). | |
| 77 | 'SAMPLE_STANDARD_DEVIATION'(SetOrSequenceOfValues,Res,Span) :- | |
| 78 | one_sample_call(SetOrSequenceOfValues,sample_standard_deviation,Res,Span). | |
| 79 | ||
| 80 | :- block one_sample_call(-,?,?,?). | |
| 81 | one_sample_call(SetOrSequenceOfValues,Pred,Res,Span) :- | |
| 82 | convert_to_prolog_list(SetOrSequenceOfValues,Done,List,Span), | |
| 83 | one_sample_call_aux(Done,Pred,List,Res). | |
| 84 | ||
| 85 | :- block one_sample_call_aux(-,?,?,?). | |
| 86 | one_sample_call_aux(_,Pred,L,Mean) :- get_numbers(L,VL), | |
| 87 | call(Pred,VL,Res), | |
| 88 | construct_float(Res,Mean). | |
| 89 | ||
| 90 | :- block 'FRACTILE'(-,?,?,?). | |
| 91 | 'FRACTILE'(Real,SetOrSequenceOfValues,Res,Span) :- | |
| 92 | get_real(Real,Frac), | |
| 93 | when(nonvar(Frac),one_sample_call(SetOrSequenceOfValues,fractile(Frac),Res,Span)). | |
| 94 | ||
| 95 | :- block 'CENTRAL_MOMENT'(-,?,?,?). | |
| 96 | 'CENTRAL_MOMENT'(int(K),SetOrSequenceOfValues,Res,Span) :- | |
| 97 | when(nonvar(K),one_sample_call(SetOrSequenceOfValues,central_moment(K),Res,Span)). | |
| 98 | ||
| 99 | % ------------------------------- | |
| 100 | % function which take two samples: | |
| 101 | ||
| 102 | :- block 'COVARIANCE'(-,?,?,?), 'COVARIANCE'(?,-,?,?). | |
| 103 | 'COVARIANCE'(SetOrSequenceOfValues1,SetOrSequenceOfValues2,Res,Span) :- | |
| 104 | convert_to_prolog_list(SetOrSequenceOfValues1,Done1,List1,Span), | |
| 105 | convert_to_prolog_list(SetOrSequenceOfValues2,Done2,List2,Span), | |
| 106 | two_samples_aux(Done1,Done2,covariance,List1,List2,Res). | |
| 107 | :- block 'CORRELATION'(-,?,?,?), 'CORRELATION'(?,-,?,?). | |
| 108 | 'CORRELATION'(SetOrSequenceOfValues1,SetOrSequenceOfValues2,Res,Span) :- | |
| 109 | convert_to_prolog_list(SetOrSequenceOfValues1,Done1,List1,Span), | |
| 110 | convert_to_prolog_list(SetOrSequenceOfValues2,Done2,List2,Span), | |
| 111 | two_samples_aux(Done1,Done2,correlation,List1,List2,Res). | |
| 112 | :- block 'WEIGHTED_MEAN'(-,?,?,?), 'WEIGHTED_MEAN'(?,-,?,?). | |
| 113 | 'WEIGHTED_MEAN'(Weights,SetOrSequenceOfValues2,Res,Span) :- | |
| 114 | convert_to_prolog_list(Weights,Done1,List1,Span), | |
| 115 | convert_to_prolog_list(SetOrSequenceOfValues2,Done2,List2,Span), | |
| 116 | two_samples_aux(Done1,Done2,weighted_sample_call(weighted_mean,'WEIGHTED_MEAN',Span),List1,List2,Res). | |
| 117 | :- block 'WEIGHTED_VARIANCE'(-,?,?,?), 'WEIGHTED_VARIANCE'(?,-,?,?). | |
| 118 | 'WEIGHTED_VARIANCE'(Weights,SetOrSequenceOfValues2,Res,Span) :- | |
| 119 | convert_to_prolog_list(Weights,Done1,List1,Span), | |
| 120 | convert_to_prolog_list(SetOrSequenceOfValues2,Done2,List2,Span), | |
| 121 | two_samples_aux(Done1,Done2,weighted_sample_call(weighted_variance,'WEIGHTED_MEAN',Span),List1,List2,Res). | |
| 122 | :- block 'WEIGHTED_STANDARD_DEVIATION'(-,?,?,?), 'WEIGHTED_STANDARD_DEVIATION'(?,-,?,?). | |
| 123 | 'WEIGHTED_STANDARD_DEVIATION'(Weights,SetOrSequenceOfValues2,Res,Span) :- | |
| 124 | convert_to_prolog_list(Weights,Done1,List1,Span), | |
| 125 | convert_to_prolog_list(SetOrSequenceOfValues2,Done2,List2,Span), | |
| 126 | two_samples_aux(Done1,Done2,weighted_sample_call(weighted_standard_deviation, | |
| 127 | 'WEIGHTED_STANDARD_DEVIATION',Span),List1,List2,Res). | |
| 128 | ||
| 129 | ||
| 130 | weighted_sample_call(PrologPred,BFun,Span,List1,List2,Res) :- | |
| 131 | (same_length(List1,List2) -> true | |
| 132 | ; error_manager:add_error(statistics_library,'Weights must have same length as sample for',BFun,Span)), | |
| 133 | call(PrologPred,List1,List2,Res). | |
| 134 | ||
| 135 | :- block two_samples_aux(-,?,?,?,?,?), two_samples_aux(?,-,?,?,?,?). | |
| 136 | two_samples_aux(_,_,Pred,L1,L2,Res) :- get_numbers(L1,VL1), get_numbers(L2,VL2), | |
| 137 | call(Pred,VL1,VL2,VRes), | |
| 138 | construct_float(VRes,Res). | |
| 139 | ||
| 140 | % ------------------------------- | |
| 141 | % functions which return a sample or list of values: | |
| 142 | ||
| 143 | :- block 'NORMALIZE'(-,?,?). | |
| 144 | 'NORMALIZE'(SetOrSequenceOfValues,Res,Span) :- | |
| 145 | convert_to_prolog_list(SetOrSequenceOfValues,Done,List,Span), | |
| 146 | seq_float_result_aux(Done,normalize,List,Res). | |
| 147 | :- block 'MODE'(-,?,?). | |
| 148 | 'MODE'(SetOrSequenceOfValues,Res,Span) :- | |
| 149 | convert_to_prolog_list(SetOrSequenceOfValues,Done,List,Span), | |
| 150 | seq_float_result_aux(Done,mode,List,Res). | |
| 151 | ||
| 152 | :- block seq_float_result_aux(-,?,?,?). | |
| 153 | seq_float_result_aux(_,Pred,L,BSeq) :- get_numbers(L,VL), | |
| 154 | call(Pred,VL,Res), | |
| 155 | convert_list_to_float_seq(Res,BSeq). | |
| 156 | ||
| 157 | ||
| 158 | % --------------------- | |
| 159 | ||
| 160 | get_numbers(L,VL) :- maplist(get_number,L,VL). | |
| 161 | get_number(int(X),X). | |
| 162 | get_number(term(floating(X)),X). | |
| 163 | get_number((int(_),Range),X) :- get_number(Range,X). % we have a sequence of values | |
| 164 | get_number(pred_false,0). | |
| 165 | get_number(pred_true,1). | |
| 166 | ||
| 167 | get_real(term(floating(X)),X). | |
| 168 | ||
| 169 | construct_float(X,term(floating(RX))) :- | |
| 170 | (integer(X) -> RX is float(X) | |
| 171 | ; float(X) -> RX=X | |
| 172 | ; error_manager:add_error(statistics_library,'Illegal number:',X), RX=term(undefined)). | |
| 173 | ||
| 174 | % construct a B sequence from a Prolog list of numbers | |
| 175 | convert_list_to_float_seq(ER,Res) :- convert_list_to_fseq(ER,1,Seq), kernel_objects:equal_object_optimized(Seq,Res). | |
| 176 | ||
| 177 | convert_list_to_fseq([],_,[]). | |
| 178 | convert_list_to_fseq([H|T],N,[(int(N),FH)|CT]) :- construct_float(H,FH), N1 is N+1, convert_list_to_fseq(T,N1,CT). | |
| 179 | ||
| 180 | ||
| 181 | % TODO: move to external_function_tools.pl | |
| 182 | convert_to_prolog_list(SeqOrSetOfValues,Done,List,Span) :- | |
| 183 | kernel_tools:ground_value_check(SeqOrSetOfValues,Gr), | |
| 184 | convert_to_prolog_list_aux(Gr,SeqOrSetOfValues,List,Span,Done). | |
| 185 | ||
| 186 | :- block convert_to_prolog_list_aux(-,?,?,?,?). | |
| 187 | convert_to_prolog_list_aux(_,Set,List,_,Done) :- | |
| 188 | custom_explicit_sets:convert_to_avl(Set,avl_set(AVL)), !, | |
| 189 | avl:avl_domain(AVL,List), | |
| 190 | Done=done. | |
| 191 | convert_to_prolog_list_aux(_,Set,_,Span,_) :- | |
| 192 | error_manager:add_error(statistics_library,'Cannot convert argument to finite set: ',Set,Span). |