1976年にアメリカの生物学者ロバート・メイが、「ロジスティック方程式」の
差分系を用いて生物の個体数の研究を行った。その差分方程式(difference equation)を
入出力の変換操作に用いた写像を「ロジスティック写像(logistic mapping)」と呼ぶ。
ロジスティック写像とは、生物の個体数の時系列に対する変遷のモデルであり、
繁殖率をa、第n世代の生物の個体数をxnとすると、
第n+1世代の生物の個体数をxn+1は、漸化式:
xn+1=axn ( 1-xn )
で表される。但し、繁殖率は、0 ≤ a ≤ 4.0 の範囲、
個体数の初期値は、0 ≤ x0 ≤ 1 の範囲である。
ここでは、JavaScriptによるスクリプトプログラムとグラフ作成ツール「gnuplot」を用いて、
aとx0との組み合わせによる個体数の変遷及び、カオスの出現する条件を調べる。
繁殖率a と個体数の初期値x0を入力後、「時系列変化」ボタンを押すと、
新しいページテキストエリアにデータが生成されるので、そこで、「全て選択」して、
テキストエディタを起動して、ファイルにコピーペーストし、名前を付けて保存する。
例えば、Cドライブ以下のtempフォルダに「logisticmap1.dat」という名前で保存した場合、
これをグラフ作成ツール「gnuplot」を用いて、グラフ化するには、
gnuplotを起動して、以下のコマンドを入力する。
すると、横軸が時間t、縦軸が個体数xtで表された、
個体数の変遷のグラフが生成される。
set terminal png set xrange[0:100] set yrange[0:1] set output 'c:\temp\logisticmap1.png' plot 'c:\temp\logisticmap1.dat' with lines exit |
また、個体数の初期値x0を入力後、「分岐図」ボタンを押すと、
やはり新しいページテキストエリアにデータ(4万個以上生成されるので注意)が生成されるので、
同様に、「全て選択」して、テキストエディタを起動して、ファイルにコピーペーストし、
名前を付けて保存する。例えば、Cドライブ以下のtempフォルダに
「logisticmap2.dat」という名前で保存した場合、
これをグラフ作成ツール「gnuplot」を用いて、グラフ化するには、
gnuplotを起動して、以下のコマンドを入力する。
すると、横軸が繁殖率a、縦軸が個体数xtで表されたグラフが生成される。
このグラフは「分岐図」と呼ばれている。
set terminal png set xrange [0:4] set yrange [0:1] set output 'c:\temp\logisticmap2.png' plot 'c:\temp\logisticmap2.dat' with dots exit |
また、繁殖率a と個体数の初期値x0を入力後、「リターンマップ」ボタンを押すと、
やはり新しいページテキストエリアにデータが生成されるので、同様に、「全て選択」して、
テキストエディタを起動して、ファイルにコピーペーストし、名前を付けて保存する。
例えば、Cドライブ以下のtempフォルダに「logisticmap3.dat」という名前で保存した場合、
これをグラフ作成ツール「gnuplot」を用いて、グラフ化するには、
gnuplotを起動して、以下のコマンドを入力する。(以下は、繁殖率a=3.5の場合)
すると、横軸が個体数xt 、
縦軸が個体数xt+1 で表されたグラフが生成される。
このグラフは「リターンマップ」と呼ばれている。
set terminal png set xrange [0:1] set yrange [0:1] a=3.5 set output 'c:\temp\logisticmap3.png' plot 'c:\temp\logisticmap3.dat' with lines, x, a*x*(1-x) exit |
ここでは、一律に個体数の初期値は、x0=0.40 に固定し、
繁殖率a の値のみを0.8、1.6、2.4、3.2、3.5、3.8、4.0と変化させて、
横軸が時間t、縦軸が個体数xtで表された「時系列変化」、
横軸が繁殖率a、縦軸が個体数xtで表された「分岐図」、
横軸が個体数xt 、縦軸が
個体数xt+1 で表された「リターンマップ」
をグラフ作成ツール「gnuplot」を用いて、グラフ化する。
a=0.8 | ![]() |
a=1.6 | ![]() |
a=2.4 | ![]() |
a=3.2 | ![]() |
a=3.5 | ![]() |
a=3.8 | ![]() |
a=4.0 | ![]() |
a=0.8 | ![]() |
a=1.6 | ![]() |
a=2.4 | ![]() |
a=3.2 | ![]() |
a=3.5 | ![]() |
a=3.8 | ![]() |
a=4.0 | ![]() |
ロジスティック写像の振る舞いは、繁殖率a の値に依存する。
例えば、繁殖率a が0 ≤ a ≤ 1では種は絶滅する。
また、繁殖率a が境界点a∞=3.56995…≈3.57
を超えると、「カオス」が出現する。この境界点a∞は、
「ファイゲンバウム点」と呼ばれている。
詳細は、以下の表にまとめておく。
0 ≤ a ≤ 1 | 「0」に単調に収束する(つまり、絶滅する) |
1 ≤ a ≤ 2 | 「1-1/a」に単調に収束する |
2 ≤ a ≤ 3 | 「1-1/a」に振動しながら収束する |
3 ≤ a ≤ 1+√6 (≈3.45) | 2点間を周期的に振動する(2周期振動) |
1+√6 (≈3.45) ≤ a ≤ a∞(≈3.57) | 「2」の冪乗の周期点を振動する |
a∞(≈3.57) ≤ a ≤ 4 | 変動は不規則になり、特定の周期を持たない (カオスが出現する) |
<form><!-- getElementByIdを使用する為、name属性を指定しない --> <table border="1" style="margin-left:auto;margin-right:auto;text-align:center;"> <tr> <td style="text-align:right">繁殖率:<i>a</i>=</td> <td style="text-align:left;"><input type="text" id="a">( 0 ≤ <i>a</i> ≤ 4.0 )</td> </tr> <tr> <td style="text-align:right">個体数の初期値:<i>x</i><sub>0</sub>=</td> <td style="text-align:left"><input type="text" id="x0">( 0 ≤ <i>x</i><sub>0</sub> ≤ 1 )</td> </tr> <tr> <td style="text-align:right;">データ出力形式:</td> <td style="text-align:left;"> <label for="csv"><input type="radio" name="separator" id="csv">CSV(半角コンマ区切り)</label><br> <label for="ssv"><input type="radio" name="separator" id="ssv" checked>SSV(半角スペース区切り)</label><br> <input type="button" value="時系列変化" style="width:160px;height:40px;" onclick="logisticmap1()"><br> <input type="button" value="分岐図" style="width:160px;height:40px;" onclick="logisticmap2()"><br> <input type="button" value="リターンマップ" style="width:160px;height:40px;" onclick="logisticmap3()"></td> </tr> <tr> <td style="text-align:right">データ出力欄:</td> <td style="text-align:left"><span id="calcfunc"></span><br><textarea id="data" cols="50" rows="20"></textarea></td> </tr> </table> </form> |
var logisticmap1 = function(){ var n = new Array(101); // 101個の値(n[0],...,n[100])を格納する配列xを宣言 var x = new Array(102); // 102個の値(x[0],...,x[101])を格納する配列xを宣言 var a = parseFloat(document.getElementById("a").value); x[0] = parseFloat(document.getElementById("x0").value); var data = ""; // データを表す変数を空の初期値と共に宣言 var separator = ""; // データの区切り文字 // データの区切り文字の種類を選択して取得 if(document.getElementById("csv").checked == true){ separator=","; } // 半角コンマ区切り if(document.getElementById("ssv").checked == true){ separator=" "; } // 半角スペース区切り document.getElementById("calcfunc").innerHTML = "時系列変化"; for(t=0;t<=100;++t){ n[t] = parseFloat(t); x[t+1] = a * x[t] * (1 - x[t]); data += n[t] + separator + x[t]; if(t<100){ data += "\n"; } // データ最後のt=100の場合のみ改行しない、それ以外は全て改行 } document.getElementById("data").value = data; // テキストエリアへ出力する }; var logisticmap2 = function(){ var x = new Array(102); // 102個の値(x[0],...,x[101])を格納する配列xを宣言 x[0] = parseFloat(document.getElementById("x0").value); var data = ""; // データを表す変数を空の初期値と共に宣言 var separator = ""; // データの区切り文字 // データの区切り文字の種類を選択して取得 if(document.getElementById("csv").checked == true){ separator=","; } // 半角コンマ区切り if(document.getElementById("ssv").checked == true){ separator=" "; } // 半角スペース区切り document.getElementById("calcfunc").innerHTML = "分岐図"; for(i=0;i<=400;++i){ for(t=0;t<=100;++t){ x[t+1] = (i/100.0) * x[t] * (1-x[t]); data += (i/100.0) + separator + x[t]; if(i<400 || t<100){ data += "\n"; } // データ最後のi=400かつt=100の場合のみ改行しない、それ以外は全て改行 } } document.getElementById("data").value = data; // テキストエリアへ出力する }; var logisticmap3 = function(){ var x = new Array(102); // 102個の値(x[0],...,x[101])を格納する配列xを宣言 var a = parseFloat(document.getElementById("a").value); x[0] = parseFloat(document.getElementById("x0").value); var data = ""; // データを表す変数を空の初期値と共に宣言 var separator = ""; // データの区切り文字 // データの区切り文字の種類を選択して取得 if(document.getElementById("csv").checked == true){ separator=","; } // 半角コンマ区切り if(document.getElementById("ssv").checked == true){ separator=" "; } // 半角スペース区切り document.getElementById("calcfunc").innerHTML = "リターンマップ"; data += x[0] + separator + 0 + "\n"; for(t=0;t<=100;++t){ x[t+1] = a * x[t] * (1 - x[t]); data += x[t] + separator + x[t] + "\n"; data += x[t] + separator + x[t+1]; if(t<100){ data += "\n"; } // データ最後のt=100の場合のみ改行しない、それ以外は全て改行 } document.getElementById("data").value = data; // テキストエリアへ出力する }; |
<form name="logisticmap"> <table border="5" frame="void" rules="none" style="margin-left:auto;margin-right:auto;text-align:center;"> <tr> <td align="right">繁殖率:<i>a</i>=</td> <td style="text-align:center;"><input type="text" name="a"></td> <td align="left">( 0 ≤ <i>a</i> ≤ 4.0 )</td> </tr> <tr> <td align="right">個体数の初期値:<i>x</i><sub>0</sub>=</td> <td style="text-align:center;"><input type="text" name="x0"></td> <td align="left">( 0 ≤ <i>x</i><sub>0</sub> ≤ 1 )</td> </tr> </table> <input type="button" value="時系列変化" onClick="logisticmap1()"> <input type="button" value="分岐図" onClick="logisticmap2()"> <input type="button" value="リターンマップ" onClick="logisticmap3()"> </form> |
function logisticmap1(){ var n=new Array(101); /* 101個の値(n[0],...,n[100])を格納する配列xを宣言 */ var x=new Array(102); /* 102個の値(x[0],...,x[101])を格納する配列xを宣言 */ a=parseFloat(document.logisticmap.a.value); x[0]=parseFloat(document.logisticmap.x0.value); document.writeln("<html>"); document.writeln("<head>"); document.writeln("<title>ロジスティック写像・時系列変化</title>"); document.writeln("</head>"); document.writeln("<body bgcolor='#ffd700' text='#000000'>"); document.writeln("<pre>"); for(t=0;t<=100;++t){ n[t]=parseFloat(t); x[t+1]=a*x[t]*(1-x[t]); document.writeln(n[t]," ",x[t]); } document.writeln("</pre>"); document.writeln("</body>"); document.write("</html>"); } function logisticmap2(){ var x=new Array(102); /* 102個の値(x[0],...,x[101])を格納する配列xを宣言 */ x[0]=parseFloat(document.logisticmap.x0.value); document.writeln("<html>"); document.writeln("<head>"); document.writeln("<title>ロジスティック写像・分岐図</title>"); document.writeln("</head>"); document.writeln("<body bgcolor='#ffd700' text='#000000'>"); document.writeln("<pre>"); for(i=0;i<=400;++i){ for(t=0;t<=100;++t){ x[t+1]=(i/100.0)*x[t]*(1-x[t]); document.writeln((i/100.0)," ",x[t]); } } document.writeln("</pre>"); document.writeln("</body>"); document.write("</html>"); } function logisticmap3(){ var x=new Array(102); /* 102個の値(x[0],...,x[101])を格納する配列xを宣言 */ a=parseFloat(document.logisticmap.a.value); x[0]=parseFloat(document.logisticmap.x0.value); document.writeln("<html>"); document.writeln("<head>"); document.writeln("<title>ロジスティック写像・リターンマップ</title>"); document.writeln("</head>"); document.writeln("<body bgcolor='#ffd700' text='#000000'>"); document.writeln("<pre>"); document.writeln(x[0]," ",0); for(t=0;t<=100;++t){ x[t+1]=a*x[t]*(1-x[t]); document.writeln(x[t]," ",x[t]); document.writeln(x[t]," ",x[t+1]); } document.writeln("</pre>"); document.writeln("</body>"); document.write("</html>"); } |
|