「講習第3回」(2005/11/29 (火) 17:52:30) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
*個体群モデルの基礎
ここではシミュレーションのもっとも単純な例として、離散時間における個体群動態モデルを構築します。まず始めに1種のロジスティック成長モデルを記述し、次に2種の
**今回必要になるプログラミングの知識
***定数
前回の講習では変数について「 var で変数名と型を定義する」ことを紹介しましたが、プログラムの中で用いる定数は const で定義して用いることができます。例えば、定数 K を double型の定数として定義し、値を1.85とする場合は以下のようにします。
const
K: intger = 1.85;
プログラムの実行中に変化しない値は、定数として定義しておくと便利です。
***for文
プログラムの中では同じ計算を何度も繰り返すことがあります。例えば、生物のシミュレーションでは何世代も計算を繰り返すことが普通です。このような繰り返し処理をループと呼びます。ループは際限ない繰り返しであっては困ります。ある条件を設けて繰り返し処理を行うのが普通です。ループを制御するいくつかのやり方がありますが、ここでは指定した回数繰り返し処理を行うための制御構文、for文を紹介します。~
ObjectPascalにおけるfor文の構文は以下のようになっています。「文」が実行されるたびに、「カウンタ」の値が1つ増加し、「終値」になるまで「文」は実行され続けます。
for カウンタ := 初期値 to 終値 do 文
具体例を出すと、以下の文は画面に1から10までの数字を表示します。カウンタとして使われている i はinteger型の変数で、あらかじめ定義しておく必要があります。
for i := 1 to 10 do Writeln(IntToStr(i));
また、「文」の部分はbegin~endのブロックで置き換えることが出来ます。
for i := 1 to 10 do
begin
MyString := IntToStr(i);
Writeln(MyString);
end;
**離散時間ロジスティック成長モデル
***下準備
まずは今回のプログラム製作のための作業フォルダを作成し、DOS窓を開き、カレントディレクトリを作業フォルダに移動してください。前回の講習で行ったので、第1回の資料を見れば分かると思います。~
全部DOS窓から作業を行うなら、DOS窓を開いた上で次のように入力するという方法もあります(C:ドライブの直下に、logisticフォルダを作成し、そこをカレントディレクトリにする場合)。
cd c:\
md logistic
cd logistic
***個体群のロジスティック成長モデル
離散時間におけるロジスティック成長を表す式にはいくつかありますが、ここではBegonら(1990)による生態学第3版第6章で取り上げられている以下の式を使うことにします。
ここでRは基礎順増殖率、Kは収容力、a = (R-1)/K です。これをObjectPascalで書き直して、モデル化してみましょう。~
どのようなモデルでもそうですが、モデル化を行う場合にはどのようなモデルにするのか方針を立ててからコーディングを始めるべきです。でなければ、書いている途中で混乱してしまいミスのもとになります((混乱した結果犯すミスは、論理的なミスです。このようなミスをコンパイラが指摘してくれることはまずありませんので、やっかいです。))。~
今回のモデルは
+N(t+1)はNnew、N(t)はNoldとする。
+計算された Nnew を画面に表示
+Nold に Nnew の値を代入
+上記3ステップをforループ内で20回(世代)まわす
とします。また、RとKの値は定数として、aはそれらから計算で求めます。RとKは適当に値を当てはめます。以上を、コード化したものが以下になります。~
初めて出てきた関数 FloatToStrF は double 型の値を文字列型に変換するものです。とりあえずは下記の通りに打ち込めばいいですが、詳細について知りたい方はヘルプファイルで FloatToStrF を検索してみてください。
program logistic;
{$APPTYPE CONSOLE}
uses
SysUtils;
const
R: double = 2.0;
K: double = 100.0;
var
Nnew, Nold, a: double;
i : integer;
begin
// 初期値の設定
a := (R-1) / K;
Nold:= 2.0;
// 以下for分によるループ
for i := 1 to 20 do
begin
Nnew := R * Nold / (1 + a * Nold);
Writeln(FloatToStrF(Nnew, ffFixed, 4,1));
Nold := Nnew;
end;
end.
これを先ほど作成した作業フォルダに保存した後、コンパイルします(やり方を忘れてしまった人は第1回の資料を見てください)。DOS窓から実行すると、その結果は次のようになります。
3.9
7.5
14.0
24.6
39.5
56.6
72.3
83.9
91.3
95.4
97.7
98.8
99.4
99.7
99.9
99.9
100.0
100.0
100.0
100.0
はい、完成です。
***テキスト出力とTStringListクラス
今のプログラムでは結果は画面に表示されるだけですが、結果を他のソフトで解析したり、グラフ化するにはファイルに保存しておくと便利です。汎用性が高く、扱いも楽なCSVファイル((カラムをコンマで区切るため「コンマ区切りテキスト形式」などとも呼ばれます。エクセルで「ファイル」→「名前を付けて保存」で表示されるダイアログボックスの「ファイルの種類」にも「CSV形式」があります。当然、CSVファイルはエクセルで読み込むことも可能です。))に世代番号と個体数を保存することにしましょう。~
ObjectPascalではテキストファイル(CSVもテキストファイルの一つです)を扱う方法の一つとして、TStringListクラスがあります。このTStringListは大変便利な機能なので、覚えていて損はありません。ここでもこれを使ってファイルの保存を行いましょう。~
TStringListはクラスです。オブジェクト指向プログラミングにおけるクラスはいわば原型やひな形に当たるもので、実際に使うにはインスタンス化する必要があります。そのためにはTStringListのコンストラクタを呼び出します。また、使い終わったらインスタンスが使っていたメモリを開放してやる必要があります。TStringListとテキストファイルに関する手順は以下のようになります。
+最初にインスタンスを宣言しておく。ここではmyListという名前にする。
+TStringListをインスタンス化して、myListを作る。
+myListにNnewの値を追加することを繰り返す。
+myListをテキストファイルに保存する。
+myListを開放する。
これらのコードを追加したものは以下のようになります。上記リストの番号と下記コメント欄の番号を揃えていますので、見比べてください。
program logistic;
{$APPTYPE CONSOLE}
uses
SysUtils, Classes; // <- 0.
const
R: double = 2.0;
K: double = 100.0;
var
Nnew, Nold, a: double;
i : integer;
myList: TStringList; // <- 1.
begin
// 初期値の設定
a := (R-1) / K;
Nold:= 2.0;
myList := TStringList.Create; // <- 2.
// 以下for分によるループ
for i := 1 to 20 do
begin
Nnew := R * Nold / (1 + a * Nold);
myList.Add(IntToStr(i) + ',' +
FloatToStrF(Nnew, ffFixed, 4,1)); // <- 3.
Nold := Nnew;
end;
myList.SaveToFile('myList.csv');// <- 4.
myList.Free; // <- 5.
end.
インスタンスの宣言(1.)は他の変数の宣言とほとんど同じです。インスタンス化(2.)は大体どのクラスもこのように、クラス名.Create で行われます。インスタンス化されたmyListに文字列を追加(3.)するのは Add メソッドを使います。(文が長くなったときはこのように複数行に分けて書くことも可能です。)テキストファイルへの保存(4.)は SaveToFile メソッドで行い、最後に Free メソッドを呼び出すことで、myListを開放(5.)します。
表示オプション
横に並べて表示:
変化行の前後のみ表示: