Kodama's home / tips.
しかし, ダーウィン的なメカニズムは進歩を保証するものではない. より高度な体制へと導く推進力のようなものは仮定しない. 進化は進歩ではないし, "進化の階梯を登る" ことを意味するのではない.
適者生存の概念と遺伝子の中立な変化をあわせて考えてみよう. 遺伝的な変化は小さなランダムな変化だが, 生き残りや繁殖の結果は適応的にランダムでは無い変化をする. ここからは大局的な意味での進歩とは言えないまでも, 適応度の改善と言い得るような変化の傾向がありうることが予想される. 実際, この効果の計算機シミュレーションである "遺伝的プログラム" では 様々な問題でかなりの "改善" 効果を観察できる.
このような, 遺伝子の構成の局所的な改善が仮にあったとしても, "高等な"生物を生み出すようなグローバルな改善の傾向, 高等な生物を目指すトレンドがあるという証明にはならない. "適応度の改善" と所謂 "高度化", "特殊化" とは直接には一致しない. 実際にも, 体の大きさや特殊化の程度などで一方向的な進化の傾向があるとは言えない. むしろ, 一般的な傾向としては, 祖先種よりも子孫種の方が特殊化の程度などが少ないことが多いという. また, 遺伝子レベルだけではなく, 表現型に関しても, 適応度とは無関係な, 中立な変化も多くみられるという. (つまり,全ての形態の変化が適応的とは言えないということ.)
原因の一部は適応度の改善と人間的な解釈での高度化が必ずしも一致しないという事にあるようだ. ("退化"などを考えてみると良い.)
ここでは, 要因の一部としてのランダムな過程を見る事にする. つまり, 仮に "改良する傾向" が無くても多様性の増大に伴って "複雑" な種も発生するという考えを単純な数値シミュレーションで見てみる.
左右への移動確率が p で決まる不均等なランダムウォークと考えれば良い. p=0.5 の場合, 複雑さを増す種と複雑さを減らす種の数は等しい. p<0.5 の場合には傾向としては変化すると "単純" な種になってゆくはず. p>0.5 の場合には進化すると複雑さを増す傾向を持つ事になる.
0.1 のように極端に小さな確率の場合でも これに従ってプログラムを実行してみると 全体としては, 時間が経つに従って "複雑" な種も増えてゆく. 現実には p はもっと大きい(0.5に近い)と思われる.
p=1/10 の例 低い ← レベル → 高い ↓時間 1 2 4 8 15 1 30 2 61 2 1 116 12 231 21 4 455 50 6 1 912 101 10 1 1825 198 24 1 3644 403 42 7 7285 804 94 8 1 14561 1628 175 19 1 29144 3224 358 40 2 58263 6470 719 76 8 116521 12944 1431 159 16 1 233040 25878 2872 319 34 1 466054 51780 5748 632 66 8 932104 103556 11490 1268 143 14 1 1864190 207102 22992 2552 282 32 2 3728327 414219 46018 5106 569 60 4 1 7456586 828495 92035 10227 1127 125 13 14913146 1656979 184111 20435 2269 245 26 5
p=0.8 の例 低い ← レベル → 高い ↓時間 1 1 1 1 2 1 0 3 4 1 1 1 6 7 1 0 4 6 10 10 2 3 2 10 15 16 15 3 1 9 11 21 29 28 24 5 2 8 21 33 47 49 49 40 7 2 9 28 57 76 91 91 85 63 10 2 14 37 79 130 156 177 167 142 103 17 6 13 49 115 202 271 308 351 302 231 171 29 15 25 72 170 304 440 575 629 637 511 375 295 48 18 50 107 222 450 738 950 1177 1217 1147 924 636 484 72 28 67 168 337 629 1101 1702 2026 2337 2328 2063 1644 1051 789 114 45 110 225 520 991 1680 2600 3682 4127 4536 4382 3762 2937 1703 1287 181 72 155 383 732 1530 2707 4066 5732 7708 8389 8811 8180 6732 5212 2777 2060 290 108 243 540 1235 2209 4091 6643 9544 12533 15885 16709 16708 15164 12010 9173 4520 3291 466 148 393 863 1742 3596 6129 10361 15785 21864 26622 31879 32715 31424 28101 21101 15918 7472 5292 739
p=0.1(<0.5) の場合: 極端に p を小さくしてみた. 指数型の分布.
p=0.4(<0.5) の場合: "退化" 傾向のある場合. 指数型の分布が見える.
p=0.5 の場合: 中立的な "受動的進化" の状況. 通常のランダムウォーク. この辺が現実に近い.
0.4 の場合と違ってピークが少し丸みを帯びて, 正規分布を半分に切り取ったような形になっている.
p=0.6(>0.5) の場合: "進歩" の傾向がある "積極的進化"(誘導型進化).
次第に右に移動する山が見える.
p=0.8(>0.5) の場合: "進歩" の傾向が強い, "積極的進化"(誘導型進化) の意味を観察するため, 極端に p を大きくしてみた.
次第に右に移動する山が見える.
p による 分布の形, 平均, ピークの位置の概略.
p の値 | 分布の概形 | 平均 | ピークの位置 |
---|---|---|---|
p<0.5 | 指数分布 | 小さいまま | 小さいまま |
p=0.5 | 正規分布の右半分 | 大きくなる(時間の平方根に比例) | 小さいまま |
p>0.5 | 正規分布 | 大きくなる(時間に比例) | 大きくなる(時間に比例) |
pが小さい場合, 指数分布で近似できると考えてみる. 隣接する 3 レベルの比が 1: a : a^2 で平衡しているときには以下が成り立つ.
p + (1 - p) a^2 = a. (1-p) a^2 - a + p = 0 ((1-p)a - p) (a-1) = 0 a= p/(1-p), 1 例えば, p=1/10 とすると a=1/9. p=1/3 とすると a=1/2. p=2/5 とすると a=2/3.p=0.1 の例では,隣接するレベル間の比率が 1:1/9 程度の(近似的な)指数分布となる.
p>0.5 の場合, 0よりも小さいレベルが無いので分布が歪むが, 近似的に正規分布(又は 2項分布)に近くなる. 分布のひろがり(σ)は時間の平方根に比例して大きくなる.
p が 0.5 のとき, 近似的に正規分布の右半分となる. 分布のひろがり(σ)は時間の平方根に比例して大きくなる.
A1 = 1 + a + a^2 + a^3 + ... = 1/(1-a) A2 = 0*1 + 1*a + 2*a^2 + 3*a^3 + ... = a/(1-a)^2 AVG = A2/A1 = a/(1-a) 例えば, p=1/10 のとき a=1/9, AVG = (1/9)/(8/9) = 1/8. p=1/3 のとき a=1/2, AVG = (1/2)/(1/2) = 1. p=2/5 のとき a=2/3, AVG = (2/3)/(1/3) = 2.時間が経過しても 平均的なレベルは 1/8 のように低いまま保たれる. 平均的な複雑さの増大, 時代とともに高度になって行くトレンドは存在しない. (ついでに言うと, いつまでたっても最多クラスはレベル0のまま.)
pが大きい場合, 二項分布で近似できると考えると, (又は, 負のレベルがないことによる歪みが小さいと考えると,) 時間ごとに 平均値が p-(1-p) = 2p-1 増大する. p=0.8 の例では 0.6 ずつ増大する. p=0.6 の例では 0.2 ずつ増大する.
p=0.5 の場合, 右半分でのランダムウォークなので,時間が経つに従って分布がひろがって行き, 平均値は次第に(時間の平方根に比例して)大きくなってゆくと考えても良い.
#!/usr/local/bin/ruby # evolution.rb # 2004-06-15 revised # 2004-05-28 K.Kodama def rev_x(a) p=0.5 # probability b=Array::new(a.size+1,0) a.each_with_index{|v,i| (v*2).times{ if p>rand then i1=i+1; else i1=[i-1,0].max; end; b[i1]=b[i1]+1 } #v1=(v*2*p).round; i1=i+1; b[i1]=b[i1]+v1 #v2=v*2-v1; i1=[i-1,0].max; b[i1]=b[i1]+v2 } while(b[-1]==0) do b=b[0..-2]; end return b end; gpStr=""; gpSep=""; a=[1] # a=[1,2,1] a.each{|v| print v.to_s+" "}; print "\n" 16.times{|ite| a=rev_x(a) a.each{|v| print v.to_s+" "}; print "\n" fileName="data"+ite.to_s+".txt" File::open(fileName,"w"){|f| a.each{|v| f << (v.to_s+"\n") } } gpStr=gpStr+gpSep+'"'+fileName+'" with lines'; gpSep=","; } ## graph using gnuplot IO.popen("gnuplot","w"){|gp| gp.puts "plot "+gpStr # gp.puts 'plot "data.txt" with lines' sleep 10; # show it. gp.puts 'set terminal png' gp.puts 'set output "evolution.png"' gp.puts 'replot' }
Kodama's home / tips.