Ejemplo n.º 1
0
        /// <summary>
        /// Метод для выполнения одноточечной инверсии особи
        /// </summary>
        /// <param name="population">Популяция, в которой находится родительская
        /// особь и в которую будет помещен потомок</param>
        /// <param name="unitNumber">Номер особи, над которой нужно выполнить инверсию
        /// (уникальный)</param>
        /// <param name="newGenerationNumber">Номер поколения, к которому относится потомок</param>
        private static void Inversion(
            ref AdditivePopulation population,
            int unitNumber,
            int newGenerationNumber)
        {
            // Признаки, у новой особи они будут такие же,
            // за исключением значений признаков - их поправим позже
            Dictionary <TId, IndividualAttribute> attributes =
                population[unitNumber].Attributes;

            // Генетический код родителя
            string parentChromo = population[unitNumber].GetChromo();

            Random rnd = new Random(DateTime.Now.Millisecond + DateTime.Now.Second);
            // Точка инверсии
            // Такая формула обусловлена следующим:
            //  - не должно получатся число, равное длине строки, потому что
            //    нумерация символов zero-based и будет ошибка;
            int crossoverPointPosition = rnd.Next(parentChromo.Length - 1);

            // Разделим хромосому на части, первая из которых останется неизменной,
            // а вторая инвертируется
            string parentFirstPart  = parentChromo.Substring(0, crossoverPointPosition);
            string parentSecondPart = parentChromo.Substring(crossoverPointPosition);

            // Инвертируем вторую часть хромосомы
            string newSecondPart = string.Empty;

            // Проверим каждый ген в этой части хромосомы
            char[] secondPart = parentSecondPart.ToCharArray();
            foreach (char gene in secondPart)
            {
                // Выполним добавление гена к новой хромосоме,
                // попутно инвертировав его
                switch (gene)
                {
                case '1':
                    newSecondPart += "0";
                    break;

                case '0':
                    newSecondPart += "1";
                    break;
                }
            }

            // Составим хромосому потомка
            string сhildChromo = parentFirstPart + newSecondPart;

            // Получим и добавим в популяцию потомка
            AdditiveIndividual child = new AdditiveIndividual(
                population.GetFreeUnitNumber(),
                newGenerationNumber,
                attributes);

            child.UpdateAttributes(сhildChromo);
            population.Add(child.Number, child);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Метод для преобразования модели в популяцию
        /// </summary>
        /// <param name="model">Исходная модель для преобразования</param>
        /// <param name="generationNumber">Номер поколения, который будет присвоен
        /// всем особям в создаваемой популяции</param>
        /// <returns></returns>
        private static AdditivePopulation ModelToPopulation(Model model, int generationNumber)
        {
            AdditivePopulation pop = new AdditivePopulation();

            // 1. Сформируем словарь с параметрами особей. Все особи
            // данной популяции должны характеризоваться одинаковым
            // набором параметров, поэтому сформируем его заранее, а
            // потом будем передавать в качестве параметра конструктора
            // всем особям. Значения параметров будем затем назначать
            // вручную
            Dictionary <TId, IndividualAttribute> attributes =
                new Dictionary <TId, IndividualAttribute>();

            foreach (Parameter param in model.Parameters.Values)
            {
                IndividualAttribute attribute =
                    new IndividualAttribute(
                        param.Id,
                        param.MinValue,
                        param.MaxValue,
                        Program.ApplicationSettings.ValuesDecimalPlaces);
                attributes.Add(param.Id, attribute);
            }

            // 2. Добавим в популяцию особи - столько же, сколько
            // АКТИВНЫХ экспериментов в модели
            foreach (Experiment exp in model.Experiments.Values)
            {
                if (exp.IsActive)
                {
                    AdditiveIndividual unit =
                        new AdditiveIndividual(
                            exp.Number,
                            generationNumber,
                            attributes);
                    // Запишем значения оптимизируемых параметров эксперимента
                    // в словарь признаков особи
                    foreach (Parameter param in model.Parameters.Values)
                    {
                        unit.Attributes[param.Id].Value =
                            exp.ParameterValues[param.Id];
                        // Рассчитаем генетический код этой особи
                        unit.Attributes[param.Id].ResolveCodeFromValue();
                    }
                    // Добавим особь в популяцию
                    pop.Add(exp.Number, unit);
                }
            }

            return(pop);

            throw new NotImplementedException();
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Метод для выполнения одноточечного скрещивания двух
        /// особей
        /// </summary>
        /// <param name="population">Популяция, в которой находятся две
        /// родительские особи и куда будут помещены два потомка</param>
        /// <param name="firstUnitNumber">Номер первого родителя в популяции (уникальный)</param>
        /// <param name="secondUnitNumber">Номер второго родителя в популяции (уникальный)</param>
        /// <param name="newGenerationNumber">Номер поколения, к которому относятся потомки</param>
        private static void CrossTwoUnits(
            ref AdditivePopulation population,
            int firstUnitNumber,
            int secondUnitNumber,
            int newGenerationNumber)
        {
            // Признаки, у новых двух особей они будут такие же,
            // за исключением значений признаков - их поправим позже
            Dictionary <TId, IndividualAttribute> attributes =
                population[firstUnitNumber].Attributes;

            // Генетические коды родителей
            string firstChromo  = population[firstUnitNumber].GetChromo();
            string secondChromo = population[secondUnitNumber].GetChromo();

            // Небольшая проверка: длины кодов должны быть одинаковые
            int chromoLength = firstChromo.Length;

            if (chromoLength != secondChromo.Length)
            {
                throw new Exception("Chromosome lengths of two parents must be the same");
            }

            Random rnd = new Random(DateTime.Now.Millisecond + DateTime.Now.Second);
            // Точка одноточечного скрещивания
            // Такая формула обусловлена следующим:
            //  - не должно получатся число, равное длине строки, потому что
            //    нумерация символов zero-based и будет ошибка;
            //  - не должен получатся ноль, потому что тогда особи просто
            //    обменяются кодами и ничего не выйдет
            int crossoverPointPosition = 1 + rnd.Next(chromoLength - 2);

            // Разделим хромосомы на части, из которых будут составлены
            // хромосомы потомков
            string firstParentFirstPart   = firstChromo.Substring(0, crossoverPointPosition);
            string firstParentSecondPart  = firstChromo.Substring(crossoverPointPosition);
            string secondParentFirstPart  = secondChromo.Substring(0, crossoverPointPosition);
            string secondParentSecondPart = secondChromo.Substring(crossoverPointPosition);

            // Составим хромосомы потомков
            string firstChildChromo  = firstParentFirstPart + secondParentSecondPart;
            string secondChildChromo = secondParentFirstPart + firstParentSecondPart;

            // Получим и добавим в популяцию первого потомка
            AdditiveIndividual firstChild = new AdditiveIndividual(
                population.GetFreeUnitNumber(),
                newGenerationNumber,
                attributes);

            firstChild.UpdateAttributes(firstChildChromo);
            population.Add(firstChild.Number, firstChild);

            // Получим и добавим в популяцию второго потомка
            AdditiveIndividual secondChild = new AdditiveIndividual(
                population.GetFreeUnitNumber(),
                newGenerationNumber,
                attributes);

            secondChild.UpdateAttributes(secondChildChromo);
            population.Add(secondChild.Number, secondChild);
        }