레이블이 공진화인 게시물을 표시합니다. 모든 게시물 표시
레이블이 공진화인 게시물을 표시합니다. 모든 게시물 표시

진화론 이야기 - 꽃과 벌

가끔씩 창조론자들의 말을 들어보면 '저들은 진화론을 창조론처럼 이해하고 있구나'라는 생각이 들곤 합니다.

벌은 꽃의 꿀을 먹고 산다. 꽃이 없다면 벌은 모두 굶어죽을 것이다.
꽃은 벌이 수정을 해주어야 한다. 벌이 없다면 꽃들은 열매를 맺지 못할 것이다.
벌과 꽃이 동시에 진화해서 나타난다는 것이 가능할 것인가?
차라리 누군가가 동시에 설계했다는 것이 더 합리적인 것이 아닌가?

즉 창조론에서 모든것이 지금 있는 그대로 창조된 것처럼 모든것이 지금 있는 그대로 진화된 것으로 이해하고 있는 것처럽 보입니다.
하지만, 늘 하는 말이지만, 진화는 포켓몬식 진화가 아닙니다. '꽃'이란 식물기관과 '벌'이란 곤충이 어느 순간 '뿅' 하고 나타난 것이 아니란 말이죠.
또 한편으로는 '둘은 절대로 떨어질 수 없이 밀접한 관련을 맺고 있다/둘은 아무 관계도 아니다'라는 흑백논리 역시 한몫을 하고 있다고 봅니다.

지금도 소나무 등은 곤충에 의해 수정되지 않습니다. 꽃가루를 바람에 날려 암꽃에 전달하죠. 먼 옛날 식물들은 벌(일단 벌의 선조지만 그냥 벌이라 하겠습니다) 없이도 수정되어 번식을 할 수 있었다는 것이죠.
나무에 따라 꽃가루의 성분은 다양합니다. 어느날 벌들이 자신의 입맛에 맞는 꽃가루를 먹기 시작했습니다(물론 원래 먹이도 같이 먹습니다). 식물의 입장에서 꽃가루를 먹히는 것은 손해지만, 대신 꽃가루를 찾아다니는 벌들에 의해 더욱 쉽고 확실하게 수정이 이루어질 수 있었습니다. 즉, '벌에 먹히는 꽃가루를 가진 식물 - 꽃'은 더욱 번성을 하고, 마찬가지로 벌들도 풍부해진 먹이 덕분에 번성할 수 있었습니다.

나무들 사이에서도 여기저기서 냄새를 풍기는 것들이 있었습니다. 어떤 녀석은 잎에서, 어떤 녀석
은 줄기에서, 어떤 녀석은 꽃가루에서...
벌들 사이에서도 여러가지 냄새를 감지하는 것들이 있었습니다. 어떤 녀석은 잎에서 나는 냄새를, 어떤 녀석은 줄기에서 나는 냄새를, 어떤 녀석은 꽃가루에서 나는 냄새를....
그중 '꽃가루에서 냄새를 내는 꽃㉮'과 '꽃가루에서 나는 냄새를 맡는 벌ⓐ'의 궁합(?)이 맞아 이들이 더욱 크게 번성을 합니다.
㉮가 없이 ⓐ만 있어도 상관 없습니다. ⓐ는 전에 하던대로 꽃가루를 찾아가면 됩니다.
ⓐ가 없이 ㉮만 있어도 상관 없습니다. 다른 벌들이 냄새를 무시하고 찾아가면 됩니다.
하지만 ㉮와 ⓐ가 만나면 둘이 크게 번성할 수 있습니다. ⓐ에 의해 꽃가루 수정이 되고 그만큼 ㉮가 더 번식하고 그만큼 ⓐ의 먹이가 많아지니까 말입니다.

나무들 사이에서도 여기저기 색소가 모이는 것들이 있었습니다. 어떤 녀석은 잎에, 어떤 녀석은 줄기에, 어떤 녀석은 꽃가루 주변에...
그들 중에 꽃가루 주변에 색소가 모여 '여기 꽃가루가 있다'라 광고하는 꽃들이 더욱 번성할 수 있었습니다.

