pyerualjetwork 4.2.0b5__py3-none-any.whl → 4.2.1__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.
- pyerualjetwork/__init__.py +2 -52
- pyerualjetwork/data_operations.py +4 -0
- pyerualjetwork/help.py +2 -1
- pyerualjetwork/memory_operations.py +4 -4
- pyerualjetwork/plan.py +3 -3
- pyerualjetwork/plan_cuda.py +3 -3
- pyerualjetwork/planeat.py +11 -14
- pyerualjetwork/planeat_cuda.py +11 -14
- {pyerualjetwork-4.2.0b5.dist-info → pyerualjetwork-4.2.1.dist-info}/METADATA +2 -2
- {pyerualjetwork-4.2.0b5.dist-info → pyerualjetwork-4.2.1.dist-info}/RECORD +12 -12
- {pyerualjetwork-4.2.0b5.dist-info → pyerualjetwork-4.2.1.dist-info}/WHEEL +0 -0
- {pyerualjetwork-4.2.0b5.dist-info → pyerualjetwork-4.2.1.dist-info}/top_level.txt +0 -0
pyerualjetwork/__init__.py
CHANGED
@@ -1,55 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
subprocess.check_call(["pip", "install", 'setuptools==75.6.0'])
|
4
|
-
import pkg_resources
|
5
|
-
|
6
|
-
print("Auto checking and installation dependencies for PyerualJetwork")
|
7
|
-
|
8
|
-
package_names = [
|
9
|
-
'scipy==1.13.1',
|
10
|
-
'tqdm==4.66.4',
|
11
|
-
'seaborn==0.13.2',
|
12
|
-
'pandas==2.2.2',
|
13
|
-
'networkx==3.3',
|
14
|
-
'numpy==1.26.4',
|
15
|
-
'matplotlib==3.9.0',
|
16
|
-
'colorama==0.4.6',
|
17
|
-
'psutil==6.1.1',
|
18
|
-
'cupy-cuda12x==13.3.0'
|
19
|
-
]
|
20
|
-
|
21
|
-
installed_packages = pkg_resources.working_set
|
22
|
-
installed = {pkg.key: pkg.version for pkg in installed_packages}
|
23
|
-
err = 0
|
24
|
-
|
25
|
-
for package_name in package_names:
|
26
|
-
package_name_only, required_version = package_name.split('==')
|
27
|
-
|
28
|
-
if package_name_only not in installed:
|
29
|
-
|
30
|
-
try:
|
31
|
-
print(f"{package_name} Installing...")
|
32
|
-
subprocess.check_call(["pip", "install", package_name])
|
33
|
-
except Exception as e:
|
34
|
-
err += 1
|
35
|
-
print(f"Error installing {package_name} library, installation continues: {e}")
|
36
|
-
else:
|
37
|
-
|
38
|
-
installed_version = installed[package_name_only]
|
39
|
-
if installed_version != required_version:
|
40
|
-
print(f"Updating {package_name_only} from version {installed_version} to {required_version}...")
|
41
|
-
try:
|
42
|
-
subprocess.check_call(["pip", "install", package_name])
|
43
|
-
except Exception as e:
|
44
|
-
err += 1
|
45
|
-
print(f"Error updating {package_name} library, installation continues: {e}")
|
46
|
-
else:
|
47
|
-
print(f"{package_name} ready.")
|
48
|
-
|
49
|
-
print(f"PyerualJetwork is ready to use with {err} errors")
|
50
|
-
|
51
|
-
__version__ = "4.2.0b5"
|
52
|
-
__update__ = "* Changes: https://github.com/HCB06/PyerualJetwork/blob/main/CHANGES\n* PyerualJetwork document: https://github.com/HCB06/PyerualJetwork/blob/main/Welcome_to_PyerualJetwork/PYERUALJETWORK_USER_MANUEL_AND_LEGAL_INFORMATION(EN).pdf\n* YouTube tutorials: https://www.youtube.com/@HasanCanBeydili"
|
1
|
+
__version__ = "4.2.1"
|
2
|
+
__update__ = "* Changes: https://github.com/HCB06/PyerualJetwork/blob/main/CHANGES\n* PyerualJetwork Homepage: https://github.com/HCB06/PyerualJetwork/tree/main\n* PyerualJetwork document: https://github.com/HCB06/PyerualJetwork/blob/main/Welcome_to_PyerualJetwork/PYERUALJETWORK_USER_MANUEL_AND_LEGAL_INFORMATION(EN).pdf\n* YouTube tutorials: https://www.youtube.com/@HasanCanBeydili"
|
53
3
|
|
54
4
|
def print_version(__version__):
|
55
5
|
print(f"PyerualJetwork Version {__version__}" + '\n')
|
@@ -66,9 +66,13 @@ def split(X, y, test_size, random_state=42, dtype=np.float32):
|
|
66
66
|
|
67
67
|
Args:
|
68
68
|
X (numpy.ndarray): Features data.
|
69
|
+
|
69
70
|
y (numpy.ndarray): Labels data.
|
71
|
+
|
70
72
|
test_size (float or int): Proportion or number of samples for the test subset.
|
73
|
+
|
71
74
|
random_state (int or None): Seed for random state. Default: 42.
|
75
|
+
|
72
76
|
dtype (numpy.dtype): Data type for the arrays. np.float32 by default. Example: np.float64 or np.float16. [fp32 for balanced devices, fp64 for strong devices, fp16 for weak devices: not reccomended!]
|
73
77
|
|
74
78
|
Returns:
|
pyerualjetwork/help.py
CHANGED
@@ -34,13 +34,13 @@ def transfer_to_cpu(x, dtype=np.float32):
|
|
34
34
|
The `transfer_to_cpu` function converts data to a specified data type on the CPU, handling memory constraints
|
35
35
|
by batching the conversion process and ensuring complete GPU memory cleanup.
|
36
36
|
|
37
|
-
|
37
|
+
param x: Input data to transfer to CPU (CuPy array)
|
38
38
|
|
39
|
-
|
39
|
+
param dtype: Target NumPy dtype for the output array (default: np.float32)
|
40
40
|
|
41
|
-
|
41
|
+
return: NumPy array with the specified dtype
|
42
42
|
"""
|
43
|
-
from ui import loading_bars, initialize_loading_bar
|
43
|
+
from .ui import loading_bars, initialize_loading_bar
|
44
44
|
try:
|
45
45
|
if isinstance(x, np.ndarray):
|
46
46
|
return x.astype(dtype) if x.dtype != dtype else x
|
pyerualjetwork/plan.py
CHANGED
@@ -195,10 +195,10 @@ def learner(x_train, y_train, optimizer, x_test=None, y_test=None, strategy='acc
|
|
195
195
|
|
196
196
|
optimizer (function): PLAN optimization technique with hyperparameters. (PLAN using NEAT(PLANEAT) for optimization.) Please use this: from pyerualjetwork import planeat (and) optimizer = lambda *args, **kwargs: planeat.evolve(*args, 'here give your neat hyperparameters for example: activation_add_prob=0.85', **kwargs) Example:
|
197
197
|
```python
|
198
|
-
genetic_optimizer = lambda *args, **kwargs: planeat.
|
198
|
+
genetic_optimizer = lambda *args, **kwargs: planeat.evolver(*args,
|
199
199
|
activation_add_prob=0.85,
|
200
|
-
mutations=
|
201
|
-
strategy='
|
200
|
+
mutations=True,
|
201
|
+
strategy='aggressive',
|
202
202
|
**kwargs)
|
203
203
|
|
204
204
|
model = plan.learner(x_train,
|
pyerualjetwork/plan_cuda.py
CHANGED
@@ -210,10 +210,10 @@ def learner(x_train, y_train, optimizer, x_test=None, y_test=None, strategy='acc
|
|
210
210
|
|
211
211
|
optimizer (function): PLAN optimization technique with hyperparameters. (PLAN using NEAT(PLANEAT) for optimization.) Please use this: from pyerualjetwork import planeat_cuda (and) optimizer = lambda *args, **kwargs: planeat_cuda.evolve(*args, 'here give your neat hyperparameters for example: activation_add_prob=0.85', **kwargs) Example:
|
212
212
|
```python
|
213
|
-
genetic_optimizer = lambda *args, **kwargs: planeat_cuda.
|
213
|
+
genetic_optimizer = lambda *args, **kwargs: planeat_cuda.evolver(*args,
|
214
214
|
activation_add_prob=0.85,
|
215
|
-
mutations=
|
216
|
-
strategy='
|
215
|
+
mutations=True,
|
216
|
+
strategy='aggressive',
|
217
217
|
**kwargs)
|
218
218
|
|
219
219
|
model = plan_cuda.learner(x_train,
|
pyerualjetwork/planeat.py
CHANGED
@@ -76,7 +76,7 @@ def evolver(weights,
|
|
76
76
|
what_gen,
|
77
77
|
fitness,
|
78
78
|
show_info=False,
|
79
|
-
policy='
|
79
|
+
policy='aggressive',
|
80
80
|
bad_genomes_selection_prob=None,
|
81
81
|
bar_status=True,
|
82
82
|
strategy='normal_selective',
|
@@ -128,7 +128,7 @@ def evolver(weights,
|
|
128
128
|
|
129
129
|
policy (str, optional): The selection policy that governs how genomes are selected for reproduction. Options:
|
130
130
|
|
131
|
-
- '
|
131
|
+
- 'aggressive': Aggressive policy using very aggressive selection policy.
|
132
132
|
Advantages: fast training.
|
133
133
|
Disadvantages: may lead to fitness stuck in a local maximum or minimum.
|
134
134
|
|
@@ -138,7 +138,7 @@ def evolver(weights,
|
|
138
138
|
|
139
139
|
Suggestions: Use hybrid and dynamic policy. When fitness appears stuck, switch to the 'explorer' policy.
|
140
140
|
|
141
|
-
Default: '
|
141
|
+
Default: 'aggressive'.
|
142
142
|
|
143
143
|
target_fitness (str, optional): Target fitness strategy for PLANEAT optimization. ('max' maximizes fitness, 'min' minimizes fitness.) Default: 'max'.
|
144
144
|
|
@@ -190,7 +190,7 @@ def evolver(weights,
|
|
190
190
|
|
191
191
|
Raises:
|
192
192
|
ValueError:
|
193
|
-
- If `policy` is not one of the specified values ('
|
193
|
+
- If `policy` is not one of the specified values ('aggressive', 'explorer').
|
194
194
|
- If 'strategy' is not one of the specified values ('less_selective', 'normal_selective', 'more_selective')
|
195
195
|
- If `cross_over_mode` is not one of the specified values ('tpm').
|
196
196
|
- If `bad_genomes_mutation_prob`, `activation_mutate_prob`, or other probability parameters are not in the range 0 and 1.
|
@@ -222,7 +222,7 @@ def evolver(weights,
|
|
222
222
|
|
223
223
|
Example:
|
224
224
|
```python
|
225
|
-
weights, activation_potentiations = planeat.evolver(weights, activation_potentiations, 1, fitness, show_info=True, strategy='normal_selective', policy='
|
225
|
+
weights, activation_potentiations = planeat.evolver(weights, activation_potentiations, 1, fitness, show_info=True, strategy='normal_selective', policy='aggressive')
|
226
226
|
```
|
227
227
|
|
228
228
|
- The function returns the updated weights and activations after processing based on the chosen strategy, policy, and mutation parameters.
|
@@ -307,12 +307,9 @@ def evolver(weights,
|
|
307
307
|
best_fitness = normalized_fitness[-1]
|
308
308
|
epsilon = np.finfo(float).eps
|
309
309
|
|
310
|
-
child_W = np.empty(bad_weights.shape, dtype=dtype)
|
311
|
-
child_act = bad_activations.copy()
|
312
|
-
|
313
310
|
for i in range(len(bad_weights)):
|
314
311
|
|
315
|
-
if policy == '
|
312
|
+
if policy == 'aggressive':
|
316
313
|
first_parent_W = best_weight
|
317
314
|
first_parent_act = best_activations
|
318
315
|
|
@@ -320,11 +317,11 @@ def evolver(weights,
|
|
320
317
|
first_parent_W = good_weights[i]
|
321
318
|
first_parent_act = good_activations[i]
|
322
319
|
|
323
|
-
else: raise ValueError("policy parameter must be: '
|
320
|
+
else: raise ValueError("policy parameter must be: 'aggressive' or 'explorer'")
|
324
321
|
|
325
322
|
second_parent_W, second_parent_act, s_i = second_parent_selection(good_weights, bad_weights, good_activations, bad_activations, bad_genomes_selection_prob)
|
326
323
|
|
327
|
-
|
324
|
+
bad_weights[i], bad_activations[i] = cross_over(first_parent_W,
|
328
325
|
second_parent_W,
|
329
326
|
first_parent_act,
|
330
327
|
second_parent_act,
|
@@ -373,8 +370,8 @@ def evolver(weights,
|
|
373
370
|
|
374
371
|
if bar_status: progress.update(1)
|
375
372
|
|
376
|
-
weights = np.vstack((
|
377
|
-
activation_potentiations =
|
373
|
+
weights = np.vstack((bad_weights, good_weights))
|
374
|
+
activation_potentiations = bad_activations + good_activations
|
378
375
|
|
379
376
|
### INFO PRINTING CONSOLE
|
380
377
|
|
@@ -557,7 +554,7 @@ def cross_over(first_parent_W,
|
|
557
554
|
first_parent_fitness=0.9,
|
558
555
|
second_parent_fitness=0.85,
|
559
556
|
fitness_bias=0.6,
|
560
|
-
epsilon=np.finfo.eps
|
557
|
+
epsilon=np.finfo(float).eps
|
561
558
|
)
|
562
559
|
```
|
563
560
|
"""
|
pyerualjetwork/planeat_cuda.py
CHANGED
@@ -78,7 +78,7 @@ def evolver(weights,
|
|
78
78
|
what_gen,
|
79
79
|
fitness,
|
80
80
|
show_info=False,
|
81
|
-
policy='
|
81
|
+
policy='aggressive',
|
82
82
|
bad_genomes_selection_prob=None,
|
83
83
|
bar_status=True,
|
84
84
|
strategy='normal_selective',
|
@@ -130,7 +130,7 @@ def evolver(weights,
|
|
130
130
|
|
131
131
|
policy (str, optional): The selection policy that governs how genomes are selected for reproduction. Options:
|
132
132
|
|
133
|
-
- '
|
133
|
+
- 'aggressive': Aggressive policy using very aggressive selection policy.
|
134
134
|
Advantages: fast training.
|
135
135
|
Disadvantages: may lead to fitness stuck in a local maximum or minimum.
|
136
136
|
|
@@ -140,7 +140,7 @@ def evolver(weights,
|
|
140
140
|
|
141
141
|
Suggestions: Use hybrid and dynamic policy. When fitness appears stuck, switch to the 'explorer' policy.
|
142
142
|
|
143
|
-
Default: '
|
143
|
+
Default: 'aggressive'.
|
144
144
|
|
145
145
|
target_fitness (str, optional): Target fitness strategy for PLANEAT optimization. ('max' maximizes fitness, 'min' minimizes fitness.) Default: 'max'.
|
146
146
|
|
@@ -192,7 +192,7 @@ def evolver(weights,
|
|
192
192
|
|
193
193
|
Raises:
|
194
194
|
ValueError:
|
195
|
-
- If `policy` is not one of the specified values ('
|
195
|
+
- If `policy` is not one of the specified values ('aggressive', 'explorer').
|
196
196
|
- If 'strategy' is not one of the specified values ('less_selective', 'normal_selective', 'more_selective')
|
197
197
|
- If `cross_over_mode` is not one of the specified values ('tpm').
|
198
198
|
- If `bad_genomes_mutation_prob`, `activation_mutate_prob`, or other probability parameters are not in the range 0 and 1.
|
@@ -224,7 +224,7 @@ def evolver(weights,
|
|
224
224
|
|
225
225
|
Example:
|
226
226
|
```python
|
227
|
-
weights, activation_potentiations = planeat.evolver(weights, activation_potentiations, 1, fitness, show_info=True, strategy='normal_selective', policy='
|
227
|
+
weights, activation_potentiations = planeat.evolver(weights, activation_potentiations, 1, fitness, show_info=True, strategy='normal_selective', policy='aggressive')
|
228
228
|
```
|
229
229
|
|
230
230
|
- The function returns the updated weights and activations after processing based on the chosen strategy, policy, and mutation parameters.
|
@@ -306,13 +306,10 @@ def evolver(weights,
|
|
306
306
|
|
307
307
|
best_fitness = normalized_fitness[-1]
|
308
308
|
epsilon = cp.finfo(float).eps
|
309
|
-
|
310
|
-
child_W = cp.empty(bad_weights.shape, dtype=dtype)
|
311
|
-
child_act = bad_activations.copy()
|
312
309
|
|
313
310
|
for i in range(len(bad_weights)):
|
314
311
|
|
315
|
-
if policy == '
|
312
|
+
if policy == 'aggressive':
|
316
313
|
first_parent_W = best_weight
|
317
314
|
first_parent_act = best_activations
|
318
315
|
|
@@ -320,11 +317,11 @@ def evolver(weights,
|
|
320
317
|
first_parent_W = good_weights[i]
|
321
318
|
first_parent_act = good_activations[i]
|
322
319
|
|
323
|
-
else: raise ValueError("policy parameter must be: '
|
320
|
+
else: raise ValueError("policy parameter must be: 'aggressive' or 'explorer'")
|
324
321
|
|
325
322
|
second_parent_W, second_parent_act, s_i = second_parent_selection(good_weights, bad_weights, good_activations, bad_activations, bad_genomes_selection_prob)
|
326
323
|
|
327
|
-
|
324
|
+
bad_weights[i], bad_activations[i] = cross_over(first_parent_W,
|
328
325
|
second_parent_W,
|
329
326
|
first_parent_act,
|
330
327
|
second_parent_act,
|
@@ -373,8 +370,8 @@ def evolver(weights,
|
|
373
370
|
|
374
371
|
if bar_status: progress.update(1)
|
375
372
|
|
376
|
-
weights = cp.vstack((
|
377
|
-
activation_potentiations =
|
373
|
+
weights = cp.vstack((bad_weights, good_weights))
|
374
|
+
activation_potentiations = bad_activations + good_activations
|
378
375
|
|
379
376
|
### INFO PRINTING CONSOLE
|
380
377
|
|
@@ -560,7 +557,7 @@ def cross_over(first_parent_W,
|
|
560
557
|
first_parent_fitness=0.9,
|
561
558
|
second_parent_fitness=0.85,
|
562
559
|
fitness_bias=0.6,
|
563
|
-
epsilon=cp.finfo.eps
|
560
|
+
epsilon=cp.finfo(float).eps
|
564
561
|
)
|
565
562
|
```
|
566
563
|
"""
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: pyerualjetwork
|
3
|
-
Version: 4.2.
|
4
|
-
Summary: PyerualJetwork is a machine learning library written in Python for professionals
|
3
|
+
Version: 4.2.1
|
4
|
+
Summary: PyerualJetwork is a machine learning library supported with GPU(CUDA) acceleration written in Python for professionals and researchers including with PLAN algorithm, PLANEAT algorithm (genetic optimization). Also includes data pre-process and memory manegament
|
5
5
|
Author: Hasan Can Beydili
|
6
6
|
Author-email: tchasancan@gmail.com
|
7
7
|
Keywords: model evaluation,classification,potentiation learning artificial neural networks,NEAT,genetic algorithms,reinforcement learning,neural networks
|
@@ -1,24 +1,24 @@
|
|
1
|
-
pyerualjetwork/__init__.py,sha256=
|
1
|
+
pyerualjetwork/__init__.py,sha256=VhaX5FzNtwSCXlCCWPHIdrSCTimD14fwAnfZQcDjTqQ,646
|
2
2
|
pyerualjetwork/activation_functions.py,sha256=WWOdMd5pI6ZKe-ieKCIsKAYPQODHuXYxx7tzhA5xjes,11767
|
3
3
|
pyerualjetwork/activation_functions_cuda.py,sha256=KmXJ5Cdig46XAMYakXFPEOlxSxtFJjD21-i3nGtxPjE,11807
|
4
|
-
pyerualjetwork/data_operations.py,sha256=
|
4
|
+
pyerualjetwork/data_operations.py,sha256=pb5CqJ0Th6fCjTNMCtqQMiwH3KezTxAijacglsKUxmY,14730
|
5
5
|
pyerualjetwork/data_operations_cuda.py,sha256=UpoJoFhIwTU4xg9dVuLAxLAT4CkRaGsxvtJG9j1xrNo,17629
|
6
|
-
pyerualjetwork/help.py,sha256=
|
6
|
+
pyerualjetwork/help.py,sha256=nQ_YbYA2RtuafhuvkreNpX0WWL1I_nzlelwCtvei0_Y,775
|
7
7
|
pyerualjetwork/loss_functions.py,sha256=6PyBI232SQRGuFnG3LDGvnv_PUdWzT2_2mUODJiejGI,618
|
8
8
|
pyerualjetwork/loss_functions_cuda.py,sha256=C93IZJcrOpT6HMK9x1O4AHJWXYTkN5WZiqdssPbvAPk,617
|
9
|
-
pyerualjetwork/memory_operations.py,sha256=
|
9
|
+
pyerualjetwork/memory_operations.py,sha256=I7QiZ--xSyRkFF0wcckPwZV7K9emEvyx5aJ3DiRHZFI,13468
|
10
10
|
pyerualjetwork/metrics.py,sha256=q7MkhnZDRbCjFBDDfUgrl8lBYnUT_1ro1LxeBq105pI,6077
|
11
11
|
pyerualjetwork/metrics_cuda.py,sha256=73h9GC7XwmnFCVzFEEiPQfF8CwHIz2wsCbxpZrJtYgw,5061
|
12
12
|
pyerualjetwork/model_operations.py,sha256=hnhR8dtoICNJWIwGgJ65-LN3GYN_DYH4LMe6YpZVbnI,12967
|
13
13
|
pyerualjetwork/model_operations_cuda.py,sha256=XnKKq54ZLaqCm-NaJ6d8IToACKcKg2Ttq6moowVRRWo,13365
|
14
|
-
pyerualjetwork/plan.py,sha256=
|
15
|
-
pyerualjetwork/plan_cuda.py,sha256=
|
16
|
-
pyerualjetwork/planeat.py,sha256=
|
17
|
-
pyerualjetwork/planeat_cuda.py,sha256=
|
14
|
+
pyerualjetwork/plan.py,sha256=hvgRaJgz_31ixI6XDy_lkucQwbAN0iIqAj4aTc0oFiw,34422
|
15
|
+
pyerualjetwork/plan_cuda.py,sha256=ZTScc7VlqBLKUh6OtweJeGh-gf244nlPHTOeYrNaIyg,36065
|
16
|
+
pyerualjetwork/planeat.py,sha256=hofSkdFHoGXP52GUpTOQ-QwhPF2Vf6zwEdoesfpmWxU,41006
|
17
|
+
pyerualjetwork/planeat_cuda.py,sha256=0DOU1cL-JeifSAF9Q_bBpEeAJp9zxB7_oS_GyNepixo,40970
|
18
18
|
pyerualjetwork/ui.py,sha256=wu2BhU1k-w3Kcho5Jtq4SEKe68ftaUeRGneUOSCVDjU,575
|
19
19
|
pyerualjetwork/visualizations.py,sha256=QaYSIyVkJZ8NqpBKArQKkI1y37nCQo_KIM98IMssnRc,28766
|
20
20
|
pyerualjetwork/visualizations_cuda.py,sha256=F60vQ92AXlMgBka3InXnOtGoM25vQJAlBIU2AlYTwks,29200
|
21
|
-
pyerualjetwork-4.2.
|
22
|
-
pyerualjetwork-4.2.
|
23
|
-
pyerualjetwork-4.2.
|
24
|
-
pyerualjetwork-4.2.
|
21
|
+
pyerualjetwork-4.2.1.dist-info/METADATA,sha256=1kq1oOOpZna0dDry5QSj3L8odHpHG73rf6KRbBHpE4o,7912
|
22
|
+
pyerualjetwork-4.2.1.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
|
23
|
+
pyerualjetwork-4.2.1.dist-info/top_level.txt,sha256=BRyt62U_r3ZmJpj-wXNOoA345Bzamrj6RbaWsyW4tRg,15
|
24
|
+
pyerualjetwork-4.2.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|