221 lines
7.2 KiB
Matlab
221 lines
7.2 KiB
Matlab
%This class impliments a string that mutates to a target
|
|
classdef EvolutionaryAlgorithm
|
|
|
|
properties
|
|
|
|
target;
|
|
parent;
|
|
children = {};
|
|
validAlphabet;
|
|
|
|
%Constants
|
|
numChildrenPerIteration;
|
|
maxIterations;
|
|
mutationRate;
|
|
|
|
end
|
|
|
|
methods
|
|
|
|
%Class constructor
|
|
function family = EvolutionaryAlgorithm(target,mutationRate,numChildren,maxIterations)
|
|
|
|
family.validAlphabet = char([32 (65:90)]); %Space char and A-Z
|
|
family.target = target;
|
|
family.children = cell(numChildren,1);
|
|
family.numChildrenPerIteration = numChildren;
|
|
family.maxIterations = maxIterations;
|
|
family.mutationRate = mutationRate;
|
|
initialize(family);
|
|
|
|
end %class constructor
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%Helper functions and class get/set functions
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
%setAlphabet() - sets the valid alphabet for the current instance
|
|
%of the EvolutionaryAlgorithm class.
|
|
function setAlphabet(family,alphabet)
|
|
|
|
if(ischar(alphabet))
|
|
family.validAlphabet = alphabet;
|
|
|
|
%Makes change permanent
|
|
assignin('caller',inputname(1),family);
|
|
else
|
|
error 'New alphabet must be a string or character array';
|
|
end
|
|
|
|
end
|
|
|
|
%setTarget() - sets the target for the current instance
|
|
%of the EvolutionaryAlgorithm class.
|
|
function setTarget(family,target)
|
|
|
|
if(ischar(target))
|
|
family.target = target;
|
|
|
|
%Makes change permanent
|
|
assignin('caller',inputname(1),family);
|
|
else
|
|
error 'New target must be a string or character array';
|
|
end
|
|
|
|
end
|
|
|
|
%setMutationRate() - sets the mutation rate for the current instance
|
|
%of the EvolutionaryAlgorithm class.
|
|
function setMutationRate(family,mutationRate)
|
|
|
|
if(isnumeric(mutationRate))
|
|
family.mutationRate = mutationRate;
|
|
|
|
%Makes change permanent
|
|
assignin('caller',inputname(1),family);
|
|
else
|
|
error 'New mutation rate must be a double precision number';
|
|
end
|
|
|
|
end
|
|
|
|
%setMaxIterations() - sets the maximum number of iterations during
|
|
%evolution for the current instance of the EvolutionaryAlgorithm class.
|
|
function setMaxIterations(family,maxIterations)
|
|
|
|
if(isnumeric(maxIterations))
|
|
family.maxIterations = maxIterations;
|
|
|
|
%Makes change permanent
|
|
assignin('caller',inputname(1),family);
|
|
else
|
|
error 'New maximum amount of iterations must be a double precision number';
|
|
end
|
|
|
|
end
|
|
|
|
%display() - overrides the built-in MATLAB display() function, to
|
|
%display the important class variables
|
|
function display(family)
|
|
disp([sprintf('Target: %s\n',family.target)...
|
|
sprintf('Parent: %s\n',family.parent)...
|
|
sprintf('Valid Alphabet: %s\n',family.validAlphabet)...
|
|
sprintf('Number of Children: %d\n',family.numChildrenPerIteration)...
|
|
sprintf('Mutation Rate [0,1]: %d\n',family.mutationRate)...
|
|
sprintf('Maximum Iterations: %d\n',family.maxIterations)]);
|
|
end
|
|
|
|
%disp() - overrides the built-in MATLAB disp() function, to
|
|
%display the important class variables
|
|
function disp(family)
|
|
display(family);
|
|
end
|
|
|
|
%randAlphabetElement() - Generates a random character from the
|
|
%valid alphabet for the current instance of the class.
|
|
function elements = randAlphabetElements(family,numChars)
|
|
|
|
%Sample the valid alphabet randomly from the uniform
|
|
%distribution
|
|
N = length(family.validAlphabet);
|
|
choices = ceil(N*rand(1,numChars));
|
|
|
|
elements = family.validAlphabet(choices);
|
|
|
|
end
|
|
|
|
%initialize() - Sets the parent to a random string of length equal
|
|
%to the length of the target
|
|
function parent = initialize(family)
|
|
|
|
family.parent = randAlphabetElements(family,length(family.target));
|
|
parent = family.parent;
|
|
|
|
%Makes changes to the instance of EvolutionaryAlgorithm permanent
|
|
assignin('caller',inputname(1),family);
|
|
|
|
end %initialize
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%Functions required by task specification
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
%mutate() - generates children from the parent and mutates them
|
|
function mutate(family)
|
|
|
|
sizeParent = length(family.parent);
|
|
|
|
%Generate mutatant children sequentially
|
|
for child = (1:family.numChildrenPerIteration)
|
|
|
|
parentCopy = family.parent;
|
|
|
|
for charIndex = (1:sizeParent)
|
|
if (rand(1) < family.mutationRate)
|
|
parentCopy(charIndex) = randAlphabetElements(family,1);
|
|
end
|
|
end
|
|
|
|
family.children{child} = parentCopy;
|
|
|
|
end
|
|
|
|
%Makes changes to the instance of EvolutionaryAlgorithm permanent
|
|
assignin('caller',inputname(1),family);
|
|
|
|
end %mutate
|
|
|
|
%fitness() - Computes the Hamming distance between the target
|
|
%string and the string input as the familyMember argument
|
|
function theFitness = fitness(family,familyMember)
|
|
|
|
if not(ischar(familyMember))
|
|
error 'The second argument must be a string';
|
|
end
|
|
|
|
theFitness = sum(family.target == familyMember);
|
|
end
|
|
|
|
%evolve() - evolves the family until the target is reached or it
|
|
%exceeds the maximum amount of iterations
|
|
function [iteration,mostFitFitness] = evolve(family)
|
|
|
|
iteration = 0;
|
|
mostFitFitness = 0;
|
|
targetFitness = fitness(family,family.target);
|
|
|
|
disp(['Target fitness is ' num2str(targetFitness)]);
|
|
|
|
while (mostFitFitness < targetFitness) && (iteration < family.maxIterations)
|
|
|
|
iteration = iteration + 1;
|
|
|
|
mutate(family);
|
|
|
|
parentFitness = fitness(family,family.parent);
|
|
mostFit = family.parent;
|
|
mostFitFitness = parentFitness;
|
|
|
|
for child = (1:family.numChildrenPerIteration)
|
|
|
|
childFitness = fitness(family,family.children{child});
|
|
if childFitness > mostFitFitness
|
|
mostFit = family.children{child};
|
|
mostFitFitness = childFitness;
|
|
end
|
|
|
|
end
|
|
|
|
family.parent = mostFit;
|
|
disp([num2str(iteration) ': ' mostFit ' - Fitness: ' num2str(mostFitFitness)]);
|
|
|
|
end
|
|
|
|
%Makes changes to the instance of EvolutionaryAlgorithm permanent
|
|
assignin('caller',inputname(1),family);
|
|
|
|
end %evolve
|
|
|
|
end %methods
|
|
end %classdef
|