나무들 중에 꽃가루 바로 옆에 수액을 모아 달콤한 꿀을 만드는 녀석도 더 많은 꽃가루를 수정시킬 수 있어 더욱 번성할 수 있었습니다.

벌들 역시 마찬가지입니다. 다른 먹이에 비해 쉽게 얻을 수 있는 꽃가루와 꿀을 더 쉽게 먹고 소화시킬 수 있도록 턱과 소화기가 진화한 것이죠. 더이상 다른 먹이는 먹을수 없을 정도로 말입니다.

꽃들도 꽃가루가 끈적해지고 돌기가 생겨 벌들에게 달라붙기 쉽게 되었습니다. 더이상 바람에 날리지 않아 벌들이 없으면 수정이 안될 정도로 말입니다.

벌과 꽃은 처음부터 밀접한 관계가 아니었습니다. 처음에는 아무 관계가 아니었다가, 점차로 관계가 깊어져, 지금은 뗄 수 없는 관계가 된 것이죠.

참고 : 공진화(co-evolution)

GA - 오델로 - 결과

6. 결과
앞과 같은 방식으로 100세대 동안 진화시킨 결과입니다.
6개 무리에서 가장 적응도가 높은 개체들의 적응도 변화 그래프입니다.



서로간에 엎치락뒤치락하기는 합니다만, 이것만으로는 얼마나 실력이 좋아졌는지 알 수가 없습니다.
어쩔수 없이 기본이 되는 AI를 하나 만들어서 비교해야겠네요.
StandardAI라 이름붙인 이 AI는 오델로플레이어와 비슷하게 돌을 놓을 수 있는 장소들의 가중치를 계산합니다. 다만 가중치를 유전자에서 계산하는 것이 아니라, 그 위치에서 잡을 수 있는 돌의 수 * 그 위치의 중요도로 계산합니다. 그 위치의 중요도란 가장자리는 10, 가장자리에서 한칸 안쪽은 1, 나머지는 5로 정의합니다.

아무튼 매 세대마다 각 무리에서 최고가중치를 가진 오델로플레이어와 이 StandardAI를 10회 대결시킨 후 오델로플레이어가 얻은 점수를 그래프로 그린 결과는 다음과 같습니다.


여기서는 20세대도 채 지나기 전에 StandardAI를 상대로한 전과가 급상승하는 것을 알 수 있습니다. 참고로 이 때의 유전자 크기(즉 유전자가 가지고 있는 패턴 갯수)는 11039입니다(물론 이것이 최대값인지는 모릅니다. 세대가 진행되면서 더 늘어날 수도 있습니다).

7. 뱀발
결과적으로 유전자알고리즘이 얼마나 진화되었는지 알기 위해 StandardAI라는 새로운 AI를 만들 수밖에 없었습니다.
그렇다면, 구태여 공진화시킬 필요 없이 이 StandardAI와의 대결을 통해 적응도를 계산, 진화시킬 수도 있지 않을까요?
물론 그럴 수도 있습니다만, 만약 StandardAI와의 대결을 통해 진화시킨다면 한가지 큰 단점이 있습니다. 오델로플레이어들이 StandardAI만을 상대하기 위해 진화한다는 점이죠. 만약 StandardAI에게 어떤 약점이 존재한다면 그 약점만을 공략하는 오델로플레이어들이 진화할 가능성이 있습니다. 그렇게 된다면 StandardAI를 상대로는 강하지만 다른 AI(심지어는 StandardAI보다 약하지만 StandardAI의 약점이 없는 AI)들을 상대로는 맥을 못추는 오델로플레이어들이 진화될 수 있습니다.

GA - 오델로 - 경쟁 및 재생산

3. 경쟁
이제 유전자도 설계했으니 이들을 경쟁시켜서 적응도를 측정해야 합니다. 그런데 무엇과 경쟁시킬까요? 특정한 AI를 하나 만들어서 이 AI와 경쟁시켜야 할까요?
아, 전에도 종종 사용했던 공진화를 이용하면 구태여 AI를 따로 만들 필요가 없겠네요. 일이 줄었습니다.
여기서는 이 오델로플레이어들을 6개의 무리로 나누었습니다. 각 무리에는 512개씩의 오델로플레이어를 포함시켰습니다. 그리고는 이들 사이에서 경쟁을 시켰습니다.
각 오델로플레이어들은 같은 무리에 있는 것들과는 싸우지 않습니다. 다른 무리에 있는 것들과 싸우게 됩니다.

