Использование шанса для генерации чисел - C#
Формулировка задачи:
Есть одна статья пытаюсь реализовать данный алгоритм на C#, вся проблема возникает когда надо выбрать пары. Дайте пример и если можно прокомментируйте что в нём происходит.
Решение задачи: «Использование шанса для генерации чисел»
textual
Листинг программы
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication152
{
class Program
{
static void Main(string[] args)
{
var res = new Solver().Solve(c => Math.Abs(1*c[0] + 2*c[1] + 3*c[2] + 4*c[3] - 30));
Console.WriteLine(res);
Console.ReadLine();
}
}
class Solver
{
public Chromosome Solve(Func<Chromosome, int> fitness)
{
//создаем популяцию
var pop = new Population(10, fitness, 4);
//пока не найдено решение...
do
{
//суммарная подходящесть
var sum = pop.Sum(c => c.Likehood);
//создем потомков
var newPop = new Population();
for (int i = 0; i < pop.Count; i++)
{
var chr = new Chromosome(fitness, pop.GetRandom(sum), pop.GetRandom(sum));
if(chr.Fitness == 0)//нашли решение
return chr;
newPop.Add(chr);//добавляем в популяцию
}
//заменяем популяцию
pop = newPop;
} while (true);
}
}
class Population: List<Chromosome>
{
private static Random rnd = new Random(1);
public Population(int chromosomesCount, Func<Chromosome, int> fitness, int koeffCount)
{
for (int i = 0; i < chromosomesCount; i++)
Add(new Chromosome(fitness, koeffCount));
}
public Population()
{
}
public Chromosome GetRandom(float sumLikehood)
{
//находим сулчайную хромосому пропорционально значениям Likehood
var r = rnd.NextDouble() * sumLikehood;
foreach(var chr in this)
{
r -= chr.Likehood;
if (r <= float.Epsilon)
return chr;
}
return this[Count - 1];
}
}
class Chromosome : List<int>
{
public static int MinKoeff = 1;
public static int MaxKoeff = 30;
private static Random rnd = new Random(1);
public float Likehood { get { return 1f / (1 + Fitness); } }
public int Fitness { get; private set; }
public Chromosome(Func<Chromosome, int> fitness, int koeffCount)
{
for (int i = 0; i < koeffCount; i++)
Add(MinKoeff + rnd.Next(MaxKoeff - MinKoeff + 1));
Fitness = fitness(this);
}
public Chromosome(Func<Chromosome, int> fitness, Chromosome parent1, Chromosome parent2)
{
for (int i = 0; i < parent1.Count; i++)
{
//берем ген отца или матери
var k = rnd.Next(0, 2) == 0 ? parent1[i] : parent2[i];
//добавляем мутацию
k += rnd.Next(3) - 1;
//соблюдаем границы
if (k < MinKoeff) k = MinKoeff;
if (k > MaxKoeff) k = MaxKoeff;
//
Add(k);
}
Fitness = fitness(this);
}
public override string ToString()
{
return string.Join(" ", this);
}
}
}