//Кроссинговер ( скрещивание двух элементов популяции) private void Crossover() { Random random = new Random(); int count_can_to_cross = 0; foreach (ChildOfPopulation elem in population) { if (elem.CanCross) { count_can_to_cross++; } } //Количество операций кроссинговера int count_of_crossovers = random.Next(0, count_can_to_cross / 2); for (int i = 0; i < count_of_crossovers; i++) { int first_index = random.Next(0, population.Length); int second_index = random.Next(0, population.Length); ChildOfPopulation first_element = population[first_index]; ChildOfPopulation second_element = population[second_index]; // Если мы случайно выбрали один и тот же элемент для кроссинговера или один из них не пригоден if ((first_index == second_index) || (!first_element.CanCross) || (!second_element.CanCross)) { i--; continue; } int[] temp_array = new int[color_array.Length]; for (int j = 0; j < color_array.Length; j++) { int which_el = random.Next(0, 1); if (which_el == 0) { temp_array[j] = first_element.Color_Array[j]; } else { temp_array[j] = second_element.Color_Array[j]; } } //Полученный элемент по итогу кроссинговера ChildOfPopulation temp_element = new ChildOfPopulation(temp_array, graph); //Обновленное поколение по итогу кроссинговера ChildOfPopulation[] temp_population = new ChildOfPopulation[population.Length + 1]; for (int k = 0; k < population.Length; k++) { temp_population[k] = population[k]; } temp_population[population.Length] = temp_element; population = temp_population; } }
//Мутация ( намеренное изменение цветов некоторых вершин ) private void Mutation() { Random random = new Random(); // Исходная вероятность в диапазоне ( 0 - 100 ) int source_rate = (int)(mutation_rate * 100); // Для каждой раскраски проверяем ее на вероятность мутации for (int i = 0; i < population.Length; i++) { // Случайное число int rate = random.Next(0, 100); // Если случайное число меньше нашей вероятности, то if (source_rate >= rate) { // Получаем элемент и его текущую раскраску ChildOfPopulation temp = population[i]; int[] temp_colors = temp.Color_Array; // Считаем, сколько вершин необходимо изменить int count_tops = random.Next(0, temp_colors.Length); // Инициализируем список вершин, подлежащих замене List <int> list_of_tops = new List <int>(); for (int k = 0; k < count_tops; k++) { int top = random.Next(0, temp_colors.Length - 1); //если вершина уже есть, то откатываемся if (list_of_tops.Contains(top)) { k--; continue; } // Добавляем индекс вершины в список list_of_tops.Add(top); } Random colors = new Random(); // Для каждой вершины из списка for (int k = 0; k < list_of_tops.Count; k++) { int new_color = colors.Next(1, 12); temp_colors[list_of_tops[k]] = new_color; } // Обновляем текущий элемент на мутированный population[i] = temp; } else { continue; } } }
//Формирование исходной популяции ( Набор из нескольких вариантов раскраски ) private void Initialization() { Random random = new Random(); for (int i = 0; i < population_size; i++) { int[] temp = new int[count]; for (int j = 0; j < count; j++) { temp[j] = random.Next(1, 12); } population[i] = new ChildOfPopulation(temp, graph); } }
//Генерация новой популяции private void GenerateNewPopulation() { List <ChildOfPopulation> list_of_elem = new List <ChildOfPopulation>(); int good_elems = 0; foreach (ChildOfPopulation elem in population) { list_of_elem.Add(elem); if (elem.Valid > 0) { good_elems++; } } int max_new_size = (int)population.Length - population.Length / count_of_generations; int new_size; if (max_new_size < good_elems) { new_size = max_new_size; } else { new_size = good_elems; } //выбор лучших list_of_elem.Sort(delegate(ChildOfPopulation child1, ChildOfPopulation child2) { return(child2.Valid.CompareTo(child1.Valid)); }); ChildOfPopulation[] temp_population = new ChildOfPopulation[new_size]; for (int i = 0; i < new_size; i++) { temp_population[i] = list_of_elem[i]; } population = temp_population; }