procedure Compatition()
.. for h := 0, 6 do
..... for p := 0, 512 do
........ Horde[h][p].Fitness := 0; // 모든 객체의 적응도 초기화
..... end
.. end

.. // 경쟁 시작
.. for white := 0, 6 do
..... for black := 0, 6 do
........ if white != black then
........... // Horde[white]와 Horde[black]간의 대결
........... // 랜덤한 상대를 만나기 위해
........... for k := 0, 512 do
.............. CardDeck[k] = k;
........... end
........... for k := 0, 512 do
.............. rnd := Random(0, 512);
.............. tmp = CardDeck[k];
.............. CardDeck[k] = CardDeck[rnd];
.............. CardDeck[rnd] = tmp;
........... end
........... for k := 0, 512 do
.............. Compatition(Horde[white][k], Horde[black][CardDeck[k]];
........... end
........ end
..... end
.. end
end

Compatition프로시저는 생략하겠습니다. 두 오델로플레이어끼리 대결을 시킨 후, 남아있는 자신의 돌 수를 Fitness에 더하는 프로시저입니다.

4. 재생산
이렇게 적응도를 구했으면 보다 많은 돌을 가진 오델로플레이어를 찾아 재생산을 시킵니다. 일단 재생산 대상은 T=0.99인 4차 토너먼트법 - 24 = 16개의 후보를 선택 후 토너먼트를 반복해서 하나 설정, 토너먼트의 승부는 1% 확률로 적응도 낮은 것이 승 - 으로 결정했습니다.

4.1 교차
다음과 같은 유전자를 가진 두 오델로플레이어가 선택되었다고 합시다.


'...+...', 0.327
'.MM.+EE.', 0.932
'EE+.M..', 0.142
'.MEEE+EE', 0.527
'EMMEE+EM', 0.106
'..EE+EEE', 0.172
'MME+MM..', 0.018
'..E+...', 0.437



'.MM.+EE.', 0.762
'..M+...', 0.007
'..EE+EEE', 0.120
'..M.+EE', 0.607
'E+EMME', 0.742
'EMMEE+EM', 0.224


검은색으로 표시된 유전자는 '가'와 '나'에 다 있지만, 붉은색으로 표시된 유전자는 '가'에만, 녹색 유전자는 '나'에만 존재하는 유전자입니다. 이를테면 '나'는 '..E+...'라는 패턴을 만난 적이 없습니다. 만약 '나'가 그 패턴을 만난다면 어떨까요? 규칙에 의해 이 패턴을 랜덤한 가중치와 함께 추가할 것입니다. 그러므로 지금 추가하더라도 상관 없겠죠.
교차를 하기 전에 '가'와 '나'는 서로가 가지고 있는 패턴을 공유합니다.



'...+...', 0.327
'.MM.+EE.', 0.932
'EE+.M..', 0.142
'.MEEE+EE', 0.527
'EMMEE+EM', 0.106
'..EE+EEE', 0.172
'MME+MM..', 0.018
'..E+...', 0.437
'..M+...', 0.725
'E+EMME', 0.176



'.MM.+EE.', 0.762
'..M+...', 0.007
'..EE+EEE', 0.120
'..M.+EE', 0.607
'E+EMME', 0.742
'EMMEE+EM', 0.224
'...+...', 0.301
'.MEEE+EE', 0.815
'MME+MM..', 0.328
'..E+...', 0.663


즉 '가'와 '나' 둘 다 10개의 동일한 패턴(가중치는 다르지만)을 가진 유전자가 되었습니다.
이후에는 '가'와 '나'에서 동일한 패턴을 꺼내서 50%확률로 가중치를 바꾸면 교차 완료입니다.

function FindPattern(gene, pattern) // gene에서 pattern과 동일한 것 찾음
.. for k := 0, gene.Size do
..... if IsSamePattern(gene.Pair[k].Pattern, pattern) then
........ return k; // 찾았으면 위치 리턴
..... end
.. end
.. return -1;
end

procedure CrossOver(childA, childB)
.. geneA = childA.Gene
.. geneB = childB.Gene
.. for locA := 0, geneA.Size do
..... locB := FindPattern(geneB, geneA.Pair[locA].Pattern
..... if locB == -1 then // 맞는 패턴이 없음, B에 추가
........ geneB.Pair[childB.Gene.Size].Pattern = geneA.Pair[locA].Pattern
........ geneB.Pair[childB.Gene.Size].Weight = Random(0, 1)
........
childB.Gene.Size + childB.Gene.Size + 1
..... end
.. end
.. // 생략 - 동일한 방법으로 B에만 있는 유전자 A에 추가

.. // 교차 시작
.. for locA := 0, geneA.Size do
..... locB := FindPattern(geneB, geneA.Pair[locA].Pattern
......... // 동일한 패턴을 B에서 찾음

..... if Random(0, 1)
0.5 then // 50%확률로 가중치 교환
........ tmp = geneA.Pair[locA].Weight
........
geneA.Pair[locA].Weight = geneB.Pair[locB].Weight
........
geneB.Pair[locB].Weight = tmp
..... end
.. end
end


4.2 돌연변이
돌연변이는 비교적 간단합니다. 오델로플레이어의 모든 유전자를 돌면서 일정확률로 가중치값을 변화시키면 됩니다.

procedure Mutantation(child)
.. for k := 0, child.Gene.Size do
..... if Random(0, 1)
< 0.001 then
........
child.Gene.Pair[k].Weight = Random(0, 1)
..... end
.. end
end

5. 이주
앞에서 설명한 것처럼, 오델로플레이어들을 공진화시키기 위해 고립된 6개의 무리를 만들어 그 안에서만 번식이 일어나도록 하였습니다. 특히 512개밖에 안되는 무리 안에서만 번식시킨다면 아무리 돌연변이를 적용시키더라도 유전자가 획일화되기 쉽습니다. 그러므로 이렇게 유전적으로 고립시킨 경우에는 가끔씩 일부 개체들을 이주시켜 새로운 유전자를 섞어주는 것이 좋습니다.

procedure Migration()
.. if Generation % 10 == 9 then // 10세대에 한번씩
..... do
........ a := Random(0, 6)
........ b := Random(0, 6)
..... while a == b

..... aa := Random(0, 512)
..... bb := Random(0, 512)
..... tmp = horde[a][aa];
..... horde[a][aa] = horde[b][bb];
..... horde[b][bb] = tmp;
end

GA - CNNC를 실은 꼬마자동차[3] - 결과

11. 결과 1
우선 앞과 같은 방식으로 돌길꼬마자동차를 공진화시켰습니다. 100세대 후 최고 적응도를 얻은 꼬마자동차의 성적표입니다.

Generation:99 MaxScore:-2440 Collision:254 MinScore:-2561 Move:264

최고성적의 꼬마자동차도 64개의 돌길을 지나며 264(평균 4.125)칸만을 이동할 수 있었습니다. 그동안 254번이나 장애물과 충돌했군요.

꼬마자동차와 함께 진화된 돌길을 살펴보겠습니다. 다음은 돌길의 앞부분만을 그린 것입니다.

오른쪽 끝의 푸른 점이 꼬마자동차의 출발점입니다. 저 위치로부터 꼬마자동차는 앞쪽, 왼쪽앞, 오른쪽앞으로 이동할 수 있습니다. 그런데 보시다시피 자동차가 갈 수 있는 곳은 모두 장애물로 덮여 있습니다. 꼬마자동차가 장애물을 통과할때 기름 5씩 들어가므로 4칸만 움직이면 기름이 떨어져 버리죠.
이런 돌길을 통과할 수 있는 꼬마자동차가 진화될 수 없습니다. 돌길에 대해 약간의 제한이 필요하겠군요.

12. 결과 2
꼬마자동차는 앞의 세 칸들 중 하나로 이동할 수 있습니다. 앞의 세 칸 중 하나가 장애물이 아니면 앞으로 이동할 수 있는 것입니다. 그러므로 돌길을 만들때 장애물 세개가 연이어 놓이는 것을 방지했습니다.
그 결과는 다음과 같습니다.

Generation:99 MaxScore:12798 Collision:0 MinScore:-2561 Move:1280

확실히 아까보다는 성적이 좋아졌군요. 그런데 64개 돌길을 지나면서 1280(평균 20)칸을 움직였습니다. 결국 초기 가지고 있던 기름만 다 사용한 것이군요. 이유가 무엇일까요.


위에서 보다시피 꼬마자동차의 앞을 모두 막진 않았지만, 기름통으로 갈 수 있는 길은 철저히 막혀 있습니다. 최소한 한개의 장애물을 밟지 않고는 기름을 얻을 수 없는 구조가 되어 버렸습니다.
조금 더 돌길에 제한이 필요하겠군요.

13. 결과 3
이번에는 각 연료통으로 갈 수 있는 길을 확보해 주었습니다. 100턴 이후 꼬마자동차의 성적표입니다.

Generation:99 MaxScore:63998 Collision:0 MinScore:-2551 Move:6400

보시다시피 길이 100인 돌길 64개, 6400칸을 장애물과 충돌 없이 움직이는데 성공했습니다.

100턴이 지날 때까지 각 세대 최고 적응도의 꼬마자동차가 장애물과 충돌한 횟수를 그래프로 그렸습니다. 이것이 공진화의 전형적인 패턴입니다.
처음 돌길의 진화로 꼬마자동차들이 피할수 없는 장애물패턴을 만듧니다(충돌횟수가 증가합니다). 그 후에는 꼬마자동차의 진화로 그 장애물을 피합니다(충돌횟수가 감소합니다). 다시 돌길의 새로운 패턴 발견(충돌증가), 꼬마자동차의 패턴 돌파(충돌감소)가 반복되며 꼬마자동차돌길의 적응도가 증가합니다. 다만 여기서는 꼬마자동차가 중심이기에 돌길에 약간의 제한을 주어 꼬마자동차의 진화를 돕는 쪽으로 유도했습니다.

GA - CNNC를 실은 꼬마자동차[1] - 공진화와 유전자설계

1. 개요
장애물을 피해 움직이는 꼬마자동차는 이미 앞에서 진화시켜본 적이 있습니다. 8개의 유전자를 가진 자동차들이었죠.
이번에는 8개의 유전자를 가진 꼬마자동차가 아니라 CNNC를 탑재한 꼬마자동차를 진화시키도록 하겠습니다. 기본적으로 바로 앞 3칸의 블럭정보를 받아들여 CNNC에 기초한 신경망을 돌려 다음 행동을 결정하는 것이죠.
하지만 이번 문제에서는 한가지 요인을 더 넣었습니다. '연료'란 개념을 넣었죠.
꼬마자동차는 최대크기 20의 기름통을 가지고 있습니다. 한칸 이동할 때마다 1씩, 그리고 장애물 위를 통과하기 위해서는 5의 기름을 소모합니다.
물론 자동차가 통과해야 할 거리는 100입니다. 그러므로 길 위에는 10칸마다 하나씩 기름통을 10만큼 채울 수 있는 기름이 존재합니다. 그리고 각 자동차들은 다음 기름통의 위치를 감지할 수 있는 감지기를 추가합니다.

2. 공진화
개인의 발전을 위해 라이벌이 필요하듯, 천적들이 서로가 서로의 선택압으로 작용하여 적응도가 높아지는 경우가 있습니다. 이러한 현상을 공진화라고 합니다.
그렇다면 이 꼬마자동차의 천적은 무엇일까요? 이 꼬마자동차가 극복해야 할 대상, 즉 장애물이 깔려있는 돌길 자체가 천적이 되겠죠.
꼬마자동차의 적응도는 '돌길을 얼마나 멀리 갔는가'에 따라 결정됩니다. 반대로 돌길의 적응도는 '자동차들을 얼마나 방해했는가'로 결정할 수 있습니다. '특정한 장애물 패턴'을 가지고 있는 돌길에 많은 자동차들이 발목을 잡힌다면, 그 돌길은 높은 적응도를 갖고 진화적 우위를 차지해서 결국 그러한 '특정한 장애물 패턴'은 점점 많아집니다. 다시 그 '특정한 장애물 패턴'을 돌파할 수 있는 자동차들이 진화적 우위를 차지합니다.

3. 유전자설계 - 꼬마자동차
꼬마자동차의 유전자는 앞의 XOR회로를 진화시키기 위해 사용했던 신경망 그대로입니다. 다만 여기서는 (뒤에서 나올 이유로) 신경세포의 전하량을 0~1이 아니라 -1~+1 사이로 정의했습니다. 이것은 시그모이드함수를 다음과 같이 수정함으로써 간단히 구현됩니다.


4. 유전자설계 - 돌길
돌길의 유전자는, 다음 그림과 같이 설계됩니다. 돌(장애물)과 기름통이 놓여있는 길이 100인 길이죠.



갈색은 장애물, 녹색은 기름통입니다. 그 외의 흰 부분은 장애물 없는 빈 공간입니다.

procedure InitGene(StoneRoad gene)
.. for length := 0, 99 do
..... gene[length][0] := ROCK
..... for width := 1, 10 do
........ gene[length][width] := ROAD
..... end
..... gene[length][11] := ROCK
..... if length % 10 == 5 then
........ gene[length][Random(1, 10)] := FUEL
..... end
.. end
end

코드를 보면 아시겠지만, 최초의 돌길은 양쪽 가장자리를 막고 있는 장애물 외에는 아무런 장애물도 없이 일정 거리마다 연료통만이 흩어져 있는 '가장 쉬운 돌길'들입니다.

미리 말씀드리지만, 유전자알고리즘을 사용하다 보면 유전자알고리즘으로 만들어진 녀석들이 상당히 '얍삽'하다고 느낄 때가 있습니다. 이 문제에서도 알 수 있지만, 결국 '규칙'을 잘 만들지 않으면 이상한 행동을 할 때가 있습니다(사실 그 녀석들도 주어진 규칙 안에서 최대 적응도를 찾은 것이니 뭐라고 할 수도 없죠).

진화론 이야기 - 진화적 군비 경쟁

나무와 벌레들이 같이 살고 있는 조그만 숲이 있습니다. 여기서 벌레는 나무를 갉아먹습니다.
이 숲의 나무들은 벌레의 공격에 의해 두꺼운 껍질을 가진 나무가 진화적 우위를 갖습니다*.
마찬가지로 벌레들 역시 나무껍질에 의해 크고 단단한 턱을 가진 벌레가 진화적 우위를 갖습니다*.
그러므로 시간이 지날수록 그 숲의 나무들은 점점 두꺼운 껍질을, 그 숲의 벌레들은 점점 더 크고 단단한 턱을 갖게 됩니다.
그럼에도 불구하고 벌레가 나무를 먹는 상황은 변하지 않습니다. 예전에는 작은 턱으로 얇은 나무껍질을 뚫고 나무를 파먹었다면 지금은 큰 턱으로 두꺼운 나무껍질을 뚫고 나무를 파먹는다는 차이일 뿐입니다.
*위에서 '진화적 우위를 갖는다'는 말은, 두꺼운 껍질을 가진 나무/크고 단단한 턱을 가진 벌레들이 생존경쟁에 유리하게 되어 더 많은 번식기회를 갖고, 그로인해 두꺼운 껍질을 가진 나무/크고 단단한 턱을 가진 벌레들이 많아진다는 뜻입니다.

밑에 공진화 이야기가 있습니다만. 공진화에 의해 천적관계의 진화가 계속되는 현상을 진화적 군비 경쟁이라고 합니다. 사실 두꺼운 나무껍질이나 크고 단단한 턱은 그들이 번식하는데는 오히려 방해가 됩니다. 나무껍질이나 턱을 만들기 위해 자원을 쓰느라 번식에 들어가는 자원이 줄어들죠.
하지만 그렇다고 해서 어느 한쪽이 진화를 멈춘다면 그들은 전멸하게 될 것입니다. 마치 냉전시대 미소의 군비경쟁처럼 말입니다.

혹시 나무와 벌레들이 협정을 맺을 수도 있겠죠.
"우리가 아무리 두꺼운 껍질과 큰 턱을 만들어봐야 벌레가 나무를 파먹는 관계는 변하지 않는다. 그럴 바에는 우리가 최소한의 껍질과 턱을 만들고 나머지는 번식에 힘쏟자"
그렇게 되면 그들은 두꺼운 나무껍질과 큰 턱을 만들 자원을 번식에 쏟을 테니 더 많은 나무들과 벌레들이 사는 지상낙원이 될 것입니다.

가끔씩 나오는 양심적 병역거부자가 그리는 세상이 저런 세상일 것입니다. 너도 나도 총을 놓는다면 전쟁으로 죽을 사람이 없으니 인구도 늘어나겠죠. 탱크대신 자동차를, 화약대신 비료를 만들테니 생산성도 늘어나는 낙원이 될 것입니다.
그런데 저런 세상이 얼마나 오래갈 수 있을까요?

하지만 극히 일부의 벌레들이 다른 벌레들보다 약간 큰 턱을 가진다면 어떻게 될까요? 그들은 더 많은 나무를 갉아먹으며 진화적 우위를 차지할 것입니다. 결국 모든 벌레들이 조금 더 큰 턱을 가지게 되며 나무들은 생존을 위해 더 두꺼운 껍질을 가져야 할 것입니다.
반대로 극히 일부의 나무들이 조금 더 두꺼운 껍질을 가져도 마찬가지가 될 겁니다.
그렇게 해서 저 지상낙원은 다시 진화적 군비경쟁이 판치는 예전의 숲으로 되돌아갈 수밖에 없습니다.

역시 아래에 있는 죄수의 딜레마상황처럼 배신자가 더 큰 이익을 가지게 됩니다. 병역거부자들의 낙원 역시 마찬가지죠. 아무도 무력을 가지고 있지 않다면 약간의 무장만으로도 커다란 이익을 얻을 수 있습니다. 그런 유혹에 빠지지 않을 사람을 찾기가 더 힘들 걸요. 그리고 그렇게 되면 결국 모든 사람들이 다시 무장을 하는 군비경쟁의 상황으로 되돌아갈 것입니다.

그렇다면 군비경쟁의 상황으로 돌아가지 않고 전쟁없는 낙원을 만들 가능성은 없을까요?

첫째로 죄수의 딜레마에서 가장 우수한 전략, 받은대로 돌려주는 Tit-for-Tat 전략을 사용하는 것입니다. 그런데 받은만큼 돌려주기 위해서는 나도 무장을 하고 있어야겠군요. 실제로 냉전중에 긴장이 높아도 전면전이 일어나지 않은 이유가 이것입니다. 하지만 모두가 무장을 한다면 '병역거부자의 낙원'이 아니게 되겠죠.

둘째로 더 두꺼운 나무껍질, 더 큰 턱을 만들었을 때 얻을 수 있는 진화적 우위를 박탈하는 방법이 있습니다. 만약 두꺼운 나무껍질이나 큰 턱을 만드는 비용이 너무 커서 그것으로 얻을 수 있는 이익이 더 작다면(즉 죄수의 딜레마에서 배신했을때의 보상을 낮추면) 다른 노력 없이도 자연스럽게 낙원이 만들어질 수 있습니다.
그런데 아무도 무장을 안한 상태에서 약간의 무장을 한 사람들에게 손해를 줄 방법이 마땅치 않다는 점이 문제겠네요.

이래저래 병역거부자들이 원하는 낙원은 불가능한가 봅니다.

그런데, 병역거부자들의 낙원은 불가능하다 치고 위에서 예로 든 나무와 벌레들의 낙원은 정말로 불가능할까요?
만약 모든 벌레들이 지나치게 큰 턱을 가진 벌레와는 짝짓기를 하지 않는다면 어떨까요(내 자손이 큰 턱을 가지고 쉽게 번식할 수 있겠다는 이익을 포기하고 말입니다)?
마찬가지로 모든 나무들이 지나치게 두꺼운 껍질을 가진 나무와는 꽃가루를 교환하지 않는다면 어떨까요(마찬가지로 내 자손들이 두꺼운 껍질을 가지고 오래 살 수 있겠다는 이익을 포기하구요)?
만약 그렇게 한다면 큰 턱과 두꺼운 껍질을 가진 '배신자'들은, 자신은 이익일 수 있으나 자손을 만들지 못하기에 도태되어버리고 지상낙원이 유지될 수 있겠군요.
물론 이 경우에는 '내 이익을 포기하고서라도 이 지상낙원을 유지하자'는 공감대가 모든 벌레들, 그리고 모든 나무들에게 퍼져있어야겠지만 말입니다.

현실에서도 '민주주의를 유지하자'는 공감대가 전 국민들에게 퍼져 있고 전 국민들이 민주주의를 유지하기 위해 자신의 이익을 약간 포기할 수 있어야 민주주의를 유지할 수 있습니다. 투표를 하기 위해 몇시간 늦게 애인과 만난다거나 몇시간동안만 온라인게임에서의 레벨업을 멈춘다든가 하는 식으로 말입니다.

진화론 이야기 - 공진화

옛날 어느 프로그램에서 '100미터 혼자달리기'같은 게임을 한 적이 있습니다. 뭐 학생들이 나오는 것이니 결국에는 대충 비슷한 기록에서 정체하더군요. 그런데 어느 학교에선가 새로운 방식을 들고 나왔습니다. '바람돌이'라고 해서 다른 친구 하나가 옆에서(트랙 밖에서) 같이 달리는 것이었죠. 그 결과 기록은 극적으로 단축되었습니다. 혼자 달리는 것보다 경쟁하는 것이 더 빠르다는 것이죠.
진화론에서도 비슷한 현상이 관찰됩니다. '공진화'라는 현상이죠. 천적관계 또는 공생관계인 두 종이 같이 진화해나가면서 서로가 상대방에 대한 선택압으로 작용하여 (창조론자들은 절대로 우연히 생길수 없다고 주장하는) 자연의 신비가 만들어지는 것입니다.
나뭇잎 틈에서 사는 벌레(a)가 있습니다. 그리고 이 벌레를 먹고 사는 새(A)가 있습니다. 이 새의 원시적인 눈은 사물의 명암만 알 수 있는 정도입니다. 그리고 이 벌레의 모습은 그야말로 나뭇잎 위에서 눈에 확 띄는 모습이죠.
벌레들 중 일부가 나뭇잎과 비슷한 색깔로 변이를 일으킵니다(b), (b)는 원시적인 (A)의 눈에 나뭇잎과 구분이 안되므로 (A)의 눈을 피해 살아남아 더 많은 자손을 남깁니다. 큰 차이가 아니라도, 설사 저녁과 새벽의 어스름, 짙은 안개 속에서만 속여넘길수 있는 변화라도 충분합니다.
이런 식으로 원시적인 눈을 가진 (A)가 나뭇잎과 착각하는 (b)가 많아지면 이것은 '약
간' 좋은 눈을 가지고 나뭇잎과 (b)를 구분할 수 있는 새(B)에 대한 선택압으로 작용합니다. (B)는 (A)에 비해 더 많은 벌레를 잡아먹고 더 많은 새끼를 낳을 수 있다는 것이죠.
(b)는 다시 (B)의 눈을 속일 수 있을 만큼 나뭇잎과 더 닮은 변이를 일으킨 (c)와의 경쟁에서 뒤떨어지고, (B)는 다시 (c)를 인식할 수 있는 (C)에 의해 도태되고....
이러한 과정이 반복되어 결국 다음과 같은
벌레가 완성되는 것입니다.







즉 이런 벌레들이 딱정벌레나 호랑나비에서 '나뭇잎을 흉내내서 나뭇잎 속에 숨어야지 숨어야지' 하다가 어느 순간 '짠~~'하고 나타난 것이 아닙니다.
형편없던 포식자의 눈과의 오랜 시간에 걸친 공진화의 결과입니다.

참조 : 눈먼 시계공(리처드 도킨스) , 인공생명(스티븐 레비)