Shadow Academy トップ > 我流・物理数学 > ロジスティック写像


ロジスティック写像

繁殖率:a ( 0 ≤ a ≤ 4.0 )
個体数の初期値:x0 ( 0 ≤ x0 ≤ 1 )
データ出力形式:



データ出力欄:



ロジスティック写像とは何か?

1976年にアメリカの生物学者ロバート・メイが、「ロジスティック方程式」の
差分系を用いて生物の個体数の研究を行った。その差分方程式(difference equation)を
入出力の変換操作に用いた写像を「ロジスティック写像(logistic mapping)」と呼ぶ。
ロジスティック写像とは、生物の個体数の時系列に対する変遷のモデルであり、
繁殖率をa、第n世代の生物の個体数をxnとすると、
n+1世代の生物の個体数をxn+1は、漸化式:
xn+1axn ( 1-xn )
で表される。但し、繁殖率は、0 ≤ a ≤ 4.0 の範囲、
個体数の初期値は、0 ≤ x0 ≤ 1 の範囲である。
ここでは、JavaScriptによるスクリプトプログラムとグラフ作成ツール「gnuplot」を用いて、
ax0との組み合わせによる個体数の変遷及び、カオスの出現する条件を調べる。




スクリプトプログラムの使い方

時系列変化

繁殖率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) ≤ aa(≈3.57) 「2」の冪乗の周期点を振動する
a(≈3.57) ≤ a ≤ 4 変動は不規則になり、特定の周期を持たない
(カオスが出現する)




ソースコード(新版)

logisticmap.html

<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 &le; <i>a</i> &le; 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 &le; <i>x</i><sub>0</sub> &le; 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>

logisticmap.js

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; // テキストエリアへ出力する
};



ソースコード(旧版)

logisticmap.html

<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>

logisticmap.js

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>");
}



参考文献

  1. 「Javaによる複雑系入門」(工学社、2008年)
    ※個体数の初期値は、x0=0.1
  2. 「爆笑問題のニッポンの教養 脳を創る男 カオス工学」(講談社、2008年)
    ※個体数の初期値は、x0=0.040



Shadow Academy トップへ戻る

inserted by FC2 system