private void Mutate(MathExpressionTree expression) { MathExpressionNode randomNode = expression.GetRandomNode(); randomNode.SubstiteValue(randomNode.IsLeaf ? stohasticGenerator.GetRandomOperand() : stohasticGenerator.GetRandomOperator(randomNode.LeftChild, randomNode.RightChild)); }
public List <MathExpressionTree> Evolve(List <MathExpressionTree> selectedIndividuals) { List <(MathExpressionTree, MathExpressionTree)> pairs = selectedIndividuals.ParallelOrderBy(x => new Guid()) .Take(selectedIndividuals.Count) .Select((individual, i) => new { index = i, individual }) .GroupBy(x => x.index / 2, x => x.individual) .Select(g => (g.First(), g.Skip(1).FirstOrNew(populationSelector))) .ToList(); List <MathExpressionTree> newPopulation = new List <MathExpressionTree>(); ThreadSafeRandom crossoverRandom = new ThreadSafeRandom(); ThreadSafeRandom mutationRandom = new ThreadSafeRandom(); foreach ((MathExpressionTree firstParent, MathExpressionTree secondParent) in pairs) { double randomProbability = crossoverRandom.NextDouble(); if (randomProbability > crossoverProbability) { MathExpressionTree firstCopy = firstParent.Copy(); MathExpressionTree secondCopy = secondParent.Copy(); Crossover(firstCopy, secondCopy); newPopulation.AddTwo(firstCopy, secondCopy); } } pairs.ForEach(x => { newPopulation.AddTwo(x.Item1, x.Item2); }); foreach (MathExpressionTree expression in newPopulation) { double randomProbability = mutationRandom.NextDouble(); if (randomProbability < mutationProbability || !expression.IsValidExpression()) { Mutate(expression); } } List <MathExpressionTree> validExpressions = newPopulation.Where(x => x.IsValidExpression()) .Distinct(new MathExpressionTreeEqualityComparer()) .ToList(); while (validExpressions.Count < populationSize) { validExpressions.Add(populationSelector.GenerateIndividual()); } IEnumerable <MathExpressionTree> elite = validExpressions.ParallelOrderBy(x => populationSelector.CalculateFitness(x)) .Take(eliteCount); return(elite.Concat(validExpressions) .Take(populationSize) .ToList()); }
public List <MathExpressionTree> GeneratePopulation(int initialPopulationSize) { BlockingCollection <MathExpressionTree> expressions = new BlockingCollection <MathExpressionTree>(initialPopulationSize); Parallel.For(0, initialPopulationSize, i => { MathExpressionTree expression = GenerateIndividual(); expressions.Add(expression); }); return(expressions.ToList()); }
public async Task Execute(int populationSize, int lookup, int[] operands, int iterationCount = 100, int eliteCount = 1, double mutationProbability = 0.05, double crossover = 0.15) { GeneticAlgorithmConfiguration configuration = new GeneticAlgorithmConfiguration(lookup, mutationProbability, crossover, populationSize, eliteCount, iterationCount) { Operands = operands }; CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); GeneticAlgorithmExecutor geneticAlgorithm = new GeneticAlgorithmExecutor(configuration, cancellationTokenSource.Token, new SemaphoreSlim(1)); MathExpressionTree result = await geneticAlgorithm.Execute(); Assert.IsNotNull(result, "Result is not found"); }
private void Crossover(MathExpressionTree first, MathExpressionTree second) { MathExpressionNode crossoverPointOfFirst = first.GetRandomSubtree(); MathExpressionNode crossoverPointOfSecond = second.GetRandomSubtree(); MathExpressionNode firstParent = crossoverPointOfFirst.Parent; MathExpressionNode secondParent = crossoverPointOfSecond.Parent; if (firstParent != null) { if (firstParent.LeftChild.Id == crossoverPointOfFirst.Id) { firstParent.LeftChild = crossoverPointOfSecond; } else { firstParent.RightChild = crossoverPointOfSecond; } } else { first.Root = crossoverPointOfSecond; } if (secondParent != null) { if (secondParent.LeftChild.Id == crossoverPointOfSecond.Id) { secondParent.LeftChild = crossoverPointOfFirst; } else { secondParent.RightChild = crossoverPointOfFirst; } } else { second.Root = crossoverPointOfFirst; } crossoverPointOfFirst.Parent = secondParent; crossoverPointOfSecond.Parent = firstParent; }
public MathExpressionTree GenerateIndividual() { MathExpressionTree validExpression; do { int operandsCount = stohasticGenerator.OperandsCount(); List <MathExpressionNode> operatorsAndOperands = Enumerable.Range(0, 2 * operandsCount - 1) .Select(x => x % 2 == 0 ? stohasticGenerator.GetRandomOperand() : stohasticGenerator.GetRandomOperator()) .ToList(); MathExpressionNode root = operatorsAndOperands.Where(x => !x.IsLeaf) .OrderBy(x => Guid.NewGuid()) .First(); MathExpressionNode getGenome(List <MathExpressionNode> elements, MathExpressionNode parent, MathExpressionNode rootNode = null) { if (elements.Count == 0) { return(null); } MathExpressionNode currentNode = (rootNode ?? elements.FirstOrDefault(x => !x.IsLeaf)) ?? elements.First(); currentNode.Parent = parent; if (!currentNode.IsLeaf) { int currentNodeIndex = elements.IndexOf(currentNode); currentNode.LeftChild = getGenome(elements.Take(currentNodeIndex).ToList(), currentNode); currentNode.RightChild = getGenome(elements.Skip(currentNodeIndex + 1).ToList(), currentNode); } return(currentNode); } validExpression = new MathExpressionTree(getGenome(operatorsAndOperands, null, root)); } while (!validExpression.IsValidExpression()); return(validExpression); }
public static void AddTwo(this List <MathExpressionTree> list, MathExpressionTree first, MathExpressionTree second) { list.Add(first); list.Add(second); }
public int CalculateFitness(MathExpressionTree individual) => Math.Abs(result - individual.Root.GetValue());