โจ 4 - Crossover ๊ต์ฐจ
Crossover is the process of forming new individuals from existing individuals while maintaining traits.
๊ต์ฐจ(Crossover)๋ ๊ธฐ์กด ๊ฐ์ฒด๋ค๋ก๋ถํฐ ํน์ฑ์ ์ ์งํ ์ฑ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ณผ์ ์
๋๋ค.
The main purpose of crossing is the exchange of experience.
๊ต์ฐจ์ ์ฃผ์ ๋ชฉ์ ์ ๊ฒฝํ์ ๊ตํ์
๋๋ค.
This approach greatly speeds up finding an acceptable solution.
์ด ๋ฐฉ์์ ์์ฉ ๊ฐ๋ฅํ ํด๋ฅผ ๋ ๋น ๋ฅด๊ฒ ์ฐพ๋ ๋ฐ ํฌ๊ฒ ๊ธฐ์ฌํฉ๋๋ค.
Crossover is the next logical action that occurs after selection.
๊ต์ฐจ๋ ์ ํ ์ดํ์ ์ผ์ด๋๋ ๋ค์ ๋จ๊ณ์ ๋
ผ๋ฆฌ์ ์ ์ฐจ์
๋๋ค.
๐ก ์ฃผ์ ๋จ์ด
| ์์ด ๋จ์ด | ํ๊ธ ๋ป |
|---|---|
| trait | ํน์ฑ |
| exchange | ๊ตํ |
| experience | ๊ฒฝํ |
| acceptable | ์์ฉ |
| solution | ํด |
| logical | ๋ ผ๋ฆฌ |
| occur | ๋ฐ์ |
โจ 4 - Structure ๊ตฌ์กฐ
In this chapter, we will look at the following crossover methods:
์ด ์ฅ์์๋ ๋ค์๊ณผ ๊ฐ์ ๊ต์ฐจ ๋ฐฉ๋ฒ๋ค์ ์ดํด๋ณผ ๊ฒ์
๋๋ค.
One-point crossover
์ํฌ์ธํธ ๊ต์ฐจ
N-point crossover
Nํฌ์ธํธ ๊ต์ฐจ
Uniform crossover
๊ท ์ผ ๊ต์ฐจ
Linear combination crossover
์ ํ ๊ฒฐํฉ ๊ต์ฐจ
Blend crossover
๋ธ๋ ๋ ๊ต์ฐจ
Order crossover
์์ ๊ธฐ๋ฐ ๊ต์ฐจ
Fitness driven crossover
์ ํฉ๋ ๊ธฐ๋ฐ ๊ต์ฐจ
โจ 4 - Objectives ํ์ต ๋ชฉํ
Understand what crossover is
๊ต์ฐจ๊ฐ ๋ฌด์์ธ์ง ์ดํดํฉ๋๋ค.
Introduce main crossover methods
์ฃผ์ ๊ต์ฐจ ๋ฐฉ๋ฒ๋ค์ ์๊ฐํฉ๋๋ค.
Get visualization and implementation of each method
๊ฐ ๋ฐฉ๋ฒ์ ์๊ฐํ์ ๊ตฌํ์ ํ์ธํฉ๋๋ค.
โจ 4.1 One-point crossover ๋จ์ผ ์ง์ ๊ต์ฐจ
In one-point crossover, a point in a gene sequence is randomly selected by dividing the gene sequence into two parts.
๋จ์ผ ์ง์ ๊ต์ฐจ๋ ์ ์ ์ ์์ด์์ ํ ์ง์ ์ ๋ฌด์์๋ก ์ ํํด, ์ด๋ฅผ ๋ ๋ถ๋ถ์ผ๋ก ๋๋๋ ๋ฐฉ์์
๋๋ค.
New individuals are created by crossing these two parts.
์ด ๋ ๋ถ๋ถ์ ์๋ก ๊ตํํ์ฌ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
Please take a look at the following figure.
๋ค์ ๊ทธ๋ฆผ์ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
One-point crossover can be applied to ordered gene and binary bin sets.
๋จ์ผ ์ง์ ๊ต์ฐจ๋ ์์๊ฐ ์๋ ์ ์ ์๋ ์ด์ง ์งํฉ์๋ ์ ์ฉํ ์ ์์ต๋๋ค.
If the gene sequence consists of one element, then a simple exchange of genes between the parents happens, and each of the children is a clone of one of the parents.
์ ์ ์ ์์ด์ด ํ๋์ ์์๋ง์ผ๋ก ์ด๋ฃจ์ด์ ธ ์๋ค๋ฉด ๋ถ๋ชจ ๊ฐ์ ๋จ์ํ ์ ์ ์ ๊ตํ์ด ์ผ์ด๋๋ฉฐ, ์์์ ๋ถ๋ชจ ์ค ํ ์ชฝ์ ๋ณต์ ๋ณธ์ด ๋ฉ๋๋ค.
Please take a look at the following figure.
๋ค์ ๊ทธ๋ฆผ์ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
If the gene sequence consists of two elements, then the genes are exchanged in a crisscross way.
์ ์ ์ ์์ด์ด ๋ ๊ฐ์ ์์๋ก ์ด๋ฃจ์ด์ ธ ์๋ค๋ฉด, ์ ์ ์๋ ์๊ฐ๋ฆฌ๋ ๋ฐฉ์์ผ๋ก ๊ตํ๋ฉ๋๋ค.
Please take a look at the following figure.
๋ค์ ๊ทธ๋ฆผ์ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
Here we will show an implementation of one-point crossover to an ordered gene set.
์ฌ๊ธฐ์๋ ์์๊ฐ ์๋ ์ ์ ์ ์งํฉ์ ๋จ์ผ ์ง์ ๊ต์ฐจ๋ฅผ ์ ์ฉํ ๊ตฌํ์ ๋ณด์ฌ์ค๋๋ค.
Import part
import copy
import randomOne-point crossover
def crossover_one_point(p1, p2):
point = random.randint(1, len(p1) - 1)
c1, c2 = copy.deepcopy(p1), copy.deepcopy(p2)
c1[point:], c2[point:] = p2[point:], p1[point:]
return [c1, c2]Example
random.seed(2)
p1 = [random.randint(0, 9) for _ in range(5)]
p2 = [random.randint(0, 9) for _ in range(5)]
offspring = crossover_one_point(p1, p2)
print(f'Parent 1: {p1}')
print(f'Parent 2: {p2}')
print(f'Child 1: {offspring[0]}')
print(f'Child 2: {offspring[1]}')Result
Parent 1: [1, 1, 0, 4, 3]
Parent 2: [3, 3, 2, 1, 8]
Child 1: [1, 1, 2, 1, 8]
Child 2: [3, 3, 0, 4, 3]๐ก ์ฃผ์ ๋จ์ด
| ์์ด ๋จ์ด | ํ๊ธ ๋ป |
|---|---|
| one-point | ๋จ์ผ |
| randomly | ๋ฌด์์๋ก |
| divide | ๋๋๋ค |
| exchange | ๊ตํ |
| clone | ๋ณต์ ๋ณธ |
| element | ์์ |
| crisscross | ์๊ฐ๋ฆผ |
| implementation | ๊ตฌํ |
| ordered | ์์๊ฐ ์๋ |
โจ 4.2 N-point crossover ๋ค์ค ์ง์ ๊ต์ฐจ
N-point crossover is a logical continuation of one-point crossover,
๋ค์ค ์ง์ ๊ต์ฐจ๋ ๋จ์ผ ์ง์ ๊ต์ฐจ์ ๋
ผ๋ฆฌ์ ์ธ ์ฐ์ฅ์ ์
๋๋ค.
but instead of choosing only one point in a gene sequence, N points are selected,
ํ๋์ ์ง์ ์ ์ ํํ๋ ๋์ , ์ ์ ์ ์์ด์์ N๊ฐ์ ์ง์ ์ ์ ํํฉ๋๋ค.
and genes are being exchanged in a crisscross way.
๊ทธ๋ฆฌ๊ณ ์ ์ ์๋ ์๊ฐ๋ฆฌ๋ ๋ฐฉ์์ผ๋ก ๊ตํ๋ฉ๋๋ค.
Please take a look at the following figure.
๋ค์ ๊ทธ๋ฆผ์ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
Letโs see an implementation of N-point crossover that is applied to an ordered gene set. ์์๊ฐ ์๋ ์ ์ ์ ์งํฉ์ ๋ค์ค ์ง์ ๊ต์ฐจ๋ฅผ ์ ์ฉํ ๊ตฌํ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
Import part
import copy
import randomN-point crossover
def crossover_n_point(p1, p2, n):
ps = random.sample(range(1, len(p1) - 1), n)
ps.append(0)
ps.append(len(p1))
ps = sorted(ps)
c1, c2 = copy.deepcopy(p1), copy.deepcopy(p2)
for i in range(0, n + 1):
if i % 2 == 0:
continue
c1[ps[i]:ps[i + 1]] = p2[ps[i]:ps[i + 1]]
c2[ps[i]:ps[i + 1]] = p1[ps[i]:ps[i + 1]]
return [c1, c2]Example
random.seed(3)
p1 = [random.randint(0, 9) for _ in range(6)]
p2 = [random.randint(10, 19) for _ in range(6)]
offspring = crossover_n_point(p1, p2, 3)
print(f'Parent 1: {p1}')
print(f'Parent 2: {p2}')
print(f'Child 1: {offspring[0]}')
print(f'Child 2: {offspring[1]}')Result
Parent 1: [3, 8, 9, 3, 8, 5]
Parent 2: [11, 13, 11, 11, 13, 13]
Child 1: [3, 13, 11, 3, 13, 5]
Child 2: [11, 8, 9, 11, 8, 13]๐ก ์ฃผ์ ๋จ์ด
| ์์ด ๋จ์ด | ํ๊ธ ๋ป |
|---|---|
| continuation | ์ฐ์ฅ์ , ํ์ฅ |
| crisscross | ์๊ฐ๋ฆผ |
โจ 4.3 Uniform crossover ๊ท ๋ฑ ๊ต์ฐจ
Uniform crossover randomly selects some points in the parentโs gene chain, and swaps the genes at these points.
๊ท ๋ฑ ๊ต์ฐจ๋ ๋ถ๋ชจ์ ์ ์ ์ ์์ด์์ ๋ช๋ช ์ง์ ์ ๋ฌด์์๋ก ์ ํํ๊ณ , ํด๋น ์ง์ ์ ์ ์ ์๋ฅผ ์๋ก ๊ตํํฉ๋๋ค.
Please take a look at the following figure.
๋ค์ ๊ทธ๋ฆผ์ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
Import part
import copy
import randomUniform crossover
def crossover_uniform(p1, p2, prop):
c1 = copy.deepcopy(p1)
c2 = copy.deepcopy(p2)
for i in range(len(p1)):
if random.random() < prop:
c1[i], c2[i] = p2[i], p1[i]
return [c1, c2]Example
random.seed(3)
p1 = [random.randint(0, 9) for _ in range(6)]
p2 = [random.randint(10, 19) for _ in range(6)]
offspring = crossover_uniform(p1, p2, 0.5)
print(f'Parent 1: {p1}')
print(f'Parent 2: {p2}')
print(f'Child 1: {offspring[0]}')
print(f'Child 2: {offspring[1]}')Result
Parent 1: [3, 8, 9, 3, 8, 5]
Parent 2: [19, 17, 11, 12, 15, 17]
Child 1: [3, 17, 9, 12, 8, 17]
Child 2: [19, 8, 11, 3, 15, 5]๐ก ์ฃผ์ ๋จ์ด
| ์์ด ๋จ์ด | ํ๊ธ ๋ป |
|---|---|
| uniform | ๋์ผํ, ๊ท ๋ฑํ |
| chain | ์ฌ์ฌ |
| swap | ๊ตํ |
| point | ์ง์ |
| probability | ํ๋ฅ |
โจ 4.4 Linear combination crossover ์ ํ ๊ฒฐํฉ ๊ต์ฐจ
Linear combination crossover is the example of a crossover without any randomness.
์ ํ ๊ฒฐํฉ ๊ต์ฐจ๋ ๋ฌด์์์ฑ์ด ์๋ ๊ต์ฐจ ๋ฐฉ์์ ์์์
๋๋ค.
Child genes is a simple linear combination of parent genes:
์์์ ์ ์ ์๋ ๋ถ๋ชจ ์ ์ ์์ ๋จ์ํ ์ ํ ๊ฒฐํฉ์ผ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค:
(xโ + ฮฑโฏ|xโย โย xโ|,ย xโย โย ฮฑโฏ|xโย โย xโ|), where ฮฑ is the parameter of linear combination in range [0, 1].
(xโ + ฮฑโฏ|xโย โย xโ|,ย xโย โย ฮฑโฏ|xโย โย xโ|), ์ฌ๊ธฐ์ ฮฑ๋ [0, 1] ๋ฒ์์ ์ ํ ๊ฒฐํฉ ๊ณ์์
๋๋ค.
NOTE : If ฮฑ equals 0 or 1, then children are the same as parents.
์ฐธ๊ณ : ฮฑ๊ฐ 0 ๋๋ 1์ด๋ฉด ์์์ ๋ถ๋ชจ์ ๋์ผํฉ๋๋ค.
If ฮฑ equals 0.5, then we have twins in offspring (both children are the same).
ฮฑ๊ฐ 0.5์ด๋ฉด ๋ ์์์ด ๋์ผํ ์๋ฅ์ด ๊ฐ์ฒด๊ฐ ์์ฑ๋ฉ๋๋ค.
If we want only new individuals to be created, then we can restrict ฮฑ to this range (0, 0.5).
ํญ์ ์๋ก์ด ๊ฐ์ฒด๋ง ์์ฑ๋๊ธฐ๋ฅผ ์ํ๋ค๋ฉด ฮฑ์ ๋ฒ์๋ฅผ (0, 0.5)๋ก ์ ํํ ์ ์์ต๋๋ค.
Letโs take a look at the following figure.
๋ค์ ๊ทธ๋ฆผ์ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
Implementation of linear crossover is just arithmetic operation applied to real gene set.
์ ํ ๊ฒฐํฉ ๊ต์ฐจ์ ๊ตฌํ์ ์ค์ํ ์ ์ ์ ์งํฉ์ ์ฐ์ ์ฐ์ฐ์ ์ ์ฉํ๋ ๊ฒ์ผ ๋ฟ์
๋๋ค.
Import part
import copy
import randomLinear crossover
def crossover_linear(p1, p2, alpha):
c1 = copy.deepcopy(p1)
c2 = copy.deepcopy(p2)
for i in range(len(p1)):
c1[i] = round(p1[i] + alpha * (p2[i] - p1[i]), 2)
c2[i] = round(p2[i] - alpha * (p2[i] - p1[i]), 2)
return [c1, c2]Example
random.seed(3)
p1 = [round(random.uniform(0, 10), 2) for _ in range(6)]
p2 = [round(random.uniform(0, 10), 2) for _ in range(6)]
offspring = crossover_linear(p1, p2, 0.3)
print(f'Parent 1: {p1}')
print(f'Parent 2: {p2}')
print(f'Child 1: {offspring[0]}')
print(f'Child 2: {offspring[1]}')Result
Parent 1: [4.16, 6.6, 1.62, 8.14, 9.58, 4.64]
Parent 2: [3.26, 0.2, 1.82, 2.91, 0.91, 7.12]
Child 1: [3.89, 4.57, 1.68, 6.51, 6.89, 5.39]
Child 2: [3.53, 2.22, 1.76, 4.54, 3.6, 6.37]๐ก ์ฃผ์ ๋จ์ด
| ์์ด ๋จ์ด | ํ๊ธ ๋ป |
|---|---|
| linear | ์ ํ์ |
| combination | ๊ฒฐํฉ |
| randomness | ๋ฌด์์์ฑ |
| parameter | ๋งค๊ฐ๋ณ์ |
| range | ๋ฒ์ |
| equal | ๊ฐ๋ค |
| twin | ์๋ฅ์ด |
| restrict | ์ ํํ๋ค |
| offspring | ์์ |
โจ 4.5 Blend crossover ํผํฉ ๊ต์ฐจ
Blend crossover method chooses random genes in the range defined by parent genes.
ํผํฉ ๊ต์ฐจ๋ ๋ถ๋ชจ ์ ์ ์์ ์ํด ์ ์๋ ๋ฒ์ ๋ด์์ ๋ฌด์์๋ก ์์ ์ ์ ์๋ฅผ ์ ํํ๋ ๋ฐฉ์์
๋๋ค.
The range for children genes is defined as follows:
์์ ์ ์ ์์ ๋ฒ์๋ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋ฉ๋๋ค:
[xโย โย ฮฑ(xโย โย xโ),ย xโย +ย ฮฑ(xโย โย xโ)], where ฮฑ is the parameter that expands the parent genes range.
[xโย โย ฮฑ(xโย โย xโ),ย xโย +ย ฮฑ(xโย โย xโ)], ์ฌ๊ธฐ์ ฮฑ๋ ๋ถ๋ชจ ์ ์ ์ ๋ฒ์๋ฅผ ํ์ฅํ๋ ๊ณ์์
๋๋ค.
Please take a look at the following figure.
๋ค์ ๊ทธ๋ฆผ์ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
Usually, ฮฑ = 0.5.
์ผ๋ฐ์ ์ผ๋ก ฮฑ๋ 0.5๋ก ์ค์ ๋ฉ๋๋ค.
Please take a look at the following figure 4.8:
๊ทธ๋ฆผ 4.8์ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
Like linear crossover, blend crossover is applied to a real gene set; letโs study an implementation.
์ ํ ๊ฒฐํฉ ๊ต์ฐจ์ฒ๋ผ, ํผํฉ ๊ต์ฐจ๋ ์ค์ํ ์ ์ ์ ์งํฉ์ ์ ์ฉ๋ฉ๋๋ค. ๊ตฌํ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
Import part
import copy
import randomBlend crossover
def crossover_blend(p1, p2, alpha):
c1 = copy.deepcopy(p1)
c2 = copy.deepcopy(p2)
for i in range(len(p1)):
l = min(c1[i], c2[i]) - alpha * abs(c2[i] - c1[i])
u = max(c1[i], c2[i]) + alpha * abs(c2[i] - c1[i])
c1[i] = round(l + random.random() * (u - l), 2)
c2[i] = round(l + random.random() * (u - l), 2)
return [c1, c2]Example
random.seed(3)
p1 = [round(random.uniform(0, 10), 2) for _ in range(6)]
p2 = [round(random.uniform(0, 10), 2) for _ in range(6)]
offspring = crossover_blend(p1, p2, 0.5)
print(f'Parent 1: {p1}')
print(f'Parent 2: {p2}')
print(f'Child 1: {offspring[0]}')
print(f'Child 2: {offspring[1]}')Result
Parent 1: [4.16, 6.6, 1.62, 8.14, 9.58, 4.64]
Parent 2: [3.26, 0.2, 1.82, 2.91, 0.91, 7.12]
Child 1: [3.95, 5.64, 1.72, 7.96, 8.41, 5.6]
Child 2: [3.84, 1.55, 1.77, 4.49, 5.29, 6.63]๐ก ์ฃผ์ ๋จ์ด
| ์์ด ๋จ์ด | ํ๊ธ ๋ป |
|---|---|
| blend | ํผํฉ |
| range | ๋ฒ์ |
| define | ์ ์ํ๋ค |
| expand | ํ์ฅํ๋ค |
| real | ์ค์ |
| uniform | ๊ท ์ผํ |
| random | ๋ฌด์์ |
โจ 4.6 Order crossover ์์ ๊ธฐ๋ฐ ๊ต์ฐจ
Order crossover is used for ordered genes; the main principle in this approach is to preserve the order of parent genes.
์์ ๊ธฐ๋ฐ ๊ต์ฐจ๋ ์์๊ฐ ์ค์ํ ์ ์ ์์ ์ฌ์ฉ๋๋ฉฐ, ์ด ๋ฐฉ์์ ํต์ฌ ์๋ฆฌ๋ ๋ถ๋ชจ ์ ์ ์์ ์์๋ฅผ ์ ์งํ๋ ๊ฒ์
๋๋ค.
We will show how this method works with an example:
์ด ๋ฐฉ๋ฒ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ์์ ๋ฅผ ํตํด ์ดํด๋ณด๊ฒ ์ต๋๋ค.
Say, we have two individuals with ordered genes:
๋ค์๊ณผ ๊ฐ์ด ์์๊ฐ ์๋ ์ ์ ์๋ฅผ ๊ฐ์ง ๋ ๊ฐ์ฒด๊ฐ ์๋ค๊ณ ๊ฐ์ ํฉ์๋ค:
Parent 1: (1, 7, 4, 5, 9, 2, 8, 3, 6)
๋ถ๋ชจ 1: (1, 7, 4, 5, 9, 2, 8, 3, 6)
Parent 2: (3, 1, 5, 4, 9, 8, 6, 2, 7)
๋ถ๋ชจ 2: (3, 1, 5, 4, 9, 8, 6, 2, 7)
We choose a random range in genes chain and swap it.
์ ์ ์ ์์ด์์ ๋ฌด์์๋ก ์ผ์ ๋ฒ์๋ฅผ ์ ํํ๊ณ , ํด๋น ๊ตฌ๊ฐ์ ๊ตํํฉ๋๋ค.
Please take a look at the following figure.
๋ค์ ๊ทธ๋ฆผ์ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
Now, we will try to find the next number in Parent which wasnโt mentioned in Child 1 yet:
์ด์ ๋ถ๋ชจ์ ์ ์ ์ ์ค ์์ 1์ ์์ง ํฌํจ๋์ง ์์ ๋ค์ ์ซ์๋ฅผ ์ฐพ์๋ณด๊ฒ ์ต๋๋ค.
Parent 1: (1, 7, 4, 5, 9, 2, 8 โ 3, 6) โ the next number is 3.
๋ถ๋ชจ 1: (1, 7, 4, 5, 9, 2, 8 โ 3, 6) โ ๋ค์ ์ซ์๋ 3์
๋๋ค.
Child 1: (X, X, 5, 4, 9, 8, 6, X, X) โ doesnโt contain 3 yet.
์์ 1: (X, X, 5, 4, 9, 8, 6, X, X) โ ์์ง 3์ ํฌํจ๋์ด ์์ง ์์ต๋๋ค.
Please take a look at the following figure.
๋ค์ ๊ทธ๋ฆผ์ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
The same happens for Child in Parent 2 โ the next number is 2, but it is already mentioned in Child 2 โ then we take the next one:
Parent 2์์๋ ๋ง์ฐฌ๊ฐ์ง๋ก ์์ 2์ ๋ํด ๋ค์ ์ซ์๊ฐ 2์ด์ง๋ง, ์ด๋ฏธ ์์ 2์ ํฌํจ๋์ด ์์ผ๋ฏ๋ก ๋ค์ ์ซ์๋ฅผ ํ์ธํฉ๋๋ค.
Parent 2: (3, 1, 5, 4, 9, 8, 6 โ 2, 7) โ the next number is 2.
๋ถ๋ชจ 2: (3, 1, 5, 4, 9, 8, 6 โ 2, 7) โ ๋ค์ ์ซ์๋ 2์
๋๋ค.
Child 2: (X, X, 4, 5, 9, 2, 8, X, X) โ already contains 2.
์์ 2: (X, X, 4, 5, 9, 2, 8, X, X) โ ์ด๋ฏธ 2๋ฅผ ํฌํจํ๊ณ ์์ต๋๋ค.
Checking the next number:
๋ค์ ์ซ์๋ฅผ ํ์ธํฉ๋๋ค:
Parent 2: (3, 1, 5, 4, 9, 8, 6, 2 โ 7) โ the next number is 7.
๋ถ๋ชจ 2: (3, 1, 5, 4, 9, 8, 6, 2 โ 7) โ ๋ค์ ์ซ์๋ 7์
๋๋ค.
Child 2: (X, X, 4, 5, 9, 2, 8, X, X) โ doesnโt contain 7 yet.
์์ 2: (X, X, 4, 5, 9, 2, 8, X, X) โ ์์ง 7์ ํฌํจ๋์ด ์์ง ์์ต๋๋ค.
Please take a look at the following figure.
๋ค์ ๊ทธ๋ฆผ์ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
Keep going for Child 1; the next Parent 1 number is 6 and this number is mentioned in Child 1 too, so weโre taking the next one:
์์ 1์ ๋ํด ๊ณ์ ์งํํฉ๋๋ค. ๋ค์ ๋ถ๋ชจ 1์ ์ซ์๋ 6์ธ๋ฐ, ์์ 1์ ์ด๋ฏธ ํฌํจ๋์ด ์์ผ๋ฏ๋ก ๋ค์ ์ซ์๋ฅผ ํ์ธํฉ๋๋ค.
Parent 1: (1, 7, 4, 5, 9, 2, 8, 3 โ 6) โ the next number is 6.
๋ถ๋ชจ 1: (1, 7, 4, 5, 9, 2, 8, 3 โ 6) โ ๋ค์ ์ซ์๋ 6์
๋๋ค.
Child 1: (X, X, 5, 4, 9, 8, 6, 3, X) โ already contains 6.
์์ 1: (X, X, 5, 4, 9, 8, 6, 3, X) โ ์ด๋ฏธ 6์ ํฌํจํ๊ณ ์์ต๋๋ค.
Checking the next number:
๋ค์ ์ซ์๋ฅผ ํ์ธํฉ๋๋ค:
Parent 1: (โ 1, 7, 4, 5, 9, 2, 8, 3, 6) โ the next number is 1.
๋ถ๋ชจ 1: (โ 1, 7, 4, 5, 9, 2, 8, 3, 6) โ ๋ค์ ์ซ์๋ 1์
๋๋ค.
Child 1: (X, X, 5, 4, 9, 8, 6, 3, X) โ doesnโt contain 1 yet.
์์ 1: (X, X, 5, 4, 9, 8, 6, 3, X) โ ์์ง 1์ ํฌํจ๋์ด ์์ง ์์ต๋๋ค.
Please take a look at the following figure.
๋ค์ ๊ทธ๋ฆผ์ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
We hope you have got the principle.
์ด์ ์๋ฆฌ๋ฅผ ์ดํดํ์
จ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
As a result, we will have the following offspring.
๊ทธ ๊ฒฐ๊ณผ๋ก ์ฐ๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ์ ์์ ๊ฐ์ฒด๋ค์ ์ป๊ฒ ๋ฉ๋๋ค.
Please take a look at the following figure.
๋ค์ ๊ทธ๋ฆผ์ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
In very high dimension tasks with a large number of variables, an execution of order crossover can be rather time-consuming;
๋ณ์๊ฐ ๋ง์ ๊ณ ์ฐจ์ ๋ฌธ์ ์์๋ ์์ ๊ธฐ๋ฐ ๊ต์ฐจ์ ์คํ์ด ์๋นํ ์๊ฐ์ ์๋ชจํ ์ ์์ต๋๋ค.
you have to pay attention to this fact by applying this method.
์ด ๋ฐฉ๋ฒ์ ์ ์ฉํ ๋๋ ์ด๋ฌํ ์ ์ ์ ์ํด์ผ ํฉ๋๋ค.
Implementation of order crossover
์์ ๊ธฐ๋ฐ ๊ต์ฐจ์ ๊ตฌํ์
๋๋ค.
Import part
import random
from math import nanOrder crossover
def crossover_order(p1, p2):
zero_shift = min(p1)
length = len(p1)
start, end = sorted([random.randrange(length) for _ in range(2)])
c1, c2 = [nan] * length, [nan] * length
t1, t2 = [x - zero_shift for x in p1], [x - zero_shift for x in p2]
spaces1, spaces2 = [True] * length, [True] * length
for i in range(length):
if i < start or i > end:
spaces1[t2[i]] = False
spaces2[t1[i]] = False
j1, j2 = end + 1, end + 1
for i in range(length):
if not spaces1[t1[(end + i + 1) % length]]:
c1[j1 % length] = t1[(end + i + 1) % length]
j1 += 1
if not spaces2[t2[(i + end + 1) % length]]:
c2[j2 % length] = t2[(i + end + 1) % length]
j2 += 1
for i in range(start, end + 1):
c1[i], c2[i] = t2[i], t1[i]
return [[x + zero_shift for x in c1], [x + zero_shift for x in c2]]Example
random.seed(10)
p1 = random.sample(range(1, 10), 9)
p2 = random.sample(range(1, 10), 9)
offspring = crossover_order(p1, p2)
print(f'Parent 1: {p1}')
print(f'Parent 2: {p2}')
print(f'Child 1: {offspring[0]}')
print(f'Child 2: {offspring[1]}')Result
Parent 1: [7, 4, 6, 1, 9, 3, 2, 5, 8]
Parent 2: [3, 2, 6, 1, 7, 5, 4, 8, 9]
Child 1: [7, 4, 6, 1, 9, 5, 8, 3, 2]
Child 2: [3, 2, 6, 1, 7, 3, 9, 4, 8]๐ก ์ฃผ์ ๋จ์ด
| ์์ด ๋จ์ด | ํ๊ธ ๋ป |
|---|---|
| order | ์์ |
| preserve | ์ ์ง |
| mention | ์ธ๊ธ |
| contain | ํฌํจ |
| execution | ์ํ |
| time-consuming | ์๋ชจ์ |
| pay attention | ์ ์ |
| variable | ๋ณ์ |
| high dimension | ๊ณ ์ฐจ์ |
| space | ์๋ฆฌ |
โจ 4.7 Fitness driven crossover
Fitness driven crossover is an approach that compares the child to the parent and selects the best one.
์ ํฉ๋ ๊ธฐ๋ฐ ๊ต์ฐจ๋ ์์๊ณผ ๋ถ๋ชจ๋ฅผ ๋น๊ตํ์ฌ ๋ ๋์ ๊ฐ์ฒด๋ฅผ ์ ํํ๋ ๋ฐฉ์์
๋๋ค.
The main principle of this approach is that children should be better than their parents or not at all.
์ด ๋ฐฉ์์ ํต์ฌ ์๋ฆฌ๋ ์์์ด ๋ถ๋ชจ๋ณด๋ค ๋ ๋์์ผ ํ๋ฉฐ, ๊ทธ๋ ์ง ์์ผ๋ฉด ์์ ์ ํ๋์ง ์๋๋ค๋ ๊ฒ์
๋๋ค.
In some tasks, the crossing operation is very unpredictable, and carries a high risk of destroying the accumulated positive experience.
์ผ๋ถ ๋ฌธ์ ์์๋ ๊ต์ฐจ ์ฐ์ฐ์ด ๋งค์ฐ ์์ธก ๋ถ๊ฐ๋ฅํ๋ฉฐ, ์ถ์ ๋ ๊ธ์ ์ ์ธ ๊ฒฝํ์ ๋ง๊ฐ๋จ๋ฆด ์ํ์ด ํฝ๋๋ค.
Then, as soon as the individuals appear to begin to adapt well to the environment, their genotype can be destroyed after crossing,
์ด๋ฌํ ๊ฒฝ์ฐ, ๊ฐ์ฒด๊ฐ ํ๊ฒฝ์ ์ ์ ์ํ๊ธฐ ์์ํ ์๊ฐ ๊ต์ฐจ๋ก ์ธํด ์ ์ ํ์ด ํ๊ดด๋ ์ ์์ต๋๋ค.
and as a result, their unique genetic adaptation will be destroyed.
๊ทธ ๊ฒฐ๊ณผ, ๊ฐ์ฒด์ ๊ณ ์ ํ ์ ์ ์ ์ ์๋ ฅ์ด ์ฌ๋ผ์ง ์ ์์ต๋๋ค.
Please take a look at the following figure.
๋ค์ ๊ทธ๋ฆผ์ ์ฐธ๊ณ ํด ์ฃผ์ธ์.
NOTE: You can notice that fitness driven crossover shares the same principle as elite selection which we covered in Chapter 3: Selection โ not to lose valuable individuals.
์ฐธ๊ณ : ์ ํฉ๋ ๊ธฐ๋ฐ ๊ต์ฐจ๋ 3์ฅ์์ ๋ค๋ฃฌ ์๋ฆฌํธ ์ ํ๊ณผ ๋์ผํ ์๋ฆฌ๋ฅผ ๊ณต์ ํฉ๋๋ค โ ์ค์ํ ๊ฐ์ฒด๋ฅผ ์์ง ์๋๋ก ํ๋ ๊ฒ์
๋๋ค.
And a reasonable question could be: Why not always do this? Why donโt we protect the best ones all the time?
์ด๋ ์์ฐ์ค๋ฝ๊ฒ ์๊ธฐ๋ ์ง๋ฌธ์ ์ด๊ฒ์
๋๋ค: ์ ํญ์ ์ด๋ ๊ฒ ํ์ง ์์๊น? ์ ์ต์ ๊ฐ์ฒด๋ฅผ ๋งค๋ฒ ๋ณดํธํ์ง ์์๊น?
Sometimes it makes sense, but evolution is very tricky and unpredictable thing; sometimes it can make one step back and two steps forward.
๋๋๋ก ๊ทธ๋ ๊ฒ ํ๋ ๊ฒ์ด ํ๋นํ์ง๋ง, ์งํ๋ ๋งค์ฐ ๋ณต์กํ๊ณ ์์ธก ๋ถ๊ฐ๋ฅํ์ฌ, ๋๋ก ํ ๊ฑธ์ ๋ค๋ก ๊ฐ๋ค๊ฐ ๋ ๊ฑธ์ ์์ผ๋ก ๋์๊ฐ๊ธฐ๋ ํฉ๋๋ค.
Tiny mammals from the Jurassic period lived on the brink of survival, but after millions of years, this species led to the appearance of human.
์ฅ๋ผ๊ธฐ ์๋์ ์์ ํฌ์ ๋ฅ๋ ์์กด์ ๋ฒผ๋ ๋์ ์์์ง๋ง, ์๋ฐฑ๋ง ๋
ํ ์ธ๋ฅ์ ํ์์ผ๋ก ์ด์ด์ก์ต๋๋ค.
We will get back to this question in further chapters.
์ด ์ง๋ฌธ์ ์ดํ ์ฅ์์ ๋ค์ ๋ค๋ฃจ๊ฒ ์ต๋๋ค.
Fitness driven crossover can be based on any other crossover method.
์ ํฉ๋ ๊ธฐ๋ฐ ๊ต์ฐจ๋ ์ด๋ค ๊ต์ฐจ ๋ฐฉ์ ์์์๋ ๊ตฌํํ ์ ์์ต๋๋ค.
For example, letโs examine the implementation of fitness driven crossover based on blend crossover.
์๋ฅผ ๋ค์ด, ํผํฉ ๊ต์ฐจ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ ์ ํฉ๋ ๊ธฐ๋ฐ ๊ต์ฐจ ๊ตฌํ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
Import part
import copy
import random
from math import sin, cosIndividual
def fitness_function(x, y):
return sin(x) * cos(y)
class Individual:
def __init__(self, x, y) -> None:
self.gene_set = [x, y]
self.fitness = fitness_function(x, y)
def __str__(self):
return f'x: {self.gene_set[0]}, ' \
f'y: {self.gene_set[1]}, ' \
f'fitness: {round(self.fitness, 4)}'
def generate_random():
return Individual(round(random.random(), 2),
round(random.random(), 2))Fitness driven blend crossover
def crossover_fitness_driven_blend(ind1, ind2, alpha):
c1 = copy.deepcopy(ind1.gene_set)
c2 = copy.deepcopy(ind2.gene_set)
for i in range(len(c1)):
l = min(c1[i], c2[i]) - alpha * abs(c2[i] - c1[i])
u = max(c1[i], c2[i]) + alpha * abs(c2[i] - c1[i])
c1[i] = round(l + random.random() * (u - l), 2)
c2[i] = round(l + random.random() * (u - l), 2)
child1 = Individual(c1[0], c1[1])
child2 = Individual(c2[0], c2[1]) # ๊ต์ฌ์๋ (c1[0], c1[1])๋ก ๋์์๋๋ฐ ์์ ํด์ผ ํจ
candidates = [ind1, ind2, child1, child2]
best = sorted(candidates, key=lambda ind: ind.fitness, reverse=True)
return best[0:2]Example
random.seed(3)
p1, p2 = generate_random(), generate_random()
offspring = crossover_fitness_driven_blend(p1, p2, 0.5)
print(f'Parent 1: {p1}')
print(f'Parent 2: {p2}')
print(f'Child 1: {offspring[0]}')
print(f'Child 2: {offspring[1]}')Result
Parent 1: x: 0.24, y: 0.13, fitness: 0.2345
Parent 2: x: 0.1, y: 0.84, fitness: 0.0672
Child 1: x: 0.24, y: 0.13, fitness: 0.2345
Child 2: x: 0.23, y: 0.24, fitness: 0.2245We see that Child 1 is the copy of Parent. ์์ 1์ ๋ถ๋ชจ์ ๋ณต์ ๋ณธ์์ ํ์ธํ ์ ์์ต๋๋ค.
๐ก ์ฃผ์ ๋จ์ด
| ์์ด ๋จ์ด | ํ๊ธ ๋ป |
|---|---|
| driven | ๊ธฐ๋ฐ |
| destroy | ํ๊ดด |
| accumulate | ์ถ์ |
| adaptation | ์ ์ |
| unpredictable | ์์ธก๋ถ๊ฐ |
| survival | ์์กด |
| brink | ์ง์ |
| species | ์ข |
| appearance | ์ถํ |
โจ 4 - Conclusion ๊ฒฐ๋ก
Crossover is a very specific evolutionary method.
๊ต์ฐจ๋ ๋งค์ฐ ๋
ํนํ ์งํ ๋ฐฉ์์
๋๋ค.
While the selection is an objective factor that is determined by nature and environment,
์ ํ์ ์์ฐ๊ณผ ํ๊ฒฝ์ ์ํด ๊ฒฐ์ ๋๋ ๊ฐ๊ด์ ์ธ ์์์ธ ๋ฐ๋ฉด,
the crossover mechanisms for each species can be very different.
๊ต์ฐจ ๋ฉ์ปค๋์ฆ์ ์ข
๋ง๋ค ๋งค์ฐ ๋ค๋ฅผ ์ ์์ต๋๋ค.
There are insect species that may not use crossbreeding as such!
์ด๋ค ๊ณค์ถฉ ์ข
์ ๊ต๋ฐฐ ์์ฒด๋ฅผ ์ฌ์ฉํ์ง ์๊ธฐ๋ ํฉ๋๋ค!
So, in genetic algorithms, crossover methods are chosen only as the source of the problem to be solved,
๋ฐ๋ผ์ ์ ์ ์๊ณ ๋ฆฌ์ฆ์์๋ ๋ฌธ์ ์ ์ฑ๊ฒฉ์ ๋ง๊ฒ ๊ต์ฐจ ๋ฐฉ์์ ์ ํํฉ๋๋ค.
and it is impossible to decide in advance which method is better.
์ด๋ค ๋ฐฉ์์ด ๋ ๋์์ง๋ ์ฌ์ ์ ๊ฒฐ์ ํ ์ ์์ต๋๋ค.
An incorrectly chosen crossover method can stop the evolutionary improvement of a population,
์๋ชป ์ ํ๋ ๊ต์ฐจ ๋ฐฉ์์ ๊ฐ์ฒด๊ตฐ์ ์งํ์ ๋ฐ์ ์ ๋ฉ์ถ๊ฒ ํ ์ ์์ผ๋ฉฐ,
and therefore make the search for a solution ineffective.
๊ทธ ๊ฒฐ๊ณผ, ํด๋ฅผ ์ฐพ๋ ๊ณผ์ ์ด ๋นํจ์จ์ ์ด ๋ ์ ์์ต๋๋ค.
In the next chapter, we will study the last part of evolution called mutation.
๋ค์ ์ฅ์์๋ ์งํ์ ๋ง์ง๋ง ๋จ๊ณ์ธ ๋์ฐ๋ณ์ด์ ๋ํด ํ์ตํ๊ฒ ์ต๋๋ค.
โจ 4 - Points to remember ๊ธฐ์ตํ ์
Each crossover method has the principle: Try to change the experience of individuals, but not to make soup of the genes, destroying the whole gene structure.
๋ชจ๋ ๊ต์ฐจ ๋ฐฉ์์ ํ๋์ ์์น์ ๋ฐ๋ฆ
๋๋ค: ๊ฐ์ฒด์ ๊ฒฝํ์ ๋ฐ๊พธ๋, ์ ์ ์๋ฅผ ๋ค์์ด ์ ์ฒด ๊ตฌ์กฐ๋ฅผ ํ๊ดดํ์ง๋ ๋ง ๊ฒ.
There is no predetermined list of crossover methods.
๊ต์ฐจ ๋ฐฉ์์๋ ๋ฏธ๋ฆฌ ์ ํด์ง ๋ชฉ๋ก์ด ์๋ ๊ฒ์ด ์๋๋๋ค.
You can implement your own crossover method for specific task.
๋ฌธ์ ์ ์ฑ๊ฒฉ์ ๋ฐ๋ผ ์์ ๋ง์ ๊ต์ฐจ ๋ฐฉ๋ฒ์ ๊ตฌํํ ์ ์์ต๋๋ค.
โจ 4 - Multiple choice questions ๊ฐ๊ด์ ๋ฌธ์
Question 1
We have a population of individuals with genes: where x and y lie in range (-10, 10).
x์ y๊ฐ (-10, 10) ๋ฒ์์ ์๋ ์ ์ ์๋ฅผ ๊ฐ์ง ๊ฐ์ฒด๊ตฐ์ด ์์ต๋๋ค.
We use blend crossover with ฮฑ = 0 in our genetic algorithm flow (without mutation).
์ฐ๋ฆฌ๋ ๋์ฐ๋ณ์ด ์์ด ฮฑ = 0์ธ ๋ธ๋ ๋ ๊ต์ฐจ๋ง์ ์ฌ์ฉํ๋ ์ ์ ์๊ณ ๋ฆฌ์ฆ ํ๋ฆ์ ์ ์ฉํฉ๋๋ค.
What can we say about our population after 50 generations?
50์ธ๋๊ฐ ์ง๋ ํ ๊ฐ์ฒด๊ตฐ์ ๋ํด ์ด๋ค ํ์์ด ๋ํ๋ ๊น์?
-
All individuals will be concentrated near one point because the best solution will be found.
๋ชจ๋ ๊ฐ์ฒด๊ฐ ํ๋์ ์ ๊ทผ์ฒ๋ก ๋ชจ์ผ ๊ฒ์ ๋๋ค. ์๋ํ๋ฉด ์ต์ ํด๊ฐ ๋ฐ๊ฒฌ๋์๊ธฐ ๋๋ฌธ์ ๋๋ค. -
All individuals will be uniformly distributed in square (-10,10) ร (-10,10).
๋ชจ๋ ๊ฐ์ฒด๊ฐ (-10,10) ร (-10,10) ์ฌ๊ฐํ ์์ญ์ ๊ท ๋ฑํ๊ฒ ๋ถํฌ๋ ๊ฒ์ ๋๋ค. -
โ All individuals will be concentrated near one point because blend crossover with ฮฑ = 0 doesnโt expand the range of genes and all children genes will be shrinking.
โ ๋ชจ๋ ๊ฐ์ฒด๋ ํ๋์ ์ ๊ทผ์ฒ์ ์ง์ค๋ ๊ฒ์ ๋๋ค. ฮฑ = 0์ธ ๋ธ๋ ๋ ๊ต์ฐจ๋ ์ ์ ์ ๋ฒ์๋ฅผ ํ์ฅํ์ง ์์ผ๋ฉฐ, ๋ชจ๋ ์์ ์ ์ ์๊ฐ ์ ์ ์๋ ด๋๊ธฐ ๋๋ฌธ์ ๋๋ค.
Question 2
We have a population of individuals with ordered genes: (1 2,โฆ,9).
์ ๋ ฌ๋ ์ ์ ์ (1, 2, โฆ, 9)๋ฅผ ๊ฐ์ง ๊ฐ์ฒด๊ตฐ์ด ์์ต๋๋ค.
Our gene structure is very fragile and there is a high probability that after each crossover, new offspring will be worse than their parents.
์ฐ๋ฆฌ์ ์ ์ ์ ๊ตฌ์กฐ๋ ๋งค์ฐ ๋ฏผ๊ฐํด์, ๊ต์ฐจ ์ดํ ์์์ด ๋ถ๋ชจ๋ณด๋ค ๋ชปํ ๊ฒฝ์ฐ๊ฐ ์์ฃผ ๋ฐ์ํฉ๋๋ค.
What approach can we use to solve that issue?
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ด๋ค ์ ๊ทผ์ ์ฌ์ฉํ ์ ์์๊น์?
-
Order Crossover
์์ ๊ธฐ๋ฐ ๊ต์ฐจ -
โ Fitness Driven Crossover based on Order Crossover
โ ์์ ๊ธฐ๋ฐ ๊ต์ฐจ๋ฅผ ๋ฐํ์ผ๋ก ํ ์ ํฉ๋ ๊ธฐ๋ฐ ๊ต์ฐจ : ์์ ์ ์ง + ์ฑ๋ฅ ๋ณด์ฅ์ด๋ผ๋ ๋ ๊ฐ์ง ์กฐ๊ฑด์ ๋ง์กฑ -
One Point Crossover
๋จ์ผ ์ง์ ๊ต์ฐจ -
Fitness Driven Crossover based on Uniform Crossover
๊ท ๋ฑ ๊ต์ฐจ๋ฅผ ๋ฐํ์ผ๋ก ํ ์ ํฉ๋ ๊ธฐ๋ฐ ๊ต์ฐจ
โจ 4 - Questions ์ง๋ฌธ
1. Why the usage of blend crossover with very high ฮฑ can lead to poor results of genetic algorithm execution?
๋ธ๋ ๋ ๊ต์ฐจ์์ ฮฑ ๊ฐ์ด ๋๋ฌด ํด ๊ฒฝ์ฐ, ์ ์ ์ ์๊ณ ๋ฆฌ์ฆ์ ์ฑ๋ฅ์ด ๋จ์ด์ง ์ ์์๊น์?
โ๏ธ ฮฑ๊ฐ ๋๋ฌด ํฌ๋ฉด ์์ ์ ์ ์๊ฐ ๋ถ๋ชจ ๋ฒ์๋ฅผ ํจ์ฌ ๋์ด์๊ฒ ๋์ด, ๋ฌด์์์ฑ์ด ๊ณผ๋ํ๊ฒ ์ปค์ง๊ณ ์ ์ฉํ ์ ์ ์ ๊ตฌ์กฐ๊ฐ ์์๋ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
2, Say we have a real gene set for genetic algorithm finding maxima of multivariable function f(x, y, z). Can we get acceptable results with the usage of order crossover here?
f(x, y, z)๋ผ๋ ๋ค๋ณ์ ํจ์์ ์ต๋๊ฐ์ ์ฐพ๋ ์ ์ ์๊ณ ๋ฆฌ์ฆ์์ ์ค์ํ ์ ์ ์ ์งํฉ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ์์ ๊ธฐ๋ฐ ๊ต์ฐจ๋ฅผ ์ ์ฉํด๋ ๊ด์ฐฎ์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์๊น์?
โ๏ธ ์๋์. ์์ ๊ธฐ๋ฐ ๊ต์ฐจ๋ ์์ด ๊ธฐ๋ฐ ์ ์ ์(์: ์ธํ์ ๋ฌธ์ )์ฒ๋ผ ์์๊ฐ ์ค์ํ ๋ฌธ์ ์ ๋ง์ถฐ ์ค๊ณ๋ ๋ฐฉ์์ด๊ธฐ ๋๋ฌธ์ ๋๋ค.