/// <summary> /// Добавляет организм в популяцию. Проверяет на валидность организм. /// </summary> /// <param name="organism">Организм</param> /// <param name="population">Популяция</param> private void AddToPopulation(Organism organism, List<Organism> population) { if (organism.GenesCount == 0) throw new ArgumentOutOfRangeException("organism"); if (organism.Factors.Count == 0) throw new ArgumentOutOfRangeException("organism"); population.Add(organism); }
private AnalyzablePage Solution(Organism organism) { try { var triggerValue = organism.Factors[0].Value; var minHeight = organism.Factors[1].Value; var height = _hystogram.GetLength(0); var page = new AnalyzablePage(height,_width); int start = 0; var isLine = false; for (var y = 0; y < height; y++) { var trigger = (_hystogram[y] > triggerValue); if (trigger) { if (!isLine) { start = y; isLine = true; } } else { if (isLine) { int end = y; var lineHeight = end - start + 1; if (lineHeight > minHeight) page.AddLine(new AnalyzableLine(start, lineHeight)); isLine = false; } } } return page; } catch (Exception e) { throw new Exception("Cant generate solution",e); } }
/// <summary> /// Находит решение /// </summary> protected void Solve() { var iterations = 0; var globalMaximumIterations = 0; double maxFitness = 0; double globalMaximum = 0.0; _population = GenerateInitialPopulation(); var fitnessLog = new List<double>(); fitnessLog.Add(0); try { while (true) { if (maxFitness > globalMaximum) { globalMaximum = maxFitness; globalMaximumIterations = 0; } else globalMaximumIterations++; fitnessLog.Add(maxFitness); GenerateFitnesses(); GenerateLikalihoods(); BestOrganism = (from organism in _population orderby organism.Fitness descending select organism).ToList()[0]; maxFitness = BestOrganism.Fitness; var solved = ((globalMaximumIterations < GeneticConfiguration.MaximumIterations*(1 - globalMaximum)) || !(Math.Abs(maxFitness - globalMaximum) < 0.01)) && (iterations < GeneticConfiguration.MaximumIterations); if (solved) break; _population = NewPopulation(); iterations++; } } catch (Exception e) { throw new Exception("Cant solve",e); } }
protected override double Fitness(Organism organism) { try { AnalyzablePage segmentation = Solution(organism); int heightsRange = segmentation.HeightRange(); int distanceRange = segmentation.DistanceRange(); //double densityRange = segmentation.DensityRange(); var summ = (segmentation.Lines.Count > 2) ? segmentation.Lines.Sum(line => line.Height) : 0; double fitness = 1 / ((double)(1 + heightsRange) * (1 + distanceRange)*(1+Math.Abs(2*segmentation.Height - summ))); if (!((fitness >= 0) && (fitness <= 1))) throw new ArgumentOutOfRangeException(); return fitness; } catch (Exception e) { throw new Exception("Cant calculate fitness",e); } }
/// <summary> /// Скрещивание организмов /// </summary> /// <param name="alpha">Первая особь</param> /// <param name="beta">Вторая особь</param> /// <returns>Потомок</returns> private Organism Breed(Organism alpha, Organism beta) { try { if (alpha.GenesCount != beta.GenesCount) { throw new ArgumentOutOfRangeException("alpha", @"Chromosome lengths must be same"); } //С вероятностью 0.5 инициирующей особью будет A if (_random.NextDouble() <= 0.5) { Organism t = alpha; alpha = beta; beta = t; } Organism offspring = Crossover(alpha, beta); MutateOrganism(offspring); return offspring; } catch (Exception e) { throw new Exception("Cant breed", e); } }
/// <summary> /// Мутирует каждый ген организма с определенной вероятностью /// </summary> /// <param name="organism">Организм для мутации</param> private void MutateOrganism(Organism organism) { double mutationRate = GeneticConfiguration.MutationRate; if ((mutationRate < 0) || (mutationRate > 1)) { throw new ArgumentOutOfRangeException(); } try { for (int index = 0; index < organism.GenesCount; index++) if (_random.NextDouble() <= GeneticConfiguration.MutationRate) organism.Alleles[index] = !organism.Alleles[index]; } catch (Exception e) { throw new Exception("Cant mutate organism", e); } }
/// <summary> /// Генерирует организм с факторами, содержащими случайные /// </summary> /// <returns></returns> private Organism GenerateRandomOrganism() { try { var organism = new Organism(); foreach ( var factor in GeneticConfiguration.FactorConfigs.Select(GenerateRandomFactor)) { organism.AddFactorAndCode(factor); } return organism; } catch (Exception e) { throw new Exception("Cant generate random organism", e); } }
protected abstract double Fitness(Organism organism);
/// <summary> /// Выполняет операцию кроссовера к генам двух особей /// </summary> /// <param name="alpha">Инициирующий</param> /// <param name="beta">Инициируемый</param> /// <returns>Потомок</returns> private Organism Crossover(Organism alpha, Organism beta) { try { if (alpha.GenesCount != beta.GenesCount) { throw new ArgumentOutOfRangeException("alpha", @"Chromosome lengths must be different"); } int length = alpha.GenesCount; var offspring = new Organism {Factors = alpha.Factors}; //Сгенерируем точки кроссовера var crossoverPoints = new[] {_random.Next(length), _random.Next(length)}; int crossoverStart = crossoverPoints.Min(); //Начало отрезка - меньшая точка int crossoverEnd = crossoverPoints.Max(); //Конец - большая //Получаем новую хромосому, заменяя гены инициируемого организма в [start; end] генами из инициирующего. // A {Ai..As..Ae..An} + B {Bi..Bs..Be..Bn} = Descendant {Bi..Bs-1,As..Ae,Be+1..Bn} for (int i = 0; i < length; i++) if ((i >= crossoverStart) && (i <= crossoverEnd)) offspring.AddGene(alpha.GetGene(i)); else offspring.AddGene(beta.GetGene(i)); offspring.Factors = offspring.GenerateFactors(); return offspring; } catch (Exception e) { throw new Exception("Cant crossover", e); } }
/// <summary> /// Скрещивает два организма с помощью взвешенного выбора /// </summary> /// <returns>Потомок</returns> private Organism CreateOffspring() { var alpha = new Organism(); Organism beta = alpha; try { while (alpha == beta) { alpha = Roullete(); beta = Roullete(); } return Breed(alpha, beta); } catch (Exception e) { throw new Exception("Cant create offspring", e); } }
private void CalculateFitness(Organism organism) { try { var fitness = Fitness(organism); organism.Fitness = fitness; } catch (Exception e) { throw new Exception("Cant calculate fitness",e); } }
protected abstract double Fitness(Organism organism);