GAModel
is an abstract class that implements the genetic algorithm. Developers only need to extend the class to implement init
, and evaluateFitness
methods.
Name | Description |
---|---|
population |
A cell containing all the individuals living in the population. |
constructor |
The constructor for individuals in the population. |
verbose |
The level of information that will show in the terminal. |
options |
Options used for optimizing the model. |
status |
A struct containing the current status of the model. |
statistics |
A struct containing the model's statistics. |
best |
The individual with the highest fitness score. |
A struct containing options about the model.
Option | Description |
---|---|
verbose |
The verbose level. |
populationSize |
The size of the population. |
generations |
The number of generations to run. |
selectionSchema |
The schema used for selecting individuals for reproduction. Popular methods include roulette , tournament , and rank . Learn more on the section for selection schema. |
tournamentSize |
The number of individuals that will be randomly chosen for each tournament. Only used in tournament selection. |
eliteSize |
The number of individuals that are guaranteed to survive to the next generation. |
crossoverFraction |
After excluding the elites, it specifies the fraction of individuals in the next generation created by performing crossover on two selected parents. |
mutateAfterCrossover |
Mutate on newly generated individuals. |
To set an option, use the register
method.
% Register a single attribute
myModel.register('verbose', verbose);
% Register a struct, will not override existing parameters.
opt.populationSize = 25;
opt.maxHeight = 6;
opt.generations = 20;
myGPModel.register(opt);
After excluding the elites, it specifies the fraction of individuals in the next generation created by performing crossover on two selected parents. For example, when the populationSize
is 50, eliteSize
is 8, then a crossoverFraction=0.70
will result in the generation consisting of:
- 10 elites directly copied from the previous generation.
- (50 - 8) * 0.8 = 29.4 = 29 (rounded) individuals are generated via crossover.
- The remaining 50 - 8 - 29 = 13 individuals are generated by mutating individuals from the previous generation.
These levels decide the amount of information you will get. Available verbose levels:
- 0: Mute
- 1: Only show results for each generation
- 2: Show information for each generation
- 3: Show results for individual
- 4: Show information for each individual (default)
The constructor for individuals in the population. Must be of type GAMember
or any class that extends the GAMember
class.
Argument | Description |
---|---|
constructor |
The constructor for individuals in the population. |
The constructor for individuals in the population. Must be of type GAMember
or any class that extends the GAMember
class.
When calling the run
method, it invokes the following methods. First, beforeRun
is called at the beginning. forEachGeneration
is called for each generation. Within forEachGeneration
, evaluateFitness
is called get the fitness score for each individual. The evaluateFitness
method must be specified by the programmers to fit the specific application. After reaching the maximum number of generations or a certain criteria are met, the loop ends and afterRun
is invoked.
function stat = run(model, varargin)
model.beforeRun(varargin{:});
...
for gen=1:gens
model.forEachGeneration(gen, gens, varargin{:});
end
...
model.afterRun(varargin{:});
end
Signature | Description |
---|---|
populate(model) |
Populate the GA model with individuals. Should specify populationSize using the register method first. |
stat = run(model, varargin) |
Start optimizing with genetic algorithm on the model. |
register(model, arg1, arg2) |
Register an option or a struct of options with the model. |
beforeRun(model, varargin) |
The method invoked at the beginning of the run method. Refer to the execution cycle. By default, the method does nothing. |
afterRun(model, varargin) |
The method invoked at the end of the run method. Refer to the execution cycle. By default, the method does nothing. |
Generate the initial population.
Optimize the model according to the execution cycle.
Argument | Description |
---|---|
varargin |
The list of arguments that will be provided to beforeRun , forEachGeneration , evaluateFitness , and afterRun . |
Register options one by one, or with the entire struct.
Argument | Description |
---|---|
arg1 |
Provide a struct of options or a key. |
arg2 |
Only when arg1 specified the key, specify the value. |
The method invoked at the beginning of the run
method. Refer to the execution cycle.
Argument | Description |
---|---|
varargin |
A list of arguments that were provided to run . |
By default, the function does nothing. |
The method invoked at the end of the run
method. Refer to the execution cycle.
Argument | Description |
---|---|
varargin |
A list of arguments that were provided to run . |
By default, the function does nothing. |
You must implement the following methods.
Signature | Description |
---|---|
init(model, varargin) |
Initialize every individual in the population. |
fitnesses = evaluateFitness(model, varargin) |
Evaulate the fitness and returns a vector of fitness values. |
The method should return a vector of size n, with the i-th entry being the fitness score of the i-th individual.
Argument | Description |
---|---|
vargin |
A cell of arguments corresponding to the arguments (in order) provided to the run method. |
Here is an example that you can fill in to meet your own needs.
When calling the run
method:
myGAModel.run(myData, myOptions);
In the method:
function fitnesses = evaluateFitness(model, varargin)
% Localize variables to avoid unnessary communication overhead.
% Skip this step if you do not use parallel computing toolbox.
n = model.options.populationSize;
% Retrieve the vairables initially provided when calling the
% run method.
myData = varargin{1};
myOptions = varargin{2};
% Spread out the variable to avoid communication overhead when
% using parallel computing toolbox
population = model.population;
fitnesses = zeros(n, 1);
% Get status information from the status struct
gen = model.status.generation;
% Execute using MATLAB's parallel computing toolbox. If you do
% not have the license for it, replace `parfor` with `for`.
parfor s=1:n
r = backtest(population{s}, myData);
fprintf("[Generation %d] Strategy %d return: %s\n", ...
gen, s, string(r));
fitnesses(s) = r;
end
end
This project, including the documentation, is licensed under the MIT license. Copyright (c) 2022 Bohui WU.