psyke 0.10.1.dev11__tar.gz → 0.10.4__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.
Potentially problematic release.
This version of psyke might be problematic. Click here for more details.
- {psyke-0.10.1.dev11/psyke.egg-info → psyke-0.10.4}/PKG-INFO +1 -1
- psyke-0.10.4/VERSION +1 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/hypercubic/gridrex/__init__.py +2 -2
- psyke-0.10.4/psyke/genetic/fgin/__init__.py +74 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/genetic/gin/__init__.py +32 -23
- {psyke-0.10.1.dev11 → psyke-0.10.4/psyke.egg-info}/PKG-INFO +1 -1
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke.egg-info/SOURCES.txt +1 -0
- psyke-0.10.1.dev11/VERSION +0 -1
- {psyke-0.10.1.dev11 → psyke-0.10.4}/LICENSE +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/MANIFEST.in +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/README.md +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/clustering/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/clustering/cream/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/clustering/exact/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/clustering/utils.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/cart/CartPredictor.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/cart/FairTree.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/cart/FairTreePredictor.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/cart/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/hypercubic/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/hypercubic/cosmik/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/hypercubic/creepy/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/hypercubic/divine/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/hypercubic/ginger/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/hypercubic/gridex/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/hypercubic/hex/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/hypercubic/hypercube.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/hypercubic/iter/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/hypercubic/strategy.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/hypercubic/utils.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/real/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/real/utils.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/trepan/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/extraction/trepan/utils.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/genetic/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/hypercubepredictor.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/schema/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/tuning/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/tuning/crash/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/tuning/orchid/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/tuning/pedro/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/utils/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/utils/dataframe.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/utils/logic.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/utils/metrics.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/utils/plot.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke/utils/sorted.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke.egg-info/dependency_links.txt +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke.egg-info/not-zip-safe +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke.egg-info/requires.txt +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/psyke.egg-info/top_level.txt +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/pyproject.toml +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/setup.cfg +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/setup.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/clustering/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/cart/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/cart/test_cart.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/cart/test_simplified_cart.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/hypercubic/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/hypercubic/gridex/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/hypercubic/gridex/test_gridex.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/hypercubic/iter/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/hypercubic/iter/test_iter.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/hypercubic/test_hypercube.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/real/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/real/test_real.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/real/test_rule.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/trepan/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/trepan/test_node.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/trepan/test_split.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/extraction/trepan/test_trepan.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/utils/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/utils/test_prune.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/utils/test_simplify.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/psyke/utils/test_simplify_formatter.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/resources/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/resources/datasets/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/resources/predictors/__init__.py +0 -0
- {psyke-0.10.1.dev11 → psyke-0.10.4}/test/resources/tests/__init__.py +0 -0
psyke-0.10.4/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.10.4
|
|
@@ -5,12 +5,12 @@ from psyke.extraction.hypercubic.gridex import GridEx
|
|
|
5
5
|
|
|
6
6
|
class GridREx(GridEx):
|
|
7
7
|
"""
|
|
8
|
-
Explanator implementing GridREx algorithm.
|
|
8
|
+
Explanator implementing GridREx algorithm, doi:10.24963/kr.2022/57.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
def __init__(self, predictor, grid: Grid, min_examples: int, threshold: float, normalization,
|
|
12
12
|
seed=get_default_random_seed()):
|
|
13
13
|
super().__init__(predictor, grid, min_examples, threshold, Target.REGRESSION, None, normalization, seed)
|
|
14
14
|
|
|
15
|
-
def _default_cube(self) -> RegressionCube:
|
|
15
|
+
def _default_cube(self, dimensions=None) -> RegressionCube:
|
|
16
16
|
return RegressionCube()
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
|
|
4
|
+
from psyke import Target
|
|
5
|
+
from psyke.genetic.gin import GIn
|
|
6
|
+
|
|
7
|
+
import skfuzzy as skf
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class FGIn(GIn):
|
|
11
|
+
|
|
12
|
+
def __init__(self, train, valid, features, sigmas, slices, min_rules=1, poly=1, alpha=0.5, indpb=0.5, tournsize=3,
|
|
13
|
+
metric='R2', output=Target.REGRESSION, warm=False):
|
|
14
|
+
super().__init__(train, valid, features, sigmas, slices, min_rules, poly, alpha, indpb, tournsize,
|
|
15
|
+
metric, output, warm)
|
|
16
|
+
self.feature_to_idx = {f: i for i, f in enumerate(self.X.columns)}
|
|
17
|
+
|
|
18
|
+
def _evaluate(self, individual=None):
|
|
19
|
+
y_pred, valid_regions = self.__predict(individual or self.best, self.X if self.valid is None else self.valid[0])
|
|
20
|
+
if valid_regions < self.min_rules:
|
|
21
|
+
return -9999,
|
|
22
|
+
return self._score(self.y if self.valid is None else self.valid[1], y_pred),
|
|
23
|
+
|
|
24
|
+
@staticmethod
|
|
25
|
+
def __generate_membership(var, domain, thresholds, shape='tri'):
|
|
26
|
+
th = [var.min()] + [min(max(t, var.min()), var.max()) for t in thresholds] + [var.max()]
|
|
27
|
+
|
|
28
|
+
if shape == 'tri':
|
|
29
|
+
mid = [(x1 + x2) / 2 for x1, x2 in zip(th[:-1], th[1:])]
|
|
30
|
+
return [skf.trapmf(domain, [domain.min()] * 2 + mid[:2])] + \
|
|
31
|
+
[skf.trimf(domain, [x1, x2, x3]) for x1, x2, x3 in zip(mid[:-2], mid[1:-1], mid[2:])] + \
|
|
32
|
+
[skf.trapmf(domain, mid[-2:] + [domain.max()] * 2)]
|
|
33
|
+
if shape == 'trap':
|
|
34
|
+
beg = [None, domain.min()] + [(3 * x1 + x2) / 4 for x1, x2 in zip(th[1:-1], th[2:])] + [domain.max()]
|
|
35
|
+
end = [domain.min()] + [(x1 + 3 * x2) / 4 for x1, x2 in zip(th[:-2], th[1:-1])] + [domain.max()]
|
|
36
|
+
return [skf.trapmf(domain, [end[i - 1], beg[i], end[i], beg[i + 1]]) for i in range(1, len(th))]
|
|
37
|
+
raise ValueError('Supported shape values are only \'tri\' and \'trap\'')
|
|
38
|
+
|
|
39
|
+
@staticmethod
|
|
40
|
+
def __extend_domain(x, q_low=0.05, q_high=0.95, p=0.05, k_sigma=2.0, abs_min_margin=0.0):
|
|
41
|
+
ql, qh = np.quantile(x, [q_low, q_high])
|
|
42
|
+
margin = max(p * (qh - ql), k_sigma * np.std(x), abs_min_margin)
|
|
43
|
+
return np.array([ql - margin, qh + margin])
|
|
44
|
+
|
|
45
|
+
def __get_activations(self, x, functions_domains, valid_masks):
|
|
46
|
+
levels = [np.array([skf.interp_membership(domain, mf, x[index]) for mf in mfs])
|
|
47
|
+
for mfs, domain, index in functions_domains.values()]
|
|
48
|
+
return np.prod(np.meshgrid(*levels, indexing='ij'), axis=0).ravel()[valid_masks]
|
|
49
|
+
|
|
50
|
+
def __fuzzify(self, cuts):
|
|
51
|
+
cuts = dict(zip(self.features, cuts))
|
|
52
|
+
doms = {c: FGIn.__extend_domain(self.X[c]) for c in self.features}
|
|
53
|
+
return {c: (FGIn.__generate_membership(self.X[c], doms[c], cuts[c], 'trap'), doms[c],
|
|
54
|
+
self.feature_to_idx[c]) for c in self.features}
|
|
55
|
+
|
|
56
|
+
def __predict(self, individual=None, to_pred=None):
|
|
57
|
+
cuts = self._get_cuts(individual or self.best)
|
|
58
|
+
masks = np.array([self._region(to_pred, cuts) == r for r in range(np.prod([s + 1 for s in self.slices]))])
|
|
59
|
+
valid_masks = masks.sum(axis=1) >= 3
|
|
60
|
+
|
|
61
|
+
masks = [mask for mask in masks if mask.sum() >= 3]
|
|
62
|
+
functions_domains = self.__fuzzify(cuts)
|
|
63
|
+
|
|
64
|
+
pred = np.array([self._output_estimation(mask, to_pred) for mask in masks]).T
|
|
65
|
+
activations = np.array([self.__get_activations(x, functions_domains, valid_masks) for x in to_pred.values])
|
|
66
|
+
|
|
67
|
+
if self.output == Target.CLASSIFICATION:
|
|
68
|
+
classes, idx = np.unique(pred, return_inverse=True)
|
|
69
|
+
pred = classes[np.argmax(np.vstack([activations[:, idx == i].sum(axis=1) for i, c in enumerate(classes)]),
|
|
70
|
+
axis=0)]
|
|
71
|
+
else:
|
|
72
|
+
pred = (pred * activations).sum(axis=1)
|
|
73
|
+
|
|
74
|
+
return pd.DataFrame(pred, index=to_pred.index), len(masks)
|
|
@@ -32,14 +32,15 @@ class GIn:
|
|
|
32
32
|
self.toolbox = None
|
|
33
33
|
self.stats = None
|
|
34
34
|
self.hof = None
|
|
35
|
+
self.best = None
|
|
35
36
|
|
|
36
|
-
self.
|
|
37
|
+
self.__setup(warm)
|
|
37
38
|
|
|
38
|
-
def
|
|
39
|
-
indices = [np.searchsorted(np.array(cut),
|
|
39
|
+
def _region(self, x, cuts):
|
|
40
|
+
indices = [np.searchsorted(np.array(cut), x[f].to_numpy(), side='right')
|
|
40
41
|
for cut, f in zip(cuts, self.features)]
|
|
41
42
|
|
|
42
|
-
regions = np.zeros(len(
|
|
43
|
+
regions = np.zeros(len(x), dtype=int)
|
|
43
44
|
multiplier = 1
|
|
44
45
|
for idx, n in zip(reversed(indices), reversed([len(cut) + 1 for cut in cuts])):
|
|
45
46
|
regions += idx * multiplier
|
|
@@ -47,7 +48,7 @@ class GIn:
|
|
|
47
48
|
|
|
48
49
|
return regions
|
|
49
50
|
|
|
50
|
-
def
|
|
51
|
+
def _output_estimation(self, mask, to_pred):
|
|
51
52
|
if self.output == Target.REGRESSION:
|
|
52
53
|
return LinearRegression().fit(self.poly.fit_transform(self.X)[mask], self.y[mask]).predict(
|
|
53
54
|
self.poly.fit_transform(to_pred))
|
|
@@ -55,9 +56,9 @@ class GIn:
|
|
|
55
56
|
return np.mean(self.y[mask])
|
|
56
57
|
if self.output == Target.CLASSIFICATION:
|
|
57
58
|
return mode(self.y[mask])
|
|
58
|
-
raise
|
|
59
|
+
raise ValueError('Supported outputs are Target.{REGRESSION, CONSTANT, CLASSIFICATION}')
|
|
59
60
|
|
|
60
|
-
def
|
|
61
|
+
def _score(self, true, pred):
|
|
61
62
|
if self.metric == 'R2':
|
|
62
63
|
return r2_score(true, pred)
|
|
63
64
|
if self.metric == 'MAE':
|
|
@@ -68,18 +69,23 @@ class GIn:
|
|
|
68
69
|
return f1_score(true, pred, average='weighted')
|
|
69
70
|
if self.metric == 'ACC':
|
|
70
71
|
return accuracy_score(true, pred)
|
|
71
|
-
raise
|
|
72
|
+
raise ValueError('Supported metrics are R2, MAE, MSE, F1, ACC')
|
|
72
73
|
|
|
73
|
-
def
|
|
74
|
-
|
|
74
|
+
def predict(self, to_pred):
|
|
75
|
+
return self.__predict(to_pred=to_pred)[0]
|
|
76
|
+
|
|
77
|
+
def _get_cuts(self, individual):
|
|
75
78
|
boundaries = np.cumsum([0] + list(self.slices))
|
|
76
|
-
|
|
79
|
+
return [sorted(individual[boundaries[i]:boundaries[i + 1]]) for i in range(len(self.slices))]
|
|
80
|
+
|
|
81
|
+
def __predict(self, individual=None, to_pred=None):
|
|
82
|
+
cuts = self._get_cuts(individual or self.best)
|
|
77
83
|
|
|
78
|
-
regions = self.
|
|
79
|
-
regionsT = self.
|
|
84
|
+
regions = self._region(to_pred, cuts)
|
|
85
|
+
regionsT = self._region(self.X, cuts)
|
|
80
86
|
|
|
81
|
-
|
|
82
|
-
else np.
|
|
87
|
+
pred = np.empty(len(to_pred), dtype=f'U{self.y.str.len().max()}') if self.output == Target.CLASSIFICATION \
|
|
88
|
+
else np.zeros(len(to_pred))
|
|
83
89
|
valid_regions = 0
|
|
84
90
|
|
|
85
91
|
for r in range(np.prod([s + 1 for s in self.slices])):
|
|
@@ -87,17 +93,20 @@ class GIn:
|
|
|
87
93
|
maskT = regionsT == r
|
|
88
94
|
if min(mask.sum(), maskT.sum()) < 3:
|
|
89
95
|
if self.output != Target.CLASSIFICATION:
|
|
90
|
-
|
|
96
|
+
pred[mask] = np.mean(self.y)
|
|
91
97
|
continue
|
|
92
|
-
|
|
98
|
+
pred[mask] = self._output_estimation(maskT, to_pred[mask])
|
|
93
99
|
valid_regions += 1
|
|
94
100
|
|
|
101
|
+
return pred, valid_regions
|
|
102
|
+
|
|
103
|
+
def _evaluate(self, individual=None):
|
|
104
|
+
y_pred, valid_regions = self.__predict(individual or self.best, self.X if self.valid is None else self.valid[0])
|
|
95
105
|
if valid_regions < self.min_rules:
|
|
96
106
|
return -9999,
|
|
107
|
+
return self._score(self.y if self.valid is None else self.valid[1], y_pred),
|
|
97
108
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def setup(self, warm=False):
|
|
109
|
+
def __setup(self, warm=False):
|
|
101
110
|
if not warm:
|
|
102
111
|
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
|
|
103
112
|
creator.create("Individual", list, fitness=creator.FitnessMax)
|
|
@@ -116,7 +125,7 @@ class GIn:
|
|
|
116
125
|
self.toolbox.register("mutate", tools.mutGaussian, indpb=self.indpb, mu=0,
|
|
117
126
|
sigma=sum([[sig] * s for sig, s in zip(self.sigmas, self.slices)], []))
|
|
118
127
|
self.toolbox.register("select", tools.selTournament, tournsize=self.tournsize)
|
|
119
|
-
self.toolbox.register("evaluate", self.
|
|
128
|
+
self.toolbox.register("evaluate", self._evaluate)
|
|
120
129
|
|
|
121
130
|
self.stats = tools.Statistics(lambda ind: ind.fitness.values[0])
|
|
122
131
|
self.stats.register("avg", np.mean)
|
|
@@ -131,5 +140,5 @@ class GIn:
|
|
|
131
140
|
pop = self.toolbox.population(n=n_pop)
|
|
132
141
|
result, log = algorithms.eaSimple(pop, self.toolbox, cxpb=cxpb, mutpb=mutpb, ngen=n_gen,
|
|
133
142
|
stats=self.stats, halloffame=self.hof, verbose=False)
|
|
134
|
-
best = tools.selBest(pop, 1)[0]
|
|
135
|
-
return best, self.
|
|
143
|
+
self.best = tools.selBest(pop, 1)[0]
|
|
144
|
+
return self.best, self._evaluate()[0], result, log
|
psyke-0.10.1.dev11/VERSION
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.10.1.dev11
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|