GA - 자원운송계획 - 재생산

4. 재생산
8193개의 개체들 중 최고적응도의 개체를 골라 엘리트로 복사하고, 나머지 8192개의 개체는 유전자알고리즘을 사용해 재생산했습니다.
T=0.99의 Tournament법을 사용하여 우수개체를 골라 교차 및 돌연변이를 일으켰습니다.

5. 교차
일반적인 유전자알고리즘의 경우와 같이 여기서도 재생산 대상을 두개 선택한 후 그들을 교차시킵니다. 그러나 유전자가 예전의 1차원 유전자가 아니라 2차원 유전자라는 문제가 있습니다.
일반적으로 2차원 유전자의 교차는 (아니 1차원부터 2차원, 3차원 이상의 고차원 유전자의 교차는) 구획나누기 이후 구획 재배치로 정의될 수 있습니다. 문제는 구획을 어떻게 나누느냐가 됩니다.
다음의 보기는 2차원의 경우이지만 n차원으로 확장시킬 수 있습니다.

① 다음 그림과 같이 x, y축을 몇개의 구획으로 나눕니다. 그후 아래 그림과 같이 순서대로 교차시키는 것입니다. 이것은 1차원교차에서 주로 사용했던 n점교차를 확장한 형태입니다.

② 또다른 방법은 구획을 다음 그림과 같이 도형으로 나누는 경우도 있습니다. 이 경우에는 구획 재배치가 쉽지 않아 보이지만, 간단히 짝수(0 포함) 또는 홀수개의 도형에 포함되는 구획만 교환하면 생각보다 쉽게 됩니다.

③ 마지막으로 임의로 선을 그어 구획을 나눌 수 있습니다.
①, ②번은 각각 하나의 축만, 그리고 각 차원에서의 원/구를 생각하면 되므로 4차원 이상의 유전자에도 비교적 쉽게 적용할 수 있습니다. 그러나 ③번은, 개념적으로는 3차원에서는 3각형평면의 연속, 4차원에서는 삼각뿔 도형의 연속, ... 등으로 할 수 있으나 직관적으로 다가오지 않아 상당히 어려운 작업이 될 수 있습니다.
여기서는 3개의 임의의 원을 그려 ②번과 같은 식의 교차를 시행했습니다.

procedure CrossOver(MoonBase a, MoonBase b)
.. // 세개의 임의의 원을 만듦
.. for k := 0, 3 do
..... circle[k].f := Random(0, 10) // 유전자크기가 10X10이므로
..... circle[k].t := Random(0, 10)
..... circle[k].radius := Random(0, 10)
.. end
.. for f := 0, 10 do
..... for t := 0, 10 do
........ covered := 0
........ // 3개 원중 몇개에 겹쳐지는지 계산
........... for k := 0, 3 do
.............. // (f,t)와 k번째 원 중심간 거리 계산
.............. df := f - circle[k].f
.............. dt := t - circle[k].t
.............. dist := sqrt(df * df + dt * dt)
.............. // 만약 거리가 반지름보다 작다면(원에 포함된다면)
.............. if dist < circle[k].radius then
................. covered := covered + 1
.............. end
........... end
........ if covered % 2 then // 홀수개에 겹쳐져 있다면 교환
........... temp := a[f][t]
........... a[f][t] := b[f][t]
........... b[f][t] := temp
........ end
..... end
.. end
end


6. 돌연변이
10×10개의 칸 하나하나에 대해 돌연변이를 적용시킵니다.

procedure Mutantation(Gene gene)
.. for f := 1, 10 do
..... for t := 1, 10 do
........ if gene[f][t] == 0 then
........... if MutantationRate then
............. gene[f][t] := Random(0, 10)
........... end
........ else // f->t로의 운송량 있을 경우
........... if MutantationRate then // 운송을 제거
............. gene[f][t] := 0
........... end
........... else if MutantationRate then // 운송량 변경
............. gene[f][t] := gene[f][t] + Random(-1, 1)
........... end
........... else if MutantationRate then // 운송을 나눔
............. T := Random(1, 3)
............. split := Random(0, gene[f][t])
............. gene[f][t] := gene[f][t] - split
............. gene[f][T] := gene[f][t] + split
........... end
........ end

