예제 #1
0
        private static void CalcUnitsFitness(
            ref Model initModel,
            ref AdditivePopulation population,
            string externalAppPath)
        {
            // У нас есть модель. Рассчитаем для нее с помощью внешней
            // программы значения критериев оптимальности и Ф.О.
#if DUMMY
            // Запустим внешнюю программу и дождемся, пока она отработает
            if (!AdditiveSolver.UseDummyExternalApplication(initModel, externalAppPath))
            {
                throw new Exception("Can not calculate fitness values using external program");
            }
#else
            // Файл для обмена данными между opt и расчетной программой
            string dataFilePath = System.IO.Path.GetDirectoryName(externalAppPath) + "\\_ga_temp_file.xml";

            // Запустим внешнюю программу и дождемся, пока она отработает
            if (!AdditiveSolver.UseExternalApplication(
                    initModel,
                    externalAppPath,
                    dataFilePath))
            {
                throw new Exception("Can not calculate fitness values using external program");
            }

            // Раз программа отработала, прочтем результаты из файла
            initModel = modelProvider.Load(dataFilePath);

            // Удалим файл с данными
            if (System.IO.File.Exists(dataFilePath))
            {
                System.IO.File.Delete(dataFilePath);
            }
#endif
            // Применим решатель для аддитивного критерия, чтобы получить его значения.
            // Они послужат нам эквивалентом функции приспособленности
            AdditiveCriterionSolver       solver = new AdditiveCriterionSolver();
            IntegralCriterionMethodResult result = solver.FindDecision(initModel);

            // Из результатов аддитивного критерия выдерем его значения
            foreach (TId expId in result.SortedPoints)
            {
                int unitNumber = initModel.Experiments[expId].Number;
                population[unitNumber].FitnessValue = result.AdditionalData[expId];
            }

            // Применим Ф.О. к модели
            initModel.ApplyFunctionalConstraints();

            // Пометим на удаление в популяции особи, соответсвующие экспериментам,
            // ставшим неактивными после применения Ф.О.
            foreach (Experiment exp in initModel.Experiments.Values)
            {
                if (!exp.IsActive)
                {
                    population.MarkForRemoval(exp.Number);
                }
            }
            // И удалим помеченные
            population.RemoveMarked();
        }
예제 #2
0
        public static AdditivePopulation TournamentSelection(
            AdditivePopulation initPop,
            int selectionLimit)
        {
            // Сначала проверим: если надо отобрать больше, чем есть,
            // то выбросим ошибку
            if (selectionLimit > initPop.Count)
            {
                throw new ArgumentException("Number of units to be selected is greater than number of units in population");
            }

            // Если надо отобрать столько же, сколько есть, просто
            // вернем входную популяцию
            if (selectionLimit == initPop.Count)
            {
                return(initPop);
            }

            // Список номеров отобранных особей
            List <int> selectedUnitNumbers = new List <int>();
            // Рандомайзер для выбора случайных особей
            Random rnd = new Random(DateTime.Now.Millisecond + DateTime.Now.Second);
            // Флагом того, что пора прекртатить итерации отбора,
            // будет служить совпадение количества отобранных
            // особей (в списке, объявленном выше) и переданного
            // в качестве аргумента требуемого количества
            int maxUnitNumber = initPop.GetMaxUnitNumber();

            while (selectedUnitNumbers.Count != selectionLimit)
            {
                // В этом цикле будет проходить разбиение на пары
                // и выбор лучшей особи из пары

                // Список пары отобранных для турнира особей
                List <int> selectedPair = new List <int>();

                // Проверим: если среди неотобранных особей осталось всего две,
                // то составим из них пару и не будем морочить себе голову
                // случайностями
                if ((initPop.Count - selectedUnitNumbers.Count) == 2)
                {
                    foreach (AdditiveIndividual unit in initPop)
                    {
                        if (IsValidPairUnit(unit.Number, selectedPair, selectedUnitNumbers, initPop))
                        {
                            selectedPair.Add(unit.Number);
                        }
                    }
                }

                // Флагом остановки выбора случайной особи в пару
                // будет служить наличие двух отобранных особей
                while (selectedPair.Count != 2)
                {
                    // Будем выбирать случайное число в диапазоне
                    // от 0 до значения счетчика особей в популяции
                    // до тех пор, пока не наткнемся на особь, которую
                    // можно отобрать в турнирную пару
                    int rndNumber = -1;
                    while (!IsValidPairUnit(rndNumber, selectedPair, selectedUnitNumbers, initPop))
                    {
                        // "+ 1" из-за особенностей реализации метода
                        // Random.Next(Int32, Int32). Если не будет "+ 1",
                        // то maxUnitNumber не выпадет никогда
                        rndNumber = rnd.Next(0, maxUnitNumber + 1);
                    }
                    // Когда найден подходящий номер, добавим его в пару
                    selectedPair.Add(rndNumber);
                }

                // Выберем из пары наиболее приспособленную особь
                // (ту, у которой значение функции приспособленности
                // лучше - то есть меньше, потому что мы работаем с
                // аддитивным критерием)
                if (opt.Helpers.Comparer.IsFirstValueBetter(
                        initPop[selectedPair[0]].FitnessValue,
                        initPop[selectedPair[1]].FitnessValue,
                        opt.DataModel.CriterionType.Minimizing))
                {
                    // Первая особь лучше второй
                    selectedUnitNumbers.Add(selectedPair[0]);
                }
                else
                {
                    // Вторая особь лучше первой
                    selectedUnitNumbers.Add(selectedPair[1]);
                }
            }

            // Пометим на удаление все особи, кроме отобранных во время турнира
            foreach (AdditiveIndividual unit in initPop)
            {
                if (!selectedUnitNumbers.Contains(unit.Number))
                {
                    initPop.MarkForRemoval(unit.Number);
                }
            }
            // Удалим помеченные особи
            initPop.RemoveMarked();

            // Вернем результат
            return(initPop);
        }