octave の表現 - nuce.nagoya-u.ac.jp · 17 第4章 octave の表現 octave は,かなりmatlab...
TRANSCRIPT
17
第4章 Octave の表現 Octave は,かなり MATLAB を意識しているが独自の拡張もある。また,表現の仕
方に Octave 独自の表現と MATLAB 互換の表現と互換に近い表現がある。本講義では
できるだけ,MATLAB 互換の表現と互換に近い表現をとることにする。これは,
MATLAB は,数値計算ツール,制御系ツールのデファクトスタンダードであり,将
来,諸君らが研究室や職場で MATLAB を使う機会があるかもしれないという観点か
らである。 4-1 Octave の数値の精度 Octave の数値の精度は,倍精度実数(double precision) (64bits, 8bytes)として扱わ
れる。C 言語では,実数は浮動小数点数(floating point) として表現され,その有
効桁は小数点以下約 16 である。Octave では表示桁精度は,何も設定しないと 6 桁で
ある。組み込み変数 output_precision を変更することもできるが,簡単なのは命令
format longを使うことである。
>> sin(1)
ans = 0.84147
>> format long
>> sin(1)
ans = 0.841470984807897
>> format
>> sin(1)
ans = 0.84147
>> output_precision=10
output_precision = 10
>> sin(1)
ans = 8.414709848e-01
>> format
>> sin(1)
ans = 0.84147
また,命令 formatを使うと元の表示桁数にもどる。 4-2 Octave での表現 Octave での基本的な演算の表現は以下のようである。
表記 数式 意味
x+y yx + x と y の和 x-y yx − x と y の差 x*y xy x と y の積 x/y yx x を y で割った商
rem(x,y) x を y で割った余り x**y, x^y yx x の y 乗
注:MATAB ではべき乗は x^y しか使えない。MATLAB との互換性を考える場合
18
は x^y をすすめる。
>> x
error: `x' undefined near line 1 column 1
>> x=tan(pi/5)
x = 0.72654
>> x
x = 0.72654
>> x=tan(pi/3);
>> x
x = 1.732
変数 x を使うために単に xと入力するとどうなるだろうか?定義されていないとい
うエラーメッセージが表示される。変数 x(の宣言ととも)に値 tan(π / 5)を代入す
るには x=tan(pi/5) と記する。すると変数に tan(π / 5)の計算値がはいっていることが
わかる。(pi はπ をあらわす組み込み定数である。)
x=tan(pi/3); とセミコロン「;」をつけると次の行の表示が抑えられる。しかし,た
だし,きちんと値が代入されていることがわかる。
>> x=2, y=3
x = 2
y = 3
>> x=4; y=5;
>> x, y
x = 4
y = 5
一行に複数の命令を書くには,カンマ「,」またはセミコロンを用いる。
4-2 代表的な組み込み定数 代表的な組み込み定数は次のようなものがある e:e pi :π NaN, nan:Not a Number(数値ではない。0/0 の結果など) Inf:Infinity(無限大)
eps: Machine epsilon (計算システムがある数と次に大きい数との間の間隔), realmax: 倍精度実数の最大値
realmin:倍精度実数の最小値
i, j, I, J:虚数単位。
演習4-1
Octave のプロンプトからこれらの組み込み定数を打ち込んでどのようになるか
確かめよ。
4-3 組み込み関数 Octaveには,大変多くの組み込み関数がある。三角関数はもちろん,双曲線関数,
特殊関数がある。例えばn次の第1種Bessel関数 ( )zJn は,Octaveでは besselj(n,z) とし
19
て組み込まれている。 ここでこれをあげるのは,書ききれないのでマニュアルを参照にしてほしい。また,
拡張パッケージ Octave-Forge に組み込まれているものもある。
4-4 複素数 複素数を簡単に扱えるのも,数値計算ツールの特色である。 したがって,
3+4i, 3+4*i, 3+i*4, 3+4J, 3+4*J, ... などと表記ができる。Octave 自身は結果の表示に“数字 i” を用いているので,そ
れを使うことを推奨する。もし“数字*i” という表記を使うと,これは数字と変数 i の積と解釈されてしまい,場合によっては重大な間違いとなる.その場合とは組み込
み定数 i, j, I, Jと同じ名前の変数を使ってしまった場合である.Octave は新しい定
義あるいは代入結果を優先するので.例えば >> i=30
i = 30
>> 3+4*i
ans = 123
>> 3+4i
ans = 3 + 4i
>>
と異なった結果になる。Octave では,i, j, I, J は,一般のプログラミング言語でよ
く,ループのインデックス変数に用いられるが,Octave では,(おそらく MATLAB で
も)も避けたほうがよい。 複素数に関する代表的な組み込み関数を挙げる。
表記 意味
real(z) z の実数部 imag(z) z の虚数部 conj(z) z の複素共役 arg(z) z の偏角 abs(z) z の絶対値
4-5 ベクトルと行列 後ほど詳しく述べるが,行列計算は数値計算の中でも特に重要である。MATLABの名前の由来も Matrix Laboratory である。したがって,MATLAB,Octave,Scilab の
特徴は行列とベクトルを変数と取り扱えようにしてある点である。 1)ベクトル プロンプトから x=0:0.1:0.5と打つと
>> x=0:0.1:0.5
x =
0.00000 0.10000 0.20000 0.30000 0.40000 0.50000
20
と表示される。これは, ( )5.0,4.0,3.0,2.0,1.0,00.=x の行ベクトルである。x=0:0.1:0.5
は,0 から 0.1 刻みで 0.5 を超えない範囲の要素の行ベクトルを代入する書き方であ
る。単に x=1:5 と書くと以下のように 1 間隔を間隔とした行ベクトルとなる。
x=1:5
x =
1 2 3 4 5
x.’で転置を表す。Xのあとの「.」の意味は後ほど語る。
>> x.'
ans =
1
2
3
4
5
>> (x.').'
ans =
1 2 3 4 5
上の例のように,x.’は列ベクトルになっている。(x.').' は当然行ベクトルに戻る。 そのほか組み込み関数 linspace, logspace がある。始点と終点の間を指定された数
でそれぞれ通常の等間隔,対数的な等間隔で分割するものである。logspace 対数グラ
フなどを作成するのによく用いられる。
>> linspace(0,2*pi,5)
ans =
0.00000 1.57080 3.14159 4.71239 6.28319
>> format long; logspace(1,10,5)
ans =
1.0e+10 *
Columns 1 through 4:
0.000000001000000 0.000000177827941 0.000031622776602 0.005623413251903
Column 5:
1.000000000000000
21
1.0e+10 *
Columns 1 through 4:
0.000000001000000 0.000000177827941 0.000031622776602 0.005623413251903
Column 5:
1.000000000000000
さきのページは,上のように表現されたが,「これはすべての要素に 1.0e+10をかけた
ものが,答えですよ。」という表現である。少し見にくいが,この出し方は,今回
traditional モードといって MATLAB に近いモードで Octave を動かしているためにこ
のような表現になってしまう。ただし,MATLAB 自体がこのような表現の仕方をす
るのか,確認をとっていないのでその点は不明である。(小野木研の人で,MATLABが使える人がいたらぜひ教えてほしい。)
直接,行ベクトル ( )0.4,0.3,0,1=x ,列ベクトル⎟⎟⎟
⎠
⎞
⎜⎜⎜
⎝
⎛=
0.40.30.1
y をそれぞれ生成するには次の
ように書く。
>> x=[1.0 3.0 4.0]
x =
1 3 4
>> y=[1.0; 3.0; 4.0]
y =
1
3
4
>> y=[1.0 3.0 4.0].'
y =
1
3
4
2)行列 2-1)行列の入力 行列は,次のように入力する。
22
>> A=[2 4 6; 1 1 1; 1 1 0]
A =
2 4 6
1 1 1
1 1 0
ここで,各成分にアクセスするには,
>> A(1,3), A(1,:), A(:,2), A(2,2:3)
ans = 6
ans =
2 4 6
ans =
4
1
1
ans =
1 1
とくに A(1,:), A(:,2) など行列の指定は,重要である。 補足:大きな行列の入力や複雑な式を 1 行で書ききれないとき,行を継続することが
できる。これを継続行と呼ぶ。Octave では,単にリターンを続ける,または,継続し
たい部分の最後に「╲」(キーボードや日本語エディタでは「\」)と「…」(半角ピリ
オドを3つ続けること)を入力することで継続行を行うことができる。ただし,
MATLAB では継続行の指定は,「…」しか認められていないので本講義では,「…」
を使うこととする。
>> A=...
[1 2 0 6 0 4; ...
3 -3 2 8 0 0; ...
-4 0 5 6 0 -6; ...
0 2 0 -1 2 -2; ...
1 5 1 0 0 0; ...
0 -2 -1 0 2 0]
A =
1 2 0 6 0 4
3 -3 2 8 0 0
-4 0 5 6 0 -6
0 2 0 -1 2 -2
1 5 1 0 0 0
0 -2 -1 0 2 0
23
演習4-2
Octave のプロンプトから以下の命令を打ち込んでどのようになるか確かめよ。
A=[2 4 6; 1 1 1; 1 1 0]
b=[1 2 3]
A(1,:)=b
A(:,2)=b.'
A(1,1)=1+i;A
行列の入力には,その他以下のような関数が用意されている。これらは,実際に使
うとき説明する。 関数
zeros(N,M) , zeros(N) それぞれ n 行 m 列,n 行 n 列の全要素が 0 の行列 ones(N,M) , ones(N) それぞれ n 行 m 列,n 行 n 列の全要素が 1 の行列 eye(N,M) , eye(N) それぞれ n 行 m 列,n 行 n 列の対角成分のみが 1 で
他の成分は 0 の行列 rand(N,M) , rand(N) それぞれ n 行 m 列,n 行 n 列の全要素が 0 から 1 ま
での一様乱数の要素からなる行列。 randn(N,M) , randn(N) それぞれ n 行 m 列,n 行 n 列の全要素が 0 から 1 ま
での正規分布の要素からなる行列。
randと randnには,乱数の seed を指定する関数があり,それぞれ,rand(“seed”, 1) ,
randn(“seed”, 2) のように用いる。
2-2)行列の合成 行列は合成することができる。
>> a=[1:3]' ; b=[4:6]' ;c=[7:9]';
>> A=[a b c]
A =
1 4 7
2 5 8
3 6 9
2-3)行列とベクトルの演算
まず,和と差と積について見る。
>> A=[1 2 3; 4 5 6; 7 8 9]; B=[9 8 7; 6 5 4; 3 2 1];
>> A+B, A-B, A*B, B*A
ans =
10 10 10
10 10 10
10 10 10
ans =
24
-8 -6 -4
-2 0 2
4 6 8
ans =
30 24 18
84 69 54
138 114 90
ans =
90 114 138
54 69 84
18 24 30
当然だが,積については交換法則は成り立たない。
線形代数では,行列には商はないが,Octave では(MATLAB でも)次のように除
算を定義する。これは,こう意義しておくと便利だからである。
B/Aは,B=XAの解 X:右除算と定義する。
A╲Bは,B=AXの解 X:左除算と定義する。
>> A=[1 2 3; 4 5 6; 7 8 9]; B=[9 8 7; 6 5 4; 3 2 1];
>> B/A, A╲B
warning: matrix singular to machine precision, rcond = 0
warning: attempting to find minimum norm solution
ans =
-2.50000 -0.33333 1.83333
-2.00000 -0.33333 1.33333
-1.50000 -0.33333 0.83333
warning: matrix singular to machine precision, rcond = 2.20304e-18
warning: attempting to find minimum norm solution
ans =
-5.83333 -5.33333 -4.83333
-0.33333 -0.33333 -0.33333
5.16667 4.66667 4.16667
除算は,逆行列がいつも存在するわけでないように,いつでも安定に計算できるわ
けでないので上のような警告が出ている。
文字コードについての注意だが,バックスラッシュ「╲」は,日本語コードで表現
すると「\」になる。現在使用しているターミナルは,英文の設定なので,日本語の
キーボードからでは「\」を入力すると「╲」と表示される。SciTE は,日本語モード
で設定してあるので,SciTE で書くときは「\」と書くこと。
左除算を使うと次のような線形連立方程式が簡単に解ける。
25
54121023
=+−=−+=++
zyxzyxzyx
(4-1)
>> A=[3 2 1; 2 1 -1; 4 -1 1]; b=[10; 1; 5];
>> A╲b
ans =
1.00000
2.00000
3.00000
演習4-3
Octave の左除算を使って,次の連立方程式を解け。
7349272
=+−=++=++
zyxzyxzyx
(4-2)
2-4)行列とスカラーの演算
これも線形代数では,やれない演算だが,便利さのために,Octave では(MATLAB でも)行列とスカラーの演算の機能がある。
>> A=[1 2 1; 2 1 1; 4 -3 1]; A+1, 2*A, A/10
ans =
2 3 2
3 2 2
5 -2 2
ans =
2 4 2
4 2 2
8 -6 2
ans =
0.10000 0.20000 0.10000
0.20000 0.10000 0.10000
0.40000 -0.30000 0.10000
行列の各成分に対してスカラーの値の演算が行われているのがわかる。
2-4)行列の成分ごとの演算
これも線形代数では,やれない演算だが,便利さのために,Octave では(MATLAB
26
でも)行列の成分ごとの演算の機能がある。
演算
A.+B 成分ごとの和 A.-B 成分ごとの差 A.*B 成分ごとの積 A./B 成分ごとの商 A.^p 成分ごとのべき f(A) 成分ごとの関数値
>> A=[1 2 3; 4 5 6; 7 8 9]; B=[9 8 7; 6 5 4; 3 2 1];
>> A.+B, A.-B, A.*B, A./B, A.^2
ans =
10 10 10
10 10 10
10 10 10
ans =
-8 -6 -4
-2 0 2
4 6 8
ans =
9 16 21
24 25 24
21 16 9
ans =
0.11111 0.25000 0.42857
0.66667 1.00000 1.50000
2.33333 4.00000 9.00000
ans =
1 4 9
16 25 36
49 64 81
2-5)行列の転置と複素共役転置
行列A の複素共役転置行列 ∗A (線形代数を思い出そう。)は,A’で表される。通常
の転置行列 At は,A.’となる。当然であるが,行列の全成分が実数の場合は A’と A.’
は同じ演算となる。
27
>> A=[1+i 1; 3 2+i], A', A.'
A =
1 + 1i 1 + 0i
3 + 0i 2 + 1i
ans =
1 - 1i 3 - 0i
1 - 0i 2 - 1i
ans =
1 + 1i 3 + 0i
1 + 0i 2 + 1i
2-6)行列に対する組み込み関数
行列に関して,さまざまな組み込み関数がある。正方行列に対しては行列の整数の
べき乗が定義できるので,たとえば正方行列A に対して
( ) ++++=!3!2
1exp32 AAAA (4-3)
のように定義される ( )Aexp は,expm(A) と書けばよい。しかし,計算自体は式(4-3)のTaylor 展開でなく Pade 近似なる手法を用いている。exp(A)と書くと成分ごとの exp の
行列となるので注意。同じようなものに logm, sqrtmがある。
>> A=[0 1;0.2 0.3];
>> exp(A), exp(A(1,1)),exp(A(1,2)),exp(A(2,1)),exp(A(2,2)), expm(A)
ans =
1.00000 2.71828
1.22140 1.34986
ans = 1
ans = 2.7183
ans = 1.2214
ans = 1.3499
ans =
1.11269 1.20540
0.24108 1.47431
28
その他の関数で代表的なものをあげる。
関数
inv(A) Aの逆行列を求める det(A) 正方行列 Aに対する行列式を求める lu(A) 正方行列 A に対するLU分解を求める。詳しくは後
述する。 rank(A) 正則行列に対し,rank を求める。 size(A), size(A,N) 行列のサイズを求める。size(A) は返り値は,行数と
列数からなる行ベクトル。size(A,N) は,N=1で行数,
N=2で列数を返す。
>> A=[1, 2; 3, 4];
>> inv(A)
ans =
-2.00000 1.00000
1.50000 -0.50000
>> [X, RCOND] = inv (A)
X =
-2.00000 1.00000
1.50000 -0.50000
RCOND = 0.047619
この例のように inv などは何も指定しなければ,求めた逆行列を返すが,上のよう
に書くと行列の条件数の逆数を与える。このように関数には,指定しないと得られな
い返り値がある場合がある。詳細はマニュアルやヘルプやハンドブックを参照のこと。
まだまだ,行列に関する関数はたくさんあるが,これも,マニュアルやヘルプやハン
ドブックを参照のこと。
連立方程式 Ax=bを解くときは,一般に x=A╲bを用い,x=inv(A)*bは用いない。A╲bは
改良された消去法に近いアルゴリズムで解いている,数値計算上,逆行列の計算は,
消去法に比べ遅く,精度も悪いとされる。小規模な問題では,それほど問題にならな
いが,大規模な連立方程式を解くときには x=inv(A)*bは,用いないのが数値計算上の
常識とされているのを喚起しておく。このように数値計算には,通常の代数と違った
配慮が必要であり,そのような議論はついては後ほど行う予定である。
演習4-4
行列 A=[1 2 3;3 2 1;2 1 3];の逆行列と行列式をもとめよ。
29
第5章 プロット
1)2次元プロット
コマンド
plot(y) ベクトル yの index(1,2,3….)を x 軸にとし,ベクトル
y の値を y 軸としてプロットする。y が複素数なら,
real(y)を x 軸にとし,imag(y)の値を y 軸としてプロッ
トする。
plot(x,y,FMT) ベクトルxを x 軸にとし,ベクトル y の値を y 軸とし
てプロットする。FMTは,省略可だが,線種や記号の種
類や色,データの名前などをしてする。
plot(x1,y1,FMT1,x2,y2, FMT2,...)
複数のデータをひとつの画面にプロットする。
polar (THETA, RHO, FMT) ベクトル THETA,ベクトル RHO,に対し,曲座標プロット
する。 semilogx (ARGS) x 軸に対し,対数軸を指定し,プロットする。
semilogy (ARGS) y 軸に対し,対数軸を指定し,プロットする。 loglog (ARGS) x 軸 y 軸に対し,対数軸を指定し,プロットする。
help plotで表示される典型的なプロット例を示す。
>> t = 0:0.1:6.3;
>> plot (t, cos(t), "-;cos(t);", t, sin(t), "+3;sin(t);");
-1
-0.8
-0.6
-0.4
-0.2
0
0.2
0.4
0.6
0.8
1
0 1 2 3 4 5 6 7
cos(t)sin(t)
"-;cos(t);","+3;sin(t);"が FMT の部分でこれを指定することにより,さまざまグラフ
が書ける。
プロットグラフの保存
いろんな方法があるが,一回目に,口頭で説明した,一番簡単なクリップボード経
30
由で保存する方法を示す。これは Octave の機能ではなく,wgnuplot の機能を用いて
いる。
上の wgnuplot のグラフ描画画面の描画ウィンドウのバー上で右クリックをして,プ
ルダウンメニューを出し,次の図のように
optionsの Copy to Clipboardを選べば図は,ベクトルデータとしてクリップボードにコ
ピーすることができる。これを,適当なアプリケーション(Word,どんな Windowsコンピュータにでもあるアクセサリのワードパッドなど)に貼り付けて保存すること
ができる。ベクトルデータなので Power Point などで図を強引に分解して,編集する
ことも可能である。
演習5-1
>> t=linspace(0,2*pi,201);
>> polar(t, sin(2*t));
上の命令を実行して,曲座標のプロットを実行してみよ。
( ) )2cos()sin( xxxf = などを効率よくプロットするためには,要素ごとの演算をうま
く使う。
31
>> x=linspace(0,2*pi,201);
>> plot(x,sin(x)*cos(2*x));
error: operator *: nonconformant arguments (op1 is 1x201, op2 is 1x201)
error: evaluating binary operator `*' near line 99, column 14
error: evaluating argument list element number 2
>> plot(x,sin(x).*cos(2*x));
plot(x,sin(x)*cos(2*x)); では上のようにエラーが出て,plot(x,sin(x).*cos(2*x));
では,
-1
-0.5
0
0.5
1
0 1 2 3 4 5 6 7
line 1
とうまくいく。
plot(x,sin(x)*cos(2*x)); ではなぜだめで,plot(x,sin(x).*cos(2*x)); でなぜうまく
いくのは,各自で考えてみよう。
2)3次元プロット
3次元プロットは,点や線のプロットと曲面のプロットに分けられる。また,厳密
には3次元の図ではないが等高線図もある。
コマンドまたは関数
plot3 (x, y, z)
plot3 (x1, y1, z1, x2,
y2, z2, ...)
plot3 (x, y, z, FMT)
3 次上に点や曲線を描くためのプロットコマンド。z軸が拡張されている以外は,ほぼ plotコマンドと同様
に使用する。*
[X, Y] = meshgrid (x, y)
[X, Y] = meshgrid (x) mesh命令を使うためのベクトル x, y配列要素 X, Yを作
成する関数。引数を一つにすると y=xとみなされる。 mesh (X,Y,Z) Meshgridで生成した配列要素 X, Yに対して,配列要素z
を曲面プロットする。 surf (X,Y,Z) 基本的に mesh (X,Y,Z) と同じだがカラーマップになる。
* contour(X,Y,Z); 基本的に mesh (X,Y,Z) と同じだが,2次元上に等高線
図が書かれる。 *のついた,plot3, surfは Octave-forge パッケージによる MATLAB との互換性のた
32
めの拡張関数。(Octave2.1 シリーズでは,octave-forge パッケージの Octave では,
使えない。)
FMTの指定の仕方は,ヘルプを参照のこと。
plot3の例
>>z = [0:0.05:5];
>>plot3(cos(2*pi*z), sin(2*pi*z), z, ";helix;");
-1 -0.5 0 0.5 1-1-0.5
0 0.5
1 0 1 2 3 4 5
helix
plot3のグラフの例
mesh, contour, surfの例
>> x=linspace(-pi/2,pi/2,20);
>> [X, Y] = meshgrid (x);
>> Z=sin(X.*X+Y.*Y);
>> mesh(X,Y,Z);
>> contour(X,Y,Z);
>> surf(X,Y,Z);
line 1
-2 -1.5 -1 -0.5 0 0.5 1 1.5 2-2-1.5-1
-0.5 0 0.5 1
1.5 2-1-0.8-0.6-0.4-0.2 0
0.2 0.4 0.6 0.8 1
meshのグラフの例
33
0.8 0.6 0.4 0.2
-5.55e-017 -0.2 -0.4 -0.6 -0.8
-2 -1.5 -1 -0.5 0 0.5 1 1.5 2-2-1.5-1-0.5 0 0.5 1 1.5 2
-1-0.8-0.6-0.4-0.2 0 0.2 0.4 0.6 0.8 1
contourのグラフの例
-1-0.8-0.6-0.4-0.2 0 0.2 0.4 0.6 0.8 1
line 1
-2 -1.5 -1 -0.5 0 0.5 1 1.5 2-2-1.5-1
-0.5 0 0.5 1
1.5 2-1-0.8-0.6-0.4-0.2 0
0.2 0.4 0.6 0.8 1
surfのグラフの例
現状では,一度 surfでグラフを書くと,カラーマップモードから戻らない。
gset nopm3dとコマンドを打てばカラーマップモードから復帰するようである。
3)分割プロット,タイトル,軸,その他
一つの画面にいくつものグラフを分割することができる。
コマンド
subplot (ROWS, COLS,
INDEX)
subplot (RCN)
たとえば引数が(2,3,1)なら画面を 2 行 3 列に分割
し,1 番目の場所にプロットする。場所の番号は数
のようにつく。subplot(2,3,1) と subplot(231) は同じ意味を
持つ。 単独に用いることはなく,他の
プロットコマンドの実行にさ
きだって位置を指定するコマンドである。 いちど subplot モードにすると hold on と同様にグ
1 2 3
4 5 6
34
ラフが上書きされる。その際は一度, subplot(111); clg
とうつとよい。 xlabel (“STRING”)
ylabel (“STRING”)
zlabel (“STRING”)
各軸に STRINGで指定された名前をつける。
title (“STRING”) グラフに STRINGで指定された名前をつける。 axis (LIMITS,“Options”) LIMITSは範囲指定する6つの要素のベクトルで x, y,
z 順にまた,始点終点の順に設定する。“Options” は
グラフの形態に関するパラメータで help を参照さ
れたい。 hold on
hold off グラフの重ねがきに対する設定。初期設定は hold
off なので,プロットのたびに前のグラフは消され
る。hold onで重ね書きモードになる。hold offコマ
ンドでもとにもどる。
その他グラフの任意場所に注釈を入れる。textコマンドなどあるが,help や前回の講
義資料で挙げたリンクリスト中の参考文献を参照されたい。
subplot を使うときは現在の wgnuplot の初期画面は小さい。マウスで大きくすれば
よい。(初期画面を大きくすることはできるが,裏技的になるので,暇があれば,ホ
ームページにでも載せる。まあ,しばらく無理でしょう。)
subplot, xlabel,ylabel,axisの例として以下を挙げる。
>> title("Subplot test");
>> t=linspace(0,2*pi,201);
>> xlabel("t");
>> ylabel("sin(t)")
>> subplot(2,2,1)
>> axis([0,2*pi*1.05,-1.05,1.05], "normal");
>> plot(t,sin(t));
>> subplot(2,2,2)
>> axis([0,2*pi*1.05,-1.05,1.05], "square");
>> plot(t,sin(t));
>> subplot(2,2,3)
>> axis([0,2*pi*1.05,-1.05,1.05], "equal");
>> plot(t,sin(t));
>> subplot(2,2,4)
>> axis([0,2*pi*1.05,-1.05,1.05], "tight");
>> plot(t,sin(t));
35
今回は,あえてスクリーンショットにした。
余談:プロンプトからいろいろ作業していると,変数などに値が保存されていてテス
トがうまくいかなくなる場合がある。変数をクリアする命令として
clear 命令がある。 clear b*r
とすると bではじまり rで終わる変数がすべてクリアされる。 clear all
とするとすべての変数がクリアされる。
36
6章 プログラミング
1)スクリプト
1-1)スクリプトとは
C 言語,C++,Fortran などの本格的なプログラミング言語でなく,アプリケーショ
ンなどに付随する命令を記述したものをスクリプト(script)と呼んでいるようである。
ただし,プログラムとスクリプトの境界はあいまいである。Octave や MATLAB,Scilabではスクリプト呼ぶことになっている。
Octave のスクリプトは,「.m」という拡張子をつける。MATLAB と同じである。こ
れは,いい面もあるが悪い面もある。Octave は,MATLAB と互換性が高いといって
も 100%ではないのでどちらのものかわからなくなる点である。両方を使うことがあ
るひとは,一応,あとで説明するコメントで Octave のスクリプトであることを明示
したほうがよい。 1-2)スクリプトファイル 2章 p.5 で示した,Ex4_4.m はスクリプトファイルである。 disp("Demonstration of solving a non-linear equation");
%
function y=funcEx4_4(x)
y=x/((1-x)*(1-x))-0.25*exp(20-10000/(450+250*x));
end
%
[x, info] = fsolve ("funcEx4_4", 0.8)
T=450+250*x
スクリプトファイルは,Octave の LOADPATHや DEFAULT_LOADPATHにあるものは, >>Ex4_4;
のように打てば実行される。これは,あたかも,Ex4_4 というコマンドを新しく定義
したように取り扱われている。ところで,スクリプトファイルは,そのファイルが存
在する場所が当然 Octave に認識されていなければならないはずである。それには,
LOADPATHという概念がある。まず,DEFAULT_LOADPATHは,標準的に Octave インストール
時に設定するファイルである。
>> DEFAULT_LOADPATH
DEFAULT_LOADPATH
= .:/opt/octave/libexec/octave/2.1.50/site/oct/i686-pc-cygwin//:/opt/octave/libexec/
octave/site/oct/i686-pc-cygwin//:/opt/octave/share/octave/2.1.50/site/m//:/opt/octav
e/share/octave/site/m//:/opt/octave/libexec/octave/2.1.50/oct/i686-pc-cygwin//:/opt/
octave/share/octave/2.1.50/m//;
インストール環境によって異なるが大体,こんなものである。DEFAULT_LOADPATHの先頭
が「.」であることに注意しよう。これは,Octave が起動されたカレントディレクト
リである。最近の Windows の言葉でいうと現在のフォルダというところであろう。
Octave を任意のフォルダから起動するのは,案外難しい。サテライトラボや私がホー
37
ムページに用意したシステムでは,「OctaveWithEditor」というショートカットがおか
れたフォルダーでこのショートカットから起動すると Octave がこのフォルダーを現
在のフォルダーとなるように「OctaveWithEditor」というショートカットに工夫を凝ら
し,専用のスタートアップ用のコマンドを用意してある。したがって,このショート
カットから Octave 起動するとこのショートカットと同じフォルダーにあるスクリプ
トファイルは,Octave から認識される。 「OctaveWithEditor」をデスクトップにコピーし,その「OctaveWithEditor」から起
動するとデスクトップ上に置かれたスクリプトファイルが認識される。したがって,
皆さんは,自分がスクリプトをおきたいフォルダーにこのショートカットをコピーし,
そこにスクリプトファイルを置けばいい。 そうでなければ,LOADPATH に自分がスクリプトを置くフォルダの値をセットすれば
よい。たとえば,D:¥Octave¥Script にデータをおいた場合,プロンプトから
>> LOADPATH='/cygdrive/d/Octave/Script'
と書けばよい。フォルダの区切りが「¥」でなく,半角の「/」であること,ドライブ
という概念がないので「D:」ドライブが「/cygdrive/d」と表されていることに注意を
しよう。このやり方の場合,日本語のフォルダ名が途中にでもあると認識できないこ
とがあるので,注意していただきたい。 また,サテライトラボのコンピュータでは,Z:ドライブ以外にはデータを恒久的に
保存できないので,今から説明する手段は,使用できないが自分のコンピュータに
Octave を イ ン ス ト ー ル し た 場 合 , C:¥Program Files¥GNU Octave 2.1.50¥opt¥octave¥share¥octave¥2.1.50¥m¥startup というフォルダに octaverc というファ
イルがあるはずである。(C:¥Program Files¥GNU Octave 2.1.50 に Octave がインストー
ルされている場合)このファイルを SciTE やメモ帳で開き,そこに, LOADPATH='/cygdrive/d/Octave/Script'
の一行を書き加えて保存しなおすとよい。 また,スクリプトファイルの名前は,半角のアルファベットと半角数字「_」で書
くことにしておこう。いろいろな意味から「-」(ハイフン)はおすすめしない。また,
「0512M.m」などのように数字でファイル名をはじめてはいけない。 なお,ここからは,必要に応じて,スクリプトファイルを作成し,そこから読み込
む場合もある。
1-3)コメント
スクリプトファイルには,実行には関係ないコメントが書けるとよい。Octave では
コメントは,「#」または,「%」であり,この記号から改行までが無視される。MATLAB では,「%」のみがコメントとして使えるので本講義では,「%」をつかうこととする。
なお,SciTE のバグにより,% をつけたコメント以外のところに全角文字を書くと異
常終了してしまうようである。注意しておこう。
2)制御構造 ここでは,プログラミングに最低限必要な事項のみを記す。もっと,詳しいことは,
マニュアル,help,Octave Handbook に任せる。
38
2-1)論理演算と比較演算 論理演算
記号 記述例 意味
| A|B A or B
& A&B A and B
~ ~A not A
比較演算
記号 記述例 意味
< A<B A < B
<= A<=B A ≦ B
> A>B A > B
>= A>=B A ≧ B
== A==B A と B は等しい。A=B は,B を A に代入する
と意味なので,比較には使用しない。 ~= A~=B A ≠ B
2-2)if 文 基本構造は,次のようになる。
if (condition)
then-body
end
となる。Octave では endifと書いてもよいが,MATLAB では,そのように書けないの
で単に endと書いた。これは for文などでも同様である。 条件に合わない場合の実行文がある場合は
if (condition)
then-body
else
else-body
end
となる。さらに,複数の条件がある場合は, if (condition)
then-body
elseif (condition)
elseif-body
else
else-body
end
となる。次ページに if 文のテストスクリプトを挙げる。
39
iftest.m %if 文のテスト
x=input("x= ");
if (x<0)
disp("x<0");
elseif (x<2)
disp("0<=x<2"); elseif (x<=5)
disp("2<=x<=5");
else
disp("x>5");
endif
2-2)while 文 繰り返し計算の基本である。基本構造は,次のようになる。
while (condition)
body
end
となる。
2-3)do-until 文 これも,繰り返し計算の基本である。基本構造は,次のようになる。
do
body
until (condition)
となる。
2-4)for 文 これも,繰り返し計算の基本でもっともよく用いる。基本構造は,次のようになる。
for var = expression
body
end
となる。
fortest.m
%for 文のテスト
knum=input("iteration number = ");
for k=1:knum
disp("iteration"), disp(k)
end
Octave,MATLAB,Scilab などでは,できるだけ,for 文の使用を少なくすることが
推奨される。これは,Octave,MATLAB,Scilab などは構文を実行時に解釈するから
繰り返し命令が遅くなる。その代わり,ベクトルと行列が定義され,ベクトルと行列
にさまざまな命令や関数が利用できるのである。後ほど述べるが,ユーザーが関数を
定義する場合もそのこと認識する必要がある。 具体例を挙げる。
40
fortest2.m
subplot(111);clg;
% for 文のテスト
pnum=20000+1;
x=linspace(0,4*pi,pnum);
y=x;
%".演算子でのテスト"
disp("Prouct by \".\" operator");
ts=cputime();
y=sin(x).*cos(2*x);
cputime()-ts
subplot(211);plot (x,y);
%for 文でのテスト
disp("for loop ");
ts=cputime();
for k=0:20000
yk=k/20000*4*pi;
y(k+1)=sin(yk)*cos(2*yk);
end
cputime()-ts
subplot(212);plot (x,y);
上で cputime()は Octave が起動した時点を起点として Octave のセッションが仕様し
たトータル時刻を秒単位で測るコマンドであり,命令や命令の集まりの実行時間を計
測するのによく用いられる。上では実行前の cputime()を ts という変数保存して差を
とった値を表示することにより実行時間の評価ができる。 実行結果(単位は秒である。)
>> fortest2
Product by "." operator
ans = 0.016000
for loop
ans = 1.3280
(実行環境:Dell Inspiron I6000, Celeron(R)M Processor, 1.30 GHz) もちろん実行環境にもよるが上の環境では,100 倍の以上速度の違いがある。した
がって,Octave,MATLAB,Scilab などでは,できるだけ,for 文の使用を少なくする
ように工夫する必要がある。
3)関数
これまで関数というと組み込み関数(build-in function)のことをいってきたが,ユ
ーザーが関数を定義することもでき,ユーザー定義関数(user-defined function)と呼ぶ。
関数は,Octave では関数は,スクリプトの内部にでも定義できる。その場合の構文は,
以下のようである。3つの代表的な表現を挙げる。 1)
function name
body
end
41
2)
function name (arg-list)
body
end
3)
function ret-var = name (arg-list)
body
end
1)では,関数は,コマンドと同じような働きをする。2)の場合,arg-list は引数の
リストで関数を呼ばれるから,情報を受け取り実行するもので,disp関数のような働
きをする。3)の場合,ret-varは,関数の返り値で,通常の意味での関数と似ている。 MATLAB では関数は,inline 関数と呼ばれる関数以外は,拡張子が「.m」のファイ
ルで用意する。通常のスクリプトを保存した拡張子が「.m」のファイルのことは「ス
クリプト m ファイル」よばれ,関数を記述した拡張子が「.m」のファイルは「関数
m ファイル」と呼ばれる。その場合の構文は,3)の場合 function ret-var = name (arg-list)
body
となる。最後に endがないのに注意しよう。Octave でも,関数 m ファイル定義でき,
その場合は,スクリプト中に定義するときに必要な endを省略することができる。 実際の関数の例を示す。球の半径を引数にとって体積を求める関数 SphereVolume を作
成し,関数ファイルとして保存してみる。
SphereVolume.m
% 球の体積を求める関数ファイル
function vol = SphereVolume (r)
vol=pi*4/3*r.^3; %"r"ではなく,"r."するのがコツ
MATLAB との互換性を考え,endは,省略してある。最後のこれを,Octave の起動フ
ォルダに保存し,(サテライトラボなら,”Z:¥My Documents¥Octave¥Scripts”),Octaveのプロンプトから実行する。
>> SphereVolume(1)
ans = 4.1888
>> SphereVolume([0.5 0.6; 0.8 1])
ans =
0.52360 0.90478
2.14466 4.18879
と新しい関数が定義されて,プロンプトからも他のスクリプトからも利用できる。 コメントに「"r"ではなく,"r."するのがコツ」と書いてあったが,こうすることにより
引数がスカラーなら値はスカラーになり,引数が行列なら行列の各要素に対して,球
の体積が計算された行列となる。このテクニックは,必ず覚えておこう。(そういう
意味では Ex4_4.m の関数定義は,まずかったなと反省している。)。このように引数の
方に応じて返り値の型が変更されるため関数の汎用性が増す。このようなことが簡単
42
るのが Octave や MATLAB の利点の一つであり,プログラミングを容易にすることと
なる。(C 言語で,型に依存しない関数を書くのは結構難しい。) Octave や MATLAB は,スクリプトと関数の m ファイルの区別は,コメント行を除
く,ファイルの最初の行が functionというキーワードで始まるかどうかで判断してい
る。 MATLAB との互換性はなくなるが,Octave では,関数をスクリプト m ファイルに
記述することができる。ただし,注意しないといけないのは,関数は,使用する前に
定義しなければならないことと,function というキーワードで始めてはいけないとい
うことである。関数は使用する前に先に定義しなければならないのでできるだけ先頭
に書きたい。これを解決するためによくとられるテクニックとして,関数定義の前に
スクリプトの disp 関数でメッセージを表示するとか,1;というようなまったく実行さ
れても意味のない。コマンドを入力しておくことである。
SphereVolume2.m
% 球の体積を求める関数をテストするスクリプトファイル
1; %ダミーのコマンド
%関数定義
function vol = SphereVolume (r)
vol=pi*4/3*r.^3; %"r"ではなく,"r."するのがコツ
end %今回は「end」は,省略できない。
SphereVolume([0.5 0.6; 0.8 1])
実行結果
>> SphereVolume2
ans =
0.52360 0.90478
2.14466 4.18879
関数の取り扱いの MATLAB と Octave の違いは,まだまだあるようであるが,必要
な人は文献やマニュアルを参照にされたい。 MatlabOctaveCompatibility というページがありその URL を紹介しておく。(英語)
http://wiki.octave.org/wiki.pl?MatlabOctaveCompatibility その他,制御構造には switch case 文などもあるが,今回おそらく使用しないので省
略する。
4)Octave における変数のスコープ スコープとは、ある変数や関数が特定の名前で参照される範囲のことをいう。その
範囲の外に置いた変数等は,通常,その名前だけでは参照できなくなる。このときこ
れらの変数はスコープの外にあるといわれる。プログラミングでは,多くの変数を扱
うため,変数の管理が重要であり,同じ名前の変数を使用すると混乱をきたすことに
なる。管理を簡単にするには,それぞれの作業段階で必要のない名前はできるだけ参
照されないようにすることが望ましくなる。
43
Octave における変数のスコープは,各関数内スコープと大域スコープ(global)の二種
類のみである。(本音を言えば,もう少し中間的なスコープがほしいところだが。新
しい 2.9シリーズではPersistent変数という新しいカテゴリーの変数スコープがサポー
トされたようである。) 関数内スコープがあるので,関数内部で定義される変数は,外からは使用できない。
一方 global で定義するとどこからでも,見えるようになる。
scopetest.m
% 局所変数のスコープのテスト
k=5;
function test(x) k=x.^2 end
test(8)
k
%
% global 変数のスコープのテスト
global kg
kg=5;
function test2(x)
global kg;
kg=x.^2
end
test2(8)
kg
実行結果
>> scopetest
k = 64
k = 5
kg = 64
kg = 64
「k」の場合は,「k」の値は,関数内では 64 になっているが,関数の外では,初期値
5 のままであるが,「kg」の場合は,global 変数で定義されているため,関数内で 64にすれば,関数から戻ったあとでも,「kg」は 64 になる。 このように global 変数はできるだけ用いないように心がけるべきであるが,どうし
ても使わざる得ない場合がある。たとえば,この講義で後ほど用いる常微分方程式の
ソルバー関数 lsodeは,パラメータを引数として受け取れないので global 変数を使用
せざるを得ない。この場合,比較的短く自己完結するスクリプト以外では,global 変数名は,「k, l」などのどこでも使うような名前を控え,たとえば解くべき関数名が
「matsuoka」ならば,global 宣言する変数名は「matsuoka_k, matsuoka_l」などのように
するなどしておくのが無難である。
44
5)変数データのファイルへの保存 Octave には(MATLAB にも),C言語と似た仕様のファイルを扱う関数が用意され
ているが,ここでは,単純な save と load コマンドを紹介する。
コマンド
save options file v1 v2 v3 .....
Fileで指定ファイルにデータ v1 v2 v3 ..... を保存
する。Options はここでは,テキスト保存の –ascii
のみ使用することにする。他の Optionsは,help で
確認すること。データのほかに,ファイルの作成時
刻,変数名,変数型,行数,列数などが記録されて
いる。 load options file 基本的には saveで保存されたデータを読み込む。変
数名は,saveに保存されたものを使用するので,要
注意。他の変数にロードする場合は,いったん現在
の使用している変数を,プログラム上で退避させ,
loadで読み込んだ変数を他の変数に代入し,退避さ
せた変数を戻すような配慮が必要。
>> x=linspace(0,2*pi,11);
>> y=sin(x);
>> save -ascii data.txt x y
として実行してできたファイルは data.txt
# Created by Octave 2.1.50, Sun Apr 15 12:20:12 2007 <Tatsu@INSPIRON>
# name: x
# type: matrix
# rows: 1
# columns: 11
0 0.628318530717959 1.25663706143592 1.88495559215388 2.51327412287183
3.14159265358979 3.76991118430775 4.39822971502571 5.02654824574367 5.65486677646163
6.28318530717959
# name: y
# type: matrix
# rows: 1
# columns: 11
0 0.587785252292473 0.951056516295154 0.951056516295154 0.587785252292473
1.22464679914735e-16 -0.587785252292473 -0.951056516295154 -0.951056516295154
-0.587785252292473 -2.44929359829471e-16
その後,変数を変化させて読み込もうとすると
>> x=1, y=1
x = 1
y = 1
>> load data.txt
45
warning: load: local variable name `x' exists
warning: use `load -force' to overwrite
error: load: unable to load variable `x'
error: load: reading file
となる。そこで option で-force を指定すると x,yに強制的に値が代入される。
>> load -force data.txt
>> x
x =
Columns 1 through 8:
0.00000 0.62832 1.25664 1.88496 2.51327 3.14159 3.76991 4.39823
Columns 9 through 11:
5.2655 5.65487 6.28319
>> y
y =
Columns 1 through 7:
0.00000 0.58779 0.95106 0.95106 0.58779 0.00000 -0.58779
Columns 8 through 11:
-0.95106 -0.95106 -0.58779 -0.00000
他のソフトで,Octave で計算したデータを使用する場合,この形式では,使いにくい
のでたとえば次のようにする。
>> x=linspace(0,2*pi,11);
>> y=sin(x);
>> xydata= [x.’y. ’]
>> save -ascii xydata.txt xydata
xydata.txt
# Created by Octave 2.1.50, Sun Apr 15 12:39:37 2007 <Tatsu@INSPIRON>
# name: xydata
# type: matrix
# rows: 11
# columns: 2
0 0
0.628318530717959 0.587785252292473
1.25663706143592 0.951056516295154
1.88495559215388 0.951056516295154
2.51327412287183 0.587785252292473
46
3.14159265358979 1.22464679914735e-16
3.76991118430775 -0.587785252292473
4.39822971502571 -0.951056516295154
5.02654824574367 -0.951056516295154
5.65486677646163 -0.587785252292473
6.28318530717959 -2.44929359829471e-16
この形式ならば,Excel などの他のソフトで使用しやすい。 また,逆に Octave にデータを読ませたいときには,適当なソフトを使って上記の
ような形式にデータを改変するか,C 言語類似のファイル操作関数を使用する必要が
ある。C 言語類似のファイル操作関数については,マニュアルを参照してほしい。