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).