..... end
.. end
end

GA - 자원운송계획 - 유전자설계

다음과 같이 A~J까지 10개의 도시가 배치되어 있습니다.


몇몇 도시에서는 어떤 자원이 생산되며 그 자원은 모든 도시에서 조금씩 소비됩니다. 각 도시들의 자원생산량과 소비량은 다음과 같습니다.

A : 0/ 5
B : 0/ 3
C : 7/ 5
D : 0/ 7
E : 0/ 2
F : 5/ 2
G : 23/ 3
H : 0/ 7
I : 5/ 3
J : 0/ 3

그러므로 각 도시에서 남아도는 자원을 모자라는 도시로 옮기는 수송계획을 짜야 합니다.
이때 가장 경제적으로 수송하기 위해서는 어떻게 해야 할까요? 문제를 간단히 하기 위해 각 자원을 운송하는 비용은 두 도시 사이의 거리에만 관계되는 것으로 합니다.

1. 유전자 설계
여기서는 2차원 유전자를 적용하기로 하겠습니다.
유전자의 구조는 오른쪽 그림과 같습니다. 각각 from도시에서 to 도시로 옮기는 자원량으로 정의합니다.
오른쪽 유전자에 의하면 A도시에서 B도시로 2개, C도시로 6개, E도시로 2개...를 옮긴다는 뜻입니다(물론 A에서 C로 6개 옮겼다가 다시 C에서 A로 6개 옮기니 이 유전자의 적응도는 매우 낮겠지만 말입니다).
기존에는 1차원 선형 유전자만 가지고 놀았지만, 이 문제에서도 유전자가 2차원으로 확장되었다는 것만 빼고는 동일합니다. 다만 1차원유전자에서 사용하던 교차기법은 사용할 수가 없습니다(2차원 이상 다차원유전자의 교차기법은 뒤에서 다루도록 하겠습니다).

2. 유전자초기화
유전자초기화는 일반적인 경우와 동일합니다. 10×10의 매트릭스를 만들고 각 칸을 0으로 만듦니다

procedure GeneInit(Gene gene)
.. for from := 0, 10 do
..... for to := 0, 10 do
........ gene[from][to] := 0
..... end
.. end
end

8193개의 개체를 만들고 각각의 유전자를 위와 같이 초기화시킵니다.

3. 적응도테스트
적응도를 계산하기 위한 요소는 두가지가 있습니다. 먼저 저 유전자대로 자원을 옮기기 위한 연료, 그리고 상품을 다 옮긴 후 필요량을 잘 채웠는지 판단이 필요합니다
① 연료
물건을 옮기기 위한 연료를 계산합니다. 도시간 운송을 위한 연료량은 도시간 거리에만 비례하므로 필요한 연료량은 (자원량) * (도시간 거리)입니다.
그러나 이렇게만 하면 한가지 문제가 생깁니다. 위의 유전자 보기에서처럼 B도시에서 B도시로 8개의 자원을 옮길 경우 연료가 0이므로 이러한 단점을 거를 수가 없는 것입니다. 그러므로 트럭 시동걸 때의 연료를 추가해서 (자원량) * (도시간 거리 + 1)을 필요한 연료량으로 정의합니다.

function FuelExhause(Gene gene, CityList citylist)
.. fuel := 0
.. for from := 0, 10 do
..... for to := 0, 10 do
........ quantity := gene[from][to]
........ distance := DistanceCalculate(from, to) // from도시와 to도시 사이의 거리
........ fuel := fuel + quantity * (distance + 1)
..... end
.. end
.. return fuel
end

