public override void Mutate()
{
// current tree level
int currentLevel = 0;
// current node
GPCustomTreeNode node = root;
for (; ; )
{
// regenerate node if it does not have children
if (node.Children == null)
{
if (currentLevel == maxLevel)
{
// we reached maximum possible level, so the gene
// can be an argument only
node.Gene.Generate(GPGeneType.Argument);
}
else
{
// generate subtree
int level = maxLevel - currentLevel;
if (level < 0)
level = 0;
Generate(node, rand.Next(level));
}
break;
}
// if it is a function node, than we need to get a decision, about
// mutation point - the node itself or one of its children
int r = rand.Next(node.Gene.ArgumentsCount + 1);
if (r == node.Gene.ArgumentsCount)
{
// node itself should be regenerated
node.Gene.Generate();
// check current type
if (node.Gene.GeneType == GPGeneType.Argument)
{
node.Children = null;
}
else
{
// create children's list if it was absent
if (node.Children == null)
node.Children = new List<GPCustomTreeNode>();
// check for missing or extra children
if (node.Children.Count != node.Gene.ArgumentsCount)
{
if (node.Children.Count > node.Gene.ArgumentsCount)
{
// remove extra children
node.Children.RemoveRange(node.Gene.ArgumentsCount, node.Children.Count - node.Gene.ArgumentsCount);
}
else
{
// add missing children
for (int i = node.Children.Count; i < node.Gene.ArgumentsCount; i++)
{
// create new child
GPCustomTreeNode child = new GPCustomTreeNode();
Generate(child, rand.Next(maxLevel - currentLevel));
// add the new child
node.Children.Add(child);
}
}
}
}
break;
}
// mutation goes further to one of the children
node = (GPCustomTreeNode)node.Children[r];
currentLevel++;
}
}