/// <summary> /// Метод для поиска решения с помощью генетического алгоритма /// </summary> /// <param name="model">Оптимизационная модель, эксперименты из которой /// выступят в качестве начальной популяции</param> /// <param name="gaParams">Параметры генетического алгоритма</param> /// <param name="table">Таблица для отображения процесса поиска решения. /// Если null, то процесс поиска решения не отображается</param> public static AdditiveMethodResult FindDecision(Model model, AdditiveParams gaParams, DataGridView table) { bool showProcess = (table != null); int currentGeneration = 0; // 1. Получим начальную популяцию из модели AdditivePopulation population = AdditiveSolver.ModelToPopulation(model, currentGeneration); // Рассчитаем значения функции приспособленности AdditiveSolver.CalcUnitsFitness( ref model, ref population, gaParams.ExternalAppPath); // Если надо, подготовим таблицу к выводу процесса и // выведем начальную популяцию (без разделителя) if (showProcess) { AdditiveDataGridFiller.PrepareProcessDataGrid(table); AdditiveDataGridFiller.AddPopulationToDataGrid(table, population, false); } // 2. Пока не достигнуто нужное количество поколений while (currentGeneration < gaParams.MaxGenerationsNumber) { // Увеличим счетчик поколений currentGeneration++; // 3. Отбор population = AdditiveSelection.TournamentSelection(population, gaParams.SelectionLimit); // 4. Скрещивание population = AdditiveCrossover.OnePointCrossover(population, currentGeneration); // 5. Мутация population = AdditiveMutation.PerformMutation(population, gaParams.MutationProbability); // 6. Расчет приспособленности // Модель обновится, метод CalcUnitsFitness рассчитает // для популяции значения функции приспособленности, а для // модели - значения критериев и Ф.О. model = AdditiveSolver.PopulationToModel(model, population); AdditiveSolver.CalcUnitsFitness( ref model, ref population, gaParams.ExternalAppPath); // Если надо, то выведем на экран информацию (с разделителем) if (showProcess) { AdditiveDataGridFiller.AddPopulationToDataGrid(table, population, true); } } // Подготовим результат на основе конечной популяции AdditiveMethodResult result = AdditiveSolver.PrepareResult(population); // Вернем результат return(result); }
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(); }