Skip to content

Latest commit

 

History

History
180 lines (152 loc) · 7.44 KB

2.7 GAModel.md

File metadata and controls

180 lines (152 loc) · 7.44 KB

Introduction

GAModel is an abstract class that implements the genetic algorithm. Developers only need to extend the class to implement init, and evaluateFitness methods.

Properties

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.

options

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.

Setting an option

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);

crossoverFraction

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.

verbose

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)

constructor

The constructor for individuals in the population. Must be of type GAMember or any class that extends the GAMember class.

Constructor

Arguments

Argument Description
constructor The constructor for individuals in the population.

constructor

The constructor for individuals in the population. Must be of type GAMember or any class that extends the GAMember class.

Execution

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

Public Methods

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.

populate(model)

Generate the initial population.

stat = run(model, varargin)

Optimize the model according to the execution cycle.

Arguments

Argument Description
varargin The list of arguments that will be provided to beforeRun, forEachGeneration, evaluateFitness, and afterRun.

register(model, arg1, arg2)

Register options one by one, or with the entire struct.

Arguments

Argument Description
arg1 Provide a struct of options or a key.
arg2 Only when arg1 specified the key, specify the value.

beforeRun(model, varargin)

The method invoked at the beginning of the run method. Refer to the execution cycle.

Arguments

Argument Description
varargin A list of arguments that were provided to run.
By default, the function does nothing.

afterRun(model, varargin)

The method invoked at the end of the run method. Refer to the execution cycle.

Arguments

Argument Description
varargin A list of arguments that were provided to run.
By default, the function does nothing.

Abstract Methods

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.

fitnesses = evaluateFitness(model, varargin)

The method should return a vector of size n, with the i-th entry being the fitness score of the i-th individual.

Arguments

Argument Description
vargin A cell of arguments corresponding to the arguments (in order) provided to the run method.

Example

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

License

This project, including the documentation, is licensed under the MIT license. Copyright (c) 2022 Bohui WU.