Я реализую генетический алгоритм (ГА).
Есть 43 номера [Расположения скорой помощи] на выбор (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39), я выбираю 3 места, так как у меня есть 3 машины скорой помощи.
Я могу разместить свою машину скорой помощи только в 3 местах среди 1-39 locations (Ограничение).
Образец хромосомы: [000010000000000000100000000000100000000]. Это означает, что я хочу поставить свою машину скорой помощи на 5th, 19th, and 31 positions. Биты напротив позиций 5th, 19th и 31 равны 1, а остальные позиции равны 0. Другими словами, я включаю 5-bit, 19-bit, and 31-bit.
скажем
Candidate solution 1 (111000000000000000000000000000000000000)
и
Candidate Solution 2 (000000000000000000000000000000000000111)
Мои решения-кандидаты закодированы в 39-битном коде, я хочу сделать кроссовер этих 39-битных. Вышеуказанные два решения-кандидата немного странные. Что здесь можно сделать?
Что может быть хорошим подходом для выполнения перекрестного перемещения при размещении машин скорой помощи в 3 местах среди 1-39 locations?
@TimRoberts Я использую генетический алгоритм для кроссинговера. Мне нужно создать потомство/ребенка из родительских хромосом.
@AdilAbid Итак, как именно это связано с машинами скорой помощи?
@pigrammer Мне нужно изучить мое пространство для поиска. Моя область поиска 9139. Следуя генетическому алгоритму, мне нужно выполнить мутацию и скрещивание, чтобы найти 3 лучших места для размещения моих машин скорой помощи.






ОП вопрос
Есть много способов выполнить кроссовер - в этом примере, поскольку мы должны получить одинаковое количество битов на входе и выходе, я использовал кроссовер между битами, позволяя 0-3 бита обмениваться местами между двумя входами. .
Предоставленное решение является динамическим и будет работать для хромосом любой длины с любым количеством перевернутых битов (1).
import random
from typing import Union
def crossover(cs1: str, cs2: str) -> Union[str, str]:
if len(cs1) != len(cs2):
raise Exception("Candidate solutions input are of different length.")
# get the flipped bits in each string
cs1_bits = [index for index, gene in enumerate(cs1) if gene == "1"]
cs2_bits = [index for index, gene in enumerate(cs2) if gene == "1"]
if len(cs1_bits) != len(cs2_bits):
raise Exception("Candidate solutions input have different number of flipped bits.")
index: int = random.randint(0, len(cs1_bits))
sol1_bits, sol2_bits = cs1_bits[:index] + cs2_bits[index:], cs2_bits[:index] + cs1_bits[index:]
output_1 = ""
output_2 = ""
for i in range(len(cs1)):
if i in sol1_bits:
output_1 += "1"
else:
output_1 += "0"
if i in sol2_bits:
output_2 += "1"
else:
output_2 += "0"
return output_1, output_2
Пример ввода/вывода для решения OP.
# Input
"111000000000000000000000000000000000000", "000000000000000000000000000000000000111"
# Output
'110000000000000000000000000000000000001', '001000000000000000000000000000000000110'
Как выполнить стандартный кроссовер
Вы выполняете кроссовер в генетическом алгоритме, выбирая случайный индекс по длине числа значений, в вашем случае вы выберете значение от 0 до 38 (39 вариантов).
Затем вы разделите оба входа и соедините переднюю часть cs1 с задней частью cs2 и наоборот.
from typing import Union
import random
def crossover(cs1: str, cs2: str) -> Union[str, str]:
index: int = random.randint(0, len(cs1))
return cs1[:index] + cs2[index:], cs2[:index] + cs1[index:]
Если у вас есть значения:
cs1 = "111000000000000000000000000000000000000"
cs2 = "000000000000000000000000000000000000111"
Кроссинговер с индексом 1 вернет:
output_1 = "100000000000000000000000000000000000111"
output_2 = "011000000000000000000000000000000000000"
Кроссинговер с индексом 5 вернет:
output_1 = "111000000000000000000000000000000000111"
output_2 = "000000000000000000000000000000000000000"
Можете ли вы также предложить мне, как «мутировать» cs1 = "111000000000000000000000000000000000000" хорошо и организованно? Так же, как кроссовер?
Задайте другой вопрос, ответьте мне здесь, когда вы это сделаете, и я отвечу на него за вас.
Я разместил еще один вопрос для мутации. Пожалуйста, посмотрите. Это мой вопрос (stackoverflow.com/questions/73966258/…)
У меня есть вопрос. Если мы посмотрим на output_1 = "111000000000000000000000000000000000111", я получаю six1's. Однако мне необходимо оставить только 3bits (всего 3 машины скорой помощи) после пересечения границы. Что мне делать?
@JeremySavage Я думаю, что кроссовер unform может решить такие проблемы. Это решение в основном приведет к незаконному потомству.
Я обновил, чтобы вернуть только 3 бита - извините, я неправильно прочитал ваш вопрос. Я оставил исходное решение ниже, так как оно может быть полезно для кого-то еще.
@JeremySavage Код вашего решения основан на One Point Crossover, Multi-Point Crossover или Uniform Crossover?
Решение представляет собой вариант кроссовера one-point. Выбирается index, а затем биты с обеих сторон индекса меняются местами. Поскольку у вас есть только 3 возможных решения, выбранных одновременно, я думаю, что one-point имеет смысл. Вы также можете использовать uniform crossover для решения этой проблемы, но multi-point crossover не имеет смысла из-за отсутствия доступных решений.
Я понятия не имею, что вы подразумеваете под словом «кроссовер». Вы имеете в виду перестановку битов? Вы можете перевернуть строку в Python, выполнив
s[::-1]. Если вы просто хотите поставить биты в обратном порядке, то вместо добавления1 << iдобавьте1 << (31-i).