Skip to content

Commit 7174771

Browse files
authored
Merge pull request #191 from ahmedfgad/github-actions
GitHub actions
2 parents fcca50c + 431b81a commit 7174771

File tree

11 files changed

+758
-46
lines changed

11 files changed

+758
-46
lines changed
File renamed without changes.

.github/workflows/main_py311.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Testing PyGAD using PyTest
2+
3+
on:
4+
push:
5+
branches:
6+
- github-actions
7+
# - master
8+
9+
jobs:
10+
job_id_1:
11+
runs-on: ubuntu-latest
12+
name: PyTest Workflow Job
13+
14+
steps:
15+
- name: Checkout Pre-Built Action
16+
uses: actions/checkout@v3
17+
18+
- name: Setup Python 3.11
19+
uses: actions/setup-python@v4
20+
with:
21+
python-version: '3.11'
22+
23+
- name: Build PyGAD from the Repository
24+
run: |
25+
python3 -m pip install --upgrade build
26+
python3 -m build
27+
28+
- name: Install PyGAD after Building the .whl File
29+
run: |
30+
find ./dist/*.whl | xargs pip install
31+
32+
- name: Install PyTest
33+
run: pip install pytest
34+
35+
- name: Run the Tests by Calling PyTest
36+
run: |
37+
pytest

.github/workflows/main_py37.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Testing PyGAD using PyTest
2+
3+
on:
4+
push:
5+
branches:
6+
- github-actions
7+
# - master
8+
9+
jobs:
10+
job_id_1:
11+
runs-on: ubuntu-20.04
12+
name: PyTest Workflow Job
13+
14+
steps:
15+
- name: Checkout Pre-Built Action
16+
uses: actions/checkout@v3
17+
18+
- name: Setup Python 3.7
19+
uses: actions/setup-python@v4
20+
with:
21+
python-version: '3.7'
22+
23+
- name: Build PyGAD from the Repository
24+
run: |
25+
python3 -m pip install --upgrade build
26+
python3 -m build
27+
28+
- name: Install PyGAD after Building the .whl File
29+
run: |
30+
find ./dist/*.whl | xargs pip install
31+
32+
- name: Install PyTest
33+
run: pip install pytest
34+
35+
- name: Run the Tests by Calling PyTest
36+
run: |
37+
pytest

.github/workflows/main_py38.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Testing PyGAD using PyTest
2+
3+
on:
4+
push:
5+
branches:
6+
- github-actions
7+
# - master
8+
9+
jobs:
10+
job_id_1:
11+
runs-on: ubuntu-latest
12+
name: PyTest Workflow Job
13+
14+
steps:
15+
- name: Checkout Pre-Built Action
16+
uses: actions/checkout@v3
17+
18+
- name: Setup Python 3.8
19+
uses: actions/setup-python@v4
20+
with:
21+
python-version: '3.8'
22+
23+
- name: Build PyGAD from the Repository
24+
run: |
25+
python3 -m pip install --upgrade build
26+
python3 -m build
27+
28+
- name: Install PyGAD after Building the .whl File
29+
run: |
30+
find ./dist/*.whl | xargs pip install
31+
32+
- name: Install PyTest
33+
run: pip install pytest
34+
35+
- name: Run the Tests by Calling PyTest
36+
run: |
37+
pytest

.github/workflows/main_py39.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Testing PyGAD using PyTest
2+
3+
on:
4+
push:
5+
branches:
6+
- github-actions
7+
# - master
8+
9+
jobs:
10+
job_id_1:
11+
runs-on: ubuntu-latest
12+
name: PyTest Workflow Job
13+
14+
steps:
15+
- name: Checkout Pre-Built Action
16+
uses: actions/checkout@v3
17+
18+
- name: Setup Python 3.9
19+
uses: actions/setup-python@v4
20+
with:
21+
python-version: '3.9'
22+
23+
- name: Build PyGAD from the Repository
24+
run: |
25+
python3 -m pip install --upgrade build
26+
python3 -m build
27+
28+
- name: Install PyGAD after Building the .whl File
29+
run: |
30+
find ./dist/*.whl | xargs pip install
31+
32+
- name: Install PyTest
33+
run: pip install pytest
34+
35+
- name: Run the Tests by Calling PyTest
36+
run: |
37+
pytest

pygad/cnn/cnn.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def layers_weights(model, initial=True):
8484
elif initial == False:
8585
network_weights.append(layer.trained_weights)
8686
else:
87-
raise ValueError("Unexpected value to the 'initial' parameter: {initial}.".format(initial=initial))
87+
raise ValueError(f"Unexpected value to the 'initial' parameter: {initial}.")
8888

8989
# Go to the previous layer.
9090
layer = layer.previous_layer
@@ -164,7 +164,7 @@ def layers_weights_as_vector(model, initial=True):
164164
# vector = pygad.nn.DenseLayer.to_vector(array=layer.trained_weights)
165165
network_weights.extend(vector)
166166
else:
167-
raise ValueError("Unexpected value to the 'initial' parameter: {initial}.".format(initial=initial))
167+
raise ValueError(f"Unexpected value to the 'initial' parameter: {initial}.")
168168

169169
# Go to the previous layer.
170170
layer = layer.previous_layer
@@ -214,7 +214,7 @@ def __init__(self, input_shape):
214214

215215
# If the input sample has less than 2 dimensions, then an exception is raised.
216216
if len(input_shape) < 2:
217-
raise ValueError("The Input2D class creates an input layer for data inputs with at least 2 dimensions but ({num_dim}) dimensions found.".format(num_dim=len(input_shape)))
217+
raise ValueError(f"The Input2D class creates an input layer for data inputs with at least 2 dimensions but ({len(input_shape)}) dimensions found.")
218218
# If the input sample has exactly 2 dimensions, the third dimension is set to 1.
219219
elif len(input_shape) == 2:
220220
input_shape = (input_shape[0], input_shape[1], 1)
@@ -261,7 +261,7 @@ def __init__(self, num_filters, kernel_size, previous_layer, activation_function
261261
elif (activation_function == "softmax"):
262262
raise ValueError("The softmax activation function cannot be used in a conv layer.")
263263
else:
264-
raise ValueError("The specified activation function '{activation_function}' is not among the supported activation functions {supported_activation_functions}. Please use one of the supported functions.".format(activation_function=activation_function, supported_activation_functions=supported_activation_functions))
264+
raise ValueError(f"The specified activation function '{activation_function}' is not among the supported activation functions {supported_activation_functions}. Please use one of the supported functions.")
265265

266266
# The activation function used in the current layer.
267267
self.activation_function = activation_function
@@ -445,7 +445,7 @@ def __init__(self, pool_size, previous_layer, stride=2):
445445
"""
446446

447447
if not (type(pool_size) is int):
448-
raise ValueError("The expected type of the pool_size is int but {pool_size_type} found.".format(pool_size_type=type(pool_size)))
448+
raise ValueError(f"The expected type of the pool_size is int but {type(pool_size)} found.")
449449

450450
if pool_size <= 0:
451451
raise ValueError("The passed value to the pool_size parameter cannot be <= 0.")
@@ -642,7 +642,7 @@ def __init__(self, num_neurons, previous_layer, activation_function="relu"):
642642
elif (activation_function == "softmax"):
643643
self.activation = softmax
644644
else:
645-
raise ValueError("The specified activation function '{activation_function}' is not among the supported activation functions {supported_activation_functions}. Please use one of the supported functions.".format(activation_function=activation_function, supported_activation_functions=supported_activation_functions))
645+
raise ValueError(f"The specified activation function '{activation_function}' is not among the supported activation functions {supported_activation_functions}. Please use one of the supported functions.")
646646

647647
self.activation_function = activation_function
648648

@@ -652,7 +652,7 @@ def __init__(self, num_neurons, previous_layer, activation_function="relu"):
652652
self.previous_layer = previous_layer
653653

654654
if type(self.previous_layer.layer_output_size) in [list, tuple, numpy.ndarray] and len(self.previous_layer.layer_output_size) > 1:
655-
raise ValueError("The input to the dense layer must be of type int but {sh} found.".format(sh=type(self.previous_layer.layer_output_size)))
655+
raise ValueError(f"The input to the dense layer must be of type int but {type(self.previous_layer.layer_output_size)} found.")
656656
# Initializing the weights of the layer.
657657
self.initial_weights = numpy.random.uniform(low=-0.1,
658658
high=0.1,
@@ -741,13 +741,13 @@ def train(self, train_inputs, train_outputs):
741741
raise ValueError("The training data input has {num_dims} but it must have 4 dimensions. The first dimension is the number of training samples, the second & third dimensions represent the width and height of the sample, and the fourth dimension represents the number of channels in the sample.".format(num_dims=train_inputs.ndim))
742742

743743
if (train_inputs.shape[0] != len(train_outputs)):
744-
raise ValueError("Mismatch between the number of input samples and number of labels: {num_samples_inputs} != {num_samples_outputs}.".format(num_samples_inputs=train_inputs.shape[0], num_samples_outputs=len(train_outputs)))
744+
raise ValueError(f"Mismatch between the number of input samples and number of labels: {train_inputs.shape[0]} != {len(train_outputs)}.")
745745

746746
network_predictions = []
747747
network_error = 0
748748

749749
for epoch in range(self.epochs):
750-
print("Epoch {epoch}".format(epoch=epoch))
750+
print(f"Epoch {epoch}")
751751
for sample_idx in range(train_inputs.shape[0]):
752752
# print("Sample {sample_idx}".format(sample_idx=sample_idx))
753753
self.feed_sample(train_inputs[sample_idx, :])
@@ -797,7 +797,7 @@ def feed_sample(self, sample):
797797
pass
798798
else:
799799
print("Other")
800-
raise TypeError("The layer of type {layer_type} is not supported yet.".format(layer_type=type(layer)))
800+
raise TypeError("The layer of type {type(layer)} is not supported yet.")
801801

802802
last_layer_outputs = layer.layer_output
803803
return self.network_layers[-1].layer_output
@@ -828,7 +828,7 @@ def predict(self, data_inputs):
828828
"""
829829

830830
if (data_inputs.ndim != 4):
831-
raise ValueError("The data input has {num_dims} but it must have 4 dimensions. The first dimension is the number of training samples, the second & third dimensions represent the width and height of the sample, and the fourth dimension represents the number of channels in the sample.".format(num_dims=data_inputs.ndim))
831+
raise ValueError("The data input has {data_inputs.ndim} but it must have 4 dimensions. The first dimension is the number of training samples, the second & third dimensions represent the width and height of the sample, and the fourth dimension represents the number of channels in the sample.")
832832

833833
predictions = []
834834
for sample in data_inputs:

pygad/gann/gann.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,22 @@ def validate_network_parameters(num_neurons_input,
2626
# Validating the number of solutions within the population.
2727
if not (num_solutions is None):
2828
if num_solutions < 2:
29-
raise ValueError("num_solutions: The number of solutions within the population must be at least 2. The current value is {num_solutions}.".format(num_solutions=num_solutions))
30-
29+
raise ValueError(f"num_solutions: The number of solutions within the population must be at least 2. The current value is {num_solutions}.")
30+
3131
# Validating the number of neurons in the input layer.
3232
if num_neurons_input is int and num_neurons_input <= 0:
3333
raise ValueError("num_neurons_input: The number of neurons in the input layer must be > 0.")
3434

3535
# Validating the number of neurons in the output layer.
3636
if num_neurons_output is int and num_neurons_output <= 0:
3737
raise ValueError("num_neurons_output: The number of neurons in the output layer must be > 0.")
38-
38+
3939
# Validating the type of the 'num_neurons_hidden_layers' parameter which is expected to be list or tuple.
4040
if not (type(num_neurons_hidden_layers) in [list, tuple]):
41-
raise TypeError("num_neurons_hidden_layers: A list or a tuple is expected but {hidden_layers_neurons_type} found.".format(hidden_layers_neurons_type=type(num_neurons_hidden_layers)))
42-
41+
raise TypeError(f"num_neurons_hidden_layers: A list or a tuple is expected but {type(num_neurons_hidden_layers)} found.")
42+
4343
# Frequently used error messages.
44-
unexpected_output_activation_value = "Output activation function: The activation function of the output layer is passed as a string not {activation_type}."
44+
unexpected_output_activation_value = f"Output activation function: The activation function of the output layer is passed as a string not {type(output_activation)}."
4545
unexpected_activation_value = "Activation function: The supported values for the activation function are {supported_activations} but an unexpected value is found:\n{activations}"
4646
unexpected_activation_type = "Activation Function: A list, tuple, or a string is expected but {activations_type} found."
4747
length_mismatch = "Hidden activation functions: When passing the activation function(s) as a list or a tuple, its length must match the length of the 'num_neurons_hidden_layers' parameter but a mismatch is found:\n{mismatched_lengths}"
@@ -51,7 +51,7 @@ def validate_network_parameters(num_neurons_input,
5151

5252
# Validating the output layer activation function.
5353
if not (type(output_activation) is str):
54-
raise ValueError(unexpected_output_activation_value.format(activation_type=type(output_activation)))
54+
raise ValueError(unexpected_output_activation_value)
5555
if not (output_activation in supported_activations): #activation_type
5656
raise ValueError(unexpected_activation_value.format(activations=output_activation, supported_activations=supported_activations))
5757

@@ -81,9 +81,9 @@ def validate_network_parameters(num_neurons_input,
8181
else:
8282
raise TypeError(unexpected_activation_type.format(activations_type=type(hidden_activations)))
8383
else: # In case there are no hidden layers (num_hidden_layers == 0)
84-
print("WARNING: There are no hidden layers however a value is assigned to the parameter 'hidden_activations'. It will be reset to [].".format(hidden_activations=hidden_activations))
84+
print("WARNING: There are no hidden layers however a value is assigned to the parameter 'hidden_activations'. It will be reset to [].")
8585
hidden_activations = []
86-
86+
8787
# If the value passed to the 'hidden_activations' parameter is actually a list, then its elements are checked to make sure the listed name(s) of the activation function(s) are supported.
8888
for act in hidden_activations:
8989
if not (act in supported_activations):

pygad/helper/unique.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def solve_duplicate_genes_randomly(self,
9292

9393
if temp_val in new_solution and trial_index == (num_trials - 1):
9494
num_unsolved_duplicates = num_unsolved_duplicates + 1
95-
if not self.suppress_warnings: warnings.warn("Failed to find a unique value for gene with index {gene_idx} whose value is {gene_value}. Consider adding more values in the gene space or use a wider range for initial population or random mutation.".format(gene_idx=duplicate_index, gene_value=solution[duplicate_index]))
95+
if not self.suppress_warnings: warnings.warn(f"Failed to find a unique value for gene with index {duplicate_index} whose value is {solution[duplicate_index]}. Consider adding more values in the gene space or use a wider range for initial population or random mutation.")
9696
elif temp_val in new_solution:
9797
continue
9898
else:
@@ -105,7 +105,7 @@ def solve_duplicate_genes_randomly(self,
105105
# self.logger.info("not_unique_indices INSIDE", not_unique_indices)
106106

107107
return new_solution, not_unique_indices, num_unsolved_duplicates
108-
108+
109109
def solve_duplicate_genes_by_space(self,
110110
solution,
111111
gene_type,
@@ -230,7 +230,7 @@ def unique_int_gene_from_range(self,
230230
all_gene_values = numpy.asarray(all_gene_values,
231231
gene_type[gene_index][0])
232232

233-
values_to_select_from = list(set(all_gene_values) - set(solution))
233+
values_to_select_from = list(set(list(all_gene_values)) - set(solution))
234234

235235
if len(values_to_select_from) == 0:
236236
# If there is no values, then keep the current gene value.
@@ -274,7 +274,7 @@ def unique_genes_by_space(self,
274274
if temp_val in new_solution and trial_index == (num_trials - 1):
275275
# self.logger.info("temp_val, duplicate_index", temp_val, duplicate_index, new_solution)
276276
num_unsolved_duplicates = num_unsolved_duplicates + 1
277-
if not self.suppress_warnings: warnings.warn("Failed to find a unique value for gene with index {gene_idx} whose value is {gene_value}. Consider adding more values in the gene space or use a wider range for initial population or random mutation.".format(gene_idx=duplicate_index, gene_value=new_solution[duplicate_index]))
277+
if not self.suppress_warnings: warnings.warn(f"Failed to find a unique value for gene with index {duplicate_index} whose value is {new_solution[duplicate_index]}. Consider adding more values in the gene space or use a wider range for initial population or random mutation.")
278278
elif temp_val in new_solution:
279279
continue
280280
else:
@@ -451,7 +451,7 @@ def unique_gene_by_space(self,
451451
# If the gene space has only 1 value, then select it. The old and new values of the gene are identical.
452452
if len(curr_gene_space) == 1:
453453
value_from_space = curr_gene_space[0]
454-
if not self.suppress_warnings: warnings.warn("You set 'allow_duplicate_genes=False' but the space of the gene with index {gene_idx} has only a single value. Thus, duplicates are possible.".format(gene_idx=gene_idx))
454+
if not self.suppress_warnings: warnings.warn(f"You set 'allow_duplicate_genes=False' but the space of the gene with index {gene_idx} has only a single value. Thus, duplicates are possible.")
455455
# If the gene space has more than 1 value, then select a new one that is different from the current value.
456456
else:
457457
values_to_select_from = list(set(curr_gene_space) - set(solution))

0 commit comments

Comments
 (0)