Skip to content
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

Add parameter count adjustment for functions that are class methods #92

Merged
merged 2 commits into from Feb 20, 2023

Conversation

richmr
Copy link
Contributor

@richmr richmr commented Mar 9, 2022

Hi, I am using PyGAD.GA inside of another class. The various functions PyGAD will accept as parameters have strict parameter count checks. However, when you assign a class method to these functions they get an extra "self" parameter assigned to them. PyGAD then interprets these extra self parameters as improperly constructed functions.

Using the "inspect" module I have added a check to see if an assigned function is actually a method. If so, it then adds one to the expected parameter count. This allows these methods to be used as contributing functions. This, in turn, permits more well-formatted object oriented code to be used when desired. Users can still assign non-class functions to these parameters and the code will accept them.

I am using this in my current experiments and it is working well.

Thanks for your time!

Mike

@mschrader15
Copy link

Bumping this. Would be really nice to have!

@richmr
Copy link
Contributor Author

richmr commented Oct 28, 2022

It does prevent PyGAD "save" function from working due to pickle issue, I discovered after submission. I did not correct that issue since I don't use "save". I see jack89roberts comment but I am not having any issues with a wide variety of fitness functions myself.

@mschrader15
Copy link

mschrader15 commented Oct 28, 2022

We built a hacky solution for >2 arguments by saving the other arguments to a common temporary file and using a closure, but the class based method is ultimately what we want. I'll fork from your branch for the time being!

@richmr
Copy link
Contributor Author

richmr commented Oct 28, 2022 via email

@ahmedfgad
Copy link
Owner

Thanks @richmr. This is a useful feature.

@ahmedfgad ahmedfgad merged commit fcf5d07 into ahmedfgad:master Feb 20, 2023
@richmr
Copy link
Contributor Author

richmr commented Feb 21, 2023 via email

