文部科学省発行「高等学校情報科『情報Ⅰ』教員研修用教材」の「学習17」にある「自然現象のモデル化とシミュレーション」では生命体の増加シミュレーション(ロジスティクス曲線)が紹介されています。こちらの内容をJavaScriptとグラフライブラリのPlotly.jsで学習する方法を紹介いたします。

サンプルプロジェクト

生命体の増加シミュレーション(ロジスティクス曲線) (zip)

完成イメージ

生命体の増加シミュレーションについて考える

 ミントを植えると一気に繁殖して他の植物を駆逐するという話がありますが、プランターに植えた場合、プランターのサイズ以上にミントが無限増殖することは考えられません。プランターのような「環境」において生命が生存できる個体数の上限を資料では「環境収容力」と呼んでいます。

余談ですが、所長の家の庭に蒔いたミントは増殖しませんでした、たぶん、バッタに食われて全滅…

 ミントほど増加率が激しくなくても、生命は環境内で増加し続けます。また、数に応じて減少も起こります。減少率は以下の式の通りです。

減少率 = (現在の個体数 / 環境収容力) * 増加率

仮に現在の個体数が1000で環境収容力も1000だった場合は(1/1 = 1)となるため、減量率 = 増加率となるため増加と減少が釣り合ってしまい個体数は1000で収束します。

増加率が高そうなミントであっても増加率がもうすこしマイルドなシソであっても、減少率 = 増加率なら、環境収容力を越えて増え続けることはできないというわけです。

変数表

変数名 意味
max 繰り返し上限数。
number 個体数の配列。時間帯毎にどんどん増える様を追加していきます。
zoukasuu 増加数。現在の個体数と増加率をかけ算して求めることができる。
zouka 増加率。繁殖力の強い生命の場合はこの値を大きくすれば良い。
gensyousuu 減少数。減少率を元に計算できる。
gensyou 減少率。減少率の式は先述の通り。
capacity 環境収容力。

ソースコード


    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
    <script>
        function plot() {
            let max = 1000; // ループ上限
            let number = [10]; // 個体数
            let zoukasuu; // 増加数
            let zouka = 0.01; // 増加率
            let gensyousuu; // 減少数
            let gensyou; // 減少率
            let capacity = 1000; // 環境収容力

            for (let i = 0; i < max; i++) {
                zoukasuu = number[i] * zouka;
                gensyou = (number[i] / capacity) * zouka;
                gensyousuu = number[i] * gensyou;
                number.push(number[i] + (zoukasuu - gensyousuu));
                console.log("zoukasuu:" + zoukasuu + " gensyousuu:" + gensyousuu);
            }
            
            // グラフ
            let graph = "myDiv";
            let layout = {
                height: 400,
                width:  400,
                showlegend:false,
                title:"生命体の増加シミュレーション",
                xaxis: {
                    title: "時間"
                },
                yaxis: {
                    title: "数"
                },
            };
            let trace = {
                y: number,
                mode: "markers",
                type: "scatter",
                marker:{
                    color:"blue",
                    size:2
                }
            };
            let data = [trace];

            Plotly.newPlot(graph, data, layout);
        }
    </script>
</head>
<body onload="plot()">
    <div id="myDiv"></div>
</body>

変数定義

個体数の初期値や増加率と環境収容力などを設定しています。
これ、仮に個体数を0にした場合はどうなるのか気になりますね。


let max = 1000; // ループ上限
let number = [10]; // 個体数
let zoukasuu; // 増加数
let zouka = 0.01; // 増加率
let gensyousuu; // 減少数
let gensyou; // 減少率
let capacity = 1000; // 環境収容力

ループ処理

変数で事前定義した回数分、ループ処理を行います。増加数の上昇とともに減少数も増加していき最後は収束します。確認のためにconsole.log()で各値をログに書き出していますので確認してみて下さい。


for (let i = 0; i < max; i++) {
    zoukasuu = number[i] * zouka;
    gensyou = (number[i] / capacity) * zouka;
    gensyousuu = number[i] * gensyou;
    number.push(number[i] + (zoukasuu - gensyousuu));
    console.log("zoukasuu:" + zoukasuu + " gensyousuu:" + gensyousuu);
}

グラフ描画

縦軸に個体数、横軸に時間を取ってグラフを描画します。


let graph = "myDiv";
let layout = {
    height: 400,
    width:  400,
    showlegend:false,
    title:"生命体の増加シミュレーション",
    xaxis: {
        title: "時間"
    },
    yaxis: {
        title: "数"
    },
};
let trace = {
    y: number,
    mode: "markers",
    type: "scatter",
    marker:{
        color:"blue",
        size:2
    }
};
let data = [trace];

Plotly.newPlot(graph, data, layout);

追加演習:増加率を変更してみよう

増加率の部分を0.01から別の数字に変更してみて下さい。


let zouka = 0.01; // 増加率

0.02にすると以下のような図になります。

おわりに

初期値を変えたり、捕食者がいる設定にしても面白いかもしれません。

ちょうど我が家のプランターで育てているシソは今からソーメンの薬味にされるようです。

7月7日はソーメンの日。