You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+88-44Lines changed: 88 additions & 44 deletions
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,4 @@
1
1
# GeneticAlgorithmPython
2
-
3
2
**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:
4
3
5
4
```python
@@ -17,12 +16,13 @@ The documentation starts by discussing the available parameters in addition to t
17
16
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:
18
17
19
18
-`num_generations` : Number of generations.
20
-
-`sol_per_pop` : Number of solutions (i.e. chromosomes) within the population.
21
19
-`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.
22
23
-`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.
26
26
-`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).
27
27
-`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`.
28
28
-`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
32
32
-`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`.
33
33
-`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`.
34
34
-`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.
35
36
36
37
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.
37
38
38
39
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`).
39
40
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
+
40
56
Next, the steps of using the PyGAD library are discussed.
41
57
42
58
## How to Use the PyGAD?
@@ -58,27 +74,32 @@ Let's discuss how to do each of these steps.
58
74
59
75
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.
60
76
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.
> where (x1,x2,x3,x4,x5,x6)=(4,-2,3.5,5,-11,-4.7) and y=44
68
84
> What are the best values for the 6 weights (w1 to w6)? We are going to use the genetic algorithm to optimize this function.
69
85
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:
71
87
72
88
```python
73
89
function_inputs = [4,-2,3.5,5,-11,-4.7] # Function inputs.
74
90
desired_output =44# Function output.
75
91
76
-
deffitness_func(solution):
92
+
deffitness_func(solution, solution_idx):
77
93
output = numpy.sum(solution*function_inputs)
78
94
fitness =1.0/ numpy.abs(output - desired_output)
79
95
return fitness
80
96
```
81
97
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
+
82
103
By creating this function, you are ready to use the library.
83
104
84
105
### Example of Preparing the Parameters
@@ -87,23 +108,41 @@ Here is an example for preparing the parameters:
87
108
88
109
```python
89
110
num_generations =50
90
-
sol_per_pop =8
91
111
num_parents_mating =4
92
112
113
+
fitness_function = fitness_func
114
+
115
+
sol_per_pop =8
116
+
num_genes =len(function_inputs)
117
+
93
118
init_range_low =-2
94
119
init_range_high =5
95
120
96
-
mutation_percent_genes =10
97
-
98
121
parent_selection_type ="sss"
122
+
keep_parents =1
99
123
100
124
crossover_type ="single_point"
101
125
102
126
mutation_type ="random"
127
+
mutation_percent_genes =10
128
+
```
103
129
104
-
keep_parents =1
130
+
#### Optional `callback_generation` Parameter
105
131
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.
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
+
...)
107
146
```
108
147
109
148
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
123
162
The `GA` class is instantiated where the previously prepared parameters are fed to its constructor. The constructor is responsible for creating the initial population.
@@ -178,7 +215,7 @@ You can also load the saved model using the `load()` function and continue using
178
215
179
216
```python
180
217
# Loading the saved GA instance.
181
-
loaded_ga_instance =ga.load(filename=filename)
218
+
loaded_ga_instance =pygad.load(filename=filename)
182
219
```
183
220
184
221
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
193
230
194
231
The supported crossover operations at this time are:
195
232
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.
199
236
200
237
The supported mutation operations at this time are:
201
238
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.
206
243
207
244
The supported parent selection techniques at this time are:
208
245
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.
215
252
216
253
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
217
254
@@ -221,13 +258,20 @@ PyGAD 1.0.17 (15 April 2020):
221
258
222
259
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.
223
260
224
-
PyGAD 1.0.18 (4 May 2020):
261
+
PyGAD 1.0.20 (4 May 2020):
225
262
226
263
1. The attributes are moved from the class scope to the instance scope.
227
264
2. Raising a `ValueError` exception on passing incorrect values to the parameters.
228
265
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.
229
266
4. The code object `__code__` of the passed fitness function is checked to ensure it has the right number of parameters.
230
267
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
+
231
275
## For More Information
232
276
233
277
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