ahmedfgad added a commit that referenced this pull request Feb 22, 2023
PyGAD 2.19.0 Release Notes
1. A new `summary()` method is supported to return a Keras-like summary of the PyGAD lifecycle.
2. A new optional parameter called `fitness_batch_size` is supported to calculate the fitness function in batches. If it is assigned the value `1` or `None` (default), then the normal flow is used where the fitness function is called for each individual solution. If the `fitness_batch_size` parameter is assigned a value satisfying this condition `1 < fitness_batch_size <= sol_per_pop`, then the solutions are grouped into batches of size `fitness_batch_size` and the fitness function is called once for each batch. In this case, the fitness function must return a list/tuple/numpy.ndarray with a length equal to the number of solutions passed. #136.
3. The `cloudpickle` library (https://github.com/cloudpipe/cloudpickle) is used instead of the `pickle` library to pickle the `pygad.GA` objects. This solves the issue of having to redefine the functions (e.g. fitness function). The `cloudpickle` library is added as a dependancy in the `requirements.txt` file. #159
4. Support of assigning methods to these parameters: `fitness_func`, `crossover_type`, `mutation_type`, `parent_selection_type`, `on_start`, `on_fitness`, `on_parents`, `on_crossover`, `on_mutation`, `on_generation`, and `on_stop`. #92 #138
5. Validating the output of the parent selection, crossover, and mutation functions.
6. The built-in parent selection operators return the parent's indices as a NumPy array.
7. The outputs of the parent selection, crossover, and mutation operators must be NumPy arrays.
8. Fix an issue when `allow_duplicate_genes=True`. #39
9. Fix an issue creating scatter plots of the solutions' fitness.
10. Sampling from a `set()` is no longer supported in Python 3.11. Instead, sampling happens from a `list()`. Thanks `Marco Brenna` for pointing to this issue.
11. The lifecycle is updated to reflect that the new population's fitness is calculated at the end of the lifecycle not at the beginning. #154 (comment)
12. There was an issue when `save_solutions=True` that causes the fitness function to be called for solutions already explored and have their fitness pre-calculated. #160
13. A new instance attribute named `last_generation_elitism_indices` added to hold the indices of the selected elitism. This attribute helps to re-use the fitness of the elitism instead of calling the fitness function.
14. Fewer calls to the `best_solution()` method which in turns saves some calls to the fitness function.
15. Some updates in the documentation to give more details about the `cal_pop_fitness()` method. #79 (comment)
@whubaichuan
Copy link

@ahmedfgad hi, could you please share a code example for the 4th update in Pygad 2.19.0 Release? Is there any relationship to the class instance or class method? I am confused about this function but I am interested.

@richmr
Copy link
Contributor Author

richmr commented Feb 25, 2023

If you are referring to this pull, all that was added was the ability to use class methods ("def method(self):" in a class) to be the assigned callback functions for fitness, generation, etc. You can still assign flat functions (not defined in a class) as well. I use class methods for all my pygad callbacks.

@ahmedfgad ahmedfgad added the enhancement New feature or request label Feb 25, 2023
ahmedfgad added a commit that referenced this pull request Apr 8, 2023
PyGAD 3.0.0 Release Notes
1. The structure of the library is changed and some methods defined in the `pygad.py` module are moved to the `pygad.utils`, `pygad.helper`, and `pygad.visualize` submodules.
  2. The `pygad.utils.parent_selection` module has a class named `ParentSelection` where all the parent selection operators exist. The `pygad.GA` class extends this class.
  3. The `pygad.utils.crossover` module has a class named `Crossover` where all the crossover operators exist. The `pygad.GA` class extends this class.
  4. The `pygad.utils.mutation` module has a class named `Mutation` where all the mutation operators exist. The `pygad.GA` class extends this class.
  5. The `pygad.helper.unique` module has a class named `Unique` some helper methods exist to solve duplicate genes and make sure every gene is unique. The `pygad.GA` class extends this class.
  6. The `pygad.visualize.plot` module has a class named `Plot` where all the methods that create plots exist. The `pygad.GA` class extends this class.

```python
...
class GA(utils.parent_selection.ParentSelection,
         utils.crossover.Crossover,
         utils.mutation.Mutation,
         helper.unique.Unique,
         visualize.plot.Plot):
...
```

2. Support of using the `logging` module to log the outputs to both the console and text file instead of using the `print()` function. This is by assigning the `logging.Logger` to the new `logger` parameter. Check the [Logging Outputs](https://pygad.readthedocs.io/en/latest/README_pygad_ReadTheDocs.html#logging-outputs) for more information.
3. A new instance attribute called `logger` to save the logger.
4. The function/method passed to the `fitness_func` parameter accepts a new parameter that refers to the instance of the `pygad.GA` class. Check this for an example: [Use Functions and Methods to Build Fitness Function and Callbacks](https://pygad.readthedocs.io/en/latest/README_pygad_ReadTheDocs.html#use-functions-and-methods-to-build-fitness-and-callbacks). #163
5. Update the documentation to include an example of using functions and methods to calculate the fitness and build callbacks. Check this for more details: [Use Functions and Methods to Build Fitness Function and Callbacks](https://pygad.readthedocs.io/en/latest/README_pygad_ReadTheDocs.html#use-functions-and-methods-to-build-fitness-and-callbacks). #92 (comment)
6. Validate the value passed to the `initial_population` parameter.
7. Validate the type and length of the `pop_fitness` parameter of the `best_solution()` method.
8. Some edits in the documentation. #106
9. Fix an issue when building the initial population as (some) genes have their value taken from the mutation range (defined by the parameters `random_mutation_min_val` and `random_mutation_max_val`) instead of using the parameters `init_range_low` and `init_range_high`.
10. The `summary()` method returns the summary as a single-line string. Just log/print the returned string it to see it properly.
11. The `callback_generation` parameter is removed. Use the `on_generation` parameter instead.
12. There was an issue when using the `parallel_processing` parameter with Keras and PyTorch. As Keras/PyTorch are not thread-safe, the `predict()` method gives incorrect and weird results when more than 1 thread is used. #145 ahmedfgad/TorchGA#5 ahmedfgad/KerasGA#6. Thanks to this [StackOverflow answer](https://stackoverflow.com/a/75606666/5426539).
13. Replace `numpy.float` by `float` in the 2 parent selection operators roulette wheel and stochastic universal. #168
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants