aggregationslib 0.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aggregationslib/__init__.py +0 -0
- aggregationslib/aggregation.py +186 -0
- aggregationslib/aggregations.py +638 -0
- aggregationslib/conjuctive/__init__.py +0 -0
- aggregationslib/conjuctive/purepython.py +5 -0
- aggregationslib/decimalaggregations.py +256 -0
- aggregationslib/disjunctive/__init__.py +0 -0
- aggregationslib/example.py +8 -0
- aggregationslib/purepython.py +25 -0
- aggregationslib-0.0.0.dist-info/METADATA +124 -0
- aggregationslib-0.0.0.dist-info/RECORD +13 -0
- aggregationslib-0.0.0.dist-info/WHEEL +5 -0
- aggregationslib-0.0.0.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import warnings
|
|
3
|
+
from decimal import Decimal
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
from pynverse.inverse import inversefunc
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# 1 Arithmetic aggregation
|
|
10
|
+
def arithmetic(y):
|
|
11
|
+
"""
|
|
12
|
+
Arithmetic aggregation
|
|
13
|
+
:param y: 1 dimensional array
|
|
14
|
+
:return: aggregation value
|
|
15
|
+
"""
|
|
16
|
+
if np.ndim(y) != 1:
|
|
17
|
+
raise ValueError("y must be 1 dimensional array")
|
|
18
|
+
return np.mean(y)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# 2
|
|
22
|
+
def quadratic(y):
|
|
23
|
+
if np.ndim(y) != 1:
|
|
24
|
+
raise ValueError("y must be 1 dimensional array")
|
|
25
|
+
y = np.array(y)
|
|
26
|
+
size = len(y)
|
|
27
|
+
with np.errstate(divide='ignore'):
|
|
28
|
+
return np.sqrt(np.sum(y ** 2) / size)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# 3
|
|
32
|
+
def geometric(y):
|
|
33
|
+
if np.ndim(y) != 1:
|
|
34
|
+
raise ValueError("y must be 1 dimensional array")
|
|
35
|
+
|
|
36
|
+
size = len(y)
|
|
37
|
+
wk = 1 / size
|
|
38
|
+
with np.errstate(divide='ignore'):
|
|
39
|
+
return np.prod(y ** wk)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# 4
|
|
43
|
+
def harmonic(y):
|
|
44
|
+
if np.ndim(y) != 1:
|
|
45
|
+
raise ValueError("y must be 1 dimensional array")
|
|
46
|
+
if type(y).__module__ != np.__name__:
|
|
47
|
+
y = np.array(y)
|
|
48
|
+
size = len(y)
|
|
49
|
+
return size / (np.sum(1 / y))
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# 5
|
|
53
|
+
def power(y, r=1):
|
|
54
|
+
if np.ndim(y) != 1:
|
|
55
|
+
raise ValueError("y must be 1 dimensional array")
|
|
56
|
+
if r == 0:
|
|
57
|
+
raise ValueError("parameter r cannot be equal to 0 ")
|
|
58
|
+
# If one 0 occur in array then mean is 0
|
|
59
|
+
if 0 in y and r < 0:
|
|
60
|
+
return 0
|
|
61
|
+
else:
|
|
62
|
+
result = (np.sum(y ** r) / y.shape[0]) ** (1 / r)
|
|
63
|
+
return result
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# 6
|
|
67
|
+
def exponential(y, r=1):
|
|
68
|
+
if np.ndim(y) != 1:
|
|
69
|
+
raise ValueError("y must be 1 dimensional array")
|
|
70
|
+
if r == 0:
|
|
71
|
+
raise ValueError("parameter r should be != 0 ")
|
|
72
|
+
size = len(y)
|
|
73
|
+
y = np.array(y)
|
|
74
|
+
with np.errstate(divide='ignore'):
|
|
75
|
+
return (1 / r) * np.lib.scimath.log(np.sum(np.exp(y * r)) / size)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# 7
|
|
79
|
+
def lehmer(y, r=0):
|
|
80
|
+
if np.ndim(y) != 1:
|
|
81
|
+
raise ValueError("y must be 1 dimensional array")
|
|
82
|
+
# if array and r below 0 return 0. 0 to power of 0.
|
|
83
|
+
if 0 in y and r - 1 <= 0:
|
|
84
|
+
return 0
|
|
85
|
+
else:
|
|
86
|
+
r2 = (r - 1)
|
|
87
|
+
nominator = np.sum(y ** r)
|
|
88
|
+
with np.errstate(divide='ignore'): #
|
|
89
|
+
denominator = np.sum(y ** r2)
|
|
90
|
+
if denominator == 0:
|
|
91
|
+
return 0
|
|
92
|
+
else:
|
|
93
|
+
return nominator / denominator
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# 8
|
|
97
|
+
def arithmetic_min(y, p=0):
|
|
98
|
+
if np.ndim(y) != 1:
|
|
99
|
+
raise ValueError("y must be 1 dimensional array")
|
|
100
|
+
min = np.min(y)
|
|
101
|
+
return p * np.mean(y) + (1 - p) * min
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# 9
|
|
105
|
+
def arithmetic_max(y, p=0):
|
|
106
|
+
if np.ndim(y) != 1:
|
|
107
|
+
raise ValueError("y must be 1 dimensional array")
|
|
108
|
+
max = np.max(y)
|
|
109
|
+
return p * np.mean(y) + (1 - p) * max
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
# 10
|
|
113
|
+
def median(y):
|
|
114
|
+
if np.ndim(y) != 1:
|
|
115
|
+
raise ValueError("y must be 1 dimensional array")
|
|
116
|
+
return np.median(y)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# 11
|
|
120
|
+
def olimpic(y):
|
|
121
|
+
if np.ndim(y) != 1:
|
|
122
|
+
raise ValueError("y must be 1 dimensional array")
|
|
123
|
+
# b = np.max(a, 0) # max
|
|
124
|
+
# c = np.min(a, 0) # min
|
|
125
|
+
if len(y) < 3:
|
|
126
|
+
return np.mean(y)
|
|
127
|
+
else:
|
|
128
|
+
d = np.sort(y)[1:-1]
|
|
129
|
+
return np.mean(d)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def exponential2(y, p=0, q=0):
|
|
133
|
+
if np.ndim(y) != 1:
|
|
134
|
+
raise ValueError("y must be 1 dimensional array")
|
|
135
|
+
y = np.array(y)
|
|
136
|
+
mean = np.mean(p ** (q ** y))
|
|
137
|
+
firstlog = math.log(mean, p)
|
|
138
|
+
result = math.log(firstlog, q)
|
|
139
|
+
return result
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def exponential3(y, p=0, q=0):
|
|
143
|
+
if np.ndim(y) != 1:
|
|
144
|
+
raise ValueError("y must be 1 dimensional array")
|
|
145
|
+
y = np.array(y)
|
|
146
|
+
result = (1 / q) * math.log(np.mean(p ** (q * y)), p)
|
|
147
|
+
return result
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def sin_aggregation(y):
|
|
151
|
+
'''
|
|
152
|
+
|
|
153
|
+
:param y:
|
|
154
|
+
:return:
|
|
155
|
+
'''
|
|
156
|
+
# Check if 1 dimensional array
|
|
157
|
+
if np.ndim(y) != 1:
|
|
158
|
+
raise ValueError("y must be 1 dimensional array")
|
|
159
|
+
n = len(y)
|
|
160
|
+
return math.asin(np.sum(np.sin(y)) / n)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def quasi_arithmeric(y, function):
|
|
164
|
+
"""
|
|
165
|
+
Quasi arithmetic mean.
|
|
166
|
+
|
|
167
|
+
If function f(x)=x to then quasi-arithmetic mean is aritmetic mean.
|
|
168
|
+
If function f(x)=x^p (p != 0) then quasi-arithmetic mean is power mean to p power.
|
|
169
|
+
If function f(x)=log x then quasi-arithmetic mean is geometric mean.
|
|
170
|
+
|
|
171
|
+
:param y: 1 dimmensional array
|
|
172
|
+
:param function: function which maps an interval I of the real line to the real numbers, and is both continuous and injective
|
|
173
|
+
:return: aggregation value
|
|
174
|
+
"""
|
|
175
|
+
# Check if 1 dimensional array
|
|
176
|
+
if np.ndim(y) != 1:
|
|
177
|
+
raise ValueError("y must be 1 dimensional array")
|
|
178
|
+
n = len(y)
|
|
179
|
+
apply_func = np.array([function(x) for x in y])
|
|
180
|
+
value = np.sum(apply_func) / n
|
|
181
|
+
return inversefunc(function, value)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
if __name__ == "__main__":
|
|
185
|
+
print(quasi_arithmeric.__str__())
|
|
186
|
+
print(arithmetic_min([0.2, 0.4, 0.6], 0))
|
|
@@ -0,0 +1,638 @@
|
|
|
1
|
+
import itertools
|
|
2
|
+
import math
|
|
3
|
+
|
|
4
|
+
import numpy as np
|
|
5
|
+
import re
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class A_mn:
|
|
9
|
+
"""
|
|
10
|
+
Minimum
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
name = 'mn'
|
|
14
|
+
|
|
15
|
+
def __init__(self):
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
def __call__(self, array):
|
|
19
|
+
if np.ndim(array) != 1:
|
|
20
|
+
raise ValueError("y must be 1 dimensional array")
|
|
21
|
+
return np.min(array)
|
|
22
|
+
|
|
23
|
+
def __repr__(self):
|
|
24
|
+
return f"A_mn()"
|
|
25
|
+
|
|
26
|
+
def __str__(self):
|
|
27
|
+
return f"A_mn"
|
|
28
|
+
|
|
29
|
+
def toLatex(self, params: str):
|
|
30
|
+
return f"A_{{mn}}({params})"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class A_mx:
|
|
34
|
+
"""
|
|
35
|
+
Maximum
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
name = 'mx'
|
|
39
|
+
|
|
40
|
+
def __init__(self):
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
def __call__(self, array):
|
|
44
|
+
if np.ndim(array) != 1:
|
|
45
|
+
raise ValueError("y must be 1 dimensional array")
|
|
46
|
+
return np.max(array)
|
|
47
|
+
|
|
48
|
+
def __repr__(self):
|
|
49
|
+
return f"A_mx()"
|
|
50
|
+
|
|
51
|
+
def __str__(self):
|
|
52
|
+
return f"A_mx"
|
|
53
|
+
|
|
54
|
+
def toLatex(self, params: str):
|
|
55
|
+
return f"A_{{mx}}({params})"
|
|
56
|
+
|
|
57
|
+
class A_pr:
|
|
58
|
+
"""
|
|
59
|
+
Product
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
name = 'pr'
|
|
63
|
+
|
|
64
|
+
def __init__(self):
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
def __call__(self, array):
|
|
68
|
+
return np.prod(array, axis=0)
|
|
69
|
+
|
|
70
|
+
def __repr__(self):
|
|
71
|
+
return f"A_pr()"
|
|
72
|
+
|
|
73
|
+
def __str__(self):
|
|
74
|
+
return f"A_pr"
|
|
75
|
+
|
|
76
|
+
def toLatex(self, params: str):
|
|
77
|
+
return f"A_{{pr}}({params})"
|
|
78
|
+
|
|
79
|
+
class A_ar:
|
|
80
|
+
"""
|
|
81
|
+
Arithmetic mean
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
name = 'ar'
|
|
85
|
+
|
|
86
|
+
def __init__(self):
|
|
87
|
+
pass
|
|
88
|
+
|
|
89
|
+
def __call__(self, array):
|
|
90
|
+
"""
|
|
91
|
+
Arithmetic aggregation
|
|
92
|
+
:param y: 1 dimensional array
|
|
93
|
+
:return: aggregation value
|
|
94
|
+
"""
|
|
95
|
+
if np.ndim(array) != 1:
|
|
96
|
+
raise ValueError("y must be 1 dimensional array")
|
|
97
|
+
return np.mean(array)
|
|
98
|
+
|
|
99
|
+
def __repr__(self):
|
|
100
|
+
return f"A_ar()"
|
|
101
|
+
|
|
102
|
+
def __str__(self):
|
|
103
|
+
return f"A_ar"
|
|
104
|
+
|
|
105
|
+
def toLatex(self, params: str):
|
|
106
|
+
return f"A_{{ar}}({params})"
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class A_qd:
|
|
110
|
+
"""
|
|
111
|
+
Quadratic mean
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
name = 'qd'
|
|
115
|
+
|
|
116
|
+
def __init__(self):
|
|
117
|
+
pass
|
|
118
|
+
|
|
119
|
+
def __call__(self, array):
|
|
120
|
+
if np.ndim(array) != 1:
|
|
121
|
+
raise ValueError("y must be 1 dimensional array")
|
|
122
|
+
y = np.array(array)
|
|
123
|
+
size = len(y)
|
|
124
|
+
with np.errstate(divide='ignore'):
|
|
125
|
+
return np.sqrt(np.sum(y ** 2) / size)
|
|
126
|
+
|
|
127
|
+
def __repr__(self):
|
|
128
|
+
return f"A_qd()"
|
|
129
|
+
|
|
130
|
+
def __str__(self):
|
|
131
|
+
return f"A_qd"
|
|
132
|
+
|
|
133
|
+
def toLatex(self, params: str):
|
|
134
|
+
return f"A_{{qd}}({params})"
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class A_gm:
|
|
138
|
+
"""
|
|
139
|
+
Geometric mean
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
name = 'gm'
|
|
143
|
+
|
|
144
|
+
def __init__(self):
|
|
145
|
+
pass
|
|
146
|
+
|
|
147
|
+
def __call__(self, array):
|
|
148
|
+
if np.ndim(array) != 1:
|
|
149
|
+
raise ValueError("y must be 1 dimensional array")
|
|
150
|
+
size = len(array)
|
|
151
|
+
wk = 1 / size
|
|
152
|
+
with np.errstate(divide='ignore'):
|
|
153
|
+
return np.prod(array ** wk)
|
|
154
|
+
|
|
155
|
+
def __repr__(self):
|
|
156
|
+
return f"A_gm()"
|
|
157
|
+
|
|
158
|
+
def __str__(self):
|
|
159
|
+
return f"A_gm"
|
|
160
|
+
|
|
161
|
+
def toLatex(self, params: str):
|
|
162
|
+
return f"A_{{gm}}({params})"
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class A_hm:
|
|
167
|
+
"""
|
|
168
|
+
Harmonic mean
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
name = 'hm'
|
|
172
|
+
|
|
173
|
+
def __init__(self):
|
|
174
|
+
pass
|
|
175
|
+
|
|
176
|
+
def __call__(self, array):
|
|
177
|
+
if np.ndim(array) != 1:
|
|
178
|
+
raise ValueError("y must be 1 dimensional array")
|
|
179
|
+
y = np.array(array)
|
|
180
|
+
size = len(y)
|
|
181
|
+
return size / (np.sum(1 / y))
|
|
182
|
+
|
|
183
|
+
def __repr__(self):
|
|
184
|
+
return f"A_hm()"
|
|
185
|
+
|
|
186
|
+
def __str__(self):
|
|
187
|
+
return f"A_hm"
|
|
188
|
+
|
|
189
|
+
def toLatex(self, params: str):
|
|
190
|
+
return f"A_{{hm}}({params})"
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
class A_pw:
|
|
194
|
+
"""
|
|
195
|
+
Power mean
|
|
196
|
+
"""
|
|
197
|
+
|
|
198
|
+
name = 'pw'
|
|
199
|
+
|
|
200
|
+
valid_params = ["r"]
|
|
201
|
+
|
|
202
|
+
def __init__(self, r):
|
|
203
|
+
self.__r = r
|
|
204
|
+
|
|
205
|
+
def __call__(self, array):
|
|
206
|
+
if np.ndim(array) != 1:
|
|
207
|
+
raise ValueError("y must be 1 dimensional array")
|
|
208
|
+
if self.__r == 0:
|
|
209
|
+
raise ValueError("parameter r cannot be equal to 0 ")
|
|
210
|
+
# If one 0 occur in array then mean is 0
|
|
211
|
+
if 0 in array and self.__r < 0:
|
|
212
|
+
return 0
|
|
213
|
+
else:
|
|
214
|
+
result = (np.sum(array ** self.__r) / array.shape[0]) ** (1 / self.__r)
|
|
215
|
+
return result
|
|
216
|
+
|
|
217
|
+
def __repr__(self):
|
|
218
|
+
return f"A_pw(r={self.__r})"
|
|
219
|
+
|
|
220
|
+
def __str__(self):
|
|
221
|
+
return f"A_pw({self.__r})"
|
|
222
|
+
|
|
223
|
+
def toLatex(self, params: str):
|
|
224
|
+
return f"A_{{pw}}^{{{self.__r}}}({params})"
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
class A_ex:
|
|
228
|
+
"""
|
|
229
|
+
Exponential mean
|
|
230
|
+
"""
|
|
231
|
+
|
|
232
|
+
name = 'ex'
|
|
233
|
+
|
|
234
|
+
valid_params = ["r"]
|
|
235
|
+
|
|
236
|
+
def __init__(self, r):
|
|
237
|
+
self.__r = r
|
|
238
|
+
|
|
239
|
+
def __call__(self, array):
|
|
240
|
+
if np.ndim(array) != 1:
|
|
241
|
+
raise ValueError("y must be 1 dimensional array")
|
|
242
|
+
if self.__r == 0:
|
|
243
|
+
raise ValueError("parameter r should be != 0 ")
|
|
244
|
+
size = len(array)
|
|
245
|
+
y = np.array(array)
|
|
246
|
+
with np.errstate(divide='ignore'):
|
|
247
|
+
return (1 / self.__r) * np.lib.scimath.log(np.sum(np.exp(y * self.__r)) / size)
|
|
248
|
+
|
|
249
|
+
def __repr__(self):
|
|
250
|
+
return f"A_ex(r={self.__r})"
|
|
251
|
+
|
|
252
|
+
def __str__(self):
|
|
253
|
+
return f"A_ex({self.__r})"
|
|
254
|
+
|
|
255
|
+
def toLatex(self, params: str):
|
|
256
|
+
return f"A_{{ex}}^{{{self.__r}}}({params})"
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class A_ex2:
|
|
261
|
+
"""
|
|
262
|
+
Exponential2 mean
|
|
263
|
+
"""
|
|
264
|
+
|
|
265
|
+
name = 'ex2'
|
|
266
|
+
valid_params = ["p", "q"]
|
|
267
|
+
|
|
268
|
+
def __init__(self, p, q):
|
|
269
|
+
self.__p = p
|
|
270
|
+
self.__q = q
|
|
271
|
+
|
|
272
|
+
def __call__(self, array):
|
|
273
|
+
if np.ndim(array) != 1:
|
|
274
|
+
raise ValueError("y must be 1 dimensional array")
|
|
275
|
+
y = np.array(array)
|
|
276
|
+
mean = np.mean(self.__p ** (self.__q ** y))
|
|
277
|
+
firstlog = math.log(mean, self.__p)
|
|
278
|
+
result = math.log(firstlog, self.__q)
|
|
279
|
+
return result
|
|
280
|
+
|
|
281
|
+
def __repr__(self):
|
|
282
|
+
return f"A_ex2(p={self.__p}, q={self.__q})"
|
|
283
|
+
|
|
284
|
+
def __str__(self):
|
|
285
|
+
return f"A_ex2({self.__p}, {self.__q})"
|
|
286
|
+
|
|
287
|
+
def toLatex(self, params: str):
|
|
288
|
+
return f"A_{{ex2}}^{{p={self.__p}, q={self.__q}}}({params})"
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
class A_ex3:
|
|
292
|
+
"""
|
|
293
|
+
Exponential3 mean
|
|
294
|
+
"""
|
|
295
|
+
|
|
296
|
+
name = 'ex3'
|
|
297
|
+
valid_params = ["p", "q"]
|
|
298
|
+
|
|
299
|
+
def __init__(self, p, q):
|
|
300
|
+
self.__p = p
|
|
301
|
+
self.__q = q
|
|
302
|
+
|
|
303
|
+
def __call__(self, array):
|
|
304
|
+
if np.ndim(array) != 1:
|
|
305
|
+
raise ValueError("y must be 1 dimensional array")
|
|
306
|
+
y = np.array(array)
|
|
307
|
+
result = (1 / self.__q) * math.log(np.mean(self.__p ** (self.__q * y)), self.__p)
|
|
308
|
+
return result
|
|
309
|
+
|
|
310
|
+
def __repr__(self):
|
|
311
|
+
return f"A_ex3(p={self.__p}, q={self.__q})"
|
|
312
|
+
|
|
313
|
+
def __str__(self):
|
|
314
|
+
return f"A_ex3({self.__p}, {self.__q})"
|
|
315
|
+
|
|
316
|
+
def toLatex(self, params: str):
|
|
317
|
+
return f"A_{{ex3}}^{{p={self.__p}, q={self.__q}}}({params})"
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
class A_lm:
|
|
321
|
+
"""
|
|
322
|
+
Lehmer mean
|
|
323
|
+
"""
|
|
324
|
+
|
|
325
|
+
name = 'lm'
|
|
326
|
+
valid_params = ["r"]
|
|
327
|
+
|
|
328
|
+
def __init__(self, r):
|
|
329
|
+
self.__r = r
|
|
330
|
+
|
|
331
|
+
def __call__(self, array):
|
|
332
|
+
if np.ndim(array) != 1:
|
|
333
|
+
raise ValueError("y must be 1 dimensional array")
|
|
334
|
+
# if array and r below 0 return 0. 0 to power of 0.
|
|
335
|
+
if 0 in array and self.__r - 1 <= 0:
|
|
336
|
+
return 0
|
|
337
|
+
else:
|
|
338
|
+
r2 = (self.__r - 1)
|
|
339
|
+
nominator = np.sum(array ** self.__r)
|
|
340
|
+
with np.errstate(divide='ignore'): #
|
|
341
|
+
denominator = np.sum(array ** r2)
|
|
342
|
+
if denominator == 0:
|
|
343
|
+
return 0
|
|
344
|
+
else:
|
|
345
|
+
return nominator / denominator
|
|
346
|
+
|
|
347
|
+
def __repr__(self):
|
|
348
|
+
return f"A_lm(r={self.__r})"
|
|
349
|
+
|
|
350
|
+
def __str__(self):
|
|
351
|
+
return f"A_lm({self.__r})"
|
|
352
|
+
|
|
353
|
+
def toLatex(self, params: str):
|
|
354
|
+
return f"A_{{lm}}^{{r={self.__r}}}({params})"
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
class A_amn:
|
|
358
|
+
"""
|
|
359
|
+
Arithmetic minimum mean
|
|
360
|
+
"""
|
|
361
|
+
|
|
362
|
+
name = 'amn'
|
|
363
|
+
valid_params = ["p"]
|
|
364
|
+
|
|
365
|
+
def __init__(self, p):
|
|
366
|
+
self.__p = p
|
|
367
|
+
|
|
368
|
+
def __call__(self, array):
|
|
369
|
+
if np.ndim(array) != 1:
|
|
370
|
+
raise ValueError("y must be 1 dimensional array")
|
|
371
|
+
min_val = np.min(array)
|
|
372
|
+
return self.__p * np.mean(array) + (1 - self.__p) * min_val
|
|
373
|
+
|
|
374
|
+
def __repr__(self):
|
|
375
|
+
return f"A_amn(p={self.__p})"
|
|
376
|
+
|
|
377
|
+
def __str__(self):
|
|
378
|
+
return f"A_amn({self.__p})"
|
|
379
|
+
|
|
380
|
+
def toLatex(self, params: str):
|
|
381
|
+
return f"A_{{amn}}^{{p={self.__p}}}({params})"
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
class A_amx:
|
|
385
|
+
"""
|
|
386
|
+
Arithmetic maximum mean
|
|
387
|
+
"""
|
|
388
|
+
|
|
389
|
+
name = 'amx'
|
|
390
|
+
valid_params = ["p"]
|
|
391
|
+
|
|
392
|
+
def __init__(self, p):
|
|
393
|
+
self.__p = p
|
|
394
|
+
|
|
395
|
+
def __call__(self, array):
|
|
396
|
+
if np.ndim(array) != 1:
|
|
397
|
+
raise ValueError("y must be 1 dimensional array")
|
|
398
|
+
max_val = np.max(array)
|
|
399
|
+
return self.__p * np.mean(array) + (1 - self.__p) * max_val
|
|
400
|
+
|
|
401
|
+
def __repr__(self):
|
|
402
|
+
return f"A_amx(p={self.__p})"
|
|
403
|
+
|
|
404
|
+
def __str__(self):
|
|
405
|
+
return f"A_amx({self.__p})"
|
|
406
|
+
|
|
407
|
+
def toLatex(self, params: str):
|
|
408
|
+
return f"A_{{amx}}^{{p={self.__p}}}({params})"
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
class A_md:
|
|
412
|
+
"""
|
|
413
|
+
Median (Ordered weighted aggregation)
|
|
414
|
+
"""
|
|
415
|
+
|
|
416
|
+
name = 'md'
|
|
417
|
+
|
|
418
|
+
def __init__(self):
|
|
419
|
+
pass
|
|
420
|
+
|
|
421
|
+
def __call__(self, array):
|
|
422
|
+
if np.ndim(array) != 1:
|
|
423
|
+
raise ValueError("y must be 1 dimensional array")
|
|
424
|
+
return np.median(array)
|
|
425
|
+
|
|
426
|
+
def __repr__(self):
|
|
427
|
+
return f"A_md()"
|
|
428
|
+
|
|
429
|
+
def __str__(self):
|
|
430
|
+
return f"A_md"
|
|
431
|
+
|
|
432
|
+
def toLatex(self, params: str):
|
|
433
|
+
return f"A_{{md}}({params})"
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
class A_ol:
|
|
437
|
+
"""
|
|
438
|
+
Olimpic mean
|
|
439
|
+
"""
|
|
440
|
+
|
|
441
|
+
name = 'ol'
|
|
442
|
+
|
|
443
|
+
def __init__(self):
|
|
444
|
+
pass
|
|
445
|
+
|
|
446
|
+
def __call__(self, array):
|
|
447
|
+
if np.ndim(array) != 1:
|
|
448
|
+
raise ValueError("y must be 1 dimensional array")
|
|
449
|
+
if len(array) < 3:
|
|
450
|
+
return np.mean(array)
|
|
451
|
+
else:
|
|
452
|
+
d = np.sort(array)[1:-1]
|
|
453
|
+
return np.mean(d)
|
|
454
|
+
|
|
455
|
+
def __repr__(self):
|
|
456
|
+
return f"A_ol()"
|
|
457
|
+
|
|
458
|
+
def __str__(self):
|
|
459
|
+
return f"A_ol"
|
|
460
|
+
|
|
461
|
+
def toLatex(self, params: str):
|
|
462
|
+
return f"A_{{ol}}({params})"
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
class A_oln:
|
|
466
|
+
"""
|
|
467
|
+
Generalized olimpic mean
|
|
468
|
+
"""
|
|
469
|
+
|
|
470
|
+
name = 'oln'
|
|
471
|
+
valid_params = ['n']
|
|
472
|
+
|
|
473
|
+
def __init__(self, n):
|
|
474
|
+
self.__n = n
|
|
475
|
+
|
|
476
|
+
def __call__(self, array):
|
|
477
|
+
if np.ndim(array) != 1:
|
|
478
|
+
raise ValueError("y must be 1 dimensional array")
|
|
479
|
+
if len(array) <= self.__n * 2:
|
|
480
|
+
return np.mean(array)
|
|
481
|
+
else:
|
|
482
|
+
d = np.sort(array)[self.__n:-self.__n]
|
|
483
|
+
return np.mean(d)
|
|
484
|
+
|
|
485
|
+
def __repr__(self):
|
|
486
|
+
return f"A_oln(n={self.__n})"
|
|
487
|
+
|
|
488
|
+
def __str__(self):
|
|
489
|
+
return f"A_oln({self.__n})"
|
|
490
|
+
|
|
491
|
+
def toLatex(self, params: str):
|
|
492
|
+
return f"A_{{oln}}^{{n={self.__n}}}({params})"
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
# TODO test this aggregation
|
|
496
|
+
class A_lo:
|
|
497
|
+
"""
|
|
498
|
+
Generalized logarithmic mean
|
|
499
|
+
If large number of arguments its numerically unstable
|
|
500
|
+
"""
|
|
501
|
+
|
|
502
|
+
name = 'lo'
|
|
503
|
+
|
|
504
|
+
def __init__(self):
|
|
505
|
+
pass
|
|
506
|
+
|
|
507
|
+
def __call__(self, array):
|
|
508
|
+
if np.ndim(array) != 1:
|
|
509
|
+
raise ValueError("y must be 1 dimensional array")
|
|
510
|
+
fact = math.factorial(len(array) - 1)
|
|
511
|
+
sum_ = 0
|
|
512
|
+
for i in range(len(array)):
|
|
513
|
+
prod_ = 1
|
|
514
|
+
for j in range(len(array)):
|
|
515
|
+
if i != j:
|
|
516
|
+
if array[j] == 0: return 0
|
|
517
|
+
prod_ *= math.log(array[i] / array[j])
|
|
518
|
+
sum_ += array[i] / prod_
|
|
519
|
+
return fact * sum_
|
|
520
|
+
|
|
521
|
+
def __repr__(self):
|
|
522
|
+
return f"A_lo()"
|
|
523
|
+
|
|
524
|
+
def __str__(self):
|
|
525
|
+
return f"A_lo"
|
|
526
|
+
|
|
527
|
+
def toLatex(self, params: str):
|
|
528
|
+
return f"A_{{lo}}({params})"
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
class Combine2Aggregations:
|
|
532
|
+
def __init__(self, aggregation_function1, aggregation_function2, p=0.5):
|
|
533
|
+
self.__agg1 = aggregation_function1
|
|
534
|
+
self.__agg2 = aggregation_function2
|
|
535
|
+
self.__p = p
|
|
536
|
+
|
|
537
|
+
def __call__(self, array):
|
|
538
|
+
if np.ndim(array) != 1:
|
|
539
|
+
raise ValueError("y must be 1 dimensional array")
|
|
540
|
+
return self.__p * self.__agg1(array) + (1 - self.__p) * self.__agg2(array)
|
|
541
|
+
|
|
542
|
+
def __str__(self):
|
|
543
|
+
pattern = r'A_(.*?)\('
|
|
544
|
+
params_pattern = r'\((.*?)\)'
|
|
545
|
+
|
|
546
|
+
agg1 = re.search(pattern, self.__agg1.__repr__()).group(1)
|
|
547
|
+
agg2 = re.search(pattern, self.__agg2.__repr__()).group(1)
|
|
548
|
+
result = f"A_{agg1}{agg2}({self.__p}"
|
|
549
|
+
|
|
550
|
+
agg1_param = re.search(params_pattern, self.__agg1.__str__())
|
|
551
|
+
if agg1_param is not None:
|
|
552
|
+
agg1_param = agg1_param.group(1)
|
|
553
|
+
result += f", {agg1_param}"
|
|
554
|
+
|
|
555
|
+
agg2_param = re.search(params_pattern, self.__agg2.__str__())
|
|
556
|
+
if agg2_param is not None:
|
|
557
|
+
agg2_param = agg2_param.group(1)
|
|
558
|
+
result += f", {agg2_param}"
|
|
559
|
+
result += ")"
|
|
560
|
+
return result
|
|
561
|
+
|
|
562
|
+
def __repr__(self):
|
|
563
|
+
pattern = r'A_(.*?)\('
|
|
564
|
+
params_pattern = r'\((.*?)\)'
|
|
565
|
+
|
|
566
|
+
agg1 = re.search(pattern, self.__agg1.__repr__()).group(1)
|
|
567
|
+
agg2 = re.search(pattern, self.__agg2.__repr__()).group(1)
|
|
568
|
+
result = f"A_{agg1}{agg2}(p={self.__p}"
|
|
569
|
+
|
|
570
|
+
agg1_param = re.search(params_pattern, self.__agg1.__repr__()).group(1)
|
|
571
|
+
if agg1_param != "":
|
|
572
|
+
result += f", {agg1_param}"
|
|
573
|
+
|
|
574
|
+
agg2_param = re.search(params_pattern, self.__agg2.__repr__()).group(1)
|
|
575
|
+
if agg2_param != "":
|
|
576
|
+
result += f", {agg2_param}"
|
|
577
|
+
result += ")"
|
|
578
|
+
return result
|
|
579
|
+
|
|
580
|
+
def toLatex(self, params: str):
|
|
581
|
+
pqrn = f"{self.__p}"
|
|
582
|
+
|
|
583
|
+
# Inicjalizacja słownika dla wartości p, q, r, n
|
|
584
|
+
values = {'p': [], 'q': [], 'r': [], 'n': []}
|
|
585
|
+
|
|
586
|
+
# Iteracja po agregatorach
|
|
587
|
+
for agg in [self.__agg1, self.__agg2]:
|
|
588
|
+
for attr in values.keys():
|
|
589
|
+
# Pobranie wartości atrybutu dla danego agregatora, jeśli istnieje
|
|
590
|
+
value = getattr(agg, f'__{attr}', None)
|
|
591
|
+
if value is not None:
|
|
592
|
+
values[attr].append(str(value))
|
|
593
|
+
|
|
594
|
+
# Dodanie wartości do pqrn
|
|
595
|
+
for attr, val_list in values.items():
|
|
596
|
+
if val_list:
|
|
597
|
+
pqrn += f" {attr}= {', '.join(val_list)}"
|
|
598
|
+
|
|
599
|
+
return f"A_{{{self.__agg1.name},{self.__agg2.name}}}^{{{pqrn}}}({params})"
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
if __name__ == "__main__":
|
|
603
|
+
# example data
|
|
604
|
+
data = [0.2, 0.6, 0.7]
|
|
605
|
+
# configure function parameters
|
|
606
|
+
func1 = A_amn(p=0.5)
|
|
607
|
+
# use aggregation funciton
|
|
608
|
+
print(func1(data))
|
|
609
|
+
|
|
610
|
+
# Combine two aggregations - arithmetic mean and minimum
|
|
611
|
+
func2 = Combine2Aggregations(A_ar(), min)
|
|
612
|
+
# use combination of aggregation funciton
|
|
613
|
+
print(func2(data))
|
|
614
|
+
|
|
615
|
+
func1 = A_amn(p=0.5)
|
|
616
|
+
print(func1)
|
|
617
|
+
|
|
618
|
+
func2 = Combine2Aggregations(A_ar(), A_md())
|
|
619
|
+
print(func2)
|
|
620
|
+
|
|
621
|
+
func3 = Combine2Aggregations(A_ar(), A_pw(r=3))
|
|
622
|
+
print(func3.__repr__()) # function parameters are printed in order: func1, func2
|
|
623
|
+
|
|
624
|
+
aggregation_functions = []
|
|
625
|
+
ex_params = [0.2, 0.5, 1, 2, 3, 5]
|
|
626
|
+
for param in ex_params:
|
|
627
|
+
aggregation_functions.append(A_ex(param))
|
|
628
|
+
|
|
629
|
+
aggregation_functions += [A_mn(), A_mx(), A_ar(), A_md(),
|
|
630
|
+
A_ol()]
|
|
631
|
+
|
|
632
|
+
combinations = []
|
|
633
|
+
for func1, func2 in itertools.combinations(aggregation_functions, 2):
|
|
634
|
+
for p in range(1, 10):
|
|
635
|
+
combinations.append(Combine2Aggregations(func1, func2, p=p / 10))
|
|
636
|
+
|
|
637
|
+
for x in combinations:
|
|
638
|
+
print(x.__repr__())
|
|
File without changes
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import numbers
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
5
|
+
from decimal import Decimal
|
|
6
|
+
|
|
7
|
+
# 1 Arithmetic aggregation
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def arithmetic(y):
|
|
12
|
+
"""
|
|
13
|
+
Arithmetic aggregation
|
|
14
|
+
:param y: 1 dimensional array
|
|
15
|
+
:return: aggregation value
|
|
16
|
+
"""
|
|
17
|
+
_sum = Decimal('0')
|
|
18
|
+
n_elems = len(y)
|
|
19
|
+
for num in y:
|
|
20
|
+
try:
|
|
21
|
+
_sum += num
|
|
22
|
+
except:
|
|
23
|
+
_sum += Decimal(str(num))
|
|
24
|
+
warnings.warn("Numbers in iterable are converted to Decimal automatically.")
|
|
25
|
+
return _sum / n_elems
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# 2
|
|
29
|
+
def quadratic(y):
|
|
30
|
+
n = len(y)
|
|
31
|
+
_sum = Decimal('0')
|
|
32
|
+
for num in y:
|
|
33
|
+
try:
|
|
34
|
+
_sum += num ** 2
|
|
35
|
+
except:
|
|
36
|
+
_sum += Decimal(str(num)) ** 2
|
|
37
|
+
warnings.warn("Numbers in iterable are converted to Decimal automatically.")
|
|
38
|
+
return Decimal.sqrt(_sum / n)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# 3
|
|
42
|
+
def geometric(y):
|
|
43
|
+
"""
|
|
44
|
+
y should contain only positive numbers [0, inf]
|
|
45
|
+
:param y:
|
|
46
|
+
:return:
|
|
47
|
+
"""
|
|
48
|
+
_prod = Decimal('1')
|
|
49
|
+
n = Decimal(len(y))
|
|
50
|
+
|
|
51
|
+
for num in y:
|
|
52
|
+
try:
|
|
53
|
+
_prod *= num ** (1 / n)
|
|
54
|
+
except:
|
|
55
|
+
_prod *= Decimal(str(num)) ** (1 / n)
|
|
56
|
+
warnings.warn("Numbers in iterable are converted to Decimal automatically.")
|
|
57
|
+
return _prod
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# 4
|
|
61
|
+
def harmonic(y):
|
|
62
|
+
"""
|
|
63
|
+
WARNING if sum of denominator is 0 eg. [-10, 0 ,10] then function return 0.
|
|
64
|
+
WARNING if y cointains 0 then return 0.
|
|
65
|
+
:param y:
|
|
66
|
+
:return:
|
|
67
|
+
"""
|
|
68
|
+
n = Decimal(len(y))
|
|
69
|
+
|
|
70
|
+
y_dec = []
|
|
71
|
+
for x in y:
|
|
72
|
+
if isinstance(x, numbers.Number):
|
|
73
|
+
val = Decimal(str(x))
|
|
74
|
+
y_dec.append(val)
|
|
75
|
+
else:
|
|
76
|
+
raise ValueError("y should contain numbers in 1D iterable object.")
|
|
77
|
+
|
|
78
|
+
_sum = Decimal('0')
|
|
79
|
+
for num in y_dec:
|
|
80
|
+
if num == 0:
|
|
81
|
+
warnings.warn("y contains 0 for hearmonic(" + str(y) + ")")
|
|
82
|
+
return Decimal('0')
|
|
83
|
+
_sum += Decimal('1') / num
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
if _sum == 0:
|
|
87
|
+
warnings.warn("sum of denominator is equal to 0 for hearmonic(" + str(y) + ")")
|
|
88
|
+
return Decimal('0')
|
|
89
|
+
return n / _sum
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# 5
|
|
93
|
+
def power(y, r=1):
|
|
94
|
+
if r == 0:
|
|
95
|
+
raise ValueError("parameter r cannot be equal to 0 ")
|
|
96
|
+
# If one 0 occur in array then mean is 0
|
|
97
|
+
if 0 in y and r < 0:
|
|
98
|
+
return 0
|
|
99
|
+
else:
|
|
100
|
+
n = Decimal(len(y))
|
|
101
|
+
|
|
102
|
+
_sum = Decimal('0')
|
|
103
|
+
for num in y:
|
|
104
|
+
try:
|
|
105
|
+
_sum += num ** r
|
|
106
|
+
except:
|
|
107
|
+
_sum += Decimal(str(num)) ** r
|
|
108
|
+
warnings.warn("Numbers in iterable are converted to Decimal automatically.")
|
|
109
|
+
|
|
110
|
+
return (_sum / n) ** (1 / Decimal(r))
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# 6
|
|
114
|
+
def exponential(y, r=1):
|
|
115
|
+
"""
|
|
116
|
+
Mean is given by equation:
|
|
117
|
+
$A_6^{(r)}(x_1,...,x_n)= \frac{1}{r}\ln
|
|
118
|
+
\Big(\frac{1}{n} \sum \limits_{k=1}^{n} e^{rx_k}\Big)$, where
|
|
119
|
+
$r \in \mathbb{R}$, $r \neq 0$
|
|
120
|
+
|
|
121
|
+
:param y: array of values
|
|
122
|
+
:param r: r != 0
|
|
123
|
+
:return: value of exponential mean
|
|
124
|
+
"""
|
|
125
|
+
size = Decimal(str(len(y)))
|
|
126
|
+
r = Decimal(r)
|
|
127
|
+
if r == 0:
|
|
128
|
+
raise ValueError("parameter r should be != 0 ")
|
|
129
|
+
|
|
130
|
+
# Convert y to Decimal
|
|
131
|
+
y_dec = []
|
|
132
|
+
for x in y:
|
|
133
|
+
if isinstance(x, numbers.Number):
|
|
134
|
+
val = Decimal(str(x))
|
|
135
|
+
y_dec.append(val)
|
|
136
|
+
else:
|
|
137
|
+
raise ValueError("y should contain numbers in 1D iterable object.")
|
|
138
|
+
|
|
139
|
+
_sum = Decimal('0')
|
|
140
|
+
for idx, num in enumerate(y_dec):
|
|
141
|
+
_sum += (num * r).exp()
|
|
142
|
+
|
|
143
|
+
# # Comparasion to numpy
|
|
144
|
+
# # np_sum = np.sum(np.exp(y * int(r)))
|
|
145
|
+
# # np_sum_log = np.lib.scimath.log(np_sum / len(y))
|
|
146
|
+
|
|
147
|
+
return (1 / r) * (_sum / size).ln()
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
# 7
|
|
151
|
+
def lehmer(y, r=0):
|
|
152
|
+
r = Decimal(r)
|
|
153
|
+
if 0 in y and r - 1 <= 0:
|
|
154
|
+
return 0
|
|
155
|
+
else:
|
|
156
|
+
r2 = (r - 1)
|
|
157
|
+
_nominator = Decimal('0')
|
|
158
|
+
_denominator = Decimal('0')
|
|
159
|
+
for num in y:
|
|
160
|
+
try:
|
|
161
|
+
_nominator += num ** r
|
|
162
|
+
_denominator += num ** r2
|
|
163
|
+
except:
|
|
164
|
+
_nominator += Decimal(str(num)) ** r
|
|
165
|
+
_denominator += Decimal(str(num)) ** r2
|
|
166
|
+
warnings.warn("Numbers in iterable are converted to Decimal automatically.")
|
|
167
|
+
|
|
168
|
+
if _denominator == 0:
|
|
169
|
+
return 0
|
|
170
|
+
else:
|
|
171
|
+
return _nominator / _denominator
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
# 8
|
|
175
|
+
def arithmetic_min(y, p=0):
|
|
176
|
+
p = Decimal(p)
|
|
177
|
+
_min = Decimal(min(y))
|
|
178
|
+
return p * arithmetic(y) + (1 - p) * _min
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
# 9
|
|
182
|
+
def arithmetic_max(y, p=0):
|
|
183
|
+
p = Decimal(p)
|
|
184
|
+
_max = Decimal(max(y))
|
|
185
|
+
return p * arithmetic(y) + (1 - p) * _max
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
# 10
|
|
189
|
+
def median(y):
|
|
190
|
+
n = len(y)
|
|
191
|
+
if n % 2 == 0:
|
|
192
|
+
return arithmetic([y[(n / 2) - 1], y[n / 2]])
|
|
193
|
+
else:
|
|
194
|
+
return y[n // 2]
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
# 11
|
|
198
|
+
def olimpic(y):
|
|
199
|
+
if len(y) < 3:
|
|
200
|
+
return arithmetic(y)
|
|
201
|
+
else:
|
|
202
|
+
d = sorted(y)
|
|
203
|
+
d = d[1:-1]
|
|
204
|
+
return arithmetic(d)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def exponential2(y, p=0, q=0):
|
|
208
|
+
pass
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def exponential3(y, p=0, q=0):
|
|
212
|
+
pass
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def sin_aggregation(y):
|
|
216
|
+
pass
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def quasi_arithmeric(y, function):
|
|
220
|
+
pass
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
if __name__ == "__main__":
|
|
224
|
+
y = [-10, -22, 10]
|
|
225
|
+
# 1
|
|
226
|
+
print(arithmetic(y))
|
|
227
|
+
|
|
228
|
+
# 2
|
|
229
|
+
print(quadratic(y))
|
|
230
|
+
|
|
231
|
+
# 3
|
|
232
|
+
print(geometric(y))
|
|
233
|
+
|
|
234
|
+
# # 4
|
|
235
|
+
print(harmonic(y))
|
|
236
|
+
|
|
237
|
+
# 5
|
|
238
|
+
print(power(y, r=1))
|
|
239
|
+
|
|
240
|
+
# 6
|
|
241
|
+
print(exponential(y, r=1))
|
|
242
|
+
|
|
243
|
+
# 7
|
|
244
|
+
print(lehmer(y, r=0))
|
|
245
|
+
|
|
246
|
+
# 8
|
|
247
|
+
print(arithmetic_min(y, p=0))
|
|
248
|
+
|
|
249
|
+
# 9
|
|
250
|
+
print(arithmetic_max(y, p=0))
|
|
251
|
+
|
|
252
|
+
# 10
|
|
253
|
+
print(median(y))
|
|
254
|
+
|
|
255
|
+
# 11
|
|
256
|
+
print(olimpic(y))
|
|
File without changes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def exponential(y, r=1):
|
|
7
|
+
"""
|
|
8
|
+
Mean is given by equation:
|
|
9
|
+
$A_6^{(r)}(x_1,...,x_n)= \frac{1}{r}\ln
|
|
10
|
+
\Big(\frac{1}{n} \sum \limits_{k=1}^{n} e^{rx_k}\Big)$, where
|
|
11
|
+
$r \in \mathbb{R}$, $r \neq 0$
|
|
12
|
+
|
|
13
|
+
:param y: array of values
|
|
14
|
+
:param r: r != 0
|
|
15
|
+
:return: value of exponential mean
|
|
16
|
+
"""
|
|
17
|
+
size = len(y)
|
|
18
|
+
if r == 0:
|
|
19
|
+
raise ValueError("parameter r should be != 0 ")
|
|
20
|
+
|
|
21
|
+
_sum = 0
|
|
22
|
+
for idx, num in enumerate(y):
|
|
23
|
+
_sum += math.exp(num * r)
|
|
24
|
+
|
|
25
|
+
return (1 / r) * math.log(_sum / size)
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: aggregationslib
|
|
3
|
+
Version: 0.0.0
|
|
4
|
+
Summary: Python implementation of Arithmetic, quasi arithmetic and other aggregating functions
|
|
5
|
+
Home-page: https://github.com/wgalka/Means
|
|
6
|
+
Download-URL: https://github.com/wgalka/Means/archive/refs/tags/v0.0.3.tar.gz
|
|
7
|
+
Author: wgalka
|
|
8
|
+
License: TO DOO
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.13
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
Requires-Dist: numpy>=2.2.2
|
|
15
|
+
Requires-Dist: pynverse
|
|
16
|
+
Provides-Extra: test
|
|
17
|
+
Requires-Dist: pytest>=8.3.4; extra == "test"
|
|
18
|
+
Dynamic: author
|
|
19
|
+
Dynamic: classifier
|
|
20
|
+
Dynamic: description
|
|
21
|
+
Dynamic: description-content-type
|
|
22
|
+
Dynamic: download-url
|
|
23
|
+
Dynamic: home-page
|
|
24
|
+
Dynamic: license
|
|
25
|
+
Dynamic: provides-extra
|
|
26
|
+
Dynamic: requires-dist
|
|
27
|
+
Dynamic: requires-python
|
|
28
|
+
Dynamic: summary
|
|
29
|
+
|
|
30
|
+
# Means
|
|
31
|
+
Means, Aggregation functions...
|
|
32
|
+
|
|
33
|
+
Aggregations functions are:
|
|
34
|
+
- Conjuctive - the final aggregated value will always be influenced by the smallest value among the inputs.
|
|
35
|
+
- Disjnuctive - the aggregated value will always be influenced by the largest value among the inputs.
|
|
36
|
+
|
|
37
|
+
#### Example 1:
|
|
38
|
+
|
|
39
|
+
```pycon
|
|
40
|
+
# example data
|
|
41
|
+
data = [0.2, 0.6, 0.7]
|
|
42
|
+
# configure function parameters
|
|
43
|
+
func1 = A_amn(p=0.5)
|
|
44
|
+
# use aggregation funciton
|
|
45
|
+
print(func1(data))
|
|
46
|
+
|
|
47
|
+
# Combine two aggregations - arithmetic mean and minimum
|
|
48
|
+
func2 = Combine2Aggregations(A_ar(), min)
|
|
49
|
+
# use combination of aggregation funciton
|
|
50
|
+
print(func2(data))
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
#### Example2:
|
|
54
|
+
To get information about aggregation function you can use `__str__()` or '__repr__()' methods.
|
|
55
|
+
|
|
56
|
+
```pycon
|
|
57
|
+
func1 = A_amn(p=0.5)
|
|
58
|
+
print(func1)
|
|
59
|
+
>>>A_amn(0.5)
|
|
60
|
+
|
|
61
|
+
func2 = Combine2Aggregations(A_ar(), A_md())
|
|
62
|
+
print(func2)
|
|
63
|
+
>>>A_armd
|
|
64
|
+
|
|
65
|
+
func3 = Combine2Aggregations(A_ar(), A_pw(r=3))
|
|
66
|
+
print(func3.__repr__()) # function parameters are printed in order: func1, func2
|
|
67
|
+
>>>A_arpw(r=3)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`exponential(y, r=1)` is given by equation
|
|
71
|
+
|
|
72
|
+
$$
|
|
73
|
+
A_6^{(r)}(x_1,...,x_n)= \frac{1}{r}\ln
|
|
74
|
+
\Big(\frac{1}{n} \sum \limits_{k=1}^{n} e^{rx_k}\Big), where
|
|
75
|
+
r \in \mathbb{R}, r \neq 0
|
|
76
|
+
$$
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# A_ar - Arithmetic mean
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
# A_qd - Quadratic mean
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# A_gm - Geometric mean
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
# A_hm - Harmonic mean
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# A_pw - Power mean
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# A_ex, A_ex2, A_ex3 - Exponential mean
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
# A_lm - Lehmer mean
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# A_amn - Arithmetic minimum mean
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# A_amx - Arithmetic maximum mean
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# A_md - Median - ordered weighted aggregation
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
# A_ol - Olimpic aggregation
|
|
110
|
+
|
|
111
|
+
# A_oln - Olimpic aggregation
|
|
112
|
+
We can specify how many greatest and smallest records remove
|
|
113
|
+
|
|
114
|
+
# A_ln - Logaritmic aggregation
|
|
115
|
+
|
|
116
|
+
https://www.researchgate.net/publication/228886844_Logarithmic_mean_for_several_arguments
|
|
117
|
+
|
|
118
|
+
$$
|
|
119
|
+
L\left(x_1, x_2, \ldots, x_n\right)=(n-1) ! \sum_{i=1}^n \frac{x_i}{\prod_{\substack{j=1 \\ j \neq i}}^n \log \left(x_i / x_j\right)}
|
|
120
|
+
$$
|
|
121
|
+
|
|
122
|
+
# Combine2Aggregations - Combine aggregation functions
|
|
123
|
+
Amn, Amx, Aar , Aex , Amd,
|
|
124
|
+
Aow1, Aow1
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
aggregationslib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
aggregationslib/aggregation.py,sha256=xByHAEHVtu3PdnK21dJz9bayKqEO9_8xPjDGQytMpSY,4565
|
|
3
|
+
aggregationslib/aggregations.py,sha256=CPkielX2iM_wVXN3z0SfNE4Dxs1HMeX3R5h9kx2la0U,14644
|
|
4
|
+
aggregationslib/decimalaggregations.py,sha256=FYwro4KcojPH7ZMAEcKoE7MHN_1ojaTDY0UkEAzJN0M,5351
|
|
5
|
+
aggregationslib/example.py,sha256=4y3caiSBq4jkqz88Qan1m0LB389TXvlf7VSOPC_1Cj4,149
|
|
6
|
+
aggregationslib/purepython.py,sha256=Ov7AuBHLzoebS7HwTsDo8Ceed5pMzn3i71uevHnHbno,557
|
|
7
|
+
aggregationslib/conjuctive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
aggregationslib/conjuctive/purepython.py,sha256=f7YOyrEvaTiBhWDyJrKPbWrym2PGFYIkTqfE2u1lOvk,82
|
|
9
|
+
aggregationslib/disjunctive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
aggregationslib-0.0.0.dist-info/METADATA,sha256=VMvpYwwRkLWSCFfusZVJK_SlVcrEO7SnWrWfAY9_mec,2977
|
|
11
|
+
aggregationslib-0.0.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
12
|
+
aggregationslib-0.0.0.dist-info/top_level.txt,sha256=aAqYX4rNyBs40QOh2hc-jTE08IsMq0haGyyy7-GSdUQ,16
|
|
13
|
+
aggregationslib-0.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
aggregationslib
|