② 자원 과부족 상황
유전자에 기록된 대로 자원을 옮긴 후 제대로 자원이 분배되었는지 확인해야 합니다. 각 도시별로 남거나 모자라는 자원의 합을 계산합니다.

function ResourceLeak(CityList citylist)
.. leak := 0
.. for city := 0, 10 do
..... cityleak := citylist[city].Need - citylist[city].AfterTransport
..... if cityleak < 0 then
........ cityleak := -cityleak
..... end
..... leak := leak + cityleak
.. end
.. return leak
end

③ 총 적응도 계산
위에서 계산한 FuelExhause와 ResourceLeak을 가지고 총 적응도를 계산합니다. 이때 둘 다 작을수록 적응도가 높으므로 총 적응도는 다음과 같이 계산합니다.

TotalFitness := -FuelExhause - ResourceLeak * 50

이때 연료보다는 자원배분이 더 중요하므로 ResourceLeak쪽에 50배의 가중치를 더 주었습니다(만약 이 가중치가 없다면, 유전자알고리즘은 차라리 자원을 운송하지 않고 연료를 아끼는 쪽으로 갈 수도 있습니다).

창조론 이야기 - 공룡과 진화론


창조론자들이 종종 언급하는 이야기에 공룡이야기가 있습니다.
'공룡은 지금까지 살아있으며 성경에 언급되어 있다. 그러므로 진화론은 거짓이다'
http://blog.naver.com/actionmancry/40100367174

하지만 정말 공룡이 살아있다고 해서 진화론이 타격을 입을까요?

1. 공룡이 살아있다고 해서 진화론에 영향이 있을까?
전혀요, 진화론은 '생물의 분화'를 연구하는 학문이지 '생물의 전멸'을 연구하는 학문이 아닙니다. 살아있는 공룡이 발견되었다고 해도 진화론에는 아무런 타격이 없습니다. 공룡이 최근까지 살아있었다면 지금껏 쌓아온 진화론이 무너진다고 생각하는 것은 창조론자들의 착각일 뿐입니다.

2. 무엇보다 공룡이 현재까지 발견되지 않고 살아있을 수 있을까?
지금까지 인류는 지구 탐험을 거의 완료했습니다. 인간의 손이 닿지 않은 곳은 깊은 밀림 속과 깊은 바닷속 뿐입니다. 과연 공룡이 지금까지 살아있다면, 더구나 곤충처럼 작은 생물이 아니라 성경에서 말하는 그런 거대한 공룡이 살아있다면, 인간의 눈에 띄지 않고 숨어있을 수 있을까요?
공룡의 수명이 수천만년이 아닌 이상 지금까지 존재하기 위해서는 종을 유지할 수 있어야 합니다. 그리고 종을 유지하기 위해서는 최소 수백 이상의 개체군이 필요합니다.
거대한 공룡 수백마리가 아직까지 인간들 눈에 띄지 않고 숨어있다... 저는 창조론자가 아니라서 그런지 수백마리 공룡이 인간들의 눈을 피해 숨어있는 것을 상상하기가 상당히 힘들군요.

3. 그렇다면 성경의 베히모스는 정말로 공룡일까?
제가 보기에 성경의 베히모스는 정말로 공룡이었을지도 모릅니다. 공룡 화석이 침식에 의해 일부 드러나는 경우는 흔하니까요.
아래 그림과 같이 바위에 박혀 있는 거대한 뼈를 보고 사람들은 무슨 생각을 했을까요? 지금이야 여러가지 연대측정법을 동원해서 수천만년~수억년 전의 동물이라고 알 수 있습니다만, 고대인들이 연대측정을 할 수 있었을까요? 그러한 뼈를 보고 동양에서는 용을, 북유럽에서는 드래곤을, 그리스에서는 키메라나 히드라를 상상한 것처럼 유대인들은 베히모스를 상상한 것입니다. 모두들 동시대에 살고 있는 거대한 동물들이라고 생각한 것이죠.
참고 : http://28boy.tistory.com/591