Skip to content

GitHub actions #191

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
37 changes: 37 additions & 0 deletions .github/workflows/main_py311.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Testing PyGAD using PyTest

on:
push:
branches:
- github-actions
# - master

jobs:
job_id_1:
runs-on: ubuntu-latest
name: PyTest Workflow Job

steps:
- name: Checkout Pre-Built Action
uses: actions/checkout@v3

- name: Setup Python 3.11
uses: actions/setup-python@v4
with:
python-version: '3.11'

- name: Build PyGAD from the Repository
run: |
python3 -m pip install --upgrade build
python3 -m build

- name: Install PyGAD after Building the .whl File
run: |
find ./dist/*.whl | xargs pip install

- name: Install PyTest
run: pip install pytest

- name: Run the Tests by Calling PyTest
run: |
pytest
37 changes: 37 additions & 0 deletions .github/workflows/main_py37.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Testing PyGAD using PyTest

on:
push:
branches:
- github-actions
# - master

jobs:
job_id_1:
runs-on: ubuntu-20.04
name: PyTest Workflow Job

steps:
- name: Checkout Pre-Built Action
uses: actions/checkout@v3

- name: Setup Python 3.7
uses: actions/setup-python@v4
with:
python-version: '3.7'

- name: Build PyGAD from the Repository
run: |
python3 -m pip install --upgrade build
python3 -m build

- name: Install PyGAD after Building the .whl File
run: |
find ./dist/*.whl | xargs pip install

- name: Install PyTest
run: pip install pytest

- name: Run the Tests by Calling PyTest
run: |
pytest
37 changes: 37 additions & 0 deletions .github/workflows/main_py38.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Testing PyGAD using PyTest

on:
push:
branches:
- github-actions
# - master

jobs:
job_id_1:
runs-on: ubuntu-latest
name: PyTest Workflow Job

steps:
- name: Checkout Pre-Built Action
uses: actions/checkout@v3

- name: Setup Python 3.8
uses: actions/setup-python@v4
with:
python-version: '3.8'

- name: Build PyGAD from the Repository
run: |
python3 -m pip install --upgrade build
python3 -m build

- name: Install PyGAD after Building the .whl File
run: |
find ./dist/*.whl | xargs pip install

- name: Install PyTest
run: pip install pytest

- name: Run the Tests by Calling PyTest
run: |
pytest
37 changes: 37 additions & 0 deletions .github/workflows/main_py39.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Testing PyGAD using PyTest

on:
push:
branches:
- github-actions
# - master

jobs:
job_id_1:
runs-on: ubuntu-latest
name: PyTest Workflow Job

steps:
- name: Checkout Pre-Built Action
uses: actions/checkout@v3

- name: Setup Python 3.9
uses: actions/setup-python@v4
with:
python-version: '3.9'

- name: Build PyGAD from the Repository
run: |
python3 -m pip install --upgrade build
python3 -m build

- name: Install PyGAD after Building the .whl File
run: |
find ./dist/*.whl | xargs pip install

- name: Install PyTest
run: pip install pytest

- name: Run the Tests by Calling PyTest
run: |
pytest
22 changes: 11 additions & 11 deletions pygad/cnn/cnn.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def layers_weights(model, initial=True):
elif initial == False:
network_weights.append(layer.trained_weights)
else:
raise ValueError("Unexpected value to the 'initial' parameter: {initial}.".format(initial=initial))
raise ValueError(f"Unexpected value to the 'initial' parameter: {initial}.")

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

# Go to the previous layer.
layer = layer.previous_layer
Expand Down Expand Up @@ -214,7 +214,7 @@ def __init__(self, input_shape):

# If the input sample has less than 2 dimensions, then an exception is raised.
if len(input_shape) < 2:
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)))
raise ValueError(f"The Input2D class creates an input layer for data inputs with at least 2 dimensions but ({len(input_shape)}) dimensions found.")
# If the input sample has exactly 2 dimensions, the third dimension is set to 1.
elif len(input_shape) == 2:
input_shape = (input_shape[0], input_shape[1], 1)
Expand Down Expand Up @@ -261,7 +261,7 @@ def __init__(self, num_filters, kernel_size, previous_layer, activation_function
elif (activation_function == "softmax"):
raise ValueError("The softmax activation function cannot be used in a conv layer.")
else:
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))
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.")

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

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

if pool_size <= 0:
raise ValueError("The passed value to the pool_size parameter cannot be <= 0.")
Expand Down Expand Up @@ -642,7 +642,7 @@ def __init__(self, num_neurons, previous_layer, activation_function="relu"):
elif (activation_function == "softmax"):
self.activation = softmax
else:
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))
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.")

self.activation_function = activation_function

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

if type(self.previous_layer.layer_output_size) in [list, tuple, numpy.ndarray] and len(self.previous_layer.layer_output_size) > 1:
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)))
raise ValueError(f"The input to the dense layer must be of type int but {type(self.previous_layer.layer_output_size)} found.")
# Initializing the weights of the layer.
self.initial_weights = numpy.random.uniform(low=-0.1,
high=0.1,
Expand Down Expand Up @@ -741,13 +741,13 @@ def train(self, train_inputs, train_outputs):
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))

if (train_inputs.shape[0] != len(train_outputs)):
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)))
raise ValueError(f"Mismatch between the number of input samples and number of labels: {train_inputs.shape[0]} != {len(train_outputs)}.")

network_predictions = []
network_error = 0

for epoch in range(self.epochs):
print("Epoch {epoch}".format(epoch=epoch))
print(f"Epoch {epoch}")
for sample_idx in range(train_inputs.shape[0]):
# print("Sample {sample_idx}".format(sample_idx=sample_idx))
self.feed_sample(train_inputs[sample_idx, :])
Expand Down Expand Up @@ -797,7 +797,7 @@ def feed_sample(self, sample):
pass
else:
print("Other")
raise TypeError("The layer of type {layer_type} is not supported yet.".format(layer_type=type(layer)))
raise TypeError("The layer of type {type(layer)} is not supported yet.")

last_layer_outputs = layer.layer_output
return self.network_layers[-1].layer_output
Expand Down Expand Up @@ -828,7 +828,7 @@ def predict(self, data_inputs):
"""

if (data_inputs.ndim != 4):
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))
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.")

predictions = []
for sample in data_inputs:
Expand Down
18 changes: 9 additions & 9 deletions pygad/gann/gann.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,22 @@ def validate_network_parameters(num_neurons_input,
# Validating the number of solutions within the population.
if not (num_solutions is None):
if num_solutions < 2:
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))
raise ValueError(f"num_solutions: The number of solutions within the population must be at least 2. The current value is {num_solutions}.")

# Validating the number of neurons in the input layer.
if num_neurons_input is int and num_neurons_input <= 0:
raise ValueError("num_neurons_input: The number of neurons in the input layer must be > 0.")

# Validating the number of neurons in the output layer.
if num_neurons_output is int and num_neurons_output <= 0:
raise ValueError("num_neurons_output: The number of neurons in the output layer must be > 0.")

# Validating the type of the 'num_neurons_hidden_layers' parameter which is expected to be list or tuple.
if not (type(num_neurons_hidden_layers) in [list, tuple]):
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)))
raise TypeError(f"num_neurons_hidden_layers: A list or a tuple is expected but {type(num_neurons_hidden_layers)} found.")

# Frequently used error messages.
unexpected_output_activation_value = "Output activation function: The activation function of the output layer is passed as a string not {activation_type}."
unexpected_output_activation_value = f"Output activation function: The activation function of the output layer is passed as a string not {type(output_activation)}."
unexpected_activation_value = "Activation function: The supported values for the activation function are {supported_activations} but an unexpected value is found:\n{activations}"
unexpected_activation_type = "Activation Function: A list, tuple, or a string is expected but {activations_type} found."
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}"
Expand All @@ -51,7 +51,7 @@ def validate_network_parameters(num_neurons_input,

# Validating the output layer activation function.
if not (type(output_activation) is str):
raise ValueError(unexpected_output_activation_value.format(activation_type=type(output_activation)))
raise ValueError(unexpected_output_activation_value)
if not (output_activation in supported_activations): #activation_type
raise ValueError(unexpected_activation_value.format(activations=output_activation, supported_activations=supported_activations))

Expand Down Expand Up @@ -81,9 +81,9 @@ def validate_network_parameters(num_neurons_input,
else:
raise TypeError(unexpected_activation_type.format(activations_type=type(hidden_activations)))
else: # In case there are no hidden layers (num_hidden_layers == 0)
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))
print("WARNING: There are no hidden layers however a value is assigned to the parameter 'hidden_activations'. It will be reset to [].")
hidden_activations = []

# 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.
for act in hidden_activations:
if not (act in supported_activations):
Expand Down
10 changes: 5 additions & 5 deletions pygad/helper/unique.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def solve_duplicate_genes_randomly(self,

if temp_val in new_solution and trial_index == (num_trials - 1):
num_unsolved_duplicates = num_unsolved_duplicates + 1
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]))
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.")
elif temp_val in new_solution:
continue
else:
Expand All @@ -105,7 +105,7 @@ def solve_duplicate_genes_randomly(self,
# self.logger.info("not_unique_indices INSIDE", not_unique_indices)

return new_solution, not_unique_indices, num_unsolved_duplicates

def solve_duplicate_genes_by_space(self,
solution,
gene_type,
Expand Down Expand Up @@ -230,7 +230,7 @@ def unique_int_gene_from_range(self,
all_gene_values = numpy.asarray(all_gene_values,
gene_type[gene_index][0])

values_to_select_from = list(set(all_gene_values) - set(solution))
values_to_select_from = list(set(list(all_gene_values)) - set(solution))

if len(values_to_select_from) == 0:
# If there is no values, then keep the current gene value.
Expand Down Expand Up @@ -274,7 +274,7 @@ def unique_genes_by_space(self,
if temp_val in new_solution and trial_index == (num_trials - 1):
# self.logger.info("temp_val, duplicate_index", temp_val, duplicate_index, new_solution)
num_unsolved_duplicates = num_unsolved_duplicates + 1
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]))
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.")
elif temp_val in new_solution:
continue
else:
Expand Down Expand Up @@ -451,7 +451,7 @@ def unique_gene_by_space(self,
# If the gene space has only 1 value, then select it. The old and new values of the gene are identical.
if len(curr_gene_space) == 1:
value_from_space = curr_gene_space[0]
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))
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.")
# If the gene space has more than 1 value, then select a new one that is different from the current value.
else:
values_to_select_from = list(set(curr_gene_space) - set(solution))
Expand Down
Loading