GRating 0.0.1__tar.gz
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.
- grating-0.0.1/PKG-INFO +17 -0
- grating-0.0.1/README.md +1 -0
- grating-0.0.1/pyproject.toml +41 -0
- grating-0.0.1/setup.cfg +4 -0
- grating-0.0.1/src/GRating.egg-info/PKG-INFO +17 -0
- grating-0.0.1/src/GRating.egg-info/SOURCES.txt +10 -0
- grating-0.0.1/src/GRating.egg-info/dependency_links.txt +1 -0
- grating-0.0.1/src/GRating.egg-info/requires.txt +4 -0
- grating-0.0.1/src/GRating.egg-info/top_level.txt +1 -0
- grating-0.0.1/src/grating/__init__.py +7 -0
- grating-0.0.1/src/grating/grating.py +431 -0
- grating-0.0.1/tests/test_rating.py +11 -0
grating-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: GRating
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Algorithm ranking library based on Bradley-Terry models
|
|
5
|
+
Author: Oscar A. Gonzalez Sanchez
|
|
6
|
+
Project-URL: Homepage, https://github.com/OscarAGonzalezSanchez/GRating
|
|
7
|
+
Keywords: optimization,ranking,metaheuristics
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: numpy
|
|
13
|
+
Requires-Dist: pandas
|
|
14
|
+
Requires-Dist: matplotlib
|
|
15
|
+
Requires-Dist: scipy
|
|
16
|
+
|
|
17
|
+
# readme = "README.md"
|
grating-0.0.1/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# readme = "README.md"
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=80"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "GRating"
|
|
7
|
+
version = "0.0.1"
|
|
8
|
+
description = "Algorithm ranking library based on Bradley-Terry models"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
|
|
12
|
+
dependencies = [
|
|
13
|
+
"numpy",
|
|
14
|
+
"pandas",
|
|
15
|
+
"matplotlib",
|
|
16
|
+
"scipy"
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
authors = [
|
|
20
|
+
{ name = "Oscar A. Gonzalez Sanchez" }
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
keywords = [
|
|
24
|
+
"optimization",
|
|
25
|
+
"ranking",
|
|
26
|
+
"metaheuristics"
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
classifiers = [
|
|
30
|
+
"Programming Language :: Python :: 3",
|
|
31
|
+
"License :: OSI Approved :: MIT License",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://github.com/OscarAGonzalezSanchez/GRating"
|
|
36
|
+
|
|
37
|
+
[tool.setuptools]
|
|
38
|
+
package-dir = {"" = "src"}
|
|
39
|
+
|
|
40
|
+
[tool.setuptools.packages.find]
|
|
41
|
+
where = ["src"]
|
grating-0.0.1/setup.cfg
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: GRating
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Algorithm ranking library based on Bradley-Terry models
|
|
5
|
+
Author: Oscar A. Gonzalez Sanchez
|
|
6
|
+
Project-URL: Homepage, https://github.com/OscarAGonzalezSanchez/GRating
|
|
7
|
+
Keywords: optimization,ranking,metaheuristics
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: numpy
|
|
13
|
+
Requires-Dist: pandas
|
|
14
|
+
Requires-Dist: matplotlib
|
|
15
|
+
Requires-Dist: scipy
|
|
16
|
+
|
|
17
|
+
# readme = "README.md"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/GRating.egg-info/PKG-INFO
|
|
4
|
+
src/GRating.egg-info/SOURCES.txt
|
|
5
|
+
src/GRating.egg-info/dependency_links.txt
|
|
6
|
+
src/GRating.egg-info/requires.txt
|
|
7
|
+
src/GRating.egg-info/top_level.txt
|
|
8
|
+
src/grating/__init__.py
|
|
9
|
+
src/grating/grating.py
|
|
10
|
+
tests/test_rating.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
grating
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
from matplotlib.ticker import FuncFormatter
|
|
2
|
+
from numpy.typing import NDArray
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
from scipy.stats import gmean
|
|
5
|
+
import pandas as pd
|
|
6
|
+
import numpy as np
|
|
7
|
+
import os
|
|
8
|
+
|
|
9
|
+
class GRating():
|
|
10
|
+
def __init__(self):
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
def create_experimentation_table(
|
|
14
|
+
self,
|
|
15
|
+
ruta: str,
|
|
16
|
+
filt: list[str] | None = None,
|
|
17
|
+
rettest: list[str] | None = None
|
|
18
|
+
) -> None:
|
|
19
|
+
"""
|
|
20
|
+
Crea una tabla de experimentación a partir de los archivos encontrados.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
ruta : str
|
|
25
|
+
Ruta raíz donde se buscarán los archivos.
|
|
26
|
+
filt : list[str], optional
|
|
27
|
+
Lista de filtros a aplicar durante la búsqueda.
|
|
28
|
+
rettest : list[str], optional
|
|
29
|
+
Lista de pruebas o resultados a retornar.
|
|
30
|
+
|
|
31
|
+
Returns
|
|
32
|
+
-------
|
|
33
|
+
None
|
|
34
|
+
"""
|
|
35
|
+
# Algorithms names are extracted
|
|
36
|
+
self.algorithms = os.listdir(ruta)
|
|
37
|
+
for i, algo in enumerate(self.algorithms):
|
|
38
|
+
self.algorithms[i] = algo[:-4]
|
|
39
|
+
|
|
40
|
+
self.algorithms = sorted(self.algorithms)
|
|
41
|
+
|
|
42
|
+
# An array for loading the data is created
|
|
43
|
+
df = pd.DataFrame(pd.read_csv(f'{ruta}/{self.algorithms[0]}.csv'))
|
|
44
|
+
self.tests = df.columns
|
|
45
|
+
|
|
46
|
+
if filt != None:
|
|
47
|
+
test = []
|
|
48
|
+
for value in self.tests:
|
|
49
|
+
for accepted in filt:
|
|
50
|
+
if accepted in value:
|
|
51
|
+
test.append(value)
|
|
52
|
+
self.tests = test
|
|
53
|
+
|
|
54
|
+
if rettest != None:
|
|
55
|
+
test = []
|
|
56
|
+
for value in self.tests:
|
|
57
|
+
flag = True
|
|
58
|
+
for rejected in rettest:
|
|
59
|
+
if rejected in value:
|
|
60
|
+
flag = False
|
|
61
|
+
if flag:
|
|
62
|
+
test.append(value)
|
|
63
|
+
self.tests = test
|
|
64
|
+
|
|
65
|
+
self.runs = len(df)
|
|
66
|
+
self.fit_data = np.zeros((len(self.algorithms), len(self.tests), self.runs))
|
|
67
|
+
|
|
68
|
+
# Information is loaded in the structure
|
|
69
|
+
for i, algo in enumerate(self.algorithms):
|
|
70
|
+
print(f'cargando {algo} ... con {len(self.tests)} test')
|
|
71
|
+
df = pd.DataFrame(pd.read_csv(f'{ruta}/{algo}.csv'))
|
|
72
|
+
for j, test in enumerate(self.tests):
|
|
73
|
+
self.fit_data[i, j, :] = df[test]
|
|
74
|
+
|
|
75
|
+
def load_fit_data(
|
|
76
|
+
self,
|
|
77
|
+
data: np.ndarray
|
|
78
|
+
) -> None:
|
|
79
|
+
"""
|
|
80
|
+
Carga directamente una matriz de resultados ya procesada.
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
data : np.ndarray
|
|
85
|
+
Arreglo tridimensional con forma
|
|
86
|
+
(algoritmos, pruebas, ejecuciones), donde cada elemento
|
|
87
|
+
representa el valor obtenido por un algoritmo en una
|
|
88
|
+
prueba específica durante una ejecución determinada.
|
|
89
|
+
|
|
90
|
+
Returns
|
|
91
|
+
-------
|
|
92
|
+
None
|
|
93
|
+
"""
|
|
94
|
+
self.fit_data = data
|
|
95
|
+
|
|
96
|
+
def create_win_lose_table(
|
|
97
|
+
self,
|
|
98
|
+
method: str='permutation',
|
|
99
|
+
draw: bool = False,
|
|
100
|
+
samples: int = 30
|
|
101
|
+
) -> None:
|
|
102
|
+
"""
|
|
103
|
+
Genera la matriz de victorias y derrotas entre algoritmos.
|
|
104
|
+
|
|
105
|
+
Cada posición [i, j] almacena el número de veces que el
|
|
106
|
+
algoritmo i supera al algoritmo j según el criterio de
|
|
107
|
+
comparación seleccionado.
|
|
108
|
+
|
|
109
|
+
Parameters
|
|
110
|
+
----------
|
|
111
|
+
method : str, optional
|
|
112
|
+
Método utilizado para realizar las comparaciones.
|
|
113
|
+
|
|
114
|
+
- 'permutation': compara todas las combinaciones posibles
|
|
115
|
+
entre ejecuciones.
|
|
116
|
+
- 'subsample': realiza una muestra aleatoria de comparaciones.
|
|
117
|
+
|
|
118
|
+
draw : bool, optional
|
|
119
|
+
Si es True, los empates se contabilizan otorgando medio
|
|
120
|
+
punto a cada algoritmo.
|
|
121
|
+
|
|
122
|
+
samples : int, optional
|
|
123
|
+
Número de comparaciones aleatorias cuando se utiliza el
|
|
124
|
+
método 'subsample'.
|
|
125
|
+
|
|
126
|
+
Returns
|
|
127
|
+
-------
|
|
128
|
+
None
|
|
129
|
+
"""
|
|
130
|
+
if method =='permutation':
|
|
131
|
+
# The size of the data is extracted
|
|
132
|
+
self.n_algorithms, self.n_test, self.runs = self.fit_data.shape
|
|
133
|
+
# A victory table is generated
|
|
134
|
+
self.vict_loss = np.zeros((self.n_algorithms, self.n_algorithms))
|
|
135
|
+
self.vict_loss[:] = np.nan
|
|
136
|
+
|
|
137
|
+
# The complete combinatory of wins is extracted
|
|
138
|
+
for ia in range(self.n_algorithms):
|
|
139
|
+
for ib in range(self.n_algorithms):
|
|
140
|
+
if ia!=ib:
|
|
141
|
+
wins = 0
|
|
142
|
+
for j in range(self.n_test):
|
|
143
|
+
for m in range(self.runs):
|
|
144
|
+
wins += (self.fit_data[ia, j, m] < self.fit_data[ib, j, :]).sum()
|
|
145
|
+
self.vict_loss[ia, ib] = wins
|
|
146
|
+
|
|
147
|
+
if draw == True:
|
|
148
|
+
# A half point is given for draws
|
|
149
|
+
for ia in range(self.n_algorithms):
|
|
150
|
+
for ib in range(self.n_algorithms):
|
|
151
|
+
if ia!=ib:
|
|
152
|
+
wins = 0
|
|
153
|
+
for j in range(self.n_test):
|
|
154
|
+
for m in range(self.runs):
|
|
155
|
+
wins += (self.fit_data[ia, j, m] == self.fit_data[ib, j, :]).sum()
|
|
156
|
+
self.vict_loss[ia, ib] = wins/2
|
|
157
|
+
self.vict_loss[ib, ia] = wins/2
|
|
158
|
+
|
|
159
|
+
elif method =='subsample':
|
|
160
|
+
# The size of the data is extracted
|
|
161
|
+
self.n_algorithms, self.n_test, self.runs = self.fit_data.shape
|
|
162
|
+
# A victory table is generated
|
|
163
|
+
self.vict_loss = np.zeros((self.n_algorithms, self.n_algorithms))
|
|
164
|
+
self.vict_loss[:] = np.nan
|
|
165
|
+
|
|
166
|
+
# The subsample of random comparisons of wins is extracted
|
|
167
|
+
for ia in range(self.n_algorithms):
|
|
168
|
+
for ib in range(self.n_algorithms):
|
|
169
|
+
if ia!=ib:
|
|
170
|
+
j = np.random.randint(0, self.n_test, size=samples)
|
|
171
|
+
m1 = np.random.randint(0, self.runs, size=samples)
|
|
172
|
+
m2 = np.random.randint(0, self.runs, size=samples)
|
|
173
|
+
wins = (self.fit_data[ia, j, m1] < self.fit_data[ib, j, m2]).sum()
|
|
174
|
+
self.vict_loss[ia, ib] = wins
|
|
175
|
+
|
|
176
|
+
if draw == True:
|
|
177
|
+
# A half point is given for draws
|
|
178
|
+
for ia in range(self.n_algorithms):
|
|
179
|
+
for ib in range(self.n_algorithms):
|
|
180
|
+
if ia!=ib:
|
|
181
|
+
wins = 0
|
|
182
|
+
for j in range(self.n_test):
|
|
183
|
+
for m in range(self.runs):
|
|
184
|
+
wins += (self.fit_data[ia, j, m] == self.fit_data[ib, j, :]).sum()
|
|
185
|
+
self.vict_loss[ia, ib] = wins/2
|
|
186
|
+
self.vict_loss[ib, ia] = wins/2
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def load_win_lose_table(
|
|
191
|
+
self,
|
|
192
|
+
table: NDArray[np.float64]
|
|
193
|
+
) -> None:
|
|
194
|
+
"""
|
|
195
|
+
Carga una matriz de victorias y derrotas.
|
|
196
|
+
|
|
197
|
+
Parameters
|
|
198
|
+
----------
|
|
199
|
+
table : NDArray[np.float64]
|
|
200
|
+
Matriz cuadrada donde la posición [i, j] indica las
|
|
201
|
+
victorias del algoritmo i sobre el algoritmo j.
|
|
202
|
+
|
|
203
|
+
Returns
|
|
204
|
+
-------
|
|
205
|
+
None
|
|
206
|
+
"""
|
|
207
|
+
self.vict_loss = table
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def train_bt_model(
|
|
211
|
+
self,
|
|
212
|
+
resolution: float=6,
|
|
213
|
+
max_iter: int = 10000
|
|
214
|
+
) -> tuple[list[str], NDArray[np.float64]]:
|
|
215
|
+
"""
|
|
216
|
+
Fits a Bradley-Terry model using an iterative maximum likelihood
|
|
217
|
+
estimation procedure.
|
|
218
|
+
|
|
219
|
+
The algorithm repeatedly updates the model parameters until
|
|
220
|
+
convergence is achieved or the maximum number of iterations is
|
|
221
|
+
reached.
|
|
222
|
+
|
|
223
|
+
Parameters
|
|
224
|
+
----------
|
|
225
|
+
resolution : float, optional
|
|
226
|
+
Number of significant digits required to declare convergence.
|
|
227
|
+
The fitting process stops when the maximum relative parameter
|
|
228
|
+
change falls below 10^(-resolution). Default is 6.
|
|
229
|
+
|
|
230
|
+
max_iter : int, optional
|
|
231
|
+
Maximum number of iterations allowed during the fitting
|
|
232
|
+
procedure. Default is 10000.
|
|
233
|
+
|
|
234
|
+
Returns
|
|
235
|
+
-------
|
|
236
|
+
tuple[list[str], NDArray[np.float64]]
|
|
237
|
+
A tuple containing:
|
|
238
|
+
|
|
239
|
+
- The algorithm names.
|
|
240
|
+
- The estimated Bradley-Terry ratings, normalized by their
|
|
241
|
+
geometric mean.
|
|
242
|
+
"""
|
|
243
|
+
self.n_algorithms = self.vict_loss.shape[0]
|
|
244
|
+
self.p = np.ones(self.n_algorithms)
|
|
245
|
+
|
|
246
|
+
max_p_percent_change = np.inf
|
|
247
|
+
n = 0
|
|
248
|
+
p_old = np.ones(self.n_algorithms)
|
|
249
|
+
while max_p_percent_change>1/np.power(10, resolution) and n<max_iter:
|
|
250
|
+
n+=1
|
|
251
|
+
p_old[:] = self.p
|
|
252
|
+
|
|
253
|
+
for i in range(self.n_algorithms):
|
|
254
|
+
num = 0
|
|
255
|
+
den = 0
|
|
256
|
+
for j in range(self.n_algorithms):
|
|
257
|
+
if i!=j:
|
|
258
|
+
num+=self.vict_loss[i, j]*self.p[j]/(self.p[i]+self.p[j])
|
|
259
|
+
den+=self.vict_loss[j, i]/(self.p[i]+self.p[j])
|
|
260
|
+
self.p[i]=num/den
|
|
261
|
+
|
|
262
|
+
self.p /= gmean(self.p)
|
|
263
|
+
|
|
264
|
+
delta = np.abs(1-self.p/p_old)
|
|
265
|
+
max_p_percent_change = np.max(delta)
|
|
266
|
+
return self.algorithms, self.p
|
|
267
|
+
|
|
268
|
+
def __str__(self) -> str:
|
|
269
|
+
"""
|
|
270
|
+
Devuelve una representación textual de los ratings calculados.
|
|
271
|
+
|
|
272
|
+
Returns
|
|
273
|
+
-------
|
|
274
|
+
str
|
|
275
|
+
Cadena con el nombre de cada algoritmo y su rating
|
|
276
|
+
correspondiente.
|
|
277
|
+
"""
|
|
278
|
+
text=''
|
|
279
|
+
for i in range(len(self.algorithms)):
|
|
280
|
+
text += f'{self.algorithms[i]}: {self.p[i]}\n'
|
|
281
|
+
return text
|
|
282
|
+
|
|
283
|
+
def get_friedman_mean_rank(self) -> NDArray[np.float64]:
|
|
284
|
+
"""
|
|
285
|
+
Calcula el ranking promedio de Friedman para cada algoritmo.
|
|
286
|
+
|
|
287
|
+
Primero se promedian las ejecuciones de cada prueba y después
|
|
288
|
+
se asigna un ranking relativo dentro de cada prueba. Finalmente
|
|
289
|
+
se obtiene el ranking medio de cada algoritmo.
|
|
290
|
+
|
|
291
|
+
Returns
|
|
292
|
+
-------
|
|
293
|
+
np.ndarray
|
|
294
|
+
Vector con el ranking promedio de Friedman para cada
|
|
295
|
+
algoritmo.
|
|
296
|
+
"""
|
|
297
|
+
n_algorithms, n_test, n_runs = self.fit_data.shape
|
|
298
|
+
|
|
299
|
+
self.friedman_mean_rank = np.zeros(n_algorithms)
|
|
300
|
+
self.test_rank = np.zeros((n_algorithms, n_test))
|
|
301
|
+
|
|
302
|
+
self.mean_fit_data = self.fit_data.mean(axis=2)
|
|
303
|
+
|
|
304
|
+
for j in range(n_test):
|
|
305
|
+
algorithm_data = self.mean_fit_data[:,j]
|
|
306
|
+
|
|
307
|
+
#Getting the ranking of each algoritm
|
|
308
|
+
array = np.array(algorithm_data)
|
|
309
|
+
temp = array.argsort()
|
|
310
|
+
ranks = np.empty_like(temp)
|
|
311
|
+
ranks[temp] = np.arange(len(array))
|
|
312
|
+
|
|
313
|
+
self.test_rank[:, j] = ranks+1
|
|
314
|
+
|
|
315
|
+
self.friedman_mean_rank = self.test_rank.mean(axis=1)
|
|
316
|
+
return self.friedman_mean_rank
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def create_scater_plot(
|
|
320
|
+
algorithms: list[str],
|
|
321
|
+
ratings: NDArray[np.float64],
|
|
322
|
+
rot: int | None = 45,
|
|
323
|
+
new_figure: bool | None = True
|
|
324
|
+
) -> None:
|
|
325
|
+
"""
|
|
326
|
+
Genera un gráfico de dispersión de los ratings obtenidos.
|
|
327
|
+
|
|
328
|
+
Parameters
|
|
329
|
+
----------
|
|
330
|
+
algorithms : list[str]
|
|
331
|
+
Nombres de los algoritmos.
|
|
332
|
+
|
|
333
|
+
ratings : NDArray[np.float64]
|
|
334
|
+
Ratings asociados a cada algoritmo.
|
|
335
|
+
|
|
336
|
+
rot : int, optional
|
|
337
|
+
Rotación de las etiquetas del eje X.
|
|
338
|
+
|
|
339
|
+
new_figure : bool, optional
|
|
340
|
+
Si es True, crea una nueva figura antes de dibujar.
|
|
341
|
+
|
|
342
|
+
Returns
|
|
343
|
+
-------
|
|
344
|
+
None
|
|
345
|
+
"""
|
|
346
|
+
if new_figure:
|
|
347
|
+
plt.Figure()
|
|
348
|
+
|
|
349
|
+
plt.scatter(ratings, np.arange(len(algorithms), 0, -1), c='Tab:Blue')
|
|
350
|
+
|
|
351
|
+
plt.yticks(np.arange(len(algorithms), 0, -1), algorithms)
|
|
352
|
+
plt.xticks()
|
|
353
|
+
|
|
354
|
+
plt.xscale('log')
|
|
355
|
+
|
|
356
|
+
ax = plt.gca()
|
|
357
|
+
ax.xaxis.set_minor_formatter(FuncFormatter(custom_minor_formatter))
|
|
358
|
+
ax.xaxis.set_major_formatter(FuncFormatter(custom_minor_formatter))
|
|
359
|
+
|
|
360
|
+
plt.tick_params(axis='x', which='both', bottom=True, labelbottom=True, rotation=rot)
|
|
361
|
+
plt.tick_params(axis='y', which='major', left=False)
|
|
362
|
+
|
|
363
|
+
plt.ylim(0, len(algorithms)+1)
|
|
364
|
+
plt.grid(True, axis='both', which='major', color='#BBBBBB', linestyle='--')
|
|
365
|
+
plt.ylabel('Algorithm')
|
|
366
|
+
plt.xlabel('G-Rating')
|
|
367
|
+
plt.tight_layout()
|
|
368
|
+
plt.show()
|
|
369
|
+
|
|
370
|
+
def custom_minor_formatter(
|
|
371
|
+
x: float,
|
|
372
|
+
pos: int
|
|
373
|
+
) -> str | float:
|
|
374
|
+
"""
|
|
375
|
+
Formateador personalizado para las marcas del eje logarítmico.
|
|
376
|
+
|
|
377
|
+
Muestra únicamente etiquetas para valores cuya mantisa sea
|
|
378
|
+
aproximadamente 1, 2, 3, 5 o 7.
|
|
379
|
+
|
|
380
|
+
Parameters
|
|
381
|
+
----------
|
|
382
|
+
x : float
|
|
383
|
+
Valor de la marca.
|
|
384
|
+
|
|
385
|
+
pos : int
|
|
386
|
+
Posición de la marca dentro del eje.
|
|
387
|
+
|
|
388
|
+
Returns
|
|
389
|
+
-------
|
|
390
|
+
str | float
|
|
391
|
+
Texto que se mostrará en la etiqueta o cadena vacía
|
|
392
|
+
cuando la etiqueta deba ocultarse.
|
|
393
|
+
"""
|
|
394
|
+
# Calculate the base coefficient (e.g., 200 -> 2, 0.5 -> 5)
|
|
395
|
+
# We do this to detect if the number 'starts' with 1, 2, or 5
|
|
396
|
+
base = np.log10(x)
|
|
397
|
+
decimal_part = base - np.floor(base)
|
|
398
|
+
coeff = 10 ** decimal_part
|
|
399
|
+
|
|
400
|
+
# Allow a small margin of error for floating point comparison
|
|
401
|
+
# We check if the number is close to 1, 2, or 5
|
|
402
|
+
if np.any([np.isclose(coeff, n, atol=0.1) for n in [1, 2, 3, 5, 7]]):
|
|
403
|
+
if base<0:
|
|
404
|
+
return np.round(x, decimals=int(-base)+1)
|
|
405
|
+
else:
|
|
406
|
+
return f'{int(x)}'
|
|
407
|
+
else:
|
|
408
|
+
return "" # Return empty string to hide the label
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
def signif(x: NDArray[np.float64], p: int) -> NDArray[np.float64]:
|
|
412
|
+
"""
|
|
413
|
+
Redondea valores a una cantidad específica de cifras significativas.
|
|
414
|
+
|
|
415
|
+
Parameters
|
|
416
|
+
----------
|
|
417
|
+
x : NDArray[np.float64]
|
|
418
|
+
Valor o conjunto de valores a redondear.
|
|
419
|
+
|
|
420
|
+
p : int
|
|
421
|
+
Número de cifras significativas deseadas.
|
|
422
|
+
|
|
423
|
+
Returns
|
|
424
|
+
-------
|
|
425
|
+
NDArray[np.float64]
|
|
426
|
+
Valores redondeados a p cifras significativas.
|
|
427
|
+
"""
|
|
428
|
+
x = np.asarray(x)
|
|
429
|
+
x_positive = np.where(np.isfinite(x) & (x != 0), np.abs(x), 10**(p-1))
|
|
430
|
+
mags = 10 ** (p - 1 - np.floor(np.log10(x_positive)))
|
|
431
|
+
return np.round(x * mags) / mags
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from grating import GRating
|
|
2
|
+
|
|
3
|
+
route = "../../data/Original_30D/best_fit"
|
|
4
|
+
model = GRating()
|
|
5
|
+
model.create_experimentation_table(route, filt=['original_30D_Ackley'], rettest=['Perm_0DB', 'Perm_DB'])
|
|
6
|
+
model.create_win_lose_table("permutation")
|
|
7
|
+
algorithms, G_rating = model.train_bt_model()
|
|
8
|
+
friedman_mean_rank = model.get_friedman_mean_rank()
|
|
9
|
+
|
|
10
|
+
print(algorithms, G_rating)
|
|
11
|
+
print(friedman_mean_rank)
|