Skip to content

Commit b79273c

Browse files
authored
Update README.md
1 parent 5338ae9 commit b79273c

File tree

1 file changed

+88
-44
lines changed

1 file changed

+88
-44
lines changed

README.md

Lines changed: 88 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# GeneticAlgorithmPython
2-
32
**GeneticAlgorithmPython** is an open source Python project for implementing the genetic algorithm based on NumPy. Based on this project, a Python library named [`PyGAD`](https://pypi.org/project/pygad) is available at PyPI: https://pypi.org/project/pygad. To install PyGAD using pip, just issue this command:
43

54
```python
@@ -17,12 +16,13 @@ The documentation starts by discussing the available parameters in addition to t
1716
The single module available in the `PyGAD` library is named `pygad.py` and contains a class named `GA`. For creating an instance of this class, there are a number of parameters that allows the user to customize the genetic algorithm. Before running the GA, the parameters must be prepared. The list of all supported parameters is as follows:
1817

1918
- `num_generations` : Number of generations.
20-
- `sol_per_pop` : Number of solutions (i.e. chromosomes) within the population.
2119
- `num_parents_mating ` : Number of solutions to be selected as parents.
20+
- `fitness_func` : Accepts a function that must accept 2 parameters (a single solution and its index in the population) and return the fitness value of the solution. Available starting from [PyGAD](https://pypi.org/project/pygad) 1.0.17 until 1.0.20 with a single parameter representing the solution. Changed in [PyGAD](https://pypi.org/project/pygad) 2.0.0 and higher to include the second parameter representing the solution index.
21+
- `initial_population`: A user-defined initial population. It is useful when the user wants to start the generations with a custom initial population. It defaults to `None` which means no initial population is specified by the user. In this case, [**PyGAD**](https://pypi.org/project/pygad) creates an initial population using the `sol_per_pop` and `num_genes` parameters. An exception is raised if the `initial_population` is `None` while any of the 2 parameters (`sol_per_pop` or `num_genes`) is also `None`. Introduced in PyGAD 2.0.0 and higher.
22+
- `sol_per_pop` : Number of solutions (i.e. chromosomes) within the population.
2223
- `num_genes`: Number of genes in the solution/chromosome.
23-
- `fitness_func` : A function for calculating the fitness value for each solution. Added in PyGAD 1.0.17.
24-
- `init_range_low=-4`: The lower value of the random range from which the gene values in the initial population are selected. `init_range_low` defaults to `-4`. Added in PyGAD 1.0.18.
25-
- `init_range_high=4`: The upper value of the random range from which the gene values in the initial population are selected. `init_range_high` defaults to `+4`. Added in PyGAD 1.0.18.
24+
- `init_range_low=-4`: The lower value of the random range from which the gene values in the initial population are selected. `init_range_low` defaults to `-4`. Available in [PyGAD](https://pypi.org/project/pygad) 1.0.20 and higher.
25+
- `init_range_high=4`: The upper value of the random range from which the gene values in the initial population are selected. `init_range_high` defaults to `+4`. Available in [PyGAD](https://pypi.org/project/pygad) 1.0.20 and higher.
2626
- `parent_selection_type="sss"` : The parent selection type. Supported types are `sss` (for steady state selection), `rws` (for roulette wheel selection), `sus` (for stochastic universal selection), `rank` (for rank selection), `random` (for random selection), and `tournament` (for tournament selection).
2727
- `keep_parents=-1` : Number of parents to keep in the current population. `-1` (default) means keep all parents in the next population. `0` means keep no parents in the next population. A value `greater than 0` means keep the specified number of parents in the next population. Note that the value assigned to `keep_parents` cannot be `< - 1` or greater than the number of solutions within the population `sol_per_pop`.
2828
- `K_tournament=3` : In case that the parent selection type is `tournament`, the `K_tournament` specifies the number of parents participating in the tournament selection. It defaults to `3`.
@@ -32,11 +32,27 @@ The single module available in the `PyGAD` library is named `pygad.py` and conta
3232
- `mutation_num_genes=None` : Number of genes to mutate which defaults to `None` meaning that no number is specified. If the parameter `mutation_num_genes` exists, then no need for the parameter `mutation_percent_genes`.
3333
- `random_mutation_min_val=-1.0` : For `random` mutation, the `random_mutation_min_val` parameter specifies the start value of the range from which a random value is selected to be added to the gene. It defaults to `-1`.
3434
- `random_mutation_max_val=1.0` : For `random` mutation, the `random_mutation_max_val` parameter specifies the end value of the range from which a random value is selected to be added to the gene. It defaults to `+1`.
35+
- `callback_generation`: If not `None`, then it accepts a function to be called after each generation. This function must accept a **single parameter** representing the instance of the genetic algorithm.
3536

3637
The user doesn't have to specify all of such parameters while creating an instance of the GA class. A very important parameter you must care about is `fitness_func` which defines the fitness function.
3738

3839
It is OK to set the value of any of the 2 parameters `init_range_low` and `init_range_high` to be equal, higher or lower than the other parameter (i.e. `init_range_low` is not needed to be lower than `init_range_high`).
3940

41+
## Instance Attributes
42+
43+
All the parameters and functions passed to the GA class constructor are used as attributes and methods in the instances of the GA class. In addition to such attributes, there are other attributes and methods added to the instances of the GA class which are:
44+
45+
- `generations_completed`: Holds the number of the last completed generation.
46+
- `population`: A NumPy array holding the initial population.
47+
- `valid_parameters`: Set to `True` when all the parameters passed in the `GA` class constructor are valid.
48+
- `run_completed`: Set to `True` only after the `run()` method completes gracefully.
49+
- `pop_size`: The population size.
50+
- `crossover`: Refers to the method that applies the crossover operator based on the selected type of crossover in the `crossover_type` property.
51+
- `mutation`: Refers to the method that applies the mutation operator based on the selected type of mutation in the `mutation_type` property.
52+
- `select_parents`: Refers to a method that selects the parents based on the parent selection type specified in the `parent_selection_type` attribute.
53+
- `best_solution_fitness`: A list holding the fitness value of the best solution for each generation.
54+
- `cal_pop_fitness`: A method that calculates the fitness values for all solutions within the population by calling the function passed to the `fitness_func` parameter for each solution.
55+
4056
Next, the steps of using the PyGAD library are discussed.
4157

4258
## How to Use the PyGAD?
@@ -58,27 +74,32 @@ Let's discuss how to do each of these steps.
5874

5975
Even there are a number of steps in the genetic algorithm pipeline that can work the same regardless of the problem being solved, one critical step is the calculation of the fitness value. There is no unique way of calculating the fitness value and it changes from one problem to another.
6076

61-
On **`15 April 2020`**, a new argument named `fitness_func` is added that allows the user to specify a custom function to be used as a fitness function. This function must be a **maximization function** so that a solution with a high fitness value returned is selected compared to a solution with a low value. Doing that allows the user to freely use the library to solve any problem by passing the appropriate fitness function.
77+
On **`15 April 2020`**, a new argument named `fitness_func` is added to PyGAD 1.0.17 that allows the user to specify a custom function to be used as a fitness function. This function must be a **maximization function** so that a solution with a high fitness value returned is selected compared to a solution with a low value. Doing that allows the user to freely use the library to solve any problem by passing the appropriate fitness function.
6278

6379
Let's discuss an example:
6480

6581
> Given the following function:
66-
> y = f(w1:w6) = w1x1 + w2x2 + w3x3 + w4x4 + w5x5 + 6wx6
67-
> where (x1,x2,x3,x4,x5,x6)=(4,-2,3.5,5,-11,-4.7) and y=44
82+
> y = f(w1:w6) = w1x1 + w2x2 + w3x3 + w4x4 + w5x5 + 6wx6
83+
> where (x1,x2,x3,x4,x5,x6)=(4,-2,3.5,5,-11,-4.7) and y=44
6884
> What are the best values for the 6 weights (w1 to w6)? We are going to use the genetic algorithm to optimize this function.
6985
70-
So, the task is about using the genetic algorithm to find the best values for the 6 weight `W1` to `W6`. Thinking of the problem, it is clear that the best solution is that returning an output that is close to the desired output `y=44`. So, the fitness function should return a value that gets higher when the solution's output is closer to `y=44`. Here is a function that does that. The function must accept a single parameter which is a 1D vector representing a single solution.
86+
So, the task is about using the genetic algorithm to find the best values for the 6 weight `W1` to `W6`. Thinking of the problem, it is clear that the best solution is that returning an output that is close to the desired output `y=44`. So, the fitness function should return a value that gets higher when the solution's output is closer to `y=44`. Here is a function that does that:
7187

7288
```python
7389
function_inputs = [4,-2,3.5,5,-11,-4.7] # Function inputs.
7490
desired_output = 44 # Function output.
7591

76-
def fitness_func(solution):
92+
def fitness_func(solution, solution_idx):
7793
output = numpy.sum(solution*function_inputs)
7894
fitness = 1.0 / numpy.abs(output - desired_output)
7995
return fitness
8096
```
8197

98+
The function must accept 2 parameters:
99+
100+
1. 1D vector representing a single solution. Introduced in PyGAD 1.0.17 and higher.
101+
2. Solution index within the population. Introduced in PyGAD 2.0.0 and higher.
102+
82103
By creating this function, you are ready to use the library.
83104

84105
### Example of Preparing the Parameters
@@ -87,23 +108,41 @@ Here is an example for preparing the parameters:
87108

88109
```python
89110
num_generations = 50
90-
sol_per_pop = 8
91111
num_parents_mating = 4
92112

113+
fitness_function = fitness_func
114+
115+
sol_per_pop = 8
116+
num_genes = len(function_inputs)
117+
93118
init_range_low = -2
94119
init_range_high = 5
95120

96-
mutation_percent_genes = 10
97-
98121
parent_selection_type = "sss"
122+
keep_parents = 1
99123

100124
crossover_type = "single_point"
101125

102126
mutation_type = "random"
127+
mutation_percent_genes = 10
128+
```
103129

104-
keep_parents = 1
130+
#### Optional `callback_generation` Parameter
105131

106-
num_genes = len(function_inputs)
132+
In PyGAD 2.0.0 and higher, an optional parameter named `callback_generation` is supported which allow the user to call a function (with a single parameter) after each generation. Here is a simple function that just prints the current generation number and the fitness value of the best solution in the current generation. The `generations_completed` attribute of the GA class returns the number of the last completed generation.
133+
134+
```python
135+
def callback_gen(ga_instance):
136+
print("Generation : ", ga_instance.generations_completed)
137+
print("Fitness of the best solution :", ga_instance.best_solution()[1])
138+
```
139+
140+
After being defined, the function is assigned to the `callback_generation` parameter of the GA class constructor. By doing that, the `callback_gen()` function will be called after each generation.
141+
142+
```python
143+
ga_instance = pygad.GA(...,
144+
callback_generation=callback_gen,
145+
...)
107146
```
108147

109148
After the parameters are prepared, we can import the `pygad` module and build an instance of the GA class.
@@ -123,20 +162,18 @@ This module has a class named `GA` which holds the implementation of all methods
123162
The `GA` class is instantiated where the previously prepared parameters are fed to its constructor. The constructor is responsible for creating the initial population.
124163

125164
```python
126-
ga_instance = ga.GA(num_generations=num_generations,
127-
sol_per_pop=sol_per_pop,
128-
num_parents_mating=num_parents_mating,
129-
num_genes=num_genes,
130-
fitness_func=fitness_func,
131-
init_range_low=init_range_low,
132-
init_range_high=init_range_high,
133-
mutation_percent_genes=mutation_percent_genes,
134-
mutation_num_genes=mutation_num_genes,
135-
parent_selection_type=parent_selection_type,
136-
crossover_type=crossover_type,
137-
mutation_type=mutation_type,
138-
keep_parents=keep_parents,
139-
K_tournament=3)
165+
ga_instance = pygad.GA(num_generations=num_generations,
166+
num_parents_mating=num_parents_mating,
167+
fitness_func=fitness_function,
168+
sol_per_pop=sol_per_pop,
169+
num_genes=num_genes,
170+
init_range_low=init_range_low,
171+
init_range_high=init_range_high,
172+
parent_selection_type=parent_selection_type,
173+
keep_parents=keep_parents,
174+
crossover_type=crossover_type,
175+
mutation_type=mutation_type,
176+
mutation_percent_genes=mutation_percent_genes)
140177
```
141178

142179
### Run the Genetic Algorithm
@@ -178,7 +215,7 @@ You can also load the saved model using the `load()` function and continue using
178215

179216
```python
180217
# Loading the saved GA instance.
181-
loaded_ga_instance = ga.load(filename=filename)
218+
loaded_ga_instance = pygad.load(filename=filename)
182219
```
183220

184221
After the instance is loaded, you can use it to run any method or access any property.
@@ -193,25 +230,25 @@ The library supports different types for selecting the parents and applying the
193230

194231
The supported crossover operations at this time are:
195232

196-
- Single point.
197-
- Two points.
198-
- Uniform.
233+
- Single point: Implemented using the `single_point_crossover()` method.
234+
- Two points: Implemented using the `two_points_crossover()` method.
235+
- Uniform: Implemented using the `uniform_crossover()` method.
199236

200237
The supported mutation operations at this time are:
201238

202-
- Random
203-
- Swap
204-
- Inversion
205-
- Scramble
239+
- Random: Implemented using the `random_mutation()` method.
240+
- Swap: Implemented using the `swap_mutation()` method.
241+
- Inversion: Implemented using the `inversion_mutation()` method.
242+
- Scramble: Implemented using the `scramble_mutation()` method.
206243

207244
The supported parent selection techniques at this time are:
208245

209-
- Steady state
210-
- Roulette wheel
211-
- Stochastic universal
212-
- Rank
213-
- Random
214-
- Tournament
246+
- Steady state: Implemented using the `steady_state_selection()` method.
247+
- Roulette wheel: Implemented using the `roulette_wheel_selection()` method.
248+
- Stochastic universal: Implemented using the `stochastic_universal_selection()` method.
249+
- Rank: Implemented using the `rank_selection()` method.
250+
- Random: Implemented using the `random_selection()` method.
251+
- Tournament: Implemented using the `tournament_selection()` method.
215252

216253
More types will be added in the future. You can also ask for supporting more types by opening an issue in the [GitHub project](https://github.com/ahmedfgad/GeneticAlgorithmPython) associated with the library: https://github.com/ahmedfgad/GeneticAlgorithmPython
217254

@@ -221,13 +258,20 @@ PyGAD 1.0.17 (15 April 2020):
221258

222259
1. The `GA` class accepts a new argument named `fitness_func` which accepts a function to be used for calculating the fitness values for the solutions. This allows the project to be customized to any problem by building the right fitness function.
223260

224-
PyGAD 1.0.18 (4 May 2020):
261+
PyGAD 1.0.20 (4 May 2020):
225262

226263
1. The attributes are moved from the class scope to the instance scope.
227264
2. Raising a `ValueError` exception on passing incorrect values to the parameters.
228265
3. Two new parameters are added (`init_range_low` and `init_range_high`) allowing the user to customize the range from which the genes values in the initial population are selected.
229266
4. The code object `__code__` of the passed fitness function is checked to ensure it has the right number of parameters.
230267

268+
PyGAD 2.0.0 (13 May 2020)
269+
270+
1. The fitness function accepts a new argument named `sol_idx` representing the index of the solution within the population.
271+
2. A new parameter to the GA constructor named `initial_population` is supported to allow the user to use a custom initial population to be used by the genetic algorithm. If not None, then the passed population will be used. If `None`, then the genetic algorithm will create the initial population using the `sol_per_pop` and `num_genes` parameters.
272+
3. The parameters `sol_per_pop` and `num_genes` are optional and set to `None` by default.
273+
4. A new parameter named `callback_generation` is introduced in the GA class constructor. It accepts a function with a single parameter representing the GA instance. This function called after each generation. This helps the user to do post-processing or debugging operations after each generation.
274+
231275
## For More Information
232276

233277
To start with coding the genetic algorithm, you can check the tutorial titled [**Genetic Algorithm Implementation in Python**](https://www.linkedin.com/pulse/genetic-algorithm-implementation-python-ahmed-gad) available at these links:

0 commit comments

Comments
 (0)